anotther compiler inference bug andlyng.io.console improvements

This commit is contained in:
sergeych committed 2026-04-03 11:55:25 +03:00
1 parent caad7d8ab9
commit fd6d05d568
7 files changed
+389 -130

No files matched your search

@@ -22,16 +22,14 @@ import net.sergeych.lyng.ExecutionError
import net.sergeych.lyng.Scope
import net.sergeych.lyng.obj.ObjBool
import net.sergeych.lyng.obj.ObjIllegalOperationException
import net.sergeych.lyngio.console.*
import net.sergeych.lyngio.console.security.ConsoleAccessOp
import net.sergeych.lyngio.console.security.ConsoleAccessPolicy
import net.sergeych.lyngio.console.security.PermitAllConsoleAccessPolicy
import net.sergeych.lyngio.fs.security.AccessContext
import net.sergeych.lyngio.fs.security.AccessDecision
import net.sergeych.lyngio.fs.security.Decision
import kotlin.test.Test
import kotlin.test.assertFalse
import kotlin.test.assertIs
import kotlin.test.assertTrue
import kotlin.test.*
class LyngConsoleModuleTest {
@@ -112,4 +110,63 @@ class LyngConsoleModuleTest {
assertIs<ObjIllegalOperationException>(error.errorObject)
}
}
@Test
fun eventsIteratorRecoversAfterSourceFailure() = runBlocking {
val scope = newScope()
var eventsCalls = 0
val console = object : LyngConsole {
override val isSupported: Boolean = true
override suspend fun isTty(): Boolean = true
override suspend fun geometry(): ConsoleGeometry? = null
override suspend fun ansiLevel(): ConsoleAnsiLevel = ConsoleAnsiLevel.NONE
override suspend fun write(text: String) {}
override suspend fun flush() {}
override fun events(): ConsoleEventSource {
eventsCalls += 1
val callNo = eventsCalls
return object : ConsoleEventSource {
private var emitted = false
override suspend fun nextEvent(timeoutMs: Long): ConsoleEvent? {
if (emitted) return null
emitted = true
return when (callNo) {
1 -> throw IllegalStateException("synthetic source failure")
else -> ConsoleEvent.KeyDown(key = "x")
}
}
override suspend fun close() {}
}
}
override suspend fun setRawMode(enabled: Boolean): Boolean = enabled
}
assertTrue(createConsoleModule(PermitAllConsoleAccessPolicy, scope.importManager, console))
val result = scope.eval(
"""
import lyng.io.console
val it = Console.events().iterator()
assert(it.hasNext())
val ev = it.next()
assert(ev is ConsoleKeyEvent)
assert((ev as ConsoleKeyEvent).key == "x")
true
""".trimIndent()
)
assertIs<ObjBool>(result)
assertTrue(result.value)
assertEquals(2, eventsCalls)
}
}
@@ -0,0 +1,59 @@
/*
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
*
* 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 net.sergeych.lyngio.console
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
class JvmConsoleKeyDecoderTest {
private fun decode(vararg bytes: Int): ConsoleEvent.KeyDown {
var index = 1
return JvmConsoleKeyDecoder.decode(bytes[0]) { _ ->
if (index >= bytes.size) null else bytes[index++]
}
}
@Test
fun decodesArrowLeft() {
val ev = decode(27, '['.code, 'D'.code)
assertEquals("ArrowLeft", ev.key)
assertFalse(ev.ctrl)
assertFalse(ev.alt)
assertFalse(ev.shift)
}
@Test
fun decodesCtrlArrowRightModifier() {
val ev = decode(27, '['.code, '1'.code, ';'.code, '5'.code, 'C'.code)
assertEquals("ArrowRight", ev.key)
assertTrue(ev.ctrl)
assertFalse(ev.alt)
assertFalse(ev.shift)
}
@Test
fun decodesAltCharacter() {
val ev = decode(27, 'x'.code)
assertEquals("x", ev.key)
assertTrue(ev.alt)
assertFalse(ev.ctrl)
}
}