Add assertEquals and assertNotEquals for floating point numbers to kotlin-test #KT-8364
This commit is contained in:
committed by
Abduqodiri Qurbonzoda
parent
ff59b1c2ef
commit
d520c37454
@@ -63,11 +63,35 @@ fun <@OnlyInputTypes T> assertEquals(expected: T, actual: T, message: String? =
|
||||
asserter.assertEquals(message, expected, actual)
|
||||
}
|
||||
|
||||
/** Asserts that the difference between the [actual] and the [expected] is within an [absoluteTolerance], with an optional [message]. */
|
||||
@SinceKotlin("1.5")
|
||||
fun assertEquals(expected: Double, actual: Double, absoluteTolerance: Double, message: String? = null) {
|
||||
checkDoublesAreEqual(expected, actual, absoluteTolerance, message)
|
||||
}
|
||||
|
||||
/** Asserts that the difference between the [actual] and the [expected] is within an [absoluteTolerance], with an optional [message]. */
|
||||
@SinceKotlin("1.5")
|
||||
fun assertEquals(expected: Float, actual: Float, absoluteTolerance: Float, message: String? = null) {
|
||||
checkFloatsAreEqual(expected, actual, absoluteTolerance, message)
|
||||
}
|
||||
|
||||
/** Asserts that the [actual] value is not equal to the illegal value, with an optional [message]. */
|
||||
fun <@OnlyInputTypes T> assertNotEquals(illegal: T, actual: T, message: String? = null) {
|
||||
asserter.assertNotEquals(message, illegal, actual)
|
||||
}
|
||||
|
||||
/** Asserts that the difference between the [actual] and the [illegal] is not within an [absoluteTolerance], with an optional [message]. */
|
||||
@SinceKotlin("1.5")
|
||||
fun assertNotEquals(illegal: Double, actual: Double, absoluteTolerance: Double, message: String? = null) {
|
||||
checkDoublesAreEqual(illegal, actual, absoluteTolerance, message, shouldFail = true)
|
||||
}
|
||||
|
||||
/** Asserts that the difference between the [actual] and the [illegal] is not within an [absoluteTolerance], with an optional [message]. */
|
||||
@SinceKotlin("1.5")
|
||||
fun assertNotEquals(illegal: Float, actual: Float, absoluteTolerance: Float, message: String? = null) {
|
||||
checkFloatsAreEqual(illegal, actual, absoluteTolerance, message, shouldFail = true)
|
||||
}
|
||||
|
||||
/** Asserts that [expected] is the same instance as [actual], with an optional [message]. */
|
||||
fun <@OnlyInputTypes T> assertSame(expected: T, actual: T, message: String? = null) {
|
||||
asserter.assertSame(message, expected, actual)
|
||||
|
||||
@@ -5,8 +5,48 @@
|
||||
|
||||
package kotlin.test
|
||||
|
||||
import kotlin.math.abs
|
||||
|
||||
internal fun messagePrefix(message: String?) = if (message == null) "" else "$message. "
|
||||
internal expect fun lookupAsserter(): Asserter
|
||||
|
||||
@PublishedApi // required to get stable name as it's called from box tests
|
||||
internal fun overrideAsserter(value: Asserter?): Asserter? = _asserter.also { _asserter = value }
|
||||
internal fun overrideAsserter(value: Asserter?): Asserter? = _asserter.also { _asserter = value }
|
||||
|
||||
|
||||
private fun checkAbsoluteTolerance(absoluteTolerance: Double) {
|
||||
require(absoluteTolerance >= 0.0) { "Illegal negative absolute tolerance <$absoluteTolerance>." }
|
||||
require(!absoluteTolerance.isNaN()) { "Illegal NaN absolute tolerance <$absoluteTolerance>." }
|
||||
}
|
||||
|
||||
internal fun checkDoublesAreEqual(
|
||||
expected: Double,
|
||||
actual: Double,
|
||||
absoluteTolerance: Double,
|
||||
message: String?,
|
||||
shouldFail: Boolean = false
|
||||
) {
|
||||
checkAbsoluteTolerance(absoluteTolerance)
|
||||
val equal = expected.toBits() == actual.toBits() || abs(expected - actual) <= absoluteTolerance
|
||||
|
||||
asserter.assertTrue(
|
||||
{ messagePrefix(message) + "Expected <$expected> with absolute tolerance <$absoluteTolerance>, actual <$actual>." },
|
||||
equal != shouldFail
|
||||
)
|
||||
}
|
||||
|
||||
internal fun checkFloatsAreEqual(
|
||||
expected: Float,
|
||||
actual: Float,
|
||||
absoluteTolerance: Float,
|
||||
message: String?,
|
||||
shouldFail: Boolean = false
|
||||
) {
|
||||
checkAbsoluteTolerance(absoluteTolerance.toDouble())
|
||||
val equal = expected.toBits() == actual.toBits() || abs(expected - actual) <= absoluteTolerance
|
||||
|
||||
asserter.assertTrue(
|
||||
{ messagePrefix(message) + "Expected <$expected> with absolute tolerance <$absoluteTolerance>, actual <$actual>." },
|
||||
equal != shouldFail
|
||||
)
|
||||
}
|
||||
+113
@@ -88,6 +88,119 @@ class BasicAssertionsTest {
|
||||
checkFailedAssertion { assertSame(instance1, instance2) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAssertEqualsDouble() {
|
||||
assertEquals(0.01, 0.02, .01)
|
||||
|
||||
// 0.0, -0.0
|
||||
assertEquals(0.0, 0.0, 0.0)
|
||||
assertEquals(0.0, -0.0, 0.0)
|
||||
assertEquals(-0.0, 0.0, 0.0)
|
||||
assertEquals(0.0, 0.0, -0.0)
|
||||
assertEquals(0.0, -0.0, -0.0)
|
||||
assertEquals(-0.0, 0.0, -0.0)
|
||||
|
||||
// NaN
|
||||
val nans = doubleArrayOf(Double.NaN, Double.fromBits(0xFFF80000L shl 32))
|
||||
for (nan1 in nans) {
|
||||
assertTrue(nan1.isNaN())
|
||||
for (nan2 in nans) {
|
||||
assertEquals(nan1, nan2, 0.1)
|
||||
assertEquals(nan1, nan2, 0.0)
|
||||
}
|
||||
}
|
||||
|
||||
// MIN_VALUE, MAX_VALUE
|
||||
assertEquals(Double.MAX_VALUE, Double.MAX_VALUE, 0.0)
|
||||
assertEquals(Double.MIN_VALUE, Double.MIN_VALUE, 0.0)
|
||||
assertEquals(Double.MAX_VALUE, Double.MIN_VALUE, Double.MAX_VALUE)
|
||||
assertEquals(Double.MIN_VALUE, Double.MAX_VALUE, Double.MAX_VALUE)
|
||||
|
||||
// POSITIVE_INFINITY, NEGATIVE_INFINITY
|
||||
assertEquals(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, 0.0)
|
||||
assertEquals(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, 0.0)
|
||||
assertEquals(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY)
|
||||
assertEquals(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAssertEqualsDoubleFails() {
|
||||
checkFailedAssertion { assertEquals(0.01, 1.03, .01) }
|
||||
|
||||
// negative absoluteTolerance
|
||||
assertFailsWith<IllegalArgumentException> { assertEquals(0.01, 1.03, -5.0) }
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAssertEqualsFloat() {
|
||||
assertEquals(0.01f, 0.02f, .01f)
|
||||
|
||||
// 0.0, -0.0
|
||||
assertEquals(0.0f, 0.0f, 0.0f)
|
||||
assertEquals(0.0f, -0.0f, 0.0f)
|
||||
assertEquals(-0.0f, 0.0f, 0.0f)
|
||||
assertEquals(0.0f, 0.0f, -0.0f)
|
||||
assertEquals(0.0f, -0.0f, -0.0f)
|
||||
assertEquals(-0.0f, 0.0f, -0.0f)
|
||||
|
||||
// NaN
|
||||
val nans = floatArrayOf(Float.NaN, Float.fromBits(0xFFC00000.toInt()))
|
||||
for (nan1 in nans) {
|
||||
assertTrue(nan1.isNaN())
|
||||
for (nan2 in nans) {
|
||||
assertEquals(nan1, nan2, 0.1f)
|
||||
assertEquals(nan1, nan2, 0.0f)
|
||||
}
|
||||
}
|
||||
|
||||
// MIN_VALUE, MAX_VALUE
|
||||
assertEquals(Float.MAX_VALUE, Float.MAX_VALUE, 0.0f)
|
||||
assertEquals(Float.MIN_VALUE, Float.MIN_VALUE, 0.0f)
|
||||
assertEquals(Float.MAX_VALUE, Float.MIN_VALUE, Float.MAX_VALUE)
|
||||
assertEquals(Float.MIN_VALUE, Float.MAX_VALUE, Float.MAX_VALUE)
|
||||
|
||||
// POSITIVE_INFINITY, NEGATIVE_INFINITY
|
||||
assertEquals(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, 0.0f)
|
||||
assertEquals(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, 0.0f)
|
||||
assertEquals(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY)
|
||||
assertEquals(Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAssertEqualsFloatFails() {
|
||||
checkFailedAssertion { assertEquals(0.01f, 1.03f, .01f) }
|
||||
|
||||
// negative absoluteTolerance
|
||||
assertFailsWith<IllegalArgumentException> { assertEquals(0.01f, 1.03f, -5.0f) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAssertNotEqualsDouble() {
|
||||
assertNotEquals(0.1, 0.3, 0.1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAssertNotEqualsDoubleFails() {
|
||||
checkFailedAssertion { assertNotEquals(0.1, 0.11, 0.1) }
|
||||
|
||||
// negative absoluteTolerance
|
||||
assertFailsWith<IllegalArgumentException> { assertNotEquals(0.1, 0.11, -0.001) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAssertNotEqualsFloat() {
|
||||
assertNotEquals(0.1f, 0.3f, 0.1f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAssertNotEqualsFloatFails() {
|
||||
checkFailedAssertion { assertNotEquals(0.1f, 0.11f, .1f) }
|
||||
|
||||
// negative absoluteTolerance
|
||||
assertFailsWith<IllegalArgumentException> { assertNotEquals(0.1f, 0.11f, -0.001f) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAssertTrue() {
|
||||
assertTrue(true)
|
||||
|
||||
Reference in New Issue
Block a user