Skip to content

Commit 781f085

Browse files
committed
C#: Update existing unit tests and add some extra ones.
1 parent aedb7a8 commit 781f085

1 file changed

Lines changed: 142 additions & 16 deletions

File tree

‎csharp/extractor/Semmle.Extraction.Tests/FileContent.cs‎

Lines changed: 142 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,37 @@
11
using Xunit;
22
using System;
33
using System.Collections.Generic;
4+
using System.IO;
5+
using System.Text;
46
using Semmle.Extraction.CSharp.DependencyFetching;
7+
using Semmle.Util.Logging;
58

69
namespace Semmle.Extraction.Tests
710
{
811
internal class UnsafeFileReaderStub : IUnsafeFileReader
912
{
10-
private readonly IEnumerable<string> lines;
13+
private readonly IReadOnlyDictionary<string, string> contents;
14+
public int OpenCount { get; private set; }
15+
public MemoryStream? LastStream { get; private set; }
1116

12-
public UnsafeFileReaderStub(IEnumerable<string> lines)
17+
public UnsafeFileReaderStub(IReadOnlyDictionary<string, string> contents)
1318
{
14-
this.lines = lines;
19+
this.contents = contents;
1520
}
1621

17-
public IEnumerable<string> ReadLines(string file)
22+
public Stream OpenRead(string file)
1823
{
19-
foreach (var line in lines)
20-
{
21-
yield return line;
22-
}
24+
OpenCount++;
25+
LastStream = new MemoryStream(Encoding.UTF8.GetBytes(contents[file]));
26+
return LastStream;
2327
}
2428
}
2529

2630
internal class TestFileContent : FileContent
2731
{
28-
public TestFileContent(IEnumerable<string> lines) : base(new LoggerStub(),
29-
new List<string>() { "test1.cs" },
30-
new UnsafeFileReaderStub(lines))
32+
public TestFileContent(IEnumerable<string> lines, string file = "test1.csproj") : base(new LoggerStub(),
33+
new[] { file },
34+
new UnsafeFileReaderStub(new Dictionary<string, string> { [file] = string.Join(Environment.NewLine, lines) }))
3135
{ }
3236
}
3337

@@ -41,10 +45,11 @@ public void TestFileContent1()
4145
{
4246
"<Project Sdk=\"Microsoft.NET.Sdk\">",
4347
"<PackageReference Include=\"DotNetAnalyzers.DocumentationAnalyzers\" Version=\"1.0.0-beta.59\" PrivateAssets=\"all\" />",
44-
"<PackageReference Version=\"7.0.0\" Include=\"Microsoft.CodeAnalysis.NetAnalyzers\"PrivateAssets=\"all\" />",
45-
"<PackageReference Include=\"StyleCop.Analyzers\" Version=\"1.2.0-beta.406\">",
48+
"<PackageReference Version=\"7.0.0\" Include=\"Microsoft.CodeAnalysis.NetAnalyzers\" PrivateAssets=\"all\" />",
49+
"<PackageReference Include=\"StyleCop.Analyzers\" Version=\"1.2.0-beta.406\"></PackageReference>",
4650
"<!-- <PackageReference Include=\"NUnit\" Version=\"3.10.1\" /> -->",
47-
"<FrameworkReference Include=\"My.Framework\"/>"
51+
"<FrameworkReference Include=\"My.Framework\"/>",
52+
"</Project>"
4853
};
4954
var fileContent = new TestFileContent(lines);
5055

@@ -68,8 +73,9 @@ public void TestFileContent2()
6873
{
6974
"<Project Sdk=\"Microsoft.NET.Sdk.Web\">",
7075
"<FrameworkReference Include=\"My.Framework\"/>",
71-
"<PackageReference Version=\"7.0.0\" Include=\"Microsoft.CodeAnalysis.NetAnalyzers\"PrivateAssets=\"all\" />",
72-
"<PackageReference Include=\"StyleCop.Analyzers\" Version=\"1.2.0-beta.406\">"
76+
"<PackageReference Version=\"7.0.0\" Include=\"Microsoft.CodeAnalysis.NetAnalyzers\" PrivateAssets=\"all\" />",
77+
"<PackageReference Include=\"StyleCop.Analyzers\" Version=\"1.2.0-beta.406\" />",
78+
"</Project>"
7379
};
7480
var fileContent = new TestFileContent(lines);
7581

@@ -148,9 +154,11 @@ public void TestFileContent_ImplicitUsingsAdditional()
148154
// Setup
149155
var lines = new List<string>()
150156
{
157+
"<Project>",
151158
"<Using Include=\"Ns0.Ns1\" />",
152159
"<Using Include=\"Ns2\" />",
153160
"<Using Remove=\"Ns3\" />",
161+
"</Project>"
154162
};
155163
var fileContent = new TestFileContent(lines);
156164

@@ -173,6 +181,7 @@ public void TestFileContent_LegacyProjectStructure()
173181
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
174182
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
175183
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
184+
</Project>
176185
""";
177186
var lines = input.Split(Environment.NewLine);
178187
var fileContent = new TestFileContent(lines);
@@ -210,5 +219,122 @@ public void TestFileContent_NewProjectStructure()
210219
Assert.True(isNew);
211220
Assert.False(isLegacy);
212221
}
222+
223+
[Fact]
224+
public void TestFileContent_XmlSyntax()
225+
{
226+
var input =
227+
"""
228+
<msb:Project xmlns:msb="http://schemas.microsoft.com/developer/msbuild/2003"
229+
Sdk='Microsoft.NET.Sdk'>
230+
<msb:ItemGroup>
231+
<msb:PackageReference
232+
Version='1.0' Include='My.Package' />
233+
<msb:PackageReference Include='Other.Package'><Version>2.0</Version></msb:PackageReference>
234+
<msb:PackageReference Update='Ignored.Package' />
235+
<msb:PackageReference Include='' />
236+
<msb:FrameworkReference
237+
Include='Microsoft.AspNetCore.App' />
238+
<msb:Using Include='My.&#78;amespace' />
239+
</msb:ItemGroup>
240+
<msb:PropertyGroup>
241+
<msb:ImplicitUsings>
242+
ENABLE
243+
</msb:ImplicitUsings><msb:UseWPF> true </msb:UseWPF>
244+
<msb:UseWindowsForms><![CDATA[true]]></msb:UseWindowsForms>
245+
</msb:PropertyGroup>
246+
</msb:Project>
247+
""";
248+
var fileContent = new TestFileContent(new[] { input });
249+
250+
Assert.Equal(2, fileContent.AllPackages.Count);
251+
Assert.Contains(new PackageReference("my.package", PackageReferenceSource.SdkCsProj), fileContent.AllPackages);
252+
Assert.Contains(new PackageReference("other.package", PackageReferenceSource.SdkCsProj), fileContent.AllPackages);
253+
Assert.True(fileContent.IsAspNetCoreDetected);
254+
Assert.True(fileContent.UseImplicitUsings);
255+
Assert.True(fileContent.UseWpf);
256+
Assert.True(fileContent.UseWindowsForms);
257+
Assert.Contains("My.Namespace", fileContent.CustomImplicitUsings);
258+
}
259+
260+
[Fact]
261+
public void TestFileContent_CommentsAreIgnored()
262+
{
263+
var input =
264+
"""
265+
<Project>
266+
<!--
267+
<Project Sdk="Microsoft.NET.Sdk.Web" />
268+
<PackageReference Include="Ignored.Package" />
269+
<FrameworkReference Include="Microsoft.AspNetCore.App" />
270+
<ImplicitUsings>true</ImplicitUsings>
271+
<UseWPF>true</UseWPF>
272+
<UseWindowsForms>true</UseWindowsForms>
273+
<Using Include="Ignored.Namespace" />
274+
<Import Project="Microsoft.CSharp.targets" />
275+
-->
276+
</Project>
277+
""";
278+
var fileContent = new TestFileContent(new[] { input });
279+
280+
Assert.Empty(fileContent.AllPackages);
281+
Assert.Empty(fileContent.CustomImplicitUsings);
282+
Assert.False(fileContent.UseAspNetCoreDlls);
283+
Assert.False(fileContent.UseImplicitUsings);
284+
Assert.False(fileContent.UseWpf);
285+
Assert.False(fileContent.UseWindowsForms);
286+
Assert.False(fileContent.IsLegacyProjectStructureUsed);
287+
Assert.False(fileContent.IsNewProjectStructureUsed);
288+
}
289+
290+
[Fact]
291+
public void TestFileContent_PackagesConfig()
292+
{
293+
var input =
294+
"""
295+
<?xml version="1.0" encoding="utf-8"?>
296+
<packages>
297+
<package
298+
version='1.0' id='My.Package' />
299+
<package id="Other.Package" version="2.0" />
300+
<package id="" />
301+
<package />
302+
<!-- <package id="Ignored.Package" /> -->
303+
<PackageReference Include="Ignored.Package" />
304+
</packages>
305+
""";
306+
var fileContent = new TestFileContent(new[] { input }, "PACKAGES.CONFIG");
307+
308+
Assert.Equal(2, fileContent.AllPackages.Count);
309+
Assert.Contains(new PackageReference("my.package", PackageReferenceSource.PackagesConfig), fileContent.AllPackages);
310+
Assert.Contains(new PackageReference("other.package", PackageReferenceSource.PackagesConfig), fileContent.AllPackages);
311+
}
312+
313+
private sealed class RecordingLogger : ILogger
314+
{
315+
public List<string> Messages { get; } = new List<string>();
316+
public void Log(Severity severity, string message, int? threadId = null) => Messages.Add(message);
317+
public void Dispose() { }
318+
}
319+
320+
[Theory]
321+
[InlineData("This is not XML.")]
322+
[InlineData("<Project><PackageReference Include='Incomplete'")]
323+
[InlineData("<!DOCTYPE Project [<!ENTITY sdk 'Microsoft.NET.Sdk.Web'>]><Project Sdk='&sdk;' />")]
324+
public void TestFileContent_InvalidXmlDoesNotPreventReadingOtherFiles(string invalidXml)
325+
{
326+
var logger = new RecordingLogger();
327+
var stub = new UnsafeFileReaderStub(new Dictionary<string, string>
328+
{
329+
["invalid.csproj"] = invalidXml,
330+
["valid.csproj"] = "<Project Sdk='Microsoft.NET.Sdk.Web'><PackageReference Include='My.Package' /></Project>"
331+
});
332+
var fileContent = new FileContent(logger, ["invalid.csproj", "valid.csproj"], stub);
333+
334+
Assert.True(fileContent.IsAspNetCoreDetected);
335+
Assert.Contains(new PackageReference("my.package", PackageReferenceSource.SdkCsProj), fileContent.AllPackages);
336+
Assert.Contains("Failed to parse invalid.csproj as an XML file.", logger.Messages);
337+
Assert.Equal(2, stub.OpenCount);
338+
}
213339
}
214340
}

0 commit comments

Comments
 (0)