Skip to content

Commit

Permalink
refactor and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dicko2 committed Nov 14, 2024
1 parent ac2acf5 commit 06e95a8
Show file tree
Hide file tree
Showing 24 changed files with 869 additions and 87 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<None Remove="TestData\invalid.sarif" />
<None Remove="TestData\sample.sarif" />
</ItemGroup>

<ItemGroup>
<Content Include="TestData\invalid.sarif">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestData\sample.sarif">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="17.8.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="NUnit" Version="4.2.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
<PackageReference Include="Shouldly" Version="4.2.1" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.8.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Agoda.CodeCompass.MSBuild\Agoda.CodeCompass.MSBuild.csproj" />
</ItemGroup>

</Project>
152 changes: 152 additions & 0 deletions src/Agoda.CodeCompass.MSBuild.Tests/SarifConversionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
using System.Text.Json;
using NUnit.Framework;
using NUnit.Framework.Internal;
using Shouldly;

namespace Agoda.CodeCompass.MSBuild.Tests;

[TestFixture]
public class SarifConversionTests
{
private readonly string _writeSarifPath = "TestData/write.sarif";
private readonly string _sampleSarifPath = "TestData/sample.sarif";

[Test]
public async Task ConvertSarif_WithValidInput_ShouldAddTechDebtProperties()
{
var outfile = "TestData/" + Guid.NewGuid().ToString();
// Arrange
var task = new TechDebtSarifTask
{
InputPath = _sampleSarifPath,
OutputPath = outfile
};

// Act
var result = task.Execute();

// Assert
result.ShouldBeTrue();

var outputJson = await File.ReadAllTextAsync(outfile);
var output = JsonSerializer.Deserialize<SarifReport>(outputJson, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });

output.ShouldNotBeNull();
output.Runs.ShouldNotBeEmpty();
output.Runs[0].Results.ShouldNotBeEmpty();

var firstResult = output.Runs[0].Results[0];
firstResult.Properties.ShouldNotBeNull();
firstResult.Properties.TechDebt.ShouldNotBeNull();
firstResult.Properties.TechDebt.Minutes.ShouldBeGreaterThan(0);
firstResult.Properties.TechDebt.Category.ShouldNotBeNullOrWhiteSpace();
firstResult.Properties.TechDebt.Priority.ShouldNotBeNullOrWhiteSpace();
}

[Test]
public void ConvertSarif_WithInvalidPath_ShouldReturnFalse()
{
var task = new TechDebtSarifTask
{
InputPath = "TestData/invalid.sarif",
OutputPath = Guid.NewGuid().ToString()
};

var result = task.Execute();

result.ShouldBeFalse();
}

[Test]
public async Task ConvertSarif_WithMultipleRules_ShouldPreserveRuleMetadata()
{
// Arrange
var sarif = new SarifReport
{
Runs = new[]
{
new Run
{
Results = new List<Result>
{
CreateSampleResult("CS8602"),
CreateSampleResult("CA1822")
}
}
}
};

await File.WriteAllTextAsync(_writeSarifPath,
JsonSerializer.Serialize(sarif, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }));
var outfile = "TestData/" + Guid.NewGuid().ToString();
var task = new TechDebtSarifTask
{
InputPath = _writeSarifPath,
OutputPath = outfile
};

// Act
task.Execute();

// Assert
var outputJson = await File.ReadAllTextAsync(outfile);
var output = JsonSerializer.Deserialize<SarifReport>(outputJson, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });

output.ShouldNotBeNull();
output.Runs[0].Results.Count.ShouldBe(2);

var results = output.Runs[0].Results;
results[0].RuleId.ShouldBe("CS8602");
results[1].RuleId.ShouldBe("CA1822");

results[0].Properties.TechDebt.Category.ShouldBe("NullableReference");

Check warning on line 102 in src/Agoda.CodeCompass.MSBuild.Tests/SarifConversionTests.cs

View workflow job for this annotation

GitHub Actions / Build Package

Dereference of a possibly null reference.

Check warning on line 102 in src/Agoda.CodeCompass.MSBuild.Tests/SarifConversionTests.cs

View workflow job for this annotation

GitHub Actions / Build Package

Dereference of a possibly null reference.
results[1].Properties.TechDebt.Category.ShouldBe("Performance");

Check warning on line 103 in src/Agoda.CodeCompass.MSBuild.Tests/SarifConversionTests.cs

View workflow job for this annotation

GitHub Actions / Build Package

Dereference of a possibly null reference.

Check warning on line 103 in src/Agoda.CodeCompass.MSBuild.Tests/SarifConversionTests.cs

View workflow job for this annotation

GitHub Actions / Build Package

Dereference of a possibly null reference.
}

private static Result CreateSampleResult(string ruleId) => new()
{
RuleId = ruleId,
Message = new Message { Text = $"Sample message for {ruleId}" },
Locations = new[]
{
new Location
{
PhysicalLocation = new PhysicalLocation
{
ArtifactLocation = new ArtifactLocation
{
Uri = "Test.cs"
},
Region = new Region
{
StartLine = 1,
StartColumn = 1,
EndLine = 1,
EndColumn = 1
}
}
}
}
};

[OneTimeSetUp]
public void Setup()
{
string[] lines = { "public class myClass {", "// comments", "}" };

using (StreamWriter outputFile = new StreamWriter("Test.cs"))
{
foreach (string line in lines)
outputFile.WriteLine(line);
}
}

[OneTimeTearDown]
public void Cleanup()
{
if (Directory.Exists("TestData"))
{
Directory.Delete("TestData", true);
}
}
}
12 changes: 12 additions & 0 deletions src/Agoda.CodeCompass.MSBuild.Tests/TestData/invalid.sarif
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": "2.1.0",
"runs": [
{
"results": [
{
"invalid": "data"
}
]
}
]
}
72 changes: 72 additions & 0 deletions src/Agoda.CodeCompass.MSBuild.Tests/TestData/sample.sarif
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "Microsoft.CodeAnalysis.CSharp",
"version": "4.8.0",
"rules": [
{
"id": "CS8602",
"shortDescription": {
"text": "Dereference of a possibly null reference"
}
},
{
"id": "CA1822",
"shortDescription": {
"text": "Member could be marked as static"
}
}
]
}
},
"results": [
{
"ruleId": "CS8602",
"message": {
"text": "Possible dereference of null reference 'user'"
},
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "Test.cs"
},
"region": {
"startLine": 10,
"startColumn": 13,
"endLine": 10,
"endColumn": 24
}
}
}
]
},
{
"ruleId": "CA1822",
"message": {
"text": "Member DoSomething does not access instance data and can be marked as static"
},
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "Test.cs"
},
"region": {
"startLine": 15,
"startColumn": 17,
"endLine": 15,
"endColumn": 28
}
}
}
]
}
]
}
]
}
22 changes: 18 additions & 4 deletions src/Agoda.CodeCompass.MSBuild/Agoda.CodeCompass.MSBuild.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,33 @@
<DevelopmentDependency>true</DevelopmentDependency>
<NoPackageAnalysis>true</NoPackageAnalysis>
</PropertyGroup>

<PropertyGroup>
<Authors>Joel Dickson</Authors>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/agoda-com/code-compass-dotnet</PackageProjectUrl>
<PackageIcon>AgodaAnalyzersAgoji.png</PackageIcon>
<RepositoryUrl>https://github.com/agoda-com/code-compass-dotnet</RepositoryUrl>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<Description>CodeCompass is a .NET analyzer that helps you navigate the treacherous waters of technical debt. It analyzes your code and produces standardized SARIF reports that quantify technical debt in terms of estimated remediation time, categorization, and priority.</Description>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Build.Framework" Version="17.8.3" PrivateAssets="all" />
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="17.8.3" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" PrivateAssets="all" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Agoda.CodeCompass\Agoda.CodeCompass.csproj" />
<None Include="build\*.props" Pack="true" PackagePath="build" />
<None Include="build\*.targets" Pack="true" PackagePath="build" />
</ItemGroup>

<ItemGroup>
<None Include="build\*.props" Pack="true" PackagePath="build" />
<None Include="build\*.targets" Pack="true" PackagePath="build" />
<None Remove="AgodaAnalyzersAgoji.png" />
</ItemGroup>

<ItemGroup>
<Content Include="AgodaAnalyzersAgoji.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions src/Agoda.CodeCompass.MSBuild/ArtifactLocation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Agoda.CodeCompass.MSBuild;

public class ArtifactLocation
{
public string Uri { get; set; } = string.Empty;
public string UriBaseId { get; set; } = "%SRCROOT%";
}
6 changes: 6 additions & 0 deletions src/Agoda.CodeCompass.MSBuild/Location.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Agoda.CodeCompass.MSBuild;

public class Location
{
public PhysicalLocation PhysicalLocation { get; set; } = new();
}
6 changes: 6 additions & 0 deletions src/Agoda.CodeCompass.MSBuild/Message.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Agoda.CodeCompass.MSBuild;

public class Message
{
public string Text { get; set; } = string.Empty;
}
7 changes: 7 additions & 0 deletions src/Agoda.CodeCompass.MSBuild/PhysicalLocation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Agoda.CodeCompass.MSBuild;

public class PhysicalLocation
{
public ArtifactLocation ArtifactLocation { get; set; } = new();
public Region Region { get; set; } = new();
}
9 changes: 9 additions & 0 deletions src/Agoda.CodeCompass.MSBuild/Region.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Agoda.CodeCompass.MSBuild;

public class Region
{
public int StartLine { get; set; }
public int StartColumn { get; set; }
public int EndLine { get; set; }
public int EndColumn { get; set; }
}
9 changes: 9 additions & 0 deletions src/Agoda.CodeCompass.MSBuild/Result.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Agoda.CodeCompass.MSBuild;

public class Result
{
public string RuleId { get; set; } = string.Empty;
public Message Message { get; set; } = new();
public Location[] Locations { get; set; } = Array.Empty<Location>();
public TechDebtProperties Properties { get; set; } = new();
}
11 changes: 11 additions & 0 deletions src/Agoda.CodeCompass.MSBuild/Rule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Agoda.CodeCompass.MSBuild;

public class Rule
{
public string Id { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public Message ShortDescription { get; set; } = new();
public Message FullDescription { get; set; } = new();
public Message Help { get; set; } = new();
public TechDebtProperties Properties { get; set; } = new();
}
7 changes: 7 additions & 0 deletions src/Agoda.CodeCompass.MSBuild/Run.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using Agoda.CodeCompass.MSBuild;

public class Run
{
public Tool Tool { get; set; } = new();
public List<Result> Results { get; set; } = new List<Result>();
}
Loading

0 comments on commit 06e95a8

Please sign in to comment.