From e0fbce008737d4ec3bb81ec7cc381cc24d5bebc7 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 21 Sep 2022 02:59:36 +0200 Subject: [PATCH] few more unittests for IR --- docs/source/todo.rst | 1 - intermediate/test/TestIRFileInOut.kt | 113 ++++++++++++++++++++++++++ intermediate/test/TestInstructions.kt | 1 + virtualmachine/test/TestVm.kt | 52 ++++++++++++ 4 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 intermediate/test/TestIRFileInOut.kt create mode 100644 virtualmachine/test/TestVm.kt diff --git a/docs/source/todo.rst b/docs/source/todo.rst index ccfeb8de7..86b3159bf 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,6 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- IR/VM: improve unit tests - write some documentation about the compiler architecture and where to plug a code generator onto. - vm: implement remaining sin/cos functions in virtual/math.p8 and merge tables diff --git a/intermediate/test/TestIRFileInOut.kt b/intermediate/test/TestIRFileInOut.kt new file mode 100644 index 000000000..d5835c2da --- /dev/null +++ b/intermediate/test/TestIRFileInOut.kt @@ -0,0 +1,113 @@ +import io.kotest.core.spec.style.FunSpec +import io.kotest.matchers.ints.shouldBeGreaterThan +import io.kotest.matchers.shouldBe +import io.kotest.matchers.types.instanceOf +import prog8.code.StStaticVariable +import prog8.code.SymbolTable +import prog8.code.core.CbmPrgLauncherType +import prog8.code.core.CompilationOptions +import prog8.code.core.OutputType +import prog8.code.core.ZeropageType +import prog8.code.target.Cx16Target +import prog8.intermediate.IRFileReader +import prog8.intermediate.IRFileWriter +import prog8.intermediate.IRProgram +import java.nio.file.Path +import kotlin.io.path.deleteExisting +import kotlin.io.path.name +import kotlin.io.path.readLines +import kotlin.io.path.writeText + +class TestIRFileInOut: FunSpec({ + test("test IR writer") { + val st = SymbolTable() + val target = Cx16Target() + val tempdir = Path.of(System.getProperty("java.io.tmpdir")) + val options = CompilationOptions( + OutputType.RAW, + CbmPrgLauncherType.NONE, + ZeropageType.DONTUSE, + emptyList(), + floats = false, + noSysInit = true, + compTarget = target, + loadAddress = target.machine.PROGRAM_LOAD_ADDRESS, + outputDir = tempdir + ) + val program = IRProgram("unittest-irwriter", st, options, target) + val writer = IRFileWriter(program) + writer.writeFile() + val generatedFile = tempdir.resolve("unittest-irwriter.p8ir") + val lines = generatedFile.readLines() + lines.first() shouldBe "" + lines.last() shouldBe "" + generatedFile.deleteExisting() + lines.size shouldBeGreaterThan 20 + } + + test("test IR reader") { + val source=""" + +compTarget=virtual +output=PRG +launcher=BASIC +zeropage=KERNALSAFE +loadAddress=0 +dontReinitGlobals=false +evalStackBaseAddress=null + + + +uword sys.wait.jiffies=0 zp=DONTCARE + + + +&uword cx16.r0=65282 + + + + + + + +load.b r1,42 + + + + + + + + +return + + + + + + + +uword sys.wait.jiffies + + + loadm.w r0,sys.wait.jiffies + syscall 13 + + +return + + + + +""" + val tempfile = kotlin.io.path.createTempFile(suffix = ".p8ir") + tempfile.writeText(source) + val filepart = tempfile.name.dropLast(5) + val reader = IRFileReader(tempfile.parent, filepart) + val program = reader.readFile() + tempfile.deleteExisting() + program.name shouldBe "test-ir-reader" + program.blocks.size shouldBe 2 + program.st.lookup("sys.wait.jiffies") shouldBe instanceOf() + } +}) \ No newline at end of file diff --git a/intermediate/test/TestInstructions.kt b/intermediate/test/TestInstructions.kt index a3f3b5313..814fb154e 100644 --- a/intermediate/test/TestInstructions.kt +++ b/intermediate/test/TestInstructions.kt @@ -2,6 +2,7 @@ import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe +import org.junit.jupiter.api.fail import prog8.intermediate.* diff --git a/virtualmachine/test/TestVm.kt b/virtualmachine/test/TestVm.kt new file mode 100644 index 000000000..f0fa3e0c0 --- /dev/null +++ b/virtualmachine/test/TestVm.kt @@ -0,0 +1,52 @@ +import io.kotest.core.spec.style.FunSpec +import io.kotest.matchers.collections.shouldBeEmpty +import io.kotest.matchers.shouldBe +import prog8.intermediate.Instruction +import prog8.intermediate.Opcode +import prog8.intermediate.VmDataType +import prog8.vm.Memory +import prog8.vm.VirtualMachine +import prog8.vm.VmRunner + +class TestVm: FunSpec( { + test("vm execution: empty program") { + val memory = Memory() + val vm = VirtualMachine(memory, emptyList(), 0xff00) + vm.callStack.shouldBeEmpty() + vm.valueStack.shouldBeEmpty() + vm.pc shouldBe 0 + vm.stepCount shouldBe 0 + vm.run(throttle = false) + vm.callStack.shouldBeEmpty() + vm.valueStack.shouldBeEmpty() + vm.pc shouldBe 0 + vm.stepCount shouldBe 1 + } + + test("vm execution: modify memory") { + val memory = Memory() + val program = listOf( + Instruction(Opcode.LOAD, VmDataType.WORD, reg1=1, value=12345), + Instruction(Opcode.STOREM, VmDataType.WORD, reg1=1, value=1000), + Instruction(Opcode.RETURN) + ) + val vm = VirtualMachine(memory, program, 0xff00) + + memory.getUW(1000) shouldBe 0u + vm.callStack.shouldBeEmpty() + vm.valueStack.shouldBeEmpty() + vm.pc shouldBe 0 + vm.stepCount shouldBe 0 + vm.run(throttle = false) + memory.getUW(1000) shouldBe 12345u + vm.callStack.shouldBeEmpty() + vm.valueStack.shouldBeEmpty() + vm.pc shouldBe 2 + vm.stepCount shouldBe 3 + } + + test("vmrunner") { + val runner = VmRunner() + runner.runProgram(";comment\n------PROGRAM------\n;comment\n", false) + } +})