141 lines
4.1 KiB
Kotlin
141 lines
4.1 KiB
Kotlin
import kotlinx.coroutines.runBlocking
|
|
import net.sergeych.lyng.PerfFlags
|
|
import net.sergeych.lyng.Scope
|
|
import net.sergeych.lyng.obj.ObjBool
|
|
import net.sergeych.lyng.obj.ObjInt
|
|
import net.sergeych.lyng.obj.ObjList
|
|
import kotlin.test.Test
|
|
import kotlin.test.assertEquals
|
|
|
|
/**
|
|
* JVM-only fast functional subset additions. Keep each test quick (< ~1s) and deterministic.
|
|
*/
|
|
class ScriptSubsetJvmTest_Additions3 {
|
|
private suspend fun evalInt(code: String): Long = (Scope().eval(code) as ObjInt).value
|
|
private suspend fun evalBool(code: String): Boolean = (Scope().eval(code) as ObjBool).value
|
|
private suspend fun evalList(code: String): List<Any?> = (Scope().eval(code) as ObjList).list.map { (it as? ObjInt)?.value ?: it }
|
|
|
|
@Test
|
|
fun controlFlow_when_and_ifElse_jvm_only() = runBlocking {
|
|
val code = """
|
|
fun classify(x) {
|
|
when(x) {
|
|
0 -> 100
|
|
1 -> 200
|
|
else -> 300
|
|
}
|
|
}
|
|
val a = classify(0)
|
|
val b = classify(1)
|
|
val c = classify(5)
|
|
if (true) 1 else 2
|
|
a + b + c
|
|
""".trimIndent()
|
|
val r = evalInt(code)
|
|
// 100 + 200 + 300 = 600
|
|
assertEquals(600L, r)
|
|
}
|
|
|
|
@Test
|
|
fun optionals_chain_field_index_method_jvm_only() = runBlocking {
|
|
val code = """
|
|
class Box() {
|
|
var xs = [10,20,30]
|
|
fun get(i) { xs[i] }
|
|
}
|
|
val maybe = null
|
|
val b = Box()
|
|
// optional on null yields null
|
|
val r1 = maybe?.xs
|
|
// optional on non-null: method and index
|
|
val r2 = b?.get(1)
|
|
r2
|
|
""".trimIndent()
|
|
val r = evalInt(code)
|
|
assertEquals(20L, r)
|
|
}
|
|
|
|
@Test
|
|
fun exceptions_try_catch_finally_jvm_only() = runBlocking {
|
|
val code = """
|
|
fun risky(x) { if (x == 0) throw "boom" else 7 }
|
|
var s = 0
|
|
try { s = risky(0) } catch (e) { s = 1 } finally { s = s + 2 }
|
|
s
|
|
""".trimIndent()
|
|
val r = evalInt(code)
|
|
// catch sets 1, finally adds 2 -> 3
|
|
assertEquals(3L, r)
|
|
}
|
|
|
|
@Test
|
|
fun classes_visibility_and_fields_jvm_only() = runBlocking {
|
|
val code = """
|
|
class C() {
|
|
var pub = 1
|
|
private var hidden = 9
|
|
fun getPub() { pub }
|
|
fun getHidden() { hidden }
|
|
fun setPub(v) { pub = v }
|
|
}
|
|
val c = C()
|
|
c.setPub(5)
|
|
c.getPub() + c.getHidden()
|
|
""".trimIndent()
|
|
val r = evalInt(code)
|
|
// 5 + 9
|
|
assertEquals(14L, r)
|
|
}
|
|
|
|
@Test
|
|
fun collections_insert_remove_and_maps_jvm_only() = runBlocking {
|
|
val code = """
|
|
val lst = []
|
|
lst.insertAt(0, 2)
|
|
lst.insertAt(0, 1)
|
|
lst.removeAt(1)
|
|
// now [1]
|
|
val a = 10
|
|
val b = 20
|
|
a + b + lst[0]
|
|
""".trimIndent()
|
|
val r = evalInt(code)
|
|
assertEquals(31L, r)
|
|
}
|
|
|
|
@Test
|
|
fun loops_for_and_while_basics_jvm_only() = runBlocking {
|
|
val n = 2000
|
|
val code = """
|
|
var s = 0
|
|
for (i in 0..$n) { s = s + 1 }
|
|
var j = 0
|
|
while (j < $n) { s = s + 1; j = j + 1 }
|
|
s
|
|
""".trimIndent()
|
|
val r = evalInt(code)
|
|
// for loop adds n+1, while adds n -> total 2n+1
|
|
assertEquals((2L*n + 1L), r)
|
|
}
|
|
|
|
@Test
|
|
fun pooling_edgecase_captures_and_exception_jvm_only() = runBlocking {
|
|
// Ensure pooling ON for this test, then restore default
|
|
val prev = PerfFlags.SCOPE_POOL
|
|
try {
|
|
PerfFlags.SCOPE_POOL = true
|
|
val code = """
|
|
fun outer(a) {
|
|
fun inner(b) { if (b == 0) throw "err" else a + b }
|
|
try { inner(0) } catch (e) { a + 2 }
|
|
}
|
|
outer(5)
|
|
""".trimIndent()
|
|
val r = evalInt(code)
|
|
assertEquals(7L, r)
|
|
} finally {
|
|
PerfFlags.SCOPE_POOL = prev
|
|
}
|
|
}
|
|
}
|