private void SetPlugins(XElement build, CodeCoverageEnablerInputs mavenCcParams, XNamespace xNameSpace)
        {
            var defaultConfigurationElement = new XElement("configuration");
            AddConfigurationDefaults(defaultConfigurationElement, xNameSpace, mavenCcParams);

            var defaultExecutions = GetDefaultExecutions();

            var pluginManagement = build.Element(xNameSpace + "pluginManagement");
            if (pluginManagement != null)
            {
                var pluginManagementplugins = pluginManagement.Element(xNameSpace + _pluginsTag);

                if (pluginManagementplugins != null)
                {
                    SetPluginsForJacoco(mavenCcParams, pluginManagementplugins, xNameSpace, defaultConfigurationElement, defaultExecutions, false);
                }
            }

            var plugins = build.Element(xNameSpace + _pluginsTag);
            if (plugins == null)
            {
                // no pluggins add plugins default jacoco plugin. <plugins>  default jacoco plugin </plugins>
                build.Add(new XElement(_pluginsTag));
                plugins = build.Element(_pluginsTag);
            }
            SetPluginsForJacoco(mavenCcParams, plugins, xNameSpace, defaultConfigurationElement, defaultExecutions, true);
        }
        public void EnableCodeCoverage(IExecutionContext context, CodeCoverageEnablerInputs ccInputs)
        {
            Trace.Entering();
            _executionContext = context;

            ccInputs.VerifyInputsForJacocoMaven();

            context.Debug(StringUtil.Format(CodeCoverageConstants.EnablingEditingTemplate, "jacoco", "maven", ccInputs.BuildFile));

            // see jacoco maven documentation for more details. http://www.eclemma.org/jacoco/trunk/doc/maven.html
            XElement pomXml;

            try
            {
                pomXml = XElement.Load(ccInputs.BuildFile);
            }
            catch (XmlException e)
            {
                _executionContext.Warning(StringUtil.Loc("InvalidBuildXml", ccInputs.BuildFile, e.Message));
                throw;
            }

            XNamespace xNameSpace = pomXml.Attribute("xmlns").Value;

            if (pomXml.Element(xNameSpace + "modules") != null)
            {
                // aa multi module project
                _isMultiModule = true;
                context.Debug(CodeCoverageConstants.MavenMultiModule);
            }

            // Add a build element if doesnot exist.
            var build = pomXml.Element(xNameSpace + "build");

            if (build == null)
            {
                pomXml.Add(new XElement("build"));
                build = pomXml.Element("build");
            }

            // Set jacoco plugins to enable code coverage.
            SetPlugins(build, ccInputs, xNameSpace);

            foreach (var e in build.DescendantsAndSelf().Where(e => string.IsNullOrEmpty(e.Name.Namespace.NamespaceName)))
            {
                e.Name = xNameSpace + e.Name.LocalName;
            }

            using (FileStream stream = new FileStream(ccInputs.BuildFile, FileMode.Create))
            {
                pomXml.Save(stream);
            }

            if (_isMultiModule)
            {
                CreateReportPomForMultiModule(ccInputs.ReportBuildFile, xNameSpace, pomXml, ccInputs);
            }

            context.Output(StringUtil.Loc("CodeCoverageEnabled", "jacoco", "maven"));
        }
Example #3
0
        private string GetAntReport(CodeCoverageEnablerInputs ccInputs, string dataFile)
        {
            var targetXml = string.Format(CodeCoverageConstants.CoberturaAntReport, AddEnvProperty().OuterXml, AddPathForCobertura().OuterXml, AddTaskDefForCobertura().OuterXml,
                                          ccInputs.CCReportTask, ccInputs.ReportDirectory, dataFile, ccInputs.SourceDirectories);

            return(targetXml);
        }
Example #4
0
        private void ProcessEnableCodeCoverageCommand(IExecutionContext context, Dictionary <string, string> eventProperties)
        {
            string codeCoverageTool;

            eventProperties.TryGetValue(EnableCodeCoverageEventProperties.CodeCoverageTool, out codeCoverageTool);
            if (string.IsNullOrWhiteSpace(codeCoverageTool))
            {
                // no code coverage tool specified. Dont enable code coverage.
                return;
            }
            codeCoverageTool = codeCoverageTool.Trim();

            string buildTool;

            eventProperties.TryGetValue(EnableCodeCoverageEventProperties.BuildTool, out buildTool);
            if (string.IsNullOrEmpty(buildTool))
            {
                throw new ArgumentException(StringUtil.Loc("ArgumentNeeded", "BuildTool"));
            }
            buildTool = buildTool.Trim();

            var codeCoverageInputs         = new CodeCoverageEnablerInputs(context, buildTool, eventProperties);
            ICodeCoverageEnabler ccEnabler = GetCodeCoverageEnabler(buildTool, codeCoverageTool);

            ccEnabler.EnableCodeCoverage(context, codeCoverageInputs);
        }
        private void SetPlugins(XElement build, CodeCoverageEnablerInputs mavenCcParams, XNamespace xNameSpace)
        {
            var defaultConfigurationElement = new XElement("configuration");

            AddConfigurationDefaults(defaultConfigurationElement, xNameSpace, mavenCcParams);

            var defaultExecutions = GetDefaultExecutions();

            var pluginManagement = build.Element(xNameSpace + "pluginManagement");

            if (pluginManagement != null)
            {
                var pluginManagementplugins = pluginManagement.Element(xNameSpace + _pluginsTag);

                if (pluginManagementplugins != null)
                {
                    SetPluginsForJacoco(mavenCcParams, pluginManagementplugins, xNameSpace, defaultConfigurationElement, defaultExecutions, false);
                }
            }

            var plugins = build.Element(xNameSpace + _pluginsTag);

            if (plugins == null)
            {
                // no pluggins add plugins default jacoco plugin. <plugins>  default jacoco plugin </plugins>
                build.Add(new XElement(_pluginsTag));
                plugins = build.Element(_pluginsTag);
            }
            SetPluginsForJacoco(mavenCcParams, plugins, xNameSpace, defaultConfigurationElement, defaultExecutions, true);
        }
        public void EnableCodeCoverage(IExecutionContext context, CodeCoverageEnablerInputs ccInputs)
        {
            Trace.Entering();
            _executionContext = context;

            ccInputs.VerifyInputsForJacocoAnt(context);

            string sourcesDirectory = context.Variables.Build_SourcesDirectory;
            if (string.IsNullOrWhiteSpace(sourcesDirectory))
            {
                throw new InvalidOperationException(StringUtil.Loc("InvalidSourceDirectory"));
            }

            var buildFileDirectory = Path.GetDirectoryName(ccInputs.BuildFile);
            if (!buildFileDirectory.StartsWith(sourcesDirectory, StringComparison.OrdinalIgnoreCase))
            {
                // build file is not present in the repository.
                // Edit the build file though not present in repository. This will ensure that the single module ant project will work. 
                // Multi module ant project won't work if the build file is not in the repository. 
                EnableJacocoForBuildFile(ccInputs.BuildFile, ccInputs);
            }
            else
            {
                var buildFiles = Directory.GetFiles(sourcesDirectory, "*.xml", SearchOption.AllDirectories);
                foreach (var buildFile in buildFiles)
                {
                    EnableJacocoForBuildFile(buildFile, ccInputs);
                }
            }

            //add jacoco report
            CreateJacocoReport(ccInputs);
            context.Output(StringUtil.Loc("CodeCoverageEnabled", "jacoco", "ant"));
        }
        private XmlNode GetInstrumentNode(CodeCoverageEnablerInputs antCCParams, string instrumentedClassesDirectory, string dataFile)
        {
            var inclusionExclusionSet = CodeCoverageUtilities.GetClassDataForAnt(antCCParams.Include, antCCParams.Exclude, antCCParams.ClassFilesDirectories);

            var targetXml = string.Format(CodeCoverageConstants.CoberturaInstrumentNode, instrumentedClassesDirectory, dataFile, inclusionExclusionSet);

            return(GetXmlNode(targetXml));
        }
        public void EnableCodeCoverage(IExecutionContext context, CodeCoverageEnablerInputs ccInputs)
        {
            Trace.Entering();
            _executionContext = context;

            ccInputs.VerifyInputsForJacocoMaven();

            context.Debug(StringUtil.Format(CodeCoverageConstants.EnablingEditingTemplate, "jacoco", "maven", ccInputs.BuildFile));

            // see jacoco maven documentation for more details. http://www.eclemma.org/jacoco/trunk/doc/maven.html
            XElement pomXml;
            try
            {
                pomXml = XElement.Load(ccInputs.BuildFile);
            }
            catch (XmlException e)
            {
                _executionContext.Warning(StringUtil.Loc("InvalidBuildXml", ccInputs.BuildFile, e.Message));
                throw;
            }

            XNamespace xNameSpace = pomXml.Attribute("xmlns").Value;

            if (pomXml.Element(xNameSpace + "modules") != null)
            {
                // aa multi module project 
                _isMultiModule = true;
                context.Debug(CodeCoverageConstants.MavenMultiModule);
            }

            // Add a build element if doesnot exist.
            var build = pomXml.Element(xNameSpace + "build");
            if (build == null)
            {
                pomXml.Add(new XElement("build"));
                build = pomXml.Element("build");
            }

            // Set jacoco plugins to enable code coverage.
            SetPlugins(build, ccInputs, xNameSpace);

            foreach (var e in build.DescendantsAndSelf().Where(e => string.IsNullOrEmpty(e.Name.Namespace.NamespaceName)))
            {
                e.Name = xNameSpace + e.Name.LocalName;
            }

            using (FileStream stream = new FileStream(ccInputs.BuildFile, FileMode.Create))
            {
                pomXml.Save(stream);
            }

            if (_isMultiModule)
            {
                CreateReportPomForMultiModule(ccInputs.ReportBuildFile, xNameSpace, pomXml, ccInputs);
            }

            context.Output(StringUtil.Loc("CodeCoverageEnabled", "jacoco", "maven"));
        }
Example #9
0
 private void CollectCodeCoverageForNodes(XmlNodeList nodes, CodeCoverageEnablerInputs antCCParams, XmlDocument buildXml, bool enableForkMode = false)
 {
     for (var index = 0; index < nodes.Count; index++)
     {
         CollectAntCodeCoverageForNode(antCCParams.ReportDirectory, antCCParams.Include, antCCParams.Exclude, (XmlElement)nodes[index], buildXml);
         if (enableForkMode)
         {
             ((XmlElement)nodes[index]).SetAttribute("forkmode", "once");
             _executionContext.Debug(StringUtil.Format(CodeCoverageConstants.SettingAttributeTemplate, "forkmode", "once", "junit"));
         }
     }
 }
Example #10
0
        private string GetAntReport(CodeCoverageEnablerInputs antCCParams)
        {
            var executionData = string.Empty;

            executionData += @"             <file file='" + Path.Combine(antCCParams.ReportDirectory, _jacocoExecPrefix + ".exec") + @"'/>" + Environment.NewLine;


            var srcData   = CodeCoverageUtilities.GetSourceDataForJacoco(antCCParams.SourceDirectories);
            var classData = CodeCoverageUtilities.GetClassDataForAnt(antCCParams.Include, antCCParams.Exclude, antCCParams.ClassFilesDirectories);

            return(string.Format(CodeCoverageConstants.JacocoAntReport, antCCParams.CCReportTask, executionData, classData, srcData, antCCParams.ReportDirectory, Path.Combine(antCCParams.ReportDirectory, "report.csv"), Path.Combine(antCCParams.ReportDirectory, antCCParams.SummaryFile)));
        }
 private void CollectCodeCoverageForNodes(XmlNodeList nodes, CodeCoverageEnablerInputs ccInputs, XmlDocument buildXml, XmlNode instrumentNode, string instrumentedClassesDirectory, string dataFile, bool enableForkMode = false)
 {
     for (var index = 0; index < nodes.Count; index++)
     {
         var instrumentTag = buildXml.ImportNode(instrumentNode, true);
         CollectAntCodeCoverageForNode(ccInputs.ReportDirectory, ccInputs.Include, ccInputs.Exclude, (XmlElement)nodes[index], buildXml, instrumentTag, instrumentedClassesDirectory, dataFile);
         if (enableForkMode)
         {
             ((XmlElement)nodes[index]).SetAttribute("forkmode", "once");
             _executionContext.Debug(StringUtil.Format(CodeCoverageConstants.SettingAttributeTemplate, "forkmode", "once", "junit"));
         }
     }
 }
        public void EnableCodeCoverage(IExecutionContext context, CodeCoverageEnablerInputs ccInputs)
        {
            Trace.Entering();

            ccInputs.VerifyInputsForCoberturaGradle();

            context.Debug(StringUtil.Format(CodeCoverageConstants.EnablingEditingTemplate, "cobertura", "gradle", ccInputs.BuildFile));
            var buildScript = new FileInfo(ccInputs.BuildFile);

            if (buildScript.Length == 0)
            {
                throw new InvalidOperationException(StringUtil.Loc("CodeCoverageBuildFileIsEmpty", ccInputs.BuildFile));
            }

            CodeCoverageUtilities.PrependDataToFile(ccInputs.BuildFile, GetCoberturaPluginDefination());
            File.AppendAllText(ccInputs.BuildFile, GetGradleCoberturaReport(ccInputs));
            context.Output(StringUtil.Loc("CodeCoverageEnabled", "cobertura", "gradle"));
        }
        public void EnableCodeCoverage(IExecutionContext context, CodeCoverageEnablerInputs ccInputs)
        {
            Trace.Entering();

            ccInputs.VerifyInputsForCoberturaGradle();

            context.Debug(StringUtil.Format(CodeCoverageConstants.EnablingEditingTemplate, "cobertura", "gradle", ccInputs.BuildFile));
            var buildScript = new FileInfo(ccInputs.BuildFile);

            if (buildScript.Length == 0)
            {
                throw new InvalidOperationException(StringUtil.Loc("CodeCoverageBuildFileIsEmpty", ccInputs.BuildFile));
            }

            CodeCoverageUtilities.PrependDataToFile(ccInputs.BuildFile, GetCoberturaPluginDefination());
            File.AppendAllText(ccInputs.BuildFile, GetGradleCoberturaReport(ccInputs));
            context.Output(StringUtil.Loc("CodeCoverageEnabled", "cobertura", "gradle"));
        }
        private string GetGradleCoberturaReport(CodeCoverageEnablerInputs gradleCCParams)
        {
            var coberturaExclude = CodeCoverageUtilities.TrimToEmptyString(gradleCCParams.Exclude);
            var coberturaInclude = CodeCoverageUtilities.TrimToEmptyString(gradleCCParams.Include);
            var exclude          = string.IsNullOrEmpty(coberturaExclude) ? string.Empty : string.Join(",", coberturaExclude.Split(':').Select(exclPackage => exclPackage.EndsWith("*") ? "'.*" + exclPackage.TrimEnd('*') + ".*'" : "'.*" + exclPackage + "'"));
            var include          = string.IsNullOrEmpty(coberturaInclude) ? string.Empty : string.Join(",", coberturaInclude.Split(':').Select(inclPackage => inclPackage.EndsWith("*") ? "'.*" + inclPackage.TrimEnd('*') + ".*'" : "'.*" + inclPackage + "'"));
            var classDirectories = string.Join(",", gradleCCParams.ClassFilesDirectories.Split(',').Select(exclPackage => "'" + exclPackage + "'"));
            var enableCobertura  = GetCoberturaPluginScriptForGradle(include, exclude);

            if (!gradleCCParams.IsMultiModule)
            {
                enableCobertura = string.Concat(enableCobertura, GetCoberturaReportingScriptForSingleModuleGradle(classDirectories, null,
                                                                                                                  gradleCCParams.ReportDirectory));
            }
            else
            {
                enableCobertura = string.Concat(enableCobertura, GetCoberturaReportingScriptForMultiModuleGradle(classDirectories, null,
                                                                                                                 gradleCCParams.ReportDirectory));
            }

            return(enableCobertura);
        }
        private void ProcessEnableCodeCoverageCommand(IExecutionContext context, Dictionary<string, string> eventProperties)
        {
            string codeCoverageTool;
            eventProperties.TryGetValue(EnableCodeCoverageEventProperties.CodeCoverageTool, out codeCoverageTool);
            if (string.IsNullOrWhiteSpace(codeCoverageTool))
            {
                // no code coverage tool specified. Dont enable code coverage.
                return;
            }
            codeCoverageTool = codeCoverageTool.Trim();

            string buildTool;
            eventProperties.TryGetValue(EnableCodeCoverageEventProperties.BuildTool, out buildTool);
            if (string.IsNullOrEmpty(buildTool))
            {
                throw new ArgumentException(StringUtil.Loc("ArgumentNeeded", "BuildTool"));
            }
            buildTool = buildTool.Trim();

            var codeCoverageInputs = new CodeCoverageEnablerInputs(context, buildTool, eventProperties);
            ICodeCoverageEnabler ccEnabler = GetCodeCoverageEnabler(buildTool, codeCoverageTool);
            ccEnabler.EnableCodeCoverage(context, codeCoverageInputs);
        }
        private void CreateCoberturaReport(CodeCoverageEnablerInputs ccInputs, string dataFile)
        {
            try
            {
                if (File.Exists(ccInputs.ReportBuildFile))
                {
                    File.Delete(ccInputs.ReportBuildFile);
                }
            }
            catch (IOException e)
            {
                _executionContext.Error(e);
            }

            try
            {
                var reportXml = GetAntReport(ccInputs, dataFile);
                var settings  = new XmlReaderSettings
                {
                    DtdProcessing = DtdProcessing.Prohibit
                };
                using (XmlReader reader = XmlReader.Create(new StringReader(reportXml), settings))
                {
                    XmlDocument xdoc = new XmlDocument();
                    xdoc.Load(reader);
                    using (FileStream stream = new FileStream(ccInputs.ReportBuildFile, FileMode.Create))
                    {
                        xdoc.Save(stream);
                    }
                }
            }
            catch (XmlException e)
            {
                _executionContext.Warning(StringUtil.Loc("InvalidBuildXml", ccInputs.ReportBuildFile, e.Message));
                throw;
            }
        }
Example #17
0
        public void EnableCodeCoverage(IExecutionContext context, CodeCoverageEnablerInputs ccInputs)
        {
            Trace.Entering();
            _executionContext = context;

            ccInputs.VerifyInputsForJacocoAnt(context);

            string sourcesDirectory = context.Variables.Build_SourcesDirectory;

            if (string.IsNullOrWhiteSpace(sourcesDirectory))
            {
                throw new InvalidOperationException(StringUtil.Loc("InvalidSourceDirectory"));
            }

            var buildFileDirectory = Path.GetDirectoryName(ccInputs.BuildFile);

            if (!buildFileDirectory.StartsWith(sourcesDirectory, StringComparison.OrdinalIgnoreCase))
            {
                // build file is not present in the repository.
                // Edit the build file though not present in repository. This will ensure that the single module ant project will work.
                // Multi module ant project won't work if the build file is not in the repository.
                EnableJacocoForBuildFile(ccInputs.BuildFile, ccInputs);
            }
            else
            {
                var buildFiles = Directory.GetFiles(sourcesDirectory, "*.xml", SearchOption.AllDirectories);
                foreach (var buildFile in buildFiles)
                {
                    EnableJacocoForBuildFile(buildFile, ccInputs);
                }
            }

            //add jacoco report
            CreateJacocoReport(ccInputs);
            context.Output(StringUtil.Loc("CodeCoverageEnabled", "jacoco", "ant"));
        }
Example #18
0
        public void EnableCodeCoverage(IExecutionContext context, CodeCoverageEnablerInputs ccInputs)
        {
            Trace.Entering();

            ccInputs.VerifyInputsForJacocoGradle();

            context.Debug(StringUtil.Format(CodeCoverageConstants.EnablingEditingTemplate, "jacoco", "gradle", ccInputs.BuildFile));

            var buildScript = new FileInfo(ccInputs.BuildFile);

            if (buildScript.Length == 0)
            {
                throw new InvalidOperationException(StringUtil.Loc("CodeCoverageBuildFileIsEmpty", ccInputs.BuildFile));
            }

            // see jacoco gradle documentation for more details. https://docs.gradle.org/current/userguide/jacoco_plugin.html

            var jacocoExclude = CodeCoverageUtilities.TrimToEmptyString(ccInputs.Exclude).Replace('.', '/');
            var jacocoInclude = CodeCoverageUtilities.TrimToEmptyString(ccInputs.Include).Replace('.', '/');
            var exclude       = string.IsNullOrEmpty(jacocoExclude) ? string.Empty : string.Join(",", jacocoExclude.Split(':').Select(
                                                                                                     exclPackage => exclPackage.EndsWith("*") ? ("'" + exclPackage + "/**'") : ("'" + exclPackage + ".class'")));
            var include = string.IsNullOrEmpty(jacocoInclude) ? string.Empty : string.Join(",", jacocoInclude.Split(':').Select(
                                                                                               inclPackage => inclPackage.EndsWith("*") ? ("'" + inclPackage + "/**'") : ("'" + inclPackage + ".class'")));

            var enableJacoco = string.Empty;

            if (ccInputs.IsMultiModule)
            {
                enableJacoco = @"
                    allprojects { apply plugin: 'jacoco' }

                    allprojects {
	                    repositories {
                            mavenCentral()
                        }
                    }

                    def jacocoExcludes = [" + CodeCoverageUtilities.TrimToEmptyString(exclude) + @"]
                    def jacocoIncludes = [" + CodeCoverageUtilities.TrimToEmptyString(include) + @"]

                    subprojects {
	
                        jacocoTestReport {
		                    doFirst {
			                    classDirectories = fileTree(dir: """             + ccInputs.ClassFilesDirectories + @""").exclude(jacocoExcludes).include(jacocoIncludes)
		                    }
		
		                    reports {
			                    html.enabled = true
			                    html.destination ""${buildDir}/jacocoHtml""
                                xml.enabled = true    
	                            xml.destination ""${buildDir}"     + "/" + _summaryFile + @"""
                            }
                        }
	
	                    test {
		                    jacoco {
			                    append = true
			                    destinationFile = file("""             + ccInputs.ReportDirectory + "/" + _jacocoExecPrefix + ".exec\"" + @")
		                    }
	                    }
                    }" + @"
                    task jacocoRootReport(type: org.gradle.testing.jacoco.tasks.JacocoReport) {
	                    dependsOn = subprojects.test
	                    executionData = files(subprojects.jacocoTestReport.executionData)
	                    sourceDirectories = files(subprojects.sourceSets.main.allSource.srcDirs)
	                    classDirectories = files()
	
	                    doFirst {
		                    subprojects.each {
			                    if (new File(""${it.sourceSets.main.output.classesDir}"").exists()) {
				                    logger.info(""Class directory exists in sub project: ${it.name}"")
				                    logger.info(""Adding class files ${it.sourceSets.main.output.classesDir}"")
				                    classDirectories += fileTree(dir: ""${it.sourceSets.main.output.classesDir}"", includes: jacocoIncludes, excludes: jacocoExcludes)
			                    } else {
				                    logger.error(""Class directory does not exist in sub project: ${it.name}"")
			                    }
		                    }
	                    }
	
	                    reports {
		                    html.enabled = true
                            xml.enabled = true    
		                    xml.destination """         + ccInputs.ReportDirectory + "/" + _summaryFile + @"""
		                    html.destination """         + ccInputs.ReportDirectory + @"""
	                    }
                    }
                    ";
            }
            else
            {
                enableJacoco = @"
                    allprojects { apply plugin: 'jacoco' }

                    allprojects {
	                    repositories {
                            mavenCentral()
                        }
                    }

                    def jacocoExcludes = [" + CodeCoverageUtilities.TrimToEmptyString(exclude) + @"]
                    def jacocoIncludes = [" + CodeCoverageUtilities.TrimToEmptyString(include) + @"]


	
                    jacocoTestReport {
	                    doFirst {
		                    classDirectories = fileTree(dir: """         + ccInputs.ClassFilesDirectories + @""").exclude(jacocoExcludes).include(jacocoIncludes)
	                    }
		
	                    reports {
	                        html.enabled = true
                            xml.enabled = true    
	                        xml.destination """     + ccInputs.ReportDirectory + "/" + _summaryFile + @"""
	                        html.destination """     + ccInputs.ReportDirectory + @"""
                        }
                    }
	
                    test {
                        finalizedBy jacocoTestReport
	                    jacoco {
		                    append = true
		                    destinationFile = file("""         + ccInputs.ReportDirectory + "/" + _jacocoExecPrefix + ".exec\"" + @")
	                    }
                    }
                    ";
            }
            File.AppendAllText(ccInputs.BuildFile, enableJacoco);
            context.Output(StringUtil.Loc("CodeCoverageEnabled", "jacoco", "gradle"));
        }
        public void EnableCodeCoverage(IExecutionContext context, CodeCoverageEnablerInputs ccInputs)
        {
            Trace.Entering();
            _executionContext = context;

            context.Debug(StringUtil.Format(CodeCoverageConstants.EnablingEditingTemplate, "cobertura", "maven", ccInputs.BuildFile));

            XElement pomXml;
            try
            {
                pomXml = XElement.Load(ccInputs.BuildFile);
            }
            catch (XmlException e)
            {
                _executionContext.Warning(StringUtil.Loc("InvalidBuildXml", ccInputs.BuildFile, e.Message));
                throw;
            }

            XNamespace xNameSpace = pomXml.Attribute("xmlns").Value;

            if (pomXml.Element(xNameSpace + "modules") != null)
            {
                // aa multi module project 
                _isMultiModule = true;
                context.Debug("This is a multi module project. Generating code coverage reports using ant task.");
            }

            // Add a build element if doesnot exist.
            var build = pomXml.Element(xNameSpace + "build");
            if (build == null)
            {
                pomXml.Add(new XElement(xNameSpace + "build"));
                build = pomXml.Element(xNameSpace + "build");
            }

            // Set cobertura plugins to enable code coverage.
            SetPlugins(build, ccInputs, xNameSpace);

            // Adding reporting enabler for cobertura
            var report = pomXml.Element(xNameSpace + "reporting");
            if (report == null)
            {
                pomXml.Add(new XElement(xNameSpace + "reporting"));
                report = pomXml.Element(xNameSpace + "reporting");
            }

            var pluginsInReport = report.Element(xNameSpace + _pluginsTag);
            if (pluginsInReport == null)
            {
                report.Add(new XElement(xNameSpace + _pluginsTag));
                pluginsInReport = report.Element(xNameSpace + _pluginsTag);
            }

            IList<XElement> pluginListInReport = pluginsInReport.Elements(xNameSpace + _pluginTag).ToList();

            foreach (var plugin in pluginListInReport.Where(plugin =>
            {
                var groupId = plugin.Element(xNameSpace + "groupId");
                var artifactId = plugin.Element(xNameSpace + "artifactId");
                return (artifactId != null && artifactId.Value == _coberturaArtifactId)
                    && (groupId != null && groupId.Value == _coberturaGroupId);
            }))
            {
                plugin.Parent.RemoveAll();
            }

            pluginsInReport.Add(GetDefaultReporting());

            foreach (var e in build.DescendantsAndSelf().Where(e => string.IsNullOrEmpty(e.Name.Namespace.NamespaceName)))
            {
                e.Name = xNameSpace + e.Name.LocalName;
            }

            foreach (var e in report.DescendantsAndSelf().Where(e => string.IsNullOrEmpty(e.Name.Namespace.NamespaceName)))
            {
                e.Name = xNameSpace + e.Name.LocalName;
            }

            using (FileStream stream = new FileStream(ccInputs.BuildFile, FileMode.Create))
            {
                pomXml.Save(stream);
            }
            context.Output(StringUtil.Loc("CodeCoverageEnabled", "cobertura", "maven"));
        }
        private void AddConfigurationDefaults(XElement configuration, XNamespace xNameSpace, CodeCoverageEnablerInputs mavenCcParams, bool isPrepartAgentExecution = false)
        {
            var      excludesElement = CodeCoverageUtilities.GetClassDataForMaven(mavenCcParams.Exclude, "excludes", "exclude", true);
            XElement includesElement;

            if (!isPrepartAgentExecution)
            {
                includesElement = CodeCoverageUtilities.GetClassDataForMaven(mavenCcParams.Include, "includes", "include", true);
            }
            else
            {
                includesElement = new XElement("includes",
                                               new XElement("include", "**/*"));
            }

            configuration.SetElementValue(xNameSpace + "destFile", Path.Combine(mavenCcParams.ReportDirectory, _jacocoExecPrefix + ".exec"));
            configuration.SetElementValue(xNameSpace + "outputDirectory", mavenCcParams.ReportDirectory);
            configuration.SetElementValue(xNameSpace + "dataFile", Path.Combine(mavenCcParams.ReportDirectory, _jacocoExecPrefix + ".exec"));
            configuration.SetElementValue(xNameSpace + "append", "true");

            // remove any existing excludes and includes. We cannot directly set the values here as the value is not one single object but multiple xelements
            configuration.SetElementValue(xNameSpace + excludesElement.Name.ToString(), null);
            configuration.SetElementValue(xNameSpace + includesElement.Name.ToString(), null);

            // add includes and excludes from user inputs
            configuration.Add(includesElement);
            configuration.Add(excludesElement);
        }
        private void CreateReportPomForMultiModule(string multiModulePomFilePath, XNamespace xNameSpace, XElement pomXml, CodeCoverageEnablerInputs mavenCcParams)
        {
            try
            {
                if (File.Exists(multiModulePomFilePath))
                {
                    File.Delete(multiModulePomFilePath);
                }
            }
            catch (IOException e)
            {
                _executionContext.Error(e);
            }

            try
            {
                var reportXml = GetReportPomXml(xNameSpace, pomXml, mavenCcParams);
                var settings  = new XmlReaderSettings
                {
                    DtdProcessing = DtdProcessing.Prohibit
                };
                using (XmlReader reader = XmlReader.Create(new StringReader(reportXml), settings))
                {
                    XmlDocument xdoc = new XmlDocument();
                    xdoc.Load(reader);
                    using (FileStream stream = new FileStream(multiModulePomFilePath, FileMode.Create))
                    {
                        xdoc.Save(stream);
                    }
                }
            }
            catch (XmlException e)
            {
                _executionContext.Warning(StringUtil.Loc("InvalidBuildXml", multiModulePomFilePath, e.Message));
                throw;
            }
        }
        private string GetGradleCoberturaReport(CodeCoverageEnablerInputs gradleCCParams)
        {
            var coberturaExclude = CodeCoverageUtilities.TrimToEmptyString(gradleCCParams.Exclude);
            var coberturaInclude = CodeCoverageUtilities.TrimToEmptyString(gradleCCParams.Include);
            var exclude = string.IsNullOrEmpty(coberturaExclude) ? string.Empty : string.Join(",", coberturaExclude.Split(':').Select(exclPackage => exclPackage.EndsWith("*") ? "'.*" + exclPackage.TrimEnd('*') + ".*'" : "'.*" + exclPackage + "'"));
            var include = string.IsNullOrEmpty(coberturaInclude) ? string.Empty : string.Join(",", coberturaInclude.Split(':').Select(inclPackage => inclPackage.EndsWith("*") ? "'.*" + inclPackage.TrimEnd('*') + ".*'" : "'.*" + inclPackage + "'"));
            var classDirectories = string.Join(",", gradleCCParams.ClassFilesDirectories.Split(',').Select(exclPackage => "'" + exclPackage + "'"));
            var enableCobertura = GetCoberturaPluginScriptForGradle(include, exclude);

            if (!gradleCCParams.IsMultiModule)
            {
                enableCobertura = string.Concat(enableCobertura, GetCoberturaReportingScriptForSingleModuleGradle(classDirectories, null,
                    gradleCCParams.ReportDirectory));
            }
            else
            {
                enableCobertura = string.Concat(enableCobertura, GetCoberturaReportingScriptForMultiModuleGradle(classDirectories, null,
                    gradleCCParams.ReportDirectory));
            }

            return enableCobertura;
        }
        private void EnableJacocoForBuildFile(string buildFile, CodeCoverageEnablerInputs antCCParams)
        {
            var buildXml = new XmlDocument();
            try
            {
                var settings = new XmlReaderSettings
                {
                    DtdProcessing = DtdProcessing.Prohibit,
                };

                using (XmlReader reader = XmlReader.Create(buildFile, settings))
                {
                    buildXml.Load(reader);
                }
            }
            catch (XmlException e)
            {
                if (buildFile.Equals(antCCParams.BuildFile))
                {
                    _executionContext.Warning(StringUtil.Loc("InvalidBuildXml", buildFile, e.Message));
                    throw;
                }
                else
                {
                    _executionContext.Debug(StringUtil.Format(CodeCoverageConstants.InvalidXMLTemplate, buildFile, e.Message));
                }
                return;
            }

            // see jacoco ant documentation for more details. http://www.eclemma.org/jacoco/trunk/doc/ant.html
            if (!string.IsNullOrWhiteSpace(buildXml.OuterXml))
            {
                var junitNodes = buildXml.SelectNodes("project//junit");
                var javaNodes = buildXml.SelectNodes("project//java");
                var testngNodes = buildXml.SelectNodes("project//testng");

                //collect code coverage
                CollectCodeCoverageForNodes(junitNodes, antCCParams, buildXml, true);
                CollectCodeCoverageForNodes(javaNodes, antCCParams, buildXml);
                CollectCodeCoverageForNodes(testngNodes, antCCParams, buildXml);

                var batchTestNodes = buildXml.SelectNodes("project//batchtest");
                for (var index = 0; index < batchTestNodes.Count; index++)
                {
                    ((XmlElement)batchTestNodes[index]).SetAttribute("fork", "true");
                    _executionContext.Debug(StringUtil.Format(CodeCoverageConstants.SettingAttributeTemplate, "fork", "true", "batchtest"));
                }

                // remove existing jacoco reports
                var isReportNodeExists = RemoveCoverageReports(buildXml);

                if (!(junitNodes.Count == 0 && javaNodes.Count == 0 && testngNodes.Count == 0) || isReportNodeExists)
                {
                    // buildFile is edited
                    _executionContext.Debug(StringUtil.Format(CodeCoverageConstants.EnablingEditingTemplate, "jacoco", "ant", buildFile));
                }
                using (FileStream stream = new FileStream(buildFile, FileMode.Create))
                {
                    buildXml.Save(stream);
                }
            }
        }
        private string GetAntReport(CodeCoverageEnablerInputs antCCParams)
        {
            var executionData = string.Empty;
            executionData += @"             <file file='" + Path.Combine(antCCParams.ReportDirectory, _jacocoExecPrefix + ".exec") + @"'/>" + Environment.NewLine;


            var srcData = CodeCoverageUtilities.GetSourceDataForJacoco(antCCParams.SourceDirectories);
            var classData = CodeCoverageUtilities.GetClassDataForAnt(antCCParams.Include, antCCParams.Exclude, antCCParams.ClassFilesDirectories);

            return string.Format(CodeCoverageConstants.JacocoAntReport, antCCParams.CCReportTask, executionData, classData, srcData, antCCParams.ReportDirectory, Path.Combine(antCCParams.ReportDirectory, "report.csv"), Path.Combine(antCCParams.ReportDirectory, antCCParams.SummaryFile));
        }
 private void CollectCodeCoverageForNodes(XmlNodeList nodes, CodeCoverageEnablerInputs antCCParams, XmlDocument buildXml, bool enableForkMode = false)
 {
     for (var index = 0; index < nodes.Count; index++)
     {
         CollectAntCodeCoverageForNode(antCCParams.ReportDirectory, antCCParams.Include, antCCParams.Exclude, (XmlElement)nodes[index], buildXml);
         if (enableForkMode)
         {
             ((XmlElement)nodes[index]).SetAttribute("forkmode", "once");
             _executionContext.Debug(StringUtil.Format(CodeCoverageConstants.SettingAttributeTemplate, "forkmode", "once", "junit"));
         }
     }
 }
        private XmlNode GetInstrumentNode(CodeCoverageEnablerInputs antCCParams, string instrumentedClassesDirectory, string dataFile)
        {
            var inclusionExclusionSet = CodeCoverageUtilities.GetClassDataForAnt(antCCParams.Include, antCCParams.Exclude, antCCParams.ClassFilesDirectories);

            var targetXml = string.Format(CodeCoverageConstants.CoberturaInstrumentNode, instrumentedClassesDirectory, dataFile, inclusionExclusionSet);

            return GetXmlNode(targetXml);
        }
Example #27
0
        private void AddConfigurationDefaults(XElement configuration, XNamespace xNameSpace, CodeCoverageEnablerInputs mavenCcParams)
        {
            var excludesElement = CodeCoverageUtilities.GetClassDataForMaven(mavenCcParams.Exclude, "excludes", "exclude");
            var includesElement = CodeCoverageUtilities.GetClassDataForMaven(mavenCcParams.Include, "includes", "include");

            var formatElement = GetFormatsElement();

            var instrumentationNode = configuration.Element(xNameSpace + "instrumentation");

            if (instrumentationNode != null)
            {
                // remove any existing excludes and includes. We cannot directly set the values here as the value is not one single object but multiple xelements
                instrumentationNode.Remove();
            }

            var formatsNode = configuration.Element(xNameSpace + "formats");

            if (formatsNode != null)
            {
                formatsNode.Remove();
            }

            //Adding formats
            configuration.Add(formatElement);

            // add includes and excludes from user inputs
            configuration.Add(new XElement(xNameSpace + "instrumentation", includesElement, excludesElement));

            var aggregateNode = configuration.Element(xNameSpace + "aggregate");

            if (aggregateNode != null && _isMultiModule)
            {
                aggregateNode.Value = "true";
            }
            else if (_isMultiModule)
            {
                configuration.Add(new XElement(xNameSpace + "aggregate", "true"));
            }
        }
        private void SetPluginsForJacoco(CodeCoverageEnablerInputs mavenCcParams, XElement plugins, XNamespace xNameSpace, XElement defaultConfigurationElement, XElement defaultExecutions, bool addIfNotExists)
        {
            IList<XElement> pluginList = plugins.Elements(xNameSpace + "plugin").ToList();
            var hasJacocoPlugin = false;

            foreach (var plugin in pluginList.Where(plugin =>
            {
                var groupId = plugin.Element(xNameSpace + "groupId");
                var artifactId = plugin.Element(xNameSpace + "artifactId");
                return (artifactId != null && artifactId.Value == _jacocoArtifactId)
                    || (groupId != null && groupId.Value == _jacocoGroupId);
            }))
            {
                _executionContext.Debug("A jacoco plugin already exists. Adding/Editing the configuration values to match inputs provided in the task.");

                // jacoco plugin
                hasJacocoPlugin = true;

                // set the values to ensure artifactid and groupid are both not null
                plugin.SetElementValue(xNameSpace + "groupId", _jacocoGroupId);
                plugin.SetElementValue(xNameSpace + "artifactId", _jacocoArtifactId);

                // dont change the existing jacoco version as it needs particular version of maven
                var versionElements = plugin.Elements(xNameSpace + "version").ToList();
                if (versionElements.Count == 0)
                {
                    // add version element if it is not there
                    plugin.SetElementValue(xNameSpace + "version", _jacocoVersion);
                }
                else
                {
                    _jacocoVersion = versionElements[0].Value;
                }

                // Edit the root configurations to default values. ie., user inputs.
                IList<XElement> rootConfigurations = plugin.Elements(xNameSpace + "configuration").ToList();

                // If there is no root configuration add one
                if (rootConfigurations.Count == 0)
                {
                    plugin.Add(defaultConfigurationElement);
                }
                else
                {
                    foreach (var rootConfiguration in rootConfigurations)
                    {
                        AddConfigurationDefaults(rootConfiguration, xNameSpace, mavenCcParams);
                    }
                }

                // <executions> <execution> <configuration/> </execution> </executions>
                IList<XElement> executionsElements = plugin.Elements(xNameSpace + "executions").ToList();

                // if executions element doesnt exist add it.
                if (executionsElements.Count == 0)
                {
                    plugin.Add(defaultExecutions);
                }
                else
                {
                    foreach (var executionsElement in executionsElements)
                    {
                        IList<XElement> executionElements = executionsElement.Elements(xNameSpace + "execution").ToList();

                        foreach (var executionElement in executionElements)
                        {
                            // isPrepartAgentExecution is a hack, without this +: filter shows 0% coverage. 
                            // Here we are collecting code coverage for all class files but reports are generated according to include/exclude filters
                            var isPrepartAgentExecution = IsPrepareAgentExecution(executionElement, xNameSpace);

                            //  Edit the configurations of executionsElements to default values. ie., user inputs.
                            IList<XElement> configurations = executionElement.Elements(xNameSpace + "configuration").ToList();
                            foreach (var configuration in configurations)
                            {
                                AddConfigurationDefaults(configuration, xNameSpace, mavenCcParams, isPrepartAgentExecution);
                            }
                            if (_isMultiModule)
                            {
                                // remove the report goal.
                                IList<XElement> goalsElements = executionElement.Elements(xNameSpace + "goals").ToList();
                                foreach (var goalsElement in goalsElements)
                                {
                                    IList<XElement> goalElements = goalsElement.Elements(xNameSpace + "goal").ToList();
                                    for (int index = 0; index < goalElements.Count; index++)
                                    {
                                        if (goalElements[index].Value.Equals("report", StringComparison.OrdinalIgnoreCase))
                                        {
                                            goalsElements[index].Remove();
                                        }
                                    }
                                }
                            }
                        }

                        // add default execution nodes to make sure we are not missing default coverage
                        executionsElement.Add(defaultExecutions.Elements().ToList());
                    }
                }
            }

            if (addIfNotExists && !hasJacocoPlugin)
            {
                _executionContext.Debug("Adding a jacoco plugin.");
                // if there is no jacoco plugin add one
                plugins.Add(GetDefaultJacocoPlugin(defaultConfigurationElement, defaultExecutions));
            }
        }
        private void AddConfigurationDefaults(XElement configuration, XNamespace xNameSpace, CodeCoverageEnablerInputs mavenCcParams)
        {
            var excludesElement = CodeCoverageUtilities.GetClassDataForMaven(mavenCcParams.Exclude, "excludes", "exclude");
            var includesElement = CodeCoverageUtilities.GetClassDataForMaven(mavenCcParams.Include, "includes", "include");

            var formatElement = GetFormatsElement();

            var instrumentationNode = configuration.Element(xNameSpace + "instrumentation");

            if (instrumentationNode != null)
            {
                // remove any existing excludes and includes. We cannot directly set the values here as the value is not one single object but multiple xelements
                instrumentationNode.Remove();
            }

            var formatsNode = configuration.Element(xNameSpace + "formats");

            if (formatsNode != null)
            {
                formatsNode.Remove();
            }

            //Adding formats  
            configuration.Add(formatElement);

            // add includes and excludes from user inputs
            configuration.Add(new XElement(xNameSpace + "instrumentation", includesElement, excludesElement));

            var aggregateNode = configuration.Element(xNameSpace + "aggregate");

            if (aggregateNode != null && _isMultiModule)
            {
                aggregateNode.Value = "true";
            }
            else if (_isMultiModule)
            {
                configuration.Add(new XElement(xNameSpace + "aggregate", "true"));
            }
        }
        private void CreateReportPomForMultiModule(string multiModulePomFilePath, XNamespace xNameSpace, XElement pomXml, CodeCoverageEnablerInputs mavenCcParams)
        {
            try
            {
                if (File.Exists(multiModulePomFilePath))
                {
                    File.Delete(multiModulePomFilePath);
                }
            }
            catch (IOException e)
            {
                _executionContext.Error(e);
            }

            try
            {
                var reportXml = GetReportPomXml(xNameSpace, pomXml, mavenCcParams);
                var settings = new XmlReaderSettings
                {
                    DtdProcessing = DtdProcessing.Prohibit
                };
                using (XmlReader reader = XmlReader.Create(new StringReader(reportXml), settings))
                {
                    XmlDocument xdoc = new XmlDocument();
                    xdoc.Load(reader);
                    using (FileStream stream = new FileStream(multiModulePomFilePath, FileMode.Create))
                    {
                        xdoc.Save(stream);
                    }
                }
            }
            catch (XmlException e)
            {
                _executionContext.Warning(StringUtil.Loc("InvalidBuildXml", multiModulePomFilePath, e.Message));
                throw;
            }
        }
        private string GetReportPomXml(XNamespace xNameSpace, XElement pomXml, CodeCoverageEnablerInputs mavenCcParams)
        {
            string settings = string.Empty;

            settings += GetSettingsForPom(xNameSpace, pomXml);


            var srcDirectories        = CodeCoverageUtilities.SetCurrentDirectoryIfDirectoriesParameterIsEmpty(_executionContext, mavenCcParams.SourceDirectories, StringUtil.Loc("SourceDirectoriesNotSpecifiedForMultiModule"));
            var classFilesDirectories = CodeCoverageUtilities.SetCurrentDirectoryIfDirectoriesParameterIsEmpty(_executionContext, mavenCcParams.ClassFilesDirectories, StringUtil.Loc("ClassDirectoriesNotSpecifiedForMultiModule"));

            var srcData   = CodeCoverageUtilities.GetSourceDataForJacoco(srcDirectories);
            var classData = CodeCoverageUtilities.GetClassDataForAnt(mavenCcParams.Include, mavenCcParams.Exclude, classFilesDirectories);

            var execFile    = Path.Combine(mavenCcParams.ReportDirectory, _jacocoExecPrefix + ".exec");
            var csvFile     = Path.Combine(mavenCcParams.ReportDirectory, "report.csv");
            var summaryFile = Path.Combine(mavenCcParams.ReportDirectory, mavenCcParams.SummaryFile);

            // ref https://dzone.com/articles/jacoco-maven-multi-module

            return
                (@"<?xml version='1.0' encoding='UTF-8'?>" + Environment.NewLine +
                 @" <project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd'>" + Environment.NewLine +
                 settings +
                 @"   <build>" + Environment.NewLine +
                 @"      <plugins>" + Environment.NewLine +
                 @"         <plugin>" + Environment.NewLine +
                 @"            <groupId>org.apache.maven.plugins</groupId>" + Environment.NewLine +
                 @"            <artifactId>maven-antrun-plugin</artifactId>" + Environment.NewLine +
                 @"            <version>" + _mavenAntRunPluginVersion + @"</version>" + Environment.NewLine +
                 @"            <executions>" + Environment.NewLine +
                 @"               <execution>" + Environment.NewLine +
                 @"                  <phase>post-integration-test</phase>" + Environment.NewLine +
                 @"                  <goals>" + Environment.NewLine +
                 @"                     <goal>run</goal>" + Environment.NewLine +
                 @"                  </goals>" + Environment.NewLine +
                 @"                  <configuration>" + Environment.NewLine +
                 @"                     <target>" + Environment.NewLine +
                 @"                        <echo message='Generating JaCoCo Reports' />" + Environment.NewLine +
                 @"                        <taskdef name='report' classname='org.jacoco.ant.ReportTask'>" + Environment.NewLine +
                 @"                           <classpath path='{basedir}/target/jacoco-jars/org.jacoco.ant.jar' />" + Environment.NewLine +
                 @"                       </taskdef>" + Environment.NewLine +
                 @"                        <report>" + Environment.NewLine +
                 @"                           <executiondata>" + Environment.NewLine +
                 @"                              <file file='" + execFile + @"' />" + Environment.NewLine +
                 @"                           </executiondata>" + Environment.NewLine +
                 @"                           <structure name='Jacoco report'>" + Environment.NewLine +
                 @"                              <classfiles>" + Environment.NewLine +
                 classData +
                 @"                              </classfiles>" + Environment.NewLine +
                 @"                              <sourcefiles encoding = 'UTF-8'>" + Environment.NewLine +
                 srcData +
                 @"                              </sourcefiles>" + Environment.NewLine +
                 @"                           </structure>" + Environment.NewLine +
                 @"                           <html destdir='" + mavenCcParams.ReportDirectory + @"' />" + Environment.NewLine +
                 @"                           <xml destfile='" + summaryFile + @"' />" + Environment.NewLine +
                 @"                           <csv destfile='" + csvFile + @"' />" + Environment.NewLine +
                 @"                        </report>" + Environment.NewLine +
                 @"                     </target>" + Environment.NewLine +
                 @"                  </configuration>" + Environment.NewLine +
                 @"               </execution>" + Environment.NewLine +
                 @"            </executions>" + Environment.NewLine +
                 @"            <dependencies>" + Environment.NewLine +
                 @"               <dependency>" + Environment.NewLine +
                 @"                  <groupId>org.jacoco</groupId>" + Environment.NewLine +
                 @"                  <artifactId>org.jacoco.ant</artifactId>" + Environment.NewLine +
                 @"                  <version>" + _jacocoVersion + @"</version>" + Environment.NewLine +
                 @"               </dependency>" + Environment.NewLine +
                 @"            </dependencies>" + Environment.NewLine +
                 @"         </plugin>" + Environment.NewLine +
                 @"     </plugins>" + Environment.NewLine +
                 @"   </build>" + Environment.NewLine +
                 @" </project>");
        }
 private string GetAntReport(CodeCoverageEnablerInputs ccInputs, string dataFile)
 {
     var targetXml = string.Format(CodeCoverageConstants.CoberturaAntReport, AddEnvProperty().OuterXml, AddPathForCobertura().OuterXml, AddTaskDefForCobertura().OuterXml,
                                 ccInputs.CCReportTask, ccInputs.ReportDirectory, dataFile, ccInputs.SourceDirectories);
     return targetXml;
 }
        public void EnableCodeCoverage(IExecutionContext context, CodeCoverageEnablerInputs ccInputs)
        {
            Trace.Entering();

            ccInputs.VerifyInputsForJacocoGradle();

            context.Debug(StringUtil.Format(CodeCoverageConstants.EnablingEditingTemplate, "jacoco", "gradle", ccInputs.BuildFile));

            var buildScript = new FileInfo(ccInputs.BuildFile);

            if (buildScript.Length == 0)
            {
                throw new InvalidOperationException(StringUtil.Loc("CodeCoverageBuildFileIsEmpty", ccInputs.BuildFile));
            }

            // see jacoco gradle documentation for more details. https://docs.gradle.org/current/userguide/jacoco_plugin.html

            var jacocoExclude = CodeCoverageUtilities.TrimToEmptyString(ccInputs.Exclude).Replace('.', '/');
            var jacocoInclude = CodeCoverageUtilities.TrimToEmptyString(ccInputs.Include).Replace('.', '/');
            var exclude = string.IsNullOrEmpty(jacocoExclude) ? string.Empty : string.Join(",", jacocoExclude.Split(':').Select(
                exclPackage => exclPackage.EndsWith("*") ? ("'" + exclPackage + "/**'") : ("'" + exclPackage + ".class'")));
            var include = string.IsNullOrEmpty(jacocoInclude) ? string.Empty : string.Join(",", jacocoInclude.Split(':').Select(
                inclPackage => inclPackage.EndsWith("*") ? ("'" + inclPackage + "/**'") : ("'" + inclPackage + ".class'")));

            var enableJacoco = string.Empty;

            if (ccInputs.IsMultiModule)
            {
                enableJacoco = @"
                    allprojects { apply plugin: 'jacoco' }

                    allprojects {
	                    repositories {
                            mavenCentral()
                        }
                    }

                    def jacocoExcludes = [" + CodeCoverageUtilities.TrimToEmptyString(exclude) + @"]
                    def jacocoIncludes = [" + CodeCoverageUtilities.TrimToEmptyString(include) + @"]

                    subprojects {
	
                        jacocoTestReport {
		                    doFirst {
			                    classDirectories = fileTree(dir: """ + ccInputs.ClassFilesDirectories + @""").exclude(jacocoExcludes).include(jacocoIncludes)
		                    }
		
		                    reports {
			                    html.enabled = true
			                    html.destination ""${buildDir}/jacocoHtml""
                                xml.enabled = true    
	                            xml.destination ""${buildDir}" + "/" + _summaryFile + @"""
                            }
                        }
	
	                    test {
		                    jacoco {
			                    append = true
			                    destinationFile = file(""" + ccInputs.ReportDirectory + "/" + _jacocoExecPrefix + ".exec\"" + @")
		                    }
	                    }
                    }" + @"
                    task jacocoRootReport(type: org.gradle.testing.jacoco.tasks.JacocoReport) {
	                    dependsOn = subprojects.test
	                    executionData = files(subprojects.jacocoTestReport.executionData)
	                    sourceDirectories = files(subprojects.sourceSets.main.allSource.srcDirs)
	                    classDirectories = files()
	
	                    doFirst {
		                    subprojects.each {
			                    if (new File(""${it.sourceSets.main.output.classesDir}"").exists()) {
				                    logger.info(""Class directory exists in sub project: ${it.name}"")
				                    logger.info(""Adding class files ${it.sourceSets.main.output.classesDir}"")
				                    classDirectories += fileTree(dir: ""${it.sourceSets.main.output.classesDir}"", includes: jacocoIncludes, excludes: jacocoExcludes)
			                    } else {
				                    logger.error(""Class directory does not exist in sub project: ${it.name}"")
			                    }
		                    }
	                    }
	
	                    reports {
		                    html.enabled = true
                            xml.enabled = true    
		                    xml.destination """ + ccInputs.ReportDirectory + "/" + _summaryFile + @"""
		                    html.destination """ + ccInputs.ReportDirectory + @"""
	                    }
                    }
                    ";
            }
            else
            {
                enableJacoco = @"
                    allprojects { apply plugin: 'jacoco' }

                    allprojects {
	                    repositories {
                            mavenCentral()
                        }
                    }

                    def jacocoExcludes = [" + CodeCoverageUtilities.TrimToEmptyString(exclude) + @"]
                    def jacocoIncludes = [" + CodeCoverageUtilities.TrimToEmptyString(include) + @"]


	
                    jacocoTestReport {
	                    doFirst {
		                    classDirectories = fileTree(dir: """ + ccInputs.ClassFilesDirectories + @""").exclude(jacocoExcludes).include(jacocoIncludes)
	                    }
		
	                    reports {
	                        html.enabled = true
                            xml.enabled = true    
	                        xml.destination """ + ccInputs.ReportDirectory + "/" + _summaryFile + @"""
	                        html.destination """ + ccInputs.ReportDirectory + @"""
                        }
                    }
	
                    test {
                        finalizedBy jacocoTestReport
	                    jacoco {
		                    append = true
		                    destinationFile = file(""" + ccInputs.ReportDirectory + "/" + _jacocoExecPrefix + ".exec\"" + @")
	                    }
                    }
                    ";
            }
            File.AppendAllText(ccInputs.BuildFile, enableJacoco);
            context.Output(StringUtil.Loc("CodeCoverageEnabled", "jacoco", "gradle"));
        }
        private void AddConfigurationDefaults(XElement configuration, XNamespace xNameSpace, CodeCoverageEnablerInputs mavenCcParams, bool isPrepartAgentExecution = false)
        {
            var excludesElement = CodeCoverageUtilities.GetClassDataForMaven(mavenCcParams.Exclude, "excludes", "exclude", true);
            XElement includesElement;
            if (!isPrepartAgentExecution)
            {
                includesElement = CodeCoverageUtilities.GetClassDataForMaven(mavenCcParams.Include, "includes", "include", true);
            }
            else
            {
                includesElement = new XElement("includes",
                                new XElement("include", "**/*"));
            }

            configuration.SetElementValue(xNameSpace + "destFile", Path.Combine(mavenCcParams.ReportDirectory, _jacocoExecPrefix + ".exec"));
            configuration.SetElementValue(xNameSpace + "outputDirectory", mavenCcParams.ReportDirectory);
            configuration.SetElementValue(xNameSpace + "dataFile", Path.Combine(mavenCcParams.ReportDirectory, _jacocoExecPrefix + ".exec"));
            configuration.SetElementValue(xNameSpace + "append", "true");

            // remove any existing excludes and includes. We cannot directly set the values here as the value is not one single object but multiple xelements
            configuration.SetElementValue(xNameSpace + excludesElement.Name.ToString(), null);
            configuration.SetElementValue(xNameSpace + includesElement.Name.ToString(), null);

            // add includes and excludes from user inputs
            configuration.Add(includesElement);
            configuration.Add(excludesElement);
        }
        private void SetPluginsForCobertura(CodeCoverageEnablerInputs mavenCcParams, XElement plugins, XNamespace xNameSpace, XElement defaultConfigurationElement, XElement defaultExecutions, bool addIfNotExists)
        {
            IList<XElement> pluginList = plugins.Elements(xNameSpace + _pluginTag).ToList();
            var hasCoberturaPlugin = false;

            foreach (var plugin in pluginList.Where(plugin =>
            {
                var groupId = plugin.Element(xNameSpace + "groupId");
                var artifactId = plugin.Element(xNameSpace + "artifactId");
                return (artifactId != null && artifactId.Value == _coberturaArtifactId)
                    && (groupId != null && groupId.Value == _coberturaGroupId);
            }))
            {
                _executionContext.Debug("A cobertura plugin already exists. Adding/Editing the configuration values to match inputs provided in the task.");

                hasCoberturaPlugin = true;

                var versionElements = plugin.Elements(xNameSpace + "version").ToList();
                if (versionElements.Count == 0)
                {
                    // add version element if it is not there
                    plugin.SetElementValue(xNameSpace + "version", _coberturaVersion);
                }
                else
                {
                    _coberturaVersion = versionElements[0].Value;
                }

                // Edit the root configurations to default values. ie., user inputs.
                IList<XElement> rootConfigurations = plugin.Elements(xNameSpace + "configuration").ToList();

                // If there is no root configuration add one
                if (rootConfigurations.Count == 0)
                {
                    plugin.Add(defaultConfigurationElement);
                }
                else
                {
                    foreach (var rootConfiguration in rootConfigurations)
                    {
                        AddConfigurationDefaults(rootConfiguration, xNameSpace, mavenCcParams);
                    }
                }

                // <executions> <execution> <configuration/> </execution> </executions>
                IList<XElement> executionsElements = plugin.Elements(xNameSpace + "executions").ToList();

                // if executions element doesnt exist add it.
                if (executionsElements.Count == 0)
                {
                    plugin.Add(defaultExecutions);
                }
            }

            if (addIfNotExists && !hasCoberturaPlugin)
            {
                _executionContext.Debug("Adding a cobertura plugin.");
                // if there is no cobertura plugin add one
                plugins.Add(GetDefaultCoberturaPlugin(defaultConfigurationElement, defaultExecutions));
            }
        }
        private string GetReportPomXml(XNamespace xNameSpace, XElement pomXml, CodeCoverageEnablerInputs mavenCcParams)
        {
            string settings = string.Empty;
            settings += GetSettingsForPom(xNameSpace, pomXml);


            var srcDirectories = CodeCoverageUtilities.SetCurrentDirectoryIfDirectoriesParameterIsEmpty(_executionContext, mavenCcParams.SourceDirectories, StringUtil.Loc("SourceDirectoriesNotSpecifiedForMultiModule"));
            var classFilesDirectories = CodeCoverageUtilities.SetCurrentDirectoryIfDirectoriesParameterIsEmpty(_executionContext, mavenCcParams.ClassFilesDirectories, StringUtil.Loc("ClassDirectoriesNotSpecifiedForMultiModule"));

            var srcData = CodeCoverageUtilities.GetSourceDataForJacoco(srcDirectories);
            var classData = CodeCoverageUtilities.GetClassDataForAnt(mavenCcParams.Include, mavenCcParams.Exclude, classFilesDirectories);

            var execFile = Path.Combine(mavenCcParams.ReportDirectory, _jacocoExecPrefix + ".exec");
            var csvFile = Path.Combine(mavenCcParams.ReportDirectory, "report.csv");
            var summaryFile = Path.Combine(mavenCcParams.ReportDirectory, mavenCcParams.SummaryFile);

            // ref https://dzone.com/articles/jacoco-maven-multi-module

            return
                @"<?xml version='1.0' encoding='UTF-8'?>" + Environment.NewLine +
                @" <project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd'>" + Environment.NewLine +
                settings +
                @"   <build>" + Environment.NewLine +
                @"      <plugins>" + Environment.NewLine +
                @"         <plugin>" + Environment.NewLine +
                @"            <groupId>org.apache.maven.plugins</groupId>" + Environment.NewLine +
                @"            <artifactId>maven-antrun-plugin</artifactId>" + Environment.NewLine +
                @"            <version>" + _mavenAntRunPluginVersion + @"</version>" + Environment.NewLine +
                @"            <executions>" + Environment.NewLine +
                @"               <execution>" + Environment.NewLine +
                @"                  <phase>post-integration-test</phase>" + Environment.NewLine +
                @"                  <goals>" + Environment.NewLine +
                @"                     <goal>run</goal>" + Environment.NewLine +
                @"                  </goals>" + Environment.NewLine +
                @"                  <configuration>" + Environment.NewLine +
                @"                     <target>" + Environment.NewLine +
                @"                        <echo message='Generating JaCoCo Reports' />" + Environment.NewLine +
                @"                        <taskdef name='report' classname='org.jacoco.ant.ReportTask'>" + Environment.NewLine +
                @"                           <classpath path='{basedir}/target/jacoco-jars/org.jacoco.ant.jar' />" + Environment.NewLine +
                @"                       </taskdef>" + Environment.NewLine +
                @"                        <report>" + Environment.NewLine +
                @"                           <executiondata>" + Environment.NewLine +
                @"                              <file file='" + execFile + @"' />" + Environment.NewLine +
                @"                           </executiondata>" + Environment.NewLine +
                @"                           <structure name='Jacoco report'>" + Environment.NewLine +
                @"                              <classfiles>" + Environment.NewLine +
                classData +
                @"                              </classfiles>" + Environment.NewLine +
                @"                              <sourcefiles encoding = 'UTF-8'>" + Environment.NewLine +
                srcData +
                @"                              </sourcefiles>" + Environment.NewLine +
                @"                           </structure>" + Environment.NewLine +
                @"                           <html destdir='" + mavenCcParams.ReportDirectory + @"' />" + Environment.NewLine +
                @"                           <xml destfile='" + summaryFile + @"' />" + Environment.NewLine +
                @"                           <csv destfile='" + csvFile + @"' />" + Environment.NewLine +
                @"                        </report>" + Environment.NewLine +
                @"                     </target>" + Environment.NewLine +
                @"                  </configuration>" + Environment.NewLine +
                @"               </execution>" + Environment.NewLine +
                @"            </executions>" + Environment.NewLine +
                @"            <dependencies>" + Environment.NewLine +
                @"               <dependency>" + Environment.NewLine +
                @"                  <groupId>org.jacoco</groupId>" + Environment.NewLine +
                @"                  <artifactId>org.jacoco.ant</artifactId>" + Environment.NewLine +
                @"                  <version>" + _jacocoVersion + @"</version>" + Environment.NewLine +
                @"               </dependency>" + Environment.NewLine +
                @"            </dependencies>" + Environment.NewLine +
                @"         </plugin>" + Environment.NewLine +
                @"     </plugins>" + Environment.NewLine +
                @"   </build>" + Environment.NewLine +
                @" </project>";
        }
Example #37
0
        private void EnableJacocoForBuildFile(string buildFile, CodeCoverageEnablerInputs antCCParams)
        {
            var buildXml = new XmlDocument();

            try
            {
                var settings = new XmlReaderSettings
                {
                    DtdProcessing = DtdProcessing.Prohibit,
                };

                using (XmlReader reader = XmlReader.Create(buildFile, settings))
                {
                    buildXml.Load(reader);
                }
            }
            catch (XmlException e)
            {
                if (buildFile.Equals(antCCParams.BuildFile))
                {
                    _executionContext.Warning(StringUtil.Loc("InvalidBuildXml", buildFile, e.Message));
                    throw;
                }
                else
                {
                    _executionContext.Debug(StringUtil.Format(CodeCoverageConstants.InvalidXMLTemplate, buildFile, e.Message));
                }
                return;
            }

            // see jacoco ant documentation for more details. http://www.eclemma.org/jacoco/trunk/doc/ant.html
            if (!string.IsNullOrWhiteSpace(buildXml.OuterXml))
            {
                var junitNodes  = buildXml.SelectNodes("project//junit");
                var javaNodes   = buildXml.SelectNodes("project//java");
                var testngNodes = buildXml.SelectNodes("project//testng");

                //collect code coverage
                CollectCodeCoverageForNodes(junitNodes, antCCParams, buildXml, true);
                CollectCodeCoverageForNodes(javaNodes, antCCParams, buildXml);
                CollectCodeCoverageForNodes(testngNodes, antCCParams, buildXml);

                var batchTestNodes = buildXml.SelectNodes("project//batchtest");
                for (var index = 0; index < batchTestNodes.Count; index++)
                {
                    ((XmlElement)batchTestNodes[index]).SetAttribute("fork", "true");
                    _executionContext.Debug(StringUtil.Format(CodeCoverageConstants.SettingAttributeTemplate, "fork", "true", "batchtest"));
                }

                // remove existing jacoco reports
                var isReportNodeExists = RemoveCoverageReports(buildXml);

                if (!(junitNodes.Count == 0 && javaNodes.Count == 0 && testngNodes.Count == 0) || isReportNodeExists)
                {
                    // buildFile is edited
                    _executionContext.Debug(StringUtil.Format(CodeCoverageConstants.EnablingEditingTemplate, "jacoco", "ant", buildFile));
                }
                using (FileStream stream = new FileStream(buildFile, FileMode.Create))
                {
                    buildXml.Save(stream);
                }
            }
        }
Example #38
0
        public void EnableCodeCoverage(IExecutionContext context, CodeCoverageEnablerInputs ccInputs)
        {
            Trace.Entering();
            _executionContext = context;

            context.Debug(StringUtil.Format(CodeCoverageConstants.EnablingEditingTemplate, "cobertura", "maven", ccInputs.BuildFile));

            XElement pomXml;

            try
            {
                pomXml = XElement.Load(ccInputs.BuildFile);
            }
            catch (XmlException e)
            {
                _executionContext.Warning(StringUtil.Loc("InvalidBuildXml", ccInputs.BuildFile, e.Message));
                throw;
            }

            XNamespace xNameSpace = pomXml.Attribute("xmlns").Value;

            if (pomXml.Element(xNameSpace + "modules") != null)
            {
                // aa multi module project
                _isMultiModule = true;
                context.Debug("This is a multi module project. Generating code coverage reports using ant task.");
            }

            // Add a build element if doesnot exist.
            var build = pomXml.Element(xNameSpace + "build");

            if (build == null)
            {
                pomXml.Add(new XElement(xNameSpace + "build"));
                build = pomXml.Element(xNameSpace + "build");
            }

            // Set cobertura plugins to enable code coverage.
            SetPlugins(build, ccInputs, xNameSpace);

            // Adding reporting enabler for cobertura
            var report = pomXml.Element(xNameSpace + "reporting");

            if (report == null)
            {
                pomXml.Add(new XElement(xNameSpace + "reporting"));
                report = pomXml.Element(xNameSpace + "reporting");
            }

            var pluginsInReport = report.Element(xNameSpace + _pluginsTag);

            if (pluginsInReport == null)
            {
                report.Add(new XElement(xNameSpace + _pluginsTag));
                pluginsInReport = report.Element(xNameSpace + _pluginsTag);
            }

            IList <XElement> pluginListInReport = pluginsInReport.Elements(xNameSpace + _pluginTag).ToList();

            foreach (var plugin in pluginListInReport.Where(plugin =>
            {
                var groupId = plugin.Element(xNameSpace + "groupId");
                var artifactId = plugin.Element(xNameSpace + "artifactId");
                return((artifactId != null && artifactId.Value == _coberturaArtifactId) &&
                       (groupId != null && groupId.Value == _coberturaGroupId));
            }))
            {
                plugin.Parent.RemoveAll();
            }

            pluginsInReport.Add(GetDefaultReporting());

            foreach (var e in build.DescendantsAndSelf().Where(e => string.IsNullOrEmpty(e.Name.Namespace.NamespaceName)))
            {
                e.Name = xNameSpace + e.Name.LocalName;
            }

            foreach (var e in report.DescendantsAndSelf().Where(e => string.IsNullOrEmpty(e.Name.Namespace.NamespaceName)))
            {
                e.Name = xNameSpace + e.Name.LocalName;
            }

            using (FileStream stream = new FileStream(ccInputs.BuildFile, FileMode.Create))
            {
                pomXml.Save(stream);
            }
            context.Output(StringUtil.Loc("CodeCoverageEnabled", "cobertura", "maven"));
        }
 private void CollectCodeCoverageForNodes(XmlNodeList nodes, CodeCoverageEnablerInputs ccInputs, XmlDocument buildXml, XmlNode instrumentNode, string instrumentedClassesDirectory, string dataFile, bool enableForkMode = false)
 {
     for (var index = 0; index < nodes.Count; index++)
     {
         var instrumentTag = buildXml.ImportNode(instrumentNode, true);
         CollectAntCodeCoverageForNode(ccInputs.ReportDirectory, ccInputs.Include, ccInputs.Exclude, (XmlElement)nodes[index], buildXml, instrumentTag, instrumentedClassesDirectory, dataFile);
         if (enableForkMode)
         {
             ((XmlElement)nodes[index]).SetAttribute("forkmode", "once");
             _executionContext.Debug(StringUtil.Format(CodeCoverageConstants.SettingAttributeTemplate, "forkmode", "once", "junit"));
         }
     }
 }
Example #40
0
        private void SetPluginsForCobertura(CodeCoverageEnablerInputs mavenCcParams, XElement plugins, XNamespace xNameSpace, XElement defaultConfigurationElement, XElement defaultExecutions, bool addIfNotExists)
        {
            IList <XElement> pluginList = plugins.Elements(xNameSpace + _pluginTag).ToList();
            var hasCoberturaPlugin      = false;

            foreach (var plugin in pluginList.Where(plugin =>
            {
                var groupId = plugin.Element(xNameSpace + "groupId");
                var artifactId = plugin.Element(xNameSpace + "artifactId");
                return((artifactId != null && artifactId.Value == _coberturaArtifactId) &&
                       (groupId != null && groupId.Value == _coberturaGroupId));
            }))
            {
                _executionContext.Debug("A cobertura plugin already exists. Adding/Editing the configuration values to match inputs provided in the task.");

                hasCoberturaPlugin = true;

                var versionElements = plugin.Elements(xNameSpace + "version").ToList();
                if (versionElements.Count == 0)
                {
                    // add version element if it is not there
                    plugin.SetElementValue(xNameSpace + "version", _coberturaVersion);
                }
                else
                {
                    _coberturaVersion = versionElements[0].Value;
                }

                // Edit the root configurations to default values. ie., user inputs.
                IList <XElement> rootConfigurations = plugin.Elements(xNameSpace + "configuration").ToList();

                // If there is no root configuration add one
                if (rootConfigurations.Count == 0)
                {
                    plugin.Add(defaultConfigurationElement);
                }
                else
                {
                    foreach (var rootConfiguration in rootConfigurations)
                    {
                        AddConfigurationDefaults(rootConfiguration, xNameSpace, mavenCcParams);
                    }
                }

                // <executions> <execution> <configuration/> </execution> </executions>
                IList <XElement> executionsElements = plugin.Elements(xNameSpace + "executions").ToList();

                // if executions element doesnt exist add it.
                if (executionsElements.Count == 0)
                {
                    plugin.Add(defaultExecutions);
                }
            }

            if (addIfNotExists && !hasCoberturaPlugin)
            {
                _executionContext.Debug("Adding a cobertura plugin.");
                // if there is no cobertura plugin add one
                plugins.Add(GetDefaultCoberturaPlugin(defaultConfigurationElement, defaultExecutions));
            }
        }
        public void EnableCodeCoverage(IExecutionContext context, CodeCoverageEnablerInputs ccInputs)
        {
            Trace.Entering();
            _executionContext = context;

            ccInputs.VerifyInputsForCoberturaAnt(context);

            var sourcesDirectory = Path.GetDirectoryName(ccInputs.BuildFile);

            if (string.IsNullOrWhiteSpace(sourcesDirectory))
            {
                throw new InvalidOperationException(StringUtil.Loc("InvalidSourceDirectory"));
            }

            var instrumentedClassesDirectory = Path.Combine(Path.GetDirectoryName(ccInputs.BuildFile), _instrumentClassesDir);
            var dataFile = Path.Combine(ccInputs.ReportDirectory, _coberturaSerPrefix + @".ser");

            var buildFiles = Directory.GetFiles(sourcesDirectory, "*.xml", SearchOption.AllDirectories);

            foreach (var buildFile in buildFiles)
            {
                var buildXml = new XmlDocument();

                try
                {
                    var settings = new XmlReaderSettings
                    {
                        DtdProcessing = DtdProcessing.Prohibit
                    };

                    using (XmlReader reader = XmlReader.Create(buildFile, settings))
                    {
                        buildXml.Load(reader);
                    }
                }
                catch (XmlException e)
                {
                    if (buildFile.Equals(ccInputs.BuildFile))
                    {
                        _executionContext.Warning(StringUtil.Loc("InvalidBuildXml", buildFile, e.Message));
                        throw;
                    }
                    else
                    {
                        _executionContext.Debug(StringUtil.Format(CodeCoverageConstants.InvalidXMLTemplate, buildFile, e.Message));
                    }
                    continue;
                }

                if (!string.IsNullOrWhiteSpace(buildXml.OuterXml))
                {
                    //Remove cobertura instrument nodes
                    var isInstrumentNodeExists = RemoveNodesWithName(buildXml, "project//cobertura-instrument");

                    // get instrument node
                    var instrumentNode = GetInstrumentNode(ccInputs, instrumentedClassesDirectory, dataFile);

                    var junitNodes  = buildXml.SelectNodes("project//junit");
                    var javaNodes   = buildXml.SelectNodes("project//java");
                    var testngNodes = buildXml.SelectNodes("project//testng");

                    //collect code coverage
                    CollectCodeCoverageForNodes(junitNodes, ccInputs, buildXml, instrumentNode, instrumentedClassesDirectory, dataFile, true);
                    CollectCodeCoverageForNodes(javaNodes, ccInputs, buildXml, instrumentNode, instrumentedClassesDirectory, dataFile);
                    CollectCodeCoverageForNodes(testngNodes, ccInputs, buildXml, instrumentNode, instrumentedClassesDirectory, dataFile);

                    var batchTestNodes = buildXml.SelectNodes("project//batchtest");
                    for (var index = 0; index < batchTestNodes.Count; index++)
                    {
                        ((XmlElement)batchTestNodes[index]).SetAttribute("fork", "true");
                        _executionContext.Debug(StringUtil.Format(CodeCoverageConstants.SettingAttributeTemplate, "fork", "true", "batchtest"));
                    }

                    // make debug=true for javac nodes
                    var javacNodes = buildXml.SelectNodes("project//javac");
                    for (int index = 0; index < javacNodes.Count; index++)
                    {
                        ((XmlElement)javacNodes[index]).SetAttribute("debug", "true");
                    }

                    // Removing any cobertura report nodes
                    var isReportNodeExists = RemoveNodesWithName(buildXml, "project//cobertura-report");

                    if (!(junitNodes.Count == 0 && javaNodes.Count == 0 && testngNodes.Count == 0) || isInstrumentNodeExists || isReportNodeExists)
                    {
                        // buildFile is edited
                        context.Debug(StringUtil.Format(CodeCoverageConstants.EnablingEditingTemplate, "cobertura", "ant", buildFile));

                        //Adding Path and TaskDef for Cobertura
                        var envProperty = AddEnvProperty();
                        var pathNode    = AddPathForCobertura();
                        var taskDefNode = AddTaskDefForCobertura();
                        var envTag      = buildXml.ImportNode(envProperty, true);
                        var pathTag     = buildXml.ImportNode(pathNode, true);
                        var taskDefTag  = buildXml.ImportNode(taskDefNode, true);

                        buildXml.DocumentElement.InsertBefore(envTag, buildXml.DocumentElement.FirstChild);
                        buildXml.DocumentElement.InsertAfter(pathTag, envTag);
                        buildXml.DocumentElement.InsertAfter(taskDefTag, pathTag);
                    }

                    using (FileStream stream = new FileStream(buildFile, FileMode.Create))
                    {
                        buildXml.Save(stream);
                    }
                }
            }

            // add cobertura report
            CreateCoberturaReport(ccInputs, dataFile);
            context.Output(StringUtil.Loc("CodeCoverageEnabled", "cobertura", "ant"));
        }
        private void SetPluginsForJacoco(CodeCoverageEnablerInputs mavenCcParams, XElement plugins, XNamespace xNameSpace, XElement defaultConfigurationElement, XElement defaultExecutions, bool addIfNotExists)
        {
            IList <XElement> pluginList = plugins.Elements(xNameSpace + "plugin").ToList();
            var hasJacocoPlugin         = false;

            foreach (var plugin in pluginList.Where(plugin =>
            {
                var groupId = plugin.Element(xNameSpace + "groupId");
                var artifactId = plugin.Element(xNameSpace + "artifactId");
                return((artifactId != null && artifactId.Value == _jacocoArtifactId) ||
                       (groupId != null && groupId.Value == _jacocoGroupId));
            }))
            {
                _executionContext.Debug("A jacoco plugin already exists. Adding/Editing the configuration values to match inputs provided in the task.");

                // jacoco plugin
                hasJacocoPlugin = true;

                // set the values to ensure artifactid and groupid are both not null
                plugin.SetElementValue(xNameSpace + "groupId", _jacocoGroupId);
                plugin.SetElementValue(xNameSpace + "artifactId", _jacocoArtifactId);

                // dont change the existing jacoco version as it needs particular version of maven
                var versionElements = plugin.Elements(xNameSpace + "version").ToList();
                if (versionElements.Count == 0)
                {
                    // add version element if it is not there
                    plugin.SetElementValue(xNameSpace + "version", _jacocoVersion);
                }
                else
                {
                    _jacocoVersion = versionElements[0].Value;
                }

                // Edit the root configurations to default values. ie., user inputs.
                IList <XElement> rootConfigurations = plugin.Elements(xNameSpace + "configuration").ToList();

                // If there is no root configuration add one
                if (rootConfigurations.Count == 0)
                {
                    plugin.Add(defaultConfigurationElement);
                }
                else
                {
                    foreach (var rootConfiguration in rootConfigurations)
                    {
                        AddConfigurationDefaults(rootConfiguration, xNameSpace, mavenCcParams);
                    }
                }

                // <executions> <execution> <configuration/> </execution> </executions>
                IList <XElement> executionsElements = plugin.Elements(xNameSpace + "executions").ToList();

                // if executions element doesnt exist add it.
                if (executionsElements.Count == 0)
                {
                    plugin.Add(defaultExecutions);
                }
                else
                {
                    foreach (var executionsElement in executionsElements)
                    {
                        IList <XElement> executionElements = executionsElement.Elements(xNameSpace + "execution").ToList();

                        foreach (var executionElement in executionElements)
                        {
                            // isPrepartAgentExecution is a hack, without this +: filter shows 0% coverage.
                            // Here we are collecting code coverage for all class files but reports are generated according to include/exclude filters
                            var isPrepartAgentExecution = IsPrepareAgentExecution(executionElement, xNameSpace);

                            //  Edit the configurations of executionsElements to default values. ie., user inputs.
                            IList <XElement> configurations = executionElement.Elements(xNameSpace + "configuration").ToList();
                            foreach (var configuration in configurations)
                            {
                                AddConfigurationDefaults(configuration, xNameSpace, mavenCcParams, isPrepartAgentExecution);
                            }
                            if (_isMultiModule)
                            {
                                // remove the report goal.
                                IList <XElement> goalsElements = executionElement.Elements(xNameSpace + "goals").ToList();
                                foreach (var goalsElement in goalsElements)
                                {
                                    IList <XElement> goalElements = goalsElement.Elements(xNameSpace + "goal").ToList();
                                    for (int index = 0; index < goalElements.Count; index++)
                                    {
                                        if (goalElements[index].Value.Equals("report", StringComparison.OrdinalIgnoreCase))
                                        {
                                            goalsElements[index].Remove();
                                        }
                                    }
                                }
                            }
                        }

                        // add default execution nodes to make sure we are not missing default coverage
                        executionsElement.Add(defaultExecutions.Elements().ToList());
                    }
                }
            }

            if (addIfNotExists && !hasJacocoPlugin)
            {
                _executionContext.Debug("Adding a jacoco plugin.");
                // if there is no jacoco plugin add one
                plugins.Add(GetDefaultJacocoPlugin(defaultConfigurationElement, defaultExecutions));
            }
        }
        public void EnableCodeCoverage(IExecutionContext context, CodeCoverageEnablerInputs ccInputs)
        {
            Trace.Entering();
            _executionContext = context;

            ccInputs.VerifyInputsForCoberturaAnt(context);

            string sourcesDirectory = context.Variables.Build_SourcesDirectory;
            if (string.IsNullOrWhiteSpace(sourcesDirectory))
            {
                throw new InvalidOperationException(StringUtil.Loc("InvalidSourceDirectory"));
            }

            var instrumentedClassesDirectory = Path.Combine(Path.GetDirectoryName(ccInputs.BuildFile), _instrumentClassesDir);
            var dataFile = Path.Combine(ccInputs.ReportDirectory, _coberturaSerPrefix + @".ser");

            var buildFiles = Directory.GetFiles(sourcesDirectory, "*.xml", SearchOption.AllDirectories);
            foreach (var buildFile in buildFiles)
            {
                var buildXml = new XmlDocument();

                try
                {
                    var settings = new XmlReaderSettings
                    {
                        DtdProcessing = DtdProcessing.Prohibit
                    };

                    using (XmlReader reader = XmlReader.Create(buildFile, settings))
                    {
                        buildXml.Load(reader);
                    }
                }
                catch (XmlException e)
                {
                    if (buildFile.Equals(ccInputs.BuildFile))
                    {
                        _executionContext.Warning(StringUtil.Loc("InvalidBuildXml", buildFile, e.Message));
                        throw;
                    }
                    else
                    {
                        _executionContext.Debug(StringUtil.Format(CodeCoverageConstants.InvalidXMLTemplate, buildFile, e.Message));
                    }
                    continue;
                }

                if (!string.IsNullOrWhiteSpace(buildXml.OuterXml))
                {
                    //Remove cobertura instrument nodes
                    var isInstrumentNodeExists = RemoveNodesWithName(buildXml, "project//cobertura-instrument");

                    // get instrument node
                    var instrumentNode = GetInstrumentNode(ccInputs, instrumentedClassesDirectory, dataFile);

                    var junitNodes = buildXml.SelectNodes("project//junit");
                    var javaNodes = buildXml.SelectNodes("project//java");
                    var testngNodes = buildXml.SelectNodes("project//testng");

                    //collect code coverage
                    CollectCodeCoverageForNodes(junitNodes, ccInputs, buildXml, instrumentNode, instrumentedClassesDirectory, dataFile, true);
                    CollectCodeCoverageForNodes(javaNodes, ccInputs, buildXml, instrumentNode, instrumentedClassesDirectory, dataFile);
                    CollectCodeCoverageForNodes(testngNodes, ccInputs, buildXml, instrumentNode, instrumentedClassesDirectory, dataFile);

                    var batchTestNodes = buildXml.SelectNodes("project//batchtest");
                    for (var index = 0; index < batchTestNodes.Count; index++)
                    {
                        ((XmlElement)batchTestNodes[index]).SetAttribute("fork", "true");
                        _executionContext.Debug(StringUtil.Format(CodeCoverageConstants.SettingAttributeTemplate, "fork", "true", "batchtest"));
                    }

                    // make debug=true for javac nodes
                    var javacNodes = buildXml.SelectNodes("project//javac");
                    for (int index = 0; index < javacNodes.Count; index++)
                    {
                        ((XmlElement)javacNodes[index]).SetAttribute("debug", "true");
                    }

                    // Removing any cobertura report nodes
                    var isReportNodeExists = RemoveNodesWithName(buildXml, "project//cobertura-report");

                    if (!(junitNodes.Count == 0 && javaNodes.Count == 0 && testngNodes.Count == 0) || isInstrumentNodeExists || isReportNodeExists)
                    {
                        // buildFile is edited
                        context.Debug(StringUtil.Format(CodeCoverageConstants.EnablingEditingTemplate, "cobertura", "ant", buildFile));

                        //Adding Path and TaskDef for Cobertura
                        var envProperty = AddEnvProperty();
                        var pathNode = AddPathForCobertura();
                        var taskDefNode = AddTaskDefForCobertura();
                        var envTag = buildXml.ImportNode(envProperty, true);
                        var pathTag = buildXml.ImportNode(pathNode, true);
                        var taskDefTag = buildXml.ImportNode(taskDefNode, true);

                        buildXml.DocumentElement.InsertBefore(envTag, buildXml.DocumentElement.FirstChild);
                        buildXml.DocumentElement.InsertAfter(pathTag, envTag);
                        buildXml.DocumentElement.InsertAfter(taskDefTag, pathTag);
                    }

                    using (FileStream stream = new FileStream(buildFile, FileMode.Create))
                    {
                        buildXml.Save(stream);
                    }
                }
            }

            // add cobertura report
            CreateCoberturaReport(ccInputs, dataFile);
            context.Output(StringUtil.Loc("CodeCoverageEnabled", "cobertura", "ant"));
        }
        private void CreateJacocoReport(CodeCoverageEnablerInputs antCCParams)
        {
            try
            {
                if (File.Exists(antCCParams.ReportBuildFile))
                {
                    File.Delete(antCCParams.ReportBuildFile);
                }
            }
            catch (IOException e)
            {
                _executionContext.Error(e);
            }

            try
            {
                var reportXml = GetAntReport(antCCParams);
                var settings = new XmlReaderSettings
                {
                    DtdProcessing = DtdProcessing.Prohibit
                };
                using (XmlReader reader = XmlReader.Create(new StringReader(reportXml), settings))
                {
                    XmlDocument xdoc = new XmlDocument();
                    xdoc.Load(reader);
                    using (FileStream stream = new FileStream(antCCParams.ReportBuildFile, FileMode.Create))
                    {
                        xdoc.Save(stream);
                    }
                }
            }
            catch (XmlException e)
            {
                _executionContext.Warning(StringUtil.Loc("InvalidBuildXml", antCCParams.ReportBuildFile, e.Message));
                throw;
            }
        }