Skip to content

Commit

Permalink
All tests pass.
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelcfanning committed Feb 12, 2023
1 parent 0926536 commit 09a417c
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 65 deletions.
2 changes: 2 additions & 0 deletions src/Sarif/FileRegionsCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ public Region ConstructMultilineContextSnippet(Region inputRegion, Uri uri, stri
return null;
}

fileText ??= newLineIndex.Text;

// Generating full inputRegion to prevent issues.
Region originalRegion = this.PopulateTextRegionProperties(inputRegion, uri, populateSnippet: true, fileText);

Expand Down
154 changes: 89 additions & 65 deletions src/Test.UnitTests.Sarif/FileRegionsCacheTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -459,51 +459,73 @@ public void FileRegionsCache_PopulatesContextRegions()
int bsl = FileRegionsCache.BIGSNIPPETLENGTH;
int ssl = FileRegionsCache.SMALLSNIPPETLENGTH;

string[] tests =
{
$"{new string(padding, 0)}{sentinel}{new string(padding, 0)}",
$"{new string(padding, 0)}{sentinel}{new string(padding, 3)}",
$"{new string(padding, 3)}{sentinel}{new string(padding, 0)}",
$"{new string(padding, 3)}{sentinel}{new string(padding, 3)}",
$"{new string(padding, ssl)}{sentinel}{new string(padding, ssl)}",
$"{new string(padding, 1)}{sentinel}{new string(padding, ssl)}",
$"{new string(padding, ssl)}{sentinel}{new string(padding, 1)}",
$"{new string(padding, ssl)}{sentinel}{new string(padding, 0)}",
$"{new string(padding, 0)}{sentinel}{new string(padding, ssl)}",
$"{new string(padding, 0)}{sentinel}{new string(padding, 0)}",
$"{new string(padding, bsl)}{sentinel}{new string(padding, bsl)}",
$"{new string(padding, 10)}{sentinel}{new string(padding, bsl)}",
$"{new string(padding, bsl)}{sentinel}{new string(padding, 10)}",
$"{new string(padding, bsl)}{sentinel}{new string(padding, 0)}",
$"{new string(padding, 0)}{sentinel}{new string(padding, bsl)}",
$"{new string(padding, 0)}{sentinel}{new string(padding, 0)}",
};

var context = new StringBuilder();
int iteration = 0;

// DEBUGGING THESE TESTS: these tests do not accumulate all outputs and report
// them, instead they break on the first failure. A failure will report a
// message like so:
//
// Expected contextRegion.Snippet not to be <null> because 'baz' snippet exists
// (iteration 12, while processing char-based region type for value 'abaza').
//
// Observe the iteration value (in this case 12). Set a conditional breakpoint
// below when the iteration variable equals this value and you can debug the
// relevant failure.

foreach (string test in tests)
// Prepend a newline (or not!) in front of every sentinel region.
foreach (string pr in new string[] { null, Environment.NewLine })
{
var cache = new FileRegionsCache();
var uri = new Uri(@"c:\temp\DoesNotExist\" + Guid.NewGuid().ToString() + ".cpp");
// Post-fix a newline (or not!) in front of every sentinel region.
foreach (string po in new string[] { null, Environment.NewLine })
{
string[] tests =
{
$"{new string(padding, 0)}{pr}{sentinel}{po}{new string(padding, 0)}",
$"{new string(padding, 0)}{pr}{sentinel}{po}{new string(padding, 3)}",
$"{new string(padding, 3)}{pr}{sentinel}{po}{new string(padding, 0)}",
$"{new string(padding, 3)}{pr}{sentinel}{po}{new string(padding, 3)}",
$"{new string(padding, ssl)}{pr}{sentinel}{po}{new string(padding, ssl)}",
$"{new string(padding, 1)}{pr}{sentinel}{po}{new string(padding, ssl)}",
$"{new string(padding, ssl)}{pr}{sentinel}{po}{new string(padding, 1)}",
$"{new string(padding, ssl)}{pr}{sentinel}{po}{new string(padding, 0)}",
$"{new string(padding, 0)}{pr}{sentinel}{po}{new string(padding, ssl)}",
$"{new string(padding, 0)}{pr}{sentinel}{po}{new string(padding, 0)}",
$"{new string(padding, bsl)}{pr}{sentinel}{po}{new string(padding, bsl)}",
$"{new string(padding, 10)}{pr}{sentinel}{po}{new string(padding, bsl)}",
$"{new string(padding, bsl)}{pr}{sentinel}{po}{new string(padding, 10)}",
$"{new string(padding, bsl)}{pr}{sentinel}{po}{new string(padding, 0)}",
$"{new string(padding, 0)}{pr}{sentinel}{po}{new string(padding, bsl)}",
$"{new string(padding, 0)}{pr}{sentinel}{po}{new string(padding, 0)}",
$"{new string(padding, 0)}{pr}{sentinel}{po}{new string(padding, 0)}",
$"{new string(padding, 0)}{pr}{sentinel}{po}{new string(padding, 3)}",
$"{new string(padding, 3)}{pr}{sentinel}{po}{new string(padding, 0)}",
$"{new string(padding, 3)}{pr}{sentinel}{po}{new string(padding, 3)}",
$"{new string(padding, ssl)}{pr}{sentinel}{po}{new string(padding, ssl)}",
$"{new string(padding, 1)}{pr}{sentinel}{po}{new string(padding, ssl)}",
$"{new string(padding, ssl)}{pr}{sentinel}{po}{new string(padding, 1)}",
$"{new string(padding, ssl)}{pr}{sentinel}{po}{new string(padding, 0)}",
$"{new string(padding, 0)}{pr}{sentinel}{po}{new string(padding, ssl)}",
$"{new string(padding, 0)}{pr}{sentinel}{po}{new string(padding, 0)}",
$"{new string(padding, bsl)}{pr}{sentinel}{po}{new string(padding, bsl)}",
$"{new string(padding, 10)}{pr}{sentinel}{po}{new string(padding, bsl)}",
$"{new string(padding, bsl)}{pr}{sentinel}{po}{new string(padding, 10)}",
$"{new string(padding, bsl)}{pr}{sentinel}{po}{new string(padding, 0)}",
$"{new string(padding, 0)}{pr}{sentinel}{po}{new string(padding, bsl)}",
$"{new string(padding, 0)}{pr}{sentinel}{po}{new string(padding, 0)}",
};

var context = new StringBuilder();
int iteration = 0;

// DEBUGGING THESE TESTS: these tests do not accumulate all outputs and report
// them, instead they break on the first failure. A failure will report a
// message like so:
//
// Expected contextRegion.Snippet not to be <null> because 'baz' snippet exists
// (iteration 12, while processing char-based region type for value 'abaza').
//
// Observe the iteration value (in this case 12). Set a conditional breakpoint
// below when the iteration variable equals this value and you can debug the
// relevant failure.

foreach (string test in tests)
{
var cache = new FileRegionsCache();
var uri = new Uri(@"c:\temp\DoesNotExist\" + Guid.NewGuid().ToString() + ".cpp");

int index = test.IndexOf(sentinel);
int index = test.IndexOf(sentinel);

// The FileRegions code takes two discrete code paths depending on whether
// the input variable is char-offset based or uses the start line convention.
var regions = new Region[]
{
// The FileRegions code takes two discrete code paths depending on whether
// the input variable is char-offset based or uses the start line convention.
var regions = new Region[]
{
new Region
{
CharOffset = index,
Expand All @@ -515,29 +537,31 @@ public void FileRegionsCache_PopulatesContextRegions()
StartColumn = index + 1,
EndColumn = index + sentinel.Length + 1,
}
};
};

string charBased = "char-based";
string lineBased = "line-based";
string charBased = "char-based";
string lineBased = "line-based";

foreach (Region region in regions)
{
context.Clear();
context.Append($"(iteration {iteration}, while processing {(region.StartLine == 1 ? lineBased : charBased)} region type for value '{test}')");

// First, we populate the region and text snippet for the actual test finding.
Region actual = cache.PopulateTextRegionProperties(region, uri, populateSnippet: true, test);

actual.Snippet.Should().NotBeNull($"'{sentinel}' snippet exists {context}");
actual.Snippet.Text?.Should().Be($"{sentinel}", $"region snippet did not match {context}");

// Now, we attempt to produce a context region.
Region contextRegion = cache.ConstructMultilineContextSnippet(actual, uri, test);
contextRegion.Snippet.Should().NotBeNull($"'{sentinel}' snippet exists {context}");
contextRegion.Snippet.Text.Contains(sentinel).Should().BeTrue($"context region should encapsulate finding {context}");
}
foreach (Region region in regions)
{
context.Clear();
context.Append($"(iteration {iteration}, while processing {(region.StartLine == 1 ? lineBased : charBased)} region type for value '{test}')");

// First, we populate the region and text snippet for the actual test finding.
Region actual = cache.PopulateTextRegionProperties(region, uri, populateSnippet: true, test);

actual.Snippet.Should().NotBeNull($"'{sentinel}' snippet exists {context}");
actual.Snippet.Text?.Should().Be($"{sentinel}", $"region snippet did not match {context}");

iteration++;
// Now, we attempt to produce a context region.
Region contextRegion = cache.ConstructMultilineContextSnippet(actual, uri, test);
contextRegion.Snippet.Should().NotBeNull($"'{sentinel}' snippet exists {context}");
contextRegion.Snippet.Text.Contains(sentinel).Should().BeTrue($"context region should encapsulate finding {context}");
}

iteration++;
}
}
}
}

Expand Down Expand Up @@ -690,14 +714,14 @@ public void FileRegionsCache_IncreasingToLeftAndRight()
CharOffset = 114,
CharLength = 600,
};

var fileRegionsCache = new FileRegionsCache();
region = fileRegionsCache.PopulateTextRegionProperties(region, uri, true, fileContent);

Region multilineRegion = fileRegionsCache.ConstructMultilineContextSnippet(region, uri);

// 114 (charoffset) + 600 (charlength) + 128 (grabbing right content)
multilineRegion.CharLength.Should().Be(114 + 600 + 128);
// 114 (charoffset) + 600 (charlength) + left-side + remainder of 128 chars.
multilineRegion.CharLength.Should().Be(114 + 600 + (128 - 114));
}

[Fact]
Expand Down

0 comments on commit 09a417c

Please sign in to comment.