Skip to content

Commit f9a2766

Browse files
committed
- UnitAbbreviationsCache: removed the obsolete method and replaced the return types to IReadOnlyList
- UnitParser: refactored the common parts of the GetUnitFromAbbreviation code - completed the test coverage for the UnitParser and the UnitAbbreviationsCache
1 parent 8e53970 commit f9a2766

File tree

5 files changed

+299
-153
lines changed

5 files changed

+299
-153
lines changed

UnitsNet.Tests/UnitAbbreviationsCacheTests.cs

Lines changed: 120 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,40 @@ public class UnitAbbreviationsCacheTests
1717
{
1818
private static readonly CultureInfo AmericanCulture = CultureInfo.GetCultureInfo("en-US");
1919
private static readonly CultureInfo NorwegianCulture = CultureInfo.GetCultureInfo("nb-NO");
20+
21+
[Fact]
22+
public void EmptyConstructor_ReturnsAnAbbreviationCacheWithDefaultQuantityInfoLookup()
23+
{
24+
var unitAbbreviationCache = new UnitAbbreviationsCache();
25+
26+
Assert.Equal(UnitsNetSetup.Default.QuantityInfoLookup, unitAbbreviationCache.Quantities);
27+
Assert.Equal("g", unitAbbreviationCache.GetUnitAbbreviations(MassUnit.Gram, AmericanCulture)[0]);
28+
Assert.Throws<UnitNotFoundException>(() => unitAbbreviationCache.GetUnitAbbreviations(HowMuchUnit.Some));
29+
}
2030

2131
[Fact]
22-
public void UnitAbbreviationsCacheDefaultReturnsUnitsNetSetupDefaultUnitAbbreviations()
32+
public void Constructor_WithQuantities_ReturnsAnAbbreviationCacheWithNewQuantityInfoLookup()
33+
{
34+
var unitAbbreviationCache = new UnitAbbreviationsCache([Mass.Info, HowMuch.Info]);
35+
36+
Assert.NotEqual(UnitsNetSetup.Default.QuantityInfoLookup, unitAbbreviationCache.Quantities);
37+
Assert.Equal("g", unitAbbreviationCache.GetUnitAbbreviations(MassUnit.Gram, AmericanCulture)[0]);
38+
Assert.Empty(unitAbbreviationCache.GetUnitAbbreviations(HowMuchUnit.Some, AmericanCulture));
39+
Assert.Throws<UnitNotFoundException>(() => unitAbbreviationCache.GetUnitAbbreviations(LengthUnit.Meter));
40+
}
41+
42+
[Fact]
43+
public void CreateDefault_ReturnsAnAbbreviationCacheWithDefaultQuantityInfoLookup()
44+
{
45+
var unitAbbreviationCache = UnitAbbreviationsCache.CreateDefault();
46+
47+
Assert.Equal(UnitsNetSetup.Default.QuantityInfoLookup, unitAbbreviationCache.Quantities);
48+
Assert.Equal("g", unitAbbreviationCache.GetUnitAbbreviations(MassUnit.Gram, AmericanCulture)[0]);
49+
Assert.Throws<UnitNotFoundException>(() => unitAbbreviationCache.GetUnitAbbreviations(HowMuchUnit.Some));
50+
}
51+
52+
[Fact]
53+
public void UnitAbbreviationsCache_Default_ReturnsInstanceFromUnitsNetSetup()
2354
{
2455
Assert.Equal(UnitsNetSetup.Default.UnitAbbreviations, UnitAbbreviationsCache.Default);
2556
}
@@ -34,7 +65,7 @@ public void GetUnitAbbreviationsThrowsUnitNotFoundExceptionIfNoneExist()
3465
}
3566

3667
[Fact]
37-
public void GetUnitAbbreviationsReturnsTheExpectedAbbreviationWhenConstructedWithTheSpecificQuantityInfo()
68+
public void GetUnitAbbreviationReturnsTheExpectedAbbreviationWhenConstructedWithTheSpecificQuantityInfo()
3869
{
3970
Assert.Multiple(checks:
4071
[
@@ -43,6 +74,13 @@ public void GetUnitAbbreviationsReturnsTheExpectedAbbreviationWhenConstructedWit
4374
]);
4475
}
4576

77+
[Fact]
78+
public void GetUnitAbbreviationsReturnsTheExpectedAbbreviationWhenConstructedWithTheSpecificQuantityInfo()
79+
{
80+
var unitAbbreviationCache = new UnitAbbreviationsCache([Mass.Info]);
81+
Assert.Equal("g", unitAbbreviationCache.GetUnitAbbreviations(MassUnit.Gram, AmericanCulture)[0]);
82+
}
83+
4684
[Fact]
4785
public void GetDefaultAbbreviationReturnsTheExpectedAbbreviationWhenConstructedWithTheSpecificQuantityInfo()
4886
{
@@ -71,6 +109,24 @@ public void GetDefaultAbbreviationFallsBackToUsEnglishCulture()
71109
Assert.Equal("US english abbreviation for Unit1", abbreviation);
72110
}
73111

112+
[Fact]
113+
public void GetDefaultAbbreviationFallsBackToInvariantCulture()
114+
{
115+
// CurrentCulture affects number formatting, such as comma or dot as decimal separator.
116+
// CurrentCulture also affects localization of unit abbreviations.
117+
// Zulu (South Africa)
118+
var zuluCulture = CultureInfo.GetCultureInfo("zu-ZA");
119+
120+
var abbreviationsCache = new UnitAbbreviationsCache([HowMuch.Info]);
121+
abbreviationsCache.MapUnitToAbbreviation(HowMuchUnit.AShitTon, CultureInfo.InvariantCulture, "Invariant abbreviation for Unit1");
122+
123+
// Act
124+
string abbreviation = abbreviationsCache.GetDefaultAbbreviation(HowMuchUnit.AShitTon, zuluCulture);
125+
126+
// Assert
127+
Assert.Equal("Invariant abbreviation for Unit1", abbreviation);
128+
}
129+
74130
[Fact]
75131
public void GetDefaultAbbreviationThrowsUnitNotFoundExceptionIfNoneExist()
76132
{
@@ -87,9 +143,22 @@ public void GetDefaultAbbreviation_ForUnitWithoutAbbreviations_ThrowsInvalidOper
87143
}
88144

89145
[Fact]
90-
public void GetAbbreviationsThrowsArgumentNullExceptionWhenGivenANullUnitInfo()
146+
public void GetAllUnitAbbreviationsForQuantity_WithQuantityWithoutAbbreviations_ReturnsEmpty()
147+
{
148+
var unitAbbreviationsCache = new UnitAbbreviationsCache([HowMuch.Info]);
149+
Assert.Empty(unitAbbreviationsCache.GetAllUnitAbbreviationsForQuantity(typeof(HowMuchUnit)));
150+
}
151+
152+
[Fact]
153+
public void GetAllUnitAbbreviationsForQuantity_WithInvalidUnitType_ThrowsArgumentException()
154+
{
155+
Assert.Throws<ArgumentException>(() => UnitAbbreviationsCache.Default.GetAllUnitAbbreviationsForQuantity(typeof(DateTime)));
156+
}
157+
158+
[Fact]
159+
public void GetAllUnitAbbreviationsForQuantity_WithUnknownUnitType_ThrowsUnitNotFoundException()
91160
{
92-
Assert.Throws<ArgumentNullException>(() => new UnitAbbreviationsCache().GetAbbreviations(null!));
161+
Assert.Throws<UnitNotFoundException>(() => UnitAbbreviationsCache.Default.GetAllUnitAbbreviationsForQuantity(typeof(HowMuchUnit)));
93162
}
94163

95164
[Fact]
@@ -119,15 +188,6 @@ public void MapUnitToAbbreviation_AddCustomUnit_DoesNotOverrideDefaultAbbreviati
119188
Assert.Equal("m²", cache.GetDefaultAbbreviation(AreaUnit.SquareMeter, AmericanCulture));
120189
}
121190

122-
[Fact]
123-
public void MapUnitToDefaultAbbreviation_GivenUnitAndCulture_SetsDefaultAbbreviationForUnitAndCulture()
124-
{
125-
var cache = new UnitAbbreviationsCache();
126-
cache.MapUnitToDefaultAbbreviation(AreaUnit.SquareMeter, AmericanCulture, "m^2");
127-
128-
Assert.Equal("m^2", cache.GetDefaultAbbreviation(AreaUnit.SquareMeter, AmericanCulture));
129-
}
130-
131191
[Fact]
132192
public void MapUnitToDefaultAbbreviation_GivenUnitAndNoCulture_SetsDefaultAbbreviationForUnitForCurrentCulture()
133193
{
@@ -141,15 +201,21 @@ public void MapUnitToDefaultAbbreviation_GivenUnitAndNoCulture_SetsDefaultAbbrev
141201
}
142202

143203
[Fact]
144-
public void MapUnitToDefaultAbbreviation_GivenUnitTypeAndValue_SetsDefaultAbbreviationForUnitForCurrentCulture()
204+
public void MapUnitToDefaultAbbreviation_GivenUnitAndCulture_SetsDefaultAbbreviationForUnitAndCulture()
145205
{
146-
using var cultureScope = new CultureScope(NorwegianCulture);
147-
var cache = new UnitAbbreviationsCache([Mass.Info]);
206+
var cache = new UnitAbbreviationsCache([Area.Info]);
207+
cache.MapUnitToDefaultAbbreviation(AreaUnit.SquareMeter, AmericanCulture, "m^2");
148208

149-
cache.MapUnitToDefaultAbbreviation(typeof(MassUnit), (int)MassUnit.Gram, null, "zz");
209+
Assert.Equal("m^2", cache.GetDefaultAbbreviation(AreaUnit.SquareMeter, AmericanCulture));
210+
}
150211

151-
Assert.Equal("zz", cache.GetDefaultAbbreviation(MassUnit.Gram));
152-
Assert.Equal("g", cache.GetDefaultAbbreviation(MassUnit.Gram, AmericanCulture));
212+
[Fact]
213+
public void MapUnitToDefaultAbbreviation_GivenUnitTypeValueAndCulture_SetsDefaultAbbreviationForUnitAndCulture()
214+
{
215+
var cache = new UnitAbbreviationsCache([Area.Info]);
216+
cache.MapUnitToDefaultAbbreviation(typeof(AreaUnit), (int)AreaUnit.SquareMeter, AmericanCulture, "m^2");
217+
218+
Assert.Equal("m^2", cache.GetDefaultAbbreviation(AreaUnit.SquareMeter, AmericanCulture));
153219
}
154220

155221
[Fact]
@@ -214,5 +280,40 @@ public void MapAndLookup_WithSpecificEnumType()
214280
unitAbbreviationsCache.MapUnitToDefaultAbbreviation(HowMuchUnit.Some, "sm");
215281
Assert.Equal("sm", unitAbbreviationsCache.GetDefaultAbbreviation(HowMuchUnit.Some));
216282
}
283+
284+
/// <inheritdoc cref="MapAndLookup_WithSpecificEnumType"/>
285+
[Fact]
286+
public void MapAndLookup_WithEnumType()
287+
{
288+
Enum valueAsEnumType = HowMuchUnit.Some;
289+
var unitAbbreviationsCache = new UnitAbbreviationsCache([HowMuch.Info]);
290+
unitAbbreviationsCache.MapUnitToDefaultAbbreviation(valueAsEnumType, "sm");
291+
Assert.Equal("sm", unitAbbreviationsCache.GetDefaultAbbreviation(valueAsEnumType));
292+
}
293+
294+
/// <inheritdoc cref="MapAndLookup_WithSpecificEnumType"/>
295+
[Fact]
296+
public void MapAndLookup_MapWithSpecificEnumType_LookupWithEnumType()
297+
{
298+
var unitAbbreviationsCache = new UnitAbbreviationsCache([HowMuch.Info]);
299+
unitAbbreviationsCache.MapUnitToDefaultAbbreviation(HowMuchUnit.Some, "sm");
300+
Assert.Equal("sm", unitAbbreviationsCache.GetDefaultAbbreviation((Enum)HowMuchUnit.Some));
301+
}
302+
303+
[Fact]
304+
public void MapUnitToAbbreviation_WithUnknownUnit_ThrowsUnitNotFoundException()
305+
{
306+
var unitAbbreviationCache = new UnitAbbreviationsCache([Mass.Info]);
307+
Assert.Throws<UnitNotFoundException>(() => unitAbbreviationCache.MapUnitToAbbreviation(HowMuchUnit.Some, "nothing"));
308+
Assert.Throws<UnitNotFoundException>(() => unitAbbreviationCache.MapUnitToAbbreviation(LengthUnit.Centimeter, "nothing"));
309+
}
310+
311+
[Fact]
312+
public void MapUnitToDefaultAbbreviation_WithUnknownUnit_ThrowsUnitNotFoundException()
313+
{
314+
var unitAbbreviationCache = new UnitAbbreviationsCache([Mass.Info]);
315+
Assert.Throws<UnitNotFoundException>(() => unitAbbreviationCache.MapUnitToDefaultAbbreviation(HowMuchUnit.Some, "nothing"));
316+
Assert.Throws<UnitNotFoundException>(() => unitAbbreviationCache.MapUnitToDefaultAbbreviation(LengthUnit.AstronomicalUnit, "nothing"));
317+
}
217318
}
218319
}

UnitsNet.Tests/UnitParserTests.cs

Lines changed: 103 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,40 @@ namespace UnitsNet.Tests
1111
{
1212
public class UnitParserTests
1313
{
14+
[Fact]
15+
public void Constructor_WithQuantitiesCreatesNewAbbreviationsCacheAndNewQuantityInfoLookup()
16+
{
17+
var unitParser = new UnitParser([Mass.Info]);
18+
Assert.NotNull(unitParser.Abbreviations);
19+
Assert.NotEqual(UnitAbbreviationsCache.Default, unitParser.Abbreviations);
20+
Assert.NotEqual(UnitsNetSetup.Default.QuantityInfoLookup, unitParser.Quantities);
21+
}
22+
23+
[Fact]
24+
public void Constructor_WithQuantityInfoLookupCreatesNewAbbreviationsCache()
25+
{
26+
var quantities = new QuantityInfoLookup([Mass.Info]);
27+
var unitParser = new UnitParser(quantities);
28+
Assert.NotNull(unitParser.Abbreviations);
29+
Assert.NotEqual(UnitAbbreviationsCache.Default, unitParser.Abbreviations);
30+
Assert.Equal(quantities, unitParser.Quantities);
31+
}
32+
33+
[Fact]
34+
public void CreateDefault_CreatesNewAbbreviationsCacheWithDefaultQuantities()
35+
{
36+
var unitParser = UnitParser.CreateDefault();
37+
Assert.NotNull(unitParser.Abbreviations);
38+
Assert.NotEqual(UnitAbbreviationsCache.Default, unitParser.Abbreviations);
39+
Assert.Equal(UnitsNetSetup.Default.QuantityInfoLookup, unitParser.Quantities);
40+
}
41+
1442
[Theory]
1543
[InlineData("m^^2", AreaUnit.SquareMeter)]
1644
[InlineData("cm^^2", AreaUnit.SquareCentimeter)]
1745
public void Parse_ReturnsUnitMappedByCustomAbbreviation(string customAbbreviation, AreaUnit expected)
1846
{
19-
var abbrevCache = new UnitAbbreviationsCache();
47+
var abbrevCache = new UnitAbbreviationsCache([Area.Info]);
2048
abbrevCache.MapUnitToAbbreviation(expected, customAbbreviation);
2149
var parser = new UnitParser(abbrevCache);
2250

@@ -59,6 +87,8 @@ public void Parse_GivenAbbreviationsThatAreAmbiguousWhenLowerCase_ReturnsCorrect
5987
[Fact]
6088
public void Parse_NullAbbreviation_Throws_ArgumentNullException()
6189
{
90+
Assert.Throws<ArgumentNullException>(() => UnitsNetSetup.Default.UnitParser.Parse<LengthUnit>(null!));
91+
Assert.Throws<ArgumentNullException>(() => UnitsNetSetup.Default.UnitParser.Parse(null!, Length.Info.UnitInfos));
6292
Assert.Throws<ArgumentNullException>(() => UnitsNetSetup.Default.UnitParser.Parse(null!, typeof(LengthUnit)));
6393
}
6494

@@ -129,9 +159,12 @@ public void Parse_AmbiguousUnitsThrowsException()
129159
[InlineData("kg", "ru-RU", MassUnit.Kilogram)] // should work with the "FallbackCulture"
130160
public void ParseMassUnit_GivenCulture(string str, string cultureName, Enum expectedUnit)
131161
{
132-
Assert.Equal(expectedUnit, UnitsNetSetup.Default.UnitParser.Parse<MassUnit>(str, CultureInfo.GetCultureInfo(cultureName)));
162+
var formatProvider = CultureInfo.GetCultureInfo(cultureName);
163+
UnitParser unitParser = UnitsNetSetup.Default.UnitParser;
164+
165+
Assert.Equal(expectedUnit, unitParser.Parse<MassUnit>(str, formatProvider));
133166
}
134-
167+
135168
[Fact]
136169
public void Parse_MappedCustomUnit()
137170
{
@@ -150,7 +183,7 @@ public void Parse_LengthUnit_MM_ThrowsExceptionDescribingTheAmbiguity()
150183
var ex = Assert.Throws<AmbiguousUnitParseException>(() => UnitsNetSetup.Default.UnitParser.Parse<LengthUnit>("MM"));
151184
Assert.Equal("""Cannot parse "MM" since it matches multiple units: Megameter ("Mm"), Millimeter ("mm").""", ex.Message);
152185
}
153-
186+
154187
[Fact]
155188
public void TryParse_WithNullAbbreviation_ReturnsFalse()
156189
{
@@ -163,20 +196,28 @@ public void TryParse_WithNullAbbreviation_ReturnsFalse()
163196
{
164197
var success = unitParser.TryParse(null, typeof(LengthUnit), out Enum? _);
165198
Assert.False(success);
199+
}, () =>
200+
{
201+
var success = unitParser.TryParse(null, [], null, out UnitInfo<LengthUnit>? _);
202+
Assert.False(success);
166203
});
167204
}
168205

169-
[Fact]
170-
public void TryParse_UnknownAbbreviation_ReturnsFalse()
206+
[Theory]
207+
[InlineData("")]
208+
[InlineData("z^2")]
209+
[InlineData("nonexistingunit")]
210+
public void TryParse_UnknownAbbreviation_ReturnsFalse(string unknownAreaAbbreviation)
171211
{
172-
Assert.False(UnitsNetSetup.Default.UnitParser.TryParse("nonexistingunit", out AreaUnit _));
212+
Assert.False(UnitsNetSetup.Default.UnitParser.TryParse(unknownAreaAbbreviation, out AreaUnit _));
173213
}
174214

175215
[Fact]
176216
public void TryParse_WithAmbiguousUnits_ReturnsFalse()
177217
{
178218
UnitParser unitParser = UnitsNetSetup.Default.UnitParser;
179219
Assert.False(unitParser.TryParse("pt", CultureInfo.InvariantCulture, out LengthUnit _));
220+
Assert.False(unitParser.TryParse("pt", Length.Info.UnitInfos, CultureInfo.InvariantCulture, out UnitInfo<LengthUnit>? _));
180221
}
181222

182223
[Theory]
@@ -197,5 +238,60 @@ public void TryParseMassUnit_GivenCulture(string str, string cultureName, Enum e
197238
Assert.True(success);
198239
Assert.Equal(expectedUnit, unitParsed);
199240
}
241+
242+
[Fact]
243+
public void TryGetUnitFromAbbreviation_WithLocalizedUnit_MatchingCulture_ReturnsTrue()
244+
{
245+
var formatProvider = CultureInfo.GetCultureInfo("ru-RU");
246+
UnitParser unitParser = UnitsNetSetup.Default.UnitParser;
247+
248+
var success = unitParser.TryGetUnitFromAbbreviation("кг", formatProvider, out UnitInfo? unitInfo);
249+
250+
Assert.True(success);
251+
Assert.NotNull(unitInfo);
252+
Assert.Equal(MassUnit.Kilogram, unitInfo.Value);
253+
}
254+
255+
[Fact]
256+
public void TryGetUnitFromAbbreviation_MatchingFallbackCulture_ReturnsTrue()
257+
{
258+
var formatProvider = CultureInfo.GetCultureInfo("ru-RU");
259+
UnitParser unitParser = UnitsNetSetup.Default.UnitParser;
260+
261+
var success = unitParser.TryGetUnitFromAbbreviation("kg", formatProvider, out UnitInfo? unitInfo);
262+
263+
Assert.True(success);
264+
Assert.NotNull(unitInfo);
265+
Assert.Equal(MassUnit.Kilogram, unitInfo.Value);
266+
}
267+
268+
[Fact]
269+
public void TryGetUnitFromAbbreviation_WithNullString_ReturnsFalse()
270+
{
271+
var success = UnitsNetSetup.Default.UnitParser.TryGetUnitFromAbbreviation(null, CultureInfo.InvariantCulture, out UnitInfo? _);
272+
273+
Assert.False(success);
274+
}
275+
276+
[Fact]
277+
public void GetUnitFromAbbreviation_GivenAbbreviationsThatAreAmbiguousWhenLowerCase_ReturnsCorrectUnit()
278+
{
279+
Assert.Equal(PressureUnit.Megabar, UnitParser.Default.GetUnitFromAbbreviation("Mbar", CultureInfo.InvariantCulture).Value);
280+
Assert.Equal(PressureUnit.Millibar, UnitParser.Default.GetUnitFromAbbreviation("mbar", CultureInfo.InvariantCulture).Value);
281+
}
282+
283+
[Fact]
284+
public void GetUnitFromAbbreviation_NullAbbreviation_Throws_ArgumentNullException()
285+
{
286+
Assert.Throws<ArgumentNullException>(() => UnitsNetSetup.Default.UnitParser.GetUnitFromAbbreviation(null!, CultureInfo.InvariantCulture));
287+
}
288+
289+
[Theory]
290+
[InlineData("z^2")]
291+
[InlineData("nonexistingunit")]
292+
public void GetUnitFromAbbreviation_UnknownAbbreviationThrowsUnitNotFoundException(string unknownAbbreviation)
293+
{
294+
Assert.Throws<UnitNotFoundException>(() => UnitsNetSetup.Default.UnitParser.GetUnitFromAbbreviation(unknownAbbreviation, CultureInfo.InvariantCulture));
295+
}
200296
}
201297
}

0 commit comments

Comments
 (0)