All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.io.data2viz.test.matchers.Matchers.kt Maven / Gradle / Ivy

/*
 * Copyright (c) 2018-2021. data2viz sàrl.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package io.data2viz.test.matchers


interface Keyword

object have : Keyword

object be : Keyword

object end : Keyword

object start : Keyword

object contain : Keyword

object include : Keyword

val epsilon = 1e-6


interface Matchers : StringMatchers,
        CollectionMatchers,
        DoubleMatchers,
        IntMatchers,
        LongMatchers,
        MapMatchers,
        TypeMatchers {

    fun fail(msg: String): Nothing = throw AssertionError(msg)

    infix fun Double.shouldBe(other: Double): Unit = ToleranceMatcher(other, 0.0).test(this)
    infix fun Double.shouldBeClose(other: Double): Unit = ToleranceMatcher(other, epsilon).test(this)
    infix fun Float.shouldBeClose(other: Float): Unit = ToleranceMatcher(other.toDouble(), epsilon).test(this.toDouble())

    infix fun Array?.shouldBe(other: Array?) {
        if (this == null) {
            if (other != null) throw AssertionError("$this did not equal $other")
            return
        }
        if (other == null) throw AssertionError("$this did not equal $other")

        this.size shouldBe other.size
        this.forEachIndexed { index, doubleA ->
            val doubleB = other[index]
            doubleA shouldBe doubleB
        }
    }

    infix fun Array.shouldBe(other: Array) = this.shouldBeClose(other)
    infix fun Array.shouldBeClose(other: Array) {
        this.size shouldBe other.size
        this.forEachIndexed { index, doubleA ->
            val doubleB = other[index]
            doubleA shouldBeClose doubleB
        }
    }

    infix fun DoubleArray.shouldBe(other: DoubleArray) {
        this.size shouldBe other.size
        this.forEachIndexed { index, doubleA ->
            val doubleB = other[index]
            doubleA shouldBe doubleB
        }
    }
    infix fun DoubleArray.shouldBeClose(other: DoubleArray) {
        this.size shouldBe other.size
        this.forEachIndexed { index, doubleA ->
            val doubleB = other[index]
            doubleA shouldBeClose doubleB
        }
    }

    infix fun   Iterable.shouldBe(other: Iterable) {
        if(this.count() != other.count())
            throw AssertionError("$this doesn't have the same size as $other" )
        this.zip(other).forEach {
            ToleranceMatcher(it.second.toDouble(), 1e-6).test(it.first.toDouble())
        }
    }
    infix fun  T.shouldBe(any: T?): Unit = shouldEqual(any)
    infix fun  T.shouldEqual(any: Any?) {
        if (this == any) return
        @Suppress("UNCHECKED_CAST")
        when (any) {
            is Matcher<*> -> (any as Matcher).test(this)
            else -> {
                if (this == null && any != null)
                    throw AssertionError("$this did not equal $any")
                if (this != null && any == null)
                    throw AssertionError("$this did not equal $any")
                if (this != any)
                    throw AssertionError("$this did not equal $any")
            }
        }
    }

    infix fun  T.should(matcher: (T) -> Unit): Unit = matcher(this)
    infix fun  T.should(matcher: Matcher) = matcher.test(this)
    infix fun  T.should(x: have): HaveWrapper = HaveWrapper(this)
    infix fun  T.should(x: start): StartWrapper = StartWrapper(this)
    infix fun  T.should(x: end): EndWrapper = EndWrapper(this)
    infix fun  T.should(x: be): BeWrapper = BeWrapper(this)
    infix fun  T.should(x: contain): ContainWrapper = ContainWrapper(this)
    infix fun  T.should(x: include): IncludeWrapper = IncludeWrapper(this)

}

interface Matcher {
    fun test(value: T)
}

class HaveWrapper(val value: T)
class BeWrapper(val value: T)
class StartWrapper(val value: T)
class EndWrapper(val value: T)
class IncludeWrapper(val value: T)
class ContainWrapper(val value: T)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy