Skip to content

Commit 00fa751

Browse files
Copilotthomhurst
andauthored
Fix floating point arguments being parsed as multiple parameters due to culture-specific formatting (#2962)
* Initial plan * Initial investigation: understand the issue with floating point arguments Co-authored-by: thomhurst <[email protected]> * Deep investigation into floating point argument parsing issue Co-authored-by: thomhurst <[email protected]> * Fix floating point argument parsing issue by using InvariantCulture for numeric formatting Co-authored-by: thomhurst <[email protected]> * Fix floating point arguments being parsed as multiple parameters due to culture-specific formatting Co-authored-by: thomhurst <[email protected]> * Add numeric suffixes to floating point literals in emitted code Co-authored-by: thomhurst <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: thomhurst <[email protected]>
1 parent d2dc7f0 commit 00fa751

File tree

10 files changed

+77
-25
lines changed

10 files changed

+77
-25
lines changed

TUnit.Core.SourceGenerator.Tests/ConstantArgumentsTests.Test.verified.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// <auto-generated/>
1+
// <auto-generated/>
22
#pragma warning disable
33

44
// <auto-generated/>
@@ -265,7 +265,7 @@ internal sealed class ConstantArgumentsTests_Double_TestSource_GUID : global::TU
265265
],
266266
DataSources = new global::TUnit.Core.IDataSourceAttribute[]
267267
{
268-
new global::TUnit.Core.ArgumentsAttribute(1.23),
268+
new global::TUnit.Core.ArgumentsAttribute(1.23d),
269269
},
270270
ClassDataSources = new global::TUnit.Core.IDataSourceAttribute[]
271271
{
@@ -386,7 +386,7 @@ internal sealed class ConstantArgumentsTests_Float_TestSource_GUID : global::TUn
386386
],
387387
DataSources = new global::TUnit.Core.IDataSourceAttribute[]
388388
{
389-
new global::TUnit.Core.ArgumentsAttribute(1.23),
389+
new global::TUnit.Core.ArgumentsAttribute(1.23f),
390390
},
391391
ClassDataSources = new global::TUnit.Core.IDataSourceAttribute[]
392392
{
@@ -507,7 +507,7 @@ internal sealed class ConstantArgumentsTests_Long_TestSource_GUID : global::TUni
507507
],
508508
DataSources = new global::TUnit.Core.IDataSourceAttribute[]
509509
{
510-
new global::TUnit.Core.ArgumentsAttribute(123),
510+
new global::TUnit.Core.ArgumentsAttribute(123L),
511511
},
512512
ClassDataSources = new global::TUnit.Core.IDataSourceAttribute[]
513513
{
@@ -628,7 +628,7 @@ internal sealed class ConstantArgumentsTests_UInt_TestSource_GUID : global::TUni
628628
],
629629
DataSources = new global::TUnit.Core.IDataSourceAttribute[]
630630
{
631-
new global::TUnit.Core.ArgumentsAttribute(123),
631+
new global::TUnit.Core.ArgumentsAttribute(123U),
632632
},
633633
ClassDataSources = new global::TUnit.Core.IDataSourceAttribute[]
634634
{
@@ -749,7 +749,7 @@ internal sealed class ConstantArgumentsTests_ULong_TestSource_GUID : global::TUn
749749
],
750750
DataSources = new global::TUnit.Core.IDataSourceAttribute[]
751751
{
752-
new global::TUnit.Core.ArgumentsAttribute(123),
752+
new global::TUnit.Core.ArgumentsAttribute(123UL),
753753
},
754754
ClassDataSources = new global::TUnit.Core.IDataSourceAttribute[]
755755
{

TUnit.Core.SourceGenerator.Tests/NumberArgumentTests.Test.verified.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// <auto-generated/>
1+
// <auto-generated/>
22
#pragma warning disable
33

44
// <auto-generated/>
@@ -146,7 +146,7 @@ internal sealed class NumberArgumentTests_Double_TestSource_GUID : global::TUnit
146146
],
147147
DataSources = new global::TUnit.Core.IDataSourceAttribute[]
148148
{
149-
new global::TUnit.Core.ArgumentsAttribute(1.1),
149+
new global::TUnit.Core.ArgumentsAttribute(1.1d),
150150
},
151151
ClassDataSources = new global::TUnit.Core.IDataSourceAttribute[]
152152
{
@@ -269,7 +269,7 @@ internal sealed class NumberArgumentTests_Float_TestSource_GUID : global::TUnit.
269269
],
270270
DataSources = new global::TUnit.Core.IDataSourceAttribute[]
271271
{
272-
new global::TUnit.Core.ArgumentsAttribute(1.1),
272+
new global::TUnit.Core.ArgumentsAttribute(1.1f),
273273
},
274274
ClassDataSources = new global::TUnit.Core.IDataSourceAttribute[]
275275
{
@@ -392,7 +392,7 @@ internal sealed class NumberArgumentTests_Long_TestSource_GUID : global::TUnit.C
392392
],
393393
DataSources = new global::TUnit.Core.IDataSourceAttribute[]
394394
{
395-
new global::TUnit.Core.ArgumentsAttribute(1),
395+
new global::TUnit.Core.ArgumentsAttribute(1L),
396396
},
397397
ClassDataSources = new global::TUnit.Core.IDataSourceAttribute[]
398398
{
@@ -515,7 +515,7 @@ internal sealed class NumberArgumentTests_ULong_TestSource_GUID : global::TUnit.
515515
],
516516
DataSources = new global::TUnit.Core.IDataSourceAttribute[]
517517
{
518-
new global::TUnit.Core.ArgumentsAttribute(1),
518+
new global::TUnit.Core.ArgumentsAttribute(1UL),
519519
},
520520
ClassDataSources = new global::TUnit.Core.IDataSourceAttribute[]
521521
{
@@ -638,7 +638,7 @@ internal sealed class NumberArgumentTests_UInt_TestSource_GUID : global::TUnit.C
638638
],
639639
DataSources = new global::TUnit.Core.IDataSourceAttribute[]
640640
{
641-
new global::TUnit.Core.ArgumentsAttribute(1),
641+
new global::TUnit.Core.ArgumentsAttribute(1U),
642642
},
643643
ClassDataSources = new global::TUnit.Core.IDataSourceAttribute[]
644644
{

TUnit.Core.SourceGenerator.Tests/NumberArgumentTests.TestDE.verified.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// <auto-generated/>
1+
// <auto-generated/>
22
#pragma warning disable
33

44
// <auto-generated/>
@@ -146,7 +146,7 @@ internal sealed class NumberArgumentTests_Double_TestSource_GUID : global::TUnit
146146
],
147147
DataSources = new global::TUnit.Core.IDataSourceAttribute[]
148148
{
149-
new global::TUnit.Core.ArgumentsAttribute(1,1),
149+
new global::TUnit.Core.ArgumentsAttribute(1.1d),
150150
},
151151
ClassDataSources = new global::TUnit.Core.IDataSourceAttribute[]
152152
{
@@ -269,7 +269,7 @@ internal sealed class NumberArgumentTests_Float_TestSource_GUID : global::TUnit.
269269
],
270270
DataSources = new global::TUnit.Core.IDataSourceAttribute[]
271271
{
272-
new global::TUnit.Core.ArgumentsAttribute(1,1),
272+
new global::TUnit.Core.ArgumentsAttribute(1.1f),
273273
},
274274
ClassDataSources = new global::TUnit.Core.IDataSourceAttribute[]
275275
{
@@ -392,7 +392,7 @@ internal sealed class NumberArgumentTests_Long_TestSource_GUID : global::TUnit.C
392392
],
393393
DataSources = new global::TUnit.Core.IDataSourceAttribute[]
394394
{
395-
new global::TUnit.Core.ArgumentsAttribute(1),
395+
new global::TUnit.Core.ArgumentsAttribute(1L),
396396
},
397397
ClassDataSources = new global::TUnit.Core.IDataSourceAttribute[]
398398
{
@@ -515,7 +515,7 @@ internal sealed class NumberArgumentTests_ULong_TestSource_GUID : global::TUnit.
515515
],
516516
DataSources = new global::TUnit.Core.IDataSourceAttribute[]
517517
{
518-
new global::TUnit.Core.ArgumentsAttribute(1),
518+
new global::TUnit.Core.ArgumentsAttribute(1UL),
519519
},
520520
ClassDataSources = new global::TUnit.Core.IDataSourceAttribute[]
521521
{
@@ -638,7 +638,7 @@ internal sealed class NumberArgumentTests_UInt_TestSource_GUID : global::TUnit.C
638638
],
639639
DataSources = new global::TUnit.Core.IDataSourceAttribute[]
640640
{
641-
new global::TUnit.Core.ArgumentsAttribute(1),
641+
new global::TUnit.Core.ArgumentsAttribute(1U),
642642
},
643643
ClassDataSources = new global::TUnit.Core.IDataSourceAttribute[]
644644
{

TUnit.Core.SourceGenerator.Tests/Tests2083.Test.verified.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// <auto-generated/>
1+
// <auto-generated/>
22
#pragma warning disable
33

44
// <auto-generated/>
@@ -33,7 +33,7 @@ internal sealed class Tests_MyTest_TestSource_GUID : global::TUnit.Core.Interfac
3333
new global::TUnit.Core.ArgumentsAttribute(32767),
3434
new global::TUnit.Core.ArgumentsAttribute('\uffff'),
3535
new global::TUnit.Core.ArgumentsAttribute(2147483647),
36-
new global::TUnit.Core.ArgumentsAttribute(9223372036854775807),
36+
new global::TUnit.Core.ArgumentsAttribute(9223372036854775807L),
3737
},
3838
ClassDataSources = new global::TUnit.Core.IDataSourceAttribute[]
3939
{

TUnit.Core.SourceGenerator.Tests/Tests2112.Test.verified.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// <auto-generated/>
1+
// <auto-generated/>
22
#pragma warning disable
33

44
// <auto-generated/>
@@ -24,7 +24,7 @@ internal sealed class Tests_Test_TestSource_GUID : global::TUnit.Core.Interfaces
2424
],
2525
DataSources = new global::TUnit.Core.IDataSourceAttribute[]
2626
{
27-
new global::TUnit.Core.ArgumentsAttribute(0, 1),
27+
new global::TUnit.Core.ArgumentsAttribute(0, 1L),
2828
new global::TUnit.Core.ArgumentsAttribute(0, 1),
2929
},
3030
ClassDataSources = new global::TUnit.Core.IDataSourceAttribute[]
@@ -192,7 +192,7 @@ internal sealed class Tests_Test2_TestSource_GUID : global::TUnit.Core.Interface
192192
],
193193
DataSources = new global::TUnit.Core.IDataSourceAttribute[]
194194
{
195-
new global::TUnit.Core.ArgumentsAttribute(0, 1, 2, 3),
195+
new global::TUnit.Core.ArgumentsAttribute(0, 1L, 2L, 3L),
196196
new global::TUnit.Core.ArgumentsAttribute(0, 1, 2, 3),
197197
},
198198
ClassDataSources = new global::TUnit.Core.IDataSourceAttribute[]

TUnit.Core.SourceGenerator.Tests/Tests2136.Test.verified.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// <auto-generated/>
1+
// <auto-generated/>
22
#pragma warning disable
33

44
// <auto-generated/>
@@ -313,7 +313,7 @@ internal sealed class Tests_GenericArgumentsTest_TestSource_GUID : global::TUnit
313313
],
314314
DataSources = new global::TUnit.Core.IDataSourceAttribute[]
315315
{
316-
new global::TUnit.Core.ArgumentsAttribute(1.1, "1.1"),
316+
new global::TUnit.Core.ArgumentsAttribute(1.1d, "1.1"),
317317
},
318318
ClassDataSources = new global::TUnit.Core.IDataSourceAttribute[]
319319
{

TUnit.Core.SourceGenerator/CodeGenerators/Formatting/TypedConstantFormatter.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,25 @@ private static string FormatPrimitive(object? value)
237237
return "double.NegativeInfinity";
238238
case null:
239239
return "null";
240+
// Use InvariantCulture for numeric types to ensure consistent formatting
241+
case double d:
242+
return d.ToString(System.Globalization.CultureInfo.InvariantCulture) + "d";
243+
case float f:
244+
return f.ToString(System.Globalization.CultureInfo.InvariantCulture) + "f";
245+
case decimal dec:
246+
return dec.ToString(System.Globalization.CultureInfo.InvariantCulture) + "m";
247+
case long l:
248+
return l.ToString(System.Globalization.CultureInfo.InvariantCulture) + "L";
249+
case ulong ul:
250+
return ul.ToString(System.Globalization.CultureInfo.InvariantCulture) + "UL";
251+
case uint ui:
252+
return ui.ToString(System.Globalization.CultureInfo.InvariantCulture) + "U";
240253
default:
254+
// For other numeric types, use InvariantCulture
255+
if (value is IFormattable formattable)
256+
{
257+
return formattable.ToString(null, System.Globalization.CultureInfo.InvariantCulture);
258+
}
241259
return value.ToString() ?? "null";
242260
}
243261
}

TUnit.Core.SourceGenerator/CodeGenerators/Helpers/TypedConstantParser.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,19 @@ public static string FormatPrimitive(object? value)
101101
return "double.NegativeInfinity";
102102
case null:
103103
return "null";
104+
// Use InvariantCulture for numeric types to ensure consistent formatting
105+
case double d:
106+
return d.ToString(System.Globalization.CultureInfo.InvariantCulture) + "d";
107+
case float f:
108+
return f.ToString(System.Globalization.CultureInfo.InvariantCulture) + "f";
109+
case decimal dec:
110+
return dec.ToString(System.Globalization.CultureInfo.InvariantCulture) + "m";
104111
default:
112+
// For other numeric types, use InvariantCulture
113+
if (value is IFormattable formattable)
114+
{
115+
return formattable.ToString(null, System.Globalization.CultureInfo.InvariantCulture);
116+
}
105117
return value.ToString() ?? "null";
106118
}
107119
}

TUnit.Core/Services/TestNameFormatter.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ public string FormatArgumentValue(object? value)
5151
string str => $"\"{str}\"",
5252
char ch => $"'{ch}'",
5353
bool b => b.ToString().ToLowerInvariant(),
54+
// Use InvariantCulture for numeric types to avoid culture-specific formatting issues
55+
double d => d.ToString(System.Globalization.CultureInfo.InvariantCulture),
56+
float f => f.ToString(System.Globalization.CultureInfo.InvariantCulture),
57+
decimal dec => dec.ToString(System.Globalization.CultureInfo.InvariantCulture),
5458
IEnumerable enumerable when value.GetType() != typeof(string) => FormatEnumerable(enumerable),
5559
_ => value.ToString() ?? "null"
5660
};
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using TUnit.Core;
2+
using TUnit.TestProject.Attributes;
3+
4+
namespace TUnit.TestProject;
5+
6+
[EngineTest(ExpectedResult.Pass)]
7+
public class FloatingPointDebugTests
8+
{
9+
[Test]
10+
[Arguments(4)]
11+
[Arguments(0.1)]
12+
[Arguments(1.1)]
13+
[Arguments(1e-1)]
14+
public void ParameterTest(double number)
15+
{
16+
// This should work without throwing "Expected exactly 1 argument, but got 2"
17+
}
18+
}

0 commit comments

Comments
 (0)