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 {
fun getPosition() = runTest {
Path().moveTo(0f, 10f).lineTo(20f, 0f).moveTo(0f, 40f).lineTo(30f, 50f).use { path ->
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 {
PathMeasure(path, false).use { measure ->
Path().lineTo(10f, 10f).use { path2 ->
assertEquals(40f, measure.length)
assertCloseEnough(Point(0f, 0f), measure.getPosition(0f))
assertCloseEnough(Point(1f, 0f), measure.getTangent(0f))
assertCloseEnough(Point(20f, 0f), measure.getPosition(20f))
assertCloseEnough(Point(1f, 0f), measure.getTangent(20f))
assertCloseEnough(Point(0f, 0f), measure.getPosition(0f)!!)
assertCloseEnough(Point(1f, 0f), measure.getTangent(0f)!!)
assertCloseEnough(Point(20f, 0f), measure.getPosition(20f)!!)
assertCloseEnough(Point(1f, 0f), measure.getTangent(20f)!!)
assertEquals(false, measure.isClosed)
assertCloseEnough(
Matrix33.makeTranslate(20f, 0f), measure.getMatrix(
20f,
getPosition = true,
getTangent = false
)
)!!
)
assertCloseEnough(
Matrix33.makeRotate(0f), measure.getMatrix(
20f,
getPosition = false,
getTangent = true
)
)!!
)
assertCloseEnough(
Matrix33.makeTranslate(20f, 0f).makeConcat(Matrix33.makeRotate(0f)),
measure.getMatrix(20f, getPosition = true, getTangent = true)
measure.getMatrix(20f, getPosition = true, getTangent = true)!!
)
measure.nextContour()
assertCloseEnough(14.14213f, measure.length)
assertCloseEnough(Point(0f, 40f), measure.getPosition(0f))
assertCloseEnough(Point(0.70710677f, 0.70710677f), measure.getTangent(0f))
assertCloseEnough(Point(4.949747f, 44.949745f), measure.getPosition(7f))
assertCloseEnough(Point(0.70710677f, 0.70710677f), measure.getTangent(7f))
assertCloseEnough(Point(0f, 40f), measure.getPosition(0f)!!)
assertCloseEnough(Point(0.70710677f, 0.70710677f), measure.getTangent(0f)!!)
assertCloseEnough(Point(4.949747f, 44.949745f), measure.getPosition(7f)!!)
assertCloseEnough(Point(0.70710677f, 0.70710677f), measure.getTangent(7f)!!)
assertCloseEnough(
Matrix33.makeTranslate(4.949747f, 44.949745f), measure.getMatrix(
7f,
getPosition = true,
getTangent = false
)
)!!
)
assertCloseEnough(
Matrix33.makeRotate(45f), measure.getMatrix(
7f,
getPosition = false,
getTangent = true
)
)!!
)
assertCloseEnough(
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)
assertCloseEnough(14.142136f, measure.length)
......
......@@ -37,7 +37,7 @@ class SvgTest {
require(e.viewBox == null)
require(e.tag == SVGTag.SVG)
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)
e.preserveAspectRatio = aspectRatio
assertEquals(aspectRatio, e.preserveAspectRatio)
......
......@@ -66,7 +66,7 @@ class TextBlobTest {
102.99094f, 132.33693f, 134.25397f, 141.45454f, 158.58522f, 173.29857f, 179.27502f, 212.21196f,
217.8335f, 229.33693f, 231.25397f
),
actual = textBlob.getIntercepts(lowerBound = 0f, upperBound = 1f),
actual = textBlob.getIntercepts(lowerBound = 0f, upperBound = 1f)!!,
epsilon = eps
)
......
......@@ -4,58 +4,79 @@ import org.jetbrains.skia.Color4f
import org.jetbrains.skia.Matrix33
import org.jetbrains.skia.Point
import org.jetbrains.skia.Rect
import org.jetbrains.skiko.KotlinBackend
import org.jetbrains.skiko.kotlinBackend
import kotlin.math.abs
import kotlin.test.assertNotNull
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) {
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) {
assertCloseEnough(expected.x, actual!!.x, epsilon)
assertCloseEnough(expected.y, actual.y, epsilon)
internal fun assertCloseEnough(expected: Point, actual: Point, epsilon: Float = EPSILON) {
assertTrue(expected.isCloseEnoughTo(actual, epsilon), message = "expected=$expected, actual=$actual, eps=$epsilon")
}
internal fun assertCloseEnough(expected: Matrix33, actual: Matrix33?, epsilon: Float = EPSILON) {
expected.mat.zip(actual!!.mat).forEach { (a, b) -> assertCloseEnough(a, b, epsilon) }
internal fun assertCloseEnough(expected: Matrix33, actual: Matrix33, epsilon: Float = 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) {
assertCloseEnough(expected.r, actual!!.r, epsilon)
assertCloseEnough(expected.g, actual.g, epsilon)
assertCloseEnough(expected.b, actual.b, epsilon)
assertCloseEnough(expected.a, actual.a, epsilon)
internal fun assertCloseEnough(expected: Color4f, actual: Color4f, epsilon: Float = EPSILON) {
assertTrue(expected.isCloseEnoughTo(actual, epsilon), message = "expected=$expected, actual=$actual, eps=$epsilon")
}
internal fun assertCloseEnough(expected: Rect, actual: Rect?, epsilon: Float = EPSILON) {
assertCloseEnough(expected.left, actual!!.left, epsilon)
assertCloseEnough(expected.top, actual.top, epsilon)
assertCloseEnough(expected.right, actual.right, epsilon)
assertCloseEnough(expected.bottom, actual.bottom, epsilon)
internal fun assertCloseEnough(expected: Rect, actual: Rect, epsilon: Float = EPSILON) {
assertTrue(expected.isCloseEnoughTo(actual, epsilon), message = "expected=$expected, actual=$actual, eps=$epsilon")
}
internal fun assertContentCloseEnough(expected: FloatArray, actual: FloatArray?, epsilon: Float = EPSILON) {
if (actual == null) {
throw AssertionError("expected $expected, got null")
}
private fun fail(message: String) {
throw AssertionError(message)
}
internal fun <T> assertContentEquivalent(expected: Iterator<T>, actual: Iterator<T>, eq: (a: T, b: T) -> Boolean) {
var count = 0
for (i in expected.indices) {
if (abs(expected[i] - actual[i]) > epsilon) {
throw AssertionError("results differ at index$i, expected ${expected[i]}, got ${actual[i]}")
while (expected.hasNext() && actual.hasNext()) {
val a = expected.next()
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) {
assertNotNull(actual)
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 (expected.hasNext()) {
fail("expected $expected has more items than actual $actual (which has $count)")
}
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