Skip to content
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

Logical locations notes #1185

Merged
merged 9 commits into from
Dec 28, 2018
Merged

Logical locations notes #1185

merged 9 commits into from
Dec 28, 2018

Conversation

michaelcfanning
Copy link
Member

Resolves:

#1183: In which we didn't set -1 properly as logical location index in case of absent logical location. This code also mishandled flowing the v1 location.decoratedName to v1 logicalLocation.decoratedName

#1182: The definitive fully qualified name for a v1 result refers to location.fullyQualifiedName first then, if absent, consults location.logicalLocationKey. The definitive logical location dictionary key reverses this process.

#1179: In which we failed to set logical location index properly for constructed stack frames (one of three v1 constructs, along with locations and annotated locations, that reference logical locations).

@lgolding

@@ -336,7 +338,7 @@ internal Location CreateLocation(LocationVersionOne v1Location)
{
location = new Location
{
FullyQualifiedLogicalName = v1Location.LogicalLocationKey ?? v1Location.FullyQualifiedLogicalName,
FullyQualifiedLogicalName = v1Location.FullyQualifiedLogicalName ?? v1Location.LogicalLocationKey,
Copy link

@ghost ghost Dec 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FullyQualifiedLogicalName [](start = 59, length = 25)

BUG: This isn't right. According to the spec (I looked as far back as the original v1 "working draft" from which the TC started its work), LogicalLocationKey is never guaranteed to be a valid FQLN. It is only guaranteed to match one of the property names in the run.logicalLocations dictionary.

If v1.FQLN is missing, your only choice is to omit v2.FQLN, so the correct code here is:

location = new Location
{
    FullyQualifiedLogicalName = v1Location.FullyQualifiedLogicalName, // Works whether or not it's present in the v1 file
    ...

It doesn't even help to use the key to find the logicalLocation object in run.logicalLocations dictionary. In v1, a logicalLocation object doesn't have a fullyQualifiedName property, so you'd have to walk the parent chain and glue the FQLN together yourself (and you'd have to know the language syntax to do it).

So there's no good answer. Just copy the FQLN from v1 to v2 and call it a day.
#Resolved

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I might be contradicting what I commented in your previous PR. If so, my previous comment was wrong. You just can't get away with using a key as an FQLN.


In reply to: 244237410 [](ancestors = 244237410)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this contradicts what we discussed previously but what you say here makes perfect sense.


In reply to: 244237488 [](ancestors = 244237488,244237410)

@@ -381,11 +383,13 @@ internal Location CreateLocation(AnnotatedCodeLocationVersionOne v1AnnotatedCode
Properties = v1AnnotatedCodeLocation.Properties
};

if (!string.IsNullOrWhiteSpace(location.FullyQualifiedLogicalName))
string logicalLocationKey = v1AnnotatedCodeLocation.LogicalLocationKey ?? v1AnnotatedCodeLocation.FullyQualifiedLogicalName;
Copy link

@ghost ghost Dec 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logicalLocationKey [](start = 23, length = 18)

Yes, good. #ByDesign

{
index = _logicalLocationToIndexMap.Count;
_logicalLocationToIndexMap[logicalLocation] = index;
logicalLocationIndex = -1;
}
Copy link

@ghost ghost Dec 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

} [](start = 12, length = 1)

This is right but I wonder if this is clearer:

location.LogicalLocationIndex = -1;
if (logicalLocation != null && _v2LogicalLocationToIndexMap.TryGetValue(logicalLocation, out int logicalLocationIndexFromMap)))
{
    location.LogicalLocationIndex = logicalLocationIndexFromMap;
}
``` #WontFix

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why I think it's clearer:

  1. Doesn't require an uninitialized variable.
  2. Doesn't use a temporary, and so...
  3. One line shorter.
  4. if statement uses "positive logic".

YMMV.


In reply to: 244239471 [](ancestors = 244239471)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like where you're taking this. However, you neglect a key point, when TryGetValue fails, 'logicalLocationIndexFromMap' is initialized to the default of 0, which is not the actual default for logical location index (it is -1 as you know).

And so another subtlety in the format, our default values that do not correspond to C# primitive defaults require additional work in cases like this.


In reply to: 244239715 [](ancestors = 244239715,244239471)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, right you are.


In reply to: 244372604 [](ancestors = 244372604,244239715,244239471)

visitor.VisitRunVersionOne(v1Run);

_v1KeyToFullyQualifiedNameMap = visitor.LogicalLocationKeyToFullyQualifiedNameMap;
_v1fullyQualifiedNameToDecoratedNameMap = visitor.FullyQualifiedNameToDecoratedNameMap;
Copy link

@ghost ghost Dec 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

; [](start = 106, length = 1)

Place lines 910-920 (this block of new code) within the test if (v1Run.LogicalLocations != null) { on Line 921. #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice catch, thanks.


In reply to: 244239959 [](ancestors = 244239959)

v1Run.LogicalLocations,
v1Run.LogicalLocations,
_v1fullyQualifiedNameToDecoratedNameMap,
_v1KeyToFullyQualifiedNameMap,
Copy link

@ghost ghost Dec 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_ [](start = 32, length = 1)

Note to self: Since he's passing these two arguments, do they need to be instance fields? #Pending

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a constantly confounding question. In general, I try to parameterize method calls with data that is relevant to its general operation. The use of instance data within a helper of this kind should represent data that 'slips' out of the core function. IOW, we are either utilizing some global initialization set previously (which is configurable) or we are opportunistically preserving some data that will be used later.

Realistically, it's hard to maintain a mental model of the code to know that these 'rules' are being followed. Also, this kind of coding in general complicates unit testability, requiring creation/initialization in some cases to test isolated helpers. A more predictably testable pattern is to author as many helpers as possible as static methods. The downside here, of course, is that if you do a good job factoring methods into small pieces, you may find a need to 'plumb' instance members through several layers in order to make it available to some low level helper.

Anyway, come in soon and have lunch (on me) and we'll discuss this specific topic thoroughly. It's been on my mind for precisely the reason you added this comment here.


In reply to: 244240108 [](ancestors = 244240108)

IDictionary<string, LogicalLocationVersionOne> v1LogicalLocations,
IDictionary<string, string> fullyQualifiedNameToDecoratedNameMap,
IDictionary<string, string> keyToFullyQualifiedNameMap,
string logicalLocationKey,
Copy link

@ghost ghost Dec 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logicalLocationKey [](start = 19, length = 18)

Yes yes yes. #ByDesign


if (v1LogicalLocation.ParentKey != null && !populatedKeys.Contains(v1LogicalLocation.ParentKey))
{
// Ensure that any parent has been populated
PopulateLogicalLocation(
v2Run, v1LogicalLocations,
fullyQualifiedNameToDecoratedNameMap,
Copy link

@ghost ghost Dec 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fullyQualifiedNameToDecoratedNameMap [](start = 20, length = 36)

This variable name makes me worry whether the logic is correct.

In v1, you might have two logical locations with the same FQLN but different decorated names (if one was a type and one was a method). So I would expect to have a mapping from key to decorated name, not from FQLN to decorated name. This might become clear when I review the visitor. #Resolved

/// common fully qualified name (but which are different types), the visitor creates a mapping between
/// the logical location key and its associated fully qualified name. This allows the v2 transformation
/// in particular to more easily populate its logical location equivalents. Additionally, the visitor
/// stores a mapping from fully qualified name to decorated name, if one exists. These data (the
Copy link

@ghost ghost Dec 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exists [](start = 77, length = 6)

BUG: This is the thing I worried about in SarifVersionOneToCurrentVisitor.cs. I would expect a mapping from key to decorated name, not from FQLN to decorated name, since there could be two logical locations with the same FQLN but different decorated names. In fact, come to think of it, one of the test files has this situation. #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice catch. The PREfast samples have this condition. I believe all these samples, however, have been converted to pre-release v2. I will add a test for this case.


In reply to: 244240540 [](ancestors = 244240540)

FullyQualifiedNameToDecoratedNameMap = new Dictionary<string, string>();
LogicalLocationKeyToFullyQualifiedNameMap = new Dictionary<string, string>();
}
public IDictionary<string, string> FullyQualifiedNameToDecoratedNameMap { get; set; }
Copy link

@ghost ghost Dec 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set [](start = 87, length = 3)

Setters not necessary for these two properties. #Resolved

{
if (!string.IsNullOrEmpty(node.LogicalLocationKey) &&
!string.IsNullOrEmpty(node.FullyQualifiedLogicalName) &&
!node.FullyQualifiedLogicalName.Equals(node.LogicalLocationKey))
Copy link

@ghost ghost Dec 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

( [](start = 54, length = 1)

StringComparison.Ordinal. #WontFix

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comparison (string.Equals) is one of the places in .NET where Ordinal is the default. This is true for other primitives such as the numerics. I don't make this explicit in code (for reasons of readability and maintainability) because I consider it a sort of essential fact about .NET that is helpful to know. (just as I suggest to people that they avoid unnecessary initialization of instance members). YMMV. :)

https://docs.microsoft.com/en-us/dotnet/csharp/how-to/compare-strings
"The most common methods that test for equality, String.Equals and String.Equality, use a case-sensitive ordinal comparison."


In reply to: 244240657 [](ancestors = 244240657)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was not aware of that.


In reply to: 244376530 [](ancestors = 244376530,244240657)


if (!string.IsNullOrEmpty(node.DecoratedName))
{
string fullyQualifiedName = node.FullyQualifiedLogicalName ?? node.LogicalLocationKey;
Copy link

@ghost ghost Dec 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LogicalLocationKey [](start = 83, length = 18)

Just use the key as the index, for reason given above. #Resolved

Copy link

@ghost ghost Dec 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, that comment is wrong. But so is the code. :-) You're trying to figure out what to use as the key, so the variable name should be key, and the code is:

string key = node.LogicalLocationKey ?? node.FullyQualifiedLogicalName;
KeyToDecoratedNameMap[key] = node.DecoratedName;

In reply to: 244240704 [](ancestors = 244240704)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(This is the fix to the bug I was worried about.)


In reply to: 244373857 [](ancestors = 244373857,244240704)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your statement isn't quite right, I mention the intent in the class comment. This code only works in cases where disambiguation is created, i.e., when a logical location key is used to resolve a collision. We don't need to persist all the other cases, because generally we have our hands on a fully qualified name already on those instances. Still open to making a change here if you see one.


In reply to: 244373857 [](ancestors = 244373857,244240704)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't think this is right. You say that this code works "when a logical location key is used to resolve a collision." So consider the case:

location1 = {
    "fullyQualifiedLogicalName": "ambiguousFqln",
    "logicalLocationKey": "key1",
    "decoratedName": "dn1"
};

location2  = {
    "fullyQualifiedLogicalName": "ambiguousFqln",
    "logicalLocationKey": "key2",
    "decoratedName": "dn2"
};

fullyQualifiedLogicalName is the same, and non-null, for both locations. So when you visit location1, you will execute.

FullyQualifiedNameToDecoratedNameMap["ambiguousFqln"] = "dn1";

... and when you visit location2, you will execute

FullyQualifiedNameToDecoratedNameMap["ambiguousFqln"] = "dn2";

... losing dn1 entirely. With my suggested code, you will execute

KeyNameToDecoratedNameMap["key1"] = "dn1";
...
KeyNameToDecoratedNameMap["key2"] = "dn2";

... which is what you need.


In reply to: 244377445 [](ancestors = 244377445,244373857,244240704)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd already fixed this. I was confused by your statement in stand-up, thought we were discussing the other mapping scenario (to retrieve FQN in cases where there is a key collision)


In reply to: 244383433 [](ancestors = 244383433,244377445,244373857,244240704)

LogicalLocationKeyToFullyQualifiedNameMap[node.LogicalLocationKey] = node.FullyQualifiedLogicalName;
}

// v1 stack frame does not reference a decorated name
Copy link

@ghost ghost Dec 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stack frame [](start = 18, length = 11)

annotated code location. #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cut-n-paste ftw


In reply to: 244240816 [](ancestors = 244240816)

{
if (!string.IsNullOrEmpty(node.LogicalLocationKey) &&
!string.IsNullOrEmpty(node.FullyQualifiedLogicalName) &&
!node.FullyQualifiedLogicalName.Equals(node.LogicalLocationKey))
Copy link

@ghost ghost Dec 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Crud. This test occurs three times, but you can't DRY it out to static bool NodeHasAmbiguousLogicalLocation because the node is of three different types. Still yet another validation of the design improvement where we moved these properties into the Location object. #ByDesign

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. Almost left a comment for you on precisely this point (my inability to DRY due to the 'duck typing' of our previous design that inlined FQN and logical location keys. :)


In reply to: 244240968 [](ancestors = 244240968)

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🕐

@ghost
Copy link

ghost commented Dec 27, 2018

Two substantive bugs and several nits. #Resolved

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@michaelcfanning
Copy link
Member Author

@lgolding thanks for your diligence cleaning this area up. I explicitly added tests that exhaustively test v1 key collisions for stack frames, annotated code locations, and locations. Everything now working.

@michaelcfanning michaelcfanning merged commit b1ed2c7 into develop Dec 28, 2018
@michaelcfanning michaelcfanning deleted the logical-locations-notes branch December 28, 2018 23:04
michaelcfanning added a commit that referenced this pull request Dec 28, 2018
* 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
michaelcfanning added a commit that referenced this pull request Dec 29, 2018
* 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
michaelcfanning added a commit that referenced this pull request Dec 31, 2018
* 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
michaelcfanning added a commit that referenced this pull request Jan 28, 2019
* 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
michaelcfanning pushed a commit that referenced this pull request Feb 6, 2019
…#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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant