|
|
|
|
@@ -0,0 +1,304 @@
|
|
|
|
|
using System;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using Palmmedia.ReportGenerator.Core;
|
|
|
|
|
using Palmmedia.ReportGenerator.Core.Logging;
|
|
|
|
|
using UnityEditor.TestTools.CodeCoverage.Utils;
|
|
|
|
|
using ILogger = Palmmedia.ReportGenerator.Core.Logging.ILogger;
|
|
|
|
|
using Palmmedia.ReportGenerator.Core.CodeAnalysis;
|
|
|
|
|
using UnityEditor.TestTools.CodeCoverage.Analytics;
|
|
|
|
|
|
|
|
|
|
namespace UnityEditor.TestTools.CodeCoverage
|
|
|
|
|
{
|
|
|
|
|
internal class CoverageReportGenerator
|
|
|
|
|
{
|
|
|
|
|
public void Generate(CoverageSettings coverageSettings)
|
|
|
|
|
{
|
|
|
|
|
CoverageReporterManager coverageReporterManager = CoverageReporterStarter.CoverageReporterManager;
|
|
|
|
|
AssemblyFiltering assemblyFiltering = null;
|
|
|
|
|
PathFiltering pathFiltering = null;
|
|
|
|
|
if (coverageReporterManager != null)
|
|
|
|
|
{
|
|
|
|
|
coverageReporterManager.CoverageReporter.GetReporterFilter().SetupFiltering();
|
|
|
|
|
assemblyFiltering = coverageReporterManager.CoverageReporter.GetReporterFilter().GetAssemblyFiltering();
|
|
|
|
|
pathFiltering = coverageReporterManager.CoverageReporter.GetReporterFilter().GetPathFiltering();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (assemblyFiltering == null || pathFiltering == null)
|
|
|
|
|
{
|
|
|
|
|
ResultsLogger.Log(ResultID.Warning_FailedReportNullCoverageFilters);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CoverageRunData.instance.ReportGenerationStart();
|
|
|
|
|
|
|
|
|
|
if (coverageSettings == null)
|
|
|
|
|
{
|
|
|
|
|
EditorUtility.ClearProgressBar();
|
|
|
|
|
ResultsLogger.Log(ResultID.Warning_FailedReportNullCoverageSettings);
|
|
|
|
|
CoverageRunData.instance.ReportGenerationEnd(false);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string includeAssemblies = assemblyFiltering != null ? assemblyFiltering.includedAssemblies : string.Empty;
|
|
|
|
|
|
|
|
|
|
// If override for include assemblies is set in coverageSettings, use overrideIncludeAssemblies instead
|
|
|
|
|
if (!String.IsNullOrEmpty(coverageSettings.overrideIncludeAssemblies))
|
|
|
|
|
includeAssemblies = coverageSettings.overrideIncludeAssemblies;
|
|
|
|
|
|
|
|
|
|
string[] assemblyFilters = includeAssemblies.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
|
|
|
|
|
|
if (assemblyFilters.Length == 0)
|
|
|
|
|
{
|
|
|
|
|
EditorUtility.ClearProgressBar();
|
|
|
|
|
ResultsLogger.Log(ResultID.Error_FailedReportNoAssemblies, CoverageUtils.GetFilteringLogParams(assemblyFiltering, pathFiltering));
|
|
|
|
|
CoverageRunData.instance.ReportGenerationEnd(false);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < assemblyFilters.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
assemblyFilters[i] = "+" + assemblyFilters[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string rootFolderPath = coverageSettings.rootFolderPath;
|
|
|
|
|
|
|
|
|
|
if (CoverageUtils.GetNumberOfFilesInFolder(rootFolderPath, "*.xml", SearchOption.AllDirectories) == 0)
|
|
|
|
|
{
|
|
|
|
|
EditorUtility.ClearProgressBar();
|
|
|
|
|
ResultsLogger.Log(ResultID.Error_FailedReportNoCoverageResults, CoverageUtils.GetFilteringLogParams(assemblyFiltering, pathFiltering));
|
|
|
|
|
CoverageRunData.instance.ReportGenerationEnd(false);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Only include xml files with the correct filename format
|
|
|
|
|
string sourceXmlPath = CoverageUtils.JoinPaths(rootFolderPath, "**");
|
|
|
|
|
string testResultsXmlPath = CoverageUtils.JoinPaths(sourceXmlPath, "TestCoverageResults_????.xml");
|
|
|
|
|
string recordingResultsXmlPath = CoverageUtils.JoinPaths(sourceXmlPath, "RecordingCoverageResults_????.xml");
|
|
|
|
|
string rootFullEmptyResultsXmlPath = CoverageUtils.JoinPaths(rootFolderPath, "TestCoverageResults_fullEmpty.xml");
|
|
|
|
|
|
|
|
|
|
string[] reportFilePatterns = new string[] { testResultsXmlPath, recordingResultsXmlPath, rootFullEmptyResultsXmlPath };
|
|
|
|
|
|
|
|
|
|
bool includeHistoryInReport = CommandLineManager.instance.batchmode && !CommandLineManager.instance.useProjectSettings ?
|
|
|
|
|
CommandLineManager.instance.generateHTMLReportHistory :
|
|
|
|
|
CommandLineManager.instance.generateHTMLReportHistory || CoveragePreferences.instance.GetBool("IncludeHistoryInReport", true);
|
|
|
|
|
|
|
|
|
|
string historyDirectory = includeHistoryInReport ? coverageSettings.historyFolderPath : null;
|
|
|
|
|
|
|
|
|
|
string targetDirectory = CoverageUtils.JoinPaths(rootFolderPath, CoverageSettings.ReportFolderName);
|
|
|
|
|
|
|
|
|
|
string[] sourceDirectories = CommandLineManager.instance.sourcePathsSpecified ? CommandLineManager.instance.sourcePaths.Split(',') : new string[] { };
|
|
|
|
|
|
|
|
|
|
bool generateHTMLReport = CommandLineManager.instance.batchmode && !CommandLineManager.instance.useProjectSettings ?
|
|
|
|
|
CommandLineManager.instance.generateHTMLReport :
|
|
|
|
|
CommandLineManager.instance.generateHTMLReport || CoveragePreferences.instance.GetBool("GenerateHTMLReport", true);
|
|
|
|
|
|
|
|
|
|
if (coverageSettings.overrideGenerateHTMLReport)
|
|
|
|
|
generateHTMLReport = true;
|
|
|
|
|
|
|
|
|
|
bool generateBadge = CommandLineManager.instance.batchmode && !CommandLineManager.instance.useProjectSettings ?
|
|
|
|
|
CommandLineManager.instance.generateBadgeReport :
|
|
|
|
|
CommandLineManager.instance.generateBadgeReport || CoveragePreferences.instance.GetBool("GenerateBadge", true);
|
|
|
|
|
|
|
|
|
|
bool generateAdditionalReports = CommandLineManager.instance.batchmode && !CommandLineManager.instance.useProjectSettings ?
|
|
|
|
|
CommandLineManager.instance.generateAdditionalReports :
|
|
|
|
|
CommandLineManager.instance.generateAdditionalReports || CoveragePreferences.instance.GetBool("GenerateAdditionalReports", false);
|
|
|
|
|
|
|
|
|
|
string reportTypesString = "xmlSummary,MarkdownSummary,JsonSummary,";
|
|
|
|
|
if (generateHTMLReport)
|
|
|
|
|
reportTypesString += "Html,";
|
|
|
|
|
if (generateBadge)
|
|
|
|
|
reportTypesString += "Badges,";
|
|
|
|
|
if (generateAdditionalReports)
|
|
|
|
|
reportTypesString += "SonarQube,lcov,Cobertura,";
|
|
|
|
|
|
|
|
|
|
string[] reportTypes = reportTypesString.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
|
string[] plugins = new string[] { };
|
|
|
|
|
|
|
|
|
|
bool includeAdditionalMetrics = coverageReporterManager != null &&
|
|
|
|
|
coverageReporterManager.CoverageReporter.GetReporterFilter().ShouldGenerateAdditionalMetrics();
|
|
|
|
|
|
|
|
|
|
string[] classFilters = new string[] { };
|
|
|
|
|
string[] fileFilters = new string[] { };
|
|
|
|
|
string verbosityLevel = null;
|
|
|
|
|
string tag = null;
|
|
|
|
|
|
|
|
|
|
ReportConfiguration config = new ReportConfiguration(
|
|
|
|
|
reportFilePatterns,
|
|
|
|
|
targetDirectory,
|
|
|
|
|
sourceDirectories,
|
|
|
|
|
historyDirectory,
|
|
|
|
|
reportTypes,
|
|
|
|
|
plugins,
|
|
|
|
|
assemblyFilters,
|
|
|
|
|
classFilters,
|
|
|
|
|
fileFilters,
|
|
|
|
|
verbosityLevel,
|
|
|
|
|
tag);
|
|
|
|
|
|
|
|
|
|
DebugFactory loggerFactory = new DebugFactory();
|
|
|
|
|
LoggerFactory.Configure(loggerFactory);
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (!CommandLineManager.instance.batchmode)
|
|
|
|
|
EditorUtility.DisplayProgressBar(ReportGeneratorStyles.ProgressTitle.text, ReportGeneratorStyles.ProgressInfoCreating.text, 0f);
|
|
|
|
|
|
|
|
|
|
if (Directory.Exists(targetDirectory))
|
|
|
|
|
Directory.Delete(targetDirectory, true);
|
|
|
|
|
|
|
|
|
|
Generator generator = new Generator();
|
|
|
|
|
ResultsLogger.LogSessionItem("Initializing report generation..", LogVerbosityLevel.Info);
|
|
|
|
|
if (generator.GenerateReport(config, new Settings() { DisableRiskHotspots = !includeAdditionalMetrics }, new RiskHotspotsAnalysisThresholds()))
|
|
|
|
|
{
|
|
|
|
|
ResultsLogger.Log(ResultID.Log_ReportSaved, CoverageUtils.GetFilteringLogParams(assemblyFiltering, pathFiltering, new string[] { targetDirectory }));
|
|
|
|
|
|
|
|
|
|
CoverageRunData.instance.ReportGenerationEnd(true);
|
|
|
|
|
|
|
|
|
|
// Send Analytics event (Report Only / Data & Report)
|
|
|
|
|
CoverageAnalytics.instance.SendCoverageEvent(true);
|
|
|
|
|
|
|
|
|
|
if (!CommandLineManager.instance.batchmode &&
|
|
|
|
|
coverageSettings.revealReportInFinder &&
|
|
|
|
|
CoveragePreferences.instance.GetBool("OpenReportWhenGenerated", true))
|
|
|
|
|
{
|
|
|
|
|
string indexHtm = CoverageUtils.JoinPaths(targetDirectory, "index.htm");
|
|
|
|
|
if (File.Exists(indexHtm))
|
|
|
|
|
EditorUtility.RevealInFinder(indexHtm);
|
|
|
|
|
else
|
|
|
|
|
EditorUtility.RevealInFinder(targetDirectory);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ResultsLogger.Log(ResultID.Error_FailedReport, CoverageUtils.GetFilteringLogParams(assemblyFiltering, pathFiltering));
|
|
|
|
|
CoverageRunData.instance.ReportGenerationEnd(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
EditorUtility.ClearProgressBar();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class DebugFactory : ILoggerFactory
|
|
|
|
|
{
|
|
|
|
|
public VerbosityLevel VerbosityLevel { get; set; }
|
|
|
|
|
|
|
|
|
|
public DebugLogger Logger { get; set; }
|
|
|
|
|
|
|
|
|
|
public DebugFactory()
|
|
|
|
|
{
|
|
|
|
|
Logger = new DebugLogger();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ILogger GetLogger(Type type)
|
|
|
|
|
{
|
|
|
|
|
return Logger;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class DebugLogger : ILogger
|
|
|
|
|
{
|
|
|
|
|
public VerbosityLevel VerbosityLevel { get; set; }
|
|
|
|
|
|
|
|
|
|
readonly StringBuilder m_StringBuilder = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
public void Debug(string message)
|
|
|
|
|
{
|
|
|
|
|
m_StringBuilder.AppendLine(message);
|
|
|
|
|
ResultsLogger.LogSessionItem(message, LogVerbosityLevel.Verbose);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void DebugFormat(string format, params object[] args)
|
|
|
|
|
{
|
|
|
|
|
string message = string.Format(format, args);
|
|
|
|
|
m_StringBuilder.AppendLine(message);
|
|
|
|
|
|
|
|
|
|
if (string.Equals(format, "Finished parsing \'{0}\' {1}/{2}") ||
|
|
|
|
|
string.Equals(format, "Parsing of {0} files completed") ||
|
|
|
|
|
string.Equals(format, "Coverage report parsing took {0:f1} seconds") ||
|
|
|
|
|
string.Equals(format, "Initializing report builders for report types: {0}") ||
|
|
|
|
|
string.Equals(format, "Analyzing {0} classes") ||
|
|
|
|
|
string.Equals(format, "Report generation took {0:f1} seconds") )
|
|
|
|
|
{
|
|
|
|
|
ResultsLogger.LogSessionItem(message, LogVerbosityLevel.Info);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ResultsLogger.LogSessionItem(message, LogVerbosityLevel.Verbose);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!CommandLineManager.instance.batchmode)
|
|
|
|
|
{
|
|
|
|
|
if (string.Equals(format, "Creating report {0}/{1} (Assembly: {2}, Class: {3})"))
|
|
|
|
|
{
|
|
|
|
|
if (args.Length >= 2)
|
|
|
|
|
{
|
|
|
|
|
if (float.TryParse(string.Format("{0}", args[0]), out float currentNum) &&
|
|
|
|
|
float.TryParse(string.Format("{0}", args[1]), out float totalNum) &&
|
|
|
|
|
currentNum <= totalNum &&
|
|
|
|
|
currentNum > 0 &&
|
|
|
|
|
totalNum > 0)
|
|
|
|
|
{
|
|
|
|
|
float progress = (currentNum + 1) / totalNum;
|
|
|
|
|
EditorUtility.DisplayProgressBar(ReportGeneratorStyles.ProgressTitle.text, ReportGeneratorStyles.ProgressInfoCreating.text, progress);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Error(string message)
|
|
|
|
|
{
|
|
|
|
|
m_StringBuilder.AppendLine(message);
|
|
|
|
|
ResultsLogger.LogSessionItem(message, LogVerbosityLevel.Error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ErrorFormat(string format, params object[] args)
|
|
|
|
|
{
|
|
|
|
|
string message = string.Format(format, args);
|
|
|
|
|
m_StringBuilder.AppendLine(message);
|
|
|
|
|
ResultsLogger.LogSessionItem(message, LogVerbosityLevel.Error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Info(string message)
|
|
|
|
|
{
|
|
|
|
|
m_StringBuilder.AppendLine(message);
|
|
|
|
|
ResultsLogger.LogSessionItem(message, LogVerbosityLevel.Info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void InfoFormat(string format, params object[] args)
|
|
|
|
|
{
|
|
|
|
|
string message = string.Format(format, args);
|
|
|
|
|
m_StringBuilder.AppendLine(message);
|
|
|
|
|
|
|
|
|
|
if (string.Equals(format, "Writing report file \'{0}\'"))
|
|
|
|
|
{
|
|
|
|
|
ResultsLogger.LogSessionItem(message, LogVerbosityLevel.Verbose);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ResultsLogger.LogSessionItem(message, LogVerbosityLevel.Info);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Warn(string message)
|
|
|
|
|
{
|
|
|
|
|
m_StringBuilder.AppendLine(message);
|
|
|
|
|
ResultsLogger.LogSessionItem(message, LogVerbosityLevel.Warning);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void WarnFormat(string format, params object[] args)
|
|
|
|
|
{
|
|
|
|
|
string message = string.Format(format, args);
|
|
|
|
|
m_StringBuilder.AppendLine(message);
|
|
|
|
|
ResultsLogger.LogSessionItem(message, LogVerbosityLevel.Verbose);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
|
|
|
|
return m_StringBuilder.ToString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|