diff --git a/SonarLint.VisualStudio.Integration.sln b/SonarLint.VisualStudio.Integration.sln
index 1957a5be32..23277701b1 100644
--- a/SonarLint.VisualStudio.Integration.sln
+++ b/SonarLint.VisualStudio.Integration.sln
@@ -5,7 +5,6 @@ VisualStudioVersion = 17.0.31815.197
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Integration.Vsix", "src\Integration.Vsix\Integration.Vsix.csproj", "{FF2AD819-28F4-493A-8E9B-1D3F16BD4689}"
ProjectSection(ProjectDependencies) = postProject
- {0E50D9A0-693D-4B4E-81E2-8B8028231CFA} = {0E50D9A0-693D-4B4E-81E2-8B8028231CFA}
{2BB16C6F-BF06-4225-99A0-F1CFE70CBE44} = {2BB16C6F-BF06-4225-99A0-F1CFE70CBE44}
EndProjectSection
EndProject
@@ -104,10 +103,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roslyn.Suppressions", "src\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roslyn.Suppressions.UnitTests", "src\Roslyn.Suppressions\Roslyn.Suppressions.UnitTests\Roslyn.Suppressions.UnitTests.csproj", "{C478DAE7-58BC-4D02-929E-E413B40F2517}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{628A579F-0D27-4F9F-A756-8CC0A67A7B3D}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CFamilyJarPreProcessor", "build\tools\CFamilyJarPreProcessor\CFamilyJarPreProcessor.csproj", "{0E50D9A0-693D-4B4E-81E2-8B8028231CFA}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ConnectedMode", "ConnectedMode", "{3B4A8B40-9821-4964-8EAB-1D8A0B078292}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConnectedMode", "src\ConnectedMode\ConnectedMode.csproj", "{0BE551DB-3C46-42A5-BB38-DA80E83F8ABD}"
@@ -347,14 +342,6 @@ Global
{C478DAE7-58BC-4D02-929E-E413B40F2517}.Release|Any CPU.Build.0 = Release|Any CPU
{C478DAE7-58BC-4D02-929E-E413B40F2517}.Release|x86.ActiveCfg = Release|Any CPU
{C478DAE7-58BC-4D02-929E-E413B40F2517}.Release|x86.Build.0 = Release|Any CPU
- {0E50D9A0-693D-4B4E-81E2-8B8028231CFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {0E50D9A0-693D-4B4E-81E2-8B8028231CFA}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {0E50D9A0-693D-4B4E-81E2-8B8028231CFA}.Debug|x86.ActiveCfg = Debug|Any CPU
- {0E50D9A0-693D-4B4E-81E2-8B8028231CFA}.Debug|x86.Build.0 = Debug|Any CPU
- {0E50D9A0-693D-4B4E-81E2-8B8028231CFA}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {0E50D9A0-693D-4B4E-81E2-8B8028231CFA}.Release|Any CPU.Build.0 = Release|Any CPU
- {0E50D9A0-693D-4B4E-81E2-8B8028231CFA}.Release|x86.ActiveCfg = Release|Any CPU
- {0E50D9A0-693D-4B4E-81E2-8B8028231CFA}.Release|x86.Build.0 = Release|Any CPU
{0BE551DB-3C46-42A5-BB38-DA80E83F8ABD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0BE551DB-3C46-42A5-BB38-DA80E83F8ABD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0BE551DB-3C46-42A5-BB38-DA80E83F8ABD}.Debug|x86.ActiveCfg = Debug|Any CPU
@@ -489,8 +476,6 @@ Global
{30E1FF8F-94BA-4A39-A737-8FFD7B4A0CD3} = {11D4BFC7-C1F2-45AC-888E-25A6A216AD1D}
{082D5D8E-F914-4139-9AE3-3F48B679E3DA} = {16BF2D77-AE3B-4218-A3E8-875829D73B00}
{C478DAE7-58BC-4D02-929E-E413B40F2517} = {16BF2D77-AE3B-4218-A3E8-875829D73B00}
- {628A579F-0D27-4F9F-A756-8CC0A67A7B3D} = {E93C2CF9-69A6-4669-BE8A-6060B18FEDCA}
- {0E50D9A0-693D-4B4E-81E2-8B8028231CFA} = {628A579F-0D27-4F9F-A756-8CC0A67A7B3D}
{0BE551DB-3C46-42A5-BB38-DA80E83F8ABD} = {3B4A8B40-9821-4964-8EAB-1D8A0B078292}
{2BD38A3A-6F0E-452B-A5B2-200113A32184} = {3B4A8B40-9821-4964-8EAB-1D8A0B078292}
{67BEB251-4EA5-44EE-92A7-B4F57D9A6867} = {25DE7210-DFC0-448B-894E-84C1C9CA223E}
diff --git a/build/tools/CFamilyJarPreProcessor/CFamilyJarPreProcessor.csproj b/build/tools/CFamilyJarPreProcessor/CFamilyJarPreProcessor.csproj
deleted file mode 100644
index 7ad4097cb1..0000000000
--- a/build/tools/CFamilyJarPreProcessor/CFamilyJarPreProcessor.csproj
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
- Exe
- net472
-
-
- true
-
-
-
-
-
-
-
-
-
-
-
diff --git a/build/tools/CFamilyJarPreProcessor/CFamilyJarPreProcessor.sln b/build/tools/CFamilyJarPreProcessor/CFamilyJarPreProcessor.sln
deleted file mode 100644
index 56920f123c..0000000000
--- a/build/tools/CFamilyJarPreProcessor/CFamilyJarPreProcessor.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.2.32516.85
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CFamilyJarPreProcessor", "CFamilyJarPreProcessor.csproj", "{CE1DC67B-EEBE-4EAF-B91C-BC622DCBBA39}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {CE1DC67B-EEBE-4EAF-B91C-BC622DCBBA39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {CE1DC67B-EEBE-4EAF-B91C-BC622DCBBA39}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {CE1DC67B-EEBE-4EAF-B91C-BC622DCBBA39}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {CE1DC67B-EEBE-4EAF-B91C-BC622DCBBA39}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {EA20A11F-9428-41DA-82A9-3403C09EB81F}
- EndGlobalSection
-EndGlobal
diff --git a/build/tools/CFamilyJarPreProcessor/Common.cs b/build/tools/CFamilyJarPreProcessor/Common.cs
deleted file mode 100644
index 4ade790c69..0000000000
--- a/build/tools/CFamilyJarPreProcessor/Common.cs
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * SonarLint for Visual Studio
- * Copyright (C) 2016-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.IO.Compression;
-using System.Linq;
-using System.Net.Http;
-using SharpCompress.Compressors.Xz;
-
-namespace CFamilyJarPreProcessor
-{
- internal static class Common
- {
- ///
- /// Returns the full path to the local directory in which the plugin will be cached at build time
- ///
- /// Per-plugin unique folder name
- /// By default the plugins will be stored under the user's %LocalAppData% folder e.g. C:\Users\JoeBloggs\AppData\Local.
- /// An alternative root directory can be specified by setting the environment variable SONARLINT_INTERNAL_PLUGIN_CACHE_DIR.
- /// This might be necessary if the user name is long so the full paths of the files being unpacked under the root folder
- /// exceed the maximum path length.
- public static string GetLocalBuildTimePluginCacheDir(string pluginFolderName)
- {
- var baseFolder = Environment.GetEnvironmentVariable("SONARLINT_INTERNAL_PLUGIN_CACHE_DIR");
- if (string.IsNullOrEmpty(baseFolder))
- {
- baseFolder = Environment.GetEnvironmentVariable("LocalAppData");
- }
-
- var fullPath = Path.Combine(baseFolder, pluginFolderName);
- return fullPath;
- }
-
- public static void EnsureWorkingDirectoryExist(string localWorkingFolder, ILogger logger)
- {
- if (!Directory.Exists(localWorkingFolder))
- {
- LogMessage($"Creating working folder: {localWorkingFolder}", logger);
- Directory.CreateDirectory(localWorkingFolder);
- }
- }
-
- public static void DownloadJarFile(string url, string targetFilePath, ILogger logger)
- {
- LogMessage($"Download url: {url}", logger);
-
- if (File.Exists(targetFilePath))
- {
- // Downloading the file is slow so skip if possible
- LogMessage($"Jar file already exists at {targetFilePath}", logger);
- return;
- }
-
- LogMessage($"Downloading file from {url} to {targetFilePath}...", logger);
-
- var timer = Stopwatch.StartNew();
-
- using (var httpClient = new HttpClient())
- using (var response = httpClient.GetAsync(url).Result)
- {
- if (response.IsSuccessStatusCode)
- {
- using (var fileStream = new FileStream(targetFilePath, FileMode.Create, FileAccess.Write))
- {
- response.Content.CopyToAsync(fileStream).Wait();
- }
- }
- else
- {
- logger.LogError($"Failed to download the CFamily plugin: {response.Content}");
- }
- }
- timer.Stop();
- LogElapsedTime("Download completed. ", timer, logger);
- }
-
- public static string ExtractPluginFileNameFromUrl(string url, ILogger logger)
- {
- if (!url.EndsWith(".jar", StringComparison.InvariantCultureIgnoreCase))
- {
- throw new ArgumentException("Expecting the url to end with '.jar'");
- }
-
- var fileName = url.Split('/').Last();
-
- LogMessage($"Plugin file name: {fileName}", logger);
- return fileName;
- }
-
- public static void UnzipJar(string jarFilePath, string destinationFolder, ILogger logger)
- {
- if (Directory.GetFiles(destinationFolder).Length > 1)
- {
- // Unzipping the jar is slow so skip if possible
- LogMessage($"Skipping unzipping the jar because the destination folder already contains multiple files.", logger);
- return;
- }
-
- LogMessage($"Unzipping jar file...", logger);
- var timer = Stopwatch.StartNew();
-
- ZipFile.ExtractToDirectory(jarFilePath, destinationFolder);
-
- timer.Stop();
- LogElapsedTime("Unzipped jar file", timer, logger);
- }
-
- public static void UncompressAndUnzipTgx(string tarFilePath, string destinationFolder, ILogger logger)
- {
- // The txz file is compressed using XZ compression and zipped using the tar format.
- // There is no built-in framework support for these format so we are using two
- // open source libraries, both licensed under the MIT license.
- Common.EnsureWorkingDirectoryExist(destinationFolder, logger);
-
- var uncompresssedFile = Common.DecompressXZFile(tarFilePath, destinationFolder, logger);
- Common.ExtractTarToDirectory(uncompresssedFile, destinationFolder, logger);
- }
-
- public static string DecompressXZFile(string sourceFilePath, string destinationDirectory, ILogger logger)
- {
- var destFile = Path.Combine(destinationDirectory, Path.GetFileName(sourceFilePath)) + ".uncompressed";
- if (File.Exists(destFile))
- {
- LogMessage($"Uncompressed tar file already exists: {destFile}", logger);
- return destFile;
- }
-
- using (Stream xz = new XZStream(File.OpenRead(sourceFilePath)))
- using (Stream outputStream = new FileStream(destFile, FileMode.CreateNew))
- {
- xz.CopyTo(outputStream);
- }
- return destFile;
- }
-
- public static void UncompressAndUnzipTgz(string tarFilePath, string destinationFolder, ILogger logger)
- {
- // The txz file is compressed using XZ compression and zipped using the tar format.
- // There is no built-in framework support for these format so we are using two
- // open source libraries, both licensed under the MIT license.
- EnsureWorkingDirectoryExist(destinationFolder, logger);
-
- var uncompresssedFile = DecompressGZipFile(tarFilePath, destinationFolder, logger);
- ExtractTarToDirectory(uncompresssedFile, destinationFolder, logger);
- }
-
- public static string DecompressGZipFile(string sourceFilePath, string destinationDirectory, ILogger logger)
- {
- var destFile = Path.Combine(destinationDirectory, Path.GetFileName(sourceFilePath)) + ".uncompressed";
- if (File.Exists(destFile))
- {
- LogMessage($"Uncompressed tar file already exists: {destFile}", logger);
- return destFile;
- }
-
- using (Stream xz = new GZipStream(File.OpenRead(sourceFilePath), CompressionMode.Decompress))
- using (Stream outputStream = new FileStream(destFile, FileMode.CreateNew))
- {
- xz.CopyTo(outputStream);
- }
- return destFile;
- }
-
- public static void ExtractTarToDirectory(string sourceFilePath, string destinationDirectory, ILogger logger)
- {
- using (var outputStream = new FileStream(sourceFilePath, FileMode.Open))
- {
- ICSharpCode.SharpZipLib.Tar.TarArchive tarArchive = ICSharpCode.SharpZipLib.Tar.TarArchive.CreateInputTarArchive(outputStream);
- tarArchive.ExtractContents(destinationDirectory);
- }
- }
-
- public static List FindSingleFiles(string searchRoot, IEnumerable patterns, ILogger logger)
- {
- var files = new List();
-
- foreach (var file in patterns)
- {
- files.Add(FindSingleFile(searchRoot, file, logger));
- }
-
- return files;
- }
-
- public static List FindMultipleFiles(string searchRoot, IEnumerable patterns, ILogger logger)
- {
- var files = new List();
-
- foreach (var pattern in patterns)
- {
- var matches = Directory.GetFiles(searchRoot, pattern, SearchOption.AllDirectories);
- if (matches.Any())
- {
- LogMessage($"Found {matches.Count()} files matching for '{pattern}'", logger);
- files.AddRange(matches);
- }
- else
- {
- throw new InvalidOperationException($"Failed to find any files matching the pattern '{pattern}'");
- }
- }
-
- return files;
- }
-
- public static string FindSingleFile(string searchFolder, string pattern, ILogger logger)
- {
- var files = Directory.GetFiles(searchFolder, pattern, SearchOption.AllDirectories);
-
- if (files.Length != 1)
- {
- throw new InvalidOperationException($"Failed to locate one and only one file matching pattern {pattern} in {searchFolder}. Matching files: {files.Length}");
- }
-
- LogMessage($"Located file: {files[0]}", logger);
-
- return files[0];
- }
-
- private static void LogElapsedTime(string message, Stopwatch timer, ILogger logger)
- {
- LogMessage($"{message} {timer.Elapsed.ToString("g")}", logger);
- }
-
- private static void LogMessage(string message, ILogger logger)
- {
- logger.LogMessage(message);
- }
- }
-}
diff --git a/build/tools/CFamilyJarPreProcessor/Preprocessor.cs b/build/tools/CFamilyJarPreProcessor/Preprocessor.cs
deleted file mode 100644
index 80dbe4b23f..0000000000
--- a/build/tools/CFamilyJarPreProcessor/Preprocessor.cs
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * SonarLint for Visual Studio
- * Copyright (C) 2016-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-using System.Collections.Generic;
-using System.IO;
-
-namespace CFamilyJarPreProcessor
-{
- internal class Preprocessor
- {
- // The txz archive containing the subprocess.exe
- private const string WindowsTxzFilePattern = "clang*-win.txz";
-
- // Sub-folder into which the tar file should be unzipped
- private const string TarUnzipSubFolder = "tar_xz";
-
- // List of patterns to match single files in the uncompressed output
- private readonly string[] SingleFilePatterns = new string[]
- {
- "Sonar_way_profile.json",
- "RulesList.json",
- "MisraRulesList.json",
- TarUnzipSubFolder + @"\subprocess.exe",
- TarUnzipSubFolder + @"\LICENSE_THIRD_PARTY.txt"
- };
-
- // List of patterns to match multiple files in the uncompressed output
- private readonly string[] MultipleFilesPatterns = new string[]
- {
- @"org\sonar\l10n\cpp\rules\params\*_params.json",
- @"org\sonar\l10n\cpp\rules\cpp\*.json",
- @"org\sonar\l10n\cpp\rules\misra23\*.json",
- };
-
- private readonly ILogger logger;
- public Preprocessor(ILogger logger)
- {
- this.logger = logger;
- }
-
- ///
- /// Downloads plugin, extracts files, and copies the requires file to the output folder
- ///
- /// The method is lazy i.e. won't download the plugin if it exists, won't copy a file
- /// unless it is newer than the target file.
- public void Execute(string downloadUrl, string destinationDir)
- {
- var pluginFileName = Common.ExtractPluginFileNameFromUrl(downloadUrl, logger);
-
- // Ensure working directories exists
- var localWorkingFolder = Common.GetLocalBuildTimePluginCacheDir("SLVS_CFamily_Build");
- var perVersionPluginFolder = Path.Combine(localWorkingFolder, Path.GetFileNameWithoutExtension(pluginFileName));
- Common.EnsureWorkingDirectoryExist(perVersionPluginFolder, logger);
-
- // Download and unzip the jar
- var jarFilePath = Path.Combine(perVersionPluginFolder, pluginFileName);
- Common.DownloadJarFile(downloadUrl, jarFilePath, logger);
- Common.UnzipJar(jarFilePath, perVersionPluginFolder, logger);
-
- // Uncompress and extract the windows tar archive to get the subprocess exe
- var tarFilePath = Common.FindSingleFile(perVersionPluginFolder, WindowsTxzFilePattern, logger);
- var tarSubFolder = Path.Combine(perVersionPluginFolder, TarUnzipSubFolder);
- Common.UncompressAndUnzipTgx(tarFilePath, tarSubFolder, logger);
-
- // Locate the required files from the uncompressed jar and tar
- var fileList = FindFiles(perVersionPluginFolder);
-
- // Copy the files to the output directory
- CopyFilesToOutputDirectory(fileList, destinationDir);
- }
-
- private List FindFiles(string searchRoot)
- {
- var files = new List();
-
- files.AddRange(Common.FindSingleFiles(searchRoot, SingleFilePatterns, logger));
- files.AddRange(Common.FindMultipleFiles(searchRoot, MultipleFilesPatterns, logger));
-
- return files;
- }
-
- private void CopyFilesToOutputDirectory(IList files, string destinationDir)
- {
- Common.EnsureWorkingDirectoryExist(destinationDir, logger);
-
- foreach(var file in files)
- {
- CopyIfNewer(file, destinationDir);
- }
- }
-
- private void CopyIfNewer(string file, string destinationDir)
- {
- // Overwrite if newer
- var sourceFileInfo = new FileInfo(file);
- var destinationFileInfo = new FileInfo(Path.Combine(destinationDir, sourceFileInfo.Name));
-
- if (!destinationFileInfo.Exists || sourceFileInfo.LastWriteTimeUtc > destinationFileInfo.LastWriteTimeUtc)
- {
- logger.LogMessage($" Copying file: {file}");
- File.Copy(sourceFileInfo.FullName, destinationFileInfo.FullName, true);
- }
- else
- {
- logger.LogMessage($" Skipping copying file - not newer: {file}");
- }
- }
- }
-}
diff --git a/build/tools/CFamilyJarPreProcessor/ReadMe.txt b/build/tools/CFamilyJarPreProcessor/ReadMe.txt
deleted file mode 100644
index 1dcc8d9d16..0000000000
--- a/build/tools/CFamilyJarPreProcessor/ReadMe.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-CFamily plugin pre-processor
-----------------------------
-
-Ultimately, we want to embed multiple artefacts in the SLVS VSIX:
-1) the subprocess.exe,
-2) the "LICENSE_THIRD_PARTY.txt" file, and
-3) a file that contains all of rules metadata.
-
-Artefacts (1) and (2) exist somewhere in the jar.
-However, artefact (3) does not. Instead, there are some well-known json files and hundreds of per-rule files. We need to find and load all of these files and generate artefact (3).
-
-Format of artefact (3)
-----------------------
-TODO
-
-
-Integration with the rest of the build
---------------------------------------
-The application is a standalone exe that is called as part of the main solution build.
-
--> the solution needs to reference the build tools.
diff --git a/build/tools/CFamilyJarPreProcessor/packages.lock.json b/build/tools/CFamilyJarPreProcessor/packages.lock.json
deleted file mode 100644
index f0d7e6a2fb..0000000000
--- a/build/tools/CFamilyJarPreProcessor/packages.lock.json
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "version": 1,
- "dependencies": {
- ".NETFramework,Version=v4.7.2": {
- "SharpCompress": {
- "type": "Direct",
- "requested": "[0.32.1, )",
- "resolved": "0.32.1",
- "contentHash": "9Cwj3lK/p7wkiBaQPCvaKINuHYuZ0ACDldA4M3o5ISSq7cjbbq3yqigTDBUoKjtyyXpqmQHUkw6fhLnjNF30ow==",
- "dependencies": {
- "System.Memory": "4.5.4",
- "System.Text.Encoding.CodePages": "6.0.0"
- }
- },
- "SharpZipLib": {
- "type": "Direct",
- "requested": "[1.3.3, )",
- "resolved": "1.3.3",
- "contentHash": "N8+hwhsKZm25tDJfWpBSW7EGhH/R7EMuiX+KJ4C4u+fCWVc1lJ5zg1u3S1RPPVYgTqhx/C3hxrqUpi6RwK5+Tg=="
- },
- "System.Buffers": {
- "type": "Transitive",
- "resolved": "4.5.1",
- "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
- },
- "System.Memory": {
- "type": "Transitive",
- "resolved": "4.5.4",
- "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==",
- "dependencies": {
- "System.Buffers": "4.5.1",
- "System.Numerics.Vectors": "4.5.0",
- "System.Runtime.CompilerServices.Unsafe": "4.5.3"
- }
- },
- "System.Numerics.Vectors": {
- "type": "Transitive",
- "resolved": "4.5.0",
- "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ=="
- },
- "System.Runtime.CompilerServices.Unsafe": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
- },
- "System.Text.Encoding.CodePages": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==",
- "dependencies": {
- "System.Memory": "4.5.4",
- "System.Runtime.CompilerServices.Unsafe": "6.0.0"
- }
- }
- },
- ".NETFramework,Version=v4.7.2/win7-x86": {
- "System.Text.Encoding.CodePages": {
- "type": "Transitive",
- "resolved": "6.0.0",
- "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==",
- "dependencies": {
- "System.Memory": "4.5.4",
- "System.Runtime.CompilerServices.Unsafe": "6.0.0"
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/CFamily.UnitTests/Analysis/CFamily_CallAnalyzerTests.cs b/src/CFamily.UnitTests/Analysis/CFamily_CallAnalyzerTests.cs
deleted file mode 100644
index bd45b8f77f..0000000000
--- a/src/CFamily.UnitTests/Analysis/CFamily_CallAnalyzerTests.cs
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * SonarLint for Visual Studio
- * Copyright (C) 2016-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.IO.Abstractions;
-using System.IO.Abstractions.TestingHelpers;
-using System.Linq;
-using System.Threading;
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Moq;
-using SonarLint.VisualStudio.CFamily.SubProcess;
-using SonarLint.VisualStudio.Core;
-using SonarLint.VisualStudio.TestInfrastructure;
-
-namespace SonarLint.VisualStudio.CFamily.Analysis.UnitTests
-{
- [TestClass]
- public class CFamily_CLangAnalyzerTests
- {
- [TestMethod]
- public void CallAnalyzer_Succeeds_ReturnsMessages()
- {
- // Arrange
- var dummyProcessRunner = new DummyProcessRunner(MockResponse());
-
- // Act
- var response = GetResponse(dummyProcessRunner, CreateRequest(), new TestLogger());
-
- // Assert
- dummyProcessRunner.ExecuteCalled.Should().BeTrue();
-
- response.Count.Should().Be(1);
- response[0].Filename.Should().Be("file.cpp");
- }
-
- [TestMethod]
- public void CallAnalyzer_Fails_ReturnsZeroMessages()
- {
- // Arrange
- var dummyProcessRunner = new DummyProcessRunner(MockEmptyResponse());
-
- // Act
- var response = GetResponse(dummyProcessRunner, CreateRequest(), new TestLogger());
-
- // Assert
- dummyProcessRunner.ExecuteCalled.Should().BeTrue();
-
- response.Should().BeEmpty();
- }
-
- [TestMethod]
- public void CallAnalyzer_RequestWithEnvironmentVariables_EnvVarsArePassed()
- {
- // Arrange
- var envVars = new Dictionary { { "aaa", "bbb" } };
-
- var request = CreateRequestMock();
- request.SetupGet(x => x.EnvironmentVariables).Returns(envVars);
-
- var dummyProcessRunner = new DummyProcessRunner(MockResponse());
- var result = GetResponse(dummyProcessRunner, request.Object, new TestLogger());
-
- // Act and Assert
- dummyProcessRunner.ExecuteCalled.Should().BeTrue();
- dummyProcessRunner.SuppliedProcessRunnerArguments.EnvironmentVariables.Should().BeSameAs(envVars);
- }
-
- [TestMethod]
- public void CallAnalyzer_RequestWithReproducer_ReturnsZeroMessages()
- {
- // Arrange
- var request = CreateRequest(new CFamilyAnalyzerOptions { CreateReproducer = true });
- var dummyProcessRunner = new DummyProcessRunner(MockBadEndResponse());
- var result = GetResponse(dummyProcessRunner, request, new TestLogger());
-
- // Act and Assert
- result.Should().BeEmpty();
- dummyProcessRunner.ExecuteCalled.Should().BeTrue();
- }
-
- [TestMethod]
- public void CallAnalyzer_RequestWithReproducer_DiagnosticsFileIsSaved()
- {
- // Arrange
- var logger = new TestLogger();
- var fileSystem = CreateInitializedFileSystem();
- var requestMock = CreateRequestMock(new CFamilyAnalyzerOptions { CreateReproducer = true });
- var dummyProcessRunner = new DummyProcessRunner(MockResponse());
- GetResponse(dummyProcessRunner, requestMock.Object, logger, fileSystem);
-
- // Act and Assert
- dummyProcessRunner.ExecuteCalled.Should().BeTrue();
-
- fileSystem.AllFiles.Should().BeEquivalentTo(SubProcessFilePaths.RequestConfigFilePath);
- requestMock.Verify(x => x.WriteRequestDiagnostics(It.IsAny()), Times.Once);
-
- logger.AssertPartialOutputStringExists(SubProcessFilePaths.RequestConfigFilePath);
- logger.AssertPartialOutputStringExists(SubProcessFilePaths.ReproducerFilePath);
- }
-
- [TestMethod]
- public void CallAnalyzer_RequestWithoutReproducer_DiagnosticsFileIsNotSaved()
- {
- // Arrange
- var logger = new TestLogger();
- var fileSystem = CreateInitializedFileSystem();
- var requestMock = CreateRequestMock(new CFamilyAnalyzerOptions { CreateReproducer = false });
- var dummyProcessRunner = new DummyProcessRunner(MockResponse());
- GetResponse(dummyProcessRunner, requestMock.Object, logger, fileSystem);
-
- // Act and Assert
- dummyProcessRunner.ExecuteCalled.Should().BeTrue();
-
- fileSystem.AllFiles.Should().BeEmpty();
- requestMock.Verify(x => x.WriteRequestDiagnostics(It.IsAny()), Times.Never);
-
- logger.AssertPartialOutputStringDoesNotExist(SubProcessFilePaths.RequestConfigFilePath);
- logger.AssertPartialOutputStringDoesNotExist(SubProcessFilePaths.ReproducerFilePath);
- }
-
- [TestMethod]
- public void CallAnalyzer_BadResponse_ThrowsException()
- {
- // Arrange
- var logger = new TestLogger();
- var dummyProcessRunner = new DummyProcessRunner(MockBadEndResponse());
-
- Action act = () => GetResponse(dummyProcessRunner, CreateRequest(), logger);
-
- // Act and Assert
- act.Should().Throw().And.Message.Should().Be("Communication issue with the C/C++ analyzer");
- dummyProcessRunner.ExecuteCalled.Should().BeTrue();
- }
-
- private static IRequest CreateRequest(CFamilyAnalyzerOptions analyzerOptions = null) =>
- CreateRequestMock(analyzerOptions).Object;
-
- private static Mock CreateRequestMock(CFamilyAnalyzerOptions analyzerOptions = null)
- {
- var context = new RequestContext(null, null, null, null, analyzerOptions, false);
- var request = new Mock();
- request.Setup(x => x.Context).Returns(context);
- return request;
- }
-
- private static MockFileSystem CreateInitializedFileSystem()
- {
- var fileSystem = new MockFileSystem();
-
- // Make sure the expected working directory exists
- fileSystem.Directory.CreateDirectory(SubProcessFilePaths.WorkingDirectory);
- return fileSystem;
- }
-
- private static List GetResponse(DummyProcessRunner dummyProcessRunner, IRequest request, ILogger logger,
- IFileSystem fileSystem = null)
- {
- return GetResponse(dummyProcessRunner, request, logger, CancellationToken.None, fileSystem ?? new FileSystem());
- }
-
- private static List GetResponse(DummyProcessRunner dummyProcessRunner, IRequest request, ILogger logger, CancellationToken cancellationToken,
- IFileSystem fileSystem)
- {
- var messages = new List();
-
- CLangAnalyzer.ExecuteSubProcess(messages.Add, request, dummyProcessRunner, logger, cancellationToken, fileSystem);
-
- return messages;
- }
-
- private class DummyProcessRunner : IProcessRunner
- {
- private readonly byte[] responseToReturn;
-
- public DummyProcessRunner(byte[] responseToReturn)
- {
- this.responseToReturn = responseToReturn;
- }
-
- public bool ExecuteCalled { get; private set; }
-
- public ProcessRunnerArguments SuppliedProcessRunnerArguments { get; private set; }
-
- public void Execute(ProcessRunnerArguments runnerArgs)
- {
- ExecuteCalled = true;
-
- runnerArgs.Should().NotBeNull();
- SuppliedProcessRunnerArguments = runnerArgs;
-
- // Expecting a single file name as input
- runnerArgs.CmdLineArgs.Count().Should().Be(1);
-
- using (var stream = new MemoryStream(responseToReturn))
- using (var streamReader = new StreamReader(stream))
- {
- runnerArgs.HandleOutputStream(streamReader);
- }
- }
- }
-
- private byte[] MockEmptyResponse()
- {
- using (MemoryStream stream = new MemoryStream())
- {
- BinaryWriter writer = new BinaryWriter(stream);
- Protocol.WriteUTF(writer, "OUT");
-
- // 0 issues
-
- // 0 measures
- Protocol.WriteUTF(writer, "measures");
- Protocol.WriteInt(writer, 0);
-
- // 0 symbols
- Protocol.WriteUTF(writer, "symbols");
- Protocol.WriteInt(writer, 0);
-
- Protocol.WriteUTF(writer, "END");
- return stream.ToArray();
- }
- }
-
- private byte[] MockResponse()
- {
- using (MemoryStream stream = new MemoryStream())
- {
- BinaryWriter writer = new BinaryWriter(stream);
- Protocol.WriteUTF(writer, "OUT");
-
- // 1 issue
- Protocol.WriteUTF(writer, "message");
-
- Protocol.WriteUTF(writer, "ruleKey");
- Protocol.WriteUTF(writer, "file.cpp");
- Protocol.WriteInt(writer, 10);
- Protocol.WriteInt(writer, 11);
- Protocol.WriteInt(writer, 12);
- Protocol.WriteInt(writer, 13);
- Protocol.WriteInt(writer, 100);
- Protocol.WriteUTF(writer, "Issue message");
- writer.Write(true);
-
- // 1 flow
- Protocol.WriteInt(writer, 1);
- Protocol.WriteUTF(writer, "another.cpp");
- Protocol.WriteInt(writer, 14);
- Protocol.WriteInt(writer, 15);
- Protocol.WriteInt(writer, 16);
- Protocol.WriteInt(writer, 17);
- Protocol.WriteUTF(writer, "Flow message");
-
- // 0 Data Flow
- Protocol.WriteInt(writer, 0);
-
- // 0 fixes
- writer.Write(false);
- Protocol.WriteInt(writer, 0);
-
- // 1 measure
- Protocol.WriteUTF(writer, "measures");
- Protocol.WriteInt(writer, 1);
- Protocol.WriteUTF(writer, "file.cpp");
- Protocol.WriteInt(writer, 1);
- Protocol.WriteInt(writer, 1);
- Protocol.WriteInt(writer, 1);
- Protocol.WriteInt(writer, 1);
- Protocol.WriteInt(writer, 1);
-
- byte[] execLines = new byte[] { 1, 2, 3, 4 };
- Protocol.WriteInt(writer, execLines.Length);
- writer.Write(execLines);
-
- // 1 symbol
- Protocol.WriteUTF(writer, "symbols");
- Protocol.WriteInt(writer, 1);
- Protocol.WriteInt(writer, 1);
- Protocol.WriteInt(writer, 1);
- Protocol.WriteInt(writer, 1);
- Protocol.WriteInt(writer, 1);
- Protocol.WriteInt(writer, 1);
-
- Protocol.WriteUTF(writer, "END");
- return stream.ToArray();
- }
- }
-
- private byte[] MockBadEndResponse()
- {
- using (MemoryStream stream = new MemoryStream())
- {
- BinaryWriter writer = new BinaryWriter(stream);
- Protocol.WriteUTF(writer, "OUT");
- Protocol.WriteUTF(writer, "FOO");
- return stream.ToArray();
- }
- }
- }
-}
diff --git a/src/CFamily.UnitTests/Analysis/CLangAnalyzerTests.cs b/src/CFamily.UnitTests/Analysis/CLangAnalyzerTests.cs
deleted file mode 100644
index 1820337fde..0000000000
--- a/src/CFamily.UnitTests/Analysis/CLangAnalyzerTests.cs
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- * SonarLint for Visual Studio
- * Copyright (C) 2016-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-using System;
-using System.IO.Abstractions;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Moq;
-using SonarLint.VisualStudio.CFamily.Helpers.UnitTests;
-using SonarLint.VisualStudio.CFamily.Rules;
-using SonarLint.VisualStudio.CFamily.SubProcess;
-using SonarLint.VisualStudio.Core;
-using SonarLint.VisualStudio.Core.Analysis;
-using SonarLint.VisualStudio.Core.Telemetry;
-using SonarLint.VisualStudio.Integration;
-using SonarLint.VisualStudio.TestInfrastructure;
-
-namespace SonarLint.VisualStudio.CFamily.Analysis.UnitTests
-{
- [TestClass]
- public class CLangAnalyzerTests
- {
- private static readonly IIssueConsumer ValidIssueConsumer = Mock.Of();
- private static readonly IAnalysisStatusNotifier AnyStatusNotifier = Mock.Of();
-
- [TestMethod]
- public void IsSupported()
- {
- var testSubject = new CLangAnalyzer(Mock.Of(),
- Mock.Of(),
- Mock.Of(),
- Mock.Of(),
- Mock.Of(),
- Mock.Of());
-
- testSubject.IsAnalysisSupported(new[] { AnalysisLanguage.CFamily }).Should().BeTrue();
- testSubject.IsAnalysisSupported(new[] { AnalysisLanguage.Javascript }).Should().BeFalse();
- testSubject.IsAnalysisSupported(new[] { AnalysisLanguage.CascadingStyleSheets }).Should().BeFalse();
- testSubject.IsAnalysisSupported(new[] { AnalysisLanguage.Javascript, AnalysisLanguage.CFamily }).Should().BeTrue();
- }
-
- [TestMethod]
- public async Task ExecuteAnalysis_RequestCannotBeCreated_NoAnalysis()
- {
- var analysisOptions = new CFamilyAnalyzerOptions();
- var requestFactory = CreateRequestFactory("path", analysisOptions, null);
-
- var testSubject = CreateTestableAnalyzer(requestFactory: requestFactory.Object);
- await testSubject.TriggerAnalysisAsync("path", new[] { AnalysisLanguage.CFamily }, ValidIssueConsumer, analysisOptions, AnyStatusNotifier, CancellationToken.None);
-
- requestFactory.Verify(x => x.TryCreateAsync("path", analysisOptions), Times.Once);
-
- // TODO - modify check to be more reliable
- Thread.Sleep(400); // delay in case the background thread has gone on to call the subprocess
- testSubject.SubProcessExecutedCount.Should().Be(0);
- }
-
- [TestMethod]
- [DataRow(true)]
- [DataRow(false)]
- public async Task ExecuteAnalysis_RequestCannotBeCreated_NotPCH_LogOutput(bool isNullOptions)
- {
- var analysisOptions = isNullOptions ? null : new CFamilyAnalyzerOptions { CreatePreCompiledHeaders = false };
- var requestFactory = CreateRequestFactory("path", analysisOptions, null);
- var testLogger = new TestLogger();
-
- var testSubject = CreateTestableAnalyzer(
- requestFactory: requestFactory.Object,
- logger: testLogger);
-
- await testSubject.TriggerAnalysisAsync("path", new[] { AnalysisLanguage.CFamily }, ValidIssueConsumer, analysisOptions, AnyStatusNotifier, CancellationToken.None);
-
- testLogger.AssertOutputStringExists(string.Format(CFamilyStrings.MSG_UnableToCreateConfig, "path"));
- }
-
- [TestMethod]
- public async Task ExecuteAnalysis_RequestCannotBeCreated_PCH_NoLogOutput()
- {
- var analysisOptions = new CFamilyAnalyzerOptions {CreatePreCompiledHeaders = true};
- var requestFactory = CreateRequestFactory("path", analysisOptions, null);
- var testLogger = new TestLogger();
-
- var testSubject = CreateTestableAnalyzer(
- requestFactory: requestFactory.Object,
- logger: testLogger);
-
- await testSubject.TriggerAnalysisAsync("path", new[] { AnalysisLanguage.CFamily }, ValidIssueConsumer, analysisOptions, AnyStatusNotifier, CancellationToken.None);
-
- testLogger.AssertNoOutputMessages();
- }
-
- [TestMethod]
- public async Task ExecuteAnalysis_RequestCanBeCreated_AnalysisIsTriggered()
- {
- var analysisOptions = new CFamilyAnalyzerOptions();
- var request = CreateRequest("path");
- var requestFactory = CreateRequestFactory("path", analysisOptions, request);
-
-
- var testSubject = CreateTestableAnalyzer(
- requestFactory: requestFactory.Object);
-
- await testSubject.TriggerAnalysisAsync("path", new[] { AnalysisLanguage.CFamily }, ValidIssueConsumer, analysisOptions, AnyStatusNotifier, CancellationToken.None);
-
- testSubject.SubProcessExecutedCount.Should().Be(1);
- }
-
- [TestMethod]
- public async Task TriggerAnalysisAsync_StreamsIssuesFromSubProcessToConsumer()
- {
- const string fileName = "c:\\data\\aaa\\bbb\\file.txt";
- var rulesConfig = new DummyCFamilyRulesConfig("c")
- .AddRule("rule1", isActive: true)
- .AddRule("rule2", isActive: true);
-
- var request = CreateRequest
- (
- file: fileName,
- rulesConfiguration: rulesConfig,
- language: rulesConfig.LanguageKey
- );
- var requestFactory = CreateRequestFactory(fileName, ValidAnalyzerOptions, request);
-
- var message1 = new Message("rule1", fileName, 1, 1, 1, 1, "message one", false, Array.Empty(), Array.Empty());
- var message2 = new Message("rule2", fileName, 2, 2, 2, 2, "message two", false, Array.Empty(), Array.Empty());
-
- var convertedMessage1 = Mock.Of();
- var convertedMessage2 = Mock.Of();
-
- var issueConverter = new Mock();
- issueConverter
- .Setup(x => x.Convert(message1, request.Context.CFamilyLanguage, rulesConfig))
- .Returns(convertedMessage1);
-
- issueConverter
- .Setup(x => x.Convert(message2, request.Context.CFamilyLanguage, rulesConfig))
- .Returns(convertedMessage2);
-
- var issueConverterFactory = new Mock();
- issueConverterFactory.Setup(x => x.Create()).Returns(issueConverter.Object);
-
- var mockConsumer = new Mock();
- var statusNotifier = new Mock();
-
- var testSubject = CreateTestableAnalyzer(issueConverterFactory: issueConverterFactory.Object,
- requestFactory: requestFactory.Object);
-
- TestableCLangAnalyzer.HandleCallSubProcess subProcessOp = (handleMessage, _, _, _, _) =>
- {
- // NOTE: on a background thread so the assertions might be handled by the product code.
- // Must check testSubject.SubProcessCompleted on the "main" test thread.
-
- // Stream the first message to the analyzer
- handleMessage(message1);
-
- mockConsumer.Verify(x => x.Accept(fileName, It.IsAny>()), Times.Once);
- var suppliedIssues = (IEnumerable)mockConsumer.Invocations[0].Arguments[1];
- suppliedIssues.Count().Should().Be(1);
- suppliedIssues.First().Should().Be(convertedMessage1);
-
- // Stream the second message to the analyzer
- handleMessage(message2);
-
- mockConsumer.Verify(x => x.Accept(fileName, It.IsAny>()), Times.Exactly(2));
- suppliedIssues = (IEnumerable)mockConsumer.Invocations[1].Arguments[1];
- suppliedIssues.Count().Should().Be(1);
- suppliedIssues.First().Should().Be(convertedMessage2);
- };
- testSubject.SetCallSubProcessBehaviour(subProcessOp);
-
- await testSubject.TriggerAnalysisAsync(fileName, ValidDetectedLanguages, mockConsumer.Object, ValidAnalyzerOptions, statusNotifier.Object, CancellationToken.None);
-
- testSubject.SubProcessCompleted.Should().BeTrue();
-
- statusNotifier.Verify(x => x.AnalysisStarted(), Times.Once);
- statusNotifier.Verify(x => x.AnalysisFinished(2, It.IsAny()), Times.Once);
- statusNotifier.VerifyNoOtherCalls();
- }
-
- [TestMethod]
- public async Task TriggerAnalysisAsync_AnalysisIsCancelled_NotifiesOfCancellation()
- {
- var mockConsumer = new Mock();
- var originalStatusNotifier = new Mock();
-
- // Call the CLangAnalyzer on another thread (that thread is blocked by subprocess wrapper)
- var filePath = "c:\\test.cpp";
- var request = CreateRequest(filePath);
- var requestFactory = CreateRequestFactory(filePath, ValidAnalyzerOptions, request);
-
- var testSubject = CreateTestableAnalyzer(requestFactory: requestFactory.Object);
-
- using var cts = new CancellationTokenSource();
-
- TestableCLangAnalyzer.HandleCallSubProcess subProcessAction = (_, _, _, _, _) =>
- {
- cts.Cancel();
- };
- testSubject.SetCallSubProcessBehaviour(subProcessAction);
-
- // Expecting to use this status notifier, not the one supplied in the constructor
- var statusNotifier = new Mock();
-
- await testSubject.TriggerAnalysisAsync(filePath, ValidDetectedLanguages, mockConsumer.Object, ValidAnalyzerOptions, statusNotifier.Object, cts.Token);
-
- testSubject.SubProcessCompleted.Should().BeTrue();
-
- statusNotifier.Verify(x => x.AnalysisStarted(), Times.Once);
- statusNotifier.Verify(x => x.AnalysisCancelled(), Times.Once);
- statusNotifier.VerifyNoOtherCalls();
- originalStatusNotifier.Invocations.Count.Should().Be(0);
- }
-
- [TestMethod]
- public async Task TriggerAnalysisAsync_AnalysisFailsDueToException_NotifiesOfFailure()
- {
- void MockSubProcessCall(Action message, IRequest request, ISonarLintSettings settings, ILogger logger, CancellationToken token)
- {
- throw new NullReferenceException("test");
- }
-
- var statusNotifier = new Mock();
-
- var filePath = "c:\\test.cpp";
- var request = CreateRequest(filePath);
- var requestFactory = CreateRequestFactory(filePath, ValidAnalyzerOptions, request);
-
- var testSubject = CreateTestableAnalyzer(requestFactory: requestFactory.Object);
- testSubject.SetCallSubProcessBehaviour(MockSubProcessCall);
-
- await testSubject.TriggerAnalysisAsync(filePath, ValidDetectedLanguages, ValidIssueConsumer, ValidAnalyzerOptions, statusNotifier.Object, CancellationToken.None);
-
- statusNotifier.Verify(x => x.AnalysisStarted(), Times.Once);
- statusNotifier.Verify(x => x.AnalysisFailed(It.Is(e => e.Message == "test")), Times.Once);
- statusNotifier.VerifyNoOtherCalls();
- }
-
- [TestMethod]
- public async Task TriggerAnalysisAsync_AnalysisFailsDueToInternalMessage_NotifiesOfFailure()
- {
- const string fileName = "c:\\data\\aaa\\bbb\\file.txt";
- var request = CreateRequest(fileName);
- var requestFactory = CreateRequestFactory(fileName, ValidAnalyzerOptions, request);
-
- var internalErrorMessage = new Message("internal.UnexpectedFailure", "", 1, 1, 1, 1, "XXX Error in subprocess XXX", false, Array.Empty(), Array.Empty());
-
- var issueConverterFactory = Mock.Of();
- var mockConsumer = new Mock();
- var statusNotifier = new Mock();
-
- var testSubject = CreateTestableAnalyzer(issueConverterFactory: issueConverterFactory,
- requestFactory: requestFactory.Object);
-
- TestableCLangAnalyzer.HandleCallSubProcess subProcessOp = (handleMessage, _, _, _, _) =>
- {
- handleMessage(internalErrorMessage);
- };
- testSubject.SetCallSubProcessBehaviour(subProcessOp);
-
- await testSubject.TriggerAnalysisAsync(fileName, ValidDetectedLanguages, mockConsumer.Object, ValidAnalyzerOptions, statusNotifier.Object, CancellationToken.None);
-
- testSubject.SubProcessCompleted.Should().BeTrue();
-
- statusNotifier.Verify(x => x.AnalysisStarted(), Times.Once);
- statusNotifier.Verify(x => x.AnalysisFailed(CFamilyStrings.MSG_GenericAnalysisFailed), Times.Once);
- statusNotifier.VerifyNoOtherCalls();
- }
-
- [TestMethod]
- public async Task TriggerAnalysisAsync_SwitchesToBackgroundThreadBeforeProcessing()
- {
- var callOrder = new List();
-
- var threadHandling = new Mock();
- threadHandling.Setup(x => x.SwitchToBackgroundThread())
- .Returns(() => new NoOpThreadHandler.NoOpAwaitable())
- .Callback(() => callOrder.Add("SwitchToBackgroundThread"));
-
- var requestFactory = new Mock();
- requestFactory.Setup(x => x.TryCreateAsync(It.IsAny(), It.IsAny()))
- .Callback(() => callOrder.Add("TryCreateAsync"));
-
- var testSubject = CreateTestableAnalyzer(requestFactory: requestFactory.Object, threadHandling: threadHandling.Object);
- await testSubject.TriggerAnalysisAsync("path", ValidDetectedLanguages, Mock.Of(),
- Mock.Of(), Mock.Of(), CancellationToken.None);
-
- callOrder.Should().Equal("SwitchToBackgroundThread", "TryCreateAsync");
- }
-
- private readonly AnalysisLanguage[] ValidDetectedLanguages = new[] { AnalysisLanguage.CFamily };
- private readonly CFamilyAnalyzerOptions ValidAnalyzerOptions = null;
-
- private static IRequest CreateRequest(string file = null, string language = null, ICFamilyRulesConfig rulesConfiguration = null)
- {
- var request = new Mock();
- var context = new RequestContext(language, rulesConfiguration, file, null, null, false);
- request.SetupGet(x => x.Context).Returns(context);
- return request.Object;
- }
-
- private static Mock CreateRequestFactory(string filePath, CFamilyAnalyzerOptions analysisOptions, IRequest request)
- {
- var factory = new Mock();
- factory.Setup(x => x.TryCreateAsync(filePath, analysisOptions))
- .Returns(Task.FromResult(request));
- return factory;
- }
-
- private static TestableCLangAnalyzer CreateTestableAnalyzer(ITelemetryManager telemetryManager = null,
- ISonarLintSettings settings = null,
- ICFamilyIssueConverterFactory issueConverterFactory = null,
- IRequestFactoryAggregate requestFactory = null,
- ILogger logger = null,
- IFileSystem fileSystem = null,
- IThreadHandling threadHandling = null)
- {
- telemetryManager ??= Mock.Of();
- settings ??= new ConfigurableSonarLintSettings();
- issueConverterFactory ??= Mock.Of();
- requestFactory ??= Mock.Of();
- logger ??= new TestLogger();
- fileSystem ??= Mock.Of();
- threadHandling ??= new NoOpThreadHandler();
-
- return new TestableCLangAnalyzer(telemetryManager, settings, logger, issueConverterFactory, requestFactory, fileSystem, threadHandling);
- }
-
- private class TestableCLangAnalyzer : CLangAnalyzer
- {
- public delegate void HandleCallSubProcess(Action handleMessage, IRequest request,
- ISonarLintSettings settings, ILogger logger, CancellationToken cancellationToken);
-
- private HandleCallSubProcess onCallSubProcess;
-
- public void SetCallSubProcessBehaviour(HandleCallSubProcess onCallSubProcess) =>
- this.onCallSubProcess = onCallSubProcess;
-
- public bool SubProcessCompleted { get; private set; }
-
- public int SubProcessExecutedCount { get; private set; }
-
- public TestableCLangAnalyzer(ITelemetryManager telemetryManager, ISonarLintSettings settings,
- ILogger logger,
- ICFamilyIssueConverterFactory cFamilyIssueConverterFactory, IRequestFactoryAggregate requestFactory, IFileSystem fileSystem,
- IThreadHandling threadHandling)
- : base(telemetryManager, settings, Mock.Of(), cFamilyIssueConverterFactory, requestFactory, logger, fileSystem, threadHandling)
- { }
-
- protected override void CallSubProcess(Action handleMessage, IRequest request,
- ISonarLintSettings settings, ILogger logger, CancellationToken cancellationToken)
- {
- SubProcessExecutedCount++;
- if (onCallSubProcess == null)
- {
- base.CallSubProcess(handleMessage, request, settings, logger, cancellationToken);
- }
- else
- {
- onCallSubProcess(handleMessage, request, settings, logger, cancellationToken);
-
- // The sub process is executed on a separate thread, so any exceptions might be
- // squashed by the product code. So, we'll set a flag to indicate whether it
- // ran to completion.
- SubProcessCompleted = true;
- }
- }
- }
- }
-}
diff --git a/src/CFamily.UnitTests/Analysis/RequestFactoryAggregateTests.cs b/src/CFamily.UnitTests/Analysis/RequestFactoryAggregateTests.cs
deleted file mode 100644
index fd084a10d4..0000000000
--- a/src/CFamily.UnitTests/Analysis/RequestFactoryAggregateTests.cs
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * SonarLint for Visual Studio
- * Copyright (C) 2016-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-using System;
-using System.ComponentModel.Composition;
-using System.ComponentModel.Composition.Hosting;
-using System.Threading.Tasks;
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Moq;
-using SonarLint.VisualStudio.TestInfrastructure;
-
-namespace SonarLint.VisualStudio.CFamily.Analysis.UnitTests
-{
- [TestClass]
- public class RequestFactoryAggregateTests
- {
- [TestMethod]
- public void MefCtor_CheckExports()
- {
- var batch = new CompositionBatch();
-
- batch.AddExport(MefTestHelpers.CreateExport(Mock.Of()));
- batch.AddExport(MefTestHelpers.CreateExport(Mock.Of()));
- batch.AddExport(MefTestHelpers.CreateExport(Mock.Of()));
-
- var aggregateImport = new SingleObjectImporter();
- batch.AddPart(aggregateImport);
-
- using var catalog = new TypeCatalog(typeof(RequestFactoryAggregate));
- using var container = new CompositionContainer(catalog);
- container.Compose(batch);
-
- aggregateImport.Import.Should().NotBeNull();
- }
-
- [TestMethod]
- public void TryGet_NullFilePath_ArgumentNullException()
- {
- var testSubject = CreateTestSubject();
-
- Func act = () => testSubject.TryCreateAsync(null, new CFamilyAnalyzerOptions());
-
- act.Should().ThrowExactly().And.ParamName.Should().Be("analyzedFilePath");
- }
-
- [TestMethod]
- public async Task TryGet_NoFactories_Null()
- {
- var testSubject = CreateTestSubject();
-
- var result = await testSubject.TryCreateAsync("path", new CFamilyAnalyzerOptions());
-
- result.Should().BeNull();
- }
-
- [TestMethod]
- public async Task TryGet_NoMatchingFactory_Null()
- {
- var factory1 = new Mock();
- var factory2 = new Mock();
-
- var testSubject = CreateTestSubject(factory1.Object, factory2.Object);
-
- var options = new CFamilyAnalyzerOptions();
- var result = await testSubject.TryCreateAsync("path", options);
-
- result.Should().BeNull();
-
- factory1.Verify(x=> x.TryCreateAsync("path", options), Times.Once);
- factory2.Verify(x=> x.TryCreateAsync("path", options), Times.Once);
- }
-
- [TestMethod]
- public async Task TryGet_HasMatchingFactory_OtherFactoriesNotChecked()
- {
- var factory1 = new Mock();
- var factory2 = new Mock();
- var factory3 = new Mock();
-
- var requestToReturn = Mock.Of();
- var options = new CFamilyAnalyzerOptions();
- factory2.Setup(x => x.TryCreateAsync("path", options)).Returns(Task.FromResult(requestToReturn));
-
- var testSubject = CreateTestSubject(factory1.Object, factory2.Object, factory3.Object);
-
- var result = await testSubject.TryCreateAsync("path", options);
-
- result.Should().Be(requestToReturn);
-
- factory1.Verify(x => x.TryCreateAsync("path", options), Times.Once);
- factory2.Verify(x => x.TryCreateAsync("path", options), Times.Once);
- factory3.Invocations.Count.Should().Be(0);
- }
-
- private RequestFactoryAggregate CreateTestSubject(params IRequestFactory[] requestFactories) =>
- new RequestFactoryAggregate(requestFactories);
- }
-}
diff --git a/src/CFamily.UnitTests/CFamilySharedTests.cs b/src/CFamily.UnitTests/CFamilySharedTests.cs
deleted file mode 100644
index 4a84ac05a3..0000000000
--- a/src/CFamily.UnitTests/CFamilySharedTests.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * SonarLint for Visual Studio
- * Copyright (C) 2016-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using SonarLint.VisualStudio.Core;
-
-namespace SonarLint.VisualStudio.CFamily.UnitTests
-{
- [TestClass]
- public class CFamilySharedTests
- {
- [TestMethod]
- [DataRow("c:\\aaa.cpp", SonarLanguageKeys.CPlusPlus)]
- [DataRow("c:\\AAA.CPP", SonarLanguageKeys.CPlusPlus)]
- [DataRow("c:\\aaa.cxx", SonarLanguageKeys.CPlusPlus)]
- [DataRow("d:\\xxx.cc", SonarLanguageKeys.CPlusPlus)]
- [DataRow("c:\\aaa\\bbb.c", SonarLanguageKeys.C)]
- [DataRow("c:\\aaa.cpp.x", null)]
- [DataRow("c:\\aaa.cs", null)]
- [DataRow("c:\\aaa.js", null)]
- [DataRow("c:\\aaa.x", null)]
- public void FindLanguage_ReturnsExpectedValue(string filePath, string expected)
- {
- CFamilyShared.FindLanguageFromExtension(filePath)
- .Should().Be(expected);
- }
-
- [TestMethod]
- [DataRow("c:\\test.h", true)]
- [DataRow("c:\\test.hpp", true)]
- [DataRow("c:\\test.hh", true)]
- [DataRow("c:\\test.hxx", true)]
- [DataRow("c:\\test.H", true)]
- [DataRow("c:\\test.HPP", true)]
- [DataRow("c:\\test.HH", true)]
- [DataRow("c:\\test.HXX", true)]
- [DataRow("c:\\test.Hxx", true)]
- [DataRow("c:\\test.h.ha", false)]
- [DataRow("c:\\test.cpp", false)]
- [DataRow("c:\\test.cpp.h", true)]
- public void IsHeaderFileExtension_ReturnsExpectedValue(string filePath, bool expected)
- {
- CFamilyShared.IsHeaderFileExtension(filePath)
- .Should().Be(expected);
- }
- }
-}
diff --git a/src/CFamily.UnitTests/CMake/CompilationDatabaseLocatorTests.cs b/src/CFamily.UnitTests/CMake/CMakeCompilationDatabaseLocatorTests.cs
similarity index 87%
rename from src/CFamily.UnitTests/CMake/CompilationDatabaseLocatorTests.cs
rename to src/CFamily.UnitTests/CMake/CMakeCompilationDatabaseLocatorTests.cs
index bd63dfa77e..ccf41187d4 100644
--- a/src/CFamily.UnitTests/CMake/CompilationDatabaseLocatorTests.cs
+++ b/src/CFamily.UnitTests/CMake/CMakeCompilationDatabaseLocatorTests.cs
@@ -18,22 +18,19 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-using System;
using System.IO;
using System.IO.Abstractions;
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SonarLint.VisualStudio.CFamily.CMake;
using SonarLint.VisualStudio.Core;
-using SonarLint.VisualStudio.Core.CFamily;
+using SonarLint.VisualStudio.Core.SystemAbstractions;
using SonarLint.VisualStudio.TestInfrastructure;
using static SonarLint.VisualStudio.TestInfrastructure.Extensions.FileSystemExtensions;
namespace SonarLint.VisualStudio.CFamily.UnitTests.CMake
{
[TestClass]
- public class CompilationDatabaseLocatorTests
+ public class CMakeCompilationDatabaseLocatorTests
{
private const string RootDirectory = "dummy root";
@@ -43,8 +40,9 @@ public class CompilationDatabaseLocatorTests
[TestMethod]
public void MefCtor_CheckIsExported()
{
- MefTestHelpers.CheckTypeCanBeImported(
+ MefTestHelpers.CheckTypeCanBeImported(
MefTestHelpers.CreateExport(),
+ MefTestHelpers.CreateExport(),
MefTestHelpers.CreateExport());
}
@@ -72,10 +70,9 @@ public void Locate_NoCMakeSettings_ReturnsDefaultLocationIfFileExists(bool fileE
var defaultLocation = GetDefaultDatabaseFileLocation(activeConfiguration);
- var fileSystem = new Mock();
- fileSystem.SetFileExists(defaultLocation, fileExists);
+ var fileSystem = Substitute.For().SetFileExists(defaultLocation, fileExists);
- var testSubject = CreateTestSubject(RootDirectory, configProvider, cmakeSettingsProvider.Object, fileSystem.Object);
+ var testSubject = CreateTestSubject(RootDirectory, configProvider, cmakeSettingsProvider.Object, fileSystem);
var result = testSubject.Locate();
@@ -132,16 +129,15 @@ public void Locate_HasCMakeSettingsFile_ReturnsConfiguredPathIfItExists(bool fil
{
var configProvider = CreateConfigProvider("my-config");
var cmakeSettings = CreateCMakeSettings("my-config", "folder");
- var cmakeSettingsProvider = CreateCMakeSettingsProvider(RootDirectory,
+ var cmakeSettingsProvider = CreateCMakeSettingsProvider(RootDirectory,
new CMakeSettingsSearchResult(cmakeSettings, "", ""));
var compilationDatabaseFullLocation = Path.GetFullPath(
- Path.Combine("folder", CompilationDatabaseLocator.CompilationDatabaseFileName));
+ Path.Combine("folder", CMakeCompilationDatabaseLocator.CompilationDatabaseFileName));
- var fileSystem = new Mock();
- fileSystem.SetFileExists(compilationDatabaseFullLocation, fileExists);
+ var fileSystem = Substitute.For().SetFileExists(compilationDatabaseFullLocation, fileExists);
- var testSubject = CreateTestSubject(RootDirectory, configProvider, cmakeSettingsProvider.Object, fileSystem.Object,
+ var testSubject = CreateTestSubject(RootDirectory, configProvider, cmakeSettingsProvider.Object, fileSystem,
macroEvaluationService: PassthroughMacroService);
var result = testSubject.Locate();
@@ -199,8 +195,8 @@ public void Locate_MacroServiceIsCalled_RelativePath_ExpectedValueIsReturn(strin
context.MacroEvalService.Invocations.Count.Should().Be(1);
}
- private static CMakeSettings CreateCMakeSettings(string activeConfigurationName,
- string buildRoot,
+ private static CMakeSettings CreateCMakeSettings(string activeConfigurationName,
+ string buildRoot,
string generator = "generator") =>
new()
{
@@ -217,15 +213,15 @@ private static CMakeSettings CreateCMakeSettings(string activeConfigurationName,
private static string GetDefaultDatabaseFileLocation(string activeBuildConfiguration) =>
Path.GetFullPath(Path.Combine(
- string.Format(CompilationDatabaseLocator.DefaultLocationFormat,
+ string.Format(CMakeCompilationDatabaseLocator.DefaultLocationFormat,
RootDirectory,
activeBuildConfiguration),
- CompilationDatabaseLocator.CompilationDatabaseFileName));
+ CMakeCompilationDatabaseLocator.CompilationDatabaseFileName));
- private static CompilationDatabaseLocator CreateTestSubject(string rootDirectory,
+ private static CMakeCompilationDatabaseLocator CreateTestSubject(string rootDirectory,
IBuildConfigProvider buildConfigProvider = null,
ICMakeSettingsProvider cMakeSettingsProvider = null,
- IFileSystem fileSystem = null,
+ IFileSystemService fileSystem = null,
ILogger logger = null,
IMacroEvaluationService macroEvaluationService = null)
{
@@ -235,17 +231,17 @@ private static CompilationDatabaseLocator CreateTestSubject(string rootDirectory
cMakeSettingsProvider ??= Mock.Of();
buildConfigProvider ??= Mock.Of();
logger ??= Mock.Of();
- fileSystem ??= new FileSystem();
+ fileSystem ??= new FileSystemService();
macroEvaluationService ??= Mock.Of();
- return new CompilationDatabaseLocator(folderWorkspaceService.Object, buildConfigProvider, cMakeSettingsProvider, macroEvaluationService, fileSystem, logger);
+ return new CMakeCompilationDatabaseLocator(folderWorkspaceService.Object, buildConfigProvider, cMakeSettingsProvider, macroEvaluationService, fileSystem, logger);
}
private static IBuildConfigProvider CreateConfigProvider(string activeConfiguration)
{
var provider = new Mock();
provider.Setup(x => x.GetActiveConfig(It.IsAny())).Returns(activeConfiguration);
-
+
return provider.Object;
}
@@ -288,10 +284,9 @@ public MacroEvalContext(string macroServiceReturnValue, string unevaluatedBuildR
new CMakeSettingsSearchResult(cmakeSettings, cmakeSettingsFilePath, cmakeListsFilePath));
// Treat all files as existing
- var fileSystem = new Mock();
- Func nonNullFilesExist = x => x != null;
- fileSystem.Setup(x => x.File.Exists(It.IsAny())).Returns(nonNullFilesExist);
-
+ var fileSystem = Substitute.For();
+ fileSystem.File.Exists(Arg.Any()).Returns(call => call.Arg() != null);
+
MacroEvalService = new Mock();
MacroEvalService.Setup(x =>
x.Evaluate(unevaluatedBuildRoot,
@@ -307,10 +302,10 @@ public MacroEvalContext(string macroServiceReturnValue, string unevaluatedBuildR
Logger = new TestLogger(logToConsole: true);
TestSubject = CreateTestSubject(workspaceRootDir, configProvider, cmakeSettingsProvider.Object,
- fileSystem.Object, Logger, MacroEvalService.Object);
+ fileSystem, Logger, MacroEvalService.Object);
}
- public CompilationDatabaseLocator TestSubject { get; }
+ public CMakeCompilationDatabaseLocator TestSubject { get; }
public Mock MacroEvalService { get; }
public TestLogger Logger { get; }
}
diff --git a/src/CFamily.UnitTests/CMake/CMakeProjectTypeIndicatorTests.cs b/src/CFamily.UnitTests/CMake/CMakeProjectTypeIndicatorTests.cs
deleted file mode 100644
index c3a5ffa80d..0000000000
--- a/src/CFamily.UnitTests/CMake/CMakeProjectTypeIndicatorTests.cs
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * SonarLint for Visual Studio
- * Copyright (C) 2016-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-using System;
-using System.IO.Abstractions;
-using System.IO.Abstractions.TestingHelpers;
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Moq;
-using SonarLint.VisualStudio.Core;
-using SonarLint.VisualStudio.Core.CFamily;
-using SonarLint.VisualStudio.TestInfrastructure;
-
-namespace SonarLint.VisualStudio.CFamily.CMake.UnitTests
-{
- [TestClass]
- public class CMakeProjectTypeIndicatorTests
- {
- [TestMethod]
- public void MefCtor_CheckIsExported()
- {
- MefTestHelpers.CheckTypeCanBeImported(
- MefTestHelpers.CreateExport());
- }
-
- [TestMethod]
- public void IsCMake_NotOpenAsFolder_False()
- {
- var folderWorkspaceService = new Mock();
- folderWorkspaceService.Setup(x => x.IsFolderWorkspace()).Returns(false);
-
- var testSubject = CreateTestSubject(folderWorkspaceService.Object);
-
- var result = testSubject.IsCMake();
-
- result.Should().BeFalse();
- }
-
- [TestMethod]
- public void IsCMake_CouldNotRetrieveRootDirectory_ArgumentNullException()
- {
- var folderWorkspaceService = SetupOpenAsFolder(rootDirectory: null);
-
- var testSubject = CreateTestSubject(folderWorkspaceService.Object);
-
- Action act = () => testSubject.IsCMake();
-
- act.Should().Throw().And.ParamName.Should().Be("path");
- }
-
- [TestMethod]
- [DataRow("c:\\some directory\\CMakeLists.txt")]
- [DataRow("c:\\some directory\\sub\\CMakeLists.txt")]
- [DataRow("c:\\some directory\\sub\\folder\\CMakeLists.txt")]
- public void IsCMake_OpenAsFolderProject_HasCmakeFiles_True(string cmakeListsLocation)
- {
- var folderWorkspaceService = SetupOpenAsFolder("c:\\some directory");
- var fileSystem = new MockFileSystem();
- fileSystem.AddDirectory("c:\\some directory");
- fileSystem.AddFile(cmakeListsLocation, new MockFileData(""));
-
- var testSubject = CreateTestSubject(folderWorkspaceService.Object, fileSystem);
-
- var actualLanguage = testSubject.IsCMake();
-
- actualLanguage.Should().BeTrue();
- }
-
- [TestMethod]
- public void IsCMake_OpenAsFolderProject_NoCmakeFiles_False()
- {
- var folderWorkspaceService = SetupOpenAsFolder("c:\\some directory");
- var fileSystem = new MockFileSystem();
- fileSystem.AddDirectory("c:\\some directory");
- fileSystem.AddFile("c:\\anotherRoot\\CMakeLists.txt", new MockFileData(""));
-
- var testSubject = CreateTestSubject(folderWorkspaceService.Object, fileSystem);
-
- var actualLanguage = testSubject.IsCMake();
-
- actualLanguage.Should().BeFalse();
- }
-
- private static CMakeProjectTypeIndicator CreateTestSubject(IFolderWorkspaceService folderWorkspaceService = null, IFileSystem fileSystem = null)
- {
- folderWorkspaceService ??= Mock.Of();
- fileSystem ??= new MockFileSystem();
-
- return new CMakeProjectTypeIndicator(folderWorkspaceService, fileSystem);
- }
-
- private static Mock SetupOpenAsFolder(string rootDirectory)
- {
- var folderWorkspaceService = new Mock();
-
- folderWorkspaceService
- .Setup(x => x.IsFolderWorkspace())
- .Returns(true);
-
- folderWorkspaceService.Setup(x => x.FindRootDirectory())
- .Returns(rootDirectory);
-
- return folderWorkspaceService;
- }
- }
-}
diff --git a/src/CFamily.UnitTests/CMake/CMakeRequestFactoryTests.cs b/src/CFamily.UnitTests/CMake/CMakeRequestFactoryTests.cs
deleted file mode 100644
index 9a81471039..0000000000
--- a/src/CFamily.UnitTests/CMake/CMakeRequestFactoryTests.cs
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * SonarLint for Visual Studio
- * Copyright (C) 2016-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Moq;
-using SonarLint.VisualStudio.CFamily.Analysis;
-using SonarLint.VisualStudio.CFamily.Helpers.UnitTests;
-using SonarLint.VisualStudio.CFamily.Rules;
-using SonarLint.VisualStudio.CFamily.SubProcess;
-using SonarLint.VisualStudio.Core;
-using SonarLint.VisualStudio.TestInfrastructure;
-
-namespace SonarLint.VisualStudio.CFamily.CMake.UnitTests
-{
- [TestClass]
- public class CMakeRequestFactoryTests
- {
- private static readonly IEnvironmentVarsProvider ValidEnvVarsProvider = CreateEnvVarsProvider(new Dictionary { { "key", "value" } }).Object;
- private static readonly ICFamilyRulesConfigProvider ValidRulesConfigProvider_Cpp = CreateRulesProvider(SonarLanguageKeys.CPlusPlus, new DummyCFamilyRulesConfig((SonarLanguageKeys.CPlusPlus))).Object;
- private const string ValidFileName_Cpp = "any.cpp";
- private static readonly ICompilationConfigProvider ValidCompilationConfigProvider = CreateCompilationProvider(ValidFileName_Cpp, CreateCompilationDatabaseEntry(ValidFileName_Cpp)).Object;
- private static readonly CFamilyAnalyzerOptions ValidAnalyzerOptions = new CFamilyAnalyzerOptions();
-
- [TestMethod]
- public void MefCtor_CheckIsExported()
- {
- MefTestHelpers.CheckTypeCanBeImported(
- MefTestHelpers.CreateExport(),
- MefTestHelpers.CreateExport(),
- MefTestHelpers.CreateExport());
- }
-
- [TestMethod]
- public async Task TryGet_NoConfig_ReturnsNull()
- {
- const string fileName = "c:\\file.cpp";
-
- var compilationConfigProvider = CreateCompilationProvider(fileName, null);
- var rulesConfigProvider = new Mock();
-
- var testSubject = CreateTestSubject(compilationConfigProvider.Object, rulesConfigProvider.Object, ValidEnvVarsProvider);
-
- var actual = await testSubject.TryCreateAsync(fileName, new CFamilyAnalyzerOptions());
-
- actual.Should().BeNull();
- compilationConfigProvider.VerifyAll();
- rulesConfigProvider.Invocations.Count.Should().Be(0);
- }
-
- [TestMethod]
- public async Task TryGet_NoEnvVars_ReturnsNull()
- {
- var envVarsProvider = CreateEnvVarsProvider(null);
- var testSubject = CreateTestSubject(ValidCompilationConfigProvider, ValidRulesConfigProvider_Cpp, envVarsProvider.Object);
-
- var actual = await testSubject.TryCreateAsync(ValidFileName_Cpp, ValidAnalyzerOptions);
-
- actual.Should().BeNull();
- envVarsProvider.VerifyAll();
- }
-
- [TestMethod]
- public async Task TryGet_HasEnvVars_ReturnsExpectedValue()
- {
- var envVarsProvider = CreateEnvVarsProvider(new Dictionary
- {
- { "key1", "value1"},
- { "INCLUDE", "some paths..." }
- });
- var testSubject = CreateTestSubject(ValidCompilationConfigProvider, ValidRulesConfigProvider_Cpp, envVarsProvider.Object);
-
- var actual = await testSubject.TryCreateAsync(ValidFileName_Cpp, ValidAnalyzerOptions);
-
- actual.Should().NotBeNull();
- envVarsProvider.VerifyAll();
-
- actual.EnvironmentVariables.Should().NotBeNull();
- actual.EnvironmentVariables.Should().HaveCount(2);
- actual.EnvironmentVariables["key1"].Should().Be("value1");
- actual.EnvironmentVariables["INCLUDE"].Should().Be("some paths...");
- }
-
- [TestMethod]
- [Description("Check support for header files")]
- public async Task TryGet_LanguageCalculatedBasedOnCompilationEntry()
- {
- const string fileName = "c:\\file.h";
-
- var compilationDatabaseEntry = CreateCompilationDatabaseEntry("file.c");
- var compilationConfigProvider = CreateCompilationProvider(fileName, compilationDatabaseEntry);
- var rulesConfigProvider = new Mock();
-
- var testSubject = CreateTestSubject(compilationConfigProvider.Object, rulesConfigProvider.Object, ValidEnvVarsProvider);
- await testSubject.TryCreateAsync(fileName, new CFamilyAnalyzerOptions());
-
- compilationConfigProvider.VerifyAll();
-
- // When analyzing header files, the analyzed file will be ".h", which is not a known rules' language.
- // However, the compilation entry is a ".c" file, so we expect the code to calculate the rules based on the entry.
- rulesConfigProvider.Verify(x=> x.GetRulesConfiguration(SonarLanguageKeys.C), Times.Once());
- }
-
- [TestMethod]
- [Description("Check support for header files")]
- [DataRow("c:\\file.h", true)]
- [DataRow("c:\\file.c", false)]
- public async Task TryGet_IsHeaderFileCalculatedCorrectly(string analyzedFilePath, bool expectedIsHeaderFile)
- {
- var compilationDatabaseEntry = CreateCompilationDatabaseEntry("file.c");
- var compilationConfigProvider = CreateCompilationProvider(analyzedFilePath, compilationDatabaseEntry);
- var rulesConfigProvider = new Mock();
-
- var testSubject = CreateTestSubject(compilationConfigProvider.Object, rulesConfigProvider.Object, ValidEnvVarsProvider);
- var request = await testSubject.TryCreateAsync(analyzedFilePath, new CFamilyAnalyzerOptions());
-
- // When analyzing header files, the analyzed file will be ".h" but the compilation entry is a ".c" file.
- // We expected the property IsHeaderFile to be calculated based of the analyzed file, and not the compilation entry
- request.Context.IsHeaderFile.Should().Be(expectedIsHeaderFile);
- }
-
- [TestMethod]
- public async Task TryGet_UnrecognizedLanguage_ReturnsNull()
- {
- const string fileName = "c:\\file.txt";
-
- var compilationDatabaseEntry = CreateCompilationDatabaseEntry(fileName);
- var compilationConfigProvider = CreateCompilationProvider(fileName, compilationDatabaseEntry);
- var rulesConfigProvider = new Mock();
-
- var testSubject = CreateTestSubject(compilationConfigProvider.Object, rulesConfigProvider.Object, ValidEnvVarsProvider);
-
- var actual = await testSubject.TryCreateAsync(fileName, new CFamilyAnalyzerOptions());
-
- actual.Should().BeNull();
- compilationConfigProvider.VerifyAll();
- rulesConfigProvider.Invocations.Count.Should().Be(0);
- }
-
- [TestMethod]
- public async Task TryGet_ValidFile_ReturnsExpectedValue()
- {
- const string fileName = "c:\\file.c";
-
- var compilationDatabaseEntry = CreateCompilationDatabaseEntry(fileName);
- var compilationConfigProvider = CreateCompilationProvider(fileName, compilationDatabaseEntry);
-
- var rulesConfig = new DummyCFamilyRulesConfig(SonarLanguageKeys.C);
- var rulesConfigProvider = CreateRulesProvider(SonarLanguageKeys.C, rulesConfig);
-
- var testSubject = CreateTestSubject(compilationConfigProvider.Object, rulesConfigProvider.Object, ValidEnvVarsProvider);
-
- var analyzerOptions = new CFamilyAnalyzerOptions();
- var actual = await testSubject.TryCreateAsync(fileName, analyzerOptions);
-
- compilationConfigProvider.VerifyAll();
- rulesConfigProvider.VerifyAll();
- actual.Should().NotBeNull();
- actual.Context.File.Should().Be(fileName);
- actual.Context.PchFile.Should().Be(SubProcessFilePaths.PchFilePath);
- actual.Context.CFamilyLanguage.Should().Be(SonarLanguageKeys.C);
- actual.Context.AnalyzerOptions.Should().BeSameAs(analyzerOptions);
- actual.Context.RulesConfiguration.Should().BeSameAs(rulesConfig);
- }
-
- private static CMakeRequestFactory CreateTestSubject(
- ICompilationConfigProvider compilationConfigProvider = null,
- ICFamilyRulesConfigProvider rulesConfigProvider = null,
- IEnvironmentVarsProvider envVarsProvider = null)
- {
- compilationConfigProvider ??= Mock.Of();
- rulesConfigProvider ??= Mock.Of();
- envVarsProvider ??= Mock.Of();
-
- return new CMakeRequestFactory(compilationConfigProvider, rulesConfigProvider, envVarsProvider);
- }
-
- private static Mock CreateCompilationProvider(string fileName, CompilationDatabaseEntry entryToReturn)
- {
- var compilationConfigProvider = new Mock();
- compilationConfigProvider.Setup(x => x.GetConfig(fileName)).Returns(entryToReturn);
-
- return compilationConfigProvider;
- }
-
- private static Mock CreateRulesProvider(string languageKey, ICFamilyRulesConfig rulesConfig)
- {
- var rulesProvider = new Mock();
- rulesProvider.Setup(x => x.GetRulesConfiguration(languageKey)).Returns(rulesConfig);
- return rulesProvider;
- }
-
- private static Mock CreateEnvVarsProvider(IReadOnlyDictionary envVars = null)
- {
- var envVarsProvider = new Mock();
- envVarsProvider.Setup(x => x.GetAsync()).Returns(Task.FromResult(envVars));
- return envVarsProvider;
- }
-
- private static CompilationDatabaseEntry CreateCompilationDatabaseEntry(string filePath) =>
- new CompilationDatabaseEntry
- {
- File = filePath,
- Command = "cmd"
- };
- }
-}
diff --git a/src/CFamily.UnitTests/CMake/CompilationConfigProviderTests.cs b/src/CFamily.UnitTests/CMake/CompilationConfigProviderTests.cs
deleted file mode 100644
index f402dd0eaa..0000000000
--- a/src/CFamily.UnitTests/CMake/CompilationConfigProviderTests.cs
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * SonarLint for Visual Studio
- * Copyright (C) 2016-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-using System;
-using System.IO.Abstractions;
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Moq;
-using Newtonsoft.Json;
-using SonarLint.VisualStudio.CFamily.CMake;
-using SonarLint.VisualStudio.Core;
-using SonarLint.VisualStudio.Core.CFamily;
-using SonarLint.VisualStudio.TestInfrastructure;
-
-namespace SonarLint.VisualStudio.CFamily.UnitTests.CMake
-{
- [TestClass]
- public class CompilationConfigProviderTests
- {
- [TestMethod]
- public void MefCtor_CheckIsExported()
- {
- MefTestHelpers.CheckTypeCanBeImported(
- MefTestHelpers.CreateExport(),
- MefTestHelpers.CreateExport());
- }
-
- [TestMethod]
- [DataRow(null)]
- [DataRow("")]
- public void GetConfig_NullFilePath_ArgumentNullException(string analyzedFilePath)
- {
- var testSubject = CreateTestSubject();
-
- Action act = () => testSubject.GetConfig(analyzedFilePath);
-
- act.Should().Throw().And.ParamName.Should().Be("filePath");
- }
-
- [TestMethod]
- [DataRow(null)]
- [DataRow("")]
- public void GetConfig_NoCompilationDatabase_Null(string compilationDatabaseFilePath)
- {
- var compilationDatabaseLocator = SetupCompilationDatabaseLocator(compilationDatabaseFilePath);
- var testSubject = CreateTestSubject(compilationDatabaseLocator.Object);
-
- var result = testSubject.GetConfig("some file");
- result.Should().BeNull();
-
- compilationDatabaseLocator.Verify(x=> x.Locate(), Times.Once);
- }
-
- [TestMethod]
- [DataRow("")]
- [DataRow("[]")]
- public void GetConfig_EmptyCompilationDatabase_Null(string compilationDatabaseContents)
- {
- var compilationDatabaseLocator = SetupCompilationDatabaseLocator("some db");
- var fileSystem = SetupDatabaseFileContents("some db", compilationDatabaseContents);
- var logger = new TestLogger();
-
- var testSubject = CreateTestSubject(compilationDatabaseLocator.Object, fileSystem.Object, logger);
-
- var result = testSubject.GetConfig("some file");
- result.Should().BeNull();
-
- fileSystem.Verify(x => x.File.ReadAllText("some db"), Times.Once);
-
- logger.AssertOutputStringExists(string.Format(Resources.EmptyCompilationDatabaseFile, "some db"));
- }
-
- [TestMethod]
- public void GetConfig_ProblemReadingDatabaseFile_NonCriticalException_Null()
- {
- var compilationDatabaseLocator = SetupCompilationDatabaseLocator("some db");
- var fileSystem = SetupDatabaseFileContents("some db", exToThrow: new NotSupportedException("this is a test"));
- var logger = new TestLogger();
-
- var testSubject = CreateTestSubject(compilationDatabaseLocator.Object, fileSystem.Object, logger);
-
- var result = testSubject.GetConfig("some file");
- result.Should().BeNull();
-
- fileSystem.Verify(x => x.File.ReadAllText("some db"), Times.Once);
-
- logger.AssertPartialOutputStringExists("this is a test");
- }
-
- [TestMethod]
- public void GetConfig_ProblemReadingDatabaseFile_CriticalException_ExceptionThrown()
- {
- var compilationDatabaseLocator = SetupCompilationDatabaseLocator("some db");
- var fileSystem = SetupDatabaseFileContents("some db", exToThrow: new StackOverflowException());
-
- var testSubject = CreateTestSubject(compilationDatabaseLocator.Object, fileSystem.Object);
-
- Action act = () => testSubject.GetConfig("some file");
-
- act.Should().Throw();
- }
-
- [TestMethod]
- public void GetConfig_ProblemParsingDatabaseFile_Null()
- {
- var compilationDatabaseLocator = SetupCompilationDatabaseLocator("some db");
- var fileSystem = SetupDatabaseFileContents("some db", "not valid json");
- var logger = new TestLogger();
-
- var testSubject = CreateTestSubject(compilationDatabaseLocator.Object, fileSystem.Object, logger);
-
- var result = testSubject.GetConfig("some file");
- result.Should().BeNull();
-
- fileSystem.Verify(x => x.File.ReadAllText("some db"), Times.Once);
-
- logger.AssertPartialOutputStringExists("JsonReaderException");
- }
-
- [TestMethod]
- [DataRow("[{}]")] // no entries in file
- [DataRow("[{\"file\" : \"some file.c\" }]")] // different extension
- [DataRow("[{\"file\" : \"sub/some file.cpp\" }]")] // different path
- public void GetConfig_CodeFile_EntryNotFoundInDatabase_Null(string databaseFileContents)
- {
- var compilationDatabaseLocator = SetupCompilationDatabaseLocator("some db");
- var fileSystem = SetupDatabaseFileContents("some db", databaseFileContents);
- var logger = new TestLogger();
-
- var testSubject = CreateTestSubject(compilationDatabaseLocator.Object, fileSystem.Object, logger);
-
- var result = testSubject.GetConfig("some file.cpp");
- result.Should().BeNull();
-
- fileSystem.Verify(x => x.File.ReadAllText("some db"), Times.Once);
-
- logger.AssertPartialOutputStringExists(string.Format(Resources.NoCompilationDatabaseEntry, "some file.cpp"));
- }
-
- [TestMethod]
- [DataRow("c:\\some file.cpp")] // exact match
- [DataRow("c:/some file.cpp")] // different format
- [DataRow("c:/SOME file.cpp")] // case-sensitivity on name
- [DataRow("c:/some file.CPP")] // case-sensitivity on extension
- public void GetConfig_CodeFile_EntryFound_ReturnsEntry(string entryFilePath)
- {
- var compilationDatabaseLocator = SetupCompilationDatabaseLocator("some db");
- var compilationDatabaseContent = new[]
- {
- new CompilationDatabaseEntry {File = entryFilePath, Command = "some command", Directory = "some dir"}
- };
- var fileSystem = SetupDatabaseFileContents("some db", JsonConvert.SerializeObject(compilationDatabaseContent));
- var logger = new TestLogger();
-
- var testSubject = CreateTestSubject(compilationDatabaseLocator.Object, fileSystem.Object, logger);
-
- var result = testSubject.GetConfig("c:\\some file.cpp");
- result.Should().BeEquivalentTo(compilationDatabaseContent[0]);
- }
-
- [TestMethod]
- public void GetConfig_CodeFile_DatabaseContainsMultipleEntriesForSameFile_ReturnsFirstOne()
- {
- var compilationDatabaseLocator = SetupCompilationDatabaseLocator("some db");
- var compilationDatabaseContent = new[]
- {
- new CompilationDatabaseEntry {File = "some other file", Command = "cmd1", Directory = "dir1"},
- new CompilationDatabaseEntry {File = "some file", Command = "cmd2", Directory = "dir2"},
- new CompilationDatabaseEntry {File = "some file", Command = "cmd3", Directory = "dir3"}
- };
-
- var fileSystem = SetupDatabaseFileContents("some db", JsonConvert.SerializeObject(compilationDatabaseContent));
- var logger = new TestLogger();
-
- var testSubject = CreateTestSubject(compilationDatabaseLocator.Object, fileSystem.Object, logger);
-
- var result = testSubject.GetConfig("some file");
-
- result.Should().BeEquivalentTo(compilationDatabaseContent[1]);
- }
-
- [TestMethod]
- public void GetConfig_HeaderFile_NoEntriesInCompilationDatabase_Null()
- {
- var compilationDatabaseLocator = SetupCompilationDatabaseLocator("some db");
- var fileSystem = SetupDatabaseFileContents("some db", "[{}]");
- var logger = new TestLogger();
-
- var testSubject = CreateTestSubject(compilationDatabaseLocator.Object, fileSystem.Object, logger);
-
- var result = testSubject.GetConfig("some header.h");
- result.Should().BeNull();
-
- fileSystem.Verify(x => x.File.ReadAllText("some db"), Times.Once);
-
- logger.AssertPartialOutputStringExists(string.Format(Resources.NoCompilationDatabaseEntryForHeaderFile, "some header.h"));
- }
-
- [TestMethod]
- [DataRow("c:\\a.cpp")]
- [DataRow("c:\\some\\folder\\a.c")]
- [DataRow("D:\\A.cxx")]
- [DataRow("c:\\test\\a.CC")]
- public void GetConfig_HeaderFile_CodeWithSameNameDifferentPath_ReturnsCodeFileEntry(string matchingCodeFile)
- {
- const string headerFilePath = "c:\\test\\a.h";
-
- var compilationDatabaseContent = new[]
- {
- new CompilationDatabaseEntry {File = "c:\\test\\a.b", Command = "cmd1", Directory = "dir1"},
- new CompilationDatabaseEntry {File = matchingCodeFile, Command = "cmd2", Directory = "dir2"},
- new CompilationDatabaseEntry {File = "c:\\test\\aa.cpp", Command = "cmd3", Directory = "dir3"}
- };
-
- var compilationDatabaseLocator = SetupCompilationDatabaseLocator("some db");
- var fileSystem = SetupDatabaseFileContents("some db", JsonConvert.SerializeObject(compilationDatabaseContent));
-
- var testSubject = CreateTestSubject(compilationDatabaseLocator.Object, fileSystem.Object);
-
- var result = testSubject.GetConfig(headerFilePath);
- result.Should().BeEquivalentTo(compilationDatabaseContent[1]);
- }
-
- [TestMethod]
- public void GetConfig_HeaderFile_CodeWithSameNameExactPath_GivenPriorityOverDifferentPath()
- {
- const string headerFilePath = "c:\\test\\a.hxx";
-
- var compilationDatabaseContent = new[]
- {
- new CompilationDatabaseEntry {File = "c:\\a.c", Command = "cmd1", Directory = "dir1"},
- new CompilationDatabaseEntry {File = "c:\\other\\a.c", Command = "cmd1", Directory = "dir1"},
- new CompilationDatabaseEntry {File = "c:\\test\\a.c", Command = "cmd1", Directory = "dir1"},
- new CompilationDatabaseEntry {File = "c:\\test\\a.b", Command = "cmd1", Directory = "dir1"}
- };
-
- var compilationDatabaseLocator = SetupCompilationDatabaseLocator("some db");
- var fileSystem = SetupDatabaseFileContents("some db", JsonConvert.SerializeObject(compilationDatabaseContent));
-
- var testSubject = CreateTestSubject(compilationDatabaseLocator.Object, fileSystem.Object);
-
- var result = testSubject.GetConfig(headerFilePath);
- result.Should().BeEquivalentTo(compilationDatabaseContent[2]);
- }
-
- [TestMethod]
- public void GetConfig_HeaderFile_NoMatchingName_HasCodeFileUnderPath_ReturnsCodeFileEntry()
- {
- const string headerFilePath = "c:\\a\\b\\test.hh";
-
- var compilationDatabaseContent = new[]
- {
- new CompilationDatabaseEntry {File = "c:\\a\\wrongRoot2.cpp", Command = "cmd1", Directory = "dir1"},
- new CompilationDatabaseEntry {File = "c:\\b\\wrongRoot3.cpp", Command = "cmd1", Directory = "dir1"},
- new CompilationDatabaseEntry {File = "c:\\a\\b\\c\\correctRoot1.cpp", Command = "cmd1", Directory = "dir1"},
- new CompilationDatabaseEntry {File = "c:\\a\\b\\correctRoot2.cpp", Command = "cmd1", Directory = "dir1"},
- new CompilationDatabaseEntry {File = "c:\\wrongRoot3.cpp", Command = "cmd1", Directory = "dir1"},
- new CompilationDatabaseEntry {File = "c:\\a\\b\\correctRoot3.cpp", Command = "cmd1", Directory = "dir1"}
- };
-
- var compilationDatabaseLocator = SetupCompilationDatabaseLocator("some db");
- var fileSystem = SetupDatabaseFileContents("some db", JsonConvert.SerializeObject(compilationDatabaseContent));
-
- var testSubject = CreateTestSubject(compilationDatabaseLocator.Object, fileSystem.Object);
-
- var result = testSubject.GetConfig(headerFilePath);
- result.Should().BeEquivalentTo(compilationDatabaseContent[2]);
- }
-
- [TestMethod]
- public void GetConfig_HeaderFile_NoMatchingName_NoMatchingPath_ReturnsFirstCodeFileEntry()
- {
- const string headerFilePath = "c:\\a\\b\\test.hpp";
-
- var compilationDatabaseContent = new[]
- {
- new CompilationDatabaseEntry {File = "c:\\wrongRoot.cpp", Command = "cmd1", Directory = "dir1"},
- new CompilationDatabaseEntry {File = "c:\\a\\c\\wrongRoot2.cpp", Command = "cmd1", Directory = "dir1"},
- new CompilationDatabaseEntry {File = "c:\\b\\wrongRoot3.cpp", Command = "cmd1", Directory = "dir1"}
- };
-
- var compilationDatabaseLocator = SetupCompilationDatabaseLocator("some db");
- var fileSystem = SetupDatabaseFileContents("some db", JsonConvert.SerializeObject(compilationDatabaseContent));
-
- var testSubject = CreateTestSubject(compilationDatabaseLocator.Object, fileSystem.Object);
-
- var result = testSubject.GetConfig(headerFilePath);
- result.Should().BeEquivalentTo(compilationDatabaseContent[0]);
- }
-
- private static Mock SetupDatabaseFileContents(string databaseFilePath, string content = null, Exception exToThrow = null)
- {
- var fileSystem = new Mock();
- fileSystem.Setup(x => x.File.Exists(databaseFilePath)).Returns(true);
-
- if (exToThrow == null)
- {
- fileSystem.Setup(x => x.File.ReadAllText(databaseFilePath)).Returns(content);
- }
- else
- {
- fileSystem.Setup(x => x.File.ReadAllText(databaseFilePath)).Throws(exToThrow);
- }
-
- return fileSystem;
- }
-
- private Mock SetupCompilationDatabaseLocator(string compilationDatabaseFilePath)
- {
- var compilationDatabaseLocator = new Mock();
-
- compilationDatabaseLocator.Setup(x => x.Locate()).Returns(compilationDatabaseFilePath);
-
- return compilationDatabaseLocator;
- }
-
- private CompilationConfigProvider CreateTestSubject(ICompilationDatabaseLocator compilationDatabaseLocator = null,
- IFileSystem fileSystem = null,
- ILogger logger = null)
- {
- compilationDatabaseLocator ??= Mock.Of();
- fileSystem ??= Mock.Of();
- logger ??= Mock.Of();
-
- return new CompilationConfigProvider(compilationDatabaseLocator, fileSystem, logger);
- }
- }
-}
diff --git a/src/CFamily.UnitTests/CMake/EnvironmentVarsProviderTests.cs b/src/CFamily.UnitTests/CMake/EnvironmentVarsProviderTests.cs
deleted file mode 100644
index 4720b3493c..0000000000
--- a/src/CFamily.UnitTests/CMake/EnvironmentVarsProviderTests.cs
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * SonarLint for Visual Studio
- * Copyright (C) 2016-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Moq;
-using SonarLint.VisualStudio.Core;
-using SonarLint.VisualStudio.CFamily.CMake;
-using SonarLint.VisualStudio.TestInfrastructure;
-
-namespace SonarLint.VisualStudio.CFamily.UnitTests.CMake
-{
- [TestClass]
- public class EnvironmentVarsProviderTests
- {
- [TestMethod]
- public void MefCtor_CheckIsExported()
- {
- MefTestHelpers.CheckTypeCanBeImported(
- MefTestHelpers.CreateExport(),
- MefTestHelpers.CreateExport());
- }
-
- [TestMethod]
- public async Task TryGet_Caching()
- {
- var envVars_AAA = new Dictionary { { "AAA", "111" } };
- var envVars_BBB = new Dictionary { { "BBB", "222" } };
-
- var vsDevCmdProvider = new Mock()
- .SetEnvVars("AAA", envVars_AAA)
- .SetEnvVars("BBB", envVars_BBB);
-
- var testSubject = CreateTestSubject(vsDevCmdProvider.Object);
-
- // 1. ScriptParams AAA: empty cache => cache miss => provider called
- var case1 = await testSubject.GetAsync("AAA");
-
- case1.Should().BeSameAs(envVars_AAA);
- vsDevCmdProvider.CheckSettingsFetchedOnce("AAA");
- vsDevCmdProvider.CheckSettingsNotFetched("BBB");
-
- // 2. ScriptParamsA: cache hit => provider not called
- var case2 = await testSubject.GetAsync("AAA");
-
- case2.Should().BeSameAs(envVars_AAA);
- vsDevCmdProvider.CheckSettingsFetchedOnce("AAA");
- vsDevCmdProvider.CheckSettingsNotFetched("BBB");
-
- // 3. ScriptParamsB: different params, cache miss => provider called
- var case3 = await testSubject.GetAsync("BBB");
-
- case3.Should().BeSameAs(envVars_BBB);
- vsDevCmdProvider.CheckSettingsFetchedOnce("AAA");
- vsDevCmdProvider.CheckSettingsFetchedOnce("BBB");
- }
-
- [TestMethod]
- public async Task TryGet_NullVsDevCmdResultsAreCached()
- {
- var vsDevCmdProvider = new Mock()
- .SetEnvVars(string.Empty, null);
-
- var testSubject = CreateTestSubject(vsDevCmdProvider.Object);
-
- // 1. empty cache => cache miss => provider called
- var actual = await testSubject.GetAsync(string.Empty);
-
- actual.Should().BeNull();
- vsDevCmdProvider.CheckSettingsFetchedOnce(string.Empty);
-
- // 2. Call again - null result should have been cached i.e. we don't
- // retry calling just because we didn't get a non-null result first time.
- actual = await testSubject.GetAsync(string.Empty);
-
- actual.Should().BeNull();
- vsDevCmdProvider.CheckSettingsFetchedOnce(string.Empty);
- }
-
- [TestMethod]
- public void TryGet_SecondCallIsBlockedUntilFirstCallCompletes()
- {
- const int timeoutMs = 300;
-
- var firstCallStarted = new ManualResetEvent(false);
- var allowFirstCallToComplete = new ManualResetEvent(false);
-
- void FirstCallToProviderOp()
- {
- // Let the test know that the provider has been called i.e. we're inside the lock
- firstCallStarted.Set();
-
- // Wait until the test indicates that it wants the call to finish i.e. to release the lock
- allowFirstCallToComplete.WaitOne();
- }
-
- // Two calls with same script params, so the provider should only be called once
- // and return the same result
- var provider = new Mock();
- provider.Setup(x => x.GetAsync(string.Empty))
- .Callback(FirstCallToProviderOp)
- .ReturnsAsync(new Dictionary());
-
- var testSubject = CreateTestSubject(provider.Object);
-
- // Start first call and wait for it to report it has started
- var firstCall = Task.Run(() => testSubject.GetAsync());
- var firstTaskRunning = firstCallStarted.WaitOne(timeoutMs);
- firstTaskRunning.Should().BeTrue();
- provider.Invocations.Count.Should().Be(1);
-
- // Start second call - should be blocked by lock
- var secondCall = Task.Run(() => testSubject.GetAsync());
- var secondCallFinished = secondCall.Wait(500);
- secondCallFinished.Should().BeFalse();
-
- // Check the second call thread is waiting for the lock
- secondCall.Status.Should().Be(TaskStatus.WaitingForActivation);
-
- // Unblock the first call
- allowFirstCallToComplete.Set();
- var firstCallCompleted = firstCall.Wait(timeoutMs);
- firstCallCompleted.Should().BeTrue();
-
- var secondCallCompleted = secondCall.Wait(timeoutMs);
- secondCallCompleted.Should().BeTrue();
-
- secondCall.Result.Should().BeSameAs(firstCall.Result);
- provider.Invocations.Count.Should().Be(1);
- }
-
- private static EnvironmentVarsProvider CreateTestSubject(IVsDevCmdEnvironmentProvider vsDevCmdProvider)
- {
- var testSubject = new EnvironmentVarsProvider(vsDevCmdProvider, new TestLogger(logToConsole: true));
- return testSubject;
- }
- }
-
- internal static class EnvironmentVarsProviderTestsExtensions
- {
- public static Mock SetEnvVars(this Mock provider, string scriptParams, IReadOnlyDictionary envVars)
- {
- provider.Setup(x => x.GetAsync(scriptParams)).Returns(Task.FromResult(envVars));
- return provider;
- }
-
- public static void CheckSettingsFetchedOnce(this Mock provider, string scriptParms) =>
- provider.Verify(x => x.GetAsync(scriptParms), Times.Once);
-
- public static void CheckSettingsNotFetched(this Mock provider, string scriptParms) =>
- provider.Verify(x => x.GetAsync(scriptParms), Times.Never);
- }
-}
diff --git a/src/CFamily.UnitTests/CMake/VsDevCmdEnvironmentVarsProviderTests.cs b/src/CFamily.UnitTests/CMake/VsDevCmdEnvironmentVarsProviderTests.cs
deleted file mode 100644
index 8c801f6315..0000000000
--- a/src/CFamily.UnitTests/CMake/VsDevCmdEnvironmentVarsProviderTests.cs
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * SonarLint for Visual Studio
- * Copyright (C) 2016-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.IO.Abstractions;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Moq;
-using SonarLint.VisualStudio.CFamily.CMake;
-using SonarLint.VisualStudio.Core;
-using SonarLint.VisualStudio.Core.SystemAbstractions;
-using SonarLint.VisualStudio.Infrastructure.VS;
-using SonarLint.VisualStudio.TestInfrastructure;
-
-namespace SonarLint.VisualStudio.CFamily.UnitTests.CMake
-{
- [TestClass]
- public class VsDevCmdEnvironmentVarsProviderTests
- {
- public TestContext TestContext { get; set; }
-
- [TestMethod]
- public void MefCtor_CheckIsExported()
- {
- MefTestHelpers.CheckTypeCanBeImported(
- MefTestHelpers.CreateExport(),
- MefTestHelpers.CreateExport());
- }
-
- [TestMethod]
- public async Task Get_MissingFile_ReturnsEmptySettings()
- {
- var context = new ProcessContext(installRootDir: "c:\\aaa\\bbb", batchFileExists: false);
-
- var actual = await context.TestSubject.GetAsync("any");
- actual.Should().BeNull();
-
- context.FileSystem.Verify(x => x.File.Exists("c:\\aaa\\bbb\\Common7\\Tools\\VsDevCmd.bat"), Times.Once);
- }
-
- [TestMethod]
- [DataRow("input-script-params")]
- [DataRow(null)]
- public async Task Get_ExpectedCommandsPassed(string scriptParams)
- {
- var context = new ProcessContext(installRootDir: "d:\\myinstalldir\\");
-
- // Act
- await context.TestSubject.GetAsync(scriptParams);
-
- context.ActualProcessStartInfo.Should().NotBeNull();
- context.ActualProcessStartInfo.FileName.Should().Be(Environment.GetEnvironmentVariable("COMSPEC"));
-
- context.ActualProcessStartInfo.Arguments.Should().NotBeNull();
- context.TestSubject.UniqueId.Should().NotBeNullOrEmpty();
-
- // Split and clean up the command string to make the individual commands easier to check
- var args = context.ActualProcessStartInfo.Arguments.Split(new string[] { " && " }, StringSplitOptions.None)
- .Select(x => x.Trim())
- .ToArray();
-
- args[0].Should().Be("/U /K set VSCMD_SKIP_SENDTELEMETRY=1"); // args to cmd.exe and first command in the sequence
- args[1].Should().Be($@"""d:\myinstalldir\Common7\Tools\VsDevCmd.bat"" {scriptParams}".TrimEnd()); // calculated full path to VsDevCmd.bat with additional params
- args[2].Should().Be("echo SONARLINT_BEGIN_CAPTURE " + context.TestSubject.UniqueId);
- args[3].Should().Be("set");
- args[4].Should().StartWith("echo SONARLINT_END_CAPTURE " + context.TestSubject.UniqueId);
- }
-
- [TestMethod]
- public async Task Get_ExpectedTimeoutDurationUsed()
- {
- var context = new ProcessContext();
-
- // Act
- await context.TestSubject.GetAsync("any");
-
- context.Process.Verify(x => x.WaitForExitAsync(30000), Times.Once);
- }
-
- [TestMethod]
- public async Task Get_Lifecycle_RunsToCompletion()
- {
- var context = new ProcessContext(hasExited: true);
-
- // Act
- await context.TestSubject.GetAsync("any");
-
- // Just checking the invocation order
- var invokedMembers = context.Process.Invocations.Select(x => x.Method.Name).ToArray();
- invokedMembers.Should().ContainInOrder(
- // Initialize and run
- "set_HandleOutputDataReceived",
- "BeginOutputReadLine",
- "WaitForExitAsync",
-
- // Cleanup
- "get_HasExited",
- "Dispose"
- );
-
- invokedMembers.Should().NotContain("Kill"); // should have terminated normally
- }
-
- [TestMethod]
- public async Task Get_Lifecycle_TimeoutOccurs_ProcessIsKilled()
- {
- var context = new ProcessContext(hasExited: false);
-
- // Act
- await context.TestSubject.GetAsync("any");
-
- var invokedMembers = context.Process.Invocations.Select(x => x.Method.Name).ToArray();
- invokedMembers.Should().ContainInOrder(
- "Kill",
- "Dispose"
- );
- }
-
- [TestMethod]
- public async Task Get_DataProcessing_DataOutsideMarkersIsIgnored()
- {
- ProcessContext.SimulateWorkInProcess writeOutputOp = (context) =>
- {
- context.WriteToOutput("before capture -> should be ignored");
- context.WriteToOutput("before_capture=ignore");
-
- context.WriteBeginCapture();
- context.WriteToOutput("key1=value1");
- context.WriteToOutput("not an env setting -> should be ignored");
- context.WriteToOutput("key2=value with spaces");
- context.WriteToOutput("anther not an env setting -> should be ignored");
- context.WriteEndCapture();
-
- context.WriteToOutput("after capture -> should be ignored");
- context.WriteToOutput("after_capture=ignore");
-
- return true; // hasExited
- };
-
- var context = new ProcessContext(simulatedWorkCallback: writeOutputOp);
-
- // Act
- var actual = await context.TestSubject.GetAsync("any");
-
- actual.Should().NotBeNull();
- actual.Count.Should().Be(2);
- actual.Keys.Should().BeEquivalentTo("key1", "key2");
- actual["key1"].Should().Be("value1");
- actual["key2"].Should().Be("value with spaces");
- }
-
- [TestMethod]
- public async Task Get_DataProcessing_TimeoutOccurs_NullReturned()
- {
- ProcessContext.SimulateWorkInProcess writeOutputOp = (context) =>
- {
- context.WriteBeginCapture();
- context.WriteToOutput("key1=value1");
- context.WriteToOutput("key2=value2");
-
- return false; // hasExited = false i.e. timeout
- };
-
- var context = new ProcessContext(simulatedWorkCallback: writeOutputOp);
-
- // Act
- var actual = await context.TestSubject.GetAsync("any");
-
- actual.Should().BeNull();
- context.Logger.AssertPartialOutputStringExists(Resources.VsDevCmd_TimedOut);
- }
-
- [TestMethod]
- public async Task Get_DataProcessing_NoSettingsCaptured_NullReturned()
- {
- ProcessContext.SimulateWorkInProcess writeOutputOp = (context) =>
- {
- context.WriteBeginCapture();
- context.WriteToOutput("not a valid setting");
- context.WriteEndCapture();
- return true; // hasExited = true i.e. completed successfully
- };
-
- var context = new ProcessContext(simulatedWorkCallback: writeOutputOp);
-
- // Act
- var actual = await context.TestSubject.GetAsync("any");
-
- actual.Should().BeNull();
- context.Logger.AssertPartialOutputStringExists(Resources.VsDevCmd_NoSettingsFound);
- }
-
- [TestMethod]
- public async Task Get_NonCriticalException_IsSuppressed()
- {
- var context = new ProcessContext();
-
- context.FileSystem.Reset();
- context.FileSystem.Setup(x => x.File.Exists(It.IsAny()))
- .Throws(new InvalidCastException("thrown from test"));
-
- var actual = await context.TestSubject.GetAsync("any");
-
- actual.Should().BeNull();
- }
-
- [TestMethod]
- public void Get_CriticalException_IsNotSuppressed()
- {
- var context = new ProcessContext();
-
- context.FileSystem.Reset();
- context.FileSystem.Setup(x => x.File.Exists(It.IsAny()))
- .Throws(new StackOverflowException("thrown from test"));
-
- Func act = () => context.TestSubject.GetAsync("any");
-
- act.Should().ThrowExactly().And.Message.Should().Be("thrown from test");
- }
-
- [TestMethod]
- public async Task Get_ThrowsIfOnUIThread()
- {
- var context = new ProcessContext();
-
- await context.TestSubject.GetAsync(null);
-
- context.ThreadHandling.Verify(x => x.ThrowIfOnUIThread(), Times.Once);
- }
-
- private class ProcessContext
- {
- ///
- /// Simulates work done in the process. The return value sets the status of
- /// Process.HasExited to indicate whether the process is still running or not.
- ///
- /// The WriteXXX methods can then be used to send output data to the test subject
- public delegate bool SimulateWorkInProcess(ProcessContext context);
-
- private readonly SimulateWorkInProcess simulatedWorkCallback;
-
- // Synchronisation objects used to control execution on a separate thread to simulate
- // work being done in the process
- private ManualResetEvent beginReadOutputCalled = new ManualResetEvent(false);
- private ManualResetEvent simulatedWorkCompleted = new ManualResetEvent(false);
-
- public ProcessContext(string installRootDir = "c:\\any",
- SimulateWorkInProcess simulatedWorkCallback = null,
- bool hasExited = true, // assume the process exits succesfully i.e. no timeout
- bool batchFileExists = true
- )
- {
- // Set up the basic mocks and properties
- Process = new Mock();
-
- ProcessFactory = new Mock();
- ProcessFactory.Setup(x => x.Start(It.IsAny()))
- .Callback(x => ActualProcessStartInfo = x)
- .Returns(Process.Object);
-
- Logger = new TestLogger(logToConsole: true, logThreadId: true);
-
- SetHasExitedValue(hasExited);
-
- var batchFilePath = Path.Combine(installRootDir, "Common7", "Tools", "VsDevCmd.bat");
- FileSystem = new Mock();
- FileSystem.Setup(x => x.File.Exists(batchFilePath)).Returns(batchFileExists);
-
- // Don't set up the background thread / sync objects unless there is
- // actually simulated work to do.
- if(simulatedWorkCallback != null)
- {
- this.simulatedWorkCallback = simulatedWorkCallback;
- SetupSimulatedProcessThread();
- }
-
- ThreadHandling = new Mock();
-
- // Create the test subject
- TestSubject = new VsDevCmdEnvironmentVarsProvider(CreateVsInfoService(installRootDir), ThreadHandling.Object, Logger,
- ProcessFactory.Object, FileSystem.Object);
- }
-
- public VsDevCmdEnvironmentVarsProvider TestSubject { get; }
-
- public Mock Process { get; }
-
- public Mock ProcessFactory { get; }
-
- public Mock FileSystem { get; }
-
- public Mock ThreadHandling { get; }
-
- public TestLogger Logger { get; }
-
- ///
- /// Process start info instance created by the test subject
- ///
- public ProcessStartInfo ActualProcessStartInfo { get; private set; }
-
- public void WriteToOutput(string message)
- {
- Action handler = Process.Object.HandleOutputDataReceived;
- handler?.Invoke(message);
- }
-
- public void WriteBeginCapture() =>
- WriteToOutput("SONARLINT_BEGIN_CAPTURE " + TestSubject.UniqueId);
-
- public void WriteEndCapture() =>
- WriteToOutput("SONARLINT_END_CAPTURE " + TestSubject.UniqueId);
-
- private static IVsInfoService CreateVsInfoService(string installRootDir)
- {
- var infoService = new Mock();
- infoService.SetupGet(x => x.InstallRootDir).Returns(installRootDir);
- return infoService.Object;
- }
-
- private void SetHasExitedValue(bool value) =>
- Process.SetupGet(x => x.HasExited).Returns(value);
-
- private void SetupSimulatedProcessThread()
- {
- Process.SetupProperty(x => x.HandleOutputDataReceived);
-
- // Block the process from completing until the callback has completed
- Process.Setup(x => x.WaitForExitAsync(It.IsAny()))
- .Callback(() => simulatedWorkCompleted.WaitOne());
-
- // Start a new thread to simulate work inside the process
- Task.Run(() => CallbackToTestOnSeparateThread());
-
- // Unblock the processing thread when the consumer calls BeginOutputReadLine
- Process.Setup(x => x.BeginOutputReadLine())
- .Callback(() => beginReadOutputCalled.Set());
- }
-
- private void CallbackToTestOnSeparateThread()
- {
- // Don't start the simulated workload until the consumer calls "BeginOutputReadLine".
- LogMessage("Waiting for BeginOutputReadLine to be called...");
- beginReadOutputCalled.WaitOne();
- LogMessage("BeginOutputReadLine has been be called. Starting to write output...");
-
- bool hasExited = simulatedWorkCallback.Invoke(this); // call back to the test
- SetHasExitedValue(hasExited);
-
- // Signal that we are done to unblock Process.WaitForExit
- LogMessage("Simulated work complete");
- simulatedWorkCompleted.Set();
-
- void LogMessage(string text)
- {
- Console.WriteLine($"[Simulated process thread: {Thread.CurrentThread.ManagedThreadId}] {text}");
- }
- }
- }
- }
-}
diff --git a/src/CFamily.UnitTests/CompilationDatabase/AggregatingCompilationDatabaseProviderTests.cs b/src/CFamily.UnitTests/CompilationDatabase/AggregatingCompilationDatabaseProviderTests.cs
new file mode 100644
index 0000000000..f4924fed0b
--- /dev/null
+++ b/src/CFamily.UnitTests/CompilationDatabase/AggregatingCompilationDatabaseProviderTests.cs
@@ -0,0 +1,89 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+using NSubstitute.ReturnsExtensions;
+using SonarLint.VisualStudio.CFamily.CMake;
+using SonarLint.VisualStudio.CFamily.CompilationDatabase;
+using SonarLint.VisualStudio.Core.CFamily;
+using SonarLint.VisualStudio.TestInfrastructure;
+
+namespace SonarLint.VisualStudio.CFamily.UnitTests.CompilationDatabase;
+
+[TestClass]
+public class AggregatingCompilationDatabaseProviderTests
+{
+ private ICMakeCompilationDatabaseLocator cmake;
+ private IVCXCompilationDatabaseProvider vcx;
+ private AggregatingCompilationDatabaseProvider testSubject;
+
+ [TestMethod]
+ public void MefCtor_CheckIsExported() =>
+ MefTestHelpers.CheckTypeCanBeImported(
+ MefTestHelpers.CreateExport(),
+ MefTestHelpers.CreateExport());
+
+ [TestMethod]
+ public void MefCtor_CheckIsSingleton() => MefTestHelpers.CheckIsSingletonMefComponent();
+
+ [TestInitialize]
+ public void TestInitialize()
+ {
+ cmake = Substitute.For();
+ vcx = Substitute.For();
+ testSubject = new AggregatingCompilationDatabaseProvider(cmake, vcx);
+ }
+
+ [TestMethod]
+ public void GetOrNull_CmakeAvailable_ReturnsCmakeLocation()
+ {
+ var location = "some location";
+ cmake.Locate().Returns(location);
+
+ var result = testSubject.GetOrNull("some path");
+
+ result.Should().BeOfType().And.BeEquivalentTo(new ExternalCompilationDatabaseHandle(location));
+ vcx.DidNotReceiveWithAnyArgs().CreateOrNull(default);
+ }
+
+ [TestMethod]
+ public void GetOrNull_CmakeUnavailable_VcxAvailable_ReturnsVcxLocation()
+ {
+ var sourcePath = "some path";
+ var location = Substitute.For();
+ cmake.Locate().ReturnsNull();
+ vcx.CreateOrNull(sourcePath).Returns(location);
+
+ var result = testSubject.GetOrNull(sourcePath);
+
+ result.Should().Be(location);
+ cmake.Received().Locate();
+ }
+
+ [TestMethod]
+ public void GetOrNull_Unavailable_ReturnsNull()
+ {
+ cmake.Locate().ReturnsNull();
+ vcx.CreateOrNull(default).ReturnsNullForAnyArgs();
+
+ var result = testSubject.GetOrNull("some path");
+
+ result.Should().BeNull();
+ }
+}
diff --git a/src/CFamily.UnitTests/CompilationDatabase/CompilationDatabaseRequestTests.cs b/src/CFamily.UnitTests/CompilationDatabase/CompilationDatabaseRequestTests.cs
deleted file mode 100644
index 72b0599776..0000000000
--- a/src/CFamily.UnitTests/CompilationDatabase/CompilationDatabaseRequestTests.cs
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * SonarLint for Visual Studio
- * Copyright (C) 2016-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Moq;
-using SonarLint.VisualStudio.CFamily.Analysis;
-using SonarLint.VisualStudio.CFamily.CMake;
-using SonarLint.VisualStudio.CFamily.Helpers.UnitTests;
-using SonarLint.VisualStudio.CFamily.Rules;
-using SonarLint.VisualStudio.CFamily.SubProcess;
-
-namespace SonarLint.VisualStudio.CFamily.CompilationDatabase.UnitTests
-{
- [TestClass]
- public class CompilationDatabaseRequestTests
- {
- private readonly RequestContext ValidContext = new RequestContext("cpp", Mock.Of(), "file.txt", "pchFile.txt", null, false);
- private readonly CompilationDatabaseEntry ValidDbEntry = new CompilationDatabaseEntry { File = "file.txt", Directory = "c:\\", Command = "a command" };
- private readonly IReadOnlyDictionary ValidEnvVars = new Dictionary { { "key1", "value1" } };
-
- [TestMethod]
- public void Ctor_InvalidArguments_Throws()
- {
- Action act = () => new CompilationDatabaseRequest(null, ValidContext, ValidEnvVars);
- act.Should().ThrowExactly().And.ParamName.Should().Be("databaseEntry");
-
- act = () => new CompilationDatabaseRequest(ValidDbEntry, null, ValidEnvVars);
- act.Should().ThrowExactly().And.ParamName.Should().Be("context");
- }
-
- [TestMethod]
- public void Ctor_NullEnvVars_DoesNotThrow()
- {
- var testSubject = new CompilationDatabaseRequest(ValidDbEntry, ValidContext, null);
- testSubject.EnvironmentVariables.Should().BeNull();
- }
-
- [TestMethod]
- [DataRow(null, "args")]
- [DataRow("", "args")]
- [DataRow("cmd", null)]
- [DataRow("cmd", "")]
- public void Ctor_ValidCommandArgsCombination_ShouldNotThrow(string command, string args)
- {
- var dbEntry = new CompilationDatabaseEntry
- {
- File = "file",
- Directory = "dir",
- Command = command,
- Arguments = args
- };
-
- Action act = () => new CompilationDatabaseRequest(dbEntry, ValidContext, ValidEnvVars);
- act.Should().NotThrow();
- }
-
- [TestMethod]
- [DataRow(null, null)]
- [DataRow("", "")]
- [DataRow(null, "")]
- [DataRow("", null)]
- [DataRow("command", "args")] // can't have both
- public void Ctor_InvalidCommandArgsCombination_ShouldThrow(string command, string args)
- {
- var dbEntry = new CompilationDatabaseEntry
- {
- File = "file",
- Directory = "dir",
- Command = command,
- Arguments = args
- };
-
- Action act = () => new CompilationDatabaseRequest(dbEntry, ValidContext, ValidEnvVars);
- act.Should().ThrowExactly();
- }
-
- [TestMethod]
- public void WriteRequest_HeaderFile_WritesTheFileFromContext()
- {
- var dbEntry = new CompilationDatabaseEntry { File = "file.cpp", Directory = "c:\\aaa", Command = "any" };
- var context = new RequestContext("any", Mock.Of(), "file.h", "d:\\preamble.txt", null, true);
-
- var tokens = WriteRequest(dbEntry, context);
-
- // File name should be taken from context, to support header files
- CheckExpectedSetting(tokens, "File", "file.h");
- }
-
- [TestMethod]
- public void WriteRequest_HeaderFile_WritesHeaderFileLanguage()
- {
- var dbEntry = new CompilationDatabaseEntry { File = "file.cpp", Directory = "c:\\aaa", Command = "any" };
- var context = new RequestContext("any.language", Mock.Of(), "file.h", "d:\\preamble.txt", null, true);
-
- var tokens = WriteRequest(dbEntry, context);
-
- CheckExpectedSetting(tokens, "HeaderFileLanguage", "any.language");
- }
-
- [TestMethod]
- public void WriteRequest_NotHeaderFile_HeaderFileLanguageIsNotWritten()
- {
- var dbEntry = new CompilationDatabaseEntry { File = "file.cpp", Directory = "c:\\aaa", Command = "any" };
- var context = new RequestContext("any.language", Mock.Of(), "file.cpp", "d:\\preamble.txt", null, false);
-
- var tokens = WriteRequest(dbEntry, context);
-
- CheckSettingDoesNotExist(tokens, "HeaderFileLanguage");
- }
-
- [TestMethod]
- public void WriteRequest_ValidRequest_ExpectedHeaderFooterAndSimpleProperties()
- {
- var dbEntry = new CompilationDatabaseEntry { File = "file.txt", Directory = "c:\\aaa", Command = "any" };
- var context = new RequestContext("any", Mock.Of(), "file.h", "d:\\preamble.txt", null, true);
-
- var tokens = WriteRequest(dbEntry, context);
-
- // Header and footer
- tokens.First().Should().Be("SL-IN");
- tokens.Last().Should().Be("SL-END");
-
- // Simple properties i.e. ones that are just written as-is
- CheckExpectedSetting(tokens, "File", "file.h");
- CheckExpectedSetting(tokens, "Directory", "c:\\aaa");
- CheckExpectedSetting(tokens, "PreambleFile", "d:\\preamble.txt");
- }
-
- [TestMethod]
- public void WriteRequest_WithCommand_ExpectedSettingWritten()
- {
- var dbEntry = new CompilationDatabaseEntry { File = "file.txt", Directory = "c:\\aaa", Command = "cmd1 cmd2" };
-
- var tokens = WriteRequest(dbEntry, ValidContext);
-
- CheckExpectedSetting(tokens, "Command", "cmd1 cmd2");
- CheckSettingDoesNotExist(tokens, "Arguments");
- }
-
- [TestMethod]
- public void WriteRequest_WithArguments_ExpectedSettingWritten()
- {
- var dbEntry = new CompilationDatabaseEntry { File = "file.txt", Directory = "c:\\aaa", Arguments = "arg1\narg2" };
-
- var tokens = WriteRequest(dbEntry, ValidContext);
-
- CheckExpectedSetting(tokens, "Arguments", "arg1\narg2");
- CheckSettingDoesNotExist(tokens, "Commands");
- }
-
- [TestMethod]
- [DataRow(true, "true")]
- [DataRow(false, "false")]
- public void WriteRequest_CreateReproducer_ExpectedSettingWritten(bool createReproducer, string expectedValue)
- {
- var analyzerOptions = new CFamilyAnalyzerOptions { CreateReproducer = createReproducer };
- var context = CreateContext(analyzerOptions: analyzerOptions);
-
- var tokens = WriteRequest(ValidDbEntry, context);
-
- CheckExpectedSetting(tokens, "CreateReproducer", expectedValue);
- }
-
- [TestMethod]
- [DataRow(true, "true")]
- [DataRow(false, "false")]
- public void WriteRequest_CreatePreamble_ExpectedSettingWritten(bool createPch, string expectedValue)
- {
- var rulesConfig = new DummyCFamilyRulesConfig("cpp")
- .AddRule("active1", isActive: true);
-
- var analyzerOptions = new CFamilyAnalyzerOptions { CreatePreCompiledHeaders = createPch };
- var context = CreateContext(rulesConfig: rulesConfig, analyzerOptions: analyzerOptions);
-
- var tokens = WriteRequest(ValidDbEntry, context);
-
- CheckExpectedSetting(tokens, "BuildPreamble", expectedValue);
-
- if (createPch)
- {
- CheckExpectedSetting(tokens, "QualityProfile", string.Empty);
- }
- else
- {
- CheckExpectedSetting(tokens, "QualityProfile", "active1");
- }
- }
-
- [TestMethod]
- public void WriteRequest_QualityProfile_ExpectedSettingWritten()
- {
- var rulesConfig = new DummyCFamilyRulesConfig("cpp")
- .AddRule("inactive1", isActive: false)
- .AddRule("active1", isActive: true)
- .AddRule("active2", isActive: true)
- .AddRule("inactive2", isActive: false);
-
- var context = CreateContext(rulesConfig: rulesConfig);
-
- var tokens = WriteRequest(ValidDbEntry, context);
-
- CheckExpectedSetting(tokens, "QualityProfile", "active1,active2");
- }
-
- [TestMethod]
- public void WriteRequest_WithRuleParameters_ExpectedSettingWritten()
- {
- var rulesConfig = new DummyCFamilyRulesConfig("cpp")
- .AddRule("inactive1", isActive: false,
- parameters: new Dictionary
- {
- { "XXX1", "VVV1"}
- })
-
- // Active rule with no parameters
- .AddRule("active1", isActive: true)
-
- // Active rule, one parameter
- .AddRule("active2", isActive: true,
- parameters: new Dictionary
- {
- { "key2_1", "value2_1" }
- })
-
- .AddRule("inactive2", isActive: false,
- parameters: new Dictionary
- {
- { "XXX2", "VVV2"},
- { "XXX3", "VVV3"}
- })
-
- // Active rule, multiple parameters
- .AddRule("active3", isActive: true,
- parameters: new Dictionary
- {
- { "key3_1", "value3_1" },
- { "key3_2", "value3_2" }
- });
-
- var context = CreateContext(rulesConfig: rulesConfig);
-
- var tokens = WriteRequest(ValidDbEntry, context);
-
- CheckExpectedSetting(tokens, "active2.key2_1", "value2_1");
- CheckExpectedSetting(tokens, "active3.key3_1", "value3_1");
- CheckExpectedSetting(tokens, "active3.key3_2", "value3_2");
-
- CheckSettingDoesNotExist(tokens, "inactive1");
- CheckSettingDoesNotExist(tokens, "inactive2");
- CheckSettingDoesNotExist(tokens, "active1");
- CheckSettingDoesNotExist(tokens, "active4");
-
- }
-
- [TestMethod]
- public void WriteRequest_NoRuleParameters_NoErrors()
- {
- // Active rules with no parameters
- var rulesConfig = new DummyCFamilyRulesConfig("cpp")
- .AddRule("active1", isActive: true)
- .AddRule("active2", isActive: true);
-
- var context = CreateContext(rulesConfig: rulesConfig);
-
- var tokens = WriteRequest(ValidDbEntry, context);
-
- tokens.Where(x => x.StartsWith("active1.")).Should().BeEmpty();
- tokens.Where(x => x.StartsWith("active2.")).Should().BeEmpty();
- }
-
- [TestMethod]
- public void WriteDiagnostics_ExpectedDataWritten()
- {
- // Expecting the context to be ignored
- var context = CreateContext("foo", Mock.Of(), "some file", "some pch file",
- new CFamilyAnalyzerOptions { CreatePreCompiledHeaders = true });
-
- var dbEntry = new CompilationDatabaseEntry
- {
- File = "c:\\file.txt", Directory = "d:\\", Command = "1\n2\n"
- };
- var expected = @"{
- ""directory"": ""d:\\"",
- ""command"": ""1\n2\n"",
- ""file"": ""c:\\file.txt"",
- ""arguments"": null
-}";
-
- var testSubject = new CompilationDatabaseRequest(dbEntry, context, ValidEnvVars);
-
- var sb = new StringBuilder();
- using (var writer = new StringWriter(sb))
- {
- testSubject.WriteRequestDiagnostics(writer);
- };
-
- var actual = sb.ToString();
- actual.Should().Be(expected);
- }
-
- [TestMethod]
- public void EnvironmentVariables_ReturnsExpectedValues()
- {
- var envVars = new Dictionary { { "INCLUDE", "" }, { "PATH", "any"} };
- var testSubject = new CompilationDatabaseRequest(ValidDbEntry, ValidContext, envVars);
-
- var actual = testSubject.EnvironmentVariables;
-
- actual.Count.Should().Be(2);
- actual.Keys.Should().BeEquivalentTo("INCLUDE", "PATH");
- actual["INCLUDE"].Should().BeEmpty();
- actual["PATH"].Should().Be("any");
- }
-
- private static RequestContext CreateContext(
- string language = "c",
- ICFamilyRulesConfig rulesConfig = null,
- string file = "file.txt",
- string pchFile = "pch.txt",
- CFamilyAnalyzerOptions analyzerOptions = null)
- {
- return new RequestContext(
- language: language,
- rulesConfig: rulesConfig ?? Mock.Of(),
- file: file,
- pchFile: pchFile,
- analyzerOptions: analyzerOptions, false);
- }
-
- ///
- /// Executes the request, and returns the ordered list of strings that were
- /// written to the binary stream
- ///
- private IList WriteRequest(CompilationDatabaseEntry dbEntry, RequestContext context)
- {
- var tokens = new List();
-
- var testSubject = new CompilationDatabaseRequest(dbEntry, context, ValidEnvVars);
-
- using (var stream = new MemoryStream())
- {
- using (var writer = new BinaryWriter(stream, Encoding.UTF8, leaveOpen: true))
- {
- testSubject.WriteRequest(writer);
- }
- stream.Flush();
- var endOfStreamPosition = stream.Position;
- stream.Position = 0;
-
- using (var reader = new BinaryReader(stream))
- {
- while(stream.Position != endOfStreamPosition)
- {
- tokens.Add(Protocol.ReadUTF(reader));
- }
- }
- }
-
- return tokens;
- }
-
- private void CheckExpectedSetting(IList tokens, string key, string value)
- {
- var keyIndex = tokens.IndexOf(key);
- keyIndex.Should().NotBe(-1);
- keyIndex.Should().NotBe(tokens.Count - 2);
- tokens[keyIndex + 1].Should().Be(value);
- }
-
- private void CheckSettingDoesNotExist(IList tokens, string key) =>
- tokens.IndexOf(key).Should().Be(-1);
- }
-}
diff --git a/src/CFamily.UnitTests/CompilationDatabase/ExternalCompilationDatabaseHandleTests.cs b/src/CFamily.UnitTests/CompilationDatabase/ExternalCompilationDatabaseHandleTests.cs
new file mode 100644
index 0000000000..5dcf3b4826
--- /dev/null
+++ b/src/CFamily.UnitTests/CompilationDatabase/ExternalCompilationDatabaseHandleTests.cs
@@ -0,0 +1,52 @@
+/*
+ * SonarLint for Visual Studio
+ * Copyright (C) 2016-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+using SonarLint.VisualStudio.CFamily.CompilationDatabase;
+
+namespace SonarLint.VisualStudio.CFamily.UnitTests.CompilationDatabase;
+
+[TestClass]
+public class ExternalCompilationDatabaseHandleTests
+{
+ [TestMethod]
+ public void Ctor_AssignsExpectedValues()
+ {
+ const string filePath = "some path";
+ var testSubject = new ExternalCompilationDatabaseHandle(filePath);
+
+ testSubject.FilePath.Should().BeSameAs(filePath);
+ }
+
+ [TestMethod]
+ public void Ctor_NullPath_Throws()
+ {
+ var act = () => new ExternalCompilationDatabaseHandle(null);
+
+ act.Should().Throw().Which.ParamName.Should().Be("filePath");
+ }
+
+ [TestMethod]
+ public void Dispose_NoOp_DoesNotThrow()
+ {
+ var act = () => new ExternalCompilationDatabaseHandle("some path").Dispose();
+
+ act.Should().NotThrow();
+ }
+}
diff --git a/src/CFamily.UnitTests/CompilationDatabase/RulesConfigProtocolFormatterTests.cs b/src/CFamily.UnitTests/CompilationDatabase/RulesConfigProtocolFormatterTests.cs
deleted file mode 100644
index 8d237329fd..0000000000
--- a/src/CFamily.UnitTests/CompilationDatabase/RulesConfigProtocolFormatterTests.cs
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * SonarLint for Visual Studio
- * Copyright (C) 2016-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-using System;
-using System.Collections.Generic;
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using SonarLint.VisualStudio.CFamily.Helpers.UnitTests;
-
-namespace SonarLint.VisualStudio.CFamily.CompilationDatabase.UnitTests
-{
- [TestClass]
- public class RulesConfigProtocolFormatterTests
- {
- [TestMethod]
- public void Format_NullRulesConfig_ArgumentNullException()
- {
- var testSubject = CreateTestSubject();
-
- Action act = () => testSubject.Format(null);
-
- act.Should().Throw().And.ParamName.Should().Be("rulesConfig");
- }
-
- [TestMethod]
- public void Format_NoRules_EmptyQualityProfile()
- {
- var rulesConfig = new DummyCFamilyRulesConfig("cpp");
-
- var testSubject = CreateTestSubject();
- var result = testSubject.Format(rulesConfig);
-
- result.QualityProfile.Should().BeEmpty();
- }
-
- [TestMethod]
- public void Format_NoActiveRules_EmptyQualityProfile()
- {
- var rulesConfig = new DummyCFamilyRulesConfig("cpp");
- rulesConfig.AddRule("123", false);
-
- var testSubject = CreateTestSubject();
- var result = testSubject.Format(rulesConfig);
-
- result.QualityProfile.Should().BeEmpty();
- }
-
- [TestMethod]
- public void Format_OneActiveRule_OneRuleInQualityProfile()
- {
- var rulesConfig = new DummyCFamilyRulesConfig("cpp");
- rulesConfig.AddRule("123", true);
-
- var testSubject = CreateTestSubject();
- var result = testSubject.Format(rulesConfig);
-
- result.QualityProfile.Should().Be("123");
- }
-
- [TestMethod]
- public void Format_MultipleActiveRules_CommaSeparatedQualityProfile()
- {
- var rulesConfig = new DummyCFamilyRulesConfig("cpp");
- rulesConfig.AddRule("12", true);
- rulesConfig.AddRule("34", false);
- rulesConfig.AddRule("56", true);
- rulesConfig.AddRule("78", false);
-
- var testSubject = CreateTestSubject();
- var result = testSubject.Format(rulesConfig);
-
- result.QualityProfile.Should().Be("12,56");
- }
-
- [TestMethod]
- public void Format_NoRules_EmptyRuleParameters()
- {
- var rulesConfig = new DummyCFamilyRulesConfig("cpp");
-
- var testSubject = CreateTestSubject();
- var result = testSubject.Format(rulesConfig);
-
- result.RuleParameters.Should().BeEmpty();
- }
-
- [TestMethod]
- public void Format_MultipleRules_DotSeparatedParametersForActiveRules()
- {
- var rulesConfig = new DummyCFamilyRulesConfig("cpp");
-
- rulesConfig.AddRule("rule1", true, new Dictionary
- {
- {"param1", "some value"},
- {"param2", "some other value"}
- });
-
- // inactive rules should be ignored
- rulesConfig.AddRule("inactive", false, new Dictionary
- {
- {"param3", "value3"},
- {"param4", "value4"}
- });
-
- rulesConfig.AddRule("rule2", true, new Dictionary
- {
- {"some param", "value1"},
- {"some other param", "value2"}
- });
-
- var testSubject = CreateTestSubject();
- var result = testSubject.Format(rulesConfig);
-
- result.RuleParameters.Should().BeEquivalentTo(new Dictionary
- {
- {"rule1.param1", "some value"},
- {"rule1.param2", "some other value"},
- {"rule2.some param", "value1"},
- {"rule2.some other param", "value2"}
- });
- }
-
- private RulesConfigProtocolFormatter CreateTestSubject() => new RulesConfigProtocolFormatter();
- }
-}
diff --git a/src/CFamily.UnitTests/Helpers/DummyCFamilyRulesConfig.cs b/src/CFamily.UnitTests/Helpers/DummyCFamilyRulesConfig.cs
deleted file mode 100644
index d5d9824f9e..0000000000
--- a/src/CFamily.UnitTests/Helpers/DummyCFamilyRulesConfig.cs
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * SonarLint for Visual Studio
- * Copyright (C) 2016-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-using System.Collections.Generic;
-using System.Linq;
-using SonarLint.VisualStudio.CFamily.Rules;
-using SonarLint.VisualStudio.Core;
-using SonarLint.VisualStudio.Core.UserRuleSettings;
-
-namespace SonarLint.VisualStudio.CFamily.Helpers.UnitTests
-{
- public class DummyCFamilyRulesConfig : ICFamilyRulesConfig
- {
- private readonly IDictionary ruleKeyToActiveMap;
-
- public DummyCFamilyRulesConfig(string languageKey)
- {
- LanguageKey = languageKey;
- ruleKeyToActiveMap = new Dictionary();
- }
-
- public DummyCFamilyRulesConfig AddRule(string partialRuleKey, IssueSeverity issueSeverity, bool isActive, Code code)
- {
- return AddRule(partialRuleKey, issueSeverity, isActive, null, code);
- }
-
- public DummyCFamilyRulesConfig AddRule(string partialRuleKey, bool isActive)
- {
- ruleKeyToActiveMap[partialRuleKey] = isActive;
- RulesMetadata[partialRuleKey] = new RuleMetadata();
- return this;
- }
-
- public DummyCFamilyRulesConfig AddRule(string partialRuleKey, bool isActive, Dictionary parameters)
- {
- return AddRule(partialRuleKey, (IssueSeverity)0 /* default enum value */, isActive, parameters, new Code());
- }
-
- public DummyCFamilyRulesConfig AddRule(string partialRuleKey, IssueSeverity issueSeverity, bool isActive, Dictionary parameters, Code code)
- {
- ruleKeyToActiveMap[partialRuleKey] = isActive;
- RulesMetadata[partialRuleKey] = new RuleMetadata { DefaultSeverity = issueSeverity, Code = code };
-
- if (parameters != null)
- {
- RulesParameters[partialRuleKey] = parameters;
- }
- return this;
- }
-
- #region IRulesConfiguration interface
-
- public string LanguageKey { get; set; }
-
- public IEnumerable AllPartialRuleKeys => ruleKeyToActiveMap.Keys;
-
- public IEnumerable ActivePartialRuleKeys => ruleKeyToActiveMap.Where(kvp => kvp.Value)
- .Select(kvp => kvp.Key)
- .ToList();
-
- public IDictionary> RulesParameters { get; set; }
- = new Dictionary>();
-
- public IDictionary RulesMetadata { get; set; }
- = new Dictionary();
-
- #endregion
- }
-}
diff --git a/src/CFamily.UnitTests/Helpers/DummyExeHelper.cs b/src/CFamily.UnitTests/Helpers/DummyExeHelper.cs
deleted file mode 100644
index b07c69f864..0000000000
--- a/src/CFamily.UnitTests/Helpers/DummyExeHelper.cs
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * SonarLint for Visual Studio
- * Copyright (C) 2016-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-using System;
-using System.CodeDom.Compiler;
-using System.IO;
-using FluentAssertions;
-using Microsoft.CSharp;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-// Note: copied from the S4MSB
-// https://github.com/SonarSource/sonar-scanner-msbuild/blob/5c23a7da9171e90a1970a31507dce3da3e8ee094/Tests/TestUtilities/DummyExeHelper.cs#L34
-
-namespace SonarLint.VisualStudio.CFamily.Helpers.UnitTests
-{
- ///
- /// Creates dummy executables that log the input parameters and return a specified
- /// exit code
- ///
- internal static class DummyExeHelper
- {
- private const string DummyExeName = "dummy.exe";
-
- #region Public methods
-
- public static string CreateDummyExe(string outputDir, string exeName, int exitCode)
- {
- return CreateDummyExe(outputDir, exeName, exitCode, null);
- }
-
- public static string CreateDummyExe(string outputDir, string exeName, int exitCode, string additionalCode)
- {
- var code = GetDummyExeSource(exitCode, additionalCode);
- var asmPath = Path.Combine(outputDir, exeName);
- CompileAssembly(code, asmPath);
- return asmPath;
- }
-
- public static string CreateDummyExe(string outputDir, int exitCode)
- {
- return CreateDummyExe(outputDir, DummyExeName, exitCode, null);
- }
-
- #endregion Public methods
-
- #region Checks
-
- public static string AssertDummyExeLogExists(string dummyBinDir, TestContext testContext)
- {
- var logFilePath = GetLogFilePath(dummyBinDir, DummyExeName);
- return AssertLogFileExists(logFilePath, testContext);
- }
-
-
- public static string GetLogFilePath(string dummyBinDir, string exeName)
- {
- var logFilePath = Path.Combine(dummyBinDir, exeName);
- logFilePath = Path.ChangeExtension(logFilePath, ".log");
- return logFilePath;
- }
-
- public static void AssertExpectedLogContents(string logPath, params string[] expected)
- {
- File.Exists(logPath).Should().BeTrue("Expected log file does not exist: {0}", logPath);
-
- var actualLines = File.ReadAllLines(logPath);
-
- (expected ?? new string[] { }).Should().BeEquivalentTo(actualLines, "Log file does not have the expected content");
- }
-
- public static string AssertLogFileExists(string logFilePath, TestContext testContext)
- {
- File.Exists(logFilePath).Should().BeTrue("Expecting the dummy exe log to exist. File: {0}", logFilePath);
- testContext.AddResultFile(logFilePath);
- return logFilePath;
- }
-
- public static string AssertLogFileDoesNotExist(string dummyBinDir, string exeName)
- {
- var logFilePath = GetLogFilePath(dummyBinDir, exeName);
-
- File.Exists(logFilePath).Should().BeFalse("Not expecting the dummy exe log to exist. File: {0}", logFilePath);
- return logFilePath;
- }
-
- #endregion Checks
-
- #region Private methods
-
- private static string GetDummyExeSource(int returnCode, string additionalCode)
- {
- string code = @"
-using System;
-using System.IO;
-
-namespace SonarQube.Bootstrapper.Tests.Dummy
-{
- class Program
- {
- static int Main(string[] args)
- {
- string logFile = Path.ChangeExtension(Path.Combine(typeof(Program).Assembly.Location), ""log"");
-
- File.WriteAllLines(logFile, args);
-
- int exitCode = EXITCODE_PLACEHOLDER;
-
- ADDITIONALCODE_PLACEHOLDER
-
- return exitCode;
- }
- }
-}";
- code = code.Replace("EXITCODE_PLACEHOLDER", returnCode.ToString());
- code = code.Replace("ADDITIONALCODE_PLACEHOLDER", additionalCode);
- return code;
- }
-
- ///
- /// Compiles the supplied code into a new assembly
- ///
- private static void CompileAssembly(string code, string outputFilePath)
- {
- var provider = new CSharpCodeProvider();
-
- var options = new CompilerParameters
- {
- OutputAssembly = outputFilePath,
- GenerateExecutable = true,
- GenerateInMemory = false
- };
-
- var result = provider.CompileAssemblyFromSource(options, code);
-
- if (result.Errors.Count > 0)
- {
- foreach(var item in result.Output)
- {
- Console.WriteLine(item);
- }
-
- Assert.Fail("Test setup error: failed to create dynamic assembly. See the test output for compiler output");
- }
- }
-
- #endregion Private methods
- }
-}
diff --git a/src/CFamily.UnitTests/IntegrationTests/CFamily_CLangAnalyzer_IntegrationTests.cs b/src/CFamily.UnitTests/IntegrationTests/CFamily_CLangAnalyzer_IntegrationTests.cs
deleted file mode 100644
index be98c6589e..0000000000
--- a/src/CFamily.UnitTests/IntegrationTests/CFamily_CLangAnalyzer_IntegrationTests.cs
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * SonarLint for Visual Studio
- * Copyright (C) 2016-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.IO;
-using System.IO.Abstractions;
-using System.Linq;
-using System.Threading;
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Newtonsoft.Json;
-using SonarLint.VisualStudio.CFamily.Analysis;
-using SonarLint.VisualStudio.CFamily.CMake;
-using SonarLint.VisualStudio.CFamily.CompilationDatabase;
-using SonarLint.VisualStudio.CFamily.Helpers.UnitTests;
-using SonarLint.VisualStudio.CFamily.Rules;
-using SonarLint.VisualStudio.CFamily.SubProcess;
-using SonarLint.VisualStudio.Core;
-using SonarLint.VisualStudio.TestInfrastructure;
-
-namespace SonarLint.VisualStudio.CFamily.IntegrationTests
-{
- [TestClass]
- public class CFamily_CLangAnalyzer_IntegrationTests
- {
- private string testsDataDirectory;
- private string clExe;
-
- [TestInitialize]
- public void TestInitialize()
- {
- // Uri absolute path is used to make issues filename slashes consistent between expected and actual
- testsDataDirectory = new Uri(Path.Combine(
- Path.GetDirectoryName(typeof(CFamily_CLangAnalyzer_IntegrationTests).Assembly.Location),
- "IntegrationTests\\")).AbsolutePath;
-
- // Subprocess.exe requires a valid path to an executable named cl.exe that prints something similar to the real compiler
- const string code = "Console.Error.WriteLine(\"Microsoft(R) C / C++ Optimizing Compiler Version 19.32.31114.2 for x64\");";
- clExe = DummyExeHelper.CreateDummyExe(testsDataDirectory, "cl.exe", 0, code);
- }
-
- [TestMethod]
- [DataRow("CLangAnalyzerTestFile_NoIssues_EmptyFile")]
- [DataRow("CLangAnalyzerTestFile_OneIssue")]
- [DataRow("CLangAnalyzerTestFile_TwoIssues")]
- [DataRow("CLangAnalyzerTestFile_OneIssue_HasSecondaryLocations")]
- public void CallAnalyzer_IntegrationTest(string testCaseFileName)
- {
- var testedFile = Path.Combine(testsDataDirectory, testCaseFileName + ".txt").Replace('/', '\\');
-
- // Sanity checks to help with debugging on the CI machine
- CheckFileExists(testedFile);
- CheckRulesMetadataFilesExist();
-
- var request = GetRequest(testedFile);
- var expectedMessages = GetExpectedMessages(testCaseFileName, testedFile);
-
- var messages = InvokeAnalyzer(request);
-
- messages.Where(x => !string.IsNullOrEmpty(x.Filename)).Should().BeEquivalentTo(expectedMessages, e => e.WithStrictOrdering());
- }
-
- private static void CheckRulesMetadataFilesExist()
- {
- var libDirectory = CFamilyShared.CFamilyFilesDirectory;
- Console.WriteLine($"[TEST SETUP] Checking CFamily lib directory exists: {libDirectory}");
- Directory.Exists(libDirectory).Should().BeTrue($"[TEST SETUP ERROR] CFamily lib directory could not be found: {libDirectory}");
-
- CheckFileExists(Path.Combine(libDirectory, "Sonar_way_profile.json"));
- CheckFileExists(Path.Combine(libDirectory, "RulesList.json"));
- }
-
- private static void CheckFileExists(string fileName)
- {
- Console.WriteLine($"[TEST SETUP] Checking for required file: {fileName}");
- File.Exists(fileName).Should().BeTrue($"[TEST SETUP ERROR] Could not find required test input file: {fileName}");
- }
-
- private CompilationDatabaseRequest GetRequest(string testedFile)
- {
- var command = "\"" + clExe + "\" /TP " + testedFile;
- var compilationDatabaseEntry = new CompilationDatabaseEntry
- {
- Directory = testsDataDirectory,
- Command = command,
- File = testedFile
- };
-
- var envVars = new ReadOnlyDictionary(new Dictionary {
- { "INCLUDE", "" }
- });
-
- var languageKey = SonarLanguageKeys.CPlusPlus;
-
- var config = new CFamilySonarWayRulesConfigProvider(CFamilyShared.CFamilyFilesDirectory).GetRulesConfiguration("cpp");
- var context = new RequestContext(
- languageKey,
- config,
- testedFile,
- "",
- new CFamilyAnalyzerOptions(),
- false);
-
- var request = new CompilationDatabaseRequest(compilationDatabaseEntry, context, envVars);
-
- return request;
- }
-
- private Message[] GetExpectedMessages(string testFileName, string testedFile)
- {
- var expectedResponseJson = File.ReadAllText(Path.Combine(testsDataDirectory, testFileName + "_response.json"));
- var expectedResponse = JsonConvert.DeserializeObject(expectedResponseJson);
- var messages = expectedResponse.Messages;
- foreach (var expectedResponseMessage in messages)
- {
- expectedResponseMessage.Filename = testedFile;
-
- foreach (var messagePart in expectedResponseMessage.Parts)
- {
- messagePart.Filename = testedFile;
- }
- }
-
- return messages;
- }
-
- private static List InvokeAnalyzer(CompilationDatabaseRequest request)
- {
- var testLogger = new TestLogger(true);
- var processRunner = new ProcessRunner(new ConfigurableSonarLintSettings(), testLogger);
-
- var messages = new List();
- CLangAnalyzer.ExecuteSubProcess(messages.Add, request, processRunner, testLogger, CancellationToken.None, new FileSystem());
- messages = messages.Where(m => !m.RuleKey.StartsWith("internal.")).ToList();
- return messages;
- }
- }
-}
diff --git a/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_NoIssues_EmptyFile.txt b/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_NoIssues_EmptyFile.txt
deleted file mode 100644
index 5f282702bb..0000000000
--- a/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_NoIssues_EmptyFile.txt
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_NoIssues_EmptyFile_response.json b/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_NoIssues_EmptyFile_response.json
deleted file mode 100644
index 4643e632d3..0000000000
--- a/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_NoIssues_EmptyFile_response.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "Messages": []
-}
\ No newline at end of file
diff --git a/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_OneIssue.txt b/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_OneIssue.txt
deleted file mode 100644
index 48340c4e67..0000000000
--- a/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_OneIssue.txt
+++ /dev/null
@@ -1 +0,0 @@
-// todo: this line should raise an issue
diff --git a/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_OneIssue_HasSecondaryLocations.txt b/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_OneIssue_HasSecondaryLocations.txt
deleted file mode 100644
index d34294e6b0..0000000000
--- a/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_OneIssue_HasSecondaryLocations.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-void a(bool b) {
- int* f = nullptr;
- if (b) {
- *f = 2;
- }
-}
\ No newline at end of file
diff --git a/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_OneIssue_HasSecondaryLocations_response.json b/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_OneIssue_HasSecondaryLocations_response.json
deleted file mode 100644
index 069067e5e5..0000000000
--- a/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_OneIssue_HasSecondaryLocations_response.json
+++ /dev/null
@@ -1,49 +0,0 @@
-{
- "Messages": [
- {
- "Filename": "",
- "Fixes": [],
- "RuleKey": "S2259",
- "PartsMakeFlow": true,
- "Parts": [
- {
- "Filename": "",
- "Line": 4,
- "Column": 12,
- "EndLine": 4,
- "EndColumn": 13,
- "Text": "Dereference of null pointer (loaded from variable 'f')"
- },
- {
- "Filename": "",
- "Line": 3,
- "Column": 5,
- "EndLine": 3,
- "EndColumn": 7,
- "Text": "Taking true branch"
- },
- {
- "Filename": "",
- "Line": 3,
- "Column": 9,
- "EndLine": 3,
- "EndColumn": 10,
- "Text": "Assuming 'b' is true"
- },
- {
- "Filename": "",
- "Line": 2,
- "Column": 5,
- "EndLine": 2,
- "EndColumn": 11,
- "Text": "'f' initialized to a null pointer value"
- }
- ],
- "Line": 4,
- "Column": 12,
- "EndLine": 4,
- "EndColumn": 13,
- "Text": "Dereference of null pointer (loaded from variable 'f')"
- }
- ]
-}
\ No newline at end of file
diff --git a/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_OneIssue_response.json b/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_OneIssue_response.json
deleted file mode 100644
index 135b1bf28b..0000000000
--- a/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_OneIssue_response.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "Messages": [
- {
- "Filename": "",
- "Fixes": [],
- "RuleKey": "S1135",
- "PartsMakeFlow": false,
- "Parts": [],
- "Line": 1,
- "Column": 4,
- "EndLine": 1,
- "EndColumn": 44,
- "Text": "Complete the task associated to this \"todo\" comment."
- }
- ]
-}
\ No newline at end of file
diff --git a/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_TwoIssues.txt b/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_TwoIssues.txt
deleted file mode 100644
index 96fce12726..0000000000
--- a/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_TwoIssues.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-// todo: this line should raise an issue
- // todo: this other line should also raise an issue
diff --git a/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_TwoIssues_response.json b/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_TwoIssues_response.json
deleted file mode 100644
index e19277393f..0000000000
--- a/src/CFamily.UnitTests/IntegrationTests/CLangAnalyzerTestFile_TwoIssues_response.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "Messages": [
- {
- "Filename": "",
- "Fixes": [],
- "RuleKey": "S1135",
- "PartsMakeFlow": false,
- "Parts": [],
- "Line": 1,
- "Column": 4,
- "EndLine": 1,
- "EndColumn": 44,
- "Text": "Complete the task associated to this \"todo\" comment."
- },
- {
- "Filename": "",
- "Fixes": [],
- "RuleKey": "S1135",
- "PartsMakeFlow": false,
- "Parts": [],
- "Line": 2,
- "Column": 4,
- "EndLine": 2,
- "EndColumn": 55,
- "Text": "Complete the task associated to this \"todo\" comment."
- }
- ]
-}
\ No newline at end of file
diff --git a/src/CFamily.UnitTests/PreCompiledHeaders/PchCacheCleanerTests.cs b/src/CFamily.UnitTests/PreCompiledHeaders/PchCacheCleanerTests.cs
deleted file mode 100644
index 19e455dbd4..0000000000
--- a/src/CFamily.UnitTests/PreCompiledHeaders/PchCacheCleanerTests.cs
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * SonarLint for Visual Studio
- * Copyright (C) 2016-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.IO.Abstractions.TestingHelpers;
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace SonarLint.VisualStudio.CFamily.PreCompiledHeaders.UnitTests
-{
- [TestClass]
- public class PchCacheCleanerTests
- {
- private MockFileSystem fileSystemMock;
-
- [TestInitialize]
- public void TestInitialize()
- {
- fileSystemMock = new MockFileSystem();
- fileSystemMock.Directory.CreateDirectory("c:\\test\\pch");
- }
-
- [TestMethod]
- public void Cleanup_NoFilesInDirectory_NoException()
- {
- var testSubject = new PchCacheCleaner(fileSystemMock, "c:\\test\\pch\\myPch.abc");
-
- Action act = () => testSubject.Cleanup();
- act.Should().NotThrow();
- }
-
- [TestMethod]
- public void Cleanup_NoMatchingFilesInDirectory_NonMatchingFilesAreNotDeleted()
- {
- var nonMatchingFilePaths = new List
- {
- "c:\\test\\pch\\test.abc",
- "c:\\test\\pch\\myPch.ab",
- "c:\\test\\pch\\myPch.ab.c",
- "c:\\test\\pch\\myPch.abd",
- "c:\\test\\pch\\amyPch.abc",
- "c:\\test\\pch\\sub\\myPch.abc",
- "c:\\test\\myPch.abc"
- };
-
- foreach (var filePath in nonMatchingFilePaths)
- {
- fileSystemMock.AddFile(filePath, new MockFileData(""));
- }
-
- var testSubject = new PchCacheCleaner(fileSystemMock, "c:\\test\\pch\\myPch.abc");
- testSubject.Cleanup();
-
- fileSystemMock.AllFiles.Should().BeEquivalentTo(nonMatchingFilePaths);
- }
-
- [TestMethod]
- public void Cleanup_HasMatchingFilesInDirectory_MatchingFilesAreDeleted()
- {
- var matchingFilePaths = new List
- {
- "c:\\test\\pch\\myPch.abc",
- "c:\\test\\pch\\MYpch.aBC",
- "c:\\test\\pch\\myPch.abcd",
- "c:\\test\\pch\\myPch.abcd.e",
- "c:\\test\\pch\\myPch.abc.d",
- "c:\\test\\pch\\myPch.abc.d.e",
- "c:\\test\\pch\\myPch.abc.de.f",
- "c:\\test\\pch\\myPCH.ABC.d.E"
- };
-
- foreach (var filePath in matchingFilePaths)
- {
- fileSystemMock.AddFile(filePath, new MockFileData(""));
- }
-
- var testSubject = new PchCacheCleaner(fileSystemMock, "c:\\test\\pch\\myPch.abc");
- testSubject.Cleanup();
-
- fileSystemMock.AllFiles.Should().BeEmpty();
- }
-
- [TestMethod]
- public void Cleanup_HasMatchingAndNonMatchingFilesInDirectory_OnlyMatchingFilesAreDeleted()
- {
- var matchingFile = "c:\\test\\pch\\myPch.abc.d";
- var nonMatchingFile = "c:\\test\\pch\\myPch.abd";
-
- fileSystemMock.AddFile(matchingFile, new MockFileData(""));
- fileSystemMock.AddFile(nonMatchingFile, new MockFileData(""));
-
- var testSubject = new PchCacheCleaner(fileSystemMock, "c:\\test\\pch\\myPch.abc");
- testSubject.Cleanup();
-
- fileSystemMock.AllFiles.Should().BeEquivalentTo(new List{nonMatchingFile});
- }
-
- [TestMethod]
- public void Cleanup_FailsToDeleteSomeFiles_DeletesTheOnesThatSucceed()
- {
- var matchingFile = "c:\\test\\pch\\myPch.abc.d";
- fileSystemMock.AddFile(matchingFile, new MockFileData(""));
-
- var matchingFailingFile = "c:\\test\\pch\\myPch.abc.de";
- var failingFileMockData = new MockFileData("")
- {
- AllowedFileShare = FileShare.None
- };
- fileSystemMock.AddFile(matchingFailingFile, failingFileMockData);
-
- var testSubject = new PchCacheCleaner(fileSystemMock, "c:\\test\\pch\\myPch.abc");
- testSubject.Cleanup();
-
- fileSystemMock.AllFiles.Should().BeEquivalentTo(new List { matchingFailingFile });
- }
- }
-}
diff --git a/src/CFamily.UnitTests/PreCompiledHeaders/PreCompiledHeadersEventListenerTests.cs b/src/CFamily.UnitTests/PreCompiledHeaders/PreCompiledHeadersEventListenerTests.cs
deleted file mode 100644
index cda4d7d644..0000000000
--- a/src/CFamily.UnitTests/PreCompiledHeaders/PreCompiledHeadersEventListenerTests.cs
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * SonarLint for Visual Studio
- * Copyright (C) 2016-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Microsoft.VisualStudio.Text;
-using Microsoft.VisualStudio.Utilities;
-using Moq;
-using SonarLint.VisualStudio.CFamily.Analysis;
-using SonarLint.VisualStudio.Core;
-using SonarLint.VisualStudio.Core.Analysis;
-using SonarLint.VisualStudio.Infrastructure.VS.DocumentEvents;
-using SonarLint.VisualStudio.IssueVisualization.Editor.LanguageDetection;
-
-namespace SonarLint.VisualStudio.CFamily.PreCompiledHeaders.UnitTests
-{
- [TestClass]
- public class PreCompiledHeadersEventListenerTests
- {
- private const string FocusedDocumentFilePath = "c:\\myfile.cpp";
- private readonly IContentType focusedDocumentContentType = Mock.Of();
-
- private Mock cFamilyAnalyzerMock;
- private Mock activeDocumentTrackerMock;
- private Mock schedulerMock;
- private Mock languageRecognizerMock;
- private Mock cacheCleanerMock;
-
- private PreCompiledHeadersEventListener testSubject;
-
- [TestInitialize]
- public void TestInitialize()
- {
- cFamilyAnalyzerMock = new Mock();
- activeDocumentTrackerMock = new Mock();
- schedulerMock = new Mock();
- languageRecognizerMock = new Mock();
- cacheCleanerMock = new Mock();
-
- var environmentSettingsMock = new Mock();
- environmentSettingsMock
- .Setup(x => x.PCHGenerationTimeoutInMs(It.IsAny()))
- .Returns(1);
-
- testSubject = new PreCompiledHeadersEventListener(cFamilyAnalyzerMock.Object, activeDocumentTrackerMock.Object, schedulerMock.Object, languageRecognizerMock.Object, environmentSettingsMock.Object, cacheCleanerMock.Object);
- }
-
- [TestMethod]
- public void Ctor_RegisterToDocumentFocusedEvent()
- {
- RaiseActiveDocumentChangedEvent();
-
- languageRecognizerMock.Verify(x => x.Detect(FocusedDocumentFilePath, focusedDocumentContentType), Times.Once);
- }
-
- [TestMethod]
- public void Dispose_UnregisterFromDocumentFocusedEvent()
- {
- testSubject.Dispose();
-
- RaiseActiveDocumentChangedEvent();
-
- cFamilyAnalyzerMock.VerifyNoOtherCalls();
- schedulerMock.VerifyNoOtherCalls();
- languageRecognizerMock.VerifyNoOtherCalls();
- }
-
- [TestMethod]
- public void Dispose_CleanupPchCache()
- {
- testSubject.Dispose();
-
- cacheCleanerMock.Verify(x=> x.Cleanup(), Times.Once);
- }
-
- [TestMethod]
- public void Dispose_ExceptionWhenCleaningCache_ExceptionCaught()
- {
- cacheCleanerMock.Setup(x => x.Cleanup()).Throws();
-
- Action act = () => testSubject.Dispose();
- act.Should().NotThrow();
- }
-
- [TestMethod]
- public void Dispose_CriticalExceptionWhenCleaningCache_ExceptionNotCaught()
- {
- cacheCleanerMock.Setup(x => x.Cleanup()).Throws();
-
- Action act = () => testSubject.Dispose();
- act.Should().ThrowExactly();
- }
-
- [TestMethod]
- public void OnDocumentFocused_NoLanguagesDetected_PchGenerationNotScheduled()
- {
- SetupDetectedLanguages(Enumerable.Empty());
-
- RaiseActiveDocumentChangedEvent();
-
- schedulerMock.VerifyNoOtherCalls();
- cFamilyAnalyzerMock.VerifyNoOtherCalls();
- }
-
- [TestMethod]
- public void OnDocumentFocused_LanguageIsUnsupported_PchGenerationNotScheduled()
- {
- var unsupportedLanguages = new List {AnalysisLanguage.Javascript};
-
- SetupDetectedLanguages(unsupportedLanguages);
-
- cFamilyAnalyzerMock.Setup(x => x.IsAnalysisSupported(unsupportedLanguages)).Returns(false).Verifiable();
-
- RaiseActiveDocumentChangedEvent();
-
- schedulerMock.VerifyNoOtherCalls();
- cFamilyAnalyzerMock.Verify();
- cFamilyAnalyzerMock.VerifyNoOtherCalls();
- }
-
- [TestMethod]
- public void OnDocumentFocused_LanguageIsSupported_SchedulePchGeneration()
- {
- var supportedLanguages = new List { AnalysisLanguage.CFamily };
-
- SetupDetectedLanguages(supportedLanguages);
-
- cFamilyAnalyzerMock.Setup(x => x.IsAnalysisSupported(supportedLanguages)).Returns(true);
-
- var cancellationToken = new CancellationTokenSource();
-
- schedulerMock
- .Setup(x=> x.Schedule(PreCompiledHeadersEventListener.PchJobId, It.IsAny