public int Run(RewriteOptions options) { try { Console.WriteLine($"Rewriting '{options.InputFilePath}' => '{options.OutputFilePath}'..."); Stopwatch w = Stopwatch.StartNew(); bool valid = ValidateOptions(options); if (!valid) { return(FAILURE); } string actualOutputPath = CommandUtilities.GetTransformedOutputFileName(options); SarifLog actualLog = null; string inputVersion = SniffVersion(options.InputFilePath); if (!inputVersion.Equals(SarifUtilities.StableSarifVersion)) { actualLog = TransformFileToVersionTwo(options.InputFilePath, inputVersion); } else { actualLog = ReadSarifFile <SarifLog>(_fileSystem, options.InputFilePath); } OptionallyEmittedData dataToInsert = options.DataToInsert.ToFlags(); OptionallyEmittedData dataToRemove = options.DataToRemove.ToFlags(); IDictionary <string, ArtifactLocation> originalUriBaseIds = options.ConstructUriBaseIdsDictionary(); SarifLog reformattedLog = new RemoveOptionalDataVisitor(dataToRemove).VisitSarifLog(actualLog); reformattedLog = new InsertOptionalDataVisitor(dataToInsert, originalUriBaseIds).VisitSarifLog(reformattedLog); if (options.SarifOutputVersion == SarifVersion.OneZeroZero) { var visitor = new SarifCurrentToVersionOneVisitor(); visitor.VisitSarifLog(reformattedLog); WriteSarifFile(_fileSystem, visitor.SarifLogVersionOne, actualOutputPath, options.Minify, SarifContractResolverVersionOne.Instance); } else { WriteSarifFile(_fileSystem, reformattedLog, actualOutputPath, options.Minify); } w.Stop(); Console.WriteLine($"Rewrite completed in {w.Elapsed}."); } catch (Exception ex) { Console.WriteLine(ex); return(FAILURE); } return(SUCCESS); }
public int Run(RewriteOptions rewriteOptions) { try { Console.WriteLine($"Rewriting '{rewriteOptions.InputFilePath}' => '{rewriteOptions.OutputFilePath}'..."); Stopwatch w = Stopwatch.StartNew(); bool valid = ValidateOptions(rewriteOptions); if (!valid) { return(FAILURE); } SarifLog actualLog = ReadSarifFile <SarifLog>(_fileSystem, rewriteOptions.InputFilePath); OptionallyEmittedData dataToInsert = rewriteOptions.DataToInsert.ToFlags(); OptionallyEmittedData dataToRemove = rewriteOptions.DataToRemove.ToFlags(); IDictionary <string, ArtifactLocation> originalUriBaseIds = rewriteOptions.ConstructUriBaseIdsDictionary(); SarifLog reformattedLog = new RemoveOptionalDataVisitor(dataToRemove).VisitSarifLog(actualLog); reformattedLog = new InsertOptionalDataVisitor(dataToInsert, originalUriBaseIds).VisitSarifLog(reformattedLog); string fileName = CommandUtilities.GetTransformedOutputFileName(rewriteOptions); WriteSarifFile(_fileSystem, reformattedLog, fileName, rewriteOptions.Formatting); w.Stop(); Console.WriteLine($"Rewrite completed in {w.Elapsed}."); } catch (Exception ex) { Console.WriteLine(ex); return(FAILURE); } return(SUCCESS); }
public int Run(FileWorkItemsOptions options, IFileSystem fileSystem) { if (!ValidateOptions(options, fileSystem)) { return(FAILURE); } // For unit tests: allow us to just validate the options and return. if (s_validateOptionsOnly) { return(SUCCESS); } string projectName = options.ProjectUri.GetProjectName(); string logFileContents = fileSystem.ReadAllText(options.InputFilePath); EnsureValidSarifLogFile(logFileContents, options.InputFilePath); FilingTarget filingTarget = FilingTargetFactory.CreateFilingTarget(options.ProjectUriString); var filer = new WorkItemFiler(filingTarget); SarifLog sarifLog = JsonConvert.DeserializeObject <SarifLog>(logFileContents); if (options.DataToRemove != null) { var dataRemovingVisitor = new RemoveOptionalDataVisitor(options.DataToRemove.ToFlags()); dataRemovingVisitor.Visit(sarifLog); } for (int runIndex = 0; runIndex < sarifLog.Runs.Count; ++runIndex) { if (sarifLog.Runs[runIndex]?.Results?.Count > 0) { IList <SarifLog> logsToProcess = new List <SarifLog>(new SarifLog[] { sarifLog }); if (options.GroupingStrategy != GroupingStrategy.PerRun) { SplittingVisitor visitor = (options.GroupingStrategy == GroupingStrategy.PerRunPerRule ? (SplittingVisitor) new PerRunPerRuleSplittingVisitor() : new PerRunPerTargetPerRuleSplittingVisitor()); visitor.VisitRun(sarifLog.Runs[runIndex]); logsToProcess = visitor.SplitSarifLogs; } IList <WorkItemFilingMetadata> workItemMetadata = new List <WorkItemFilingMetadata>(logsToProcess.Count); for (int splitFileIndex = 0; splitFileIndex < logsToProcess.Count; splitFileIndex++) { SarifLog splitLog = logsToProcess[splitFileIndex]; workItemMetadata.Add(splitLog.CreateWorkItemFilingMetadata(projectName, options.TemplateFilePath)); } try { IEnumerable <WorkItemFilingMetadata> filedWorkItems = filer.FileWorkItems(options.ProjectUri, workItemMetadata, options.PersonalAccessToken).Result; Console.WriteLine($"Created {filedWorkItems.Count()} work items for run {runIndex}."); } catch (Exception ex) { Console.Error.WriteLine(ex); } } } Console.WriteLine($"Writing log with work item Ids to {options.OutputFilePath}."); WriteSarifFile <SarifLog>(fileSystem, sarifLog, options.OutputFilePath, (options.PrettyPrint ? Formatting.Indented : Formatting.None)); return(SUCCESS); }
protected override string ConstructTestOutputFromInputResource(string inputResourceName, object parameter) { string v2LogText = GetResourceText(inputResourceName); string inputLogDirectory = this.OutputFolderPath; string inputLogFileName = Path.GetFileName(inputResourceName); string inputLogFilePath = Path.Combine(this.OutputFolderPath, inputLogFileName); string actualLogFilePath = Guid.NewGuid().ToString(); string ruleUnderTest = Path.GetFileNameWithoutExtension(inputLogFilePath).Split('.')[1]; // All SARIF rule prefixes require update to current release. // All rules with JSON prefix are low level syntax/deserialization checks. // We can't transform these test inputs as that operation fixes up erros in the file. bool updateInputsToCurrentSarif = ruleUnderTest.StartsWith("SARIF") ? true : false; var validateOptions = new ValidateOptions { SarifOutputVersion = SarifVersion.Current, TargetFileSpecifiers = new[] { inputLogFilePath }, OutputFilePath = actualLogFilePath, Quiet = true, UpdateInputsToCurrentSarif = updateInputsToCurrentSarif, PrettyPrint = true, Optimize = true }; var mockFileSystem = new Mock <IFileSystem>(); mockFileSystem.Setup(x => x.DirectoryExists(inputLogDirectory)).Returns(true); mockFileSystem.Setup(x => x.GetDirectoriesInDirectory(It.IsAny <string>())).Returns(new string[0]); mockFileSystem.Setup(x => x.GetFilesInDirectory(inputLogDirectory, inputLogFileName)).Returns(new string[] { inputLogFilePath }); mockFileSystem.Setup(x => x.ReadAllText(inputLogFilePath)).Returns(v2LogText); mockFileSystem.Setup(x => x.ReadAllText(It.IsNotIn <string>(inputLogFilePath))).Returns <string>(path => File.ReadAllText(path)); mockFileSystem.Setup(x => x.WriteAllText(It.IsAny <string>(), It.IsAny <string>())); var validateCommand = new ValidateCommand(mockFileSystem.Object); int returnCode = validateCommand.Run(validateOptions); if (validateCommand.ExecutionException != null) { Console.WriteLine(validateCommand.ExecutionException.ToString()); } returnCode.Should().Be(0); SarifLog actualLog = JsonConvert.DeserializeObject <SarifLog>(File.ReadAllText(actualLogFilePath)); // First, we'll strip any validation results that don't originate with the rule under test var newResults = new List <Result>(); foreach (Result result in actualLog.Runs[0].Results) { if (result.RuleId == ruleUnderTest) { newResults.Add(result); } } // Next, we'll remove non-deterministic information, most notably, timestamps emitted for the invocation data. var removeTimestampsVisitor = new RemoveOptionalDataVisitor(OptionallyEmittedData.NondeterministicProperties); removeTimestampsVisitor.Visit(actualLog); // Finally, we'll elide non-deterministic build root details var rebaseUrisVisitor = new RebaseUriVisitor("TEST_DIR", new Uri(inputLogDirectory)); rebaseUrisVisitor.Visit(actualLog); // There are differences in log file output depending on whether we are invoking xunit // from within Visual Studio or at the command-line via xunit.exe. We elide these differences. ToolComponent driver = actualLog.Runs[0].Tool.Driver; driver.Name = "SARIF Functional Testing"; driver.Version = null; driver.FullName = null; driver.SemanticVersion = null; driver.DottedQuadFileVersion = null; driver.Product = null; driver.Organization = null; driver.Properties?.Clear(); actualLog.Runs[0].OriginalUriBaseIds = null; return(JsonConvert.SerializeObject(actualLog, Formatting.Indented)); }
protected override string ConstructTestOutputFromInputResource(string inputResourceName, object parameter) { string v2LogText = GetResourceText(inputResourceName); string inputLogDirectory = this.OutputFolderPath; string inputLogFileName = Path.GetFileName(inputResourceName); string inputLogFilePath = Path.Combine(this.OutputFolderPath, inputLogFileName); string actualLogFilePath = Guid.NewGuid().ToString(); string ruleUnderTest = Path.GetFileNameWithoutExtension(inputLogFilePath).Split('.')[1]; // All SARIF rule prefixes require update to current release. // All rules with JSON prefix are low level syntax/deserialization checks. // We can't transform these test inputs as that operation fixes up errors in the file. // Also, don't transform the tests for SARIF1011 or SARIF2008, because these rules // examine the actual contents of the $schema property. string[] shouldNotTransform = { "SARIF1011", "SARIF2008" }; bool updateInputsToCurrentSarif = IsSarifRule(ruleUnderTest) && !shouldNotTransform.Contains(ruleUnderTest); var validateOptions = new ValidateOptions { SarifOutputVersion = SarifVersion.Current, TargetFileSpecifiers = new[] { inputLogFilePath }, OutputFilePath = actualLogFilePath, Quiet = true, UpdateInputsToCurrentSarif = updateInputsToCurrentSarif, PrettyPrint = true, Optimize = true, Kind = new List <ResultKind> { ResultKind.Fail }, Level = new List <FailureLevel> { FailureLevel.Error, FailureLevel.Warning, FailureLevel.Note, FailureLevel.None }, }; var mockFileSystem = new Mock <IFileSystem>(); mockFileSystem.Setup(x => x.DirectoryExists(inputLogDirectory)).Returns(true); mockFileSystem.Setup(x => x.DirectoryGetDirectories(It.IsAny <string>())).Returns(new string[0]); mockFileSystem.Setup(x => x.DirectoryGetFiles(inputLogDirectory, inputLogFileName)).Returns(new string[] { inputLogFilePath }); mockFileSystem.Setup(x => x.FileReadAllText(inputLogFilePath)).Returns(v2LogText); mockFileSystem.Setup(x => x.FileReadAllText(It.IsNotIn <string>(inputLogFilePath))).Returns <string>(path => File.ReadAllText(path)); mockFileSystem.Setup(x => x.FileWriteAllText(It.IsAny <string>(), It.IsAny <string>())); // Some rules are disabled by default, so create a configuration file that explicitly // enables the rule under test. using (TempFile configFile = CreateTempConfigFile(ruleUnderTest, parameter)) { validateOptions.ConfigurationFilePath = configFile.Name; mockFileSystem.Setup(x => x.FileExists(validateOptions.ConfigurationFilePath)).Returns(true); var validateCommand = new ValidateCommand(mockFileSystem.Object); int returnCode = validateCommand.Run(validateOptions); if (validateCommand.ExecutionException != null) { Console.WriteLine(validateCommand.ExecutionException.ToString()); } returnCode.Should().Be(0); } string actualLogFileContents = File.ReadAllText(actualLogFilePath); SarifLog actualLog = JsonConvert.DeserializeObject <SarifLog>(actualLogFileContents); Run run = actualLog.Runs[0]; // First, we'll strip any validation results that don't originate with the rule under test. // But leave the results that originate from JSchema! Also, be careful because output files // from "valid" test cases don't have any results. run.Results = run.Results ?.Where(r => IsRelevant(r.RuleId, ruleUnderTest)) ?.ToList(); // Next, remove any rule metadata for those rules. The output files from "valid" test // cases don't have any rules. run.Tool.Driver.Rules = run.Tool.Driver.Rules ?.Where(r => IsRelevant(r.Id, ruleUnderTest)) ?.ToList(); // Since there's only one rule in the metadata, the ruleIndex for all remaining results // must be 0. foreach (Result result in run.Results) { result.RuleIndex = 0; } // Next, we'll remove non-deterministic information, most notably, timestamps emitted for the invocation data. var removeTimestampsVisitor = new RemoveOptionalDataVisitor(OptionallyEmittedData.NondeterministicProperties); removeTimestampsVisitor.Visit(actualLog); // Finally, we'll elide non-deterministic build root details var rebaseUrisVisitor = new RebaseUriVisitor("TEST_DIR", new Uri(inputLogDirectory)); rebaseUrisVisitor.Visit(actualLog); // There are differences in log file output depending on whether we are invoking xunit // from within Visual Studio or at the command-line via xunit.exe. We elide these differences. ToolComponent driver = actualLog.Runs[0].Tool.Driver; driver.Name = "SARIF Functional Testing"; driver.Version = null; driver.FullName = null; driver.SemanticVersion = null; driver.DottedQuadFileVersion = null; driver.Product = null; driver.Organization = null; driver.Properties?.Clear(); actualLog.Runs[0].OriginalUriBaseIds = null; return(JsonConvert.SerializeObject(actualLog, Formatting.Indented)); }
public virtual void FileWorkItems(SarifLog sarifLog) { sarifLog = sarifLog ?? throw new ArgumentNullException(nameof(sarifLog)); this.FilingClient.Connect(this.FilingContext.PersonalAccessToken).Wait(); OptionallyEmittedData optionallyEmittedData = this.FilingContext.DataToRemove; if (optionallyEmittedData != OptionallyEmittedData.None) { var dataRemovingVisitor = new RemoveOptionalDataVisitor(optionallyEmittedData); dataRemovingVisitor.Visit(sarifLog); } optionallyEmittedData = this.FilingContext.DataToInsert; if (optionallyEmittedData != OptionallyEmittedData.None) { var dataInsertingVisitor = new InsertOptionalDataVisitor(optionallyEmittedData); dataInsertingVisitor.Visit(sarifLog); } SplittingStrategy splittingStrategy = this.FilingContext.SplittingStrategy; if (splittingStrategy == SplittingStrategy.None) { FileWorkItemsHelper(sarifLog, this.FilingContext, this.FilingClient); return; } for (int runIndex = 0; runIndex < sarifLog.Runs?.Count; ++runIndex) { if (sarifLog.Runs[runIndex]?.Results?.Count > 0) { IList <SarifLog> logsToProcess = new List <SarifLog>(new SarifLog[] { sarifLog }); if (splittingStrategy != SplittingStrategy.PerRun) { SplittingVisitor visitor; switch (splittingStrategy) { case SplittingStrategy.PerRunPerRule: visitor = new PerRunPerRuleSplittingVisitor(); break; case SplittingStrategy.PerRunPerTarget: visitor = new PerRunPerTargetSplittingVisitor(); break; case SplittingStrategy.PerRunPerTargetPerRule: visitor = new PerRunPerTargetPerRuleSplittingVisitor(); break; // TODO: Implement PerResult and PerRun splittings strategies // // https://github.com/microsoft/sarif-sdk/issues/1763 // https://github.com/microsoft/sarif-sdk/issues/1762 // case SplittingStrategy.PerResult: case SplittingStrategy.PerRun: default: throw new ArgumentOutOfRangeException($"SplittingStrategy: {splittingStrategy}"); } visitor.VisitRun(sarifLog.Runs[runIndex]); logsToProcess = visitor.SplitSarifLogs; } for (int splitFileIndex = 0; splitFileIndex < logsToProcess.Count; splitFileIndex++) { SarifLog splitLog = logsToProcess[splitFileIndex]; FileWorkItemsHelper(splitLog, this.FilingContext, this.FilingClient); } } } }
public virtual IReadOnlyList <SarifLog> SplitLogFile(SarifLog sarifLog) { IList <SarifLog> logsToProcess; using (Logger.BeginScopeContext(nameof(SplitLogFile))) { sarifLog = sarifLog ?? throw new ArgumentNullException(nameof(sarifLog)); sarifLog.SetProperty("guid", Guid.NewGuid()); this.FilingResult = FilingResult.None; this.FiledWorkItems = new List <WorkItemModel>(); sarifLog = sarifLog ?? throw new ArgumentNullException(nameof(sarifLog)); Logger.LogInformation("Connecting to filing client: {accountOrOrganization}", this.FilingClient.AccountOrOrganization); this.FilingClient.Connect(this.FilingContext.PersonalAccessToken).Wait(); OptionallyEmittedData optionallyEmittedData = this.FilingContext.DataToRemove; if (optionallyEmittedData != OptionallyEmittedData.None) { Logger.LogDebug("Removing optional data."); var dataRemovingVisitor = new RemoveOptionalDataVisitor(optionallyEmittedData); dataRemovingVisitor.Visit(sarifLog); } optionallyEmittedData = this.FilingContext.DataToInsert; if (optionallyEmittedData != OptionallyEmittedData.None) { Logger.LogDebug("Inserting optional data."); var dataInsertingVisitor = new InsertOptionalDataVisitor(optionallyEmittedData); dataInsertingVisitor.Visit(sarifLog); } using (Logger.BeginScopeContext("Splitting visitor")) { SplittingStrategy splittingStrategy = this.FilingContext.SplittingStrategy; Logger.LogInformation($"Splitting strategy - {splittingStrategy}"); if (splittingStrategy == SplittingStrategy.None) { return(new[] { sarifLog }); } PartitionFunction <string> partitionFunction = null; Stopwatch splittingStopwatch = Stopwatch.StartNew(); switch (splittingStrategy) { case SplittingStrategy.PerRun: { partitionFunction = (result) => result.ShouldBeFiled() ? "Include" : null; break; } case SplittingStrategy.PerResult: { partitionFunction = (result) => result.ShouldBeFiled() ? Guid.NewGuid().ToString() : null; break; } case SplittingStrategy.PerRunPerOrgPerEntityTypePerPartialFingerprint: { partitionFunction = (result) => result.ShouldBeFiled() ? result.GetFingerprintSplittingStrategyId() : null; break; } case SplittingStrategy.PerRunPerOrgPerEntityTypePerRepositoryPerPartialFingerprint: { partitionFunction = (result) => result.ShouldBeFiled() ? result.GetPerRepositoryFingerprintSplittingStrategyId() : null; break; } default: { throw new ArgumentOutOfRangeException($"SplittingStrategy: {splittingStrategy}"); } } Logger.LogDebug("Begin splitting logs"); var partitioningVisitor = new PartitioningVisitor <string>(partitionFunction, deepClone: false); partitioningVisitor.VisitSarifLog(sarifLog); Logger.LogDebug("Begin retrieving split logs"); logsToProcess = new List <SarifLog>(partitioningVisitor.GetPartitionLogs().Values); Logger.LogDebug("End retrieving split logs"); var logsToProcessMetrics = new Dictionary <string, object> { { "splittingStrategy", splittingStrategy }, { "logsToProcessCount", logsToProcess.Count }, { "splittingDurationInMilliseconds", splittingStopwatch.ElapsedMilliseconds }, }; this.Logger.LogMetrics(EventIds.LogsToProcessMetrics, logsToProcessMetrics); splittingStopwatch.Stop(); } } if (logsToProcess != null && !this.FilingContext.ShouldFileUnchanged) { // Remove any logs that do not contain at least one result with a New or None baselinestate. logsToProcess = logsToProcess.Where(log => log?.Runs?.Any(run => run.Results?.Any(result => result.BaselineState == BaselineState.New || result.BaselineState == BaselineState.None) == true) == true).ToList(); } return(logsToProcess.ToArray()); }
public virtual SarifLog FileWorkItems(SarifLog sarifLog) { sarifLog = sarifLog ?? throw new ArgumentNullException(nameof(sarifLog)); sarifLog.SetProperty("guid", Guid.NewGuid()); using (Logger.BeginScope(nameof(FileWorkItems))) { this.FilingResult = FilingResult.None; this.FiledWorkItems = new List<WorkItemModel>(); sarifLog = sarifLog ?? throw new ArgumentNullException(nameof(sarifLog)); Logger.LogInformation("Connecting to filing client: {accountOrOrganization}", this.FilingClient.AccountOrOrganization); this.FilingClient.Connect(this.FilingContext.PersonalAccessToken).Wait(); OptionallyEmittedData optionallyEmittedData = this.FilingContext.DataToRemove; if (optionallyEmittedData != OptionallyEmittedData.None) { var dataRemovingVisitor = new RemoveOptionalDataVisitor(optionallyEmittedData); dataRemovingVisitor.Visit(sarifLog); } optionallyEmittedData = this.FilingContext.DataToInsert; if (optionallyEmittedData != OptionallyEmittedData.None) { var dataInsertingVisitor = new InsertOptionalDataVisitor(optionallyEmittedData); dataInsertingVisitor.Visit(sarifLog); } SplittingStrategy splittingStrategy = this.FilingContext.SplittingStrategy; if (splittingStrategy == SplittingStrategy.None) { FileWorkItemsHelper(sarifLog, this.FilingContext, this.FilingClient); return sarifLog; } IList<SarifLog> logsToProcess; PartitionFunction<string> partitionFunction = null; Stopwatch splittingStopwatch = Stopwatch.StartNew(); switch (splittingStrategy) { case SplittingStrategy.PerRun: { partitionFunction = (result) => result.ShouldBeFiled() ? "Include" : null; break; } case SplittingStrategy.PerResult: { partitionFunction = (result) => result.ShouldBeFiled() ? Guid.NewGuid().ToString() : null; break; } default: { throw new ArgumentOutOfRangeException($"SplittingStrategy: {splittingStrategy}"); } } var partitioningVisitor = new PartitioningVisitor<string>(partitionFunction, deepClone: false); partitioningVisitor.VisitSarifLog(sarifLog); logsToProcess = new List<SarifLog>(partitioningVisitor.GetPartitionLogs().Values); var logsToProcessMetrics = new Dictionary<string, object> { { "splittingStrategy", splittingStrategy }, { "logsToProcessCount", logsToProcess.Count }, { "splittingDurationInMilliseconds", splittingStopwatch.ElapsedMilliseconds }, }; this.Logger.LogMetrics(EventIds.LogsToProcessMetrics, logsToProcessMetrics); splittingStopwatch.Stop(); for (int splitFileIndex = 0; splitFileIndex < logsToProcess.Count; splitFileIndex++) { SarifLog splitLog = logsToProcess[splitFileIndex]; FileWorkItemsHelper(splitLog, this.FilingContext, this.FilingClient); } } return sarifLog; }