Snippets

Leonid Kozarin Test runner and DSL to check LD schemas

Created by Leonid Kozarin last modified
import State.*

val openingFunc: LD = {
    val x = !max * !closeButtonPressed * !somethingUnderBarrier
    
    line { !opening * openButtonPressed * x } +
    line { opening * !closing * x }
}

val closingFunc: LD = {
    // alternative syntax
    val x = line(!min, !openButtonPressed, !somethingUnderBarrier)
    
    line(!closing, closeButtonPressed, x)
    .line(!opening, closing, x)
}

val cases = mapOf(
    Input(min = true)                                            to STOPPED,    // closed
    Input(min = true, closeButtonPressed = true)                 to STOPPED,    // closed + close button
    Input(min = true, openButtonPressed = true)                  to OPENING,    // closed + open button
    Input(opening = true, min = true)                            to OPENING,    // started opening
    Input(opening = true, min = true, openButtonPressed = true)  to OPENING,    // started opening + open button
    Input(opening = true, min = true, closeButtonPressed = true) to STOPPED,    // started opening + close button
    Input(opening = true)                                        to OPENING,    // opening
    Input(opening = true, openButtonPressed = true)              to OPENING,    // opening + open button
    Input(opening = true, closeButtonPressed = true)             to CLOSING,    // opening + close button
    Input(opening = true, max = true)                            to STOPPED,    // almost opened
    Input(opening = true, max = true, openButtonPressed = true)  to STOPPED,    // almost opened + open button
    Input(opening = true, max = true, closeButtonPressed = true) to CLOSING,    // almost opened + close button
    Input(max = true)                                            to STOPPED,    // opened
    Input(max = true, openButtonPressed = true)                  to STOPPED,    // opened + open button
    Input(max = true, closeButtonPressed = true)                 to CLOSING,    // opened + close button
    Input(closing = true, max = true)                            to CLOSING,    // started closing
    Input(closing = true, max = true, closeButtonPressed = true) to CLOSING,    // started closing + close button
    Input(closing = true, max = true, openButtonPressed = true)  to STOPPED,    // started closing + open button
    Input(closing = true)                                        to CLOSING,    // closing
    Input(closing = true, closeButtonPressed = true)             to CLOSING,    // closing + close button
    Input(closing = true, openButtonPressed = true)              to OPENING,    // closing + open button
    Input(closing = true, min = true)                            to STOPPED,    // almost closed
    Input(closing = true, min = true, closeButtonPressed = true) to STOPPED,    // almost closed + close button
    Input(closing = true, min = true, openButtonPressed = true)  to OPENING,    // almost closed + open button
    Input(openButtonPressed = true)                              to OPENING,    // stopped + open button
    Input(closeButtonPressed = true)                             to CLOSING,    // stopped + close button
    Input(somethingUnderBarrier = true)                          to STOPPED,    // stop if something under the barrier
    // corner cases
    Input(openButtonPressed = true, closeButtonPressed = true)   to STOPPED,
    Input(opening = true, closing = true)                        to STOPPED,
    Input(min = true, max = true)                                to STOPPED
)

fun main(args: Array<String>) = test(openingFunc, closingFunc, cases)
enum class State(val opening: Boolean, val closing: Boolean) {
    OPENING(true, false),
    CLOSING(false, true),
    STOPPED(false, false),
    ERROR(true, true)
}

fun getState(opening: Boolean, closing: Boolean) = when {
    opening && !closing -> State.OPENING
    !opening && closing -> State.CLOSING
    !opening && !closing -> State.STOPPED
    else -> State.ERROR
}
fun Boolean.line(vararg vars: Boolean) = this || vars.reduce { acc, v -> acc && v }

fun Boolean.line(func: () -> Boolean) = this || func()

fun line(vararg vars: Boolean) = vars.reduce { acc, v -> acc && v }

fun line(func: () -> Boolean) = func()

operator fun Boolean.times(other: Boolean) = this && other

operator fun Boolean.plus(other: Boolean) = this || other
data class Input(
	val opening: Boolean = false,
	val closing: Boolean = false,
	val min: Boolean = false,
	val max: Boolean = false,
	val openButtonPressed: Boolean = false,
	val closeButtonPressed: Boolean = false,
	val somethingUnderBarrier: Boolean = false
)

typealias LD = Input.() -> Boolean

fun test(openingFunc: LD, closingFunc: LD, cases: Map<Input, State>) {
    for ((input, expectedState) in cases) {
        val actualState = getState(openingFunc(input), closingFunc(input))
        if (actualState == expectedState) {
            println("PASSED ($input)")
        } else {
            println("FAILED ($input)")
            println("Expected: $expectedState")
            println("Actual state: $actualState")
        }
    }
}

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.