1+
2+ namespace FTMS . NET . Utils . UnitTests ;
3+
4+ /// <summary>
5+ /// Unit tests for the <see cref="ValueCalculation"/> record's Calculate method.
6+ /// </summary>
7+ public partial class ValueCalculationTests
8+ {
9+ /// <summary>
10+ /// Tests that Calculate returns the correct result with default parameters (multiplier=1, exponents=0).
11+ /// The constant multiplier should be 1, so the result should equal the raw value.
12+ /// </summary>
13+ [ Theory ]
14+ [ InlineData ( 0L , 0.0 ) ]
15+ [ InlineData ( 1L , 1.0 ) ]
16+ [ InlineData ( - 1L , - 1.0 ) ]
17+ [ InlineData ( 100L , 100.0 ) ]
18+ [ InlineData ( - 100L , - 100.0 ) ]
19+ [ InlineData ( long . MaxValue , 9223372036854775807.0 ) ]
20+ [ InlineData ( long . MinValue , - 9223372036854775808.0 ) ]
21+ public void Calculate_WithDefaultParameters_ReturnsRawValue ( long rawValue , double expected )
22+ {
23+ // Arrange
24+ var calculation = new ValueCalculation ( ) ;
25+
26+ // Act
27+ double result = calculation . Calculate ( rawValue ) ;
28+
29+ // Assert
30+ Assert . Equal ( expected , result ) ;
31+ }
32+
33+ /// <summary>
34+ /// Tests that Calculate returns zero when the raw value is zero, regardless of the multiplier.
35+ /// </summary>
36+ [ Theory ]
37+ [ InlineData ( 1 , 0 , 0 ) ]
38+ [ InlineData ( 5 , 0 , 0 ) ]
39+ [ InlineData ( - 5 , 0 , 0 ) ]
40+ [ InlineData ( 100 , 2 , 3 ) ]
41+ [ InlineData ( int . MaxValue , 10 , 10 ) ]
42+ public void Calculate_WithZeroRawValue_ReturnsZero ( int multiplier , int decimalExponent , int binaryExponent )
43+ {
44+ // Arrange
45+ var calculation = new ValueCalculation ( multiplier , decimalExponent , binaryExponent ) ;
46+
47+ // Act
48+ double result = calculation . Calculate ( 0L ) ;
49+
50+ // Assert
51+ Assert . Equal ( 0.0 , result ) ;
52+ }
53+
54+ /// <summary>
55+ /// Tests that Calculate correctly applies the multiplier to the raw value.
56+ /// With decimal and binary exponents at 0, the constant multiplier equals the multiplier parameter.
57+ /// </summary>
58+ [ Theory ]
59+ [ InlineData ( 2 , 10L , 20.0 ) ]
60+ [ InlineData ( 5 , 3L , 15.0 ) ]
61+ [ InlineData ( - 2 , 10L , - 20.0 ) ]
62+ [ InlineData ( - 3 , - 5L , 15.0 ) ]
63+ [ InlineData ( 0 , 100L , 0.0 ) ]
64+ [ InlineData ( 1 , long . MaxValue , 9223372036854775807.0 ) ]
65+ [ InlineData ( 10 , 100L , 1000.0 ) ]
66+ public void Calculate_WithMultiplier_ReturnsScaledValue ( int multiplier , long rawValue , double expected )
67+ {
68+ // Arrange
69+ var calculation = new ValueCalculation ( Multiplier : multiplier , DecimalExponent : 0 , BinaryExponent : 0 ) ;
70+
71+ // Act
72+ double result = calculation . Calculate ( rawValue ) ;
73+
74+ // Assert
75+ Assert . Equal ( expected , result ) ;
76+ }
77+
78+ /// <summary>
79+ /// Tests that Calculate correctly applies the decimal exponent (power of 10).
80+ /// The constant multiplier should be multiplied by 10^decimalExponent.
81+ /// </summary>
82+ [ Theory ]
83+ [ InlineData ( 1 , 2 , 0 , 5L , 500.0 ) ] // 5 * (1 * 10^2 * 2^0) = 5 * 100 = 500
84+ [ InlineData ( 1 , 3 , 0 , 2L , 2000.0 ) ] // 2 * (1 * 10^3 * 2^0) = 2 * 1000 = 2000
85+ [ InlineData ( 1 , - 2 , 0 , 100L , 1.0 ) ] // 100 * (1 * 10^-2 * 2^0) = 100 * 0.01 = 1
86+ [ InlineData ( 2 , 1 , 0 , 5L , 100.0 ) ] // 5 * (2 * 10^1 * 2^0) = 5 * 20 = 100
87+ [ InlineData ( 1 , 0 , 0 , 10L , 10.0 ) ] // 10 * (1 * 10^0 * 2^0) = 10 * 1 = 10
88+ public void Calculate_WithDecimalExponent_ReturnsCorrectValue ( int multiplier , int decimalExponent , int binaryExponent , long rawValue , double expected )
89+ {
90+ // Arrange
91+ var calculation = new ValueCalculation ( multiplier , decimalExponent , binaryExponent ) ;
92+
93+ // Act
94+ double result = calculation . Calculate ( rawValue ) ;
95+
96+ // Assert
97+ Assert . Equal ( expected , result ) ;
98+ }
99+
100+ /// <summary>
101+ /// Tests that Calculate correctly applies the binary exponent (power of 2).
102+ /// The constant multiplier should be multiplied by 2^binaryExponent.
103+ /// </summary>
104+ [ Theory ]
105+ [ InlineData ( 1 , 0 , 3 , 5L , 40.0 ) ] // 5 * (1 * 10^0 * 2^3) = 5 * 8 = 40
106+ [ InlineData ( 1 , 0 , 4 , 2L , 32.0 ) ] // 2 * (1 * 10^0 * 2^4) = 2 * 16 = 32
107+ [ InlineData ( 1 , 0 , - 2 , 16L , 4.0 ) ] // 16 * (1 * 10^0 * 2^-2) = 16 * 0.25 = 4
108+ [ InlineData ( 2 , 0 , 2 , 5L , 40.0 ) ] // 5 * (2 * 10^0 * 2^2) = 5 * 8 = 40
109+ [ InlineData ( 1 , 0 , 0 , 10L , 10.0 ) ] // 10 * (1 * 10^0 * 2^0) = 10 * 1 = 10
110+ public void Calculate_WithBinaryExponent_ReturnsCorrectValue ( int multiplier , int decimalExponent , int binaryExponent , long rawValue , double expected )
111+ {
112+ // Arrange
113+ var calculation = new ValueCalculation ( multiplier , decimalExponent , binaryExponent ) ;
114+
115+ // Act
116+ double result = calculation . Calculate ( rawValue ) ;
117+
118+ // Assert
119+ Assert . Equal ( expected , result ) ;
120+ }
121+
122+ /// <summary>
123+ /// Tests that Calculate correctly combines all three parameters (multiplier, decimal exponent, binary exponent).
124+ /// </summary>
125+ [ Theory ]
126+ [ InlineData ( 2 , 1 , 2 , 5L , 400.0 ) ] // 5 * (2 * 10^1 * 2^2) = 5 * (2 * 10 * 4) = 5 * 80 = 400
127+ [ InlineData ( 3 , 2 , 3 , 1L , 2400.0 ) ] // 1 * (3 * 10^2 * 2^3) = 3 * 100 * 8 = 2400
128+ [ InlineData ( 5 , - 1 , 1 , 10L , 10.0 ) ] // 10 * (5 * 10^-1 * 2^1) = 10 * (0.5 * 2) = 10 * 1 = 10
129+ [ InlineData ( 1 , 1 , 1 , 50L , 1000.0 ) ] // 50 * (1 * 10^1 * 2^1) = 50 * 20 = 1000
130+ [ InlineData ( - 2 , 1 , 1 , 5L , - 200.0 ) ] // 5 * (-2 * 10^1 * 2^1) = 5 * (-40) = -200
131+ public void Calculate_WithCombinedParameters_ReturnsCorrectValue ( int multiplier , int decimalExponent , int binaryExponent , long rawValue , double expected )
132+ {
133+ // Arrange
134+ var calculation = new ValueCalculation ( multiplier , decimalExponent , binaryExponent ) ;
135+
136+ // Act
137+ double result = calculation . Calculate ( rawValue ) ;
138+
139+ // Assert
140+ Assert . Equal ( expected , result ) ;
141+ }
142+
143+ /// <summary>
144+ /// Tests that Calculate handles negative raw values correctly.
145+ /// The sign of the raw value should be preserved in the result.
146+ /// </summary>
147+ [ Theory ]
148+ [ InlineData ( 1 , 0 , 0 , - 10L , - 10.0 ) ]
149+ [ InlineData ( 2 , 0 , 0 , - 5L , - 10.0 ) ]
150+ [ InlineData ( 1 , 2 , 0 , - 1L , - 100.0 ) ]
151+ [ InlineData ( - 2 , 0 , 0 , - 10L , 20.0 ) ] // Negative multiplier with negative rawValue = positive
152+ [ InlineData ( 5 , 1 , 1 , - 2L , - 200.0 ) ]
153+ public void Calculate_WithNegativeRawValue_ReturnsCorrectSignedResult ( int multiplier , int decimalExponent , int binaryExponent , long rawValue , double expected )
154+ {
155+ // Arrange
156+ var calculation = new ValueCalculation ( multiplier , decimalExponent , binaryExponent ) ;
157+
158+ // Act
159+ double result = calculation . Calculate ( rawValue ) ;
160+
161+ // Assert
162+ Assert . Equal ( expected , result ) ;
163+ }
164+
165+ /// <summary>
166+ /// Tests that Calculate handles extreme raw values (long.MinValue and long.MaxValue) correctly.
167+ /// These tests verify that the calculation doesn't cause unexpected overflow behavior.
168+ /// </summary>
169+ [ Theory ]
170+ [ InlineData ( 2 , 0 , 0 , long . MaxValue , 1.8446744073709552E+19 ) ] // long.MaxValue * 2
171+ [ InlineData ( 2 , 0 , 0 , long . MinValue , - 1.8446744073709552E+19 ) ] // long.MinValue * 2
172+ [ InlineData ( 1 , 1 , 0 , long . MaxValue , 9.223372036854776E+19 ) ] // long.MaxValue * 10
173+ [ InlineData ( 1 , - 10 , 0 , long . MaxValue , 922337203.6854776 ) ] // long.MaxValue * 10^-10
174+ public void Calculate_WithExtremeRawValues_ReturnsCorrectValue ( int multiplier , int decimalExponent , int binaryExponent , long rawValue , double expected )
175+ {
176+ // Arrange
177+ var calculation = new ValueCalculation ( multiplier , decimalExponent , binaryExponent ) ;
178+
179+ // Act
180+ double result = calculation . Calculate ( rawValue ) ;
181+
182+ // Assert
183+ Assert . Equal ( expected , result , precision : 10 ) ;
184+ }
185+
186+ /// <summary>
187+ /// Tests that Calculate can produce positive infinity when the result exceeds double's maximum value.
188+ /// </summary>
189+ [ Fact ]
190+ public void Calculate_WithVeryLargeMultiplier_ReturnsPositiveInfinity ( )
191+ {
192+ // Arrange
193+ var calculation = new ValueCalculation ( Multiplier : 1 , DecimalExponent : 300 , BinaryExponent : 10 ) ;
194+
195+ // Act
196+ double result = calculation . Calculate ( long . MaxValue ) ;
197+
198+ // Assert
199+ Assert . Equal ( double . PositiveInfinity , result ) ;
200+ }
201+
202+ /// <summary>
203+ /// Tests that Calculate can produce negative infinity when the result is below double's minimum value.
204+ /// </summary>
205+ [ Fact ]
206+ public void Calculate_WithVeryLargeMultiplierAndNegativeValue_ReturnsNegativeInfinity ( )
207+ {
208+ // Arrange
209+ var calculation = new ValueCalculation ( Multiplier : 1 , DecimalExponent : 300 , BinaryExponent : 10 ) ;
210+
211+ // Act
212+ double result = calculation . Calculate ( long . MinValue ) ;
213+
214+ // Assert
215+ Assert . Equal ( double . NegativeInfinity , result ) ;
216+ }
217+
218+ /// <summary>
219+ /// Tests that Calculate returns values very close to zero when using large negative exponents.
220+ /// </summary>
221+ [ Theory ]
222+ [ InlineData ( 1 , - 300 , 0 , 100L ) ]
223+ [ InlineData ( 1 , 0 , - 1000 , 100L ) ]
224+ [ InlineData ( 1 , - 150 , - 150 , 1000L ) ]
225+ public void Calculate_WithVerySmallMultiplier_ReturnsValueCloseToZero ( int multiplier , int decimalExponent , int binaryExponent , long rawValue )
226+ {
227+ // Arrange
228+ var calculation = new ValueCalculation ( multiplier , decimalExponent , binaryExponent ) ;
229+
230+ // Act
231+ double result = calculation . Calculate ( rawValue ) ;
232+
233+ // Assert
234+ Assert . True ( result >= 0.0 && result < 1e-100 ) ;
235+ }
236+
237+ /// <summary>
238+ /// Tests that Calculate with a zero multiplier always returns zero.
239+ /// </summary>
240+ [ Theory ]
241+ [ InlineData ( 0 , 0 , 0 , 100L ) ]
242+ [ InlineData ( 0 , 5 , 3 , long . MaxValue ) ]
243+ [ InlineData ( 0 , - 5 , - 3 , long . MinValue ) ]
244+ [ InlineData ( 0 , 10 , 10 , - 1000L ) ]
245+ public void Calculate_WithZeroMultiplier_ReturnsZero ( int multiplier , int decimalExponent , int binaryExponent , long rawValue )
246+ {
247+ // Arrange
248+ var calculation = new ValueCalculation ( multiplier , decimalExponent , binaryExponent ) ;
249+
250+ // Act
251+ double result = calculation . Calculate ( rawValue ) ;
252+
253+ // Assert
254+ Assert . Equal ( 0.0 , result ) ;
255+ }
256+ }
0 commit comments