Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
37ef13e
[tsp-client] Fix tool version (#8818)
catalinaperalta Aug 12, 2024
f2506c2
[tsp-client] Fix bundled dependency issue (#8817)
tjprescott Aug 12, 2024
062cdcf
Ensure Commets are added in correct line when docs are expanded (#8798)
chidozieononiwu Aug 12, 2024
b444030
Add Button for Disabling CodeLines Lazy Loading (#8803)
chidozieononiwu Aug 12, 2024
34de2dc
Replace Global Rush (#8820)
wanlwanl Aug 13, 2024
dd35ef2
adopt tsp-client command instead of pwsh script (#8723)
kazrael2119 Aug 13, 2024
7bd7a29
Clear Package Folder Before Generation (#8826)
wanlwanl Aug 13, 2024
08698d3
Improve Logging (#8795)
wanlwanl Aug 13, 2024
310645b
upgrade openapi-to-typespec (#8827)
pshao25 Aug 13, 2024
42598e1
[GitHub] Add common service label (#8828)
jsquire Aug 13, 2024
6e8d78e
[TSP Client] Update dependency for compare command (#8829)
tjprescott Aug 13, 2024
0732701
[tsp-client] Miscellaneous fixes (#8825)
catalinaperalta Aug 13, 2024
6829db8
Fix test-commands. (#8832)
tjprescott Aug 13, 2024
0c1b964
[tsp-client] Revert openapi-to-typespec changes (#8833)
catalinaperalta Aug 13, 2024
0b9efdb
Add exception for Utf8JsonReader/Writer to AZC0014 (#8752)
pshao25 Aug 14, 2024
a62328f
071824.01/conversation (#8834)
chidozieononiwu Aug 15, 2024
51d0611
Add RestAPISpecsDocsRepos to branch cleanup and update the delete scr…
JimSuplizio Aug 15, 2024
4148bf2
Clean-up publish-blobs.yml to have better defaults (#8842)
weshaggard Aug 15, 2024
e4bf857
[tsp-client] Report diagnostic errors and exit with an error (#8844)
catalinaperalta Aug 15, 2024
c376240
Ensure assets resolution script handles special-case file paths (#8831)
scbedd Aug 15, 2024
571fc6a
Add FilePattern support for .github\workflow sync (#8849)
weshaggard Aug 16, 2024
9d583e6
Upgrade openapi-to-typespec to 0.9.0 (#8845)
pshao25 Aug 16, 2024
ee00555
[tsp-client] Add gh action for tests (#8847)
catalinaperalta Aug 16, 2024
a37817c
Support RLC Changelog Generation Based on Inline Usage (#8751)
wanlwanl Aug 19, 2024
ef3c919
Adding Workflow to label description (#8855)
ronniegeraghty Aug 19, 2024
aa0fc47
APIView code file token tsp and json schema (#8816)
praveenkuttappan Aug 19, 2024
414852c
examples automation examples-dir for tsp (#8854)
weidongxu-microsoft Aug 20, 2024
2eaf22b
[tsp-client] Update rest-api-diff dependency (#8840)
tjprescott Aug 20, 2024
7aea8e6
prettier (#8836)
catalinaperalta Aug 21, 2024
f5b732c
.NET API review parser changes to use new token schema (#8850)
praveenkuttappan Aug 22, 2024
5590e2b
Apiview token changes (#8851)
praveenkuttappan Aug 23, 2024
a371747
Avoid code file caching when for new tree style code files (#8874)
praveenkuttappan Aug 23, 2024
c6475aa
Include RenderClasses in serialized JSON code file (#8877)
praveenkuttappan Aug 23, 2024
969d7f1
Allow Save-package-properties to exit 0 when prs produce no package c…
hallipr Aug 24, 2024
4aea26a
Skip documentation node id remapping if node is not changed (#8876)
praveenkuttappan Aug 24, 2024
c597728
Compare json object values instead of byte streams when matching bodi…
scbedd Aug 25, 2024
a434ce6
Test Proxy Version w/ Json Value Compare (#8865)
scbedd Aug 25, 2024
69ff96c
[Pylint] Disallow using legacy type hinting (#8801)
MJoshuaB Aug 26, 2024
80b4e64
feat(pylint): Add httpx as a blocked networking import (#8870)
kdestin Aug 26, 2024
461c1f1
Update azure-sdk-build-tools Repository Resource Refs in Yaml files (…
azure-sdk Aug 26, 2024
9040deb
fixes issue description over 100 characters (#8869)
ronniegeraghty Aug 26, 2024
bd0fc39
Fix apiviewgo download paths (#8856) (#8883)
praveenkuttappan Aug 26, 2024
4f63562
.NET API review parser tests (#8881)
praveenkuttappan Aug 26, 2024
b6d0b88
Fix Tree and node view diff and add more test cases for parser (#8880)
praveenkuttappan Aug 26, 2024
d039913
Apiview revision upgradability to new parser version test (#8882)
praveenkuttappan Aug 26, 2024
7b333b1
APIView server and client unit tests (#8889)
praveenkuttappan Aug 27, 2024
2afc9d4
Fixed issue when processing code file for metapackage (#8892)
praveenkuttappan Aug 27, 2024
5835f21
Fix issue in attribute line with attribute class name (#8897)
praveenkuttappan Aug 28, 2024
3051445
Add RealTime Comment Updates (#8868)
chidozieononiwu Aug 28, 2024
6bfb884
chore(): add playwright-testing to product slugs (#8875)
Sid200026 Aug 28, 2024
2489a64
Pull Request automation feedback (#8878)
scbedd Aug 29, 2024
21c1ba4
Add hubs URL to Build Pipeline (#8901)
chidozieononiwu Aug 29, 2024
da75627
Encapsulate Save-Package-Properties.ps1 invocation into yaml (#8900)
hallipr Aug 29, 2024
0fb9cd4
Surface Associated Pull Request Information (#8890)
chidozieononiwu Aug 30, 2024
6550939
upgrade openapi-to-typespec version to 0.9.1 (#8904)
pshao25 Aug 30, 2024
0e3daff
Switch to User Delegate SAS for vcpkg caching (#8907)
weshaggard Aug 30, 2024
5dda57e
add quotes to powershell args (#8909)
hallipr Aug 30, 2024
0576d81
Remove unused variable group (old cpp cache key) (#8920)
weshaggard Sep 3, 2024
5424b37
Update default API parser version for .NET (#8913)
praveenkuttappan Sep 3, 2024
d3169e4
Avoid adding the same package twice, use TrimStart instead of substri…
hallipr Sep 3, 2024
58a0759
Add support for aka.ms, github wiki and crates.io checking (#8887)
hallipr Sep 3, 2024
e2658f6
073124.02/subscribe (#8886)
chidozieononiwu Sep 4, 2024
f305a42
Updated API review tokens to include two additional properties (#8885)
praveenkuttappan Sep 4, 2024
9e0cb37
Adding Network - Cloud label (#8911)
ronniegeraghty Sep 4, 2024
d8e8f8d
Ensure all parts of comment updates in real time (#8924)
chidozieononiwu Sep 4, 2024
fc3bda5
Add real time updates for review and revisions (#8925)
chidozieononiwu Sep 4, 2024
4ce99f0
Address `micromatch` cspell lock update (#8928)
scbedd Sep 4, 2024
ea8390c
Rename autorest.csharp branch feature/v3 to main (#8923)
hallipr Sep 5, 2024
f9bbdd2
Add support for missing build processing (#8424)
hallipr Sep 5, 2024
cfc4c9f
Support Modular Auto Generation (#8906)
wanlwanl Sep 6, 2024
39dacb7
Test apiviewgo review names for v2 module (#8933)
chlowell Sep 6, 2024
65dbdb2
Add CI to verify APIView token schema (#8930)
praveenkuttappan Sep 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Compare json object values instead of byte streams when matching bodi…
…es that are content-type `json` (Azure#8860)
  • Loading branch information
scbedd authored Aug 25, 2024
commit c597728040cc696b1e46c2d89dfdf079a6cbfcbe
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
Expand Down Expand Up @@ -689,8 +688,10 @@ public async void GenStringSanitizerQuietExitForAllHttpComponents()

Assert.Equal(0, matcher.CompareHeaderDictionaries(targetUntouchedEntry.Request.Headers, targetEntry.Request.Headers, new HashSet<string>(), new HashSet<string>()));
Assert.Equal(0, matcher.CompareHeaderDictionaries(targetUntouchedEntry.Response.Headers, targetEntry.Response.Headers, new HashSet<string>(), new HashSet<string>()));
Assert.Equal(0, matcher.CompareBodies(targetUntouchedEntry.Request.Body, targetEntry.Request.Body));
Assert.Equal(0, matcher.CompareBodies(targetUntouchedEntry.Response.Body, targetEntry.Response.Body));

targetUntouchedEntry.Request.TryGetContentType(out var contentType);
Assert.Equal(0, matcher.CompareBodies(targetUntouchedEntry.Request.Body, targetEntry.Request.Body, contentType));
Assert.Equal(0, matcher.CompareBodies(targetUntouchedEntry.Response.Body, targetEntry.Response.Body, contentType));
Assert.Equal(targetUntouchedEntry.RequestUri, targetEntry.RequestUri);
}

Expand Down Expand Up @@ -769,8 +770,9 @@ public async void BodyStringSanitizerQuietlyExits(string targetValue, string rep
await session.Session.Sanitize(sanitizer);

var resultBodyValue = Encoding.UTF8.GetString(targetEntry.Request.Body);
Assert.Equal(0, matcher.CompareBodies(targetUntouchedEntry.Request.Body, targetEntry.Request.Body));
Assert.Equal(0, matcher.CompareBodies(targetUntouchedEntry.Response.Body, targetEntry.Response.Body));
targetUntouchedEntry.Request.TryGetContentType(out var contentType);
Assert.Equal(0, matcher.CompareBodies(targetUntouchedEntry.Request.Body, targetEntry.Request.Body, contentType));
Assert.Equal(0, matcher.CompareBodies(targetUntouchedEntry.Response.Body, targetEntry.Response.Body, contentType));
}

[Fact]
Expand Down
157 changes: 157 additions & 0 deletions tools/test-proxy/Azure.Sdk.Tools.TestProxy/Common/JsonComparer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
using System.Text.Json;

namespace Azure.Sdk.Tools.TestProxy.Common
{
public class JsonComparer
{
public static List<string> CompareJson(byte[] json1, byte[] json2)
{
var differences = new List<string>();
JsonDocument doc1;
JsonDocument doc2;

// Deserialize the byte arrays to JsonDocument
try
{
doc1 = JsonDocument.Parse(json1);
}
catch(Exception ex)
{
differences.Add($"Unable to parse the request json body. Content \"{Encoding.UTF8.GetString(json1)}.\" Exception: {ex.Message}");
return differences;
}

try
{
doc2 = JsonDocument.Parse(json2);
}

catch (Exception ex)
{
differences.Add($"Unable to parse the record json body. Content \"{Encoding.UTF8.GetString(json2)}.\" Exception: {ex.Message}");
return differences;
}

CompareElements(doc1.RootElement, doc2.RootElement, differences, "");

return differences;
}

private static void CompareElements(JsonElement element1, JsonElement element2, List<string> differences, string path)
{
if (element1.ValueKind != element2.ValueKind)
{
differences.Add($"{path}: Request and record have different types.");
return;
}

switch (element1.ValueKind)
{
case JsonValueKind.Object:
{
var properties1 = element1.EnumerateObject();
var properties2 = element2.EnumerateObject();

var propDict1 = new Dictionary<string, JsonElement>();
var propDict2 = new Dictionary<string, JsonElement>();

foreach (var prop in properties1)
propDict1[prop.Name] = prop.Value;

foreach (var prop in properties2)
propDict2[prop.Name] = prop.Value;

foreach (var key in propDict1.Keys)
{
if (propDict2.ContainsKey(key))
{
CompareElements(propDict1[key], propDict2[key], differences, $"{path}.{key}");
}
else
{
differences.Add($"{path}.{key}: Missing in request JSON");
}
}

foreach (var key in propDict2.Keys)
{
if (!propDict1.ContainsKey(key))
{
differences.Add($"{path}.{key}: Missing in record JSON");
}
}

break;
}
case JsonValueKind.Array:
{
var array1 = element1.EnumerateArray();
var array2 = element2.EnumerateArray();

int index = 0;
var enum1 = array1.GetEnumerator();
var enum2 = array2.GetEnumerator();

while (enum1.MoveNext() && enum2.MoveNext())
{
CompareElements(enum1.Current, enum2.Current, differences, $"{path}[{index}]");
index++;
}

while (enum1.MoveNext())
{
differences.Add($"{path}[{index}]: Extra element in request JSON");
index++;
}

while (enum2.MoveNext())
{
differences.Add($"{path}[{index}]: Extra element in record JSON");
index++;
}

break;
}
case JsonValueKind.String:
{
if (element1.GetString() != element2.GetString())
{
differences.Add($"{path}: \"{element1.GetString()}\" != \"{element2.GetString()}\"");
}
break;
}
case JsonValueKind.Number:
{
if (element1.GetDecimal() != element2.GetDecimal())
{
differences.Add($"{path}: {element1.GetDecimal()} != {element2.GetDecimal()}");
}
break;
}
case JsonValueKind.True:
case JsonValueKind.False:
{
if (element1.GetBoolean() != element2.GetBoolean())
{
differences.Add($"{path}: {element1.GetBoolean()} != {element2.GetBoolean()}");
}
break;
}
case JsonValueKind.Null:
{
// Both are null, nothing to compare
break;
}
default:
{
differences.Add($"{path}: Unhandled value kind {element1.ValueKind}");
break;
}
}
}
}
}
59 changes: 43 additions & 16 deletions tools/test-proxy/Azure.Sdk.Tools.TestProxy/Common/RecordMatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,10 @@ public virtual RecordEntry FindMatch(RecordEntry request, IList<RecordEntry> ent
if (!entry.IsTrack1Recording)
{
score += CompareHeaderDictionaries(request.Request.Headers, entry.Request.Headers, IgnoredHeaders, ExcludeHeaders);
score += CompareBodies(request.Request.Body, entry.Request.Body);

request.Request.TryGetContentType(out var contentType);

score += CompareBodies(request.Request.Body, entry.Request.Body, descriptionBuilder: null, contentType: contentType);
}

if (score == 0)
Expand All @@ -130,7 +133,7 @@ public virtual RecordEntry FindMatch(RecordEntry request, IList<RecordEntry> ent
throw new TestRecordingMismatchException(GenerateException(request, bestScoreEntry, entries));
}

public virtual int CompareBodies(byte[] requestBody, byte[] recordBody, StringBuilder descriptionBuilder = null)
public virtual int CompareBodies(byte[] requestBody, byte[] recordBody, string contentType, StringBuilder descriptionBuilder = null)
{
if (!_compareBodies)
{
Expand All @@ -154,27 +157,50 @@ public virtual int CompareBodies(byte[] requestBody, byte[] recordBody, StringBu
return 1;
}


if (!requestBody.SequenceEqual(recordBody))
{
if (descriptionBuilder != null)
// we just failed sequence equality, before erroring, lets check if we're a json body and check for property equality
if (!string.IsNullOrWhiteSpace(contentType) && contentType.Contains("json"))
{
var minLength = Math.Min(requestBody.Length, recordBody.Length);
int i;
for (i = 0; i < minLength - 1; i++)
var jsonDifferences = JsonComparer.CompareJson(requestBody, recordBody);

if (jsonDifferences.Count > 0)
{
if (requestBody[i] != recordBody[i])

if (descriptionBuilder != null)
{
break;
descriptionBuilder.AppendLine($"There are differences between request and recordentry bodies:");
foreach (var jsonDifference in jsonDifferences)
{
descriptionBuilder.AppendLine(jsonDifference);
}
}

return 1;
}
descriptionBuilder.AppendLine($"Request and record bodies do not match at index {i}:");
var before = Math.Max(0, i - 10);
var afterRequest = Math.Min(i + 20, requestBody.Length);
var afterResponse = Math.Min(i + 20, recordBody.Length);
descriptionBuilder.AppendLine($" request: \"{Encoding.UTF8.GetString(requestBody, before, afterRequest - before)}\"");
descriptionBuilder.AppendLine($" record: \"{Encoding.UTF8.GetString(recordBody, before, afterResponse - before)}\"");
}
else {
if (descriptionBuilder != null)
{
var minLength = Math.Min(requestBody.Length, recordBody.Length);
int i;
for (i = 0; i < minLength - 1; i++)
{
if (requestBody[i] != recordBody[i])
{
break;
}
}
descriptionBuilder.AppendLine($"Request and record bodies do not match at index {i}:");
var before = Math.Max(0, i - 10);
var afterRequest = Math.Min(i + 20, requestBody.Length);
var afterResponse = Math.Min(i + 20, recordBody.Length);
descriptionBuilder.AppendLine($" request: \"{Encoding.UTF8.GetString(requestBody, before, afterRequest - before)}\"");
descriptionBuilder.AppendLine($" record: \"{Encoding.UTF8.GetString(recordBody, before, afterResponse - before)}\"");
}
return 1;
}
return 1;
}

return 0;
Expand Down Expand Up @@ -250,7 +276,8 @@ private string GenerateException(RecordEntry request, RecordEntry bestScoreEntry

builder.AppendLine("Body differences:");

CompareBodies(request.Request.Body, bestScoreEntry.Request.Body, builder);
request.Request.TryGetContentType(out var contentType);
CompareBodies(request.Request.Body, bestScoreEntry.Request.Body, contentType, descriptionBuilder: builder);

return builder.ToString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,10 @@ public RecordEntry Lookup(RecordEntry requestEntry, RecordMatcher matcher, IEnum
{
sanitizer.Sanitize(requestEntry);
}

// normalize request body with STJ using relaxed escaping to match behavior when Deserializing from session files
RecordEntry.NormalizeJsonBody(requestEntry.Request);


RecordEntry entry = matcher.FindMatch(requestEntry, Entries);
if (remove)
{
Expand Down