public void SarifErrorListItem_HasEmbeddedLinks_MultipleSentencesWithEmbeddedLinks()
        {
            const string s1     = "The quick [brown](1) fox.";
            const string s2     = "Jumps over the [lazy](2) dog.";
            var          result = new Result
            {
                Message = new Message()
                {
                    Text = $"{s1} {s2}",
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);

            item.HasEmbeddedLinks.Should().BeTrue();

            // "The quick ", "brown", " fox.", "Jumps over the ", "lazy", " dog."
            item.MessageInlines.Count.Should().Be(5);
            item.MessageInlines[0].ContentStart.GetTextInRun(XamlDoc.LogicalDirection.Forward).Should().BeEquivalentTo("The quick ");
            var hyperlink = item.MessageInlines[1] as XamlDoc.Hyperlink;

            hyperlink.Inlines.First().ContentStart.GetTextInRun(XamlDoc.LogicalDirection.Forward).Should().BeEquivalentTo("brown");
            item.MessageInlines[2].ContentStart.GetTextInRun(XamlDoc.LogicalDirection.Forward).Should().BeEquivalentTo(" fox. Jumps over the ");
            hyperlink = item.MessageInlines[3] as XamlDoc.Hyperlink;
            hyperlink.Inlines.First().ContentStart.GetTextInRun(XamlDoc.LogicalDirection.Forward).Should().BeEquivalentTo("lazy");
            item.MessageInlines[4].ContentStart.GetTextInRun(XamlDoc.LogicalDirection.Forward).Should().BeEquivalentTo(" dog.");

            item.ShortMessage.Should().Be("The quick [brown](1) fox.");
            item.Message.Should().Be("The quick [brown](1) fox. Jumps over the [lazy](2) dog.");
        }
        public void SarifErrorListItem_WhenResultRefersToRuleWithNoMessageStrings_ContainsBlankMessage()
        {
            var result = new Result
            {
                Message = new Message
                {
                    Id = "nonExistentMessageId",
                },
                RuleId = "TST0001",
            };

            var run = new Run
            {
                Tool = new Tool
                {
                    Driver = new ToolComponent
                    {
                        Rules = new List <ReportingDescriptor>
                        {
                            new ReportingDescriptor
                            {
                                Id = "TST0001",
                            },
                        },
                    },
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(run, result);

            item.Message.Should().Be(string.Empty);
        }
        public void SarifErrorListItem_WhenMessageAndFormattedRuleMessageAreAbsentButRuleMetadataIsPresent_ContainsBlankMessage()
        {
            // This test prevents regression of #647,
            // "Viewer NRE when result lacks message/formattedRuleMessage but rule metadata is present"
            var result = new Result
            {
                RuleId = "TST0001",
            };

            var run = new Run
            {
                Tool = new Tool
                {
                    Driver = new ToolComponent
                    {
                        Rules = new List <ReportingDescriptor>
                        {
                            new ReportingDescriptor
                            {
                                Id = "TST0001",
                            },
                        },
                    },
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(run, result);

            item.Message.Should().Be(string.Empty);
        }
        public void SarifErrorListItem_WhenRuleMetadataIsAbsent_SynthesizesRuleModelFromResultRuleId()
        {
            var result = new Result
            {
                RuleId = "TST0001",
            };

            var run = new Run
            {
                Tool = new Tool
                {
                    Driver = new ToolComponent
                    {
                        Rules = new List <ReportingDescriptor>
                        {
                            // No metadata for rule TST0001.
                        },
                    },
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(run, result);

            item.Rule.Id.Should().Be("TST0001");
        }
        public void SarifErrorListItem_WhenRuleMetadataIsPresent_PopulatesRuleModelFromSarifRule()
        {
            var result = new Result
            {
                RuleId = "TST0001",
            };

            var run = new Run
            {
                Tool = new Tool
                {
                    Driver = new ToolComponent
                    {
                        Rules = new List <ReportingDescriptor>
                        {
                            new ReportingDescriptor
                            {
                                Id = "TST0001",
                            },
                        },
                    },
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(run, result);

            item.Fixes.Should().BeEmpty();
            item.PopulateFixModelsIfNot();
            item.Fixes.Should().BeEmpty();
            item.Rule.Id.Should().Be("TST0001");
        }
        public void SarifErrorListItem_WithPropertyBags_HasProperties()
        {
            var result = new Result();

            result.SetProperty("text", "test strings");
            result.SetProperty <bool>("validated", true);
            result.SetProperty <double>("totalAmount", 344.235d);
            result.SetProperty <int[]>("params", new int[] { -1, 2, 3 });
            result.SetProperty <object>("nullObj", null);
            result.SetProperty <dynamic>("object", new { foo = "bar" });

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);

            item.Properties.Should().BeEmpty();

            item.PopulateAdditionalPropertiesIfNot();

            item.Properties.Should().NotBeNull();
            item.Properties.Count.Should().Be(6);
            item.Properties.First(kv => kv.Key == "text").Value.Should().BeEquivalentTo("\"test strings\"");
            item.Properties.First(kv => kv.Key == "validated").Value.Should().BeEquivalentTo("true");
            item.Properties.First(kv => kv.Key == "totalAmount").Value.Should().BeEquivalentTo("344.235");
            item.Properties.First(kv => kv.Key == "params").Value.Should().BeEquivalentTo("[-1,2,3]");
            item.Properties.First(kv => kv.Key == "nullObj").Value.Should().BeNull();
            item.Properties.First(kv => kv.Key == "object").Value.Should().BeEquivalentTo("{\"foo\":\"bar\"}");
        }
        public void SarifErrorListItem_WhenFixIsConfinedToOneFile_IsFixable()
        {
            var result = new Result
            {
                Fixes = new List <Fix>
                {
                    new Fix
                    {
                        ArtifactChanges = new List <ArtifactChange>
                        {
                            new ArtifactChange
                            {
                                ArtifactLocation = new ArtifactLocation
                                {
                                    Uri = new Uri(FileName, UriKind.Relative),
                                },
                                Replacements = new List <Replacement>
                                {
                                    new Replacement
                                    {
                                        DeletedRegion = new Region
                                        {
                                            CharOffset = 52,
                                            CharLength = 5,
                                        },
                                    },
                                },
                            },
                            new ArtifactChange
                            {
                                ArtifactLocation = new ArtifactLocation
                                {
                                    Uri = new Uri(FileName, UriKind.Relative),
                                },
                                Replacements = new List <Replacement>
                                {
                                    new Replacement
                                    {
                                        DeletedRegion = new Region
                                        {
                                            CharOffset = 52,
                                            CharLength = 5,
                                        },
                                    },
                                },
                            },
                        },
                    },
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);

            CodeAnalysisResultManager.Instance.RunIndexToRunDataCache.Add(item.RunIndex, new RunDataCache());
            item.Fixes.Should().BeEmpty();
            item.PopulateFixModelsIfNot();
            item.Fixes.Should().NotBeEmpty();
            item.IsFixable().Should().BeTrue();
        }
        public void SarifErrorListItem_WhenThereAreNoFixes_IsNotFixable()
        {
            var result = new Result();

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);

            item.IsFixable().Should().BeFalse();
        }
        public void SarifErrorListItem_WhenMessageIsAbsent_ContainsBlankMessage()
        {
            var result = new Result();

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);

            item.Message.Should().Be(string.Empty);
        }
        public void SarifErrorListItem_WithoutPropertyBags_EmptyProperties()
        {
            var result = new Result();

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);

            item.Properties.Should().NotBeNull();
            item.Properties.Should().BeEmpty();
        }
        public void SarifErrorListItem_HelpLinkShouldBeSameAs_RuleHelpUri()
        {
            string link   = "https://example.com/TST0001";
            var    result = new Result
            {
                Message = new Message
                {
                    Text = "The quick brown fox.",
                },
                RuleId = "TST0001",
            };

            var run = new Run
            {
                Tool = new Tool
                {
                    Driver = new ToolComponent
                    {
                        Rules = new List <ReportingDescriptor>
                        {
                            new ReportingDescriptor
                            {
                                Id      = "TST0001",
                                HelpUri = new Uri(link),
                            },
                        },
                    },
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(run, result);

            item.HelpLink.Should().NotBeNull();
            item.HelpLink.Should().BeEquivalentTo(link);

            // without help Uri
            run = new Run
            {
                Tool = new Tool
                {
                    Driver = new ToolComponent
                    {
                        Rules = new List <ReportingDescriptor>
                        {
                            new ReportingDescriptor
                            {
                                Id = "TST0001"
                            },
                        },
                    },
                },
            };

            item = TestUtilities.MakeErrorListItem(run, result);
            item.HelpLink.Should().BeNull();
        }
        public void SarifErrorListItem_WhenFixSpansMultipleFiles_IsNotFixable()
        {
            var result = new Result
            {
                Fixes = new List <Fix>
                {
                    new Fix
                    {
                        ArtifactChanges = new List <ArtifactChange>
                        {
                            new ArtifactChange
                            {
                                ArtifactLocation = new ArtifactLocation
                                {
                                    Uri = new Uri(FileName, UriKind.Relative),
                                },
                                Replacements = new List <Replacement>
                                {
                                    new Replacement
                                    {
                                        DeletedRegion = new Region
                                        {
                                            CharOffset = 52,
                                            CharLength = 5,
                                        },
                                    },
                                },
                            },
                            new ArtifactChange
                            {
                                ArtifactLocation = new ArtifactLocation
                                {
                                    Uri = new Uri("SomeOther" + FileName, UriKind.Relative),
                                },
                                Replacements = new List <Replacement>
                                {
                                    new Replacement
                                    {
                                        DeletedRegion = new Region
                                        {
                                            CharOffset = 52,
                                            CharLength = 5,
                                        },
                                    },
                                },
                            },
                        },
                    },
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);

            item.IsFixable().Should().BeFalse();
        }
        public void SarifErrorListItem_TreatsFailResultAccordingToLevel()
        {
            var result = new Result
            {
                Level = FailureLevel.Error,
                Kind  = ResultKind.Fail,
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);

            item.Level.Should().Be(FailureLevel.Error);
        }
        public void SarifErrorListItem_TreatsReviewResultAsWarning()
        {
            var result = new Result
            {
                Kind  = ResultKind.Review,
                Level = FailureLevel.None,
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);

            item.Level.Should().Be(FailureLevel.Warning);
        }
        public void SarifErrorListItem_TreatsPassResultAsNote()
        {
            var result = new Result
            {
                Kind  = ResultKind.Pass,
                Level = FailureLevel.None,
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);

            item.Level.Should().Be(FailureLevel.Note);
        }
        public void SarifErrorListItem_ResultMessageFormat_NoTrailingPeriod()
        {
            const string s1     = "The quick brown fox";
            var          result = new Result
            {
                Message = new Message()
                {
                    Text = s1,
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);

            item.Message.Should().Be($"{s1}.");
            item.ShortMessage.Should().Be($"{s1}.");
        }
        public void SarifErrorListItem_ResultMessageFormat_MultipleSentences()
        {
            const string s1     = "The quick brown fox.";
            const string s2     = "Jumps over the lazy dog.";
            var          result = new Result
            {
                Message = new Message()
                {
                    Text = $"{s1} {s2}",
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);

            item.Message.Should().Be($"{s1} {s2}");
            item.ShortMessage.Should().Be($"{s1}");
        }
        public void SarifErrorListItem_ResultMessageFormat_TextWitLinerBreak()
        {
            const string s0 = "The quick brown fox. Jumps over the lazy dog.";
            // text with varies style of line breakers
            string s1     = "The\rquick brown fox." + Environment.NewLine + "Jumps over the lazy\ndog.";
            var    result = new Result
            {
                Message = new Message()
                {
                    Text = s1,
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);

            item.Message.Should().Be(s0);
            item.ShortMessage.Should().Be(s0);
        }
        public void SarifErrorListItem_ResultMessageFormat_LongTextWitBreak()
        {
            // very long text has a space every 10 chars
            const string s1     = "123456789 ";
            var          result = new Result
            {
                Message = new Message()
                {
                    Text = string.Concat(Enumerable.Repeat(s1, 20)), // replace s1 10 times, a string which length is 200
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);
            int breakPoistion       = 159;                            // 0 indexed

            item.ShortMessage.Length.Should().Be(breakPoistion + 2);  // the space break the text will be removed
            item.Message.Length.Should().Be(200 - breakPoistion - 2); // last space is trimmed
        }
        public void SarifErrorListItem_ResultMessageFormat_LongTextWithoutBreak()
        {
            // very long text without break like space or NewLine, longer than SarifErrorListItem.MaxConcisedTextLength
            const string s1     = "1234567890";
            var          result = new Result
            {
                Message = new Message()
                {
                    Text = string.Concat(Enumerable.Repeat(s1, 20)), // replace s1 10 times, a string which length is 200
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);
            int breakPoistion       = SarifErrorListItem.MaxConcisedTextLength;

            item.ShortMessage.Length.Should().Be(breakPoistion + 1); // add ellipsis
            item.Message.Length.Should().Be(200 + 1);                // add end punctuation
        }
        public void SarifErrorListItem_ResultMessageFormat_LongTextShouldBreak()
        {
            const string s1     = "In httplib2 before version 0.18.0, an attacker controlling unescaped part of uri for `httplib2.Http.request()` could change request headers and body, send additional hidden requests to same server. This vulnerability impacts software that uses httplib2 with uri constructed by string concatenation, as opposed to proper urllib building with escaping. This has been fixed in 0.18.0.";
            var          result = new Result
            {
                Message = new Message()
                {
                    Text = s1,
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);
            int breakPoistion       = SarifErrorListItem.MaxConcisedTextLength;

            item.ShortMessage.Length.Should().Be(breakPoistion + 1); // horizontal ellipsis chars is added at end "\u2026"
            item.ShortMessage.Last().ToString().Should().Be("\u2026");
            item.ShortMessage.Substring(0, breakPoistion).Should().Be(s1.Substring(0, breakPoistion));
            item.Message.Should().Be(s1);
        }
        public void SarifErrorListItem_WhenResultRefersToExistingMessageString_ContainsExpectedMessage()
        {
            var result = new Result
            {
                RuleId  = "TST0001",
                Message = new Message()
                {
                    Arguments = new string[]
                    {
                        "Mary",
                    },
                    Id = "greeting",
                },
            };

            var run = new Run
            {
                Tool = new Tool
                {
                    Driver = new ToolComponent
                    {
                        Rules = new List <ReportingDescriptor>
                        {
                            new ReportingDescriptor
                            {
                                Id             = "TST0001",
                                MessageStrings = new Dictionary <string, MultiformatMessageString>
                                {
                                    { "greeting", new MultiformatMessageString {
                                          Text = "Hello, {0}!"
                                      } },
                                },
                            },
                        },
                    },
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(run, result);

            item.Message.Should().Be("Hello, Mary!");
        }
        public void SarifErrorListItem_WithXamlProperty_ContainsXamlMessage()
        {
            var result = new Result
            {
                Message = new Message
                {
                    Text = "Message to be a tooltip.",
                },
                RuleId    = "TST0001",
                Locations = new[]
                {
                    new Location
                    {
                        PhysicalLocation = new PhysicalLocation
                        {
                            Region = new Region
                            {
                                StartLine   = 10,
                                StartColumn = 6,
                            },
                        },
                    },
                },
            };

            result.Message.SetProperty(SarifErrorListItem.XamlPropertyName, ValidXamlWithHyperlink);

            var run = new Run
            {
                Tool = new Tool(),
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(run, result);

            item.Message.Should().Be(result.Message.Text);
            item.XamlMessage.Should().Be(ValidXamlWithHyperlink);

            ResultTextMarker lineMarker = item.LineMarker;

            lineMarker.ToolTipContent.Should().Be(result.Message.Text);
            lineMarker.ToolTipXamlString.Should().Be(ValidXamlWithHyperlink);
        }
        public void SarifErrorListItem_ResultMessageFormat_LongTextSplitAtSpace()
        {
            // a string that index at Max Length (165) happens to be a space
            const string s1     = "In httplib2 before version 0.18.0, an attacker controlling unescaped part of uri for `httplib2.Http.request()` could change request headers and body, send additional hidden requests to same server. This vulnerability impacts software that uses httplib2 with uri constructed by string concatenation, as opposed to proper urllib building with escaping. This has been fixed in 0.18.0.";
            var          result = new Result
            {
                Message = new Message()
                {
                    Text = s1,
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);
            int breakPoistion       = 165;                           // 0 indexed

            item.ShortMessage.Length.Should().Be(breakPoistion + 2); // 2 chars is added at end " \u2026"
            item.ShortMessage.Substring(0, breakPoistion).Should().Be(s1.Substring(0, breakPoistion));
            item.Message.Length.Should().Be(s1.Length - breakPoistion - 1);
            item.Message.Should().Be(s1.Substring(breakPoistion + 1)); // leading space trimmed
        }
        public void SarifErrorListItem_WhenResultRefersToNonExistentRule_ContainsBlankMessage()
        {
            var result = new Result
            {
                Message = new Message
                {
                    Id = "nonExistentMessageId",
                },
                RuleId = "TST0001",
            };

            var run = new Run
            {
                Tool = new Tool(),
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(run, result);

            item.Message.Should().Be(string.Empty);
        }
        public void SarifErrorListItem_HasLongEmbeddedLink()
        {
            const string s1     = "The quick brown fox. Jumps over the lazy dog. Reference to [docs](https://github.com/long/path/to/docs/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/)";
            var          result = new Result
            {
                Message = new Message()
                {
                    Text = s1,
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);

            // short message should be the first sentence "The quick brown fox."
            item.HasEmbeddedLinks.Should().BeTrue();
            item.MessageInlines.Count.Should().Be(2);

            item.ShortMessage.Should().Be("The quick brown fox.");
            item.Message.Should().Be(s1 + ".");
        }
        public void SarifErrorListItem_WhenFixHasRelativePath_UsesThatPath()
        {
            var result = new Result
            {
                Fixes = new[]
                {
                    new Fix
                    {
                        ArtifactChanges = new[]
                        {
                            new ArtifactChange
                            {
                                ArtifactLocation = new ArtifactLocation
                                {
                                    Uri = new Uri("path/to/file.html", UriKind.Relative),
                                },
                                Replacements = new[]
                                {
                                    new Replacement()
                                    {
                                        DeletedRegion = new Region
                                        {
                                            ByteLength = 5,
                                            ByteOffset = 10,
                                        },
                                    },
                                },
                            },
                        },
                    },
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);

            item.Fixes.Should().BeEmpty();
            item.PopulateFixModelsIfNot();
            item.Fixes.Should().NotBeEmpty();
            item.Fixes[0].ArtifactChanges[0].FilePath.Should().Be("path/to/file.html");
        }
        public void SarifErrorListItem_WhenResultRefersToNonExistentMessageFormat_ContainsBlankMessage()
        {
            var result = new Result
            {
                Message = new Message
                {
                    Id = "nonExistentFormatId",
                },
                RuleId = "TST0001",
            };

            var run = new Run
            {
                Tool = new Tool
                {
                    Driver = new ToolComponent
                    {
                        Rules = new List <ReportingDescriptor>
                        {
                            new ReportingDescriptor
                            {
                                Id             = "TST0001",
                                MessageStrings = new Dictionary <string, MultiformatMessageString>
                                {
                                    { "realFormatId", new MultiformatMessageString {
                                          Text = "The message"
                                      } },
                                },
                            },
                        },
                    },
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(run, result);

            item.Message.Should().Be(string.Empty);
        }
예제 #29
0
        public void SarifResultEntry_MessagesTests()
        {
            string ellipsis  = "\u2026";
            var    testCases = new[]
            {
                new
                {
                    MaxTextLength     = 40,
                    RawMessage        = "",
                    ShortMessage      = "",
                    FullMessage       = "",
                    ContainsHyperlink = false,
                    ShortPlainText    = (string)null,
                    FullPlainText     = (string)null,
                },
                new
                {
                    MaxTextLength     = 40,
                    RawMessage        = "   ",
                    ShortMessage      = "",
                    FullMessage       = "",
                    ContainsHyperlink = false,
                    ShortPlainText    = (string)null,
                    FullPlainText     = (string)null,
                },
                new
                {
                    MaxTextLength     = 40,
                    RawMessage        = "A short sentence",
                    ShortMessage      = "A short sentence.",
                    FullMessage       = "A short sentence.",
                    ContainsHyperlink = false,
                    ShortPlainText    = (string)null,
                    FullPlainText     = (string)null,
                },
                new
                {
                    MaxTextLength     = 40,
                    RawMessage        = "A short sentence.",
                    ShortMessage      = "A short sentence.",
                    FullMessage       = "A short sentence.",
                    ContainsHyperlink = false,
                    ShortPlainText    = (string)null,
                    FullPlainText     = (string)null,
                },
                new
                {
                    MaxTextLength     = 40,
                    RawMessage        = "A short sentence!",
                    ShortMessage      = "A short sentence!",
                    FullMessage       = "A short sentence!",
                    ContainsHyperlink = false,
                    ShortPlainText    = (string)null,
                    FullPlainText     = (string)null,
                },
                new
                {
                    MaxTextLength     = 15,
                    RawMessage        = "A short sentence",
                    ShortMessage      = "A short sentenc" + ellipsis,
                    FullMessage       = "A short sentence.",
                    ContainsHyperlink = false,
                    ShortPlainText    = (string)null,
                    FullPlainText     = (string)null,
                },
                new
                {
                    MaxTextLength     = 16,
                    RawMessage        = "A short sentence",
                    ShortMessage      = "A short sentence" + ellipsis,
                    FullMessage       = "A short sentence.",
                    ContainsHyperlink = false,
                    ShortPlainText    = (string)null,
                    FullPlainText     = (string)null,
                },
                new
                {
                    MaxTextLength     = 17,
                    RawMessage        = "A short sentence",
                    ShortMessage      = "A short sentence.",
                    FullMessage       = "A short sentence.",
                    ContainsHyperlink = false,
                    ShortPlainText    = (string)null,
                    FullPlainText     = (string)null,
                },
                new
                {
                    MaxTextLength     = 100,
                    RawMessage        = "A short sentence? The second sentence",
                    ShortMessage      = "A short sentence?",
                    FullMessage       = "A short sentence? The second sentence.",
                    ContainsHyperlink = false,
                    ShortPlainText    = (string)null,
                    FullPlainText     = (string)null,
                },
                new
                {
                    MaxTextLength     = 100,
                    RawMessage        = "A short sentence\r\n The second sentence",
                    ShortMessage      = "A short sentence.",
                    FullMessage       = "A short sentence\r\n The second sentence.",
                    ContainsHyperlink = false,
                    ShortPlainText    = (string)null,
                    FullPlainText     = (string)null,
                },
                new
                {
                    MaxTextLength     = 18,
                    RawMessage        = "The [quick brown fox](https://www.quickfox.com) jumps over the [lazy dog](http://lazy.dog.com).",
                    ShortMessage      = "The quick brown fo" + ellipsis,
                    FullMessage       = "The [quick brown fox](https://www.quickfox.com) jumps over the [lazy dog](http://lazy.dog.com).",
                    ContainsHyperlink = true,
                    ShortPlainText    = (string)null,
                    FullPlainText     = "The quick brown fox jumps over the lazy dog.",
                },
                new
                {
                    MaxTextLength     = 19,
                    RawMessage        = "The [quick brown fox](https://www.quickfox.com) jumps over the [lazy dog](http://lazy.dog.com).",
                    ShortMessage      = "The [quick brown fox](https://www.quickfox.com)" + ellipsis,
                    FullMessage       = "The [quick brown fox](https://www.quickfox.com) jumps over the [lazy dog](http://lazy.dog.com).",
                    ContainsHyperlink = true,
                    ShortPlainText    = "The quick brown fox" + ellipsis,
                    FullPlainText     = "The quick brown fox jumps over the lazy dog.",
                },
                new
                {
                    MaxTextLength     = 20,
                    RawMessage        = "The [quick brown fox](https://www.quickfox.com) jumps over the [lazy dog](http://lazy.dog.com).",
                    ShortMessage      = "The [quick brown fox](https://www.quickfox.com) " + ellipsis,
                    FullMessage       = "The [quick brown fox](https://www.quickfox.com) jumps over the [lazy dog](http://lazy.dog.com).",
                    ContainsHyperlink = true,
                    ShortPlainText    = "The quick brown fox " + ellipsis,
                    FullPlainText     = "The quick brown fox jumps over the lazy dog.",
                },
                new
                {
                    MaxTextLength     = 21,
                    RawMessage        = "The [quick brown fox](https://www.quickfox.com) jumps over the [lazy dog](http://lazy.dog.com).",
                    ShortMessage      = "The [quick brown fox](https://www.quickfox.com) j" + ellipsis,
                    FullMessage       = "The [quick brown fox](https://www.quickfox.com) jumps over the [lazy dog](http://lazy.dog.com).",
                    ContainsHyperlink = true,
                    ShortPlainText    = "The quick brown fox j" + ellipsis,
                    FullPlainText     = "The quick brown fox jumps over the lazy dog.",
                },
                new
                {
                    MaxTextLength     = 42,
                    RawMessage        = "The [quick brown fox](https://www.quickfox.com) jumps over the [lazy dog](http://lazy.dog.com).",
                    ShortMessage      = "The [quick brown fox](https://www.quickfox.com) jumps over the lazy do" + ellipsis,
                    FullMessage       = "The [quick brown fox](https://www.quickfox.com) jumps over the [lazy dog](http://lazy.dog.com).",
                    ContainsHyperlink = true,
                    ShortPlainText    = "The quick brown fox jumps over the lazy do" + ellipsis,
                    FullPlainText     = "The quick brown fox jumps over the lazy dog.",
                },
                new
                {
                    MaxTextLength     = 43,
                    RawMessage        = "The [quick brown fox](https://www.quickfox.com) jumps over the [lazy dog](http://lazy.dog.com).",
                    ShortMessage      = "The [quick brown fox](https://www.quickfox.com) jumps over the [lazy dog](http://lazy.dog.com)" + ellipsis,
                    FullMessage       = "The [quick brown fox](https://www.quickfox.com) jumps over the [lazy dog](http://lazy.dog.com).",
                    ContainsHyperlink = true,
                    ShortPlainText    = "The quick brown fox jumps over the lazy dog" + ellipsis,
                    FullPlainText     = "The quick brown fox jumps over the lazy dog.",
                },
                new
                {
                    MaxTextLength     = 44,
                    RawMessage        = "The [quick brown fox](https://www.quickfox.com) jumps over the [lazy dog](http://lazy.dog.com).",
                    ShortMessage      = "The [quick brown fox](https://www.quickfox.com) jumps over the [lazy dog](http://lazy.dog.com).",
                    FullMessage       = "The [quick brown fox](https://www.quickfox.com) jumps over the [lazy dog](http://lazy.dog.com).",
                    ContainsHyperlink = true,
                    ShortPlainText    = "The quick brown fox jumps over the lazy dog.",
                    FullPlainText     = "The quick brown fox jumps over the lazy dog.",
                },
                new
                {
                    MaxTextLength     = 160,
                    RawMessage        = "The [quick brown fox](https://www.quickfox.com) jumps over the [lazy dog](http://lazy.dog.com).",
                    ShortMessage      = "The [quick brown fox](https://www.quickfox.com) jumps over the [lazy dog](http://lazy.dog.com).",
                    FullMessage       = "The [quick brown fox](https://www.quickfox.com) jumps over the [lazy dog](http://lazy.dog.com).",
                    ContainsHyperlink = true,
                    ShortPlainText    = "The quick brown fox jumps over the lazy dog.",
                    FullPlainText     = "The quick brown fox jumps over the lazy dog.",
                }
            };

            int originalMax = SarifErrorListItem.MaxConcisedTextLength;

            foreach (var test in testCases)
            {
                SarifErrorListItem.MaxConcisedTextLength = test.MaxTextLength;
                var result = new Result
                {
                    Message = new Message()
                    {
                        Text = test.RawMessage,
                    },
                };
                SarifErrorListItem    error = TestUtilities.MakeErrorListItem(result);
                SarifResultTableEntry entry = new SarifResultTableEntry(error);

                VerifyErrorListItemEntry(error, entry, test);
            }
            SarifErrorListItem.MaxConcisedTextLength = originalMax;
        }
        public void SarifErrorListItem_WithAdditionalProperties_ShouldDeferLoading()
        {
            string moduleName            = "Microsoft.CodeAnalysis.Sarif.PatternMatcher.AnalyzeCommand";
            string relatedLocationString = "location related to the issue";
            var    result = new Result
            {
                Locations = new List <Location>
                {
                    new Location
                    {
                        PhysicalLocation = new PhysicalLocation
                        {
                            ArtifactLocation = new ArtifactLocation {
                                Uri = new Uri("path/to/file", UriKind.Relative)
                            },
                        },
                    },
                },
                RelatedLocations = new List <Location>
                {
                    new Location
                    {
                        Message = new Message {
                            Text = relatedLocationString
                        },
                        PhysicalLocation = new PhysicalLocation
                        {
                            ArtifactLocation = new ArtifactLocation {
                                Description = new Message {
                                    Text = relatedLocationString
                                }
                            },
                        },
                    },
                    new Location
                    {
                        Message = new Message {
                            Text = relatedLocationString
                        },
                        PhysicalLocation = new PhysicalLocation
                        {
                            ArtifactLocation = new ArtifactLocation {
                                Description = new Message {
                                    Text = relatedLocationString
                                }
                            },
                        },
                    },
                    new Location
                    {
                        Message = new Message {
                            Text = relatedLocationString
                        },
                        PhysicalLocation = new PhysicalLocation
                        {
                            ArtifactLocation = new ArtifactLocation {
                                Description = new Message {
                                    Text = relatedLocationString
                                }
                            },
                        },
                    },
                },
                Stacks = new List <Stack>
                {
                    new Stack
                    {
                        Frames = new List <StackFrame>
                        {
                            new StackFrame {
                                Module = moduleName
                            },
                        },
                    },
                },
                CodeFlows = new List <CodeFlow>
                {
                    new CodeFlow
                    {
                        Message = new Message {
                            Text = "'*Temp_value_#8086' is not initialized"
                        },
                    },
                    new CodeFlow
                    {
                        Message = new Message {
                            Text = "'*Temp_value_#8086' is used, but may not have been initialized"
                        },
                    },
                },
            };

            SarifErrorListItem item = TestUtilities.MakeErrorListItem(result);

            item.Locations.Should().BeEmpty();
            item.RelatedLocations.Should().BeEmpty();
            item.Stacks.Should().BeEmpty();
            item.AnalysisSteps.Should().BeEmpty();

            item.PopulateAdditionalPropertiesIfNot();

            item.Locations.Count.Should().Be(1);
            item.Locations.First().FilePath.Should().BeEquivalentTo("path/to/file");
            item.RelatedLocations.Count.Should().Be(3);
            item.RelatedLocations.First().Message.Should().BeEquivalentTo(relatedLocationString);
            item.Stacks.Count.Should().Be(1);
            item.Stacks.First().First().Module.Should().BeEquivalentTo(moduleName);
            item.AnalysisSteps.Count.Should().Be(2);
            item.AnalysisSteps.Verbosity.Should().Be(100);
        }