diff --git a/src/test/java/com/dostalgia/ConfigBuilderTest.java b/src/test/java/com/dostalgia/ConfigBuilderTest.java new file mode 100644 index 0000000..5d0ab0e --- /dev/null +++ b/src/test/java/com/dostalgia/ConfigBuilderTest.java @@ -0,0 +1,80 @@ +package com.dostalgia; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +class ConfigBuilderTest { + + private final ConfigBuilder builder = new ConfigBuilder(); + + @Test + void buildDosboxConf_noCdImages() { + String conf = builder.buildDosboxConf("FALLOUT.EXE", List.of()); + assertTrue(conf.contains("memsize=64"), "Should include memsize"); + assertTrue(conf.contains("mount c ."), "Should mount C drive"); + assertTrue(conf.contains("FALLOUT.EXE"), "Should reference executable"); + assertFalse(conf.contains("imgmount"), "No CD images should produce no imgmount"); + } + + @Test + void buildDosboxConf_withCdImages() { + String conf = builder.buildDosboxConf("DOTT.EXE", List.of("game.cue", "game.bin")); + assertTrue(conf.contains("imgmount D \"game.bin\" -t cdrom -fs iso"), "Should mount .bin with iso flag"); + assertFalse(conf.contains("game.cue"), "Should skip .cue when .bin exists"); + } + + @Test + void buildDosboxConf_subdirectory() { + String conf = builder.buildDosboxConf("FALLOUT/FALLOUT.EXE", List.of()); + assertTrue(conf.contains("cd FALLOUT"), "Should cd into subdirectory"); + assertTrue(conf.contains("path=c:\\"), "Should set path"); + } + + @Test + void buildCdOnlyDosboxConf() { + String conf = builder.buildCdOnlyDosboxConf(List.of("game.iso")); + assertTrue(conf.contains("runs from the CD-ROM"), "CD-only message"); + assertTrue(conf.contains("imgmount D"), "Should mount CD"); + } + + @Test + void buildJsdosJson() { + byte[] json = builder.buildJsdosJson("GAME.EXE", List.of()); + String s = new String(json); + assertTrue(s.contains("\"script\""), "Should have script key"); + assertTrue(s.contains("\"autolock\""), "Should have autolock"); + assertTrue(s.contains("GAME.EXE"), "Should contain executable name"); + } + + @Test + void splitExePath_rootLevel() { + var parts = ConfigBuilder.splitExePath("GAME.EXE"); + assertNull(parts.dir()); + assertEquals("GAME.EXE", parts.exe()); + } + + @Test + void splitExePath_subdirectory() { + var parts = ConfigBuilder.splitExePath("FALLOUT1/FALLOUT.EXE"); + assertEquals("FALLOUT1", parts.dir()); + assertEquals("FALLOUT.EXE", parts.exe()); + } + + @Test + void splitExePath_nullOrEmpty() { + assertNull(ConfigBuilder.splitExePath(null).dir()); + assertEquals("", ConfigBuilder.splitExePath("").exe()); + } + + @Test + void escapeJson() { + assertEquals("hello", ConfigBuilder.escapeJson("hello")); + assertEquals("\\\\n", ConfigBuilder.escapeJson("\\n")); + assertEquals("he said \\\"hi\\\"", ConfigBuilder.escapeJson("he said \"hi\"")); + } +} diff --git a/src/test/java/com/dostalgia/PlatformDetectorTest.java b/src/test/java/com/dostalgia/PlatformDetectorTest.java new file mode 100644 index 0000000..b89af2f --- /dev/null +++ b/src/test/java/com/dostalgia/PlatformDetectorTest.java @@ -0,0 +1,90 @@ +package com.dostalgia; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import java.nio.file.Files; +import java.nio.file.Path; + +class PlatformDetectorTest { + + private final PlatformDetector detector = new PlatformDetector(); + + @Test + void detect_comFile_returnsDos(@TempDir Path dir) throws Exception { + Path f = dir.resolve("test.com"); + Files.write(f, new byte[]{0x4D, 0x5A}); // MZ header + assertEquals("dos", detector.detect(f)); + } + + @Test + void detect_batFile_returnsDos(@TempDir Path dir) throws Exception { + Path f = dir.resolve("test.bat"); + Files.writeString(f, "@echo off"); + assertEquals("dos", detector.detect(f)); + } + + @Test + void detect_plainMZ_returnsDos(@TempDir Path dir) throws Exception { + byte[] buf = new byte[0x80]; + buf[0] = 0x4D; // M + buf[1] = 0x5A; // Z + // e_lfanew points to garbage — should be treated as plain DOS + buf[0x3C] = 0x00; + buf[0x3D] = 0x00; + buf[0x3E] = 0x00; + buf[0x3F] = 0x00; + + Path f = dir.resolve("test.exe"); + Files.write(f, buf); + assertEquals("dos", detector.detect(f)); + } + + @Test + void detect_peHeader_returnsWindows(@TempDir Path dir) throws Exception { + byte[] buf = new byte[0x100]; + buf[0] = 0x4D; // M + buf[1] = 0x5A; // Z + // e_lfanew = 0x80 + buf[0x3C] = (byte) 0x80; + buf[0x3D] = 0x00; + buf[0x3E] = 0x00; + buf[0x3F] = 0x00; + // PE signature at offset 0x80 + buf[0x80] = 0x50; // P + buf[0x81] = 0x45; // E + + Path f = dir.resolve("test.exe"); + Files.write(f, buf); + assertEquals("windows", detector.detect(f)); + } + + @Test + void detect_neHeader_returnsWindows(@TempDir Path dir) throws Exception { + byte[] buf = new byte[0x100]; + buf[0] = 0x4D; + buf[1] = 0x5A; + buf[0x3C] = (byte) 0x80; + buf[0x80] = 0x4E; // N + buf[0x81] = 0x45; // E + + Path f = dir.resolve("test.exe"); + Files.write(f, buf); + assertEquals("windows", detector.detect(f)); + } + + @Test + void detect_emptyFile_returnsNull(@TempDir Path dir) throws Exception { + Path f = dir.resolve("empty.exe"); + Files.write(f, new byte[0]); + assertNull(detector.detect(f)); + } + + @Test + void detect_noMZ_returnsNull(@TempDir Path dir) throws Exception { + Path f = dir.resolve("bad.exe"); + Files.write(f, new byte[]{0x00, 0x00}); + assertNull(detector.detect(f)); + } +}