From: chaoskagami Date: Thu, 8 Sep 2016 16:17:08 +0000 (-0400) Subject: Basic sanity tests X-Git-Tag: v0.3.0~14 X-Git-Url: https://chaos.moe/g/?a=commitdiff_plain;h=722c0071d029cc25bdb0043d5877e77aa776848b;p=corbenik%2Fcorbenik.git Basic sanity tests --- diff --git a/include/corbconf.h b/include/corbconf.h index cec84b7..4e74f00 100644 --- a/include/corbconf.h +++ b/include/corbconf.h @@ -3,4 +3,6 @@ #include +#define UNITTESTS 1 + #endif diff --git a/source/Makefile.am b/source/Makefile.am index 69045da..9db3653 100644 --- a/source/Makefile.am +++ b/source/Makefile.am @@ -19,4 +19,4 @@ corbenikdir = $(top_srcdir)/source inc_dir = $(top_srcdir)/include -corbenik_SOURCES = patch/reboot.c patch/svc.c patch/module.c patch/emunand.c main.c std/fs.c std/draw.c std/memory.c std/abort.c std/allocator.c menu.c firm/util.c firm/keys.c firm/firmlaunch.c firm/version.c firm/firm.c firm/decryptor.c interpreter.c input.c patcher.c chainloader.c config-backend-file.c menu-backend.c start.s interrupt.c arm11.c +corbenik_SOURCES = patch/reboot.c patch/svc.c patch/module.c patch/emunand.c main.c std/fs.c std/draw.c std/memory.c std/abort.c std/allocator.c menu.c firm/util.c firm/keys.c firm/firmlaunch.c firm/version.c firm/firm.c firm/decryptor.c interpreter.c input.c patcher.c chainloader.c config-backend-file.c menu-backend.c start.s interrupt.c arm11.c test-framework.c diff --git a/source/menu.c b/source/menu.c index 6a7da9b..388bcdc 100644 --- a/source/menu.c +++ b/source/menu.c @@ -16,6 +16,10 @@ static int desc_is_fname_sto = 0; void chainload_menu(); #endif +#if defined(UNITTESTS) && UNITTESTS == 1 +void run_test_harness(); +#endif + #ifndef REL #define REL "master" #endif @@ -171,6 +175,11 @@ static struct options_s main_s[] = { { "Chainload", "Boot another ARM9 payload file.", option, 0, chainload_menu, NULL, 0, 0 }, +#endif +#if defined(UNITTESTS) && UNITTESTS == 1 + { "Unit tests", + "Runs through a number of sanity and regression tests to check for defects.", + option, 0, run_test_harness, NULL, 0, 0 }, #endif { "Boot Firmware", "Patches the firmware, and boots it.", diff --git a/source/test-framework.c b/source/test-framework.c new file mode 100644 index 0000000..f91647f --- /dev/null +++ b/source/test-framework.c @@ -0,0 +1,82 @@ +#include +#if defined(UNITTESTS) && UNITTESTS == 1 + +#include + +uint32_t total; +uint32_t pass; +uint32_t fail; +uint32_t skip; + +void test(int value, const char* name) { + fprintf(stderr, "%s: ", name); + + switch(value) { + case 0: + fprintf(stderr, "pass\n"); + ++pass; + break; + case 1: + fprintf(stderr, "fail\n"); + ++fail; + break; + default: + fprintf(stderr, "skip\n"); + ++skip; + break; + } + ++total; +} + +int assert_null(void* ptr) { + if (ptr == NULL) + return 0; + return 1; +} + +int assert_nonnull(void* ptr) { + if (ptr != NULL) + return 0; + return 1; +} + +int assert_int(int input, int value) { + if (input != value) + return 1; + return 0; +} + +int assert_u32(uint32_t input, uint32_t value) { + if (input != value) + return 1; + return 0; +} + +int assert_array_eq(uint8_t* input, uint8_t* test, uint32_t len) { + for (uint32_t i=0; i < len; i++) { + if (input[i] != test[i]) + return 1; + } + return 0; +} + +// We do NOT want the test harness optimized whatsoever. + +void __attribute__((optimize("O0"))) run_test_harness() { + total = pass = fail = skip = 0; + + #include "test/basic-sanity.test" + #include "test/file.test" +// #include "test/firmware.test" +// #include "test/vm.test" +// #include "test/vm-patch.test" + + fprintf(stderr, "= Tests =\n" + "Total: %lu\n" + "Pass: %lu\n" + "Fail: %lu\n" + "Skip: %lu\n", + total, pass, fail, skip); +} + +#endif diff --git a/source/test/basic-sanity.test b/source/test/basic-sanity.test new file mode 100644 index 0000000..95fb3a9 --- /dev/null +++ b/source/test/basic-sanity.test @@ -0,0 +1,15 @@ +{ + uint8_t memory0[8] = "reverse"; + uint8_t memory1[8] = "forward"; + uint8_t memory_out[8] = "forward"; + + // Test for inequivalence. + test(assert_int(!memcmp(memory0, memory1, 8), 0), "Inverted memcmp"); + + // Test for equivalence. + test(assert_int(memcmp(memory1, memory_out, 8), 0), "memcmp"); + + // Test sanity of memcpy. + memcpy(memory1, memory0, 8); + test(assert_int(memcmp(memory0, memory1, 8), 0), "memcpy"); +} diff --git a/source/test/file.test b/source/test/file.test new file mode 100644 index 0000000..986b600 --- /dev/null +++ b/source/test/file.test @@ -0,0 +1,37 @@ +{ + FILE* file_handle = NULL; + char filename[] = "/lolidontexistwowlol"; + + // Test; open nonexistent file for read. + file_handle = fopen(filename, "r"); + + test(assert_null(file_handle), "Nonexistent file"); + + // Test; open nonexistent file for write. + file_handle = fopen(filename, "w"); + + test(assert_nonnull(file_handle), "Open for writing"); + + // Test; write string. Close file, check length, compare equality. + char data_str[] = "LOOK AT THIS STRING; It Should be equal."; + char data_str2[] = " "; + + test(assert_u32(fwrite(data_str, 1, sizeof(data_str), file_handle), sizeof(data_str)), "fwrite return"); + fclose(file_handle); + + file_handle = fopen(filename, "r"); + test(assert_nonnull(file_handle), "Open for read"); + + test(assert_u32(fread(data_str2, 1, sizeof(data_str), file_handle), sizeof(data_str)), "fread return"); + + test(assert_int(memcmp(data_str, data_str2, sizeof(data_str)), 0), "read data"); + + fclose(file_handle); + + // Test removal. + + f_unlink(filename); + + file_handle = fopen(filename, "r"); + test(assert_null(file_handle), "Remove file"); +}