Skip to content

Commit 258c484

Browse files
authored
Merge pull request #149 from tonyhallett/fix-outofmemoryexception
replace File.ReadAllText(cobertura) with reading from file by xmlreader
2 parents 97ae2ba + 7f3d677 commit 258c484

File tree

13 files changed

+87
-108
lines changed

13 files changed

+87
-108
lines changed

FineCodeCoverage/Core/Cobertura/CoberturaUtil.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ internal class CoberturaUtil:ICoberturaUtil
1717
private CoverageReport coverageReport;
1818
public List<CoverageLine> CoverageLines { get; private set; }
1919

20-
private CoverageReport LoadReport(string xml)
20+
private CoverageReport LoadReport(string xmlFile)
2121
{
22-
using (var reader = XmlReader.Create(new StringReader(xml), READER_SETTINGS))
22+
using (var reader = XmlReader.Create(xmlFile, READER_SETTINGS))
2323
{
2424
var report = (CoverageReport)SERIALIZER.Deserialize(reader);
2525
return report;
@@ -68,11 +68,11 @@ private CoverageReport LoadReport(string xml)
6868
// return jsonText;
6969
//}
7070

71-
public void ProcessCoberturaXml(string xml)
71+
public void ProcessCoberturaXml(string xmlFile)
7272
{
7373
CoverageLines = new List<CoverageLine>();
7474

75-
coverageReport = LoadReport(xml);
75+
coverageReport = LoadReport(xmlFile);
7676

7777
foreach (var package in coverageReport.Packages.Package)
7878
{

FineCodeCoverage/Core/Cobertura/ICoberturaUtil.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ interface ICoberturaUtil
77
{
88
List<CoverageLine> CoverageLines { get; }
99

10-
void ProcessCoberturaXml(string xml);
10+
void ProcessCoberturaXml(string xmlFile);
1111
string[] GetSourceFiles(string assemblyName, string qualifiedClassName, int file);
1212
}
1313
}

FineCodeCoverage/Core/CoverageToolOutput/CoverageToolOutputManager.cs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ internal class CoverageToolOutputManager : ICoverageToolOutputManager
1313
{
1414
private readonly ILogger logger;
1515
private readonly IFileUtil fileUtil;
16-
private const string unifiedHtmlFileName = "index.html";
17-
private const string unifiedXmlFileName = "Cobertura.xml";
18-
private const string processedHtmlFileName = "index-processed.html";
1916
private const string projectCoverageToolOutputFolderName = "coverage-tool-output";
2017
private string outputFolderForAllProjects;
2118
private List<ICoverageProject> coverageProjects;
@@ -50,14 +47,7 @@ public void SetProjectCoverageOutputFolder(List<ICoverageProject> coverageProjec
5047
}
5148
}
5249

53-
public void OutputReports(string unifiedHtml, string processedReport, string unifiedXml)
54-
{
55-
var outputFolder = outputFolderForAllProjects ?? coverageProjects[0].CoverageOutputFolder;
56-
57-
fileUtil.WriteAllText(Path.Combine(outputFolder, unifiedHtmlFileName), unifiedHtml);
58-
fileUtil.WriteAllText(Path.Combine(outputFolder, processedHtmlFileName), processedReport);
59-
fileUtil.WriteAllText(Path.Combine(outputFolder, unifiedXmlFileName), unifiedXml);
60-
}
50+
6151

6252
private void DetermineOutputFolder()
6353
{
@@ -67,5 +57,10 @@ private void DetermineOutputFolder()
6757
logger.Log($"FCC output in {outputFolderForAllProjects}");
6858
}
6959
}
60+
61+
public string GetReportOutputFolder()
62+
{
63+
return outputFolderForAllProjects ?? coverageProjects[0].CoverageOutputFolder;
64+
}
7065
}
7166
}

FineCodeCoverage/Core/CoverageToolOutput/ICoverageToolOutputManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ namespace FineCodeCoverage.Engine
66
internal interface ICoverageToolOutputManager
77
{
88
void SetProjectCoverageOutputFolder(List<ICoverageProject> coverageProjects);
9-
void OutputReports(string unifiedHtml, string processedReport, string unifiedXml);
9+
string GetReportOutputFolder();
1010
}
1111
}

FineCodeCoverage/Core/Coverlet/Console/CoverletConsoleUtil.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,14 @@ public async Task<bool> RunAsync(ICoverageProject project, bool throwError = fal
138138
*/
139139
if (result.ExitCode > 3)
140140
{
141+
logger.Log($"{title} Error. Exit code: {result.ExitCode}");
142+
logger.Log($"{title} Error. Output: ", result.Output);
141143
if (throwError)
142144
{
143145
throw new Exception(result.Output);
144146
}
145147

146-
logger.Log($"{title} Error", result.Output);
148+
147149
return false;
148150
}
149151

FineCodeCoverage/Core/Coverlet/DataCollector/CoverletDataCollectorUtil.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ private string GetSettings()
120120
{
121121
var dataCollectorSettingsBuilder = dataCollectorSettingsBuilderFactory.Create();
122122
dataCollectorSettingsBuilder
123-
.Initialize(coverageProject.Settings, coverageProject.RunSettingsFile, $"{coverageProject.CoverageOutputFolder}/FCC.runsettings");
123+
.Initialize(coverageProject.Settings, coverageProject.RunSettingsFile, Path.Combine(coverageProject.CoverageOutputFolder,"FCC.runsettings"));
124124

125125
// command arguments
126126
dataCollectorSettingsBuilder

FineCodeCoverage/Core/Coverlet/DataCollector/DataCollectorSettingsBuilder.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ internal class DataCollectorSettingsBuilder : IDataCollectorSettingsBuilder
1414
private string generatedRunSettingsPath;
1515
private string existingRunSettings;
1616
private IAppOptions coverageProjectSettings;
17+
private readonly ILogger logger;
1718

19+
public DataCollectorSettingsBuilder(ILogger logger)
20+
{
21+
this.logger = logger;
22+
}
1823
#region Arguments
1924
internal string ProjectDll { get; set; }
2025
internal string Blame { get; set; }
@@ -67,6 +72,7 @@ public string Build()
6772
private void GenerateRunSettings()
6873
{
6974
var runSettingsDocument = existingRunSettings == null ? GenerateFullRunSettings() : GenerateRunSettingsFromExisting();
75+
logger.Log($"Saving run settings to {generatedRunSettingsPath}");
7076
runSettingsDocument.Save(generatedRunSettingsPath);
7177
}
7278

FineCodeCoverage/Core/Coverlet/DataCollector/DataCollectorSettingsBuilderFactory.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,16 @@ namespace FineCodeCoverage.Engine.Coverlet
66
[Export(typeof(IDataCollectorSettingsBuilderFactory))]
77
internal class DataCollectorSettingsBuilderFactory : IDataCollectorSettingsBuilderFactory
88
{
9+
private readonly ILogger logger;
910

11+
[ImportingConstructor]
12+
public DataCollectorSettingsBuilderFactory(ILogger logger)
13+
{
14+
this.logger = logger;
15+
}
1016
public IDataCollectorSettingsBuilder Create()
1117
{
12-
return new DataCollectorSettingsBuilder();
18+
return new DataCollectorSettingsBuilder(logger);
1319
}
1420
}
1521
}

FineCodeCoverage/Core/FCCEngine.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ private void UpdateUI(List<CoverageLine> coverageLines, string reportHtml)
155155
RaiseUpdateOutputWindow(reportHtml);
156156
}
157157

158-
private async System.Threading.Tasks.Task<(List<CoverageLine> coverageLines,string reportFilePath)> RunAndProcessReportAsync(string[] coverOutputFiles,CancellationToken cancellationToken)
158+
private async System.Threading.Tasks.Task<(List<CoverageLine> coverageLines,string reportFilePath)> RunAndProcessReportAsync(string[] coverOutputFiles,string reportOutputFolder,CancellationToken cancellationToken)
159159
{
160160
cancellationToken.ThrowIfCancellationRequested();
161161

@@ -164,15 +164,16 @@ private void UpdateUI(List<CoverageLine> coverageLines, string reportHtml)
164164

165165
var darkMode = CurrentTheme.Equals("Dark", StringComparison.OrdinalIgnoreCase);
166166

167-
var result = await reportGeneratorUtil.GenerateAsync(coverOutputFiles, darkMode, true);
167+
var result = await reportGeneratorUtil.GenerateAsync(coverOutputFiles,reportOutputFolder, darkMode, true);
168168

169169
if (result.Success)
170170
{
171-
coberturaUtil.ProcessCoberturaXml(result.UnifiedXml);
171+
logger.Log("Processing cobertura");
172+
coberturaUtil.ProcessCoberturaXml(result.UnifiedXmlFile);
172173
coverageLines = coberturaUtil.CoverageLines;
173174

174-
processedReport = reportGeneratorUtil.ProcessUnifiedHtml(result.UnifiedHtml, darkMode);
175-
coverageOutputManager.OutputReports(result.UnifiedHtml, processedReport, result.UnifiedXml);
175+
logger.Log("Processing report");
176+
processedReport = reportGeneratorUtil.ProcessUnifiedHtml(result.UnifiedHtml,reportOutputFolder, darkMode);
176177
}
177178
return (coverageLines, processedReport);
178179
}
@@ -257,12 +258,13 @@ public void ReloadCoverage(Func<System.Threading.Tasks.Task<List<ICoverageProjec
257258
var coverageProjects = await coverageRequestCallback();
258259

259260
coverageOutputManager.SetProjectCoverageOutputFolder(coverageProjects);
261+
var reportOutputFolder = coverageOutputManager.GetReportOutputFolder();
260262

261263
var coverOutputFiles = await RunCoverageAsync(coverageProjects, cancellationToken);
262264

263265
if (coverOutputFiles.Any())
264266
{
265-
var (lines, report) = await RunAndProcessReportAsync(coverOutputFiles,cancellationToken);
267+
var (lines, report) = await RunAndProcessReportAsync(coverOutputFiles,reportOutputFolder,cancellationToken);
266268
coverageLines = lines;
267269
reportHtml = report;
268270
}

FineCodeCoverage/Core/ReportGenerator/ReportGeneratorUtil.cs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ namespace FineCodeCoverage.Engine.ReportGenerator
1717
interface IReportGeneratorUtil
1818
{
1919
void Initialize(string appDataFolder);
20-
string ProcessUnifiedHtml(string htmlForProcessing, bool darkMode);
21-
Task<ReportGeneratorResult> GenerateAsync(IEnumerable<string> coverOutputFiles, bool darkMode, bool throwError = false);
20+
string ProcessUnifiedHtml(string htmlForProcessing,string reportOutputFolder, bool darkMode);
21+
Task<ReportGeneratorResult> GenerateAsync(IEnumerable<string> coverOutputFiles,string reportOutputFolder, bool darkMode, bool throwError = false);
2222

2323
}
2424

2525
internal class ReportGeneratorResult
2626
{
2727
public string UnifiedHtml { get; set; }
28-
public string UnifiedXml { get; set; }
28+
public string UnifiedXmlFile { get; set; }
2929
public bool Success { get; set; }
3030
}
3131

@@ -68,17 +68,16 @@ public void Initialize(string appDataFolder)
6868
?? Directory.GetFiles(zipDestination, "*reportGenerator*.exe", SearchOption.AllDirectories).FirstOrDefault();
6969
}
7070

71-
public async Task<ReportGeneratorResult> GenerateAsync(IEnumerable<string> coverOutputFiles, bool darkMode, bool throwError = false)
71+
public async Task<ReportGeneratorResult> GenerateAsync(IEnumerable<string> coverOutputFiles,string reportOutputFolder, bool darkMode, bool throwError = false)
7272
{
7373
var title = "ReportGenerator Run";
74-
var tempDirectory = fileUtil.CreateTempDirectory();
7574

76-
var unifiedHtmlFile = Path.Combine(tempDirectory, "index.html");
77-
var unifiedXmlFile = Path.Combine(tempDirectory, "Cobertura.xml");
75+
var unifiedHtmlFile = Path.Combine(reportOutputFolder, "index.html");
76+
var unifiedXmlFile = Path.Combine(reportOutputFolder, "Cobertura.xml");
7877

7978
var reportGeneratorSettings = new List<string>();
8079

81-
reportGeneratorSettings.Add($@"""-targetdir:{tempDirectory}""");
80+
reportGeneratorSettings.Add($@"""-targetdir:{reportOutputFolder}""");
8281

8382
async Task<bool> run(string outputReportType, string inputReports)
8483
{
@@ -107,20 +106,22 @@ async Task<bool> run(string outputReportType, string inputReports)
107106
{
108107
FilePath = ReportGeneratorExePath,
109108
Arguments = string.Join(" ", reportTypeSettings),
110-
WorkingDirectory = tempDirectory
109+
WorkingDirectory = reportOutputFolder
111110
});
112111
113112
114113
if(result != null)
115114
{
116115
if (result.ExitCode != 0)
117116
{
117+
logger.Log($"{title} [reporttype:{outputReportType}] Error", result.Output);
118+
logger.Log($"{title} [reporttype:{outputReportType}] Error", result.ExitCode);
119+
118120
if (throwError)
119121
{
120122
throw new Exception(result.Output);
121123
}
122124
123-
logger.Log($"{title} [reporttype:{outputReportType}] Error", result.Output);
124125
return false;
125126
}
126127
@@ -131,7 +132,7 @@ async Task<bool> run(string outputReportType, string inputReports)
131132
132133
}
133134
134-
var reportGeneratorResult = new ReportGeneratorResult { Success = false, UnifiedHtml = null, UnifiedXml = null };
135+
var reportGeneratorResult = new ReportGeneratorResult { Success = false, UnifiedHtml = null, UnifiedXmlFile = unifiedXmlFile };
135136
136137
var coberturaResult = await run("Cobertura", string.Join(";", coverOutputFiles));
137138
@@ -140,20 +141,17 @@ async Task<bool> run(string outputReportType, string inputReports)
140141
var htmlResult = await run("HtmlInline_AzurePipelines", unifiedXmlFile);
141142
if (htmlResult)
142143
{
143-
reportGeneratorResult.UnifiedXml = fileUtil.ReadAllText(unifiedXmlFile);
144144
reportGeneratorResult.UnifiedHtml = fileUtil.ReadAllText(unifiedHtmlFile);
145145
reportGeneratorResult.Success = true;
146146
}
147147
148148
}
149149
150-
fileUtil.TryDeleteDirectory(tempDirectory);
151-
152150
return reportGeneratorResult;
153151
154152
}
155153
156-
public string ProcessUnifiedHtml(string htmlForProcessing, bool darkMode)
154+
public string ProcessUnifiedHtml(string htmlForProcessing, string reportOutputFolder, bool darkMode)
157155
{
158156
return assemblyUtil.RunInAssemblyResolvingContext(() =>
159157
{
@@ -163,6 +161,7 @@ public string ProcessUnifiedHtml(string htmlForProcessing, bool darkMode)
163161
doc.OptionAutoCloseOnEnd = true;
164162
165163
doc.LoadHtml(htmlForProcessing);
164+
htmlForProcessing = null;
166165
167166
doc.DocumentNode.QuerySelectorAll(".footer").ToList().ForEach(x => x.SetAttributeValue("style", "display:none"));
168167
doc.DocumentNode.QuerySelectorAll(".container").ToList().ForEach(x => x.SetAttributeValue("style", "margin:0;padding:0;border:0"));
@@ -500,7 +499,7 @@ Risk Hotspots
500499
501500
htmlSb.Replace("branchCoverageAvailable = true", "branchCoverageAvailable = false");
502501
503-
return string.Join(
502+
var processed = string.Join(
504503
Environment.NewLine,
505504
htmlSb.ToString().Split('\r', '\n')
506505
.Select(line =>
@@ -566,6 +565,11 @@ Risk Hotspots
566565
return line;
567566
}));
568567

568+
var processedHtmlFile = Path.Combine(reportOutputFolder, "index-processed.html");
569+
File.WriteAllText(processedHtmlFile, processed);
570+
571+
return processed;
572+
569573
});
570574
}
571575
}

0 commit comments

Comments
 (0)