Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Info/Active/ now offers data for individual sessions #5384

Merged
merged 9 commits into from
Feb 15, 2023
35 changes: 34 additions & 1 deletion tools/test-proxy/Azure.Sdk.Tools.TestProxy.Tests/InfoTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using Azure.Sdk.Tools.TestProxy.Common;
using Azure.Sdk.Tools.TestProxy.Common;
using Azure.Sdk.Tools.TestProxy.Matchers;
using Azure.Sdk.Tools.TestProxy.Models;
using Azure.Sdk.Tools.TestProxy.Sanitizers;
using Azure.Sdk.Tools.TestProxy.Transforms;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
Expand Down Expand Up @@ -58,5 +60,36 @@ public void TestReflectionModelWithAdvancedType()

var result = controller.Active();
}

[Fact]
public async Task TestReflectionModelWithTargetRecordSession()
{
RecordingHandler testRecordingHandler = new RecordingHandler(Directory.GetCurrentDirectory());
var httpContext = new DefaultHttpContext();

await testRecordingHandler.StartPlaybackAsync("Test.RecordEntries/multipart_request.json", httpContext.Response);
testRecordingHandler.Transforms.Clear();

var recordingId = httpContext.Response.Headers["x-recording-id"].ToString();

testRecordingHandler.AddSanitizerToRecording(recordingId, new UriRegexSanitizer(regex: "ABC123"));
testRecordingHandler.AddSanitizerToRecording(recordingId, new BodyRegexSanitizer(regex: ".+?"));
testRecordingHandler.SetMatcherForRecording(recordingId, new CustomDefaultMatcher(compareBodies: false, excludedHeaders: "an-excluded-header"));

var model = new ActiveMetadataModel(testRecordingHandler, recordingId);
var descriptions = model.Descriptions.ToList();

// we should have exactly 6 if we're counting all the customizations appropriately
Assert.True(descriptions.Count == 6);
Assert.True(model.Matchers.Count() == 1);
Assert.True(model.Sanitizers.Count() == 5);

// confirm that the overridden matcher is showing up
Assert.True(descriptions[3].ConstructorDetails.Arguments[1].Item2 == "\"ABC123\"");
Assert.True(descriptions[4].ConstructorDetails.Arguments[1].Item2 == "\".+?\"");

// and finally confirm our sanitizers are what we expect
Assert.True(descriptions[5].Name == "CustomDefaultMatcher");
}
}
}
6 changes: 3 additions & 3 deletions tools/test-proxy/Azure.Sdk.Tools.TestProxy/Info.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using Azure.Sdk.Tools.TestProxy.Models;
Expand Down Expand Up @@ -33,9 +33,9 @@ public async Task<ContentResult> Available()
}

[HttpGet]
public async Task<ContentResult> Active()
public async Task<ContentResult> Active(string id="")
{
var dataModel = new ActiveMetadataModel(_recordingHandler);
var dataModel = new ActiveMetadataModel(_recordingHandler, recordingId: id);
var viewHtml = await RenderViewAsync(this, "ActiveExtensions", dataModel);

return new ContentResult
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,65 @@
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Xml;
using System.IO;
using Azure.Sdk.Tools.TestProxy.Common;
using System.Collections.Concurrent;
using Microsoft.CodeAnalysis.Operations;

namespace Azure.Sdk.Tools.TestProxy.Models
{
public class ActiveMetadataModel : RunTimeMetaDataModel
{
public ActiveMetadataModel(RecordingHandler pageRecordingHandler)
{
Descriptions = _populateFromHandler(pageRecordingHandler);
Descriptions = _populateFromHandler(pageRecordingHandler, "");
}

private List<ActionDescription> _populateFromHandler(RecordingHandler handler)
public ActiveMetadataModel(RecordingHandler pageRecordingHandler, string recordingId)
{
RecordingId = recordingId;
Descriptions = _populateFromHandler(pageRecordingHandler, recordingId);
}

public string RecordingId { get; set; }

private List<ActionDescription> _populateFromHandler(RecordingHandler handler, string recordingId)
{
var sanitizers = (IEnumerable<RecordedTestSanitizer>) handler.Sanitizers;
var transforms = (IEnumerable<ResponseTransform>) handler.Transforms;
var matcher = handler.Matcher;

List<ConcurrentDictionary<string, ModifiableRecordSession>> searchCollections = new List<ConcurrentDictionary<string, ModifiableRecordSession>>()
{
handler.PlaybackSessions,
handler.RecordingSessions,
handler.InMemorySessions
};

if (!string.IsNullOrWhiteSpace(recordingId)){
foreach (var sessionDict in searchCollections)
{
if (sessionDict.TryGetValue(recordingId, out var session))
{
sanitizers = sanitizers.Concat(session.AdditionalSanitizers);
transforms = transforms.Concat(session.AdditionalTransforms);

if (session.CustomMatcher != null)
{
matcher = session.CustomMatcher;
}
break;
}
}
}

List<ActionDescription> descriptions = new List<ActionDescription>();
var docXML = GetDocCommentXML();

descriptions.AddRange(handler.Sanitizers.Select(x => new ActionDescription()
descriptions.AddRange(sanitizers.Select(x => new ActionDescription()
{
ActionType = MetaDataType.Sanitizer,
Name = x.GetType().Name,
Expand All @@ -39,9 +78,9 @@ private List<ActionDescription> _populateFromHandler(RecordingHandler handler)
descriptions.Add(new ActionDescription()
{
ActionType = MetaDataType.Matcher,
Name = handler.Matcher.GetType().Name,
ConstructorDetails = GetInstanceDetails(handler.Matcher),
Description = GetClassDocComment(handler.Matcher.GetType(), docXML)
Name = matcher.GetType().Name,
ConstructorDetails = GetInstanceDetails(matcher),
Description = GetClassDocComment(matcher.GetType(), docXML)
});

return descriptions;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:5001/",
"sslPort": 44362
}
},
"profiles": {
"Azure.Sdk.Tools.TestProxy": {
"commandName": "Project",
"workingDirectory": "C:/repo/sdk-for-java",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"Logging__LogLevel__Microsoft": "Information"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
scbedd marked this conversation as resolved.
Show resolved Hide resolved
}
},
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:5001/",
"sslPort": 44362
}
}
}
14 changes: 13 additions & 1 deletion tools/test-proxy/Azure.Sdk.Tools.TestProxy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
- [A note about where sanitizers apply](#a-note-about-where-sanitizers-apply)
- [For Sanitizers, Matchers, or Transforms in general](#for-sanitizers-matchers-or-transforms-in-general)
- [Viewing available/active Sanitizers, Matchers, and Transforms](#viewing-availableactive-sanitizers-matchers-and-transforms)
- [To see customizations on a specific recording](#to-see-customizations-on-a-specific-recording)
- [Resetting active Sanitizers, Matchers, and Transforms](#resetting-active-sanitizers-matchers-and-transforms)
- [Reset the session](#reset-the-session)
- [Reset for a specific recordingId](#reset-for-a-specific-recordingid)
Expand Down Expand Up @@ -456,10 +457,21 @@ Currently, the configured set of transforms/playback/sanitizers are NOT propogat
Launch the test-proxy through your chosen method, then visit:

- `<proxyUrl>/Info/Available` to see all available
- `<proxyUrl>/Info/Active` to see all currently active.
- `<proxyUrl>/Info/Active` to see all currently active for all sessions.

Note that the `constructor arguments` that are documented must be present (where documented as such) in the body of the POST sent to the Admin Interface.

#### To see customizations on a specific recording

This only works **while a session is available**. A specific session is only available _before_ it has been stopped. Once that happens it has been written to disk or evacuated from server memory.

Example flow

- Start playback for "hello_world.json"
- Receive a recordingId back
- Place a breakpoint **before** the part of your code that calls `/Record/Stop` or `Playback/Stop`.
- Visit the url `<proxyUrl>/Info/Active?id=<your-recording-id>`

### Resetting active Sanitizers, Matchers, and Transforms

Given that the test-proxy offers the ability to set up customizations for an entire session or a single recording, it also must provide the ability to **reset** these settings without entirely restarting the server.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@using Azure.Sdk.Tools.TestProxy.Models;
@using Azure.Sdk.Tools.TestProxy.Models;
@model ActiveMetadataModel

@{
Expand All @@ -17,9 +17,20 @@
<h1>
Test-Proxy - Active Extensions
</h1>
<p>
The below extensions are currently configured.
</p>

@if (!string.IsNullOrWhiteSpace(Model.RecordingId))
{
<p>
The below extensions are configured for recording <b>@Model.RecordingId</b>.
</p>
}
else
{
<p>
The below extensions are currently configured.
scbedd marked this conversation as resolved.
Show resolved Hide resolved
</p>
}

<p>
To observe ALL extensions (rather than just what is currently active), visit <a href="/Info/Available">/Info/Available</a>. For clarity, note that argument values below are surrounded in quotes. The actual value itself being utilized by
the test-proxy does not contain these quotes.
Expand Down