From df3966a90ca971c661e139af2aa9673a51656294 Mon Sep 17 00:00:00 2001 From: Jonathon Reinhart Date: Mon, 7 Sep 2015 16:07:48 -0400 Subject: [PATCH] continued work on test framework --- test/unit/.gitignore | 1 + test/unit/Makefile | 9 ++--- test/unit/test_mem_map.c | 77 +++++++++++++++++++++++++++++++++++++--- test/unit/test_x86.c | 2 +- test/unit/unicorn_test.h | 15 +++++--- 5 files changed, 87 insertions(+), 17 deletions(-) diff --git a/test/unit/.gitignore b/test/unit/.gitignore index b045baae..1a39afbc 100644 --- a/test/unit/.gitignore +++ b/test/unit/.gitignore @@ -1 +1,2 @@ test_x86 +test_mem_map diff --git a/test/unit/Makefile b/test/unit/Makefile index 0eac4063..707e9cd2 100644 --- a/test/unit/Makefile +++ b/test/unit/Makefile @@ -1,4 +1,5 @@ +CFLAGS += -Wall -Werror -Wno-unused-function -g CFLAGS += -L ../../ CFLAGS += -lcmocka -lunicorn CFLAGS += -I ../../include @@ -15,12 +16,8 @@ clean: .PHONY: test test: export LD_LIBRARY_PATH=../../ test: ${ALL_TESTS} - @#echo ${ALL_TESTS} | xargs -n1 | xargs -I CMD sh -c ./CMD - @for test in ${ALL_TESTS}; do \ - echo -e "\n--------------------------------------------------------------------------------"; \ - echo "TEST: $$test"; \ - ./$$test || break; \ - done + ./test_x86 + ./test_mem_map test_x86: test_x86.c diff --git a/test/unit/test_mem_map.c b/test/unit/test_mem_map.c index 58e2a779..08b46aef 100644 --- a/test/unit/test_mem_map.c +++ b/test/unit/test_mem_map.c @@ -1,10 +1,10 @@ #include "unicorn_test.h" #include +#include +/* Called before every test to set up a new instance */ static int setup(void **state) { - fprintf(stderr, "~~~ setup() ~~~\n"); - uc_engine *uc; uc_assert_success(uc_open(UC_ARCH_X86, UC_MODE_32, &uc)); @@ -13,23 +13,90 @@ static int setup(void **state) return 0; } +/* Called after every test to clean up */ static int teardown(void **state) { uc_engine *uc = *state; - fprintf(stderr, "~~~ teardown() ~~~\n"); uc_assert_success(uc_close(uc)); + + *state = NULL; return 0; } +/******************************************************************************/ + +/** + * A basic test showing mapping of memory, and reading/writing it + */ static void test_basic(void **state) { + uc_engine *uc = *state; + const uint64_t mem_start = 0x1000; + const uint64_t mem_len = 0x1000; + const uint64_t test_addr = mem_start + 0x100; + + /* Map a region */ + uc_assert_success(uc_mem_map(uc, mem_start, mem_len, UC_PROT_NONE)); + + /* Write some data to it */ + uc_assert_success(uc_mem_write(uc, test_addr, "test", 4)); + + uint8_t buf[4]; + memset(buf, 0xCC, sizeof(buf)); + + /* Read it back */ + uc_assert_success(uc_mem_read(uc, test_addr, buf, sizeof(buf))); + + /* And make sure it matches what we expect */ + assert_memory_equal(buf, "test", 4); + + /* Unmap the region */ + uc_assert_success(uc_mem_unmap(uc, mem_start, mem_len)); } +/** + * Verify that we can read/write across memory map region boundaries + */ +static void test_rw_across_boundaries(void **state) +{ + uc_engine *uc = *state; + + /* Map in two adjacent regions */ + uc_assert_success(uc_mem_map(uc, 0, 0x1000, 0)); /* 0x0000 - 0x1000 */ + uc_assert_success(uc_mem_map(uc, 0x1000, 0x1000, 0)); /* 0x1000 - 0x2000 */ + + const uint64_t addr = 0x1000 - 2; /* 2 bytes before end of block */ + + /* Write some data across the boundary */ + uc_assert_success(uc_mem_write(uc, addr, "test", 4)); + + uint8_t buf[4]; + memset(buf, 0xCC, sizeof(buf)); + + /* Read the data across the boundary */ + uc_assert_success(uc_mem_read(uc, addr, buf, sizeof(buf))); + + assert_memory_equal(buf, "test", 4); +} + +static void test_bad_unmap(void **state) +{ + uc_engine *uc = *state; + uc_err err; + + /* Try to unmap memory that has not been mapped */ + err = uc_mem_unmap(uc, 0x0, 0x1000); + assert_int_not_equal(err, UC_ERR_OK); +} + + int main(void) { const struct CMUnitTest tests[] = { - cmocka_unit_test(test_basic), + cmocka_unit_test_setup_teardown(test_basic, setup, teardown), + cmocka_unit_test_setup_teardown(test_bad_unmap, setup, teardown), + cmocka_unit_test_setup_teardown(test_rw_across_boundaries, setup, teardown), }; - return cmocka_run_group_tests(tests, setup, teardown); + return cmocka_run_group_tests(tests, NULL, NULL); } diff --git a/test/unit/test_x86.c b/test/unit/test_x86.c index a6b509bd..a56e332e 100644 --- a/test/unit/test_x86.c +++ b/test/unit/test_x86.c @@ -14,7 +14,7 @@ static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *use // callback for tracing instruction static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) { - int eflags; + //int eflags; //printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); //uc_reg_read(uc, UC_X86_REG_EFLAGS, &eflags); diff --git a/test/unit/unicorn_test.h b/test/unit/unicorn_test.h index 03f9e556..a9dff775 100644 --- a/test/unit/unicorn_test.h +++ b/test/unit/unicorn_test.h @@ -7,10 +7,15 @@ #include #include -static void uc_assert_success(uc_err err) -{ - assert_int_equal(err, 0); - // uc_strerror(err) -} +#define uc_assert_success(err) \ +do { \ + uc_err __err = err; \ + if (__err != UC_ERR_OK) { \ + fail_msg("%s", uc_strerror(__err)); \ + } \ +} while (0) + + + #endif /* UNICORN_TEST_H */