-
Notifications
You must be signed in to change notification settings - Fork 93
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
Implement smart validation in SarifCli tool #501
Changes from 2 commits
7faaf3d
ebb4a4c
302d02f
bf4b015
046c98f
d6de920
00a6e30
c1e2261
2110f95
a80c8d9
d241fa0
3316b0a
b1da0ed
2da17d4
06a904a
7d6ccdd
e03e8e9
a518291
2a7ca77
4918d39
b73be17
d46055f
7666936
075284c
eb59c47
85cf6c5
6c12eee
dadefdf
02aff1f
bd6596b
6a77b70
714ef3a
255ad4f
4dd64a8
372554e
0f7d0d2
b2e999c
1445d1c
caf7d82
0d70945
78d9a5e
0466ffe
88602d8
6d2129d
ddaaf13
0e40898
9e6ea5a
fbd4bbf
e8b143b
3197e82
c83acff
d51cb4a
e6f6029
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
using System.Reflection; | ||
|
||
// General Information about an assembly is controlled through the following | ||
// set of attributes. Change these attribute values to modify the information | ||
// associated with an assembly. | ||
[assembly: AssemblyTitle("Sarif CLI Unit Tests")] | ||
[assembly: AssemblyDescription("Unit tests for the SARIF command line interface tool")] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
using Microsoft.CodeAnalysis.Sarif.Cli.Rules; | ||
using Xunit; | ||
|
||
namespace Microsoft.CodeAnalysis.Sarif.Cli.FunctionalTests.Rules | ||
{ | ||
public class DoNotUseFriendlyNameAsRuleIdTests : SkimmerTestsBase | ||
{ | ||
[Fact] | ||
public void DoNotUseFriendlyNameAsRuleId_Diagnostic_RuleIdMatchesFriendlyName() | ||
{ | ||
Verify(new DoNotUseFriendlyNameAsRuleId(), "RuleIdMatchesFriendlyName.sarif"); | ||
} | ||
|
||
[Fact] | ||
public void DoNotUseFriendlyNameAsRuleId_NoDiagnostic_RuleIdDoesNotMatchFriendlyName() | ||
{ | ||
Verify(new DoNotUseFriendlyNameAsRuleId(), "RuleIdDoesNotMatchFriendlyName.sarif"); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
using System; | ||
using System.IO; | ||
using System.Linq; | ||
using FluentAssertions; | ||
using Microsoft.CodeAnalysis.Sarif.Cli.Rules; | ||
using Microsoft.CodeAnalysis.Sarif.Readers; | ||
using Microsoft.CodeAnalysis.Sarif.Writers; | ||
using Newtonsoft.Json; | ||
|
||
namespace Microsoft.CodeAnalysis.Sarif.Cli.FunctionalTests.Rules | ||
{ | ||
public abstract class SkimmerTestsBase | ||
{ | ||
private const string JsonSchemaFile = "Sarif.schema.json"; | ||
private const string TestDataDirectory = "TestData"; | ||
|
||
protected void Verify(SarifValidationSkimmerBase skimmer, string testFileName) | ||
{ | ||
string ruleName = skimmer.GetType().Name; | ||
string testDirectory = Path.Combine(Environment.CurrentDirectory, TestDataDirectory, ruleName); | ||
|
||
string targetPath = Path.Combine(testDirectory, testFileName); | ||
string expectedFilePath = MakeExpectedFilePath(testDirectory, testFileName); | ||
string actualFilePath = MakeActualFilePath(testDirectory, testFileName); | ||
|
||
using (var logger = new SarifLogger( | ||
actualFilePath, | ||
new string[] { targetPath }, | ||
verbose: false, | ||
logEnvironment: false, | ||
computeTargetsHash: false, | ||
prereleaseInfo: null, | ||
invocationTokensToRedact: null)) | ||
{ | ||
logger.AnalysisStarted(); | ||
|
||
var context = new SarifValidationContext | ||
{ | ||
Rule = skimmer, | ||
Logger = logger, | ||
TargetUri = new Uri(targetPath), | ||
SchemaFilePath = JsonSchemaFile | ||
}; | ||
|
||
skimmer.Initialize(context); | ||
context.Logger.AnalyzingTarget(context); | ||
|
||
skimmer.Analyze(context); | ||
|
||
logger.AnalysisStopped(RuntimeConditions.None); | ||
} | ||
|
||
string actualLogContents = File.ReadAllText(actualFilePath); | ||
string expectedLogContents = File.ReadAllText(expectedFilePath); | ||
|
||
// We can't just compare the text of the log files because properties | ||
// like start time, and absolute paths, will differ from run to run. | ||
// Until SarifLogger has a "deterministic" option (see http://github.com/Microsoft/sarif-sdk/issues/500), | ||
// we perform a selective compare of just the elements we care about. | ||
SelectiveCompare(actualLogContents, expectedLogContents); | ||
} | ||
|
||
private static void SelectiveCompare(string actualText, string expectedText) | ||
{ | ||
var settings = new JsonSerializerSettings() | ||
{ | ||
ContractResolver = SarifContractResolver.Instance | ||
}; | ||
|
||
SarifLog actualLog = JsonConvert.DeserializeObject<SarifLog>(actualText, settings); | ||
SarifLog expectedLog = JsonConvert.DeserializeObject<SarifLog>(expectedText, settings); | ||
|
||
SelectiveCompare(actualLog, expectedLog); | ||
} | ||
|
||
private static void SelectiveCompare(SarifLog actualLog, SarifLog expectedLog) | ||
{ | ||
Result[] actualResults = actualLog.Runs[0].Results.ToArray(); | ||
Result[] expectedResults = expectedLog.Runs[0].Results.ToArray(); | ||
|
||
actualResults.Length.Should().Be(expectedResults.Length); | ||
|
||
for (int i = 0; i < actualResults.Length; ++i) | ||
{ | ||
Result actualResult = actualResults[i]; | ||
Result expectedResult = expectedResults[i]; | ||
|
||
actualResult.RuleId.Should().Be(expectedResult.RuleId); | ||
|
||
actualResult.Locations[0].AnalysisTarget.Region.ValueEquals( | ||
expectedResult.Locations[0].AnalysisTarget.Region).Should().BeTrue(); | ||
} | ||
} | ||
|
||
private static string MakeExpectedFilePath(string testDirectory, string testFileName) | ||
{ | ||
return MakeQualifiedFilePath(testDirectory, testFileName, "Expected"); | ||
} | ||
|
||
private static string MakeActualFilePath(string testDirectory, string testFileName) | ||
{ | ||
return MakeQualifiedFilePath(testDirectory, testFileName, "Actual"); | ||
} | ||
|
||
private static string MakeQualifiedFilePath(string testDirectory, string testFileName, string qualifier) | ||
{ | ||
string qualifiedFileName = | ||
Path.GetFileNameWithoutExtension(testFileName) + "_" + qualifier + Path.GetExtension(testFileName); | ||
|
||
return Path.Combine(testDirectory, qualifiedFileName); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
<Import Project="..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props" Condition="Exists('..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props')" /> | ||
<PropertyGroup> | ||
<ProjectGuid>{859920F3-DB09-4C1D-9EAD-DFB1D7A03A46}</ProjectGuid> | ||
<OutputType>Library</OutputType> | ||
<RootNamespace>Microsoft.CodeAnalysis.Sarif.Cli.FunctionalTests</RootNamespace> | ||
<AssemblyName>Microsoft.CodeAnalysis.Sarif.Cli.FunctionalTests</AssemblyName> | ||
<NuGetPackageImportStamp> | ||
</NuGetPackageImportStamp> | ||
</PropertyGroup> | ||
<PropertyGroup> | ||
<SignAssembly>true</SignAssembly> | ||
<AssemblyOriginatorKeyFile>..\TestKey.snk</AssemblyOriginatorKeyFile> | ||
</PropertyGroup> | ||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory).., build.props))\build.props" /> | ||
<PropertyGroup> | ||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<Reference Include="FluentAssertions, Version=4.2.1.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL"> | ||
<HintPath>..\packages\FluentAssertions.4.2.1\lib\net45\FluentAssertions.dll</HintPath> | ||
<Private>True</Private> | ||
</Reference> | ||
<Reference Include="FluentAssertions.Core, Version=4.2.1.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL"> | ||
<HintPath>..\packages\FluentAssertions.4.2.1\lib\net45\FluentAssertions.Core.dll</HintPath> | ||
<Private>True</Private> | ||
</Reference> | ||
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> | ||
<HintPath>..\packages\Newtonsoft.Json.6.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> | ||
<Private>True</Private> | ||
</Reference> | ||
<Reference Include="System" /> | ||
<Reference Include="System.Core" /> | ||
<Reference Include="System.Xml.Linq" /> | ||
<Reference Include="System.Data.DataSetExtensions" /> | ||
<Reference Include="Microsoft.CSharp" /> | ||
<Reference Include="System.Data" /> | ||
<Reference Include="System.Net.Http" /> | ||
<Reference Include="System.Xml" /> | ||
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | ||
<HintPath>..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll</HintPath> | ||
<Private>True</Private> | ||
</Reference> | ||
<Reference Include="xunit.assert, Version=2.1.0.3179, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | ||
<HintPath>..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll</HintPath> | ||
<Private>True</Private> | ||
</Reference> | ||
<Reference Include="xunit.core, Version=2.1.0.3179, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | ||
<HintPath>..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll</HintPath> | ||
<Private>True</Private> | ||
</Reference> | ||
<Reference Include="xunit.execution.desktop, Version=2.1.0.3179, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | ||
<HintPath>..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll</HintPath> | ||
<Private>True</Private> | ||
</Reference> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<Compile Include="Properties\AssemblyInfo.cs" /> | ||
<Compile Include="Rules\DoNotUseFriendlyNameAsRuleIdTests.cs" /> | ||
<Compile Include="Rules\SkimmerTestsBase.cs" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<ProjectReference Include="..\Sarif.Driver\Sarif.Driver.csproj"> | ||
<Project>{8ceaea61-b1a2-4777-bcbe-c9a129a5f6c5}</Project> | ||
<Name>Sarif.Driver</Name> | ||
</ProjectReference> | ||
<ProjectReference Include="..\SarifCli\SarifCli.csproj"> | ||
<Project>{0eba700d-29e7-4fff-8ebf-20b8c0ef9a98}</Project> | ||
<Name>SarifCli</Name> | ||
</ProjectReference> | ||
<ProjectReference Include="..\Sarif\Sarif.csproj"> | ||
<Project>{cc9b247e-7103-4bf7-bdab-6e625b3680a8}</Project> | ||
<Name>Sarif</Name> | ||
</ProjectReference> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<None Include="packages.config"> | ||
<SubType>Designer</SubType> | ||
</None> | ||
<None Include="TestData\DoNotUseFriendlyNameAsRuleId\RuleIdDoesNotMatchFriendlyName.sarif"> | ||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
</None> | ||
<None Include="TestData\DoNotUseFriendlyNameAsRuleId\RuleIdDoesNotMatchFriendlyName_Expected.sarif"> | ||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
</None> | ||
<None Include="TestData\DoNotUseFriendlyNameAsRuleId\RuleIdMatchesFriendlyName.sarif"> | ||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
</None> | ||
<None Include="TestData\DoNotUseFriendlyNameAsRuleId\RuleIdMatchesFriendlyName_Expected.sarif"> | ||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
</None> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> | ||
</ItemGroup> | ||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | ||
<Target Name="CopySchema" AfterTargets="Build"> | ||
<Copy SourceFiles="$(SolutionDir)\Sarif\Schemata\Sarif.schema.json" DestinationFolder="$(OutDir)" /> | ||
</Target> | ||
</Project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test file does not violate the rule. #Closed |
||
"$schema": "http://json.schemastore.org/sarif-1.0.0", | ||
"version": "1.0.0", | ||
"runs": [ | ||
{ | ||
"tool": { | ||
"name": "SarifCli", | ||
"fullName": "SarifCli 1.0.0", | ||
"version": "1.0.0" | ||
}, | ||
"results": [], | ||
"rules": { | ||
"ImportantRule": { | ||
"id": "TST0001", | ||
"name": "ImportantRule", | ||
"shortDescription": "Important rule", | ||
"fullDescription": "Important rule", | ||
"messageFormats": { | ||
"DefaultFormatId": "\"{0}\" violates an important rule." | ||
} | ||
} | ||
} | ||
} | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The validator produces this output file for the log file that does not violate the rule. There are no |
||
"$schema": "http://json.schemastore.org/sarif-1.0.0", | ||
"version": "1.0.0", | ||
"runs": [ | ||
{ | ||
"id": "4f730ffa-cc94-4b7b-ba08-23211cb25d03", | ||
"tool": { | ||
"name": "Sarif", | ||
"fullName": "Sarif 1.5.28.0", | ||
"version": "1.5.28.0", | ||
"semanticVersion": "1.5.28", | ||
"sarifLoggerVersion": "1.5.28.0", | ||
"language": "en-US", | ||
"properties": { | ||
"Comments": "Object model and utilities for reading and writing files in the SARIF format.", | ||
"CompanyName": "Microsoft Corporation", | ||
"ProductName": "Microsoft SARIF SDK" | ||
} | ||
}, | ||
"results": [], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No results. #Closed |
||
"toolNotifications": [ | ||
{ | ||
"id": "MSG001.AnalyzingTarget", | ||
"physicalLocation": { | ||
"uri": "file:///G:/Code/sarif-sdk/bld/bin/SarifCli.FunctionalTests/AnyCPU_Release/TestData/DoNotUseFriendlyNameAsRuleId/RuleIdDoesNotMatchFriendlyName.sarif" | ||
}, | ||
"message": "Analyzing 'RuleIdDoesNotMatchFriendlyName.sarif'...", | ||
"level": "note", | ||
"time": "2016-08-23T22:55:51.110Z" | ||
} | ||
], | ||
"files": { | ||
"file:///G:/Code/sarif-sdk/bld/bin/SarifCli.FunctionalTests/AnyCPU_Release/TestData/DoNotUseFriendlyNameAsRuleId/RuleIdDoesNotMatchFriendlyName.sarif": { | ||
"mimeType": "text/x-sarif" | ||
} | ||
}, | ||
"invocation": { | ||
"commandLine": "src\\packages\\xunit.runner.console.2.1.0\\tools\\xunit.console.x86.exe bld\\bin\\SarifCli.FunctionalTests\\AnyCPU_Release\\Microsoft.CodeAnalysis.Sarif.Cli.FunctionalTests.dll", | ||
"startTime": "2016-08-23T22:55:51.109Z", | ||
"endTime": "2016-08-23T22:55:51.190Z", | ||
"processId": 9688, | ||
"fileName": "C:\\Users\\lgolding\\AppData\\Local\\Temp\\bcef3d89-d123-4f33-b0de-1c3a541c8040\\bcef3d89-d123-4f33-b0de-1c3a541c8040\\assembly\\dl3\\acb70b02\\0b034856_91fdd101\\Sarif.dll", | ||
"workingDirectory": "G:\\Code\\sarif-sdk\\bld\\bin\\SarifCli.FunctionalTests\\AnyCPU_Release" | ||
} | ||
} | ||
] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so we wouldn't just use 'application/json' as our mime type? #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"application" is definitely right. I'd like us to officially register SARIF with IANA, probably as "application/sarif+json" (similar to the dozens of existing MIME types "application/foo+xml"). I'll change it to "application/json" for now. Filed sarif-standard/sarif-spec-v1#268, "Register SARIF MIME type with IANA".
Update: I see that there are already MIME types of the form "application/xxx+json", so yes, this is what we want.
In reply to: 76704516 [](ancestors = 76704516)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed: Set MIME type to "application/sarif+json".
In reply to: 77440108 [](ancestors = 77440108,76704516)