public void ProjectLoader() { // Arrange string testSourcePath = TestUtils.CreateTestSpecificFolder(this.TestContext); // Create sub-directories, some with project info XML files and some without TestUtils.EnsureTestSpecificFolder(this.TestContext, "EmptyDir1"); ProjectDescriptor validTestProject = new ProjectDescriptor() { ParentDirectoryPath = testSourcePath, ProjectFolderName = "validTestProjectDir", ProjectFileName = "validTestProject.csproj", ProjectGuid = Guid.NewGuid(), IsTestProject = true }; validTestProject.AddCompileInputFile("TestFile1.cs", true); validTestProject.AddCompileInputFile("TestFile1.cs", true); validTestProject.AddContentFile("contentFile1.js", true); CreateFilesFromDescriptor(validTestProject, "testCompileListFile", "testContentList", "testFxCopReport", "testVisualStudioCodeCoverageReport"); TestUtils.EnsureTestSpecificFolder(this.TestContext, "EmptyDir2"); ProjectDescriptor validNonTestProject = new ProjectDescriptor() { ParentDirectoryPath = testSourcePath, ProjectFolderName = "validNonTestProjectDir", ProjectFileName = "validNonTestproject.proj", ProjectGuid = Guid.NewGuid(), IsTestProject = false }; validNonTestProject.AddContentFile("ASourceFile.vb", true); validNonTestProject.AddContentFile("AnotherSourceFile.vb", true); CreateFilesFromDescriptor(validNonTestProject, "list.txt", null, "fxcop.xml", "visualstudio-codecoverage.xml"); ProjectDescriptor validNonTestNoReportsProject = new ProjectDescriptor() { ParentDirectoryPath = testSourcePath, ProjectFolderName = "validNonTestNoReportsProjectDir", ProjectFileName = "validNonTestNoReportsProject.proj", ProjectGuid = Guid.NewGuid(), IsTestProject = false }; validNonTestNoReportsProject.AddContentFile("SomeFile.cs", true); CreateFilesFromDescriptor(validNonTestNoReportsProject, "SomeList.txt", null, null, null); // Act IEnumerable<ProjectInfo> projects = SonarRunner.Shim.ProjectLoader.LoadFrom(testSourcePath); // Assert Assert.AreEqual(3, projects.Count()); AssertProjectResultExists(validTestProject.ProjectName, projects); AssertProjectResultExists(validNonTestProject.ProjectName, projects); AssertProjectResultExists(validNonTestNoReportsProject.ProjectName, projects); }
/// <summary> /// Creates and returns a valid project descriptor for a project in the supplied folders /// </summary> public static ProjectDescriptor CreateValidProjectDescriptor(string parentDirectory, string projectFileName = "MyProject.xproj.txt", bool isVBProject = false) { ProjectDescriptor descriptor = new ProjectDescriptor() { ProjectLanguage = isVBProject ? SonarQube.Common.ProjectLanguages.VisualBasic : SonarQube.Common.ProjectLanguages.CSharp, ProjectGuid = Guid.NewGuid(), IsTestProject = false, ParentDirectoryPath = parentDirectory, ProjectFolderName = "MyProjectDir", ProjectFileName = projectFileName }; return descriptor; }
/// <summary> /// Creates a project file on disk from the specified descriptor. /// Sets the SonarQube output folder property, if specified. /// </summary> public static ProjectRootElement CreateInitializedProjectRoot(TestContext testContext, ProjectDescriptor descriptor, IDictionary<string, string> preImportProperties) { if (testContext == null) { throw new ArgumentNullException("testContext"); } if (descriptor == null) { throw new ArgumentNullException("descriptor"); } ProjectRootElement projectRoot = BuildUtilities.CreateAnalysisProject(testContext, descriptor, preImportProperties); projectRoot.ToolsVersion = MSBuildToolsVersionForTestProjects; projectRoot.Save(descriptor.FullFilePath); testContext.AddResultFile(descriptor.FullFilePath); return projectRoot; }
public void E2E_MissingProjectGuid() { // Projects with missing guids should have a warning emitted. The project info // should not be generated. // Arrange string rootInputFolder = TestUtils.CreateTestSpecificFolder(this.TestContext, "Inputs"); string rootOutputFolder = TestUtils.CreateTestSpecificFolder(this.TestContext, "Outputs"); WellKnownProjectProperties preImportProperties = CreateDefaultAnalysisProperties(rootInputFolder, rootOutputFolder); preImportProperties["SonarConfigPath"] = rootInputFolder; ProjectDescriptor descriptor = new ProjectDescriptor() { // No guid property IsTestProject = false, ParentDirectoryPath = rootInputFolder, ProjectFolderName = "MyProjectDir", ProjectFileName = "MissingProjectGuidProject.proj" }; AddEmptyAnalysedCodeFile(descriptor, rootInputFolder); ProjectRootElement projectRoot = BuildUtilities.CreateInitializedProjectRoot(this.TestContext, descriptor, preImportProperties); BuildLogger logger = new BuildLogger(); // Act BuildResult result = BuildUtilities.BuildTargets(projectRoot, logger); // Assert BuildAssertions.AssertTargetSucceeded(result, TargetConstants.DefaultBuildTarget); // Build should succeed with warnings ProjectInfoAssertions.AssertNoProjectInfoFilesExists(rootOutputFolder); logger.AssertExpectedErrorCount(0); logger.AssertExpectedWarningCount(1); BuildWarningEventArgs warning = logger.Warnings[0]; Assert.IsTrue(warning.Message.Contains(descriptor.FullFilePath), "Expecting the warning to contain the full path to the bad project file"); }
/// <summary> /// Creates and returns an empty MSBuild project using the data in the supplied descriptor. /// The project will import the SonarQube analysis targets file and the standard C# targets file. /// The project name and GUID will be set if the values are supplied in the descriptor. /// </summary> private static ProjectRootElement CreateAnalysisProject(TestContext testContext, ProjectDescriptor descriptor, IDictionary<string, string> preImportProperties) { if (testContext == null) { throw new ArgumentNullException("testContext"); } if (descriptor == null) { throw new ArgumentNullException("descriptor"); } string sqTargetFile = TestUtils.EnsureAnalysisTargetsExists(testContext); Assert.IsTrue(File.Exists(sqTargetFile), "Test error: the SonarQube analysis targets file could not be found. Full path: {0}", sqTargetFile); testContext.AddResultFile(sqTargetFile); IDictionary<string, string> properties = preImportProperties ?? new Dictionary<string, string>(); // Disable the standard "ImportBefore/ImportAfter" behaviour if the caller // hasn't defined what they want to happen explicitly if (!properties.ContainsKey(StandardImportBeforePropertyName)) { DisableStandardTargetsWildcardImporting(properties); } ProjectRootElement root = CreateMinimalBuildableProject(properties, descriptor.IsVbProject, sqTargetFile); // Set the location of the task assembly if (!properties.ContainsKey(TargetProperties.SonarBuildTasksAssemblyFile)) { root.AddProperty(TargetProperties.SonarBuildTasksAssemblyFile, typeof(WriteProjectInfoFile).Assembly.Location); } if (descriptor.ProjectGuid != Guid.Empty) { root.AddProperty(TargetProperties.ProjectGuid, descriptor.ProjectGuid.ToString("D")); } foreach (ProjectDescriptor.FileInProject file in descriptor.Files) { root.AddItem(file.ItemGroup, file.FilePath); } if (descriptor.IsTestProject && !root.Properties.Any(p => string.Equals(p.Name, TargetProperties.SonarQubeTestProject))) { root.AddProperty(TargetProperties.SonarQubeTestProject, "true"); } return root; }
/// <summary> /// Creates a folder containing a ProjectInfo.xml and compiled file list as /// specified in the supplied descriptor /// </summary> private static void CreateFilesFromDescriptor(ProjectDescriptor descriptor, string compileFiles, string contentFiles, string fxcopReportFileName, string visualStudioCodeCoverageReportFileName) { if (!Directory.Exists(descriptor.FullDirectoryPath)) { Directory.CreateDirectory(descriptor.FullDirectoryPath); } ProjectInfo projectInfo = descriptor.CreateProjectInfo(); // Create the analysis file list if any input files have been specified if (descriptor.FilesToAnalyse.Any()) { string fullAnalysisFileListPath = Path.Combine(descriptor.FullDirectoryPath, compileFiles); File.WriteAllLines(fullAnalysisFileListPath, descriptor.FilesToAnalyse); // Add the compile list as an analysis result projectInfo.AnalysisResults.Add(new AnalysisResult() { Id = AnalysisType.FilesToAnalyze.ToString(), Location = fullAnalysisFileListPath }); } // Create the FxCop report file if (fxcopReportFileName != null) { string fullFxCopName = Path.Combine(descriptor.FullDirectoryPath, fxcopReportFileName); File.Create(fullFxCopName); // Add the FxCop report as an analysis result var analysisResult = new AnalysisResult() { Id = AnalysisType.FxCop.ToString(), Location = fullFxCopName }; descriptor.AnalysisResults.Add(analysisResult); projectInfo.AnalysisResults.Add(analysisResult); } // Create the Visual Studio Code Coverage report file if (visualStudioCodeCoverageReportFileName != null) { string fullVisualStudioCodeCoverageName = Path.Combine(descriptor.FullDirectoryPath, visualStudioCodeCoverageReportFileName); File.Create(fullVisualStudioCodeCoverageName); // Add the Visual Studio Code Coverage report as an analysis result var analysisResult = new AnalysisResult() { Id = AnalysisType.VisualStudioCodeCoverage.ToString(), Location = fullVisualStudioCodeCoverageName }; descriptor.AnalysisResults.Add(analysisResult); projectInfo.AnalysisResults.Add(analysisResult); } // Save a project info file in the target directory projectInfo.Save(Path.Combine(descriptor.FullDirectoryPath, FileConstants.ProjectInfoFileName)); }
public void ProjectLoader_NonRecursive() { // 0. Setup string rootTestDir = Path.Combine(this.TestContext.DeploymentDirectory, "ProjectLoader_NonRecursive"); string childDir = Path.Combine(rootTestDir, "Child1"); // Create a valid project in the child directory ProjectDescriptor validNonTestProject = new ProjectDescriptor() { ParentDirectoryPath = childDir, ProjectFolderName = "validNonTestProjectDir", ProjectFileName = "validNonTestproject.proj", ProjectGuid = Guid.NewGuid(), IsTestProject = false }; validNonTestProject.AddCompileInputFile("ASourceFile.vb", true); validNonTestProject.AddCompileInputFile("AnotherSourceFile.vb", true); CreateFilesFromDescriptor(validNonTestProject, "CompileList.txt", null, null, null); // 1. Run against the root dir -> not expecting the project to be found IEnumerable<ProjectInfo> projects = SonarRunner.Shim.ProjectLoader.LoadFrom(rootTestDir); Assert.AreEqual(0, projects.Count()); // 2. Run against the child dir -> project should be found projects = SonarRunner.Shim.ProjectLoader.LoadFrom(childDir); Assert.AreEqual(1, projects.Count()); }
private static ProjectInfo CreateExpectedProjectInfo (ProjectDescriptor expected, string projectOutputFolder) { ProjectInfo expectedProjectInfo = expected.CreateProjectInfo(); // Work out what the expected analysis results are if (expected.Files.Any(f => f.ShouldBeAnalysed)) { expectedProjectInfo.AnalysisResults.Add( new AnalysisResult() { Id = AnalysisType.FilesToAnalyze.ToString(), Location = Path.Combine(projectOutputFolder, ExpectedAnalysisFilesListFileName) }); } return expectedProjectInfo; }
private void CheckAnalysisFileList(ProjectDescriptor expected, string projectOutputFolder) { string[] expectedFiles = GetExpectedAnalysisFiles(expected).ToArray(); if (!expectedFiles.Any()) { AssertFileDoesNotExist(projectOutputFolder, ExpectedAnalysisFilesListFileName); } else { string fullName = AssertFileExists(projectOutputFolder, ExpectedAnalysisFilesListFileName); string[] actualFiles = File.ReadAllLines(fullName); // The actual files might contain extra compiler generated files, so check the expected files // we expected is a subset of the actual CollectionAssert.IsSubsetOf(expectedFiles, actualFiles, "Analysis file does not contain the expected entries"); // Check that any files that should not be analysed are not included if (expected.FilesNotToAnalyse != null && expected.FilesNotToAnalyse.Any()) { foreach(string unanalysedFile in expected.FilesNotToAnalyse) { string filePathToCheck = unanalysedFile; if (!Path.IsPathRooted(filePathToCheck)) { // Assume paths are relative to the project directory filePathToCheck = Path.Combine(expected.FullDirectoryPath, filePathToCheck); } CollectionAssert.DoesNotContain(actualFiles, filePathToCheck, "Not expecting file to be included for analysis: {0}", filePathToCheck); } } } }
private static IList<string> GetExpectedAnalysisFiles(ProjectDescriptor descriptor) { return descriptor.Files.Where(f => f.ShouldBeAnalysed).Select(f => f.FilePath).ToList(); }
private void CheckProjectOutputFolder(ProjectDescriptor expected, string projectOutputFolder) { Assert.IsFalse(string.IsNullOrEmpty(projectOutputFolder), "Test error: projectOutputFolder should not be null/empty"); Assert.IsTrue(Directory.Exists(projectOutputFolder), "Expected project folder does not exist: {0}", projectOutputFolder); // Check folder naming string folderName = Path.GetFileName(projectOutputFolder); Assert.IsTrue(folderName.StartsWith(expected.ProjectName), "Project output folder does not start with the project name. Expected: {0}, actual: {1}", expected.ProjectFolderName, folderName); // Check specific files ProjectInfo expectedProjectInfo = CreateExpectedProjectInfo(expected, projectOutputFolder); CheckProjectInfo(expectedProjectInfo, projectOutputFolder); CheckAnalysisFileList(expected, projectOutputFolder); // Check there are no other files List<string> allowedFiles = new List<string>(expectedProjectInfo.AnalysisResults.Select(ar => ar.Location)); allowedFiles.Add(Path.Combine(projectOutputFolder, FileConstants.ProjectInfoFileName)); AssertNoAdditionalFilesInFolder(projectOutputFolder, allowedFiles.ToArray()); }
/// <summary> /// Creates and builds a new Sonar-enabled project using the supplied descriptor. /// The method will check the build succeeded and that a single project output file was created. /// </summary> /// <returns>The full path of the project-specsific directory that was created during the build</returns> private string CreateAndBuildSonarProject(ProjectDescriptor descriptor, string rootOutputFolder, WellKnownProjectProperties preImportProperties) { ProjectRootElement projectRoot = BuildUtilities.CreateInitializedProjectRoot(this.TestContext, descriptor, preImportProperties); BuildLogger logger = new BuildLogger(); // Act BuildResult result = BuildUtilities.BuildTargets(projectRoot, logger); // Assert BuildAssertions.AssertTargetSucceeded(result, TargetConstants.DefaultBuildTarget); // We expect the compiler to warn if there are no compiler inputs int expectedWarnings = (descriptor.ManagedSourceFiles.Any()) ? 0 : 1; logger.AssertExpectedErrorCount(0); logger.AssertExpectedWarningCount(expectedWarnings); logger.AssertExpectedTargetOrdering( TargetConstants.CategoriseProjectTarget, TargetConstants.DefaultBuildTarget, TargetConstants.CalculateFilesToAnalyzeTarget, TargetConstants.WriteProjectDataTarget); // Check expected folder structure exists CheckRootOutputFolder(rootOutputFolder); // Check expected project outputs Assert.AreEqual(1, Directory.EnumerateDirectories(rootOutputFolder).Count(), "Only expecting one child directory to exist under the root analysis output folder"); ProjectInfoAssertions.AssertProjectInfoExists(rootOutputFolder, projectRoot.FullPath); return Directory.EnumerateDirectories(rootOutputFolder).Single(); }
private static void AddEmptyContentFile(ProjectDescriptor descriptor, string projectFolder) { string filePath = CreateEmptyFile(projectFolder, "txt"); descriptor.AddContentFile(filePath, true); }
private string AddEmptyAnalysedCodeFile(ProjectDescriptor descriptor, string projectFolder, string extension = "cs") { string filePath = CreateEmptyFile(projectFolder, extension); descriptor.AddCompileInputFile(filePath, true); return filePath; }
/// <summary> /// Creates a new project using the supplied descriptor and properties, then /// execute the WriteProjectInfoFile task. The method will check the build succeeded /// and that a single project output file was created. /// </summary> /// <returns>The project info file that was created during the build</returns> private ProjectInfo ExecuteWriteProjectInfo(ProjectDescriptor descriptor, WellKnownProjectProperties preImportProperties, string rootOutputFolder) { ProjectRootElement projectRoot = CreateInitializedProject(descriptor, preImportProperties, rootOutputFolder); return this.ExecuteWriteProjectInfo(projectRoot, rootOutputFolder); }
private ProjectRootElement CreateInitializedProject(ProjectDescriptor descriptor, WellKnownProjectProperties preImportProperties, string rootOutputFolder) { // Still need to set the conditions so the target is invoked preImportProperties.SonarQubeOutputPath = rootOutputFolder; // The temp folder needs to be set for the targets to succeed. Use the temp folder // if one has not been supplied. if (string.IsNullOrEmpty(preImportProperties.SonarQubeTempPath)) { preImportProperties.SonarQubeTempPath = Path.GetTempPath(); } // The config folder needs to be set for the targets to succeed. Use the temp folder // if one has not been supplied. if (string.IsNullOrEmpty(preImportProperties.SonarQubeConfigPath)) { preImportProperties.SonarQubeConfigPath = Path.GetTempPath(); } ProjectRootElement projectRoot = BuildUtilities.CreateInitializedProjectRoot(this.TestContext, descriptor, preImportProperties); return projectRoot; }