Skip to content

Commit 6ee2d9b

Browse files
fix serialization bug
1 parent 24d5aca commit 6ee2d9b

File tree

5 files changed

+248
-47
lines changed

5 files changed

+248
-47
lines changed

Documentation/Troubleshooting.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,55 @@ Hits file:'C:\Users\Marco\AppData\Local\Temp\coverlet.core_703263e9-21f0-4d1c-9c
5959
| Average | 4,44% | 3,455% | 5,66% |
6060
+---------+--------+--------+--------+
6161
```
62+
63+
## Use local build
64+
65+
Sometimes is useful test local updated source to fix issue.
66+
You can "load" your local build using simple switch:
67+
68+
* build repo
69+
70+
```
71+
D:\git\coverlet (fixjsonserializerbug -> origin)
72+
λ dotnet build
73+
Microsoft (R) Build Engine version 16.1.76+g14b0a930a7 for .NET Core
74+
Copyright (C) Microsoft Corporation. All rights reserved.
75+
76+
Restore completed in 52.23 ms for D:\git\coverlet\test\coverlet.testsubject\coverlet.testsubject.csproj.
77+
Restore completed in 58.97 ms for D:\git\coverlet\src\coverlet.console\coverlet.console.csproj.
78+
Restore completed in 59 ms for D:\git\coverlet\src\coverlet.core\coverlet.core.csproj.
79+
Restore completed in 59.17 ms for D:\git\coverlet\src\coverlet.msbuild.tasks\coverlet.msbuild.tasks.csproj.
80+
Restore completed in 59.26 ms for D:\git\coverlet\src\coverlet.collector\coverlet.collector.csproj.
81+
Restore completed in 60.1 ms for D:\git\coverlet\test\coverlet.collector.tests\coverlet.collector.tests.csproj.
82+
Restore completed in 60.42 ms for D:\git\coverlet\test\coverlet.core.performancetest\coverlet.core.performancetest.csproj.
83+
Restore completed in 60.47 ms for D:\git\coverlet\test\coverlet.core.tests\coverlet.core.tests.csproj.
84+
Restore completed in 22.85 ms for D:\git\coverlet\test\coverlet.core.tests\coverlet.core.tests.csproj.
85+
coverlet.testsubject -> D:\git\coverlet\test\coverlet.testsubject\bin\Debug\netcoreapp2.0\coverlet.testsubject.dll
86+
coverlet.core -> D:\git\coverlet\src\coverlet.core\bin\Debug\netstandard2.0\coverlet.core.dll
87+
coverlet.msbuild.tasks -> D:\git\coverlet\src\coverlet.msbuild.tasks\bin\Debug\netstandard2.0\coverlet.msbuild.tasks.dll
88+
coverlet.collector -> D:\git\coverlet\src\coverlet.collector\bin\Debug\netcoreapp2.0\coverlet.collector.dll
89+
coverlet.console -> D:\git\coverlet\src\coverlet.console\bin\Debug\netcoreapp2.2\coverlet.console.dll
90+
coverlet.core.performancetest -> D:\git\coverlet\test\coverlet.core.performancetest\bin\Debug\netcoreapp2.0\coverlet.core.performancetest.dll
91+
coverlet.core.tests -> D:\git\coverlet\test\coverlet.core.tests\bin\Debug\netcoreapp2.0\coverlet.core.tests.dll
92+
coverlet.collector.tests -> D:\git\coverlet\test\coverlet.collector.tests\bin\Debug\netcoreapp2.2\coverlet.collector.tests.dll
93+
94+
Build succeeded.
95+
0 Warning(s)
96+
0 Error(s)
97+
98+
Time Elapsed 00:00:07.42
99+
100+
D:\git\coverlet (fixjsonserializerbug -> origin)
101+
λ
102+
103+
```
104+
105+
* Go to repro project and run
106+
```
107+
D:\git\Cake.Codecov\Source\Cake.Codecov.Tests (develop -> origin)
108+
λ dotnet test /p:CollectCoverage=true /p:Exclude="[xunit.*]*" /p:CoverletToolsPath=D:\git\coverlet\src\coverlet.msbuild.tasks\bin\Debug\netstandard2.0\
109+
Test run for D:\git\Cake.Codecov\Source\Cake.Codecov.Tests\bin\Debug\netcoreapp2.0\Cake.Codecov.Tests.dll(.NETCoreApp,Version=v2.0)
110+
...
111+
```
112+
113+
In this way you can add `Debug.Launch()` inside coverlet source and debug.
Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,39 @@
1-
using System.IO;
2-
using System.Text;
3-
1+
using System;
2+
using System.IO;
3+
using System.Runtime.Serialization;
4+
using System.Runtime.Serialization.Formatters.Binary;
45
using Coverlet.Core.Instrumentation;
5-
using Newtonsoft.Json;
66

77
namespace Coverlet.Core
88
{
9+
// Followed safe serializer guide, will emit xml format
10+
// https://docs.microsoft.com/en-us/visualstudio/code-quality/ca2300-do-not-use-insecure-deserializer-binaryformatter?view=vs-2019
11+
// https://docs.microsoft.com/en-us/visualstudio/code-quality/ca2301-do-not-call-binaryformatter-deserialize-without-first-setting-binaryformatter-binder?view=vs-2019
12+
[DataContract]
913
public class CoveragePrepareResult
1014
{
15+
[DataMember]
1116
public string Identifier { get; set; }
17+
[DataMember]
1218
public string Module { get; set; }
19+
[DataMember]
1320
public string MergeWith { get; set; }
21+
[DataMember]
1422
public bool UseSourceLink { get; set; }
23+
[DataMember]
1524
public InstrumenterResult[] Results { get; set; }
1625

1726
public static CoveragePrepareResult Deserialize(Stream serializedInstrumentState)
1827
{
19-
var serializer = new JsonSerializer();
20-
using (var sr = new StreamReader(serializedInstrumentState))
21-
using (var jsonTextReader = new JsonTextReader(sr))
22-
{
23-
return serializer.Deserialize<CoveragePrepareResult>(jsonTextReader);
24-
}
28+
return (CoveragePrepareResult)new DataContractSerializer(typeof(CoveragePrepareResult)).ReadObject(serializedInstrumentState);
2529
}
2630

2731
public static Stream Serialize(CoveragePrepareResult instrumentState)
2832
{
29-
var serializer = new JsonSerializer();
3033
MemoryStream ms = new MemoryStream();
31-
using (var sw = new StreamWriter(ms, Encoding.UTF8, 1024, true))
32-
{
33-
serializer.Serialize(sw, instrumentState);
34-
sw.Flush();
35-
ms.Position = 0;
36-
return ms;
37-
}
34+
new DataContractSerializer(typeof(CoveragePrepareResult)).WriteObject(ms, instrumentState);
35+
ms.Position = 0;
36+
return ms;
3837
}
3938
}
4039
}
Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,44 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.ComponentModel;
4-
using System.Globalization;
5-
using System.IO;
6-
using Newtonsoft.Json;
3+
using System.Runtime.Serialization;
74

85
namespace Coverlet.Core.Instrumentation
96
{
7+
[DataContract]
108
public class Line
119
{
10+
[DataMember]
1211
public int Number;
12+
[DataMember]
1313
public string Class;
14+
[DataMember]
1415
public string Method;
16+
[DataMember]
1517
public int Hits;
1618
}
1719

20+
[DataContract]
1821
public class Branch : Line
1922
{
23+
[DataMember]
2024
public int Offset;
25+
[DataMember]
2126
public int EndOffset;
27+
[DataMember]
2228
public int Path;
29+
[DataMember]
2330
public uint Ordinal;
2431
}
2532

26-
public class BranchKeyConverter : TypeConverter
27-
{
28-
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
29-
{
30-
return sourceType == typeof(string);
31-
}
32-
33-
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
34-
{
35-
return JsonConvert.DeserializeObject<BranchKey>(value.ToString());
36-
}
37-
38-
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
39-
{
40-
return destinationType == typeof(BranchKey);
41-
}
42-
}
43-
44-
[TypeConverter(typeof(BranchKeyConverter))]
33+
// Implements IEquatable because is used by dictionary key https://docs.microsoft.com/en-us/dotnet/api/system.iequatable-1?view=netcore-2.2#remarks
34+
[DataContract]
4535
public class BranchKey : IEquatable<BranchKey>
4636
{
4737
public BranchKey(int line, int ordinal) => (Line, Ordinal) = (line, ordinal);
4838

39+
[DataMember]
4940
public int Line { get; set; }
41+
[DataMember]
5042
public int Ordinal { get; set; }
5143

5244
public override bool Equals(object obj) => Equals(obj);
@@ -57,13 +49,9 @@ public override int GetHashCode()
5749
{
5850
return (this.Line, this.Ordinal).GetHashCode();
5951
}
60-
61-
public override string ToString()
62-
{
63-
return JsonConvert.SerializeObject(this);
64-
}
6552
}
6653

54+
[DataContract]
6755
public class Document
6856
{
6957
public Document()
@@ -72,22 +60,32 @@ public Document()
7260
Branches = new Dictionary<BranchKey, Branch>();
7361
}
7462

63+
[DataMember]
7564
public string Path;
65+
[DataMember]
7666
public int Index;
67+
[DataMember]
7768
public Dictionary<int, Line> Lines { get; private set; }
69+
[DataMember]
7870
public Dictionary<BranchKey, Branch> Branches { get; private set; }
7971
}
8072

73+
[DataContract]
8174
public class HitCandidate
8275
{
8376
public HitCandidate(bool isBranch, int docIndex, int start, int end) => (this.isBranch, this.docIndex, this.start, this.end) = (isBranch, docIndex, start, end);
8477

78+
[DataMember]
8579
public bool isBranch { get; set; }
80+
[DataMember]
8681
public int docIndex { get; set; }
82+
[DataMember]
8783
public int start { get; set; }
84+
[DataMember]
8885
public int end { get; set; }
8986
}
9087

88+
[DataContract]
9189
public class InstrumenterResult
9290
{
9391
public InstrumenterResult()
@@ -96,12 +94,19 @@ public InstrumenterResult()
9694
HitCandidates = new List<HitCandidate>();
9795
}
9896

97+
[DataMember]
9998
public string Module;
99+
[DataMember]
100100
public string[] AsyncMachineStateMethod;
101+
[DataMember]
101102
public string HitsFilePath;
103+
[DataMember]
102104
public string ModulePath;
105+
[DataMember]
103106
public string SourceLink;
107+
[DataMember]
104108
public Dictionary<string, Document> Documents { get; private set; }
109+
[DataMember]
105110
public List<HitCandidate> HitCandidates { get; private set; }
106111
}
107112
}

src/coverlet.core/coverlet.core.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99

1010
<ItemGroup>
1111
<PackageReference Include="Mono.Cecil" Version="0.10.1" />
12-
<PackageReference Include="Newtonsoft.Json" Version="10.0.1" />
12+
<!-- Do not upgrade this version or we won't support old SDK -->
13+
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
1314
<!--
1415
Do not change System.Reflection.Metadata version since we need to support VSTest DataCollectors. Goto https://www.nuget.org/packages/System.Reflection.Metadata to check versions.
1516
We need to load assembly version 1.4.2.0 to properly work

0 commit comments

Comments
 (0)