Skip to content

Commit 8149c36

Browse files
authored
Json exporter fix for double.NaN (#1581), fixes #1242
1 parent d5c158c commit 8149c36

File tree

5 files changed

+169
-80
lines changed

5 files changed

+169
-80
lines changed

src/BenchmarkDotNet/Exporters/Json/SimpleJson.cs

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ static class SimpleJson
515515
private const int TOKEN_FALSE = 10;
516516
private const int TOKEN_NULL = 11;
517517
private const int BUILDER_CAPACITY = 2000;
518+
internal const string JSON_EMPTY_STRING = "\"\"";
518519

519520
private static readonly char[] EscapeTable;
520521
private static readonly char[] EscapeCharacters = new char[] { '"', '\\', '\b', '\f', '\n', '\r', '\t' };
@@ -1169,20 +1170,36 @@ static bool SerializeString(string aString, StringBuilder builder)
11691170

11701171
static bool SerializeNumber(object number, StringBuilder builder)
11711172
{
1172-
if (number is long)
1173-
builder.Append(((long)number).ToString(CultureInfo.InvariantCulture));
1174-
else if (number is ulong)
1175-
builder.Append(((ulong)number).ToString(CultureInfo.InvariantCulture));
1176-
else if (number is int)
1177-
builder.Append(((int)number).ToString(CultureInfo.InvariantCulture));
1178-
else if (number is uint)
1179-
builder.Append(((uint)number).ToString(CultureInfo.InvariantCulture));
1180-
else if (number is decimal)
1181-
builder.Append(((decimal)number).ToString(CultureInfo.InvariantCulture));
1182-
else if (number is float)
1183-
builder.Append(((float)number).ToString(CultureInfo.InvariantCulture));
1184-
else
1185-
builder.Append(Convert.ToDouble(number, CultureInfo.InvariantCulture).ToString("r", CultureInfo.InvariantCulture));
1173+
object value = ReplaceUnsupportedNumericValues(number);
1174+
if (!value.Equals(JSON_EMPTY_STRING))
1175+
{
1176+
switch (value)
1177+
{
1178+
case long num:
1179+
value = num.ToString(CultureInfo.InvariantCulture);
1180+
break;
1181+
case ulong num:
1182+
value = num.ToString(CultureInfo.InvariantCulture);
1183+
break;
1184+
case int num:
1185+
value = num.ToString(CultureInfo.InvariantCulture);
1186+
break;
1187+
case uint num:
1188+
value = num.ToString(CultureInfo.InvariantCulture);
1189+
break;
1190+
case decimal num:
1191+
value = num.ToString(CultureInfo.InvariantCulture);
1192+
break;
1193+
case float num:
1194+
value = num.ToString(CultureInfo.InvariantCulture);
1195+
break;
1196+
default:
1197+
value = Convert.ToDouble(value, CultureInfo.InvariantCulture).ToString("r", CultureInfo.InvariantCulture);
1198+
break;
1199+
}
1200+
}
1201+
1202+
builder.Append(value);
11861203
return true;
11871204
}
11881205

@@ -1206,6 +1223,22 @@ static bool IsNumeric(object value)
12061223
return false;
12071224
}
12081225

1226+
internal static object ReplaceUnsupportedNumericValues(object value)
1227+
{
1228+
switch (value)
1229+
{
1230+
case float.NaN:
1231+
case float.NegativeInfinity:
1232+
case float.PositiveInfinity:
1233+
case double.NaN:
1234+
case double.NegativeInfinity:
1235+
case double.PositiveInfinity:
1236+
return JSON_EMPTY_STRING;
1237+
default:
1238+
return value;
1239+
}
1240+
}
1241+
12091242
private static int indentationLevel;
12101243
private static string indentationText;
12111244
private static readonly int spacesPerIndent = 3;

tests/BenchmarkDotNet.Tests/Exporters/ApprovedFiles/CommonExporterApprovalTests.Exporters.Invariant.approved.txt

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -112,16 +112,16 @@ JsonExporter-brief
112112
"StandardError":0,
113113
"Variance":0,
114114
"StandardDeviation":0,
115-
"Skewness":NaN,
116-
"Kurtosis":NaN,
115+
"Skewness":"",
116+
"Kurtosis":"",
117117
"ConfidenceInterval":{
118118
"N":1,
119119
"Mean":1,
120120
"StandardError":0,
121121
"Level":12,
122-
"Margin":NaN,
123-
"Lower":NaN,
124-
"Upper":NaN
122+
"Margin":"",
123+
"Lower":"",
124+
"Upper":""
125125
},
126126
"Percentiles":{
127127
"P0":1,
@@ -169,16 +169,16 @@ JsonExporter-brief
169169
"StandardError":0,
170170
"Variance":0,
171171
"StandardDeviation":0,
172-
"Skewness":NaN,
173-
"Kurtosis":NaN,
172+
"Skewness":"",
173+
"Kurtosis":"",
174174
"ConfidenceInterval":{
175175
"N":1,
176176
"Mean":1,
177177
"StandardError":0,
178178
"Level":12,
179-
"Margin":NaN,
180-
"Lower":NaN,
181-
"Upper":NaN
179+
"Margin":"",
180+
"Lower":"",
181+
"Upper":""
182182
},
183183
"Percentiles":{
184184
"P0":1,
@@ -198,7 +198,7 @@ JsonExporter-brief
198198
############################################
199199
JsonExporter-brief-compressed
200200
############################################
201-
{"Title":"MockSummary","HostEnvironmentInfo":{"BenchmarkDotNetCaption":"BenchmarkDotNet","BenchmarkDotNetVersion":"0.10.x-mock","OsVersion":"Microsoft Windows NT 10.0.x.mock","ProcessorName":"MockIntel Core i7-6700HQ CPU 2.60GHz","PhysicalProcessorCount":1,"PhysicalCoreCount":4,"LogicalCoreCount":8,"RuntimeVersion":"Clr 4.0.x.mock","Architecture":"64mock","HasAttachedDebugger":false,"HasRyuJit":true,"Configuration":"CONFIGURATION","DotNetCliVersion":null,"ChronometerFrequency":{"Hertz":2531248},"HardwareTimerKind":"Tsc"},"Benchmarks":[{"DisplayInfo":"MockBenchmarkClass.Foo: LongRun(IterationCount=100, LaunchCount=3, WarmupCount=15)","Namespace":"BenchmarkDotNet.Tests.Mocks","Type":"MockBenchmarkClass","Method":"Foo","MethodTitle":"Foo","Parameters":"","FullName":"BenchmarkDotNet.Tests.Mocks.MockFactory+MockBenchmarkClass.Foo","Statistics":{"OriginalValues":[1],"N":1,"Min":1,"LowerFence":1,"Q1":1,"Median":1,"Mean":1,"Q3":1,"UpperFence":1,"Max":1,"InterquartileRange":0,"LowerOutliers":[],"UpperOutliers":[],"AllOutliers":[],"StandardError":0,"Variance":0,"StandardDeviation":0,"Skewness":NaN,"Kurtosis":NaN,"ConfidenceInterval":{"N":1,"Mean":1,"StandardError":0,"Level":12,"Margin":NaN,"Lower":NaN,"Upper":NaN},"Percentiles":{"P0":1,"P25":1,"P50":1,"P67":1,"P80":1,"P85":1,"P90":1,"P95":1,"P100":1}}},{"DisplayInfo":"MockBenchmarkClass.Bar: LongRun(IterationCount=100, LaunchCount=3, WarmupCount=15)","Namespace":"BenchmarkDotNet.Tests.Mocks","Type":"MockBenchmarkClass","Method":"Bar","MethodTitle":"Bar","Parameters":"","FullName":"BenchmarkDotNet.Tests.Mocks.MockFactory+MockBenchmarkClass.Bar","Statistics":{"OriginalValues":[1],"N":1,"Min":1,"LowerFence":1,"Q1":1,"Median":1,"Mean":1,"Q3":1,"UpperFence":1,"Max":1,"InterquartileRange":0,"LowerOutliers":[],"UpperOutliers":[],"AllOutliers":[],"StandardError":0,"Variance":0,"StandardDeviation":0,"Skewness":NaN,"Kurtosis":NaN,"ConfidenceInterval":{"N":1,"Mean":1,"StandardError":0,"Level":12,"Margin":NaN,"Lower":NaN,"Upper":NaN},"Percentiles":{"P0":1,"P25":1,"P50":1,"P67":1,"P80":1,"P85":1,"P90":1,"P95":1,"P100":1}}}]}
201+
{"Title":"MockSummary","HostEnvironmentInfo":{"BenchmarkDotNetCaption":"BenchmarkDotNet","BenchmarkDotNetVersion":"0.10.x-mock","OsVersion":"Microsoft Windows NT 10.0.x.mock","ProcessorName":"MockIntel Core i7-6700HQ CPU 2.60GHz","PhysicalProcessorCount":1,"PhysicalCoreCount":4,"LogicalCoreCount":8,"RuntimeVersion":"Clr 4.0.x.mock","Architecture":"64mock","HasAttachedDebugger":false,"HasRyuJit":true,"Configuration":"CONFIGURATION","DotNetCliVersion":null,"ChronometerFrequency":{"Hertz":2531248},"HardwareTimerKind":"Tsc"},"Benchmarks":[{"DisplayInfo":"MockBenchmarkClass.Foo: LongRun(IterationCount=100, LaunchCount=3, WarmupCount=15)","Namespace":"BenchmarkDotNet.Tests.Mocks","Type":"MockBenchmarkClass","Method":"Foo","MethodTitle":"Foo","Parameters":"","FullName":"BenchmarkDotNet.Tests.Mocks.MockFactory+MockBenchmarkClass.Foo","Statistics":{"OriginalValues":[1],"N":1,"Min":1,"LowerFence":1,"Q1":1,"Median":1,"Mean":1,"Q3":1,"UpperFence":1,"Max":1,"InterquartileRange":0,"LowerOutliers":[],"UpperOutliers":[],"AllOutliers":[],"StandardError":0,"Variance":0,"StandardDeviation":0,"Skewness":"","Kurtosis":"","ConfidenceInterval":{"N":1,"Mean":1,"StandardError":0,"Level":12,"Margin":"","Lower":"","Upper":""},"Percentiles":{"P0":1,"P25":1,"P50":1,"P67":1,"P80":1,"P85":1,"P90":1,"P95":1,"P100":1}}},{"DisplayInfo":"MockBenchmarkClass.Bar: LongRun(IterationCount=100, LaunchCount=3, WarmupCount=15)","Namespace":"BenchmarkDotNet.Tests.Mocks","Type":"MockBenchmarkClass","Method":"Bar","MethodTitle":"Bar","Parameters":"","FullName":"BenchmarkDotNet.Tests.Mocks.MockFactory+MockBenchmarkClass.Bar","Statistics":{"OriginalValues":[1],"N":1,"Min":1,"LowerFence":1,"Q1":1,"Median":1,"Mean":1,"Q3":1,"UpperFence":1,"Max":1,"InterquartileRange":0,"LowerOutliers":[],"UpperOutliers":[],"AllOutliers":[],"StandardError":0,"Variance":0,"StandardDeviation":0,"Skewness":"","Kurtosis":"","ConfidenceInterval":{"N":1,"Mean":1,"StandardError":0,"Level":12,"Margin":"","Lower":"","Upper":""},"Percentiles":{"P0":1,"P25":1,"P50":1,"P67":1,"P80":1,"P85":1,"P90":1,"P95":1,"P100":1}}}]}
202202
############################################
203203
JsonExporter-full
204204
############################################
@@ -258,16 +258,16 @@ JsonExporter-full
258258
"StandardError":0,
259259
"Variance":0,
260260
"StandardDeviation":0,
261-
"Skewness":NaN,
262-
"Kurtosis":NaN,
261+
"Skewness":"",
262+
"Kurtosis":"",
263263
"ConfidenceInterval":{
264264
"N":1,
265265
"Mean":1,
266266
"StandardError":0,
267267
"Level":12,
268-
"Margin":NaN,
269-
"Lower":NaN,
270-
"Upper":NaN
268+
"Margin":"",
269+
"Lower":"",
270+
"Upper":""
271271
},
272272
"Percentiles":{
273273
"P0":1,
@@ -325,16 +325,16 @@ JsonExporter-full
325325
"StandardError":0,
326326
"Variance":0,
327327
"StandardDeviation":0,
328-
"Skewness":NaN,
329-
"Kurtosis":NaN,
328+
"Skewness":"",
329+
"Kurtosis":"",
330330
"ConfidenceInterval":{
331331
"N":1,
332332
"Mean":1,
333333
"StandardError":0,
334334
"Level":12,
335-
"Margin":NaN,
336-
"Lower":NaN,
337-
"Upper":NaN
335+
"Margin":"",
336+
"Lower":"",
337+
"Upper":""
338338
},
339339
"Percentiles":{
340340
"P0":1,
@@ -364,7 +364,7 @@ JsonExporter-full
364364
############################################
365365
JsonExporter-full-compressed
366366
############################################
367-
{"Title":"MockSummary","HostEnvironmentInfo":{"BenchmarkDotNetCaption":"BenchmarkDotNet","BenchmarkDotNetVersion":"0.10.x-mock","OsVersion":"Microsoft Windows NT 10.0.x.mock","ProcessorName":"MockIntel Core i7-6700HQ CPU 2.60GHz","PhysicalProcessorCount":1,"PhysicalCoreCount":4,"LogicalCoreCount":8,"RuntimeVersion":"Clr 4.0.x.mock","Architecture":"64mock","HasAttachedDebugger":false,"HasRyuJit":true,"Configuration":"CONFIGURATION","DotNetCliVersion":null,"ChronometerFrequency":{"Hertz":2531248},"HardwareTimerKind":"Tsc"},"Benchmarks":[{"DisplayInfo":"MockBenchmarkClass.Foo: LongRun(IterationCount=100, LaunchCount=3, WarmupCount=15)","Namespace":"BenchmarkDotNet.Tests.Mocks","Type":"MockBenchmarkClass","Method":"Foo","MethodTitle":"Foo","Parameters":"","FullName":"BenchmarkDotNet.Tests.Mocks.MockFactory+MockBenchmarkClass.Foo","Statistics":{"OriginalValues":[1],"N":1,"Min":1,"LowerFence":1,"Q1":1,"Median":1,"Mean":1,"Q3":1,"UpperFence":1,"Max":1,"InterquartileRange":0,"LowerOutliers":[],"UpperOutliers":[],"AllOutliers":[],"StandardError":0,"Variance":0,"StandardDeviation":0,"Skewness":NaN,"Kurtosis":NaN,"ConfidenceInterval":{"N":1,"Mean":1,"StandardError":0,"Level":12,"Margin":NaN,"Lower":NaN,"Upper":NaN},"Percentiles":{"P0":1,"P25":1,"P50":1,"P67":1,"P80":1,"P85":1,"P90":1,"P95":1,"P100":1}},"Measurements":[{"IterationMode":"Workload","IterationStage":"Result","LaunchIndex":1,"IterationIndex":1,"Operations":1,"Nanoseconds":1}]},{"DisplayInfo":"MockBenchmarkClass.Bar: LongRun(IterationCount=100, LaunchCount=3, WarmupCount=15)","Namespace":"BenchmarkDotNet.Tests.Mocks","Type":"MockBenchmarkClass","Method":"Bar","MethodTitle":"Bar","Parameters":"","FullName":"BenchmarkDotNet.Tests.Mocks.MockFactory+MockBenchmarkClass.Bar","Statistics":{"OriginalValues":[1],"N":1,"Min":1,"LowerFence":1,"Q1":1,"Median":1,"Mean":1,"Q3":1,"UpperFence":1,"Max":1,"InterquartileRange":0,"LowerOutliers":[],"UpperOutliers":[],"AllOutliers":[],"StandardError":0,"Variance":0,"StandardDeviation":0,"Skewness":NaN,"Kurtosis":NaN,"ConfidenceInterval":{"N":1,"Mean":1,"StandardError":0,"Level":12,"Margin":NaN,"Lower":NaN,"Upper":NaN},"Percentiles":{"P0":1,"P25":1,"P50":1,"P67":1,"P80":1,"P85":1,"P90":1,"P95":1,"P100":1}},"Measurements":[{"IterationMode":"Workload","IterationStage":"Result","LaunchIndex":1,"IterationIndex":1,"Operations":1,"Nanoseconds":1}]}]}
367+
{"Title":"MockSummary","HostEnvironmentInfo":{"BenchmarkDotNetCaption":"BenchmarkDotNet","BenchmarkDotNetVersion":"0.10.x-mock","OsVersion":"Microsoft Windows NT 10.0.x.mock","ProcessorName":"MockIntel Core i7-6700HQ CPU 2.60GHz","PhysicalProcessorCount":1,"PhysicalCoreCount":4,"LogicalCoreCount":8,"RuntimeVersion":"Clr 4.0.x.mock","Architecture":"64mock","HasAttachedDebugger":false,"HasRyuJit":true,"Configuration":"CONFIGURATION","DotNetCliVersion":null,"ChronometerFrequency":{"Hertz":2531248},"HardwareTimerKind":"Tsc"},"Benchmarks":[{"DisplayInfo":"MockBenchmarkClass.Foo: LongRun(IterationCount=100, LaunchCount=3, WarmupCount=15)","Namespace":"BenchmarkDotNet.Tests.Mocks","Type":"MockBenchmarkClass","Method":"Foo","MethodTitle":"Foo","Parameters":"","FullName":"BenchmarkDotNet.Tests.Mocks.MockFactory+MockBenchmarkClass.Foo","Statistics":{"OriginalValues":[1],"N":1,"Min":1,"LowerFence":1,"Q1":1,"Median":1,"Mean":1,"Q3":1,"UpperFence":1,"Max":1,"InterquartileRange":0,"LowerOutliers":[],"UpperOutliers":[],"AllOutliers":[],"StandardError":0,"Variance":0,"StandardDeviation":0,"Skewness":"","Kurtosis":"","ConfidenceInterval":{"N":1,"Mean":1,"StandardError":0,"Level":12,"Margin":"","Lower":"","Upper":""},"Percentiles":{"P0":1,"P25":1,"P50":1,"P67":1,"P80":1,"P85":1,"P90":1,"P95":1,"P100":1}},"Measurements":[{"IterationMode":"Workload","IterationStage":"Result","LaunchIndex":1,"IterationIndex":1,"Operations":1,"Nanoseconds":1}]},{"DisplayInfo":"MockBenchmarkClass.Bar: LongRun(IterationCount=100, LaunchCount=3, WarmupCount=15)","Namespace":"BenchmarkDotNet.Tests.Mocks","Type":"MockBenchmarkClass","Method":"Bar","MethodTitle":"Bar","Parameters":"","FullName":"BenchmarkDotNet.Tests.Mocks.MockFactory+MockBenchmarkClass.Bar","Statistics":{"OriginalValues":[1],"N":1,"Min":1,"LowerFence":1,"Q1":1,"Median":1,"Mean":1,"Q3":1,"UpperFence":1,"Max":1,"InterquartileRange":0,"LowerOutliers":[],"UpperOutliers":[],"AllOutliers":[],"StandardError":0,"Variance":0,"StandardDeviation":0,"Skewness":"","Kurtosis":"","ConfidenceInterval":{"N":1,"Mean":1,"StandardError":0,"Level":12,"Margin":"","Lower":"","Upper":""},"Percentiles":{"P0":1,"P25":1,"P50":1,"P67":1,"P80":1,"P85":1,"P90":1,"P95":1,"P100":1}},"Measurements":[{"IterationMode":"Workload","IterationStage":"Result","LaunchIndex":1,"IterationIndex":1,"Operations":1,"Nanoseconds":1}]}]}
368368
############################################
369369
MarkdownExporter-default
370370
############################################

0 commit comments

Comments
 (0)