Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Test Impact Analysis #154

Draft
wants to merge 189 commits into
base: master
Choose a base branch
from
Draft
Changes from 1 commit
Commits
Show all changes
189 commits
Select commit Hold shift + click to select a range
065c418
zmq powered gui
mpdeimos Sep 28, 2020
2385d65
retarget vc projects
mpdeimos Sep 28, 2020
a1e3e9f
codemaid
mpdeimos Sep 28, 2020
e0d81b1
add ZMQ, first concept of one-way profiler communication
mpdeimos Sep 29, 2020
a64c664
add testcase for one-way profiler communication
mpdeimos Sep 29, 2020
f0c0be3
rename gui
mpdeimos Sep 30, 2020
5befda8
add profiler commons project and use in test
mpdeimos Sep 30, 2020
95d8074
Test infra: use .net ZMQ and native ZMQ
mpdeimos Nov 24, 2020
59af32f
Extend Profiler Testee with an interactive mode
mpdeimos Nov 25, 2020
2f6f80d
Add publisher socket to C# IPC implementation
mpdeimos Nov 25, 2020
5c63ba7
Wire subscribe socket in C++ IPC
mpdeimos Nov 25, 2020
d40729c
write function infos to log on test case switch
mpdeimos Nov 25, 2020
1d016b9
Real TIA method call profiling
mpdeimos Dec 1, 2020
ea2fa00
Refactor tests
mpdeimos Dec 2, 2020
2f2e923
No locking until IPC is started
mpdeimos Dec 14, 2020
3022397
Use NetMQ-native threading
mpdeimos Dec 14, 2020
a5d3519
compiler profiler testee with native bitness and as x86, x64
mpdeimos Dec 14, 2020
aee3e91
parameterize tia tests as x64 and x86
mpdeimos Dec 14, 2020
1fbf7e7
test start ipc after app (not working yet)
mpdeimos Jan 22, 2021
82ea47f
commander rework
mpdeimos Jan 22, 2021
3874d31
simplified commander
mpdeimos Jan 22, 2021
519a256
multipart tia start/end
mpdeimos Jan 26, 2021
b421dc6
escaping of characters
mpdeimos Jan 26, 2021
0fec463
store test execution result
mpdeimos Jan 26, 2021
0bf704e
disable mscorlib profiling for TIA
mpdeimos Jan 26, 2021
8d868f8
fix for default socket
mpdeimos Jan 29, 2021
b256b52
Wrap coverage data in report class.
salsolatragus Nov 24, 2020
efa1a83
Write testwise coverage report.
salsolatragus Nov 27, 2020
6f639cf
Merge TraceFile and ParsedTraceFile classes.
salsolatragus Jan 31, 2021
266c6c0
Hide internal data of TraceFile.
salsolatragus Jan 31, 2021
5f9ad5e
Make names consistent.
salsolatragus Jan 31, 2021
c379efa
Ignores method references from unkown assemblies.
salsolatragus Jan 31, 2021
f83ce26
Improve some names.
salsolatragus Jan 31, 2021
985a4a4
Split testwise report and separate conversion from files.
salsolatragus Jan 31, 2021
9abbb23
Generate aggregated report.
salsolatragus Jan 31, 2021
1fcbe09
Introduce ICoverageReport abstraction.
salsolatragus Jan 31, 2021
abd3188
Tests simple report output.
salsolatragus Jan 31, 2021
d30faf1
Tests aggregated trace.
salsolatragus Jan 31, 2021
702224b
Test testwise report contents.
salsolatragus Jan 31, 2021
0769fc1
Remove obsolete method.
salsolatragus Jan 31, 2021
9a7a5f4
Simplify tests.
salsolatragus Jan 31, 2021
0bb95e6
Test generating testwise report.
salsolatragus Feb 1, 2021
760c7b9
Merge SimpleCoverageReport and LineCoverageReport.
salsolatragus Feb 1, 2021
2e0df40
Remove unused import.
salsolatragus Feb 1, 2021
9784045
Remove obsolete class.
salsolatragus Feb 1, 2021
7d2353f
Cleanup testwise report model.
salsolatragus Feb 1, 2021
6ef6870
Simplify creation of testwise report.
salsolatragus Feb 1, 2021
4cd2c43
Merge testwise reports with different tests.
salsolatragus Feb 1, 2021
2fba176
Merge testwise reports.
salsolatragus Feb 1, 2021
dffe644
Send report format to Teamscale.
salsolatragus Feb 1, 2021
d297d3b
Move simple report to own namespace.
salsolatragus Feb 1, 2021
9de811b
Serialize testwise report.
salsolatragus Feb 1, 2021
5c1df8d
Test parsing jitted, inlined, and called events.
salsolatragus Feb 2, 2021
458b210
Assume tests always start.
salsolatragus Feb 2, 2021
54b99b5
Consider test without end.
salsolatragus Feb 2, 2021
4057fab
Add no-test coverage only if any.
salsolatragus Feb 2, 2021
6a8c035
Fix test result labels.
salsolatragus Feb 2, 2021
73b2bd3
Keep non-test coverage.
salsolatragus Feb 2, 2021
4d232e2
cache latest test runs
mpdeimos Feb 2, 2021
3a32c3c
Merge test metadata.
salsolatragus Feb 2, 2021
77888f4
Simplify archiving API.
salsolatragus Feb 2, 2021
2e35d47
Shorten an expression.
salsolatragus Feb 2, 2021
6f74a98
Fix stupid merge error.
salsolatragus Feb 2, 2021
059a5e5
test timing fix
mpdeimos Feb 3, 2021
7563980
error logging
mpdeimos Feb 12, 2021
e13ce46
test name validation
mpdeimos Feb 12, 2021
083ea6d
Extract Tia test baseclass.
salsolatragus Feb 19, 2021
f850e52
Abstract test setup.
salsolatragus Feb 19, 2021
515f5c9
Restructure test infrastructure.
salsolatragus Feb 23, 2021
1a4fb06
Remove TiaTestee.
salsolatragus Feb 23, 2021
c07b91b
Simplify testee.
salsolatragus Feb 23, 2021
ee83cde
Reduce visibility.
salsolatragus Feb 23, 2021
8017b25
Specify bitness on testee rather than profiler.
salsolatragus Feb 24, 2021
5f36782
Add performance testee.
salsolatragus Feb 24, 2021
7f5505f
Configure Commons to build a nuget package.
salsolatragus Mar 2, 2021
f0eca90
Remove unused import.
salsolatragus Mar 2, 2021
8657ed2
Add logging to commander.
salsolatragus Mar 2, 2021
577373d
Merge remote-tracking branch 'origin/tia_report' into tia
salsolatragus Mar 2, 2021
601669b
Performance improvements:
mpdeimos Mar 2, 2021
cfb259b
Merge branch 'tia' of https://github.com/cqse/teamscale-profiler-dotn…
mpdeimos Mar 2, 2021
d52ecaf
Add missing dependency to commander.
salsolatragus Mar 8, 2021
4cc5eb5
support test path prefixes
mpdeimos Feb 12, 2021
5907e52
correct emptiness handling for testwise traces
mpdeimos Feb 12, 2021
d0c4f3e
Add some interface comments.
salsolatragus Mar 10, 2021
e561a15
Reduce default log level to Info.
salsolatragus Mar 10, 2021
609bdfd
Add improvements to branch
Raphael-N Sep 8, 2021
8c869e9
Add comments and fix Testee bitness
Raphael-N Oct 4, 2021
975801d
fix empty traces
mpdeimos Mar 16, 2021
4cafeeb
* keep existing tests also for report merge
mpdeimos Mar 16, 2021
f7503c2
remove support for known test cases
mpdeimos Mar 17, 2022
793f93b
add support for partial coverage reports
mpdeimos Mar 17, 2022
e6c7c79
Potential Fix for crashes at Healthineers
Raphael-N Mar 22, 2022
244bc12
Fix casing
mpdeimos Mar 24, 2022
c780e5f
Commander CLI
mpdeimos Mar 24, 2022
ef2410a
Commander Server
mpdeimos Mar 24, 2022
717a669
Review
mpdeimos Apr 1, 2022
6717a8e
review
mpdeimos Apr 12, 2022
b083f25
add logging
mpdeimos Apr 13, 2022
7cece30
add quiet mode
mpdeimos Apr 13, 2022
889d158
additional null checks
mpdeimos Apr 13, 2022
3d3a934
add nullable library
mpdeimos Apr 13, 2022
823bac7
forbid setting test name to null
mpdeimos Apr 13, 2022
f1a85b3
🤦
mpdeimos Apr 13, 2022
4e08202
better error handling
mpdeimos Apr 13, 2022
725cbe5
Merge pull request #160 from cqse/tia_server_cli
Raphael-N Apr 25, 2022
af822fe
Update Platform version and toolset
Raphael-N Apr 26, 2022
59171c6
Remove ifdefs, rework, add tga toggle to options
Raphael-N Apr 26, 2022
e1ca972
Swap vectors instead of using a toggle boolean
Raphael-N Apr 28, 2022
9afa9aa
Rename method id vectors to primary and backing vectors
Raphael-N Apr 28, 2022
c57da74
Merge pull request #155 from cqse/tia-merge-reports
Raphael-N Apr 28, 2022
6bde083
Add tests for tga and tia configurations
Raphael-N May 12, 2022
776e0bd
Implement int set to achieve faster checks
Raphael-N May 22, 2022
ef52fae
Add documentation to custom set implementation
Raphael-N Jun 1, 2022
c5e0762
Merge branch 'tia' into performance_improvements_tia
Raphael-N Jun 1, 2022
b3d64f2
Fix minor issue
Raphael-N Jun 1, 2022
122a357
Rework
Raphael-N Jun 7, 2022
0bd6864
Merge pull request #158 from cqse/performance_improvements_tia
mpdeimos Jun 8, 2022
3e0225e
Fix issue in functionId_set
Raphael-N Jul 4, 2022
b09bc74
update bummer/update output path
mpdeimos Jul 8, 2022
04d1980
bummer update
mpdeimos Jul 14, 2022
6aeea2c
fix tests
mpdeimos Jul 14, 2022
ec9d95f
Use newer libzmq commands for context shutdown and add timeout to sub…
Raphael-N Aug 1, 2022
68bd98f
pre-initialize profiler ipc
mpdeimos Aug 10, 2022
37db7ce
Add documentation for TIA mode catch in shutdown
Raphael-N Jan 18, 2023
907d385
Merge branch 'master' into tia
Raphael-N Feb 8, 2023
1833413
Fix Test cases
Raphael-N Feb 8, 2023
6f5659f
Consider testwise coverage for artifactory uploads
Raphael-N May 19, 2023
0866873
Change name for artifactory report upload
Raphael-N Jun 16, 2023
ef114a8
Merge branch 'master' into tia
Raphael-N Jun 21, 2023
732af2b
Fix Test after merge
Raphael-N Jun 23, 2023
df39b8d
Remove Worker thread due to issues with many processes
Raphael-N Jul 24, 2023
34570e4
Add Zipping step to Artifactory Upload
Raphael-N Jul 30, 2023
eb09de3
Fix Artifactory Upload
Raphael-N Jul 30, 2023
7e6b4ee
Improve artifactory branches
Raphael-N Jul 30, 2023
13a4cc6
add dialog for recording test duration
Aug 1, 2023
265f77d
implement long <-> string conversion for duration
Aug 1, 2023
488b600
send adjusted duration to profiler
Aug 1, 2023
0013465
fix bugs
Aug 1, 2023
77f704a
fix teamscale findings
Aug 1, 2023
a14794b
Start implementing synchronous communication
Raphael-N Aug 2, 2023
25cc661
Add Socket handling
Raphael-N Aug 2, 2023
352cd4f
Support time configuration in profiler and daemon
Raphael-N Aug 2, 2023
82e4720
Use milliseconds for automated tests
Raphael-N Aug 2, 2023
1af9253
Fix some communication issues
Raphael-N Aug 3, 2023
48ec74d
rework
Aug 3, 2023
69c2fdf
update to newer framework version
Aug 4, 2023
50c49b8
malformed trace lines should not crash upload daemon
Aug 4, 2023
89f82ef
Send PID to ZmqIpcServer as clientID
Aug 4, 2023
b12a785
Update TargetFrameworkVersion in UploadDaemon_Test
Aug 4, 2023
96e5746
rework
Raphael-N Aug 7, 2023
82a9680
Rework
Raphael-N Aug 7, 2023
474fa63
Write as one string instead of per entry
Raphael-N Aug 7, 2023
78b8d62
Add synchronization to jit inlining events
Raphael-N Aug 9, 2023
1a961c8
Fix casing of results
Raphael-N Aug 17, 2023
8e94aa4
Merge branch 'tia_synchronous_events' of https://github.com/cqse/team…
Raphael-N Aug 17, 2023
269a07e
Disable inlining for accurate results
Raphael-N Aug 17, 2023
c584514
Merge pull request #180 from cqse/test-commander-change-duration
Raphael-N Aug 18, 2023
fa7ea27
Fix encoding of test names
Raphael-N Aug 29, 2023
c6fe173
Update Test Times and Add Checks for running Tests
Raphael-N Sep 19, 2023
a16e337
Fix initial test not appearing
Raphael-N Sep 22, 2023
652929c
Fix Process not shutting down
Raphael-N Sep 22, 2023
306ab2e
Improve performance of Upload Daemon
Raphael-N Sep 22, 2023
82c75f9
TS#35530 Check if the trace directory is writable
Raphael-N Sep 25, 2023
77630df
Fix issue with time sending
Raphael-N Oct 4, 2023
0485275
Reduce Memory Usage
Raphael-N Oct 27, 2023
6ef1bcf
Replace newline with space in testname
Raphael-N Oct 27, 2023
668537d
Implement Splitting for too large reports
Raphael-N Oct 30, 2023
7db2f6d
Merge branch 'tia' into tia_synchronous_events
Raphael-N Nov 27, 2023
5d1bb79
Cleanup leftovers from merge
Raphael-N Nov 29, 2023
5aa9762
Minor fixes
Raphael-N Jan 10, 2024
db12283
Fix several Teamscale findings
Raphael-N Jan 26, 2024
ca0da28
Add String report splitting for other upload types
Raphael-N Jan 31, 2024
9311980
Small fixes
Raphael-N Feb 27, 2024
a239651
Fix tests and socket configurations
Raphael-N Feb 28, 2024
20fa0fe
Fix Tests
Raphael-N Mar 20, 2024
62a1aeb
Update tests
Raphael-N Apr 10, 2024
a192408
More Test fixes and add back pipeline
Raphael-N Apr 12, 2024
b0ef272
Merge pull request #183 from cqse/tia_synchronous_events
Raphael-N Apr 12, 2024
38c11b4
Merge branch 'master' into tia
Raphael-N Jun 21, 2024
5160d84
Merge branch 'tia' of https://github.com/cqse/teamscale-profiler-dotn…
Raphael-N Jun 21, 2024
6800edd
Fix merge leftovers
Raphael-N Jun 26, 2024
0a63d9c
TS#38029 Fix remaining tests
Raphael-N Jul 10, 2024
a43ce20
Merge branch 'master' into tia
Raphael-N Jul 10, 2024
e71d373
TS#38029 Update Profiler Testee
Raphael-N Jul 10, 2024
91c8a68
TS#38029 Introduce AssemblyExtractor to fix EmbeddudUploadTarget Hand…
Raphael-N Jul 15, 2024
bd3289a
TS#38029 Fix TS findings
Raphael-N Jul 15, 2024
d660612
TS#38029 Rework functionId_set
Raphael-N Jul 22, 2024
a4a70c8
TS#38029 Refactor trace file parsing
Raphael-N Aug 1, 2024
55b4ec4
TS#38029 Fix leftover issues from TraceFileParser rework
Raphael-N Aug 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Introduce ICoverageReport abstraction.
  • Loading branch information
salsolatragus committed Jan 31, 2021
commit 1fcbe0971fc3b84a4bf0e0c0a2ee465d44919064
17 changes: 17 additions & 0 deletions UploadDaemon/Report/ICoverageReport.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
namespace UploadDaemon.Report
{
/// <summary>
/// A coverage report.
/// </summary>
public interface ICoverageReport
{
/// <summary>
/// Whether this report contains any coverage.
/// </summary>
bool IsEmpty { get; }

/// <summary>
/// The file extension for this type of report.
/// </summary>
string FileExtension { get; }

/// <summary>
/// Returns a new report wth the union of the coverage data of both reports.
/// </summary>
ICoverageReport UnionWith(ICoverageReport coverageReport);
}
}
43 changes: 41 additions & 2 deletions UploadDaemon/Report/SimpleCoverageReport.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,56 @@
using UploadDaemon.SymbolAnalysis;
using System;
using System.Collections.Generic;
using System.Text;
using UploadDaemon.SymbolAnalysis;

namespace UploadDaemon.Report
{
/// <summary>
/// A Teamscale simple coverage report.
/// </summary>
public class SimpleCoverageReport :ICoverageReport
public class SimpleCoverageReport : ICoverageReport
{
private readonly LineCoverageReport coverage;

public SimpleCoverageReport(LineCoverageReport coverage)
{
this.coverage = coverage;
}

public bool IsEmpty => coverage.IsEmpty;

public string FileExtension => "simple";

/// <inheritDoc/>
public ICoverageReport UnionWith(ICoverageReport otherReport)
{
if (!(otherReport is SimpleCoverageReport other))
{
throw new NotSupportedException();
}

LineCoverageReport union = new LineCoverageReport(new Dictionary<string, FileCoverage>());
union.UnionWith(this.coverage);
union.UnionWith(other.coverage);
return new SimpleCoverageReport(union);
}

/// <summary>
/// Converts this report into a SIMPLE format report for Teamscale.
/// </summary>
public override string ToString()
{
StringBuilder report = new StringBuilder();
report.AppendLine("# isMethodAccurate=true");
foreach (string file in coverage.FileNames)
{
report.AppendLine(file);
foreach ((uint startLine, uint endLine) in coverage[file].CoveredLineRanges)
{
report.AppendLine($"{startLine}-{endLine}");
}
}
return report.ToString();
}
}
}
18 changes: 18 additions & 0 deletions UploadDaemon/Report/TestwiseCoverageReport.cs
Original file line number Diff line number Diff line change
@@ -53,5 +53,23 @@ public static CoverageForPath From(LineCoverageReport report)

[JsonProperty(PropertyName = "tests")]
public IList<Test> Tests = new List<Test>();

public bool IsEmpty => Tests.All(test => test.CoverageByPath.All(coverage => coverage.Files.Count == 0));

public string FileExtension => "testwise";

public ICoverageReport UnionWith(ICoverageReport coverageReport)
{
throw new System.NotImplementedException();
}


/// <summary>
/// Converts this report into a TESTWISE format report for Teamscale.
/// </summary>
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
}
43 changes: 1 addition & 42 deletions UploadDaemon/SymbolAnalysis/LineCoverageReport.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UploadDaemon.Report;

namespace UploadDaemon.SymbolAnalysis
{
@@ -41,44 +38,6 @@ public FileCoverage this[string fileName]
get => lineCoverage[fileName];
}

/// <summary>
/// Converts the given line coverage (covered line ranges per file) into a SIMPLE format report for Teamscale.
/// </summary>
public string ToReportString()
{
StringBuilder report = new StringBuilder();
report.AppendLine("# isMethodAccurate=true");
foreach (string file in lineCoverage.Keys)
{
report.AppendLine(file);
foreach ((uint startLine, uint endLine) in lineCoverage[file].CoveredLineRanges)
{
report.AppendLine($"{startLine}-{endLine}");
}
}
return report.ToString();
}

public string ToTestwiseReportString()
{
return JsonConvert.SerializeObject(new TestwiseCoverageReport()
{
Tests = new List<TestwiseCoverageReport.Test>()
{
new TestwiseCoverageReport.Test()
{
UniformPath = "No Test",
Duration = 42.0,
Result = "PASSED",
CoverageByPath = new List<TestwiseCoverageReport.Test.CoverageForPath>()
{
TestwiseCoverageReport.Test.CoverageForPath.From(this)
}
}
}
});
}

/// <summary>
/// Modifies the current <see cref="LineCoverageReport"/> to contain the coverage from this report and the other report.
/// </summary>
6 changes: 4 additions & 2 deletions UploadDaemon/Upload/AzureUpload.cs
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@
using System.Threading.Tasks;
using UploadDaemon.SymbolAnalysis;
using UploadDaemon.Configuration;
using UploadDaemon.Report;

namespace UploadDaemon.Upload
{
@@ -114,7 +115,8 @@ public string Describe()
return $"Azure share {storage.ShareName}, directory {storage.Directory}";
}

public async Task<bool> UploadLineCoverageAsync(string originalTraceFilePath, string lineCoverageReport, RevisionFileUtils.RevisionOrTimestamp revisionOrTimestamp)
/// <inheritDoc/>
public async Task<bool> UploadLineCoverageAsync(string originalTraceFilePath, ICoverageReport coverageReport, RevisionFileUtils.RevisionOrTimestamp revisionOrTimestamp)
{
try
{
@@ -125,7 +127,7 @@ public async Task<bool> UploadLineCoverageAsync(string originalTraceFilePath, st
CloudFileShare share = await GetOrCreateShareAsync(account);
CloudFileDirectory directory = await GetOrCreateTargetDirectoryAsync(share);
long unixSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
await UploadTextAsync(lineCoverageReport, $"{unixSeconds}.simple", directory);
await UploadTextAsync(coverageReport.ToString(), $"{unixSeconds}.{coverageReport.FileExtension}", directory);
await UploadTextAsync(revisionOrTimestamp.ToRevisionFileContent(), $"{unixSeconds}.metadata", directory);

logger.Info("Successfully uploaded line coverage from {trace} to {azure}/{directory}", originalTraceFilePath,
8 changes: 5 additions & 3 deletions UploadDaemon/Upload/FileSystemUpload.cs
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
using System.IO.Abstractions;
using System.Threading.Tasks;
using NLog;
using UploadDaemon.Report;
using UploadDaemon.SymbolAnalysis;

namespace UploadDaemon.Upload
@@ -53,15 +54,16 @@ public string Describe()
return $"file system directory {targetDirectory}";
}

public Task<bool> UploadLineCoverageAsync(string originalTraceFilePath, string lineCoverageReport, RevisionFileUtils.RevisionOrTimestamp revisionOrTimestamp)
/// <inheritDoc/>
public Task<bool> UploadLineCoverageAsync(string originalTraceFilePath, ICoverageReport coverageReport, RevisionFileUtils.RevisionOrTimestamp revisionOrTimestamp)
{
long unixSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
string filePath = Path.Combine(targetDirectory, $"{unixSeconds}.simple");
string filePath = Path.Combine(targetDirectory, $"{unixSeconds}.{coverageReport.FileExtension}");
string metadataFilePath = Path.Combine(targetDirectory, $"{unixSeconds}.metadata");

try
{
fileSystem.File.WriteAllText(filePath, lineCoverageReport);
fileSystem.File.WriteAllText(filePath, coverageReport.ToString());
fileSystem.File.WriteAllText(metadataFilePath, revisionOrTimestamp.ToRevisionFileContent());
return Task.FromResult(true);
}
5 changes: 3 additions & 2 deletions UploadDaemon/Upload/IUpload.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Threading.Tasks;
using UploadDaemon.Report;
using UploadDaemon.SymbolAnalysis;

namespace UploadDaemon.Upload
@@ -22,10 +23,10 @@ public interface IUpload
/// Must not throw any exceptions.
/// </summary>
/// <param name="originalTraceFilePath">The path to the original trace file (used when logging to allow attribution of log messages to a trace file).</param>
/// <param name="lineCoverageReport">The content of the coverage report.</param>
/// <param name="coverageReport">The coverage report.</param>
/// <param name="revisionOrTimestamp">The VCS revision or Teamscale branch+timestamp to which the report should be uploaded.</param>
/// <returns>Whether the upload succeeded</returns>
Task<bool> UploadLineCoverageAsync(string originalTraceFilePath, string lineCoverageReport, RevisionFileUtils.RevisionOrTimestamp revisionOrTimestamp);
Task<bool> UploadLineCoverageAsync(string originalTraceFilePath, ICoverageReport coverageReport, RevisionFileUtils.RevisionOrTimestamp revisionOrTimestamp);

/// <summary>
/// Returns a human-readable description of the upload that can be incorporated in log messages.
13 changes: 9 additions & 4 deletions UploadDaemon/Upload/LineCoverageMerger.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using UploadDaemon.Report;
using UploadDaemon.SymbolAnalysis;

namespace UploadDaemon.Upload
@@ -58,9 +59,9 @@ public class CoverageBatch
public IUpload Upload { get; }

/// <summary>
/// The line coverage that should be uploaded.
/// The aggregated coverage report in this batch.
/// </summary>
public LineCoverageReport LineCoverage { get; } = new LineCoverageReport(new Dictionary<string, FileCoverage>());
public ICoverageReport AggregatedCoverageReport;

/// <summary>
/// The original trace files from which the line coverage was generated.
@@ -81,7 +82,7 @@ public CoverageBatch(IUpload upload, RevisionFileUtils.RevisionOrTimestamp revis
/// given revision/timestamp to the given upload to the merger. The coverage will be merged with
/// any existing coverage that should be uploaded to the same destination.
/// </summary>
public void AddLineCoverage(string traceFilePath, RevisionFileUtils.RevisionOrTimestamp revisionOrTimestamp, IUpload upload, LineCoverageReport lineCoverage)
public void AddLineCoverage(string traceFilePath, RevisionFileUtils.RevisionOrTimestamp revisionOrTimestamp, IUpload upload, ICoverageReport coverageReport)
{
MergeKey key = new MergeKey
{
@@ -93,11 +94,15 @@ public void AddLineCoverage(string traceFilePath, RevisionFileUtils.RevisionOrTi
if (!mergedCoverage.TryGetValue(key, out CoverageBatch batch))
{
batch = new CoverageBatch(upload, key.RevisionOrTimestamp);
batch.AggregatedCoverageReport = coverageReport;
mergedCoverage[key] = batch;
}
else
{
batch.AggregatedCoverageReport = batch.AggregatedCoverageReport.UnionWith(coverageReport);
}

batch.TraceFilePaths.Add(traceFilePath);
batch.LineCoverage.UnionWith(lineCoverage);
}

/// <summary>
6 changes: 4 additions & 2 deletions UploadDaemon/Upload/TeamscaleUpload.cs
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@
using System.Web;
using UploadDaemon.SymbolAnalysis;
using UploadDaemon.Configuration;
using UploadDaemon.Report;

namespace UploadDaemon.Upload
{
@@ -79,7 +80,8 @@ public string Describe()
return server.ToString();
}

public async Task<bool> UploadLineCoverageAsync(string originalTraceFilePath, string lineCoverageReport, RevisionFileUtils.RevisionOrTimestamp revisionOrTimestamp)
/// <inheritDoc/>
public async Task<bool> UploadLineCoverageAsync(string originalTraceFilePath, ICoverageReport coverageReport, RevisionFileUtils.RevisionOrTimestamp revisionOrTimestamp)
{
string timestampParameter;
if (revisionOrTimestamp.IsRevision)
@@ -104,7 +106,7 @@ public async Task<bool> UploadLineCoverageAsync(string originalTraceFilePath, st

try
{
byte[] reportBytes = Encoding.UTF8.GetBytes(lineCoverageReport);
byte[] reportBytes = Encoding.UTF8.GetBytes(coverageReport.ToString());
using (MemoryStream stream = new MemoryStream(reportBytes))
{
return await PerformLineCoverageUpload(originalTraceFilePath, timestampParameter, revisionOrTimestamp.Value, url, stream);
26 changes: 13 additions & 13 deletions UploadDaemon/UploadTask.cs
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@
using UploadDaemon.Configuration;
using UploadDaemon.Scanning;
using UploadDaemon.Upload;
using UploadDaemon.Report;

namespace UploadDaemon
{
@@ -88,14 +89,14 @@ private static void UploadCoverageBatch(Archive archive, Config config, LineCove
{
logger.Debug("Uploading merged line coverage from {traceFile} to {upload}",
string.Join(", ", batch.TraceFilePaths), batch.Upload.Describe());
string report = batch.LineCoverage.ToReportString();
ICoverageReport report = batch.AggregatedCoverageReport;

string traceFilePaths = string.Join(", ", batch.TraceFilePaths);

if (config.ArchiveLineCoverage)
{
long timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
archive.ArchiveLineCoverage($"merged_{timestamp}.simple", report);
archive.ArchiveLineCoverage($"merged_{timestamp}.{report.FileExtension}", report.ToString());
}

if (RunSync(batch.Upload.UploadLineCoverageAsync(traceFilePaths, report, batch.RevisionOrTimestamp)))
@@ -145,27 +146,26 @@ private void ProcessLineCoverage(TraceFile trace, Archive archive, Config config
{
logger.Debug("Preparing line coverage from {traceFile} for {upload}", trace.FilePath, upload.Describe());
RevisionFileUtils.RevisionOrTimestamp timestampOrRevision = ParseRevisionFile(trace, processConfig);
LineCoverageReport lineCoverage = ConvertTraceFileToLineCoverage(trace, archive, processConfig);
if (timestampOrRevision == null || lineCoverage == null)
ICoverageReport coverageReport = ConvertTraceToCoverageReport(trace, archive, processConfig);
if (timestampOrRevision == null || coverageReport == null)
{
return;
}

if (config.ArchiveLineCoverage)
{
archive.ArchiveLineCoverage(Path.GetFileName(trace.FilePath) + ".simple", lineCoverage.ToReportString());
archive.ArchiveLineCoverage(Path.GetFileName(trace.FilePath) + "." + coverageReport.FileExtension, coverageReport.ToString());
}

if (processConfig.MergeLineCoverage)
{
logger.Debug("Merging line coverage from {traceFile} into previous line coverage", trace.FilePath);
coverageMerger.AddLineCoverage(trace.FilePath, timestampOrRevision, upload, lineCoverage);
coverageMerger.AddLineCoverage(trace.FilePath, timestampOrRevision, upload, coverageReport);
return;
}

logger.Debug("Uploading line coverage from {traceFile} to {upload}", trace.FilePath, upload.Describe());
string report = lineCoverage.ToReportString();
if (RunSync(upload.UploadLineCoverageAsync(trace.FilePath, report, timestampOrRevision)))
if (RunSync(upload.UploadLineCoverageAsync(trace.FilePath, coverageReport, timestampOrRevision)))
{
archive.ArchiveUploadedFile(trace.FilePath);
}
@@ -196,27 +196,27 @@ private RevisionFileUtils.RevisionOrTimestamp ParseRevisionFile(TraceFile trace,
/// Tries to read and convert the trace file. Logs and returns null if this fails.
/// Empty trace files are archived and null is returned as well.
/// </summary>
private LineCoverageReport ConvertTraceFileToLineCoverage(TraceFile traceFile, Archive archive, Config.ConfigForProcess processConfig)
private ICoverageReport ConvertTraceToCoverageReport(TraceFile traceFile, Archive archive, Config.ConfigForProcess processConfig)
{
LineCoverageReport lineCoverage;
ICoverageReport report;
try
{
lineCoverage = lineCoverageSynthesizer.ConvertToLineCoverage(new Trace() { OriginTraceFilePath = traceFile.FilePath, CoveredMethods = traceFile.FindCoveredMethods() }, processConfig.PdbDirectory, processConfig.AssemblyPatterns);
report = traceFile.ToReport((trace) => lineCoverageSynthesizer.ConvertToLineCoverage(trace, processConfig.PdbDirectory, processConfig.AssemblyPatterns));
}
catch (Exception e)
{
logger.Error(e, "Failed to convert {traceFile} to line coverage. Will retry later", traceFile.FilePath);
return null;
}

if (lineCoverage.IsEmpty)
if (report.IsEmpty)
{
logger.Info("Archiving {trace} because it did not produce any line coverage after conversion", traceFile.FilePath);
archive.ArchiveFileWithoutLineCoverage(traceFile.FilePath);
return null;
}

return lineCoverage;
return report;
}

private static void ProcessMethodCoverage(TraceFile trace, Archive archive, Config.ConfigForProcess processConfig, IUpload upload)
Loading