Skip to content

Commit 4f63562

Browse files
.NET API review parser tests (#8881)
* .NET API review parser tests
1 parent bd0fc39 commit 4f63562

1 file changed

Lines changed: 150 additions & 27 deletions

File tree

tools/apiview/parsers/csharp-api-parser/CSharpAPIParserTests/CodeFileTests.cs

Lines changed: 150 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,167 @@
77
using Newtonsoft.Json.Linq;
88
using System.Text.Json.Serialization;
99
using APIView.Model.V2;
10+
using Microsoft.CodeAnalysis;
11+
using NuGet.ContentModel;
1012

1113

1214
namespace CSharpAPIParserTests
1315
{
1416
public class CodeFileTests
1517
{
16-
private readonly CodeFile codeFile;
17-
public Assembly assembly { get; set; }
18+
static CodeFile templateCodeFile;
19+
static Assembly templateAssembly { get; set; }
20+
static CodeFile storageCodeFile;
21+
static Assembly storageAssembly { get; set; }
22+
static CodeFile coreCodeFile;
23+
static Assembly coreAssembly { get; set; }
1824

19-
public CodeFileTests()
25+
public CodeFileTests() { }
26+
static CodeFileTests()
2027
{
21-
assembly = Assembly.Load("Azure.Template");
22-
var dllStream = assembly.GetFile("Azure.Template.dll");
28+
templateAssembly = Assembly.Load("Azure.Template");
29+
var dllStream = templateAssembly.GetFile("Azure.Template.dll");
2330
var assemblySymbol = CompilationFactory.GetCompilation(dllStream, null);
24-
this.codeFile = new CSharpAPIParser.TreeToken.CodeFileBuilder().Build(assemblySymbol, true, null);
31+
templateCodeFile = new CSharpAPIParser.TreeToken.CodeFileBuilder().Build(assemblySymbol, true, null);
32+
33+
storageAssembly = Assembly.Load("Azure.Storage.Blobs");
34+
dllStream = storageAssembly.GetFile("Azure.Storage.Blobs.dll");
35+
assemblySymbol = CompilationFactory.GetCompilation(dllStream, null);
36+
storageCodeFile = new CSharpAPIParser.TreeToken.CodeFileBuilder().Build(assemblySymbol, true, null);
37+
38+
coreAssembly = Assembly.Load("Azure.Core");
39+
dllStream = coreAssembly.GetFile("Azure.Core.dll");
40+
assemblySymbol = CompilationFactory.GetCompilation(dllStream, null);
41+
coreCodeFile = new CSharpAPIParser.TreeToken.CodeFileBuilder().Build(assemblySymbol, true, null);
42+
}
43+
44+
public static IEnumerable<object[]> CodeFiles => new List<object[]>
45+
{
46+
new object[] { templateCodeFile, "Azure.Template" , "1.0.3.0", 8},
47+
new object[] { storageCodeFile , "Azure.Storage.Blobs", "12.21.2.0", 14},
48+
new object[] { coreCodeFile, "Azure.Core", "1.42.0.0", 26},
49+
};
50+
51+
[Theory]
52+
[MemberData(nameof(CodeFiles))]
53+
public void TestPackageMetadata(CodeFile codeFile, string expectedPackageName, string expectedVersion, int expectedNumberOfTopLines)
54+
{
55+
Assert.Equal(expectedPackageName, codeFile.PackageName);
56+
Assert.Equal(expectedVersion, codeFile.PackageVersion);
57+
Assert.Equal("C#", codeFile.Language);
58+
Assert.Equal(expectedNumberOfTopLines, codeFile.ReviewLines.Count);
59+
}
60+
61+
[Fact]
62+
public void TestClassReviewLineWithoutBase()
63+
{
64+
var lines = storageCodeFile.ReviewLines;
65+
var namespaceLine = lines.Where(lines => lines.LineId == "Azure.Storage.Blobs").FirstOrDefault();
66+
Assert.NotNull(namespaceLine);
67+
var classLine = namespaceLine.Children.Where(lines => lines.LineId == "Azure.Storage.Blobs.BlobServiceClient").FirstOrDefault();
68+
Assert.NotNull(classLine);
69+
Assert.Equal(4, classLine.Tokens.Count());
70+
Assert.Equal("public class BlobServiceClient {", classLine.ToString().Trim());
71+
}
72+
73+
[Fact]
74+
public void TestClassReviewLineWithBase()
75+
{
76+
var lines = storageCodeFile.ReviewLines;
77+
var namespaceLine = lines.Where(lines => lines.LineId == "Azure.Storage.Blobs.Models").FirstOrDefault();
78+
Assert.NotNull(namespaceLine);
79+
var classLine = namespaceLine.Children.Where(lines => lines.LineId == "Azure.Storage.Blobs.Models.BlobDownloadInfo").FirstOrDefault();
80+
Assert.NotNull(classLine);
81+
Assert.Equal(6, classLine.Tokens.Count());
82+
Assert.Equal("public class BlobDownloadInfo : IDisposable {", classLine.ToString().Trim());
2583
}
2684

2785
[Fact]
28-
public void TestPackageName()
86+
public void TestMultipleKeywords()
2987
{
30-
Assert.Equal("Azure.Template", codeFile.PackageName);
88+
var lines = storageCodeFile.ReviewLines;
89+
var namespaceLine = lines.Where(lines => lines.LineId == "Azure.Storage.Blobs.Models").FirstOrDefault();
90+
Assert.NotNull(namespaceLine);
91+
var classLine = namespaceLine.Children.Where(lines => lines.LineId == "Azure.Storage.Blobs.Models.AccessTier").FirstOrDefault();
92+
Assert.NotNull(classLine);
93+
Assert.Equal(10, classLine.Tokens.Count());
94+
Assert.Equal("public readonly struct AccessTier : IEquatable<AccessTier> {", classLine.ToString().Trim());
3195
}
3296

3397
[Fact]
34-
public void TestTopLevelReviewLineCount()
98+
public void TestApiReviewLine()
3599
{
36-
Assert.Equal(8, codeFile.ReviewLines.Count());
100+
var lines = storageCodeFile.ReviewLines;
101+
var namespaceLine = lines.Where(lines => lines.LineId == "Azure.Storage.Blobs").FirstOrDefault();
102+
Assert.NotNull(namespaceLine);
103+
var classLine = namespaceLine.Children.Where(lines => lines.LineId == "Azure.Storage.Blobs.BlobServiceClient").FirstOrDefault();
104+
Assert.NotNull(classLine);
105+
var methodLine = classLine.Children.Where(lines => lines.LineId == "Azure.Storage.Blobs.BlobServiceClient.BlobServiceClient(System.String)").FirstOrDefault();
106+
Assert.Equal(7, methodLine.Tokens.Count());
107+
Assert.Equal("public BlobServiceClient(string connectionString);", methodLine.ToString().Trim());
108+
}
109+
110+
[Fact]
111+
public void TestApiReviewLineMoreParams()
112+
{
113+
var lines = storageCodeFile.ReviewLines;
114+
var namespaceLine = lines.Where(lines => lines.LineId == "Azure.Storage.Blobs").FirstOrDefault();
115+
Assert.NotNull(namespaceLine);
116+
var classLine = namespaceLine.Children.Where(lines => lines.LineId == "Azure.Storage.Blobs.BlobServiceClient").FirstOrDefault();
117+
Assert.NotNull(classLine);
118+
var methodLine = classLine.Children.Where(lines => lines.LineId.Contains("UndeleteBlobContainerAsync")).FirstOrDefault();
119+
Assert.NotNull(methodLine);
120+
Assert.Equal(23, methodLine.Tokens.Count);
121+
Assert.Equal("public virtual Task<Response<BlobContainerClient>> UndeleteBlobContainerAsync(string deletedContainerName, string deletedContainerVersion, CancellationToken cancellationToken = default);", methodLine.ToString().Trim());
122+
}
123+
124+
public static IEnumerable<object[]> PackageCodeFiles => new List<object[]>
125+
{
126+
new object[] { templateCodeFile },
127+
new object[] { storageCodeFile },
128+
new object[] { coreCodeFile }
129+
};
130+
131+
[Theory]
132+
[MemberData(nameof(PackageCodeFiles))]
133+
public void TestAllClassesHaveEndOfContextLine(CodeFile codeFile)
134+
{
135+
// If current line is for class then next line at same level is expected to be a end of context line
136+
var lines = codeFile.ReviewLines;
137+
foreach(var namespaceLine in lines)
138+
{
139+
Assert.NotNull(namespaceLine);
140+
bool expectEndOfContext = false;
141+
var classLines = namespaceLine.Children;
142+
for (int i = 0; i < classLines.Count; i++)
143+
{
144+
if (expectEndOfContext)
145+
{
146+
Assert.True(classLines[i].IsContextEndLine == true);
147+
expectEndOfContext = false;
148+
continue;
149+
}
150+
151+
expectEndOfContext = classLines[i].Tokens.Any(t => (t.RenderClasses.Contains("class") ||
152+
t.RenderClasses.Contains("struct") ||
153+
t.RenderClasses.Contains("interface")) && !classLines[i].Tokens.Any(t => t.Value == "abstract"));
154+
}
155+
}
156+
}
157+
158+
[Fact]
159+
public void TestHiddenAPI()
160+
{
161+
var apiText = "protected static BlobServiceClient CreateClient(Uri serviceUri, BlobClientOptions options, HttpPipelinePolicy authentication, HttpPipeline pipeline);";
162+
var lines = storageCodeFile.ReviewLines;
163+
var namespaceLine = lines.Where(lines => lines.LineId == "Azure.Storage.Blobs").FirstOrDefault();
164+
Assert.NotNull(namespaceLine);
165+
var classLine = namespaceLine.Children.Where(lines => lines.LineId == "Azure.Storage.Blobs.BlobServiceClient").FirstOrDefault();
166+
Assert.NotNull(classLine);
167+
var hiddenApis = classLine.Children.Where(lines => lines.LineId == "Azure.Storage.Blobs.BlobServiceClient.CreateClient(System.Uri, Azure.Storage.Blobs.BlobClientOptions, Azure.Core.Pipeline.HttpPipelinePolicy, Azure.Core.Pipeline.HttpPipeline)").FirstOrDefault();
168+
Assert.NotNull(hiddenApis);
169+
Assert.Equal(18, hiddenApis.Tokens.Count());
170+
Assert.Equal(apiText, hiddenApis.ToString().Trim());
37171
}
38172

39173
[Fact]
@@ -77,29 +211,18 @@ public static class TemplateClientBuilderExtensions {
77211
}
78212
}
79213
";
80-
Assert.Equal(expected, codeFile.GetApiText());
214+
Assert.Equal(expected, templateCodeFile.GetApiText());
81215
}
82216

83-
[Fact]
84-
public void TestCodeFileJsonSchema()
217+
[Theory]
218+
[MemberData(nameof(PackageCodeFiles))]
219+
public void TestCodeFileJsonSchema(CodeFile codeFile)
85220
{
86221
//Verify JSON file generated for Azure.Template
87222
var isValid = validateSchema(codeFile);
88223
Assert.True(isValid);
89224
}
90225

91-
[Fact]
92-
public void TestCodeFileJsonSchema2()
93-
{
94-
//Verify JSON file generated for Azure.Storage.Blobs
95-
var storageAssembly = Assembly.Load("Azure.Storage.Blobs");
96-
var dllStream = storageAssembly.GetFile("Azure.Storage.Blobs.dll");
97-
var assemblySymbol = CompilationFactory.GetCompilation(dllStream, null);
98-
var storageCodeFile = new CSharpAPIParser.TreeToken.CodeFileBuilder().Build(assemblySymbol, true, null);
99-
var isValid = validateSchema(storageCodeFile);
100-
Assert.True(isValid);
101-
}
102-
103226
private bool validateSchema(CodeFile codeFile)
104227
{
105228
var json = JsonSerializer.Serialize(codeFile, new JsonSerializerOptions
@@ -129,9 +252,9 @@ private bool validateSchema(CodeFile codeFile)
129252
}
130253

131254
[Fact]
132-
public void TestNavigatonNodeHasRenderingClass()
255+
public void TestNavigationNodeHasRenderingClass()
133256
{
134-
var jsonString = JsonSerializer.Serialize(codeFile);
257+
var jsonString = JsonSerializer.Serialize(templateCodeFile);
135258
var parsedCodeFile = JsonSerializer.Deserialize<CodeFile>(jsonString);
136259
Assert.Equal(8, CountNavigationNodes(parsedCodeFile.ReviewLines));
137260
}

0 commit comments

Comments
 (0)