private void ParseVulnerability() { var result = new Result { Locations = new List <Location>(), RelatedLocations = new List <Location>(), CodeFlows = new [] { SarifUtilities.CreateSingleThreadedCodeFlow() } }; _reader.Read(); while (!AtEndOf(_strings.Vulnerability)) { if (AtStartOfNonEmpty(_strings.ClassId)) { result.RuleId = _reader.ReadElementContentAsString(); } else if (AtStartOfNonEmpty(_strings.ReplacementDefinitions)) { ParseReplacementDefinitions(result); } else if (AtStartOfNonEmpty(_strings.Trace)) { ParseLocationFromTrace(result); } _reader.Read(); } _results.Add(result); }
public void CanConvertCodeFlowToTreeOnlyDeclarations() { var codeFlow = SarifUtilities.CreateSingleThreadedCodeFlow(new[] { new ThreadFlowLocation { NestingLevel = 0, // Declaration }, new ThreadFlowLocation { NestingLevel = 0, // Declaration }, new ThreadFlowLocation { NestingLevel = 0, // Declaration }, }); List <CallTreeNode> topLevelNodes = CodeFlowToTreeConverter.Convert(codeFlow, run: null); topLevelNodes.Count.Should().Be(3); topLevelNodes[0].Children.Should().BeEmpty(); topLevelNodes[1].Children.Should().BeEmpty(); topLevelNodes[2].Children.Should().BeEmpty(); topLevelNodes[1].Location.NestingLevel.Should().Be(0); // Declaration topLevelNodes[0].Location.NestingLevel.Should().Be(0); // Declaration topLevelNodes[2].Location.NestingLevel.Should().Be(0); // Declaration topLevelNodes[0].Parent.Should().Be(null); topLevelNodes[1].Parent.Should().Be(null); topLevelNodes[2].Parent.Should().Be(null); }
public void SelectPreviousNextCommandsTest() { var codeFlow = SarifUtilities.CreateSingleThreadedCodeFlow(new[] { new ThreadFlowLocation { NestingLevel = 0 }, new ThreadFlowLocation { NestingLevel = 1 }, new ThreadFlowLocation { NestingLevel = 1 }, new ThreadFlowLocation { NestingLevel = 1 }, new ThreadFlowLocation { NestingLevel = 0 }, new ThreadFlowLocation { NestingLevel = 0 } }); var mockToolWindow = new Mock <IToolWindow>(); mockToolWindow.Setup(s => s.UpdateSelectionList(It.IsAny <object[]>())); CallTree callTree = new CallTree(CodeFlowToTreeConverter.Convert(codeFlow, run: null), mockToolWindow.Object); callTree.FindPrevious().Should().Be(null); callTree.FindNext().Should().Be(null); callTree.SelectedItem = callTree.TopLevelNodes[0]; callTree.FindPrevious().Should().Be(callTree.TopLevelNodes[0]); callTree.FindNext().Should().Be(callTree.TopLevelNodes[0].Children[0]); callTree.SelectedItem = callTree.TopLevelNodes[0].Children[0]; callTree.FindPrevious().Should().Be(callTree.TopLevelNodes[0]); callTree.FindNext().Should().Be(callTree.TopLevelNodes[0].Children[1]); callTree.SelectedItem = callTree.TopLevelNodes[0].Children[2]; callTree.FindPrevious().Should().Be(callTree.TopLevelNodes[0].Children[1]); callTree.FindNext().Should().Be(callTree.TopLevelNodes[1]); callTree.SelectedItem = callTree.TopLevelNodes[1]; callTree.FindPrevious().Should().Be(callTree.TopLevelNodes[0].Children[2]); callTree.FindNext().Should().Be(callTree.TopLevelNodes[2]); callTree.SelectedItem = callTree.TopLevelNodes[2]; callTree.FindPrevious().Should().Be(callTree.TopLevelNodes[1]); callTree.FindNext().Should().Be(callTree.TopLevelNodes[2]); }
public void SelectPreviousNextCommandsTest() { CodeFlow codeFlow = SarifUtilities.CreateSingleThreadedCodeFlow(new[] { new ThreadFlowLocation { NestingLevel = 0, }, new ThreadFlowLocation { NestingLevel = 1, }, new ThreadFlowLocation { NestingLevel = 1, }, new ThreadFlowLocation { NestingLevel = 1, }, new ThreadFlowLocation { NestingLevel = 0, }, new ThreadFlowLocation { NestingLevel = 0, }, }); var analysisStep = new AnalysisStep(CodeFlowToTreeConverter.Convert(codeFlow, run: null, resultId: 0, runIndex: 0)); analysisStep.FindPrevious().Should().Be(null); analysisStep.FindNext().Should().Be(null); analysisStep.SelectedItem = analysisStep.TopLevelNodes[0]; analysisStep.FindPrevious().Should().Be(analysisStep.TopLevelNodes[0]); analysisStep.FindNext().Should().Be(analysisStep.TopLevelNodes[0].Children[0]); analysisStep.SelectedItem = analysisStep.TopLevelNodes[0].Children[0]; analysisStep.FindPrevious().Should().Be(analysisStep.TopLevelNodes[0]); analysisStep.FindNext().Should().Be(analysisStep.TopLevelNodes[0].Children[1]); analysisStep.SelectedItem = analysisStep.TopLevelNodes[0].Children[2]; analysisStep.FindPrevious().Should().Be(analysisStep.TopLevelNodes[0].Children[1]); analysisStep.FindNext().Should().Be(analysisStep.TopLevelNodes[1]); analysisStep.SelectedItem = analysisStep.TopLevelNodes[1]; analysisStep.FindPrevious().Should().Be(analysisStep.TopLevelNodes[0].Children[2]); analysisStep.FindNext().Should().Be(analysisStep.TopLevelNodes[2]); analysisStep.SelectedItem = analysisStep.TopLevelNodes[2]; analysisStep.FindPrevious().Should().Be(analysisStep.TopLevelNodes[1]); analysisStep.FindNext().Should().Be(analysisStep.TopLevelNodes[2]); }
private static void AddLocationToResult(IEnumerable <CppCheckLocation> cppCheckLocations, Result result) { PhysicalLocation lastLocationConverted; var locations = new List <ThreadFlowLocation> { Capacity = cppCheckLocations.Count() }; if (locations.Capacity == 0) { return; } foreach (CppCheckLocation loc in cppCheckLocations) { locations.Add(new ThreadFlowLocation { Location = new Location { PhysicalLocation = loc.ToSarifPhysicalLocation() }, Importance = ThreadFlowLocationImportance.Essential }); } // A codeflow doesn't make sense if you only have the result location, and nothing leading up to it. if (locations.Capacity > 1) { result.CodeFlows = new List <CodeFlow>() { SarifUtilities.CreateSingleThreadedCodeFlow(locations) }; } // Set the result's location to the last location in the code flow. lastLocationConverted = locations[locations.Count - 1].Location.PhysicalLocation; result.Locations = new List <Location> { new Location { PhysicalLocation = lastLocationConverted } }; }
private CallTree CreateCallTree() { var codeFlow = SarifUtilities.CreateSingleThreadedCodeFlow(new[] { new ThreadFlowLocation { NestingLevel = 0, Importance = ThreadFlowLocationImportance.Unimportant, }, new ThreadFlowLocation { NestingLevel = 1, Importance = ThreadFlowLocationImportance.Important, }, new ThreadFlowLocation { NestingLevel = 1, Importance = ThreadFlowLocationImportance.Essential, }, new ThreadFlowLocation { NestingLevel = 1, Importance = ThreadFlowLocationImportance.Unimportant, }, new ThreadFlowLocation { NestingLevel = 0, Importance = ThreadFlowLocationImportance.Unimportant, }, new ThreadFlowLocation { NestingLevel = 0, Importance = ThreadFlowLocationImportance.Essential, } }); var mockToolWindow = new Mock <IToolWindow>(); mockToolWindow.Setup(s => s.UpdateSelectionList(It.IsAny <object[]>())); CallTree callTree = new CallTree(CodeFlowToTreeConverter.Convert(codeFlow, run: null), mockToolWindow.Object); return(callTree); }
private AnalysisStep CreateAnalysisStep() { CodeFlow codeFlow = SarifUtilities.CreateSingleThreadedCodeFlow(new[] { new ThreadFlowLocation { NestingLevel = 0, Importance = ThreadFlowLocationImportance.Unimportant, }, new ThreadFlowLocation { NestingLevel = 1, Importance = ThreadFlowLocationImportance.Important, }, new ThreadFlowLocation { NestingLevel = 1, Importance = ThreadFlowLocationImportance.Essential, }, new ThreadFlowLocation { NestingLevel = 1, Importance = ThreadFlowLocationImportance.Unimportant, }, new ThreadFlowLocation { NestingLevel = 0, Importance = ThreadFlowLocationImportance.Unimportant, }, new ThreadFlowLocation { NestingLevel = 0, Importance = ThreadFlowLocationImportance.Essential, }, }); var analysisStep = new AnalysisStep(CodeFlowToTreeConverter.Convert(codeFlow, run: null, resultId: 0, runIndex: 0)); return(analysisStep); }
public void CanConvertCodeFlowToTreeOnlyDeclarations() { CodeFlow codeFlow = SarifUtilities.CreateSingleThreadedCodeFlow(new[] { new ThreadFlowLocation { NestingLevel = 0, // Declaration }, new ThreadFlowLocation { NestingLevel = 0, // Declaration }, new ThreadFlowLocation { NestingLevel = 0, // Declaration }, }); List <AnalysisStepNode> topLevelNodes = CodeFlowToTreeConverter.Convert(codeFlow, run: null, resultId: 0, runIndex: 0); topLevelNodes.Count.Should().Be(3); topLevelNodes[0].Children.Should().BeEmpty(); topLevelNodes[1].Children.Should().BeEmpty(); topLevelNodes[2].Children.Should().BeEmpty(); topLevelNodes[1].Location.NestingLevel.Should().Be(0); // Declaration topLevelNodes[0].Location.NestingLevel.Should().Be(0); // Declaration topLevelNodes[2].Location.NestingLevel.Should().Be(0); // Declaration topLevelNodes[0].Parent.Should().Be(null); topLevelNodes[1].Parent.Should().Be(null); topLevelNodes[2].Parent.Should().Be(null); List <AnalysisStepNode> flatNodes = CodeFlowToTreeConverter.ToFlatList(codeFlow, run: null, resultId: 0, runIndex: 0); VerifyCodeFlowFlatList(flatNodes, codeFlow, run: null); }
private Result ProcessSdvDefectStream(Stream input) { var result = new Result { Locations = new List <Location>(), CodeFlows = new [] { SarifUtilities.CreateSingleThreadedCodeFlow() } }; using (var reader = new StreamReader(input)) { int nestingLevel = 0; string line; while (!string.IsNullOrEmpty(line = reader.ReadLine())) { ProcessLine(line, ref nestingLevel, result); } } return(result); }
private void GenerateCodeFlows(Defect defect, Result result) { List <SFA> sfas = defect?.Path?.SFAs; if (sfas == null || sfas.Count == 0) { return; } int step = 0; var locations = new List <ThreadFlowLocation>(); bool pathUsesKeyEvents = defect.Path.SFAs.Any(x => !string.IsNullOrWhiteSpace(x?.KeyEvent?.Id)); foreach (var sfa in defect.Path.SFAs) { var region = new Region() { StartColumn = sfa.Column + 1, StartLine = sfa.Line }; var uri = new Uri($"{sfa.FilePath}{sfa.FileName}", UriKind.Relative); var fileLocation = new PhysicalLocation(id: 0, fileLocation: new FileLocation(uri: uri, uriBaseId: null), region: region, contextRegion: null); var threadFlowLocation = new ThreadFlowLocation { Location = new Location { PhysicalLocation = fileLocation }, Step = ++step }; if (pathUsesKeyEvents) { if (string.IsNullOrWhiteSpace(sfa.KeyEvent?.Id)) { threadFlowLocation.Importance = ThreadFlowLocationImportance.Unimportant; } else { threadFlowLocation.SetProperty("keyEventId", sfa.KeyEvent.Id); if (Enum.TryParse(sfa.KeyEvent.Importance, true, out ThreadFlowLocationImportance importance)) { threadFlowLocation.Importance = importance; } if (!string.IsNullOrWhiteSpace(sfa.KeyEvent.Message) && threadFlowLocation.Location?.Message != null) { threadFlowLocation.Location.Message.Text = sfa.KeyEvent.Message; } } } locations.Add(threadFlowLocation); } result.CodeFlows = new List <CodeFlow>() { SarifUtilities.CreateSingleThreadedCodeFlow(locations) }; }
public void CanConvertCodeFlowToTree() { var codeFlow = SarifUtilities.CreateSingleThreadedCodeFlow(new[] { new ThreadFlowLocation { NestingLevel = 0, // Call Location = new Location { Message = new Message { Text = "first parent" } } }, new ThreadFlowLocation { NestingLevel = 1, // Call Location = new Location { Message = new Message { Text = "second parent" } } }, new ThreadFlowLocation { NestingLevel = 2, // CallReturn }, new ThreadFlowLocation { NestingLevel = 1, // Call Location = new Location { Message = new Message { Text = "third parent" } } }, new ThreadFlowLocation { NestingLevel = 2, // CallReturn }, new ThreadFlowLocation { NestingLevel = 1, // Call Location = new Location { Message = new Message { Text = "fourth parent" } } }, new ThreadFlowLocation { NestingLevel = 2, // CallReturn }, new ThreadFlowLocation { NestingLevel = 1, // CallReturn }, new ThreadFlowLocation { NestingLevel = 0, // Call Location = new Location { Message = new Message { Text = "fifth parent" } } }, new ThreadFlowLocation { NestingLevel = 1, // CallReturn, } }); List <CallTreeNode> topLevelNodes = CodeFlowToTreeConverter.Convert(codeFlow, run: null); topLevelNodes.Count.Should().Be(2); topLevelNodes[0].Children.Count.Should().Be(4); topLevelNodes[0].Children[2].Children.Count.Should().Be(1); // Check that we have the right nodes at the right places in the tree. topLevelNodes[0].Location.NestingLevel.Should().Be(0); // Call topLevelNodes[0].Children[0].Location.NestingLevel.Should().Be(1); // Call topLevelNodes[0].Children[0].Children[0].Location.NestingLevel.Should().Be(2); // CallReturn topLevelNodes[0].Children[1].Location.NestingLevel.Should().Be(1); // Call topLevelNodes[0].Children[1].Children[0].Location.NestingLevel.Should().Be(2); // CallReturn topLevelNodes[0].Children[2].Location.NestingLevel.Should().Be(1); // Call topLevelNodes[0].Children[2].Children[0].Location.NestingLevel.Should().Be(2); // CallReturn topLevelNodes[0].Children[3].Location.NestingLevel.Should().Be(1); // CallReturn topLevelNodes[1].Location.NestingLevel.Should().Be(0); // Call topLevelNodes[1].Children[0].Location.NestingLevel.Should().Be(1); // CallReturn // Check parents topLevelNodes[0].Parent.Should().Be(null); topLevelNodes[0].Children[0].Parent.Location.Location.Message.Text.Should().Be("first parent"); topLevelNodes[0].Children[0].Children[0].Parent.Location.Location.Message.Text.Should().Be("second parent"); topLevelNodes[0].Children[1].Parent.Location.Location.Message.Text.Should().Be("first parent"); topLevelNodes[0].Children[1].Children[0].Parent.Location.Location.Message.Text.Should().Be("third parent"); topLevelNodes[0].Children[2].Parent.Location.Location.Message.Text.Should().Be("first parent"); topLevelNodes[0].Children[2].Children[0].Parent.Location.Location.Message.Text.Should().Be("fourth parent"); topLevelNodes[0].Children[3].Parent.Location.Location.Message.Text.Should().Be("first parent"); topLevelNodes[1].Parent.Should().Be(null); topLevelNodes[1].Children[0].Parent.Location.Location.Message.Text.Should().Be("fifth parent"); }
private void ParseLocationsFromTraces(Result result) { CodeFlow codeFlow = null; string nodeLabel = null; string lastNodeId = null; bool? isDefault = null; while (!AtEndOf(_strings.Unified)) { if (AtStartOf(_strings.Trace)) { codeFlow = SarifUtilities.CreateSingleThreadedCodeFlow(); result.CodeFlows.Add(codeFlow); while (!AtEndOf(_strings.Trace)) { if (AtStartOf(_strings.NodeRef)) { string nodeId = _reader.GetAttribute(_strings.IdAttribute); if (!string.IsNullOrWhiteSpace(nodeId)) { var tfl = new ThreadFlowLocation(); _tflToNodeIdDictionary.Add(tfl, nodeId); codeFlow.ThreadFlows[0].Locations.Add(tfl); } _reader.Read(); } else if (AtStartOf(_strings.Node)) { if (isDefault == null) { // We haven't found the default node yet, so check this one. string isDefaultValue = _reader.GetAttribute(_strings.IsDefaultAttribute); if (!string.IsNullOrWhiteSpace(isDefaultValue) && bool.TryParse(isDefaultValue, out bool val) && val == true) { // This is the default, set the flag so we know to add a result location isDefault = val; } } nodeLabel = _reader.GetAttribute(_strings.LabelAttribute); _reader.Read(); } else if (AtStartOf(_strings.SourceLocation)) { // Note: SourceLocation is an empty element (it has only attributes), // so we can't call AtStartOfNonEmpty here. string snippetId = _reader.GetAttribute(_strings.SnippetAttribute); PhysicalLocation physicalLocation = ParsePhysicalLocationFromSourceInfo(); // Step past the empty SourceLocation element. _reader.Read(); string actionType = null; if (AtStartOf(_strings.Action)) { actionType = _reader.GetAttribute(_strings.TypeAttribute); actionType = actionType ?? string.Empty; // We use empty string to indicates there is an // Action element without a type attribute. // If we don't have a label, get the <Action> value if (string.IsNullOrWhiteSpace(nodeLabel)) { nodeLabel = _reader.ReadElementContentAsString(); } } if (actionType == string.Empty) { if (codeFlow.ThreadFlows[0].Locations.Count > 0) { // If there is no type attribute on the Action element, we treat // it as a note about the prior node. ThreadFlowLocation tfl = codeFlow.ThreadFlows[0].Locations.Last(); // Annotate the location with the Action text. if (tfl?.Location != null) { tfl.Location.Annotations = new List <Region>(); Region region = physicalLocation.Region; region.Message = new Message { Text = nodeLabel }; tfl.Location.Annotations.Add(region); } } } else { var location = new Location { PhysicalLocation = physicalLocation }; if (isDefault == true) { result.Locations = new List <Location>(); result.Locations.Add(location.DeepClone()); result.RelatedLocations.Add(location.DeepClone()); // Keep track of the snippet associated with the default location. // That's the snippet that we'll associate with the result. lastNodeId = snippetId; isDefault = false; // This indicates we have already found the default node. } var tfl = new ThreadFlowLocation { Kinds = new List <string> { actionType }, Location = location }; if (!string.IsNullOrWhiteSpace(nodeLabel)) { tfl.Location.Message = new Message { Text = nodeLabel }; } // Remember the id of the snippet associated with this location. // We'll use it to fill the snippet text when we read the Snippets element later on. if (!string.IsNullOrEmpty(snippetId)) { _tflToSnippetIdDictionary.Add(tfl, snippetId); } codeFlow.ThreadFlows[0].Locations.Add(tfl); } } else { _reader.Read(); } } } else { _reader.Read(); } } if (result.RelatedLocations.Any()) { Location relatedLocation = result.RelatedLocations.Last(); if (relatedLocation != null) { relatedLocation.PhysicalLocation.Id = 1; } } if (!string.IsNullOrEmpty(lastNodeId)) { _resultToSnippetIdDictionary.Add(result, lastNodeId); } }
/// <summary>Converts this instance to <see cref="Result"/>.</summary> /// <returns>This instance as an <see cref="Result"/>.</returns> public Result ToSarifIssue() { if (this.Locations.Length == 0) { throw new InvalidOperationException("At least one location must be present in a SARIF result."); } var result = new Result { RuleId = this.Id, }; result.SetProperty("Severity", this.Severity); if (!string.IsNullOrEmpty(this.VerboseMessage)) { result.Message = new Message { Text = this.VerboseMessage }; } else { result.Message = new Message { Text = this.Message }; } PhysicalLocation lastLocationConverted; if (this.Locations.Length == 1) { lastLocationConverted = this.Locations[0].ToSarifPhysicalLocation(); } else { var locations = new List <ThreadFlowLocation> { Capacity = this.Locations.Length }; foreach (CppCheckLocation loc in this.Locations) { locations.Add(new ThreadFlowLocation { Location = new Location { PhysicalLocation = loc.ToSarifPhysicalLocation() }, Importance = ThreadFlowLocationImportance.Essential }); } result.CodeFlows = new List <CodeFlow>() { SarifUtilities.CreateSingleThreadedCodeFlow(locations) }; // In the N != 1 case, set the overall location's location to // the last entry in the execution flow. lastLocationConverted = locations[locations.Count - 1].Location.PhysicalLocation; } result.Locations = new List <Location> { new Location { PhysicalLocation = lastLocationConverted } }; return(result); }
/// <summary>Converts a Fortify result to a static analysis results interchange format result.</summary> /// <param name="fortify">The Fortify result convert.</param> /// <returns> /// A SARIF result <see cref="Result"/> containing the same content as the supplied /// <see cref="FortifyIssue"/>. /// </returns> public static Result ConvertFortifyIssueToSarifIssue(FortifyIssue fortify) { var result = new Result(); result.RuleId = fortify.Category; if (!string.IsNullOrWhiteSpace(fortify.InstanceId)) { if (result.PartialFingerprints == null) { result.PartialFingerprints = new Dictionary <string, string>(); } SarifUtilities.AddOrUpdateDictionaryEntry(result.PartialFingerprints, "InstanceId", fortify.InstanceId); } List <string> messageComponents = new List <string>(); if (fortify.Abstract != null) { messageComponents.Add(fortify.Abstract); } if (fortify.AbstractCustom != null) { messageComponents.Add(fortify.AbstractCustom); } if (messageComponents.Count == 0) { result.Message = new Message { Text = String.Format(CultureInfo.InvariantCulture, ConverterResources.FortifyFallbackMessage, result.RuleId) }; } else { result.Message = new Message { Text = String.Join(Environment.NewLine, messageComponents) }; } result.SetProperty("kingdom", fortify.Kingdom); if (fortify.Priority != null) { result.SetProperty("priority", fortify.Priority); } if (!fortify.CweIds.IsDefaultOrEmpty) { result.SetProperty("cwe", String.Join(", ", fortify.CweIds.Select(id => id.ToString(CultureInfo.InvariantCulture)))); } if (fortify.RuleId != null) { result.SetProperty("fortifyRuleId", fortify.RuleId); } PhysicalLocation primaryOrSink = ConvertFortifyLocationToPhysicalLocation(fortify.PrimaryOrSink); result.Locations = new List <Location> { new Location { PhysicalLocation = primaryOrSink } }; if (fortify.Source != null) { PhysicalLocation source = ConvertFortifyLocationToPhysicalLocation(fortify.Source); var locations = new List <CodeFlowLocation>() { new CodeFlowLocation { Location = new Location { PhysicalLocation = source } }, new CodeFlowLocation { Location = new Location { PhysicalLocation = primaryOrSink } } }; result.CodeFlows = new List <CodeFlow>() { SarifUtilities.CreateSingleThreadedCodeFlow(locations) }; } return(result); }
public void CanConvertCodeFlowToTreeNonCallOrReturn() { var codeFlow = SarifUtilities.CreateSingleThreadedCodeFlow(new[] { new ThreadFlowLocation { NestingLevel = 0, // Call Location = new Location { Message = new Message { Text = "first parent", }, }, }, new ThreadFlowLocation { NestingLevel = 1, // Declaration }, new ThreadFlowLocation { NestingLevel = 1, // Declaration }, new ThreadFlowLocation { NestingLevel = 1, // Declaration }, new ThreadFlowLocation { NestingLevel = 1, // CallReturn }, new ThreadFlowLocation { NestingLevel = 0, // Call Location = new Location { Message = new Message { Text = "second parent", }, }, }, new ThreadFlowLocation { NestingLevel = 1, // Declaration }, new ThreadFlowLocation { NestingLevel = 1, // Declaration }, new ThreadFlowLocation { NestingLevel = 1, // CallReturn }, }); List <AnalysisStepNode> topLevelNodes = CodeFlowToTreeConverter.Convert(codeFlow, run: null, resultId: 0, runIndex: 0); topLevelNodes.Count.Should().Be(2); topLevelNodes[0].Children.Count.Should().Be(4); topLevelNodes[1].Children.Count.Should().Be(3); // Spot-check that we have the right nodes at the right places in the tree. topLevelNodes[0].Location.NestingLevel.Should().Be(0); // Call topLevelNodes[0].Children[0].Location.NestingLevel.Should().Be(1); // Declaration topLevelNodes[0].Children[3].Location.NestingLevel.Should().Be(1); // CallReturn topLevelNodes[1].Location.NestingLevel.Should().Be(0); // Call topLevelNodes[1].Children[2].Location.NestingLevel.Should().Be(1); // CallReturn // Check parents topLevelNodes[0].Parent.Should().Be(null); topLevelNodes[0].Children[0].Parent.Location.Location.Message.Text.Should().Be("first parent"); topLevelNodes[0].Children[1].Parent.Location.Location.Message.Text.Should().Be("first parent"); topLevelNodes[0].Children[2].Parent.Location.Location.Message.Text.Should().Be("first parent"); topLevelNodes[0].Children[3].Parent.Location.Location.Message.Text.Should().Be("first parent"); topLevelNodes[1].Parent.Should().Be(null); topLevelNodes[1].Children[0].Parent.Location.Location.Message.Text.Should().Be("second parent"); topLevelNodes[1].Children[1].Parent.Location.Location.Message.Text.Should().Be("second parent"); topLevelNodes[1].Children[2].Parent.Location.Location.Message.Text.Should().Be("second parent"); }
public void CanConvertCodeFlowToFlatListNonZeroBasedLevel() { CodeFlow codeFlow = SarifUtilities.CreateSingleThreadedCodeFlow(new[] { new ThreadFlowLocation { NestingLevel = 5, Location = new Location { Message = new Message { Text = "location level 5", }, PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Index = 0, } }, }, }, new ThreadFlowLocation { NestingLevel = 6, Location = new Location { Message = new Message { Text = "location level 6", }, PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Index = 0, } }, }, }, new ThreadFlowLocation { NestingLevel = 7, Location = new Location { Message = new Message { Text = "location level 7", }, PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Index = 0, } }, }, }, new ThreadFlowLocation { NestingLevel = 8, Location = new Location { Message = new Message { Text = "location level 8", }, PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Index = 0, } }, }, }, new ThreadFlowLocation { NestingLevel = 7, }, new ThreadFlowLocation { NestingLevel = 6, }, new ThreadFlowLocation { NestingLevel = 5, }, new ThreadFlowLocation { NestingLevel = 5, Location = new Location { Message = new Message { Text = "location level 5", }, PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Index = 1 } }, }, }, new ThreadFlowLocation { NestingLevel = 5, Location = new Location { Message = new Message { Text = "location level 5", }, PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Index = 2 } }, }, }, }); var run = new Run { Artifacts = new[] { new Artifact { Location = new ArtifactLocation { Uri = new Uri("path/to/file1.cpp", UriKind.Relative), } }, new Artifact { Location = new ArtifactLocation { Uri = new Uri("path/to/file2.cpp", UriKind.Relative), } }, new Artifact { Location = new ArtifactLocation { Uri = new Uri("path/to/file3.cpp", UriKind.Relative), } }, }, }; List <AnalysisStepNode> nodes = CodeFlowToTreeConverter.ToFlatList(codeFlow, run, resultId: 0, runIndex: 0); VerifyCodeFlowFlatList(nodes, codeFlow, run: null); }
public void CanConvertCodeFlowToFlatListZeroBasedLevel() { CodeFlow codeFlow = SarifUtilities.CreateSingleThreadedCodeFlow(new[] { new ThreadFlowLocation { NestingLevel = 0, Location = new Location { Message = new Message { Text = "location level 0", }, PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Uri = new Uri("path/to/file.cpp", UriKind.Relative), } }, }, }, new ThreadFlowLocation { NestingLevel = 1, Location = new Location { Message = new Message { Text = "location level 1", }, PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Uri = new Uri("path/to/file.cpp", UriKind.Relative), } }, }, }, new ThreadFlowLocation { NestingLevel = 2, }, new ThreadFlowLocation { NestingLevel = 1, Location = new Location { Message = new Message { Text = "location level 1", }, PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Uri = new Uri("path/to/file.cpp", UriKind.Relative), } }, }, }, new ThreadFlowLocation { NestingLevel = 2, }, new ThreadFlowLocation { NestingLevel = 1, Location = new Location { Message = new Message { Text = "location level 1", }, PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Uri = new Uri("path/to/file.cpp", UriKind.Relative), } }, }, }, new ThreadFlowLocation { NestingLevel = 2, }, new ThreadFlowLocation { NestingLevel = 1, }, new ThreadFlowLocation { NestingLevel = 0, Location = new Location { Message = new Message { Text = "location level 0", }, PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Uri = new Uri("path/to/file.cpp", UriKind.Relative), } }, }, }, new ThreadFlowLocation { NestingLevel = 1, }, }); List <AnalysisStepNode> nodes = CodeFlowToTreeConverter.ToFlatList(codeFlow, run: null, resultId: 0, runIndex: 0); VerifyCodeFlowFlatList(nodes, codeFlow, run: null); }