Skip to content

Commit 8ac4f4e

Browse files
author
snopan
committed
Rework for clarity and resolving rounding issues close to INF
1 parent 038b8ed commit 8ac4f4e

1 file changed

Lines changed: 34 additions & 20 deletions

File tree

assert/assertions.go

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -177,39 +177,53 @@ func ObjectsAreEqualValues(expected, actual interface{}) bool {
177177
return false
178178
}
179179

180+
convertedExpectedValue := expectedValue.Convert(actualType).Interface()
181+
180182
if !isNumericType(expectedType) || !isNumericType(actualType) {
181183
// Attempt comparison after type conversion
182-
return reflect.DeepEqual(
183-
expectedValue.Convert(actualType).Interface(), actual,
184-
)
184+
return reflect.DeepEqual(convertedExpectedValue, actual)
185185
}
186186

187187
// If BOTH values are numeric, there are chances of false positives due
188188
// to overflow or underflow. So, we need to make sure to always convert
189189
// the smaller type to a larger type before comparing.
190-
fromType := actualType
191-
toType := expectedType
192-
fromValue := actualValue
193-
toValue := expectedValue
194-
if expectedType.Size() < actualType.Size() {
195-
fromType = expectedType
196-
toType = actualType
197-
fromValue = expectedValue
198-
toValue = actualValue
199-
}
200-
201-
// If we are converting from float32 to float64, the converted value will
202-
// have trailing non zero decimals due to binary representation differences
190+
// Assume smaller is expected value and larger is actual value
191+
smallerTypeValue, largerTypeValue := expectedValue, actualValue
192+
smallerValueCmp, largerValueCmp := convertedExpectedValue, actual
193+
194+
// Actual value is smaller than expected value, converting actual value to expected value type
195+
if actualType.Size() < expectedType.Size() {
196+
smallerTypeValue, largerTypeValue = actualValue, expectedValue
197+
198+
if !actualType.ConvertibleTo(expectedType) {
199+
return false
200+
}
201+
smallerValueCmp = actualValue.Convert(expectedType).Interface()
202+
largerValueCmp = expected
203+
}
204+
205+
// Quick comparison after type conversion to see if overflow or underflow is resolved
206+
if smallerValueCmp == largerValueCmp {
207+
return true
208+
}
209+
210+
// We want to allow comparison between float32(10.1) and float64(10.1).
211+
// The problem here is when converting from float32 to float64, the converted
212+
// value will have trailing non zero decimals due to binary representation differences
203213
// For example: float64(float32(10.1)) = 10.100000381469727
204214
// To remove the trailing decimals we can round the 64-bit value to
205215
// expected precision of 32-bit which is 6 decimal places
206-
newValue := fromValue.Convert(toType).Interface()
207-
if fromType.Kind() == reflect.Float32 && toType.Kind() == reflect.Float64 {
216+
if smallerTypeValue.Kind() == reflect.Float32 && largerTypeValue.Kind() == reflect.Float64 {
217+
float := smallerValueCmp.(float64)
218+
integerPart := math.Floor(float)
219+
decimalPart := float - integerPart
220+
208221
scale := math.Pow(10, 6)
209-
newValue = math.Round(newValue.(float64)*scale) / scale
222+
decimalPart = math.Round(decimalPart*scale) / scale
223+
smallerValueCmp = integerPart + decimalPart
210224
}
211225

212-
return newValue == toValue.Interface()
226+
return smallerValueCmp == largerValueCmp
213227
}
214228

215229
// isNumericType returns true if the type is one of:

0 commit comments

Comments
 (0)