diff --git a/Makefile.am b/Makefile.am index 4c114ffa..7d74f5fa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -83,8 +83,8 @@ LOG_DRIVER = testcpu ## hack TODO/FIXME ... should be wrapper shell script acce A2_TEST_SOURCES = $(apple2ix_SOURCES) A2_TEST_CFLAGS = -DTESTING=1 -Isrc/greatest -TESTS = testcpu testdisplay -check_PROGRAMS = testcpu testdisplay +TESTS = testcpu testdisplay testvm +check_PROGRAMS = testcpu testdisplay testvm testcpu_SOURCES = src/test/testcpu.c $(A2_TEST_SOURCES) $(EXTRA_apple2ix_SOURCES) testcpu_CFLAGS = $(apple2ix_CFLAGS) $(A2_TEST_CFLAGS) @@ -97,6 +97,12 @@ testdisplay_CFLAGS = $(apple2ix_CFLAGS) $(A2_TEST_CFLAGS) -UAUDIO_ENABLED -UVIDE testdisplay_LDFLAGS = $(apple2ix_LDFLAGS) testdisplay_DEPENDENCIES = @VM_O@ @META_O@ +testvm_SOURCES = src/test/testvm.c $(A2_TEST_SOURCES) $(VM_SRC) $(META_SRC) +# HACK FIXME TODO NOTE: why don't these CFLAGS here pass down to the .S and .c files in the subdirectories? +testvm_CFLAGS = $(apple2ix_CFLAGS) $(A2_TEST_CFLAGS) -UAUDIO_ENABLED -UVIDEO_X11 -UINTERFACE_CLASSIC +testvm_LDFLAGS = $(apple2ix_LDFLAGS) +testvm_DEPENDENCIES = @VM_O@ @META_O@ + ############################################################################### # Misc diff --git a/disks/testvm1.dsk.gz b/disks/testvm1.dsk.gz new file mode 100644 index 00000000..d95e0f75 Binary files /dev/null and b/disks/testvm1.dsk.gz differ diff --git a/src/test/testcommon.h b/src/test/testcommon.h index 5ad5bd79..f0456205 100644 --- a/src/test/testcommon.h +++ b/src/test/testcommon.h @@ -14,4 +14,33 @@ #include "common.h" +#define TEST_FINISHED 0xff +#define MIXSWITCH_ADDR 0x1f32 // PEEK(7986) +#define WATCHPOINT_ADDR 0x1f33 // PEEK(7987) +#define TESTOUT_ADDR 0x1f43 // PEEK(8003) + +#define BLANK_SCREEN "6C8ABA272F220F00BE0E76A8659A1E30C2D3CDBE" +#define BOOT_SCREEN "F8D6C781E0BB7B3DDBECD69B25E429D845506594" + +#define TESTBUF_SZ 256 + +#define ASSERT_SHA(SHA_STR) \ + do { \ + uint8_t md[SHA_DIGEST_LENGTH]; \ + char mdstr[(SHA_DIGEST_LENGTH*2)+1]; \ + const uint8_t * const fb = video_current_framebuffer(); \ + SHA1(fb, SCANWIDTH*SCANHEIGHT, md); \ + sha1_to_str(md, mdstr); \ + ASSERT(strcmp(mdstr, SHA_STR) == 0); \ + } while(0); + +#define BOOT_TO_DOS() \ + if (test_do_reboot) { \ + ASSERT(apple_ii_64k[0][WATCHPOINT_ADDR] != TEST_FINISHED); \ + c_debugger_go(); \ + ASSERT(apple_ii_64k[0][WATCHPOINT_ADDR] == TEST_FINISHED); \ + ASSERT_SHA(BOOT_SCREEN); \ + apple_ii_64k[0][WATCHPOINT_ADDR] = 0x00; \ + } + #endif // whole file diff --git a/src/test/testdisplay.c b/src/test/testdisplay.c index ab9afacd..cb0f36bf 100644 --- a/src/test/testdisplay.c +++ b/src/test/testdisplay.c @@ -18,15 +18,6 @@ #error "these tests require OpenSSL libraries" #endif -#define TEST_FINISHED 0xff -#define MIXSWITCH_ADDR 0x1f32 // PEEK(7986) -#define WATCHPOINT_ADDR 0x1f33 // PEEK(7987) - -#define BLANK_SCREEN "6C8ABA272F220F00BE0E76A8659A1E30C2D3CDBE" -#define BOOT_SCREEN "F8D6C781E0BB7B3DDBECD69B25E429D845506594" - -#define TESTBUF_SZ 256 - static char *input_str = NULL; // ASCII static unsigned int input_length = 0; static unsigned int input_counter = 0; @@ -115,27 +106,6 @@ void c_interface_print(int x, int y, const int cs, const char *s) { } // ---------------------------------------------------------------------------- -// VM TESTS ... - -#define ASSERT_SHA(SHA_STR) \ - do { \ - uint8_t md[SHA_DIGEST_LENGTH]; \ - char mdstr[(SHA_DIGEST_LENGTH*2)+1]; \ - const uint8_t * const fb = video_current_framebuffer(); \ - SHA1(fb, SCANWIDTH*SCANHEIGHT, md); \ - sha1_to_str(md, mdstr); \ - ASSERT(strcmp(mdstr, SHA_STR) == 0); \ - } while(0); - -#define BOOT_TO_DOS() \ - if (test_do_reboot) { \ - ASSERT(apple_ii_64k[0][WATCHPOINT_ADDR] != TEST_FINISHED); \ - c_debugger_go(); \ - ASSERT(apple_ii_64k[0][WATCHPOINT_ADDR] == TEST_FINISHED); \ - ASSERT_SHA(BOOT_SCREEN); \ - apple_ii_64k[0][WATCHPOINT_ADDR] = 0x00; \ - } - TEST test_boot_disk() { char *disk = "./disks/testdisplay1.dsk.gz"; diff --git a/src/test/testvm.c b/src/test/testvm.c new file mode 100644 index 00000000..87f5038d --- /dev/null +++ b/src/test/testvm.c @@ -0,0 +1,229 @@ +/* + * Apple // emulator for *nix + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +#include "greatest.h" +#include "testcommon.h" + +#ifdef HAVE_OPENSSL +#include +#else +#error "these tests require OpenSSL libraries (SHA)" +#endif + +static char *input_str = NULL; // ASCII +static unsigned int input_length = 0; +static unsigned int input_counter = 0; +static bool test_do_reboot = true; + +extern unsigned char joy_button0; + +static void testvm_setup(void *arg) { + apple_ii_64k[0][MIXSWITCH_ADDR] = 0x00; + apple_ii_64k[0][WATCHPOINT_ADDR] = 0x00; + apple_ii_64k[0][TESTOUT_ADDR] = 0x00; + input_counter = 0; + input_length = 0; + joy_button0 = 0xff; // OpenApple + if (test_do_reboot) { + cpu65_interrupt(ResetSig); + } +} + +static void testvm_teardown(void *arg) { + if (input_str) { + free(input_str); + } + input_str = NULL; +} + +static void testvm_breakpoint(void *arg) { + fprintf(GREATEST_STDOUT, "set breakpoint on testvm_breakpoint to check for problems...\n"); +} + +static void sha1_to_str(const uint8_t * const md, char *buf) { + int i=0; + for (int j=0; j= input_length) { + return; + } + + uint8_t ch = (uint8_t)input_str[input_counter]; + if (ch == '\n') { + fprintf(stderr, "converting '\\n' to '\\r' in test input string..."); + ch = '\r'; + } + + if ( (apple_ii_64k[0][0xC000] & 0x80) || (apple_ii_64k[1][0xC000] & 0x80) ) { + // last character typed not processed by emulator... + return; + } + + apple_ii_64k[0][0xC000] = ch | 0x80; + apple_ii_64k[1][0xC000] = ch | 0x80; + + ++input_counter; +} + +// ---------------------------------------------------------------------------- +// Stub functions because I've reached diminishing returns with the build system ... +// +// NOTE: You'd think the commandline CFLAGS set specifically for this test program would pass down to the sources in +// subdirectories, but it apparently isn't. GNU buildsystem bug? Also see HACK FIXME TODO NOTE in Makefile.am +// + +uint8_t c_MB_Read(uint16_t addr) { + return 0x0; +} + +void c_MB_Write(uint16_t addr, uint8_t byte) { +} + +uint8_t c_PhasorIO(uint16_t addr) { + return 0x0; +} + +void SpkrToggle() { +} + +void c_interface_print(int x, int y, const int cs, const char *s) { +} + +// ---------------------------------------------------------------------------- +// VM TESTS ... + +TEST test_boot_disk() { + char *disk = "./disks/testvm1.dsk.gz"; + ASSERT(!c_new_diskette_6(0, disk, 0)); + + BOOT_TO_DOS(); + + PASS(); +} + +TEST test_read_keyboard() { + BOOT_TO_DOS(); + + ASSERT(apple_ii_64k[0][WATCHPOINT_ADDR] != TEST_FINISHED); + ASSERT(apple_ii_64k[0][TESTOUT_ADDR] == 0x00); + + input_str = strdup("RUN TESTGETKEY\rZ"); + input_length = strlen(input_str); + c_debugger_go(); + + ASSERT(apple_ii_64k[0][WATCHPOINT_ADDR] == TEST_FINISHED); + ASSERT(apple_ii_64k[0][TESTOUT_ADDR] == 'Z'); + + PASS(); +} + +TEST test_clear_keyboard() { + BOOT_TO_DOS(); + + ASSERT(apple_ii_64k[0][WATCHPOINT_ADDR] != TEST_FINISHED); + ASSERT(apple_ii_64k[0][TESTOUT_ADDR] == 0x00); + + input_str = strdup("RUN TESTCLEARKEY\rZA"); + input_length = strlen(input_str); + c_debugger_go(); + + ASSERT(apple_ii_64k[0][WATCHPOINT_ADDR] == TEST_FINISHED); + ASSERT(apple_ii_64k[0][TESTOUT_ADDR] == 'A'); + + PASS(); +} + +TEST test_read_random() { + SKIPm("random numbers current b0rken..."); + + BOOT_TO_DOS(); + + ASSERT(apple_ii_64k[0][WATCHPOINT_ADDR] != TEST_FINISHED); + ASSERT(apple_ii_64k[0][TESTOUT_ADDR] == 0x00); + + input_str = strdup("RUN TESTRND\r"); + input_length = strlen(input_str); + c_debugger_go(); + + ASSERT(apple_ii_64k[0][WATCHPOINT_ADDR] == TEST_FINISHED); + ASSERT(apple_ii_64k[0][TESTOUT_ADDR] == 0xFF); + + PASS(); +} + +// ---------------------------------------------------------------------------- +// Test Suite + +extern void cpu_thread(void *dummyptr); + +GREATEST_SUITE(test_suite_vm) { + + c_read_random(); + srandom(0); // force a known sequence + + GREATEST_SET_SETUP_CB(testvm_setup, NULL); + GREATEST_SET_TEARDOWN_CB(testvm_teardown, NULL); + GREATEST_SET_BREAKPOINT_CB(testvm_breakpoint, NULL); + + do_logging = false;// silence regular emulator logging + setenv("APPLE2IXCFG", "nosuchconfigfile", 1); + + load_settings(); + c_initialize_firsttime(); + + // kludgey set max CPU speed... + cpu_scale_factor = CPU_SCALE_FASTEST; + cpu_altscale_factor = CPU_SCALE_FASTEST; + g_bFullSpeed = true; + + caps_lock = true; + + // spin off cpu thread + pthread_create(&cpu_thread_id, NULL, (void *) &cpu_thread, (void *)NULL); + + pthread_mutex_lock(&interface_mutex); + + c_debugger_set_watchpoint(WATCHPOINT_ADDR); + c_debugger_set_timeout(5); + + // TESTS -------------------------- + + RUN_TESTp(test_boot_disk); + + RUN_TESTp(test_read_keyboard); + + RUN_TESTp(test_clear_keyboard); + + RUN_TESTp(test_read_random); + + // ... + c_eject_6(0); + pthread_mutex_unlock(&interface_mutex); +} + +SUITE(test_suite_vm); +GREATEST_MAIN_DEFS(); + +int main(int argc, char **argv) { + GREATEST_MAIN_BEGIN(); + RUN_SUITE(test_suite_vm); + GREATEST_MAIN_END(); +} +