package prog8tests import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance import kotlin.test.* import java.nio.file.Path // TODO: use kotlin.io.path.Path instead import kotlin.io.path.* import prog8.ast.IBuiltinFunctions import prog8.ast.IMemSizer import prog8.ast.IStringEncoding import prog8.ast.Program import prog8.ast.base.DataType import prog8.ast.base.Position import prog8.ast.expressions.Expression import prog8.ast.expressions.InferredTypes import prog8.ast.expressions.NumericLiteralValue import prog8.parser.ModuleImporter import prog8.parser.ParseError @TestInstance(TestInstance.Lifecycle.PER_CLASS) class TestModuleImporter { object DummyEncoding: IStringEncoding { override fun encodeString(str: String, altEncoding: Boolean): List { TODO("Not yet implemented") } override fun decodeString(bytes: List, altEncoding: Boolean): String { TODO("Not yet implemented") } } object DummyFunctions: IBuiltinFunctions { override val names: Set = emptySet() override val purefunctionNames: Set = emptySet() override fun constValue(name: String, args: List, position: Position, memsizer: IMemSizer): NumericLiteralValue? = null override fun returnType(name: String, args: MutableList) = InferredTypes.InferredType.unknown() } object DummyMemsizer: IMemSizer { override fun memorySize(dt: DataType): Int = 0 } @Test fun testImportModuleWithNonExistingPath() { val program = Program("foo", mutableListOf(), DummyFunctions, DummyMemsizer) val importer = ModuleImporter(program, DummyEncoding, "blah", listOf("./test/fixtures")) val srcPath = Path.of("test", "fixtures", "i_do_not_exist") assertFalse(srcPath.exists(), "sanity check: file should not exist") assertFailsWith { importer.importModule(srcPath) } } @Test fun testImportModuleWithDirectoryPath() { val program = Program("foo", mutableListOf(), DummyFunctions, DummyMemsizer) val importer = ModuleImporter(program, DummyEncoding, "blah", listOf("./test/fixtures")) val srcPath = Path.of("test", "fixtures") assertTrue(srcPath.isDirectory(), "sanity check: should be a directory") // fn importModule(Path) used to check *.isReadable()*, but NOT .isRegularFile(): assertTrue(srcPath.isReadable(), "sanity check: should still be readable") assertFailsWith { importer.importModule(srcPath) } } @Test fun testImportModuleWithSyntaxError() { val program = Program("foo", mutableListOf(), DummyFunctions, DummyMemsizer) val importer = ModuleImporter(program, DummyEncoding, "blah", listOf("./test/fixtures")) val filename = "file_with_syntax_error.p8" val path = Path.of("test", "fixtures", filename) val act = { importer.importModule(path) } assertFailsWith { act() } try { act() } catch (e: ParseError) { assertEquals(path.absolutePathString(), e.position.file) assertEquals(2, e.position.line, "line; should be 1-based") assertEquals(6, e.position.startCol, "startCol; should be 0-based" ) assertEquals(6, e.position.endCol, "endCol; should be 0-based") } } @Test fun testImportModuleWithImportingModuleWithSyntaxError() { val program = Program("foo", mutableListOf(), DummyFunctions, DummyMemsizer) val importer = ModuleImporter(program, DummyEncoding, "blah", listOf("./test/fixtures")) val importing = Path.of("test", "fixtures", "import_file_with_syntax_error.p8") val imported = Path.of("test", "fixtures", "file_with_syntax_error.p8") val act = { importer.importModule(importing) } assertTrue(importing.isRegularFile(), "sanity check: should be regular file") assertFailsWith { act() } try { act() } catch (e: ParseError) { val expectedProvenance = imported.absolutePathString() assertEquals(expectedProvenance, e.position.file) assertEquals(2, e.position.line, "line; should be 1-based") assertEquals(6, e.position.startCol, "startCol; should be 0-based" ) assertEquals(6, e.position.endCol, "endCol; should be 0-based") } } @Test fun testImportLibraryModuleWithNonExistingName() { val program = Program("foo", mutableListOf(), DummyFunctions, DummyMemsizer) val importer = ModuleImporter(program, DummyEncoding, "blah", listOf("./test/fixtures")) val filenameNoExt = "i_do_not_exist" val filenameWithExt = filenameNoExt + ".p8" val srcPathNoExt = Path.of("test", "fixtures", filenameNoExt) val srcPathWithExt = Path.of("test", "fixtures", filenameWithExt) assertFalse(srcPathNoExt.exists(), "sanity check: file should not exist") assertFalse(srcPathWithExt.exists(), "sanity check: file should not exist") assertFailsWith { importer.importLibraryModule(filenameNoExt) } assertFailsWith { importer.importLibraryModule(filenameWithExt) } } @Test fun testImportLibraryModuleWithSyntaxError() { val program = Program("foo", mutableListOf(), DummyFunctions, DummyMemsizer) val importer = ModuleImporter(program, DummyEncoding, "blah", listOf("./test/fixtures")) val filename = "file_with_syntax_error" val act = { importer.importLibraryModule(filename) } assertFailsWith { act() } try { act() } catch (e: ParseError) { val expectedProvenance = Path.of("test", "fixtures", filename + ".p8") .absolutePathString() assertEquals(expectedProvenance, e.position.file) assertEquals(2, e.position.line, "line; should be 1-based") assertEquals(6, e.position.startCol, "startCol; should be 0-based") assertEquals(6, e.position.endCol, "endCol; should be 0-based") } } @Test fun testImportLibraryModuleWithImportingBadModule() { val program = Program("foo", mutableListOf(), DummyFunctions, DummyMemsizer) val libdirs = listOf("./test/fixtures") val importer = ModuleImporter(program, DummyEncoding, "blah", libdirs) val importing = "import_file_with_syntax_error" val imported = "file_with_syntax_error" val act = { importer.importLibraryModule(importing) } assertFailsWith { act() } try { act() } catch (e: ParseError) { val expectedProvenance = Path.of(libdirs[0], imported + ".p8") .normalize() .absolutePathString() assertEquals(expectedProvenance, e.position.file) assertEquals(2, e.position.line, "line; should be 1-based") assertEquals(6, e.position.startCol, "startCol; should be 0-based") assertEquals(6, e.position.endCol, "endCol; should be 0-based") } } }