4
4
5
5
namespace CodeGen . Generators . UnitsNetGen
6
6
{
7
+ /// <summary>
8
+ /// Generates base class for each quantity test class, with stubs for testing conversion functions and error tolerances that the developer must complete to fix compile errors.
9
+ /// </summary>
10
+ /// <example>
11
+ /// <list type="bullet">
12
+ /// <item><description>UnitsNet.Tests\GeneratedCode\AccelerationTestsBase.g.cs</description></item>
13
+ /// <item><description>UnitsNet.Tests\GeneratedCode\LengthTestsBase.g.cs</description></item>
14
+ /// </list>
15
+ /// </example>
7
16
internal class UnitTestBaseClassGenerator : GeneratorBase
8
17
{
18
+ /// <summary>
19
+ /// The quantity to generate test base class for.
20
+ /// </summary>
9
21
private readonly Quantity _quantity ;
22
+
23
+ /// <summary>
24
+ /// Base unit for this quantity, such as Meter for quantity Length.
25
+ /// </summary>
10
26
private readonly Unit _baseUnit ;
27
+
28
+ /// <summary>
29
+ /// Example: "LengthUnit"
30
+ /// </summary>
11
31
private readonly string _unitEnumName ;
12
32
33
+ /// <summary>
34
+ /// Example: "m" for Length quantity.
35
+ /// </summary>
36
+ private readonly string _baseUnitEnglishAbbreviation ;
37
+
38
+ /// <summary>
39
+ /// Example: "LengthUnit.Meter".
40
+ /// </summary>
41
+ private readonly string _baseUnitFullName ;
42
+
43
+ /// <summary>
44
+ /// Constructors for decimal-backed quantities require decimal numbers as input, so add the "m" suffix to numbers when constructing those quantities.
45
+ /// </summary>
46
+ private readonly string _numberSuffix ;
47
+
13
48
public UnitTestBaseClassGenerator ( Quantity quantity )
14
49
{
15
50
_quantity = quantity ;
16
51
_baseUnit = quantity . Units . FirstOrDefault ( u => u . SingularName == _quantity . BaseUnit ) ??
17
52
throw new ArgumentException ( $ "No unit found with SingularName equal to BaseUnit [{ _quantity . BaseUnit } ]. This unit must be defined.",
18
53
nameof ( quantity ) ) ;
19
54
_unitEnumName = $ "{ quantity . Name } Unit";
55
+ _baseUnitEnglishAbbreviation = GetEnglishAbbreviation ( _baseUnit ) ;
56
+ _baseUnitFullName = $ "{ _unitEnumName } .{ _baseUnit . SingularName } ";
57
+ _numberSuffix = quantity . BaseType == "decimal" ? "m" : "" ;
20
58
}
21
59
60
+ private string GetUnitFullName ( Unit unit ) => $ "{ _unitEnumName } .{ unit . SingularName } ";
61
+
62
+ /// <summary>
63
+ /// Gets the first en-US abbreviation for the unit -or- empty string if none is defined.
64
+ /// </summary>
65
+ private static string GetEnglishAbbreviation ( Unit unit ) => unit . Localization . First ( l => l . Culture == "en-US" ) . Abbreviations . FirstOrDefault ( ) ?? "" ;
66
+
22
67
public override string Generate ( )
23
68
{
24
69
var baseUnitVariableName = _baseUnit . SingularName . ToLowerInvariant ( ) ;
25
70
26
71
Writer . WL ( GeneratedFileHeader ) ;
27
72
Writer . WL ( $@ "
28
73
using System;
74
+ using System.Globalization;
29
75
using System.Linq;
76
+ using System.Threading;
30
77
using UnitsNet.Units;
31
78
using Xunit;
32
79
@@ -57,22 +104,58 @@ public void Ctor_WithUndefinedUnit_ThrowsArgumentException()
57
104
{{
58
105
Assert.Throws<ArgumentException>(() => new { _quantity . Name } (({ _quantity . BaseType } )0.0, { _unitEnumName } .Undefined));
59
106
}}
107
+
108
+ [Fact]
109
+ public void DefaultCtor_ReturnsQuantityWithZeroValueAndBaseUnit()
110
+ {{
111
+ var quantity = new { _quantity . Name } ();
112
+ Assert.Equal(0, quantity.Value);
113
+ Assert.Equal({ _baseUnitFullName } , quantity.Unit);
114
+ }}
115
+
60
116
" ) ;
61
117
if ( _quantity . BaseType == "double" ) Writer . WL ( $@ "
62
118
[Fact]
63
119
public void Ctor_WithInfinityValue_ThrowsArgumentException()
64
120
{{
65
- Assert.Throws<ArgumentException>(() => new { _quantity . Name } (double.PositiveInfinity, { _unitEnumName } . { _baseUnit . SingularName } ));
66
- Assert.Throws<ArgumentException>(() => new { _quantity . Name } (double.NegativeInfinity, { _unitEnumName } . { _baseUnit . SingularName } ));
121
+ Assert.Throws<ArgumentException>(() => new { _quantity . Name } (double.PositiveInfinity, { _baseUnitFullName } ));
122
+ Assert.Throws<ArgumentException>(() => new { _quantity . Name } (double.NegativeInfinity, { _baseUnitFullName } ));
67
123
}}
68
124
69
125
[Fact]
70
126
public void Ctor_WithNaNValue_ThrowsArgumentException()
71
127
{{
72
- Assert.Throws<ArgumentException>(() => new { _quantity . Name } (double.NaN, { _unitEnumName } .{ _baseUnit . SingularName } ));
128
+ Assert.Throws<ArgumentException>(() => new { _quantity . Name } (double.NaN, { _baseUnitFullName } ));
129
+ }}
130
+
131
+ [Fact]
132
+ public void Ctor_NullAsUnitSystem_ThrowsArgumentNullException()
133
+ {{
134
+ Assert.Throws<ArgumentNullException>(() => new { _quantity . Name } (value: 1.0, unitSystem: null));
73
135
}}
74
136
" ) ; Writer . WL ( $@ "
75
137
138
+ [Fact]
139
+ public void { _quantity . Name } _QuantityInfo_ReturnsQuantityInfoDescribingQuantity()
140
+ {{
141
+ var quantity = new { _quantity . Name } (1, { _baseUnitFullName } );
142
+
143
+ QuantityInfo<{ _unitEnumName } > quantityInfo = quantity.QuantityInfo;
144
+
145
+ Assert.Equal({ _quantity . Name } .Zero, quantityInfo.Zero);
146
+ Assert.Equal(""{ _quantity . Name } "", quantityInfo.Name);
147
+ Assert.Equal(QuantityType.{ _quantity . Name } , quantityInfo.QuantityType);
148
+
149
+ var units = EnumUtils.GetEnumValues<{ _unitEnumName } >().Except(new[] {{{_unitEnumName}.Undefined}}).ToArray();
150
+ var unitNames = units.Select(x => x.ToString());
151
+
152
+ // Obsolete members
153
+ #pragma warning disable 618
154
+ Assert.Equal(units, quantityInfo.Units);
155
+ Assert.Equal(unitNames, quantityInfo.UnitNames);
156
+ #pragma warning restore 618
157
+ }}
158
+
76
159
[Fact]
77
160
public void { _baseUnit . SingularName } To{ _quantity . Name } Units()
78
161
{{
@@ -84,10 +167,19 @@ public void Ctor_WithNaNValue_ThrowsArgumentException()
84
167
}}
85
168
86
169
[Fact]
87
- public void FromValueAndUnit ()
170
+ public void From_ValueAndUnit_ReturnsQuantityWithSameValueAndUnit ()
88
171
{{" ) ;
89
- foreach ( var unit in _quantity . Units ) Writer . WL ( $@ "
90
- AssertEx.EqualTolerance(1, { _quantity . Name } .From(1, { _unitEnumName } .{ unit . SingularName } ).{ unit . PluralName } , { unit . PluralName } Tolerance);" ) ;
172
+ int i = 0 ;
173
+ foreach ( var unit in _quantity . Units )
174
+ {
175
+ var quantityVariable = $ "quantity{ i ++ : D2} ";
176
+ Writer . WL ( $@ "
177
+ var { quantityVariable } = { _quantity . Name } .From(1, { GetUnitFullName ( unit ) } );
178
+ AssertEx.EqualTolerance(1, { quantityVariable } .{ unit . PluralName } , { unit . PluralName } Tolerance);
179
+ Assert.Equal({ GetUnitFullName ( unit ) } , { quantityVariable } .Unit);
180
+ " ) ;
181
+
182
+ }
91
183
Writer . WL ( $@ "
92
184
}}
93
185
" ) ;
@@ -111,7 +203,7 @@ public void As()
111
203
{{
112
204
var { baseUnitVariableName } = { _quantity . Name } .From{ _baseUnit . PluralName } (1);" ) ;
113
205
foreach ( var unit in _quantity . Units ) Writer . WL ( $@ "
114
- AssertEx.EqualTolerance({ unit . PluralName } InOne{ _baseUnit . SingularName } , { baseUnitVariableName } .As({ _unitEnumName } . { unit . SingularName } ), { unit . PluralName } Tolerance);" ) ;
206
+ AssertEx.EqualTolerance({ unit . PluralName } InOne{ _baseUnit . SingularName } , { baseUnitVariableName } .As({ GetUnitFullName ( unit ) } ), { unit . PluralName } Tolerance);" ) ;
115
207
Writer . WL ( $@ "
116
208
}}
117
209
@@ -125,9 +217,9 @@ public void ToUnit()
125
217
126
218
Writer . WL ( "" ) ;
127
219
Writer . WL ( $@ "
128
- var { asQuantityVariableName } = { baseUnitVariableName } .ToUnit({ _unitEnumName } . { unit . SingularName } );
220
+ var { asQuantityVariableName } = { baseUnitVariableName } .ToUnit({ GetUnitFullName ( unit ) } );
129
221
AssertEx.EqualTolerance({ unit . PluralName } InOne{ _baseUnit . SingularName } , (double){ asQuantityVariableName } .Value, { unit . PluralName } Tolerance);
130
- Assert.Equal({ _unitEnumName } . { unit . SingularName } , { asQuantityVariableName } .Unit);" ) ;
222
+ Assert.Equal({ GetUnitFullName ( unit ) } , { asQuantityVariableName } .Unit);" ) ;
131
223
}
132
224
Writer . WL ( $@ "
133
225
}}
@@ -303,6 +395,67 @@ public void BaseDimensionsShouldNeverBeNull()
303
395
{{
304
396
Assert.False({ _quantity . Name } .BaseDimensions is null);
305
397
}}
398
+
399
+ [Fact]
400
+ public void ToString_ReturnsValueAndUnitAbbreviationInCurrentCulture()
401
+ {{
402
+ var prevCulture = Thread.CurrentThread.CurrentUICulture;
403
+ Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(""en-US"");
404
+ try {{" ) ;
405
+ foreach ( var unit in _quantity . Units )
406
+ {
407
+ Writer . WL ( $@ "
408
+ Assert.Equal(""1 { GetEnglishAbbreviation ( unit ) } "", new { _quantity . Name } (1, { GetUnitFullName ( unit ) } ).ToString());" ) ;
409
+ }
410
+ Writer . WL ( $@ "
411
+ }}
412
+ finally
413
+ {{
414
+ Thread.CurrentThread.CurrentUICulture = prevCulture;
415
+ }}
416
+ }}
417
+
418
+ [Fact]
419
+ public void ToString_WithSwedishCulture_ReturnsUnitAbbreviationForEnglishCultureSinceThereAreNoMappings()
420
+ {{
421
+ // Chose this culture, because we don't currently have any abbreviations mapped for that culture and we expect the en-US to be used as fallback.
422
+ var swedishCulture = CultureInfo.GetCultureInfo(""sv-SE"");
423
+ " ) ;
424
+ foreach ( var unit in _quantity . Units )
425
+ {
426
+ Writer . WL ( $@ "
427
+ Assert.Equal(""1 { GetEnglishAbbreviation ( unit ) } "", new { _quantity . Name } (1, { GetUnitFullName ( unit ) } ).ToString(swedishCulture));" ) ;
428
+ }
429
+ Writer . WL ( $@ "
430
+ }}
431
+
432
+ [Fact]
433
+ public void ToString_SFormat_FormatsNumberWithGivenDigitsAfterRadixForCurrentCulture()
434
+ {{
435
+ var oldCulture = CultureInfo.CurrentUICulture;
436
+ try
437
+ {{
438
+ CultureInfo.CurrentUICulture = CultureInfo.InvariantCulture;
439
+ Assert.Equal(""0.1 { _baseUnitEnglishAbbreviation } "", new { _quantity . Name } (0.123456{ _numberSuffix } , { _baseUnitFullName } ).ToString(""s1""));
440
+ Assert.Equal(""0.12 { _baseUnitEnglishAbbreviation } "", new { _quantity . Name } (0.123456{ _numberSuffix } , { _baseUnitFullName } ).ToString(""s2""));
441
+ Assert.Equal(""0.123 { _baseUnitEnglishAbbreviation } "", new { _quantity . Name } (0.123456{ _numberSuffix } , { _baseUnitFullName } ).ToString(""s3""));
442
+ Assert.Equal(""0.1235 { _baseUnitEnglishAbbreviation } "", new { _quantity . Name } (0.123456{ _numberSuffix } , { _baseUnitFullName } ).ToString(""s4""));
443
+ }}
444
+ finally
445
+ {{
446
+ CultureInfo.CurrentUICulture = oldCulture;
447
+ }}
448
+ }}
449
+
450
+ [Fact]
451
+ public void ToString_SFormatAndCulture_FormatsNumberWithGivenDigitsAfterRadixForGivenCulture()
452
+ {{
453
+ var culture = CultureInfo.InvariantCulture;
454
+ Assert.Equal(""0.1 { _baseUnitEnglishAbbreviation } "", new { _quantity . Name } (0.123456{ _numberSuffix } , { _baseUnitFullName } ).ToString(""s1"", culture));
455
+ Assert.Equal(""0.12 { _baseUnitEnglishAbbreviation } "", new { _quantity . Name } (0.123456{ _numberSuffix } , { _baseUnitFullName } ).ToString(""s2"", culture));
456
+ Assert.Equal(""0.123 { _baseUnitEnglishAbbreviation } "", new { _quantity . Name } (0.123456{ _numberSuffix } , { _baseUnitFullName } ).ToString(""s3"", culture));
457
+ Assert.Equal(""0.1235 { _baseUnitEnglishAbbreviation } "", new { _quantity . Name } (0.123456{ _numberSuffix } , { _baseUnitFullName } ).ToString(""s4"", culture));
458
+ }}
306
459
}}
307
460
}}" ) ;
308
461
return Writer . ToString ( ) ;
0 commit comments