package prog8tests.compiler import io.kotest.common.ExperimentalKotest import io.kotest.core.spec.style.FunSpec import io.kotest.datatest.withData import io.kotest.engine.spec.tempdir import io.kotest.matchers.shouldNotBe import prog8.code.core.ICompilationTarget import prog8.code.target.C128Target import prog8.code.target.C64Target import prog8.code.target.Cx16Target import prog8.code.target.VMTarget import prog8.compiler.CompilationResult import prog8.compiler.CompilerArguments import prog8.compiler.compileProgram import prog8tests.helpers.assumeDirectory import prog8tests.helpers.cartesianProduct import prog8tests.helpers.workingDir import java.nio.file.Path import kotlin.io.path.exists /** * ATTENTION: this is just kludge! * They are not really unit tests, but rather tests of the whole process, * from source file loading all the way through to running 64tass. */ private val examplesDir = assumeDirectory(workingDir, "../examples") private fun compileTheThing(filepath: Path, optimize: Boolean, target: ICompilationTarget, outputDir: Path): CompilationResult? { val args = CompilerArguments( filepath, optimize, writeAssembly = true, warnSymbolShadowing = false, quietAll = true, quietAssembler = true, showTimings = false, asmListfile = false, includeSourcelines = false, experimentalCodegen = false, dumpVariables = false, dumpSymbols = false, varsHighBank = null, varsGolden = false, slabsHighBank = null, slabsGolden = false, compilationTarget = target.name, dontSplitWordArrays = false, breakpointCpuInstruction = null, printAst1 = false, printAst2 = false, ignoreFootguns = false, symbolDefs = emptyMap(), outputDir = outputDir ) return compileProgram(args) } private fun prepareTestFiles(source: String, optimize: Boolean, target: ICompilationTarget): Pair { val searchIn = mutableListOf(examplesDir) when (target) { is C64Target -> searchIn.add(0, assumeDirectory(examplesDir, "c64")) is Cx16Target -> searchIn.add(0, assumeDirectory(examplesDir, "cx16")) is VMTarget -> searchIn.add(0, assumeDirectory(examplesDir, "virtual")) is C128Target -> searchIn.add(0, assumeDirectory(examplesDir, "c128")) } val filepath = searchIn.asSequence() .map { it.resolve("$source.p8") } .map { it.normalize() } .map { workingDir.relativize(it) } .first { it.exists() } val displayName = "${examplesDir.relativize(filepath)}: ${target.name}, optimize=$optimize" return Pair(displayName, filepath) } class TestCompilerOnExamplesC64: FunSpec({ @OptIn(ExperimentalKotest::class) this.concurrency = 4 val outputDir = tempdir().toPath() val onlyC64 = cartesianProduct( listOf( "balloonflight", "banking", "bdmusic", "bdmusic-irq", "charset", "cube3d", "cube3d-sprites", "fileselector", "library/main", "plasma", "rasterbars", "sprites", "starfield", "tehtriz", "turtle-gfx", "wizzine", ), listOf(false, true) ) val target = C64Target() withData( nameFn = { it.second.first }, onlyC64.map { it to prepareTestFiles(it.first, it.second, target) } ) { (params, prep) -> val filepath = prep.second val optimize = params.second compileTheThing(filepath, optimize, target, outputDir) shouldNotBe null } }) class TestCompilerOnExamplesCx16: FunSpec({ @OptIn(ExperimentalKotest::class) this.concurrency = 4 val outputDir = tempdir().toPath() val onlyCx16 = cartesianProduct( listOf( "vtui/testvtui", "pcmaudio/play-adpcm", "pcmaudio/stream-wav", "pcmaudio/stream-simple-aflow", "pcmaudio/stream-simple-poll", "pcmaudio/vumeter", "sprites/dragon", "sprites/dragons", "zsmkit_v1/demo1", "zsmkit_v1/demo2", "zsmkit_v2/demo", "banking/program", "fileselector/standalone", "fileselector/main", "amiga", "audioroutines", "automatons", "balloonflight", "bdmusic", "bobs", "bubbleuniverse", "charsets", "circles", "cobramk3-gfx", "colorbars", "cube3d", "cxlogo", "diskspeed", "fileseek", "interpolation", "kefrenbars", "keyboardhandler", "landscape", "life", "mandelbrot", "multi-irq-old", "multi-irq-new", "plasma", "rasterbars", "showbmx", "snow", "sortingbench", "spotlight", "starszoom", "tehtriz", "test_gfx_lores", "test_gfx_hires", "testmonogfx", ), listOf(false, true) ) val target = Cx16Target() withData( nameFn = { it.second.first }, onlyCx16.map { it to prepareTestFiles(it.first, it.second, target) } ) { (params, prep) -> val filepath = prep.second val optimize = params.second compileTheThing(filepath, optimize, target, outputDir) shouldNotBe null } }) class TestCompilerOnExamplesBothC64andCx16: FunSpec({ @OptIn(ExperimentalKotest::class) this.concurrency = 4 val outputDir = tempdir().toPath() val bothCx16AndC64 = cartesianProduct( listOf( "animals", "balls", "cube3d", "cube3d-float", "cube3d-gfx", "dirlist", "fibonacci", "fractal-tree", "maze", "mandelbrot", "mandelbrot-gfx", "multitasking", "numbergame", "primes", "queens", "screencodes", "swirl", "swirl-float", "tehtriz", "textelite", ), listOf(false, true), listOf(C64Target(), Cx16Target()) ) withData( nameFn = { it.third.first }, bothCx16AndC64.map { Triple(it.second, it.third, prepareTestFiles(it.first, it.second, it.third)) } ) { params -> val filepath = params.third.second val optimize = params.first compileTheThing(filepath, optimize, params.second, outputDir) shouldNotBe null } }) class TestCompilerOnExamplesVirtual: FunSpec({ val outputDir = tempdir().toPath() val onlyVirtual = cartesianProduct( listOf( "bouncegfx", "bsieve", "pixelshader", "sincos", "pointers/animalgame", "pointers/binarytree", // TODO add to "c64" later as well "pointers/sortedlist" // TODO add to "c64" later as well ), listOf(false, true) ) val target = VMTarget() withData( nameFn = { it.second.first }, onlyVirtual.map { it to prepareTestFiles(it.first, it.second, target) } ) { (params, prep) -> val filepath = prep.second val optimize = params.second compileTheThing(filepath, optimize, target, outputDir) shouldNotBe null } })