-
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
Basic rules transformation (except for v1 <-> v2 conversion) #1223
Conversation
@@ -15,7 +15,7 @@ namespace Microsoft.CodeAnalysis.Sarif | |||
/// <summary> | |||
/// Base class for objects that can hold properties of arbitrary types. | |||
/// </summary> | |||
public abstract class PropertyBagHolder : IPropertyBagHolder | |||
public class PropertyBagHolder : IPropertyBagHolder |
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.
class [](start = 11, length = 5)
not strictly a required change. i am observing odd cases where serialization isn't eliding default values, thought this might help. i don't see a need to retain this class as abstract, though, so left this in. #ByDesign
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.
@@ -13,5 +13,12 @@ public string Format(string messageId, IEnumerable<string> arguments) | |||
{ | |||
return string.Format(CultureInfo.CurrentCulture, this.MessageStrings[messageId], arguments.ToArray()); | |||
} | |||
|
|||
public bool ShouldSerializeDeprecatedIds() |
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.
ShouldSerializeDeprecatedIds [](start = 20, length = 28)
the absence of this helper caused a test to fail. somehow the conversion from dictionary to array interacts with json.net default value handling. to be investigated further. #ByDesign
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.
/// <summary> | ||
/// Rewriting visitor for the Sarif object model. | ||
/// </summary> | ||
public abstract partial class SarifRewritingVisitor |
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.
SarifRewritingVisitor [](start = 34, length = 21)
yay! all dictionaries converted to arrays, no need for this key visiting thing. unless we decide it's required in future for things like graphs dictionary #ByDesign
btw - this is the only code that is requiring us to maintain a NotYetGenerated copy #ByDesign Refers to: src/Sarif/NotYetAutoGenerated/SarifRewritingVisitor.cs:724 in 1707f72. [](commit_id = 1707f72, deletion_comment = False) |
@@ -1,6 +1,6 @@ | |||
{ | |||
"$schema": "http://json.schemastore.org/sarif-2.0.0-csd.2.beta.2018-11-28", | |||
"version": "2.0.0-csd.2.beta.2018-11-28", | |||
"$schema": "http://json.schemastore.org/sarif-2.0.0", |
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.
http://json.schemastore.org/sarif-2.0.0 [](start = 14, length = 39)
need a version that forces the prerelease transform #ByDesign
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.
{ | ||
return Path.GetFullPath(Path.Combine(@"..\..\..\..\..\src\Sarif.UnitTests\TestData", subdirectory)); | ||
return Path.GetFullPath(Path.Combine($@"..\..\..\..\..\src\{testBinaryName}\TestData", subdirectory)); |
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.
testBinaryName [](start = 72, length = 14)
baseline file location was previously always getting redirected to sarif.unit tests location. #ByDesign
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.
@@ -29,7 +29,7 @@ | |||
], | |||
"results": [ | |||
{ | |||
"ruleId": "C1", | |||
"ruleIndex": 0, |
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.
ruleIndex [](start = 11, length = 9)
I don't think this is the desired outcome. I think you should always include ruleId
for readability. As your "rule id collisions" test demonstrates, you do mention both ruleId
and ruleIndex
when there is a collision. I think you should do it even if there is no collision. #Closed
"rules": { | ||
"C1": { | ||
"rules": [ | ||
{ |
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.
{ [](start = 10, length = 1)
And now the rule
object doesn't have an id
property. In v1 the key was the id, unless there was a collision, so we should have "id": "C1"
here. #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.
@@ -40,7 +40,7 @@ | |||
"runs[0].tool.downloadUri", | |||
"runs[0].results[0].workItemUris[0]", | |||
"runs[0].originalUriBaseIds.SRCROOT", | |||
"runs[0].resources.rules.TST0001.helpUri", | |||
"runs[0].resources.rules[0].helpUri", |
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.
runs[0].resources.rules[0].helpUri [](start = 13, length = 34)
I hope you are enjoying the easy maintainability :-) #ByDesign
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.
@@ -32,7 +32,8 @@ internal class FortifyFprConverter : ToolFileConverterBase | |||
private string _originalUriBasePath; | |||
private List<Result> _results = new List<Result>(); | |||
private HashSet<FileData> _files; | |||
private Dictionary<string, Rule> _ruleDictionary; | |||
private List<Rule> _rules; | |||
private Dictionary<string, int> _ruleIdToIndexMap; |
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.
_ruleIdToIndexMap [](start = 40, length = 17)
Note to self: This only works if Fortify doesn't have rule collisions (if it did, a single rule id could map to multiple indices). #Closed
{ | ||
Message message = rule.ShortDescription ?? rule.FullDescription; | ||
Dictionary<string, string> replacements = null; | ||
int ruleIndex = _ruleIdToIndexMap[result.RuleId]; |
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.
RuleId [](start = 57, length = 6)
Don't you need a test similar to the old code, where you do TryGetValue
on _ruleIdToIndexMap
? #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.
don't believe so. i think the previous test was unnecessary, as the fortify report consistently contains rules metadata. will verify.
In reply to: 249143447 [](ancestors = 249143447)
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.
verified this data s.be present, no need for check
In reply to: 249147574 [](ancestors = 249147574,249143447)
run.Resources = new Resources | ||
{ | ||
Rules = rulesDictionary | ||
Rules = rules |
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.
rules [](start = 28, length = 5)
Well, that's a nice simple change! #ByDesign
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.
@@ -654,9 +654,10 @@ private void Visit(Resources resources, string resourcesPointer) | |||
{ | |||
string rulesPointer = resourcesPointer.AtProperty(SarifPropertyName.Rules); | |||
|
|||
foreach (string key in resources.Rules.Keys) | |||
|
|||
for (int i = 0; i < resources.Rules.Count; ++i) |
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.
Remove extra blank line. #Closed
@@ -46,38 +46,38 @@ private static string MakeQualifiedFilePath(string testDirectory, string testFil | |||
|
|||
private static void SelectiveCompare(SarifLog actualLog, SarifLog expectedLog) | |||
{ | |||
Result[] actualResults = SafeListToArray(actualLog.Runs[0].Results); |
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.
SafeListToArray [](start = 37, length = 15)
I don't think you can remove this. The spec says that Runs
can be null
if (for example) the tool couldn't start, or the database query that was supposed to return a set of runs was malformed. Removing this from test code relies on us never having a test with a missing Runs
array. #ByDesign
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.
How about actualLog.Runs?[0].Results
-- checking to see if that's legal C#.
In reply to: 249150331 [](ancestors = 249150331)
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.
I'm sorry, I'm confused, but I still have a point :-). You don't need the helper, because you're not converting a possibly-null
list to an array. BUT! Runs
might still be null
. I guess it's ok to leave. On the day we add such a test, that will be time enough to test for that.
In reply to: 249150739 [](ancestors = 249150739,249150331)
Rule expectedRule; | ||
expectedRules.TryGetValue(key, out expectedRule).Should().BeTrue(); | ||
Rule actualRule = actualRules[i]; | ||
Rule expectedRule = expectedRules[i]; |
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.
[i] [](start = 53, length = 3)
Ah, I see. Assuming I wrote this code, it was all based on my misconception that you couldn't index into a list. Bleah. #ByDesign
src/Sarif/Writers/SarifLogger.cs
Outdated
@@ -308,7 +308,16 @@ public void Log(IRule rule, Result result) | |||
|
|||
// TODO: we need to finish eliminating the IRule interface from the OM | |||
// https://github.com/Microsoft/sarif-sdk/issues/1189 | |||
Rules[result.RuleId] = (Rule)rule; | |||
if (!RuleToIndexMap.TryGetValue((Rule)iRule, out int ruleIndex)) |
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.
if [](start = 12, length = 2)
These 8 lines (311-318) occur twice. Consider DRYing them out with a helper LogRule(Rule rule, out int ruleIndex)
#Closed
@@ -1248,10 +1248,13 @@ | |||
} | |||
}, | |||
|
|||
|
|||
"rules": { |
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.
rules [](start = 9, length = 5)
Specify "default": []
#Closed
@@ -41,7 +41,7 @@ public void UpdateIndicesVisitor_FunctionsWithNullMaps() | |||
{ | |||
var result = _result.DeepClone(); | |||
|
|||
var visitor = new UpdateIndicesVisitor(null, null); | |||
var visitor = new UpdateIndicesVisitor(null, null, null); |
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.
UpdateIndicesVisitor [](start = 30, length = 20)
Consider: use named parameter syntax so we know what the null
s are. (I see below you did that sometimes but not always.) #WontFix
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.
right, when every argument is null in a test named 'FunctionsWithNullMap', i don't see the need for this readability. the need for naming comes during actual utilization.
things that need to be readable need to be readable. otherwise, they should be compact. still don't care enough about this to push back.
In reply to: 249155287 [](ancestors = 249155287)
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.
I took a look at the fix and it actually, to me, compromises the readability of this test. the test is intended to comprehensively validate a call where all args are null. the call without named parameters makes it easiest to chunk the information allowing this condition to be validated.
In reply to: 249187800 [](ancestors = 249187800,249155287)
"runs[0].resources.rules.TST0001.fullDescription.richText", | ||
"runs[0].resources.rules.TST0001.messageStrings.Default", | ||
"runs[0].resources.rules.TST0001.richMessageStrings.Default" | ||
"runs[0].resources.rules[0].shortDescription.text", |
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.
rules[0] [](start = 31, length = 8)
I assume this path has an array, even though the rules
property above is a dictionary, because this file goes through the PrereleaseCompatibilityTransformer
. #ByDesign
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.
that's right. i didn't care to tinker partially with this file. better to tackle all these comprehensively later when appropriate.
In reply to: 249156600 [](ancestors = 249156600)
{ | ||
// Otherwise, pick it up from the |
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.
the [](start = 50, length = 3)
Unfinished comment. #Closed
string formatString = null; | ||
if (_ruleId != null && | ||
_run.Resources?.Rules.TryGetValue(_ruleId, out rule) == true) | ||
Rule rule = _ruleIndex != -1 ? _run.Resources.Rules[_ruleIndex] : null; |
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.
_ruleIndex [](start = 28, length = 10)
Ugh, right, "lookup for messages in results is special". result.ruleMessageId
is lookin' pretty good right now, isn't it? ;-) #Resolved
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.
BUG: Darn it, I don't even think this works. There are messages in sub-objects of a result that are not rule messages. You will incorrectly take this branch, for example, for a code flow location message.
In reply to: 249157484 [](ancestors = 249157484)
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.
One possible fix: As soon as you see _ruleIndex
is not -1, then use it and immediately reset it to -1. Don't wait to come back from base.VisitResult
.
In reply to: 249166259 [](ancestors = 249166259,249157484)
_run.Resources?.Rules.TryGetValue(_ruleId, out rule) == true) | ||
Rule rule = _ruleIndex != -1 ? _run.Resources.Rules[_ruleIndex] : null; | ||
|
||
if (rule != null && rule.MessageStrings.TryGetValue(node.MessageId, out formatString)) |
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.
.T [](start = 55, length = 2)
Careful of null
: rule.MessageStrings?.TryGetValue
. #ByDesign
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.
nice catch. what a fantastic corner case. adding unit test.
In reply to: 249157825 [](ancestors = 249157825)
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.
I don't think this is a sufficient fix. It assumes that a message id that points into a rule's message strings will never be the same as a message id that points into run.resources.messageStrings
. It's easy to imagine message ids like "default"
or "success"
that might occur in both places (and even if it weren't easy to imagine, it might still happen).
What do you think of the fix I suggested above (reset _ruleIndex
to -1 as soon as you use it)?
In reply to: 249194811 [](ancestors = 249194811,249157825)
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.
See my comment in the unit tests, where I describe the failure case I'm worried about.
In reply to: 249229167 [](ancestors = 249229167,249194811,249157825)
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.
I don't understand your suggestion. When we are visiting a result with a corresponding resultIndex, we retain it. If we reset this to -1 on first use, as you suggest, no other message visiting in context of the result would have access to this data. This seems like entirely the wrong thing to so. Remember: stacks, codeflows, graphs, fixes, etc. might dip into the rule resources to get format string.
We explicitly designed string look-up to refer to the rule first, then fall back to the global. Maybe your objections will be clearer to me when i look at your unit test remarks.
oasis-tcs/sarif-spec#216
"in the presence of a non-null message.messageId, consult resources.rules by rule id, to attempt to locate the string. if not present, fall back to resources for look-up."
In reply to: 249229167 [](ancestors = 249229167,249194811,249157825)
@@ -10,11 +10,40 @@ public class UpdateIndicesVisitor : SarifRewritingVisitor | |||
{ | |||
private IDictionary<string, int> _fullyQualifiedLogicalNameToIndexMap; |
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.
IDictionary [](start = 16, length = 11)
While you're in here: The three dictionaries can be readonly
. #Closed
|
||
// We need to update the rule id, as it previously referred to a synthesized | ||
// key that resolved some collision in the resources.rules collection. | ||
node.RuleId = _resources.Rules[ruleIndex].Id; |
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.
ruleIndex [](start = 51, length = 9)
Can run.resources
fail to exist, or run.resources.rules
fail to exist, or run.resources.rules
fail to have as many entries as ruleIndex
? #ByDesign
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.
if you have a rule index but no entry, you've got bad SARIF. admittedly, we aren't hardened for negative conditions, but these are numerically intimidating. most systems should work like this: validate your SARIF if you need a hardened system, somewhere close to ingestion. from here, code can assume it is in reasonable shape.
In reply to: 249159879 [](ancestors = 249159879)
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.
ok, that sounds like a reasonable workflow to require.
In reply to: 249204481 [](ancestors = 249204481,249159879)
src/Sarif/Core/Rule.cs
Outdated
public bool ShouldSerializeDeprecatedIds() | ||
{ | ||
return this.DeprecatedIds != null && | ||
(this.DeprecatedIds.Where((e) => { return e != null; }).Count() == this.DeprecatedIds.Count); |
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.
Where [](start = 36, length = 5)
Count
can take a predicate (and my goodness, so many extra keystrokes in that lambda :-)):
this.DeprecatedIds.Count(e => e != null) == this.DeprecatedIds.Count()
``` #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.
But is this the right test? You could just
return this.DeprecatedIds?.Count(e => e != null) > 0;
... and then persist the non-null
ones.
In reply to: 249160403 [](ancestors = 249160403)
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.
} | ||
|
||
if (run["resources"] is JObject resources) |
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.
resources [](start = 52, length = 9)
Yay! #ByDesign
{ | ||
// Remove 'open' from rule configuration default level enumeration | ||
// https://github.com/oasis-tcs/sarif-spec/issues/288 | ||
modifiedLog |= RemapRuleDefaultLevelFromOpenToNote(resources); |
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.
RemapRuleDefaultLevelFromOpenToNote [](start = 39, length = 35)
Love the method name! #ByDesign
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.
if (resources["rules"] is JObject rules) | ||
{ | ||
resources["rules"] = | ||
ConstructRulesArray( |
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.
ConstructRulesArray [](start = 32, length = 19)
How about ConvertRulesDictionaryToArray
. I had to do a quick glance upward to remember that variable rules
is a dictionary at this point. #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.
For that matter, same thing for ConstructFilesArray
.
In reply to: 249161968 [](ancestors = 249161968)
@@ -477,6 +532,7 @@ private static bool RemapRuleDefaultLevelFromOpenToNote(JObject resources) | |||
// reasonable level to associate with this class of report, if it is emitted. In | |||
// practice, we don't expect that a current producer exists who is in this condition. | |||
configuration["defaultLevel"] = "note"; | |||
modifiedResources = true; |
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.
modifiedResources [](start = 20, length = 17)
Biting my tongue ;-) #WontFix
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.
Prudent. And still your point is made. :) We'll get this fixed.
In reply to: 249162790 [](ancestors = 249162790)
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.
} | ||
|
||
|
||
private static void AddEntryToRuleToIndexMap(JObject rulesDictionary, string key, JObject file, Dictionary<JObject, int> jObjectToIndexMap, Dictionary<string, int> ruleKeyToIndexMap) |
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.
file [](start = 98, length = 4)
file
=> rule
#Closed
ruleKeyToIndexMap); | ||
} | ||
|
||
var updatedArrayElements = new JObject[jObjectToIndexMap.Count]; |
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.
updatedArrayElements [](start = 16, length = 20)
Why not just rulesArray
? This name makes it sounds like there were some array elements before, and now they're different. #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.
Wow, reading my comments over I see I'm in full-on snark mode today ;-) Anyway, most of my comments are easy point fixes. The only functional change I requested was always to populate |
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.
Re-reading my comments, I noticed a bug in In reply to: 455665596 [](ancestors = 455665596) |
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.
🕐
Thanks for the snark alert, will prepare myself. result.ruleId absolutely should be populated for readability, agree In reply to: 455667726 [](ancestors = 455667726,455665596) |
src/Sarif/Core/Rule.cs
Outdated
|
||
public bool ShouldSerializeDeprecatedIds() | ||
{ | ||
return this.DeprecatedIds?.Count(e => e != null) > 1; |
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.
1 [](start = 63, length = 1)
Shouldn't this be > 0
? #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.
Oops. All changes introduce change of regression, even small ones. :)
In reply to: 249228972 [](ancestors = 249228972)
visitor.Visit(run); | ||
|
||
run.Results[0].Message.Text.Should().Be(globalMessageValue); | ||
} |
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.
} [](start = 8, length = 1)
This test doesn't demonstrate the failure case I'm worried about. Consider this test case:
var run = new Run
{
Results = new List<Result>
{
new Result
{
RuleId = "TST0001",
RuleIndex = 0,
Message = new Message
{
MessageId = "default"
},
Fixes = new List<Fix>
{
new Fix
{
Description = new Message
{
MessageId = "default"
}
}
}
},
Resources = new Resources
{
MessageStrings = new Dictionary<string, string>
{
["default"] = "Global message"
},
Rules = new List<Rule>
{
new Rule
{
Id = "TST0001",
MessageStrings = new Dictionary<string, string>
{
["default"] = "Rule message"
}
}
}
}
};
};
The visitor should set run.Results[0].Message.Text
to "Rule message"
, and it should set run.Results[0].Fixes[0].Description.Text
to "Global message"
. I claim that this test will fail because it will set both run.Results[0].Message.Text
and run.Results[0].Fixes[0].Description.Text
to "Rule message"
. #ByDesign
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.
I don't agree. A result is strongly associated with a rule. Every string look-up in context of that result should refer to the rules table first. The global table is intended to hold strings that apply to all rules. A fix may utilize a global string, sure, as anything might. But it is more likely that the fix itself has user-facing text that applies to the rule (every rule remediation is likely to differ in some aspects).
It looks like the spec may not be accurate on this. The bug I filed on it in September describes the correct look-up semantics. I will file a new issue
In reply to: 249229879 [](ancestors = 249229879)
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.
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.
Regardless of whether we agree on the intended outcome, we can agree on two things this is the test case we want.
You say "A fix may utilize a global string.". How would it do that?
In reply to: 249290961 [](ancestors = 249290961,249229879)
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.
Gotcha and agree. :) my remark on fix is a general comment, yes, nearly anything could use a global string. to do so, there must not be a collision between strings in the current rule (i.e., the rule associated with the current result) and the global table.
in any case, you're right, this is a test we need, will take care of it.
In reply to: 249291338 [](ancestors = 249291338,249290961,249229879)
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.
🕐
* Fix up tests * Conversion to files array. WIP. Core SARIF component build complete except for SarifLogger tail. * Add fileIndex property to file object (#1186) * Fix up tests * PR feedback to improve schema comment * Logical locations notes (#1185) (#1187) * Respond to a small # of PR comments related to recent logical locations change. * Fix visibility on helper * Fix up v1 transformation with keys that collide * Preserve decorated name data * Rebaseline test for decorated name propagation * Respond to PR feedback. Update tests to close test holes. * Rebaseline updated test * Test key collision in annotated code locations. * Update baseline * Reduced files array build (#1191) * Sarif and Sarif.Converters now building * Files array (#1188) * Add fileIndex property to file object (#1186) * Fix up tests * PR feedback to improve schema comment * Logical locations notes (#1185) (#1187) * Respond to a small # of PR comments related to recent logical locations change. * Fix visibility on helper * Fix up v1 transformation with keys that collide * Preserve decorated name data * Rebaseline test for decorated name propagation * Respond to PR feedback. Update tests to close test holes. * Rebaseline updated test * Test key collision in annotated code locations. * Update baseline * DRY out converters to isolate shared code. * Restore essential change in schema that converts files dictionary to an array. * Simplify ShouldSerialize logic * Remove unused namespaces * Respond to PR feedback. * Respond to PR feedback * End-to-end build works. Now we can author core transformation and fix tests. (#1192) * Fix up merge from 'develop' branch. * Update supporting test code for processing checked in files. (#1202) * Update supporting test code for processing checked in files. * Update nested files test to contain single file. * Files array basic transform (#1205) * Update supporting test code for processing checked in files. * Update nested files test to contain single file. * WIP. Furhter progress * Fix up samples build * Fix up merge from basic transform branch * Mime type validation (#1206) * Fix up merge from basic transform branch * Fix up mime test * Start work on v1 <-> v2 transformation (#1208) * Restore TransformCommand and first (unaffected) unit test * Restore "minimal prerelease v2 to current v2" test. * estore "minimal v1 to current v2" test. * Restore remaining TransformCommand unit tests. * Uncomment v2 => v1 tests to observe failures. * Uncomment 'transform' command. * Restore MakeUrisAbsoluteVisitor tests (#1210) This change updates the visitor that expands URIs in the presence of `originalUriBaseIds`. Turns out there was technical debt here, because our tests provided `originalUriBaseIds` equivalents in the property bag (because we had no official SARIF slot for them). I did not notice this gap when we made the schema change to add `originalUriBaseIds`. * Get v2 -> v1 transform working with files array (#1211) Test failure count is down to 32; will be 28 when you merge your fix. There is not -- and never was -- a test case for fileLocations that use uriBaseId (never was one). I know for a fact that there is no code to support that case. You’ll see a comment to that effect in the code. I will take care of that next. Then I will move on to v1 -> v2 transform. As part of this change, the `SarifCurrentToVersionOneVisitorTests` are now based on the `RunTest` helper method from the base class `FileDiffingTests`. * Convert debug assert to exception to make test execution more deterministic (#1214) * Update insert optional data tests and update indices visitor. (#1212) * Update insert optional data tests and update indices visitor. * Delete speculatively needed file * Remove erroneous override of base visit method. * Rework summary comment on DeletesOutputsDirectoryOnClassInitializationFixture. * Update clang analyzer name. Flow converter log verification through JToken comparison. (#1213) * The multiool, core sarif, and validation test binaries now all pass (#1215) * The multiool, core sarif, and validation test binaries now all pass completely. * Remove unwanted assert that may fire during unit testing. * Merge from files-array * PR feedback. * PR feedback tweaks * Accept PR feedback from previous change. (#1216) Use LINQ IEnuemrable.Except in the unit test, which improves readability without compromising efficiency (because Except uses a Set to do its work in O(N) time). * Fix Sarif.Driver and Sarif.Functional tests. (#1217) * Fix Sarif.Driver and Sarif.Functional tests. * Restore test file * Fix Semmle tests and Fortify converter: all tests now pass. (#1218) * Sarif converters fixups (#1219) * Fix semmle tests and fority. * Final test fixups * Invoke appveyor for files-array branch.: (#1220) * Update SarifVersionOneToCurrentVisitor for run.files array (#1221) * Uncomment v1 -> v2 tests; 3/14 fail. * Move test data to locations expected by FileDiffingTests. * Fix up some IDE C#7 code cleanups. * Use FileDiffingTests helper. * Fix bug in FileDiffingTests that caused a test failure. * Remove default-valued argument from a call to RunTest. * Create basic files array Does not yet have fileIndex, parentIndex, or response file handling. * Revert incorrect change in FileDiffingTests. * Fix one unit test with spot fix to "expected" file. * Fix up some C#7 IDE warnings * Force update in FileDiffing tests to avoid deserialization errors from out of date "expected" files. * Fix missing "modified" flag sets in PreRelCompatTransformer. * Populate fileIndex in run.files array. * Fix unit test by fixing fileLocation creation. * Restore response file handling. * Populate fileIndex on fileLocations as appropriate. * Fix last test failure by reworking response file handling. * Feedback: Introduce transformer helper PopulatePropertyIfAbsent. * Feedback: Tighten platform-independent string compare. Also: - Reformat unit test lines. * Feedbakc: Revert FileDiffingTest change; downgrade affected test files to provoke transform * Basic rules transformation (except for v1 <-> v2 conversion) (#1223) * Basic rules transformation (except for v1 <-> v2 conversion) * Respond to very excellent PR feedback. * PR feedback * Add files array tests for nested files and uriBaseIds (#1226) * Add failing v1 -> v2 nested files test * Fix existing mis-handling of analysisTarget and resultFile. * Get nested files test case working. * Add failing v1 => v2 uriBaseId test. * Populate v2 uriBaseId. * Fix up expected v2 fileLocation.properties: test passes. * Enhance uriBaseIds test case. * Implement v2->v1 conversion for rules dictionary (#1228) * Notification rule index (#1229) * Add notification.ruleIndex and increase flatten messages testing * Notification message tests + add notification.ruleIndex to schema * Notification rule index (#1230) * Add notification.ruleIndex and increase flatten messages testing * Notification message tests + add notification.ruleIndex to schema * Missed feedback from previous PR (#1231) * Implement v1->v2 conversion for rules dictionary (#1232) * Partial implementation * Get last test working. * Somebody missed checking in a generated file. * Schema changes from TC #30 (#1233) * Add source language, fix rank default. * Adjust rank minimum to accommoodate default. * Fix broken test. * Remove unnecessary None items from project file. * PR feedback * Files array results matching (#1234) * WIP preliminary results matching * Restore results matching for files array * Add back autogenerated (unused) namespace directive
…#1264) * Fix tests that are broken in appveyor (#1134) * Properly persist run level property bags (#1136) * Fix #1138: Add validation rule: contextRegion requires region (#1142) Also: - Enhance the "new-style" verification so that we no longer require the file "Invalid_Expected.sarif". Each file can now contain a property that specifies the expected locations of all the validation results. * Prep for 2018-11-28 schema update. Remove run.architecture. (#1145) * Add run.newlineSequences to schema (#1146) * Mark result.message as required in the schema (#1147) * Mark result.message as required in the schema * Update release history with result.message breaking change. * Fix typo in testoutput. * Rename tool.fileVersion to tool.dottedQuadFileVersion (#1148) * Upgrade more validator functional tests (#1149) We apply the new functional test pattern to four more rules: - `EndColumnMustNotBeLessThanStartColumn` - `EndLineMustNotBeLessThanStartLine` - `EndTimeMustBeAfterStartTime` (which is misnamed, and in a future PR we will rename it to `EndTimeMustNotBeBeforeStartTime`) - `MessageShouldEndWithPeriod` In addition, we remove the test data for a rule that no longer exists, `HashAlgorithmsMustBeUnique` (which no longer applies because `file.hashes` is now an object keyed by the hash algorithm). Because there are so many properties of type `message`, exhaustively testing the rule `MessageShouldEndWithPeriod` revealed many holes in the visitor class `SarifValidationSkimmerBase`, which I plugged. As we have discussed, we should generate this class from the schema. After this, there are only two more rules to convert: - `UriBaseIdRequiresRelativeUri` - `UseAbsolutePathsForNestedFileUriFragments` ... but this PR is already large enough. * Remove 'open' from list of valid rule configuration default values. (#1158) * Emit column kind default explicitly for Windows SDK SARIF emit. (#1160) * Emit column kind default explicitly for Windows SDK SARIF emit. * Update release notes * More column kind test fixes * Change behavior to always serialize column kind. * Always serialize column kind * Finish validator functional test upgrade (#1159) * Rename rule EndTimeMustBeAfterStartTime => ...MustNotBeBefore... * Upgrade UriBaseIdRequiresRelativeUri tests. * Remove obsolete rule UseAbsolutePathsForNestedFileUriFragments. * Remove support for old test design. * Remove 'package' as a documented logical location kind in the schema. Documentation only change. (#1162) * Fortify FPR converter improvements + unit tests (#1161) * Improvements and corrections Populate originalUriBaseIds from <SourceBasePath> Populate tFL.kind from <Action type="..."> Add default node to result.locations * Add location annotation for Action elements with no type attribute * Support node annotations + uribasepath + test updates * Update FortifyTest.fpr.sarif * Add converter tests & assets + opportunistic code cleanup * PR feedback * Logical locations dictionaries to arrays (#1170) The core change here is the transformation of `run.logicalLocations` from a dictionary (which is keyed, generally, by the fully qualified name of a logical location) to an array of logical locations. Result locations now reference logical locations by a logical location index. This changes removes the necessity of resolving key name collisions for logical locations that differ only by type (a namespace that collides with the fully qualified name of a type being the classic example). In addition to making the core change, we have also authored a transformation that converts existing pre-release SARIF v2 files to the new design. We accomplish this by creating dictionaries, with value type comparison for keys, that are keyed by logical locations. This processing requires that any parent keys already exist in the array (so that a logical location can populate its parent logical location index, if any). In addition to the core functionality and any transformation of individual log files, result matching presents special complications. In a result matching scenario, the logical location index of a result is not relevant to its identify: only the contents of the logical location this index points to are relevant. Furthermore, when merging a baseline file (which can contain results that are exclusive to a single log file within the matching domain), logical location indices are subject to change and must be updated. For this scenario and at least one other, we use a visitor pattern to update indices. The reason is that locations are pervasive in the format and the visitor provides a convenient mechanism to put common location processing logical. This visitor uses puts additional pressure on the transformation logic, as it entails additional deserialization of the JSON. With more time/effort, we could have exhaustively updated all locations using the JParser/JObject/etc. API domain. Oh well. Finally, we must update the logical that transforms v1 to v2 and vice versa. Whew. If that was not already sufficiently intrusive, this work revealed some minor flaws in various converters (the ones that handle logical locations): AndroidStudio, FxCop and PREfast. This change is complex but valuable. Logical locations are now expressed as coherent objects in their table. In the main, I have preferred to leave `result.fullyQualifiedName` populated (in addition to `result.logicalLocationIndex`, to support easily looking up matching logical locations). * Add result.rank and ruleConfiguration.defaultRank (#1167) As we discussed offline with @fishoak, the design is good as it stands. The only change is that the default should be -1. I filed oasis-tcs/sarif-spec#303 for that, and put it on the agenda for TC #30. * Logical locations notes (#1184) * Respond to a small # of PR comments related to recent logical locations change. * Fix visibility on helper * Logical locations notes (#1185) * Respond to a small # of PR comments related to recent logical locations change. * Fix visibility on helper * Fix up v1 transformation with keys that collide * Preserve decorated name data * Rebaseline test for decorated name propagation * Respond to PR feedback. Update tests to close test holes. * Rebaseline updated test * Test key collision in annotated code locations. * Update baseline * Incorporate "provenance" schema changes and fix package licenses (#1193) * Add autogenerated RuleConfiguration.cs missed from earlier commit. * Upgrade to NuGet.exe 4.9.2 to handle new license tag. * Remove unused 'Owners' element from build.props. * Add package Title. * Use packageLicenseExpression to specify package license. * Suppress NU5105 (about SemVer 2.0.0 strings) for "dotnet pack" packages. NuGet.exe still warns for ".nuspec" packages. * Incorporate latest "provenance" schema changes. * Address PR feedback. * External property files (#1194) * Update spec for externalPropertiesFile object. * Add external property files to schema. * Finish merge of provenance changes. * Update release notes. * Remove vertical whitespace. * PR feedback. Fix 'properties' to refer to an external file not an actual properties bag. * Remove code gen hint that makes external property files a property bag holder. * Introduce missing brace. Fix up code emit for 'properties' property that isn't a property bag. * Incorporate schema changes for versionControlDetails.mappedTo and rule.deprecatedIds (#1198) * Incorporate "versionControlDetails.mappedTo" schema change. * Incorporate "rule.deprecatedIds" schema change. * Revert updates to comprehensive.sarif (to allow transformer to continue to use this as test content). * Array scrub part 1: everything but anyOf-or-null properties. (#1201) NOTE: For explicitness, I added schema attributes even when they matched the JSON schema defaults, namely: `"minItems": 0` and `"uniqueItems": false`. * Fix v1->v2 hash transformation (#1203) CreateHash must be called to handle algorithm names that aren't in our translation table. Also updated a unit test to cover this case. * Integrate jschema 0.61.0 into SDK (#1204) * Merging arrays transformations back into 'develop' branch (#1236) * Fix up tests * Conversion to files array. WIP. Core SARIF component build complete except for SarifLogger tail. * Add fileIndex property to file object (#1186) * Fix up tests * PR feedback to improve schema comment * Logical locations notes (#1185) (#1187) * Respond to a small # of PR comments related to recent logical locations change. * Fix visibility on helper * Fix up v1 transformation with keys that collide * Preserve decorated name data * Rebaseline test for decorated name propagation * Respond to PR feedback. Update tests to close test holes. * Rebaseline updated test * Test key collision in annotated code locations. * Update baseline * Reduced files array build (#1191) * Sarif and Sarif.Converters now building * Files array (#1188) * Add fileIndex property to file object (#1186) * Fix up tests * PR feedback to improve schema comment * Logical locations notes (#1185) (#1187) * Respond to a small # of PR comments related to recent logical locations change. * Fix visibility on helper * Fix up v1 transformation with keys that collide * Preserve decorated name data * Rebaseline test for decorated name propagation * Respond to PR feedback. Update tests to close test holes. * Rebaseline updated test * Test key collision in annotated code locations. * Update baseline * DRY out converters to isolate shared code. * Restore essential change in schema that converts files dictionary to an array. * Simplify ShouldSerialize logic * Remove unused namespaces * Respond to PR feedback. * Respond to PR feedback * End-to-end build works. Now we can author core transformation and fix tests. (#1192) * Fix up merge from 'develop' branch. * Update supporting test code for processing checked in files. (#1202) * Update supporting test code for processing checked in files. * Update nested files test to contain single file. * Files array basic transform (#1205) * Update supporting test code for processing checked in files. * Update nested files test to contain single file. * WIP. Furhter progress * Fix up samples build * Fix up merge from basic transform branch * Mime type validation (#1206) * Fix up merge from basic transform branch * Fix up mime test * Start work on v1 <-> v2 transformation (#1208) * Restore TransformCommand and first (unaffected) unit test * Restore "minimal prerelease v2 to current v2" test. * estore "minimal v1 to current v2" test. * Restore remaining TransformCommand unit tests. * Uncomment v2 => v1 tests to observe failures. * Uncomment 'transform' command. * Restore MakeUrisAbsoluteVisitor tests (#1210) This change updates the visitor that expands URIs in the presence of `originalUriBaseIds`. Turns out there was technical debt here, because our tests provided `originalUriBaseIds` equivalents in the property bag (because we had no official SARIF slot for them). I did not notice this gap when we made the schema change to add `originalUriBaseIds`. * Get v2 -> v1 transform working with files array (#1211) Test failure count is down to 32; will be 28 when you merge your fix. There is not -- and never was -- a test case for fileLocations that use uriBaseId (never was one). I know for a fact that there is no code to support that case. You’ll see a comment to that effect in the code. I will take care of that next. Then I will move on to v1 -> v2 transform. As part of this change, the `SarifCurrentToVersionOneVisitorTests` are now based on the `RunTest` helper method from the base class `FileDiffingTests`. * Convert debug assert to exception to make test execution more deterministic (#1214) * Update insert optional data tests and update indices visitor. (#1212) * Update insert optional data tests and update indices visitor. * Delete speculatively needed file * Remove erroneous override of base visit method. * Rework summary comment on DeletesOutputsDirectoryOnClassInitializationFixture. * Update clang analyzer name. Flow converter log verification through JToken comparison. (#1213) * The multiool, core sarif, and validation test binaries now all pass (#1215) * The multiool, core sarif, and validation test binaries now all pass completely. * Remove unwanted assert that may fire during unit testing. * Merge from files-array * PR feedback. * PR feedback tweaks * Accept PR feedback from previous change. (#1216) Use LINQ IEnuemrable.Except in the unit test, which improves readability without compromising efficiency (because Except uses a Set to do its work in O(N) time). * Fix Sarif.Driver and Sarif.Functional tests. (#1217) * Fix Sarif.Driver and Sarif.Functional tests. * Restore test file * Fix Semmle tests and Fortify converter: all tests now pass. (#1218) * Sarif converters fixups (#1219) * Fix semmle tests and fority. * Final test fixups * Invoke appveyor for files-array branch.: (#1220) * Update SarifVersionOneToCurrentVisitor for run.files array (#1221) * Uncomment v1 -> v2 tests; 3/14 fail. * Move test data to locations expected by FileDiffingTests. * Fix up some IDE C#7 code cleanups. * Use FileDiffingTests helper. * Fix bug in FileDiffingTests that caused a test failure. * Remove default-valued argument from a call to RunTest. * Create basic files array Does not yet have fileIndex, parentIndex, or response file handling. * Revert incorrect change in FileDiffingTests. * Fix one unit test with spot fix to "expected" file. * Fix up some C#7 IDE warnings * Force update in FileDiffing tests to avoid deserialization errors from out of date "expected" files. * Fix missing "modified" flag sets in PreRelCompatTransformer. * Populate fileIndex in run.files array. * Fix unit test by fixing fileLocation creation. * Restore response file handling. * Populate fileIndex on fileLocations as appropriate. * Fix last test failure by reworking response file handling. * Feedback: Introduce transformer helper PopulatePropertyIfAbsent. * Feedback: Tighten platform-independent string compare. Also: - Reformat unit test lines. * Feedbakc: Revert FileDiffingTest change; downgrade affected test files to provoke transform * Basic rules transformation (except for v1 <-> v2 conversion) (#1223) * Basic rules transformation (except for v1 <-> v2 conversion) * Respond to very excellent PR feedback. * PR feedback * Add files array tests for nested files and uriBaseIds (#1226) * Add failing v1 -> v2 nested files test * Fix existing mis-handling of analysisTarget and resultFile. * Get nested files test case working. * Add failing v1 => v2 uriBaseId test. * Populate v2 uriBaseId. * Fix up expected v2 fileLocation.properties: test passes. * Enhance uriBaseIds test case. * Implement v2->v1 conversion for rules dictionary (#1228) * Notification rule index (#1229) * Add notification.ruleIndex and increase flatten messages testing * Notification message tests + add notification.ruleIndex to schema * Notification rule index (#1230) * Add notification.ruleIndex and increase flatten messages testing * Notification message tests + add notification.ruleIndex to schema * Missed feedback from previous PR (#1231) * Implement v1->v2 conversion for rules dictionary (#1232) * Partial implementation * Get last test working. * Somebody missed checking in a generated file. * Schema changes from TC #30 (#1233) * Add source language, fix rank default. * Adjust rank minimum to accommoodate default. * Fix broken test. * Remove unnecessary None items from project file. * PR feedback * Files array results matching (#1234) * WIP preliminary results matching * Restore results matching for files array * Add back autogenerated (unused) namespace directive * Updated release notes for TC30 changes. (#1240) * Mention rules array change in release history. (#1243) * Baseline states (#1245) * Add 'updated' state to baselineState and rename 'existing' to 'unchanged' * Update prerelease transformer * Enable appveyor build + test. Correct version constant. * Update test. Respond to PR feedback. * Fix #1251 #1252 #1253 (#1254) * Fixes + test coverage + cleanup * Update SDK version * Update version in test assets * Fix multitool nuspec (#1256) * Revert unintentional change to BaselineState (#1262) The `develop` branch should match TC <span>#</span>30, but we inadvertently introduced a change from TC <span>#</span>31: replacing `BaselineState.Existing` with `.Unchanged` and `Updated`. I did not revert the entire change. Some things (like having AppVeyor build the `tc-31` branch instead of the defunct `files-array` branch, and some C# 7 updates to the `PrereleaseCompatibilityTransformer`) were good, and I kept them. Also: - Update the version to `2019-01-09` in preparation for merge to `master`. * Transfer Bogdan's point fix (analysisTarget handling) from master to develop (#1263) In preparation for merging `develop` to `master` for the publication of version 2019-01-09 (TC <span>#</span>30), we apply the recent changes in `master` to the `develop` branch. These changes fixed two bugs in the handling of `analysisTarget` in the v1-to-v2 converter (`SarifVersionOneToCurrentVisitor`). Now `develop` is completely up to date, and when we merge `develop` to `master`, we _should_ be able to simply take the "incoming" changes on all conflicting files. * Cherry-pick: v1 transformer analysis target region persistence fix. (#1238) * Mention NuGet publishing changes in release history. * Cherry pick: Don't emit v2 analysisTarget if there is no v1 resultFile. (#1247)
@lgolding, core rules array transformation work is done. I haven't made my own scan of this PR yet, wanted you to know that this is definitely landing today. Note that I've disabled the v1 <-> v2 testing for the change.