diff --git a/.editorconfig b/.editorconfig index 2b7c019..db932fc 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,12 +1,33 @@ root = true +[*] +end_of_line = CRLF + [*.{msbuild,xml}] charset = utf-8 -end_of_line = crlf insert_final_newline = true indent_style = space indent_size = 2 trim_trailing_whitespace = true [*.md] -indent_size = 4 \ No newline at end of file +indent_size = 4 + +[*.{config,cs,json}] +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +[*.{proj,props,sln,targets}] +indent_style = tab +trim_trailing_whitespace = true + +[*.{kproj,csproj,ps1,resx,rst}] +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + +[NuGet.Config] +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true \ No newline at end of file diff --git a/.gitignore b/.gitignore index 2ae903d..bb50c2a 100644 --- a/.gitignore +++ b/.gitignore @@ -230,3 +230,7 @@ _Pvt_Extensions # FAKE - F# Make .fake/ + +.idea/ +*.sln.iml +*.zip \ No newline at end of file diff --git a/Plugin/agent/bin/PvsStudioIssueTypes.xml b/Plugin/agent/bin/PvsStudioIssueTypes.xml index d943ac0..b1eff14 100644 --- a/Plugin/agent/bin/PvsStudioIssueTypes.xml +++ b/Plugin/agent/bin/PvsStudioIssueTypes.xml @@ -1,44 +1,59 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Plugin/agent/bin/ResharperReport.xslt b/Plugin/agent/bin/ResharperReport.xslt index a9a6c16..ee4b3e1 100644 --- a/Plugin/agent/bin/ResharperReport.xslt +++ b/Plugin/agent/bin/ResharperReport.xslt @@ -1,6 +1,7 @@  + @@ -14,10 +15,10 @@ Solution - - + + @@ -55,6 +56,38 @@ - - + + + + + + + + + + + + + + + + + + + + ERROR + + + + + + + + + + + + + + diff --git a/Plugin/server/metaRunners/MRPLUGIN_PvsStudioBuildRunnerPlugin.xml b/Plugin/server/metaRunners/MRPLUGIN_PvsStudioBuildRunnerPlugin.xml index d7c5aba..35e880d 100644 --- a/Plugin/server/metaRunners/MRPLUGIN_PvsStudioBuildRunnerPlugin.xml +++ b/Plugin/server/metaRunners/MRPLUGIN_PvsStudioBuildRunnerPlugin.xml @@ -6,12 +6,14 @@ + + diff --git a/Plugin/teamcity-plugin.xml b/Plugin/teamcity-plugin.xml index 7adf9f1..5764c8e 100644 --- a/Plugin/teamcity-plugin.xml +++ b/Plugin/teamcity-plugin.xml @@ -4,7 +4,7 @@ PvsStudioBuildRunnerPlugin PVS Studio Build Runner - snapshot + 1.1.0.0 Adds a PVS Studio Build Step option to TeamCity Ales Buzhynsky diff --git a/documents/releaseNotes/1.1.0.0.md b/documents/releaseNotes/1.1.0.0.md new file mode 100644 index 0000000..67bb1c3 --- /dev/null +++ b/documents/releaseNotes/1.1.0.0.md @@ -0,0 +1,18 @@ +#TeamCity PVS Studio Meta-Runner v1.1.0.0 + +##Changes: + +###Added grouping by category name and priority (e.g. PVS-Studio General Analysis Priority: 1) + +###Added possibility to treat priority 1 issues as errors +Now there is a checkbox in build step to toggle this behaviour. + +###Added PVS-Studio 6.01 inspections support + +###Added support of PVS-Studio next releases inspections +They will be displayed without category name in build results but with inspection Id and inspection message. + +##Update instructions: +1. Download 'pvs-studio-build-runner.zip' from the [latest release](https://github.com/abuzhynsky/teamcity-pvs-studio-meta-runner/releases/latest) +2. Copy this file into the _[Team City Data Directory]\plugins_ directory on the TeamCity Server, by default this is _C:\ProgramData\JetBrains\TeamCity\plugins_ or upload it using TeamCity 'Plugins List' tab (_Administration-Plugins List_) +3. Restart the Team City server \ No newline at end of file diff --git a/tests/TeamCity.PvsStudio.MetaRunner.Tests.sln b/tests/TeamCity.PvsStudio.MetaRunner.Tests.sln new file mode 100644 index 0000000..c3d7650 --- /dev/null +++ b/tests/TeamCity.PvsStudio.MetaRunner.Tests.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TeamCity.PvsStudio.MetaRunner.TestProject", "app\TeamCity.PvsStudio.MetaRunner.TestProject\TeamCity.PvsStudio.MetaRunner.TestProject.csproj", "{0C821208-FBE5-4421-826C-E9E22ADF7303}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TeamCity.PvsStudio.MetaRunner.Tests", "tests\TeamCity.PvsStudio.MetaRunner.Tests\TeamCity.PvsStudio.MetaRunner.Tests.csproj", "{282843E9-1846-4874-805A-5CCB59B3E633}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0C821208-FBE5-4421-826C-E9E22ADF7303}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C821208-FBE5-4421-826C-E9E22ADF7303}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C821208-FBE5-4421-826C-E9E22ADF7303}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C821208-FBE5-4421-826C-E9E22ADF7303}.Release|Any CPU.Build.0 = Release|Any CPU + {282843E9-1846-4874-805A-5CCB59B3E633}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {282843E9-1846-4874-805A-5CCB59B3E633}.Debug|Any CPU.Build.0 = Debug|Any CPU + {282843E9-1846-4874-805A-5CCB59B3E633}.Release|Any CPU.ActiveCfg = Release|Any CPU + {282843E9-1846-4874-805A-5CCB59B3E633}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/tests/TeamCity.PvsStudio.MetaRunner.Tests.sln.DotSettings b/tests/TeamCity.PvsStudio.MetaRunner.Tests.sln.DotSettings new file mode 100644 index 0000000..a038c82 --- /dev/null +++ b/tests/TeamCity.PvsStudio.MetaRunner.Tests.sln.DotSettings @@ -0,0 +1,2 @@ + + ExplicitlyExcluded \ No newline at end of file diff --git a/tests/app/TeamCity.PvsStudio.MetaRunner.TestProject/Class1.cs b/tests/app/TeamCity.PvsStudio.MetaRunner.TestProject/Class1.cs new file mode 100644 index 0000000..3ad86e9 --- /dev/null +++ b/tests/app/TeamCity.PvsStudio.MetaRunner.TestProject/Class1.cs @@ -0,0 +1,22 @@ +namespace TeamCity.PvsStudio.MetaRunner.TestProject +{ + public class Class1 + { + public void Method() + { + //intentionally made mistakes for PVS-Studio testing + var s = "qwerty"; + + string f = null; + + var a = 0; + + if (f == string.Empty || f == string.Empty) + { + a = 5; + } + + s.Replace("s", a.ToString()); + } + } +} diff --git a/tests/app/TeamCity.PvsStudio.MetaRunner.TestProject/Properties/AssemblyInfo.cs b/tests/app/TeamCity.PvsStudio.MetaRunner.TestProject/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8bf41d0 --- /dev/null +++ b/tests/app/TeamCity.PvsStudio.MetaRunner.TestProject/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("TeamCity.PvsStudio.MetaRunner.TestProject")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TeamCity.PvsStudio.MetaRunner.TestProject")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("0c821208-fbe5-4421-826c-e9e22adf7303")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/tests/app/TeamCity.PvsStudio.MetaRunner.TestProject/TeamCity.PvsStudio.MetaRunner.TestProject.csproj b/tests/app/TeamCity.PvsStudio.MetaRunner.TestProject/TeamCity.PvsStudio.MetaRunner.TestProject.csproj new file mode 100644 index 0000000..53edc62 --- /dev/null +++ b/tests/app/TeamCity.PvsStudio.MetaRunner.TestProject/TeamCity.PvsStudio.MetaRunner.TestProject.csproj @@ -0,0 +1,55 @@ + + + + + Debug + AnyCPU + {0C821208-FBE5-4421-826C-E9E22ADF7303} + Library + Properties + TeamCity.PvsStudio.MetaRunner.TestProject + TeamCity.PvsStudio.MetaRunner.TestProject + v4.6.1 + 512 + 1.0.0.0 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/Helpers/PluginParameters.cs b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/Helpers/PluginParameters.cs new file mode 100644 index 0000000..8a0bb1d --- /dev/null +++ b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/Helpers/PluginParameters.cs @@ -0,0 +1,101 @@ +using System; +using System.IO; +using System.Reflection; + +namespace TeamCity.PvsStudio.MetaRunner.Tests.Helpers +{ + public static class PluginParameters + { + public static string PvsStudioOutputPath + { + get { return Path.Combine(CurrentAssemblyPath, "temp", "result.xml"); } + } + + public static string XsltOutputPath + { + get { return Path.Combine(CurrentAssemblyPath, "temp", "resharperResult.xml"); } + } + + public static string PvsStudioConsolePath + { + get { return @"C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cs.exe"; } + } + + public static string MsXslPath + { + get { return Path.Combine(PluginPath, "msxsl.exe"); } + } + + public static string PvsStudioParameters + { + get { return $"-r -o {PvsStudioOutputPath} -t {SolutionPath}"; } + } + + public static string MsXslParameters + { + get { return GenerateXsltParameters(PvsStudioOutputPath, false); } + } + + public static string GenerateXsltParameters(string inputPath, bool treatPriority1IssuesAsErrors) + { + return $@"{inputPath} {XsltPath} -o {XsltOutputPath} treatPriority1IssuesAsErrors=""{Convert.ToInt32(treatPriority1IssuesAsErrors)}"""; + } + + public static string UnknownIssueTypeReportPath + { + get { return Path.Combine(CurrentAssemblyPath, "TestData", "UnknownIssueTypeReport.xml"); } + } + + private static string SolutionPath + { + get + { + var solutionDirectoryPath = GetParentDirectoryPath(CurrentAssemblyPath, 4); + + return Path.Combine(solutionDirectoryPath, "TeamCity.PvsStudio.MetaRunner.Tests.sln"); + } + } + + private static string PluginPath + { + get + { + var rootPath = GetParentDirectoryPath(CurrentAssemblyPath, 5); + + return Path.Combine(rootPath, "plugin", "agent", "bin"); + } + } + + private static string XsltPath + { + get { return Path.Combine(PluginPath, "ResharperReport.xslt"); } + } + + private static string CurrentAssemblyPath + { + get + { + var currentAssemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase); + + if (currentAssemblyPath == null) + { + throw new DirectoryNotFoundException(); + } + + return new Uri(currentAssemblyPath).LocalPath; + } + } + + private static string GetParentDirectoryPath(string directoryPath, int levelsUp) + { + var resultPath = directoryPath; + + for (var i = 0; i < levelsUp; i++) + { + resultPath = Directory.GetParent(resultPath).FullName; + } + + return resultPath; + } + } +} \ No newline at end of file diff --git a/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/Helpers/PvsStudioExpectedErrorCode.cs b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/Helpers/PvsStudioExpectedErrorCode.cs new file mode 100644 index 0000000..5cab4f6 --- /dev/null +++ b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/Helpers/PvsStudioExpectedErrorCode.cs @@ -0,0 +1,21 @@ +namespace TeamCity.PvsStudio.MetaRunner.Tests.Helpers +{ + public class PvsStudioExpectedErrorCode + { + public PvsStudioExpectedErrorCode(string errorCode, string category, int priority, int occurrenceCount) + { + ErrorCode = errorCode; + Category = category; + OccurrenceCount = occurrenceCount; + Priority = priority; + } + + public string ErrorCode { get; private set; } + + public string Category { get; private set; } + + public int OccurrenceCount { get; private set; } + + public int Priority { get; private set; } + } +} \ No newline at end of file diff --git a/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/Properties/AssemblyInfo.cs b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..e4bb4f7 --- /dev/null +++ b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("TeamCity.PvsStudio.MetaRunner.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TeamCity.PvsStudio.MetaRunner.Tests")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("282843e9-1846-4874-805a-5ccb59b3e633")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/PvsStudioTests.cs b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/PvsStudioTests.cs new file mode 100644 index 0000000..30f6563 --- /dev/null +++ b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/PvsStudioTests.cs @@ -0,0 +1,195 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using System.Xml.Linq; +using JetBrains.Annotations; +using RunProcessAsTask; +using TeamCity.PvsStudio.MetaRunner.Tests.Helpers; +using Xunit; + +namespace TeamCity.PvsStudio.MetaRunner.Tests +{ + public class PvsStudioTests + { + private const string CategoryGeneralAnalysis = "General Analysis"; + private const string CategoryMissing = "Unknown Inspections"; + + private const string ErrorCode3001 = "V3001"; + private const string ErrorCode3010 = "V3010"; + private const string ErrorCodeMissing = "V9999"; + + public PvsStudioTests() + { + DeleteExistingFile(PluginParameters.PvsStudioOutputPath); + DeleteExistingFile(PluginParameters.XsltOutputPath); + } + + [Fact] + public async Task PvsStudioOutputTest() + { + var result = await ProcessEx.RunAsync(PluginParameters.PvsStudioConsolePath, PluginParameters.PvsStudioParameters); + AssertSuccessfulProcessCompletion(result); + + var expectedErrorCodes = new List + { + new PvsStudioExpectedErrorCode(ErrorCode3001, CategoryGeneralAnalysis, 1, 1), + new PvsStudioExpectedErrorCode(ErrorCode3010, CategoryGeneralAnalysis, 1, 1) + }; + + AssertValidPvsStudioAnalysisReport(PluginParameters.PvsStudioOutputPath, expectedErrorCodes); + } + + [Fact] + public async Task UnknownIssueTypeXsltOutputTest() + { + var xsltResult = await ProcessEx.RunAsync(PluginParameters.MsXslPath, PluginParameters.GenerateXsltParameters(PluginParameters.UnknownIssueTypeReportPath, false)); + AssertSuccessfulProcessCompletion(xsltResult); + + var expectedErrorCodes = new List + { + new PvsStudioExpectedErrorCode(ErrorCode3001, CategoryGeneralAnalysis, 1, 1), + new PvsStudioExpectedErrorCode(ErrorCodeMissing, CategoryMissing, 2, 2) + }; + + AssertValidResharperAnalysisReport(PluginParameters.XsltOutputPath, expectedErrorCodes, false); + } + + [Fact] + public async Task TreatPriority1IssuesAsErrorsXsltOutputTest() + { + var xsltResult = await ProcessEx.RunAsync(PluginParameters.MsXslPath, PluginParameters.GenerateXsltParameters(PluginParameters.UnknownIssueTypeReportPath, true)); + AssertSuccessfulProcessCompletion(xsltResult); + + var expectedErrorCodes = new List + { + new PvsStudioExpectedErrorCode(ErrorCode3001, CategoryGeneralAnalysis, 1, 1), + new PvsStudioExpectedErrorCode(ErrorCodeMissing, CategoryMissing, 2, 2) + }; + + AssertValidResharperAnalysisReport(PluginParameters.XsltOutputPath, expectedErrorCodes, true); + } + + [Fact] + public async Task XsltOutputTest() + { + var pvsStudioResult = await ProcessEx.RunAsync(PluginParameters.PvsStudioConsolePath, PluginParameters.PvsStudioParameters); + AssertSuccessfulProcessCompletion(pvsStudioResult); + + var expectedErrorCodes = new List + { + new PvsStudioExpectedErrorCode(ErrorCode3001, CategoryGeneralAnalysis, 1, 1), + new PvsStudioExpectedErrorCode(ErrorCode3010, CategoryGeneralAnalysis, 1, 1) + }; + + AssertValidPvsStudioAnalysisReport(PluginParameters.PvsStudioOutputPath, expectedErrorCodes); + + var xsltResult = await ProcessEx.RunAsync(PluginParameters.MsXslPath, PluginParameters.MsXslParameters); + AssertSuccessfulProcessCompletion(xsltResult); + + AssertValidResharperAnalysisReport(PluginParameters.XsltOutputPath, expectedErrorCodes, false); + } + + private static void DeleteExistingFile(string filePath) + { + if (File.Exists(filePath)) + { + File.Delete(filePath); + } + } + + [AssertionMethod] + private static void AssertFileExists(string filePath) + { + Assert.True(File.Exists(filePath)); + } + + [AssertionMethod] + private static void AssertSuccessfulProcessCompletion(ProcessResults result) + { + Assert.NotNull(result); + Assert.NotEqual(1, result.Process.ExitCode); + Assert.Empty(result.StandardError); + } + + [AssertionMethod] + private static void AssertValidPvsStudioAnalysisReport(string filePath, ICollection expectedErrorCodes) + { + AssertFileExists(filePath); + + var outputDocument = XDocument.Load(filePath); + Assert.NotNull(outputDocument); + + var analysisLogs = outputDocument.Descendants("PVS-Studio_Analysis_Log").ToList(); + + Assert.NotNull(analysisLogs); + Assert.Equal(expectedErrorCodes.Count, analysisLogs.Count); + + var errorCodes = analysisLogs.Select(analysisLog => analysisLog.Element("ErrorCode")).ToList(); + + var groupedCodesInReport = errorCodes.GroupBy(_ => _).ToList(); + + foreach (var expectedErrorCode in expectedErrorCodes) + { + var grouping = Assert.Single(groupedCodesInReport, _ => _.Key.Value == expectedErrorCode.ErrorCode); + Assert.NotNull(grouping); + Assert.Equal(expectedErrorCode.OccurrenceCount, grouping.Count()); + } + } + + [AssertionMethod] + private static void AssertValidResharperAnalysisReport(string filePath, ICollection expectedErrorCodes, bool treatPriority1IssuesAsErrors) + { + AssertFileExists(filePath); + + var resharperOutputDocument = XDocument.Load(filePath); + Assert.NotNull(resharperOutputDocument); + + var reportElement = resharperOutputDocument.Element("Report"); + Assert.NotNull(reportElement); + + var issueTypesElement = reportElement.Element("IssueTypes"); + Assert.NotNull(issueTypesElement); + + var issueTypeElements = issueTypesElement.Descendants("IssueType").ToList(); + + Assert.NotNull(issueTypeElements); + Assert.Equal(expectedErrorCodes.Count, issueTypeElements.Count); + + foreach (var expectedErrorCode in expectedErrorCodes) + { + AssertResharperIssueTypes(issueTypeElements, expectedErrorCode, treatPriority1IssuesAsErrors); + } + + var issuesElement = reportElement.Element("Issues"); + Assert.NotNull(issuesElement); + + var projectElement = issuesElement.Element("Project"); + Assert.NotNull(projectElement); + + var issueElements = projectElement.Descendants("Issue").ToList(); + + Assert.NotNull(issueElements); + Assert.Equal(expectedErrorCodes.Select(_ => _.OccurrenceCount).Sum(), issueElements.Count); + } + + [AssertionMethod] + private static void AssertResharperIssueTypes(IEnumerable issueTypeElements, PvsStudioExpectedErrorCode expectedErrorCode, bool treatPriority1IssuesAsErrors) + { + var issueType = Assert.Single(issueTypeElements, _ => _.Attribute("Id").Value == expectedErrorCode.ErrorCode); + Assert.NotNull(issueType); + + Assert.Equal($"PVS-Studio {expectedErrorCode.Category}. Priority: {expectedErrorCode.Priority}", issueType.Attribute("Category").Value); + Assert.Equal($"{issueType.Attribute("Id").Value}. {issueType.Attribute("Description").Value}", issueType.Attribute("SubCategory").Value); + + AssertSeverity(expectedErrorCode, issueType, treatPriority1IssuesAsErrors); + } + + [AssertionMethod] + private static void AssertSeverity(PvsStudioExpectedErrorCode expectedErrorCode, XElement issueType, bool treatPriority1IssuesAsErrors) + { + var expectedSeverity = treatPriority1IssuesAsErrors && expectedErrorCode.Priority == 1 ? "ERROR" : "WARNING"; + Assert.Equal(expectedSeverity, issueType.Attribute("Severity").Value); + } + } +} diff --git a/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/TeamCity.PvsStudio.MetaRunner.TestProject/App.config b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/TeamCity.PvsStudio.MetaRunner.TestProject/App.config new file mode 100644 index 0000000..731f6de --- /dev/null +++ b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/TeamCity.PvsStudio.MetaRunner.TestProject/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/TeamCity.PvsStudio.MetaRunner.TestProject/Program.cs b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/TeamCity.PvsStudio.MetaRunner.TestProject/Program.cs new file mode 100644 index 0000000..af2557e --- /dev/null +++ b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/TeamCity.PvsStudio.MetaRunner.TestProject/Program.cs @@ -0,0 +1,14 @@ +namespace TeamCity.PvsStudio.MetaRunner.TestProject +{ + static class Program + { + static void Main() + { + var s = "qwerty"; + + //issue is made intentionally for testing PVS Studio + // ReSharper disable once ReturnValueOfPureMethodIsNotUsed + s.Replace("q", string.Empty); + } + } +} diff --git a/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/TeamCity.PvsStudio.MetaRunner.TestProject/Properties/AssemblyInfo.cs b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/TeamCity.PvsStudio.MetaRunner.TestProject/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..29aecaf --- /dev/null +++ b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/TeamCity.PvsStudio.MetaRunner.TestProject/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("TeamCity.PvsStudio.MetaRunner.TestProject")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TeamCity.PvsStudio.MetaRunner.TestProject")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("2850fbfa-1f9d-46be-a8e3-0ecf5fff7a75")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/TeamCity.PvsStudio.MetaRunner.TestProject/TeamCity.PvsStudio.MetaRunner.TestProject.csproj b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/TeamCity.PvsStudio.MetaRunner.TestProject/TeamCity.PvsStudio.MetaRunner.TestProject.csproj new file mode 100644 index 0000000..84ecd98 --- /dev/null +++ b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/TeamCity.PvsStudio.MetaRunner.TestProject/TeamCity.PvsStudio.MetaRunner.TestProject.csproj @@ -0,0 +1,61 @@ + + + + + Debug + AnyCPU + {2850FBFA-1F9D-46BE-A8E3-0ECF5FFF7A75} + Exe + Properties + TeamCity.PvsStudio.MetaRunner.TestProject + TeamCity.PvsStudio.MetaRunner.TestProject + v4.6.1 + 512 + true + 1.0.0.0 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/TeamCity.PvsStudio.MetaRunner.Tests.csproj b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/TeamCity.PvsStudio.MetaRunner.Tests.csproj new file mode 100644 index 0000000..c261d6c --- /dev/null +++ b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/TeamCity.PvsStudio.MetaRunner.Tests.csproj @@ -0,0 +1,89 @@ + + + + + Debug + AnyCPU + {282843E9-1846-4874-805A-5CCB59B3E633} + Library + Properties + TeamCity.PvsStudio.MetaRunner.Tests + TeamCity.PvsStudio.MetaRunner.Tests + v4.6.1 + 512 + 1.0.0.0 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\packages\JetBrains.Annotations.10.0.0\lib\net20\JetBrains.Annotations.dll + True + + + ..\..\packages\RunProcessAsTask.1.1.0\lib\RunProcessAsTask.dll + True + + + + + + + + + + + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll + True + + + ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + True + + + ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + True + + + + + + + + + + + + + + Always + + + + + \ No newline at end of file diff --git a/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/TestData/UnknownIssueTypeReport.xml b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/TestData/UnknownIssueTypeReport.xml new file mode 100644 index 0000000..6e6fb41 --- /dev/null +++ b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/TestData/UnknownIssueTypeReport.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D:\Projects\teamcity-pvs-studio-meta-runner\tests\TeamCity.PvsStudio.MetaRunner.Tests.sln + 14.0 + 3 + 2016-02-29T14:49:54.0332805Z + + + false + 1 + 1 + V3001 + There are identical sub-expressions 'f == string.Empty' to the left and to the right of the '||' operator. + TeamCity.PvsStudio.MetaRunner.TestProject + TRIAL RESTRICTION + 14 + false + 1 + 214879571 + 1629368839 + 123 + true + 4 + + false + + + false + 2 + 2 + V9999 + The return value of function 'Replace' is required to be utilized. + TeamCity.PvsStudio.MetaRunner.TestProject + TRIAL RESTRICTION + 21 + false + 2 + 1345105634 + 3418268110 + 125 + true + 4 + + false + + + false + 2 + 2 + V9999 + The return value of function 'Replace' is required to be utilized. + TeamCity.PvsStudio.MetaRunner.TestProject + TRIAL RESTRICTION + 23 + false + 2 + 1345105634 + 3418268110 + 125 + true + 4 + + false + + diff --git a/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/packages.config b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/packages.config new file mode 100644 index 0000000..09efc5c --- /dev/null +++ b/tests/tests/TeamCity.PvsStudio.MetaRunner.Tests/packages.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file