Unverified Commit 39debd70 authored by Shagen Ogandzhanian's avatar Shagen Ogandzhanian Committed by GitHub

Assert close enough refactoring (#370)

* Introduce helper function fail

* Simplify signatures for assertContentCloseEnough

* In the middle of refactoring

* Don't use nested assertions in assertCloseEnough family of functions

* Platform-aware default epsilon

* Correct one of assertion error messages

* Yet another typo in a commit message
parent 3340df22
...@@ -31,7 +31,7 @@ class PathMeasureTest { ...@@ -31,7 +31,7 @@ class PathMeasureTest {
fun getPosition() = runTest { fun getPosition() = runTest {
Path().moveTo(0f, 10f).lineTo(20f, 0f).moveTo(0f, 40f).lineTo(30f, 50f).use { path -> Path().moveTo(0f, 10f).lineTo(20f, 0f).moveTo(0f, 40f).lineTo(30f, 50f).use { path ->
PathMeasure(path, false).use { measure -> PathMeasure(path, false).use { measure ->
assertCloseEnough(Point(0.89442724f, 9.552787f), measure.getPosition(1f)) assertCloseEnough(Point(0.89442724f, 9.552787f), measure.getPosition(1f)!!)
} }
} }
} }
...@@ -44,52 +44,52 @@ class PathMeasureTest { ...@@ -44,52 +44,52 @@ class PathMeasureTest {
PathMeasure(path, false).use { measure -> PathMeasure(path, false).use { measure ->
Path().lineTo(10f, 10f).use { path2 -> Path().lineTo(10f, 10f).use { path2 ->
assertEquals(40f, measure.length) assertEquals(40f, measure.length)
assertCloseEnough(Point(0f, 0f), measure.getPosition(0f)) assertCloseEnough(Point(0f, 0f), measure.getPosition(0f)!!)
assertCloseEnough(Point(1f, 0f), measure.getTangent(0f)) assertCloseEnough(Point(1f, 0f), measure.getTangent(0f)!!)
assertCloseEnough(Point(20f, 0f), measure.getPosition(20f)) assertCloseEnough(Point(20f, 0f), measure.getPosition(20f)!!)
assertCloseEnough(Point(1f, 0f), measure.getTangent(20f)) assertCloseEnough(Point(1f, 0f), measure.getTangent(20f)!!)
assertEquals(false, measure.isClosed) assertEquals(false, measure.isClosed)
assertCloseEnough( assertCloseEnough(
Matrix33.makeTranslate(20f, 0f), measure.getMatrix( Matrix33.makeTranslate(20f, 0f), measure.getMatrix(
20f, 20f,
getPosition = true, getPosition = true,
getTangent = false getTangent = false
) )!!
) )
assertCloseEnough( assertCloseEnough(
Matrix33.makeRotate(0f), measure.getMatrix( Matrix33.makeRotate(0f), measure.getMatrix(
20f, 20f,
getPosition = false, getPosition = false,
getTangent = true getTangent = true
) )!!
) )
assertCloseEnough( assertCloseEnough(
Matrix33.makeTranslate(20f, 0f).makeConcat(Matrix33.makeRotate(0f)), Matrix33.makeTranslate(20f, 0f).makeConcat(Matrix33.makeRotate(0f)),
measure.getMatrix(20f, getPosition = true, getTangent = true) measure.getMatrix(20f, getPosition = true, getTangent = true)!!
) )
measure.nextContour() measure.nextContour()
assertCloseEnough(14.14213f, measure.length) assertCloseEnough(14.14213f, measure.length)
assertCloseEnough(Point(0f, 40f), measure.getPosition(0f)) assertCloseEnough(Point(0f, 40f), measure.getPosition(0f)!!)
assertCloseEnough(Point(0.70710677f, 0.70710677f), measure.getTangent(0f)) assertCloseEnough(Point(0.70710677f, 0.70710677f), measure.getTangent(0f)!!)
assertCloseEnough(Point(4.949747f, 44.949745f), measure.getPosition(7f)) assertCloseEnough(Point(4.949747f, 44.949745f), measure.getPosition(7f)!!)
assertCloseEnough(Point(0.70710677f, 0.70710677f), measure.getTangent(7f)) assertCloseEnough(Point(0.70710677f, 0.70710677f), measure.getTangent(7f)!!)
assertCloseEnough( assertCloseEnough(
Matrix33.makeTranslate(4.949747f, 44.949745f), measure.getMatrix( Matrix33.makeTranslate(4.949747f, 44.949745f), measure.getMatrix(
7f, 7f,
getPosition = true, getPosition = true,
getTangent = false getTangent = false
) )!!
) )
assertCloseEnough( assertCloseEnough(
Matrix33.makeRotate(45f), measure.getMatrix( Matrix33.makeRotate(45f), measure.getMatrix(
7f, 7f,
getPosition = false, getPosition = false,
getTangent = true getTangent = true
) )!!
) )
assertCloseEnough( assertCloseEnough(
Matrix33.makeTranslate(4.949747f, 44.949745f).makeConcat(Matrix33.makeRotate(45f)), Matrix33.makeTranslate(4.949747f, 44.949745f).makeConcat(Matrix33.makeRotate(45f)),
measure.getMatrix(7f, getPosition = true, getTangent = true) measure.getMatrix(7f, getPosition = true, getTangent = true)!!
) )
measure.setPath(path2, false) measure.setPath(path2, false)
assertCloseEnough(14.142136f, measure.length) assertCloseEnough(14.142136f, measure.length)
......
...@@ -37,7 +37,7 @@ class SvgTest { ...@@ -37,7 +37,7 @@ class SvgTest {
require(e.viewBox == null) require(e.viewBox == null)
require(e.tag == SVGTag.SVG) require(e.tag == SVGTag.SVG)
e.viewBox = Rect(0f, 1f, 100f, 200f) e.viewBox = Rect(0f, 1f, 100f, 200f)
assertCloseEnough(Rect(0f, 1f, 100f, 200f), e.viewBox) assertCloseEnough(Rect(0f, 1f, 100f, 200f), e.viewBox!!)
val aspectRatio = SVGPreserveAspectRatio(SVGPreserveAspectRatioAlign.XMIN_YMIN, SVGPreserveAspectRatioScale.MEET) val aspectRatio = SVGPreserveAspectRatio(SVGPreserveAspectRatioAlign.XMIN_YMIN, SVGPreserveAspectRatioScale.MEET)
e.preserveAspectRatio = aspectRatio e.preserveAspectRatio = aspectRatio
assertEquals(aspectRatio, e.preserveAspectRatio) assertEquals(aspectRatio, e.preserveAspectRatio)
......
...@@ -66,7 +66,7 @@ class TextBlobTest { ...@@ -66,7 +66,7 @@ class TextBlobTest {
102.99094f, 132.33693f, 134.25397f, 141.45454f, 158.58522f, 173.29857f, 179.27502f, 212.21196f, 102.99094f, 132.33693f, 134.25397f, 141.45454f, 158.58522f, 173.29857f, 179.27502f, 212.21196f,
217.8335f, 229.33693f, 231.25397f 217.8335f, 229.33693f, 231.25397f
), ),
actual = textBlob.getIntercepts(lowerBound = 0f, upperBound = 1f), actual = textBlob.getIntercepts(lowerBound = 0f, upperBound = 1f)!!,
epsilon = eps epsilon = eps
) )
......
...@@ -4,58 +4,79 @@ import org.jetbrains.skia.Color4f ...@@ -4,58 +4,79 @@ import org.jetbrains.skia.Color4f
import org.jetbrains.skia.Matrix33 import org.jetbrains.skia.Matrix33
import org.jetbrains.skia.Point import org.jetbrains.skia.Point
import org.jetbrains.skia.Rect import org.jetbrains.skia.Rect
import org.jetbrains.skiko.KotlinBackend
import org.jetbrains.skiko.kotlinBackend
import kotlin.math.abs import kotlin.math.abs
import kotlin.test.assertNotNull
import kotlin.test.assertTrue import kotlin.test.assertTrue
private const val EPSILON = 0.00001f private val EPSILON = if (kotlinBackend == KotlinBackend.JS) 0.00001f else 0.00000001f
private inline fun Float.isCloseEnoughTo(b: Float, epsilon: Float) = abs(this - b) < epsilon
private inline fun Point.isCloseEnoughTo(b: Point, epsilon: Float) =
x.isCloseEnoughTo(b.x, epsilon) && y.isCloseEnoughTo(b.y, epsilon)
private inline fun Color4f.isCloseEnoughTo(otherColor: Color4f, epsilon: Float) =
r.isCloseEnoughTo(otherColor.r, epsilon) && g.isCloseEnoughTo(
otherColor.g,
epsilon
) && b.isCloseEnoughTo(otherColor.b, epsilon) && a.isCloseEnoughTo(otherColor.a, epsilon)
private inline fun Rect.isCloseEnoughTo(rect: Rect, epsilon: Float): Boolean =
left.isCloseEnoughTo(rect.left, epsilon) && right.isCloseEnoughTo(rect.right, epsilon)
&& top.isCloseEnoughTo(rect.top, epsilon) && bottom.isCloseEnoughTo(rect.bottom, epsilon)
internal fun assertCloseEnough(expected: Float, actual: Float, epsilon: Float = EPSILON) { internal fun assertCloseEnough(expected: Float, actual: Float, epsilon: Float = EPSILON) {
assertTrue(abs(expected - actual) < epsilon, message = "expected=$expected, actual=$actual, eps=$epsilon") assertTrue(expected.isCloseEnoughTo(actual, epsilon), message = "expected=$expected, actual=$actual, eps=$epsilon")
} }
internal fun assertCloseEnough(expected: Point, actual: Point?, epsilon: Float = EPSILON) { internal fun assertCloseEnough(expected: Point, actual: Point, epsilon: Float = EPSILON) {
assertCloseEnough(expected.x, actual!!.x, epsilon) assertTrue(expected.isCloseEnoughTo(actual, epsilon), message = "expected=$expected, actual=$actual, eps=$epsilon")
assertCloseEnough(expected.y, actual.y, epsilon)
} }
internal fun assertCloseEnough(expected: Matrix33, actual: Matrix33?, epsilon: Float = EPSILON) { internal fun assertCloseEnough(expected: Matrix33, actual: Matrix33, epsilon: Float = EPSILON) {
expected.mat.zip(actual!!.mat).forEach { (a, b) -> assertCloseEnough(a, b, epsilon) } assertTrue(
expected.mat.zip(actual.mat).all { (a, b) -> a.isCloseEnoughTo(b, epsilon) },
message = "expected=$expected, actual=$actual, eps=$epsilon"
)
} }
internal fun assertCloseEnough(expected: Color4f, actual: Color4f?, epsilon: Float = EPSILON) { internal fun assertCloseEnough(expected: Color4f, actual: Color4f, epsilon: Float = EPSILON) {
assertCloseEnough(expected.r, actual!!.r, epsilon) assertTrue(expected.isCloseEnoughTo(actual, epsilon), message = "expected=$expected, actual=$actual, eps=$epsilon")
assertCloseEnough(expected.g, actual.g, epsilon)
assertCloseEnough(expected.b, actual.b, epsilon)
assertCloseEnough(expected.a, actual.a, epsilon)
} }
internal fun assertCloseEnough(expected: Rect, actual: Rect?, epsilon: Float = EPSILON) { internal fun assertCloseEnough(expected: Rect, actual: Rect, epsilon: Float = EPSILON) {
assertCloseEnough(expected.left, actual!!.left, epsilon) assertTrue(expected.isCloseEnoughTo(actual, epsilon), message = "expected=$expected, actual=$actual, eps=$epsilon")
assertCloseEnough(expected.top, actual.top, epsilon)
assertCloseEnough(expected.right, actual.right, epsilon)
assertCloseEnough(expected.bottom, actual.bottom, epsilon)
} }
internal fun assertContentCloseEnough(expected: FloatArray, actual: FloatArray?, epsilon: Float = EPSILON) { private fun fail(message: String) {
if (actual == null) { throw AssertionError(message)
throw AssertionError("expected $expected, got null") }
}
internal fun <T> assertContentEquivalent(expected: Iterator<T>, actual: Iterator<T>, eq: (a: T, b: T) -> Boolean) {
var count = 0
for (i in expected.indices) { while (expected.hasNext() && actual.hasNext()) {
if (abs(expected[i] - actual[i]) > epsilon) { val a = expected.next()
throw AssertionError("results differ at index$i, expected ${expected[i]}, got ${actual[i]}") val b = actual.next()
if (!eq(a, b)) {
fail("results differ at index $count, expected $a, got $b")
} }
count++
} }
}
internal fun assertContentCloseEnough(expected: Array<Point>, actual: Array<Point>?, epsilon: Float = EPSILON) { if (expected.hasNext()) {
assertNotNull(actual) fail("expected $expected has more items than actual $actual (which has $count)")
for (i in expected.indices) {
try {
assertCloseEnough(expected[i], actual[i], epsilon)
} catch (e: AssertionError) {
throw AssertionError("results differ at index $i, ${e.message}")
} }
if (actual.hasNext()) {
fail("actual $actual has more items than actual $expected (which has $count)")
} }
} }
internal fun assertContentCloseEnough(expected: FloatArray, actual: FloatArray, epsilon: Float = EPSILON) {
assertContentEquivalent(expected.iterator(), actual.iterator()) { a, b -> a.isCloseEnoughTo(b, epsilon) }
}
internal fun assertContentCloseEnough(expected: Array<Point>, actual: Array<Point>, epsilon: Float = EPSILON) {
assertContentEquivalent(expected.iterator(), actual.iterator()) { a, b -> a.isCloseEnoughTo(b, epsilon) }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment