public void CodeAnalysisResultManager_CacheUriBasePaths_EnsuresTrailingSlash()
        {
            var run = new Run
            {
                OriginalUriBaseIds = new Dictionary <string, ArtifactLocation>
                {
                    ["HAS_SLASH"] = new ArtifactLocation
                    {
                        Uri = new Uri("file:///C:/code/myProject/src/"),
                    },
                    ["NO_SLASH"] = new ArtifactLocation
                    {
                        Uri = new Uri("file:///C:/code/myProject/test"),
                    },
                    ["NO_SLASH_RELATIVE"] = new ArtifactLocation
                    {
                        Uri = new Uri("code/myProject/test", UriKind.Relative),
                    },
                },
            };

            var resultManager = new CodeAnalysisResultManager(fileSystem: null, promptForResolvedPathDelegate: null);

            int runIndex  = resultManager.GetNextRunIndex();
            var dataCache = new RunDataCache(runIndex);

            resultManager.RunIndexToRunDataCache.Add(runIndex, dataCache);
            resultManager.CacheUriBasePaths(run);

            resultManager.CurrentRunDataCache.OriginalUriBasePaths["HAS_SLASH"].Should().Be("file:///C:/code/myProject/src/");
            resultManager.CurrentRunDataCache.OriginalUriBasePaths["NO_SLASH"].Should().Be("file:///C:/code/myProject/test/");
            resultManager.CurrentRunDataCache.OriginalUriBasePaths["NO_SLASH_RELATIVE"].Should().Be("code/myProject/test/");
        }
        public void CodeAnalysisResultManager_GetRebaselinedFileName_AcceptsMatchingFileNameFromUser()
        {
            // Arrange.
            const string PathInLogFile        = @"C:\Code\sarif-sdk\src\Sarif\Notes.cs";
            const string ExpectedResolvedPath = @"D:\Users\John\source\sarif-sdk\src\Sarif\Notes.cs";

            const int RunId = 1;

            this.pathFromPrompt = ExpectedResolvedPath;

            var target = new CodeAnalysisResultManager(
                null,                               // This test never touches the file system.
                this.FakePromptForResolvedPath);
            var dataCache = new RunDataCache();

            target.RunIndexToRunDataCache.Add(RunId, dataCache);

            // Act.
            string actualResolvedPath = target.GetRebaselinedFileName(uriBaseId: null, pathFromLogFile: PathInLogFile, dataCache: dataCache);

            actualResolvedPath = this.FakePromptForResolvedPath(null, actualResolvedPath);
            target.SaveResolvedPathToUriBaseMapping(null, PathInLogFile, PathInLogFile, actualResolvedPath, dataCache);
            // Assert.
            actualResolvedPath.Should().Be(ExpectedResolvedPath);

            Tuple <string, string>[] remappedPathPrefixes = target.GetRemappedPathPrefixes();
            remappedPathPrefixes.Length.Should().Be(1);
            remappedPathPrefixes[0].Item1.Should().Be(@"C:\Code");
            remappedPathPrefixes[0].Item2.Should().Be(@"D:\Users\John\source");
        }
예제 #3
0
        public void CodeAnalysisResultManager_CacheUriBasePaths_EnsuresTrailingSlash()
        {
            var run = new Run
            {
                OriginalUriBaseIds = new Dictionary <string, ArtifactLocation>
                {
                    ["HAS_SLASH"] = new ArtifactLocation
                    {
                        Uri = new Uri("file:///C:/code/myProject/src/")
                    },
                    ["NO_SLASH"] = new ArtifactLocation
                    {
                        Uri = new Uri("file:///C:/code/myProject/test")
                    }
                }
            };

            var resultManager = new CodeAnalysisResultManager(fileSystem: null, promptForResolvedPathDelegate: null);

            RunDataCache dataCache = new RunDataCache(run);

            resultManager.RunDataCaches.Add(++resultManager.CurrentRunId, dataCache);
            resultManager.CacheUriBasePaths(run);

            resultManager.CurrentRunDataCache.OriginalUriBasePaths["HAS_SLASH"].Should().Be("file:///C:/code/myProject/src/");
            resultManager.CurrentRunDataCache.OriginalUriBasePaths["NO_SLASH"].Should().Be("file:///C:/code/myProject/test/");
        }
        public void CodeAnalysisResultManager_GetRebaselinedFileName_ConstructPathFromSolutionPathRemapping()
        {
            const int    RunId = 1;
            const string ResultArtifactPath1   = @"Sarif/Notes.cs";
            const string ResultArtifactPath2   = @"Sarif/OffsetInfo.cs";
            const string SolutionPath          = @"D:\Users\John\source\sarif-sdk\src";
            string       ExpectedResolvedPath1 = Path.Combine(SolutionPath, "Sarif", "Notes.cs");
            string       ExpectedResolvedPath2 = Path.Combine(SolutionPath, "Sarif", "OffsetInfo.cs");

            this.existingFiles.Add(ExpectedResolvedPath1);
            this.existingFiles.Add(ExpectedResolvedPath2);

            var target = new CodeAnalysisResultManager(
                fileSystem: this.mockFileSystem.Object,
                this.FakePromptForResolvedPath);
            var dataCache = new RunDataCache();

            target.RunIndexToRunDataCache.Add(RunId, dataCache);

            // Mimic first time user navigate to a result, resolve file path using solution path.
            // The resolved path should be cached for next resolving
            target.SaveResolvedPathToUriBaseMapping(null, ResultArtifactPath1, ResultArtifactPath1, ExpectedResolvedPath1, dataCache);
            Tuple <string, string>[] remappedPathPrefixes = target.GetRemappedPathPrefixes();
            remappedPathPrefixes.Length.Should().Be(1);
            remappedPathPrefixes[0].Item1.Should().Be("");
            remappedPathPrefixes[0].Item2.Should().Be(SolutionPath);

            string actualResolvedPath = target.GetRebaselinedFileName(
                uriBaseId: null,
                pathFromLogFile: ResultArtifactPath2,
                dataCache: dataCache);

            actualResolvedPath.Should().Be(ExpectedResolvedPath2);
        }
        public void CodeAnalysisResultManager_GetRebaselinedFileName_IgnoresMismatchedFileNameFromUser()
        {
            // Arrange.
            const string PathInLogFile        = @"C:\Code\sarif-sdk\src\Sarif\Notes.cs";
            const string ExpectedResolvedPath = @"D:\Users\John\source\sarif-sdk\src\Sarif\HashData.cs";

            const int RunId = 1;

            this.pathFromPrompt = ExpectedResolvedPath;

            var target = new CodeAnalysisResultManager(
                null,                               // This test never touches the file system.
                this.FakePromptForResolvedPath);
            var dataCache = new RunDataCache();

            target.RunIndexToRunDataCache.Add(RunId, dataCache);

            // Act.
            string actualResolvedPath = target.GetRebaselinedFileName(uriBaseId: null, pathFromLogFile: PathInLogFile, dataCache: dataCache);

            // Assert.
            actualResolvedPath.Should().BeNull();

            Tuple <string, string>[] remappedPathPrefixes = target.GetRemappedPathPrefixes();
            remappedPathPrefixes.Should().BeEmpty();
        }
        public void CodeAnalysisResultManager_GetRebaselinedFileName_WhenRebaselinedPathDiffersOnlyInDriveLetter_ReturnsRebaselinedPath()
        {
            // Arrange.
            const string PathInLogFile        = @"C:\Code\sarif-sdk\src\Sarif\Notes.cs";
            const string ExpectedResolvedPath = @"D:\Code\sarif-sdk\src\Sarif\Notes.cs";

            const int RunId = 1;

            this.pathFromPrompt = ExpectedResolvedPath;

            var target = new CodeAnalysisResultManager(
                null,                               // This test never touches the file system.
                this.FakePromptForResolvedPath);
            var dataCache = new RunDataCache();

            target.RunIndexToRunDataCache.Add(RunId, dataCache);

            // Act.
            string actualResolvedPath = target.GetRebaselinedFileName(sarifErrorListItem: null, uriBaseId: null, pathFromLogFile: PathInLogFile, dataCache: dataCache);

            // Assert.
            actualResolvedPath.Should().Be(ExpectedResolvedPath);

            Tuple <string, string>[] remappedPathPrefixes = target.GetRemappedPathPrefixes();
            remappedPathPrefixes.Length.Should().Be(1);
            remappedPathPrefixes[0].Item1.Should().Be("C:");
            remappedPathPrefixes[0].Item2.Should().Be("D:");
        }
예제 #7
0
        public void CodeAnalysisResultManager_GetRebaselinedFileName_WhenRebaselinedPathHasMoreComponents_ReturnsRebaselinedPath()
        {
            // Arrange.
            const string FileNameInLogFile   = @"C:\Code\sarif-sdk\src\Sarif\Notes.cs";
            const string RebaselinedFileName = @"C:\Users\Mary\Code\sarif-sdk\src\Sarif\Notes.cs";

            const int RunId = 1;

            this.rebaselinedFileName = RebaselinedFileName;

            var target = new CodeAnalysisResultManager(
                null,                               // This test never touches the file system.
                this.FakePromptForResolvedPath);
            RunDataCache dataCache = new RunDataCache();

            target.RunDataCaches.Add(RunId, dataCache);

            // Act.
            string actualRebaselinedFileName = target.GetRebaselinedFileName(uriBaseId: null, pathFromLogFile: FileNameInLogFile, dataCache: dataCache);

            // Assert.
            actualRebaselinedFileName.Should().Be(RebaselinedFileName);

            Tuple <string, string>[] remappedPathPrefixes = target.GetRemappedPathPrefixes();
            remappedPathPrefixes.Length.Should().Be(1);
            remappedPathPrefixes[0].Item1.Should().Be(@"C:");
            remappedPathPrefixes[0].Item2.Should().Be(@"C:\Users\Mary");
        }
예제 #8
0
        public void GetFileLocationPath_UriPathCanBeResolved()
        {
            string repoPath = "file:///C:/code/myProject/src/";
            var    run      = new Microsoft.CodeAnalysis.Sarif.Run
            {
                OriginalUriBaseIds = new Dictionary <string, ArtifactLocation>
                {
                    ["REPO_ROOT"] = new ArtifactLocation
                    {
                        Uri = new Uri(repoPath),
                    }
                },
            };
            var dataCache = new RunDataCache();
            int runId     = CodeAnalysisResultManager.Instance.GetNextRunIndex();

            CodeAnalysisResultManager.Instance.RunIndexToRunDataCache.Add(runId, dataCache);
            CodeAnalysisResultManager.Instance.CacheUriBasePaths(run);

            string filePath = @"AnalysisStep.cs";
            var    artifact = new ArtifactLocation {
                Uri = new Uri(filePath, UriKind.Relative), UriBaseId = "REPO_ROOT"
            };
            string path = SdkUIUtilities.GetFileLocationPath(artifact, runId);

            path.Should().Be(@"C:\code\myProject\src\AnalysisStep.cs");
        }
        public void CodeAnalysisResultManager_VerifyFileWithArtifactHash_HasNoEmbeddedFile()
        {
            // Arrange.
            const string PathInLogFile    = @"C:\Code\sarif-sdk\src\Sarif\Notes.cs";
            const string ResolvedPath     = @"D:\Users\John\source\sarif-sdk\src\Sarif\Notes.cs";
            const string EmbeddedFilePath = null;
            const int    RunId            = 1;

            var target = new CodeAnalysisResultManager(
                null,                               // This test never touches the file system.
                this.FakePromptForResolvedPath,
                this.FakePromptForEmbeddedFile);
            var dataCache = new RunDataCache();

            target.RunIndexToRunDataCache.Add(RunId, dataCache);
            this.embeddedFileDialogResult = ResolveEmbeddedFileDialogResult.None;

            var sarifErrorListItem = new SarifErrorListItem {
                LogFilePath = @"C:\Code\sarif-sdk\src\.sarif\Result.sarif"
            };

            // Act.
            bool result = target.VerifyFileWithArtifactHash(sarifErrorListItem, PathInLogFile, dataCache, ResolvedPath, EmbeddedFilePath, out string actualResolvedPath);

            // Assert.
            result.Should().BeTrue();
            actualResolvedPath.Should().Be(ResolvedPath);
            // no dialog pop up
            this.numEmbeddedFilePrompts.Should().Be(0);
        }
        public void CodeAnalysisResultManager_GetRebaselinedFileName_WhenUserDoesNotSelectRebaselinedPath_UsesPathFromLogFile()
        {
            // Arrange.
            const string PathInLogFile = @"C:\Code\sarif-sdk\src\Sarif\Notes.cs";

            const int RunId = 1;

            // The user does not select a file in the File Open dialog:
            this.pathFromPrompt = null;

            var target = new CodeAnalysisResultManager(
                null,                               // This test never touches the file system.
                this.FakePromptForResolvedPath);
            var dataCache = new RunDataCache();

            target.RunIndexToRunDataCache.Add(RunId, dataCache);

            // Act.
            string actualResolvedPath = target.GetRebaselinedFileName(uriBaseId: null, pathFromLogFile: PathInLogFile, dataCache: dataCache);

            // Assert.
            actualResolvedPath.Should().BeNull();

            Tuple <string, string>[] remappedPathPrefixes = target.GetRemappedPathPrefixes();
            remappedPathPrefixes.Should().BeEmpty();
        }
예제 #11
0
        private int WriteRunToErrorList(Run run, string logFilePath, Solution solution)
        {
            RunDataCache dataCache = new RunDataCache(run);

            CodeAnalysisResultManager.Instance.RunDataCaches.Add(++CodeAnalysisResultManager.Instance.CurrentRunId, dataCache);
            CodeAnalysisResultManager.Instance.CacheUriBasePaths(run);
            List <SarifErrorListItem> sarifErrors = new List <SarifErrorListItem>();

            var projectNameCache = new ProjectNameCache(solution);

            StoreFileDetails(run.Artifacts);

            if (run.Results != null)
            {
                foreach (Result result in run.Results)
                {
                    result.Run = run;
                    var sarifError = new SarifErrorListItem(run, result, logFilePath, projectNameCache);
                    sarifErrors.Add(sarifError);
                }
            }

            if (run.Invocations != null)
            {
                foreach (var invocation in run.Invocations)
                {
                    if (invocation.ToolConfigurationNotifications != null)
                    {
                        foreach (Notification configurationNotification in invocation.ToolConfigurationNotifications)
                        {
                            var sarifError = new SarifErrorListItem(run, configurationNotification, logFilePath, projectNameCache);
                            sarifErrors.Add(sarifError);
                        }
                    }

                    if (invocation.ToolExecutionNotifications != null)
                    {
                        foreach (Notification toolNotification in invocation.ToolExecutionNotifications)
                        {
                            if (toolNotification.Level != FailureLevel.Note)
                            {
                                var sarifError = new SarifErrorListItem(run, toolNotification, logFilePath, projectNameCache);
                                sarifErrors.Add(sarifError);
                            }
                        }
                    }
                }
            }

            (dataCache.SarifErrors as List <SarifErrorListItem>).AddRange(sarifErrors);
            SarifTableDataSource.Instance.AddErrors(sarifErrors);
            return(sarifErrors.Count);
        }
예제 #12
0
        public void GetFileLocationPath_UriIsLocalPath()
        {
            var dataCache = new RunDataCache();
            int runId     = CodeAnalysisResultManager.Instance.GetNextRunIndex();

            CodeAnalysisResultManager.Instance.RunIndexToRunDataCache.Add(runId, dataCache);

            string filePath = @"C:\repo\src\AnalysisStep.cs";
            var    artifact = new ArtifactLocation {
                Uri = new Uri(filePath, UriKind.Absolute)
            };
            string path = SdkUIUtilities.GetFileLocationPath(artifact, runId);

            path.Should().Be(filePath);
        }
예제 #13
0
        public void GetFileLocationPath_UriIsNull()
        {
            var dataCache = new RunDataCache();
            int runId     = CodeAnalysisResultManager.Instance.GetNextRunIndex();

            CodeAnalysisResultManager.Instance.RunIndexToRunDataCache.Add(runId, dataCache);

            var    artifact = new ArtifactLocation();
            string path     = SdkUIUtilities.GetFileLocationPath(artifact, runId);

            path.Should().BeNull();

            artifact = null;
            path     = SdkUIUtilities.GetFileLocationPath(artifact, runId);
            path.Should().BeNull();
        }
        public void CodeAnalysisResultManager_GetRebaselinedFileName_UsesExistingMapping()
        {
            // Arrange.
            const string FirstFileNameInLogFile   = @"C:\Code\sarif-sdk\src\Sarif\Notes.cs";
            const string FirstRebaselinedFileName = @"D:\Users\John\source\sarif-sdk\src\Sarif\Notes.cs";

            const string SecondFileNameInLogFile   = @"C:\Code\sarif-sdk\src\Sarif.UnitTests\JsonTests.cs";
            const string SecondRebaselinedFileName = @"D:\Users\John\source\sarif-sdk\src\Sarif.UnitTests\JsonTests.cs";

            const int RunId = 1;

            this.existingFiles.Add(SecondRebaselinedFileName);

            this.pathFromPrompt = FirstRebaselinedFileName;

            var target = new CodeAnalysisResultManager(
                this.fileSystem,
                this.FakePromptForResolvedPath);
            var dataCache = new RunDataCache();

            target.RunIndexToRunDataCache.Add(RunId, dataCache);

            // First, rebase a file to prime the list of mappings.
            target.GetRebaselinedFileName(uriBaseId: null, pathFromLogFile: FirstFileNameInLogFile, dataCache: dataCache);
            string actualResolvedPath = this.FakePromptForResolvedPath(null, FirstFileNameInLogFile);

            target.SaveResolvedPathToUriBaseMapping(null, FirstFileNameInLogFile, FirstFileNameInLogFile, actualResolvedPath, dataCache);
            // The first time, we prompt the user for the name of the file to rebaseline to.
            this.numPrompts.Should().Be(1);

            // Act: Rebaseline a second file with the same prefix.
            actualResolvedPath = target.GetRebaselinedFileName(uriBaseId: null, pathFromLogFile: SecondFileNameInLogFile, dataCache: dataCache);

            // Assert.
            actualResolvedPath.Should().Be(SecondRebaselinedFileName);

            Tuple <string, string>[] remappedPathPrefixes = target.GetRemappedPathPrefixes();
            remappedPathPrefixes.Length.Should().Be(1);
            remappedPathPrefixes[0].Item1.Should().Be(@"C:\Code");
            remappedPathPrefixes[0].Item2.Should().Be(@"D:\Users\John\source");

            // The second time, since the existing mapping suffices for the second file,
            // it's not necessary to prompt again.
            this.numPrompts.Should().Be(1);
        }
        public void CodeAnalysisResultManager_VerifyFileWithArtifactHash_LocalFileDoesNotExists()
        {
            // Arrange.
            const string PathInLogFile       = @"C:\Code\sarif-sdk\src\Sarif\Notes.cpp";
            const string ResolvedPath        = null;
            const string EmbeddedFilePath    = @"D:\Users\John\AppData\Local\Temp\SarifViewer\e1bb39f712fbb56ee0ae3782c68d1278a6ab494b7e2daf214400af283b75307c\Notes.cpp";
            const string EmbeddedFileContent = "UUID uuid;\nUuidCreate(&uuid);";
            const int    RunId = 1;

            var target = new CodeAnalysisResultManager(
                null,                               // This test never touches the file system.
                this.FakePromptForResolvedPath,
                this.FakePromptForEmbeddedFile);
            var dataCache = new RunDataCache();

            target.RunIndexToRunDataCache.Add(RunId, dataCache);
            var artifact = new Artifact
            {
                Hashes = new Dictionary <string, string> {
                    ["sha-256"] = "e1bb39f712fbb56ee0ae3782c68d1278a6ab494b7e2daf214400af283b75307c"
                },
                Contents = new ArtifactContent {
                    Text = EmbeddedFileContent
                },
            };

            dataCache.FileDetails.Add(PathInLogFile, new Models.ArtifactDetailsModel(artifact));
            this.embeddedFileDialogResult = ResolveEmbeddedFileDialogResult.None;

            var sarifErrorListItem = new SarifErrorListItem {
                LogFilePath = @"C:\Code\sarif-sdk\src\.sarif\Result.sarif"
            };

            // Act.
            bool result = target.VerifyFileWithArtifactHash(sarifErrorListItem, PathInLogFile, dataCache, ResolvedPath, EmbeddedFilePath, out string actualResolvedPath);

            // Assert.
            result.Should().BeTrue();
            actualResolvedPath.Should().Be(EmbeddedFilePath);
            // no dialog pop up
            this.numEmbeddedFilePrompts.Should().Be(0);
        }
예제 #16
0
        private int WriteRunToErrorList(Run run, string logFilePath, SarifLog sarifLog)
        {
            if (!SarifViewerPackage.IsUnitTesting)
            {
#pragma warning disable VSTHRD108 // Assert thread affinity unconditionally
                ThreadHelper.ThrowIfNotOnUIThread();
#pragma warning restore VSTHRD108
            }

            int runIndex  = CodeAnalysisResultManager.Instance.GetNextRunIndex();
            var dataCache = new RunDataCache(runIndex, logFilePath, sarifLog);
            CodeAnalysisResultManager.Instance.RunIndexToRunDataCache.Add(runIndex, dataCache);
            CodeAnalysisResultManager.Instance.CacheUriBasePaths(run);
            var sarifErrors = new List <SarifErrorListItem>();

            var dte = Package.GetGlobalService(typeof(DTE)) as DTE2;

            var projectNameCache = new ProjectNameCache(dte?.Solution);

            this.StoreFileDetails(run.Artifacts);

            if (run.Results != null)
            {
                foreach (Result result in run.Results)
                {
                    result.Run = run;
                    var sarifError = new SarifErrorListItem(run, runIndex, result, logFilePath, projectNameCache);
                    sarifErrors.Add(sarifError);
                }
            }

            if (run.Invocations != null)
            {
                foreach (Invocation invocation in run.Invocations)
                {
                    if (invocation.ToolConfigurationNotifications != null)
                    {
                        foreach (Notification configurationNotification in invocation.ToolConfigurationNotifications)
                        {
                            var sarifError = new SarifErrorListItem(run, runIndex, configurationNotification, logFilePath, projectNameCache);
                            sarifErrors.Add(sarifError);
                        }
                    }

                    if (invocation.ToolExecutionNotifications != null)
                    {
                        foreach (Notification toolNotification in invocation.ToolExecutionNotifications)
                        {
                            if (toolNotification.Level != FailureLevel.Note)
                            {
                                var sarifError = new SarifErrorListItem(run, runIndex, toolNotification, logFilePath, projectNameCache);
                                sarifErrors.Add(sarifError);
                            }
                        }
                    }
                }
            }

            if (run.HasAbsentResults())
            {
                this.ShowFilteredCategoryColumn();
            }

            if (run.HasSuppressedResults())
            {
                this.ShowFilteredSuppressionStateColumn();
            }

            (dataCache.SarifErrors as List <SarifErrorListItem>).AddRange(sarifErrors);
            SarifTableDataSource.Instance.AddErrors(sarifErrors);

            // This causes already open "text views" to be tagged when SARIF logs are processed after a view is opened.
            SarifLocationTagHelpers.RefreshTags();

            return(sarifErrors.Count);
        }
        public void CodeAnalysisResultManager_VerifyFileWithArtifactHash_HashDoesNotMatches()
        {
            // Arrange.
            const string PathInLogFile       = @"C:\Code\sarif-sdk\src\Sarif\Notes.cpp";
            const string ResolvedPath        = @"D:\Users\John\source\sarif-sdk\src\Sarif\Notes.cs";
            const string EmbeddedFilePath    = @"D:\Users\John\AppData\Local\Temp\SarifViewer\e1bb39f712fbb56ee0ae3782c68d1278a6ab494b7e2daf214400af283b75307c\Notes.cpp";
            const string EmbeddedFileContent = "UUID uuid;\nUuidCreate(&uuid);";
            const int    RunId = 1;

            this.existingFiles.Add(ResolvedPath);
            this.mockFileSystem
            .Setup(fs => fs.FileOpenRead(ResolvedPath))
            .Returns(new MemoryStream(Encoding.UTF8.GetBytes(EmbeddedFileContent + "\n")));

            var target = new CodeAnalysisResultManager(
                this.mockFileSystem.Object,
                this.FakePromptForResolvedPath,
                this.FakePromptForEmbeddedFile);
            var dataCache = new RunDataCache();

            target.RunIndexToRunDataCache.Add(RunId, dataCache);
            var artifact = new Artifact
            {
                Hashes = new Dictionary <string, string> {
                    ["sha-256"] = "e1bb39f712fbb56ee0ae3782c68d1278a6ab494b7e2daf214400af283b75307c"
                },
                Contents = new ArtifactContent {
                    Text = EmbeddedFileContent
                },
            };

            dataCache.FileDetails.Add(PathInLogFile, new Models.ArtifactDetailsModel(artifact));

            // simulate user cancelled dialog without selecting any option
            this.embeddedFileDialogResult = ResolveEmbeddedFileDialogResult.None;

            var sarifErrorListItem = new SarifErrorListItem {
                LogFilePath = @"C:\Code\sarif-sdk\src\.sarif\Result.sarif"
            };

            // Act.
            bool result = target.VerifyFileWithArtifactHash(sarifErrorListItem, PathInLogFile, dataCache, ResolvedPath, EmbeddedFilePath, out string actualResolvedPath);

            // Assert.
            result.Should().BeFalse();
            actualResolvedPath.Should().BeNull();
            // dialog pop up
            this.numEmbeddedFilePrompts.Should().Be(1);

            // simulate user selected open embedded file
            this.embeddedFileDialogResult = ResolveEmbeddedFileDialogResult.OpenEmbeddedFileContent;
            this.mockFileSystem
            .Setup(fs => fs.FileOpenRead(ResolvedPath))
            .Returns(new MemoryStream(Encoding.UTF8.GetBytes(EmbeddedFileContent + "\n")));
            // Act.
            result = target.VerifyFileWithArtifactHash(sarifErrorListItem, PathInLogFile, dataCache, ResolvedPath, EmbeddedFilePath, out actualResolvedPath);

            // Assert.
            result.Should().BeTrue();
            actualResolvedPath.Should().Be(EmbeddedFilePath);
            // dialog pop up
            this.numEmbeddedFilePrompts.Should().Be(2);

            // simulate user selected open local file
            this.embeddedFileDialogResult = ResolveEmbeddedFileDialogResult.OpenLocalFileFromSolution;
            this.mockFileSystem
            .Setup(fs => fs.FileOpenRead(ResolvedPath))
            .Returns(new MemoryStream(Encoding.UTF8.GetBytes(EmbeddedFileContent + "\n")));
            // Act.
            result = target.VerifyFileWithArtifactHash(sarifErrorListItem, PathInLogFile, dataCache, ResolvedPath, EmbeddedFilePath, out actualResolvedPath);

            // Assert.
            result.Should().BeTrue();
            actualResolvedPath.Should().Be(ResolvedPath);
            // dialog pop up
            this.numEmbeddedFilePrompts.Should().Be(3);

            // simulate user selected to browser alternate file
            this.embeddedFileDialogResult = ResolveEmbeddedFileDialogResult.BrowseAlternateLocation;
            this.mockFileSystem
            .Setup(fs => fs.FileOpenRead(ResolvedPath))
            .Returns(new MemoryStream(Encoding.UTF8.GetBytes(EmbeddedFileContent + "\n")));
            this.pathFromPrompt = ResolvedPath;
            // Act.
            result = target.VerifyFileWithArtifactHash(sarifErrorListItem, PathInLogFile, dataCache, ResolvedPath, EmbeddedFilePath, out actualResolvedPath);

            // Assert.
            result.Should().BeTrue();
            actualResolvedPath.Should().Be(ResolvedPath);
            // dialog pop up
            this.numEmbeddedFilePrompts.Should().Be(4);
            this.numPrompts.Should().Be(1);
        }
        public void CodeAnalysisResultManager_VerifyFileWithArtifactHash_HashMatches()
        {
            // Arrange.
            const string PathInLogFile       = @"C:\Code\sarif-sdk\src\Sarif\Notes.cpp";
            const string ResolvedPath        = @"D:\Users\John\source\sarif-sdk\src\Sarif\Notes.cs";
            const string EmbeddedFilePath    = @"D:\Users\John\AppData\Local\Temp\SarifViewer\e1bb39f712fbb56ee0ae3782c68d1278a6ab494b7e2daf214400af283b75307c\Notes.cpp";
            const string EmbeddedFileContent = "UUID uuid;\nUuidCreate(&uuid);";
            const int    RunId = 1;

            this.existingFiles.Add(ResolvedPath);
            this.mockFileSystem
            .Setup(fs => fs.FileOpenRead(ResolvedPath))
            .Returns(new MemoryStream(Encoding.UTF8.GetBytes(EmbeddedFileContent)));

            var target = new CodeAnalysisResultManager(
                this.mockFileSystem.Object,
                this.FakePromptForResolvedPath,
                this.FakePromptForEmbeddedFile);
            var dataCache = new RunDataCache();

            target.RunIndexToRunDataCache.Add(RunId, dataCache);
            var artifact = new Artifact
            {
                Hashes = new Dictionary <string, string> {
                    ["sha-256"] = "e1bb39f712fbb56ee0ae3782c68d1278a6ab494b7e2daf214400af283b75307c"
                },
                Contents = new ArtifactContent {
                    Text = EmbeddedFileContent
                },
            };

            dataCache.FileDetails.Add(PathInLogFile, new Models.ArtifactDetailsModel(artifact));
            this.embeddedFileDialogResult = ResolveEmbeddedFileDialogResult.None;

            var sarifErrorListItem = new SarifErrorListItem {
                LogFilePath = @"C:\Code\sarif-sdk\src\.sarif\Result.sarif"
            };

            // Act.
            bool result = target.VerifyFileWithArtifactHash(sarifErrorListItem, PathInLogFile, dataCache, ResolvedPath, EmbeddedFilePath, out string actualResolvedPath);

            // Assert.
            result.Should().BeTrue();
            actualResolvedPath.Should().Be(ResolvedPath);
            // no dialog pop up
            this.numEmbeddedFilePrompts.Should().Be(0);

            // change hash to upper case and verify again
            this.mockFileSystem
            .Setup(fs => fs.FileOpenRead(ResolvedPath))
            .Returns(new MemoryStream(Encoding.UTF8.GetBytes(EmbeddedFileContent)));
            artifact = new Artifact
            {
                Hashes = new Dictionary <string, string> {
                    ["sha-256"] = "e1bb39f712fbb56ee0ae3782c68d1278a6ab494b7e2daf214400af283b75307c".ToUpper()
                },
                Contents = new ArtifactContent {
                    Text = EmbeddedFileContent
                },
            };
            dataCache.FileDetails[PathInLogFile] = new Models.ArtifactDetailsModel(artifact);
            this.embeddedFileDialogResult        = ResolveEmbeddedFileDialogResult.None;

            // Act.
            result = target.VerifyFileWithArtifactHash(sarifErrorListItem, PathInLogFile, dataCache, ResolvedPath, EmbeddedFilePath, out actualResolvedPath);

            // Assert.
            result.Should().BeTrue();
            actualResolvedPath.Should().Be(ResolvedPath);
            // no dialog pop up
            this.numEmbeddedFilePrompts.Should().Be(0);
        }