Skip to content

Commit

Permalink
Add tests, testrunner and gradle task run-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
karlll committed Nov 27, 2021
1 parent ce11460 commit 0730b81
Show file tree
Hide file tree
Showing 16 changed files with 949 additions and 8 deletions.
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,15 @@
# krisp
A Lisp in Kotlin

A Lisp in Kotlin

## Build

$ gradle build

## Start (REPL)

$ bin/krisp-repl.sh

## Run tests

$ gradle run-tests
4 changes: 4 additions & 0 deletions bin/krisp-repl.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"

java -jar "${SCRIPT_DIR}/../build/libs/krisp-0.0.1-SNAPSHOT.jar"

8 changes: 7 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {
}

group = "com.ninjacontrol"
version = "1.0-SNAPSHOT"
version = "0.0.1-SNAPSHOT"

repositories {
mavenCentral()
Expand All @@ -25,3 +25,9 @@ tasks.withType<Jar> {
from(zipTree(file.absoluteFile)).duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
}

task<JavaExec>("run-tests") {
dependsOn("testClasses")
mainClass.set("com.ninjacontrol.krisp.TestRunnerKt")
classpath = sourceSets["test"].runtimeClasspath
}
9 changes: 3 additions & 6 deletions src/main/kotlin/com/ninjacontrol/krisp/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ fun evaluateFileAndExit(file: String) {
fun start(
file: String? = null,
withInit: Boolean = true,
runTests: Boolean = false,
args: Array<String>?
) {
args?.let {
Expand All @@ -63,7 +62,6 @@ fun start(
}
when {
file != null -> evaluateFileAndExit(file)
runTests -> Unit // TODO: start test: `runSuite()`
else -> {
banner()
mainLoop()
Expand All @@ -73,7 +71,8 @@ fun start(

fun banner() {

val bannerExpression = """(println (str "Mal [" *host-language* "]"))"""
val versionString = "0.0.1"
val bannerExpression = "(println \"krisp v$versionString \")"

try {
rep(bannerExpression, replExecutionEnv)
Expand All @@ -90,17 +89,15 @@ fun printHelp() {
out("")
out("options:")
out("--skipInit\t\t\tDo not run init")
out("--runTests\t\t\tRun tests and quit")
out("--help|-h\t\t\t\tPrint help and quit")
}

fun main(args: Array<String>) {
val file = args.getOrNull(0)?.let { if (it.startsWith("-")) null else it }
val withInit = !args.contains("--skipInit")
val runTests = args.contains("--runTests")
val printHelp = args.contains("--help") || args.contains("-h")
when {
printHelp -> printHelp()
else -> start(file, withInit, runTests, args)
else -> start(file, withInit, args)
}
}
32 changes: 32 additions & 0 deletions src/test/kotlin/com/ninjacontrol/krisp/AllTests.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.ninjacontrol.krisp

class AllTests : TestSuite {

override val name = "All tests"

private val testSuites = listOf(
EnvironmentTest(),
NamespaceTest(),
StringTest(),
EvaluationTest(),
FunctionsTest(),
QuoteTest(),
MacroTest(),
MetadataTest()
)

override fun getTests() = testSuites.flatMap { testSuite -> testSuite.getTests() }

override fun run(): Boolean {
val only = getTests().filter { it.only }
val suite = when {
only.isNotEmpty() -> listOf(CustomSuite(testCases = only))
else -> testSuites
}
return suite.map { testSuite ->
log(testSuite.name)
testSuite.run()
}
.reduce { acc, result -> acc && result }
}
}
79 changes: 79 additions & 0 deletions src/test/kotlin/com/ninjacontrol/krisp/Assertions.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.ninjacontrol.krisp

class AssertionException(message: String, context: String? = null) :
Throwable(context?.let { "$context: $message" } ?: message)

fun assertNeverExecuted() {
throw AssertionException("assertion failed, should never execute!")
}

fun fail(message: String) {
throw AssertionException("test failed: $message")
}

fun assertTrue(a: Boolean, context: String? = null) {
if (!a) throw AssertionException(
"assertion failed, value is false",
context
)
}

fun assertFalse(a: Boolean, context: String? = null) {
if (a) throw AssertionException(
"assertion failed, value is true",
context
)
}

fun assertNotNull(a: Any?, context: String? = null) {
if (a == null) throw AssertionException("assertion failed, value is null", context)
}

fun assertNull(a: Any?, context: String? = null) {
if (a != null) throw AssertionException("assertion failed, value is not null", context)
}

fun assertNil(a: MalType, context: String? = null) {
if (a !is MalNil) throw AssertionException("assertion failed, $a is not NIL", context)
}

fun assertError(a: MalType, context: String? = null) {
if (a !is MalError) throw AssertionException("assertion failed, $a is not an error", context)
}

fun assertNonError(a: MalType, context: String? = null) {
if (a is MalError) throw AssertionException("assertion failed, $a is an error", context)
}

fun assertEqual(a: String, b: String, context: String? = null) {
if (a != b) throw AssertionException("assertion failed, \"$a\" is not equal to \"$b\"", context)
}

fun assertEqual(a: Int, b: Int, context: String? = null) {
if (a != b) throw AssertionException("assertion failed, $a is not equal to $b", context)
}

fun assertEqual(a: Char, b: Char, context: String? = null) {
if (a != b) throw AssertionException("assertion failed, '$a' is not equal to '$b'", context)
}

fun assertEqual(a: MalType, b: MalType, context: String? = null) {
if (!isEqual(a, b)) throw AssertionException("assertion failed, $a is not equal to $b", context)
}

fun assertReadEval(
input: String,
result: MalType,
env: Environment = replExecutionEnv,
context: String? = null
) {
val ast = re(input, env)
if (!isEqual(
ast,
result
)
) throw AssertionException(
"assertion failed, expected '$input' to result in $result, but was $ast instead",
context
)
}
164 changes: 164 additions & 0 deletions src/test/kotlin/com/ninjacontrol/krisp/EnvironmentTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package com.ninjacontrol.krisp

class EnvironmentTest : TestSuite {

override val name = "Environment"

private val tests = listOf(

test {
description = "Initialize environment"
verify = {
val env = Environment()
assertNotNull(env)
}
},
test {
description = "Initialize environment with bindings"
verify = {
val env = Environment.withBindings(
outer = null,
bindings = listOf(
symbol("foo"),
symbol("bar"),
symbol("baz")
),
expressions = listOf(
symbol("xux"),
symbol("bug"),
symbol("xug")
)
)
assertEqual(env.get(symbol("foo")), symbol("xux"))
assertEqual(env.get(symbol("bar")), symbol("bug"))
assertEqual(env.get(symbol("baz")), symbol("xug"))
}
},
test {
description =
"Initialize environment with variadic parameters, 2 bindings, 3 expressions"
verify = {
val env = Environment.withBindings(
outer = null,
bindings = listOf(
symbol("foo"),
symbol("&"),
symbol("baz")
),
expressions = listOf(
symbol("xux"),
symbol("bug"),
symbol("xug")
)
)
assertNotNull(env)
assertEqual(env.get(symbol("foo")), symbol("xux"))
assertEqual(env.get(symbol("baz")), list(symbol("bug"), symbol("xug")))
}
},
test {
description =
"Initialize environment with variadic parameters, 2 bindings, 2 expressions"
verify = {
val env = Environment.withBindings(
outer = null,
bindings = listOf(
symbol("foo"),
symbol("&"),
symbol("baz")
),
expressions = listOf(
symbol("xux"),
symbol("xug")
)
)
assertNotNull(env)
assertEqual(env.get(symbol("foo")), symbol("xux"))
assertEqual(env.get(symbol("baz")), list(symbol("xug")))
}
},
test {
description =
"Initialize environment with variadic parameters, 5 bindings, 12 expressions"
verify = {
val env = Environment.withBindings(
outer = null,
bindings = listOf(
symbol("a"),
symbol("b"),
symbol("c"),
symbol("d"),
symbol("&"),
symbol("e"),
),
expressions = listOf(
symbol("a1"),
symbol("b1"),
symbol("c1"),
symbol("d1"),
symbol("e1"),
symbol("e2"),
symbol("e3"),
symbol("e4"),
symbol("e5"),
symbol("e6"),
symbol("e7"),
symbol("e8"),
)
)
assertNotNull(env)
assertEqual(env.get(symbol("a")), symbol("a1"))
assertEqual(env.get(symbol("b")), symbol("b1"))
assertEqual(env.get(symbol("c")), symbol("c1"))
assertEqual(env.get(symbol("d")), symbol("d1"))
assertEqual(
env.get(symbol("e")),
list(
symbol("e1"),
symbol("e2"),
symbol("e3"),
symbol("e4"),
symbol("e5"),
symbol("e6"),
symbol("e7"),
symbol("e8"),
)
)
}
},
test {
description = "Add symbol"
verify = {
val env = Environment()
val foo = symbol("foo")
val bar = symbol("bar")
env.set(foo, bar)
assertEqual(env.get(foo), bar)
}
},
test {
description = "Find symbol in environment, symbol found"
verify = {
val env = Environment()
val foo = symbol("foo")
env.set(foo, foo)
env.find(foo)
assertTrue(env.find(foo) == env)
}
},
test {
description = "Find symbol in environment, symbol not found"
verify = {
val env = Environment()
val foo = symbol("foo")
env.find(foo)
assertNull(env.find(foo))
}
},

)

override fun getTests(): List<TestCase> = tests
override fun run(): Boolean =
verifyTests(tests)
}
Loading

0 comments on commit 0730b81

Please sign in to comment.