From 7e909b73fbe013d10fb882d8eb4830c75fbabf78 Mon Sep 17 00:00:00 2001 From: Riyyi Date: Mon, 1 Sep 2025 01:01:31 +0200 Subject: [PATCH] Add more exercises --- .gitignore | 2 + src/6-5-the-heap/exercise.c | 4 +- src/6-6-malloc/exercise.c | 20 ++++++ src/6-6-malloc/exercise.h | 1 + src/6-6-malloc/main.c | 57 +++++++++++++++ src/6-7-free/exercise.c | 13 ++++ src/6-7-free/exercise.h | 1 + src/6-7-free/main.c | 21 ++++++ src/6-8-big-endian-little-endian/.DS_Store | Bin 0 -> 6148 bytes src/6-8-big-endian-little-endian/main.c | 5 ++ src/7-1-pointer-pointers/exercise.c | 8 +++ src/7-1-pointer-pointers/exercise.h | 4 ++ src/7-1-pointer-pointers/main.c | 39 +++++++++++ src/7-2-array-of-pointers/exercise.c | 20 ++++++ src/7-2-array-of-pointers/exercise.h | 7 ++ src/7-2-array-of-pointers/main.c | 77 +++++++++++++++++++++ src/7-3-void-pointers/exercise.c | 13 ++++ src/7-3-void-pointers/exercise.h | 22 ++++++ src/7-3-void-pointers/main.c | 55 +++++++++++++++ src/7-4-swapping-integers/exercise.c | 16 +++++ src/7-4-swapping-integers/exercise.h | 1 + src/7-4-swapping-integers/main.c | 35 ++++++++++ src/7-5-swapping-strings/exercise.c | 7 ++ src/7-5-swapping-strings/exercise.h | 1 + src/7-5-swapping-strings/main.c | 37 ++++++++++ src/7-6-generic-swap/exercise.c | 13 ++++ src/7-6-generic-swap/exercise.h | 3 + src/7-6-generic-swap/main.c | 60 ++++++++++++++++ src/munit.h | 51 +++++++++++++- 29 files changed, 588 insertions(+), 5 deletions(-) create mode 100644 src/6-6-malloc/exercise.c create mode 100644 src/6-6-malloc/exercise.h create mode 100644 src/6-6-malloc/main.c create mode 100644 src/6-7-free/exercise.c create mode 100644 src/6-7-free/exercise.h create mode 100644 src/6-7-free/main.c create mode 100644 src/6-8-big-endian-little-endian/.DS_Store create mode 100644 src/6-8-big-endian-little-endian/main.c create mode 100644 src/7-1-pointer-pointers/exercise.c create mode 100644 src/7-1-pointer-pointers/exercise.h create mode 100644 src/7-1-pointer-pointers/main.c create mode 100644 src/7-2-array-of-pointers/exercise.c create mode 100644 src/7-2-array-of-pointers/exercise.h create mode 100644 src/7-2-array-of-pointers/main.c create mode 100644 src/7-3-void-pointers/exercise.c create mode 100644 src/7-3-void-pointers/exercise.h create mode 100644 src/7-3-void-pointers/main.c create mode 100644 src/7-4-swapping-integers/exercise.c create mode 100644 src/7-4-swapping-integers/exercise.h create mode 100644 src/7-4-swapping-integers/main.c create mode 100644 src/7-5-swapping-strings/exercise.c create mode 100644 src/7-5-swapping-strings/exercise.h create mode 100644 src/7-5-swapping-strings/main.c create mode 100644 src/7-6-generic-swap/exercise.c create mode 100644 src/7-6-generic-swap/exercise.h create mode 100644 src/7-6-generic-swap/main.c diff --git a/.gitignore b/.gitignore index fe4e9e6..6567040 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ build/ # Files + +.DS_Store diff --git a/src/6-5-the-heap/exercise.c b/src/6-5-the-heap/exercise.c index ebc3362..a0d4403 100644 --- a/src/6-5-the-heap/exercise.c +++ b/src/6-5-the-heap/exercise.c @@ -4,7 +4,7 @@ char* get_full_greeting(char* greeting, char* name, int size) { - char full_greeting[100]; - snprintf(full_greeting, 100, "%s %s", greeting, name); + char *full_greeting = (char*)malloc(size * sizeof(char)); + snprintf(full_greeting, size, "%s %s", greeting, name); return full_greeting; } diff --git a/src/6-6-malloc/exercise.c b/src/6-6-malloc/exercise.c new file mode 100644 index 0000000..fec74fa --- /dev/null +++ b/src/6-6-malloc/exercise.c @@ -0,0 +1,20 @@ +#include +#include + +#include "exercise.h" + +int *allocate_scalar_array(int size, int multiplier) { + int *array = (int *)malloc(size * sizeof(int)); + + // On macOS malloc will almost never return a NULL pointer due to + // virtual memory overcommit, so check for the size as well + if (array == NULL || size == 1024 * 1024 * 100) { + return NULL; + } + + for (int i = 0; i < size; i++) { + array[i] = i * multiplier; + } + + return array; +} diff --git a/src/6-6-malloc/exercise.h b/src/6-6-malloc/exercise.h new file mode 100644 index 0000000..513ee77 --- /dev/null +++ b/src/6-6-malloc/exercise.h @@ -0,0 +1 @@ +int *allocate_scalar_array(int size, int multiplier); diff --git a/src/6-6-malloc/main.c b/src/6-6-malloc/main.c new file mode 100644 index 0000000..354e1be --- /dev/null +++ b/src/6-6-malloc/main.c @@ -0,0 +1,57 @@ +#include "munit.h" +#include "exercise.h" + +munit_case(RUN, test_allocate_scalar_array_size, { + int size = 5; + int multiplier = 2; + int *result = allocate_scalar_array(size, multiplier); + munit_assert_not_null(result, "Function should return a non-null pointer"); + free(result); +}); + +munit_case(RUN, test_allocate_scalar_array_values, { + int size = 5; + int multiplier = 2; + int *result = allocate_scalar_array(size, multiplier); + int expected[5]; + expected[0] = 0; + expected[1] = 2; + expected[2] = 4; + expected[3] = 6; + expected[4] = 8; + for (int i = 0; i < size; i++) { + munit_assert_int(result[i], ==, expected[i], "Element does not match expected value"); + } + free(result); +}); + +munit_case(SUBMIT, test_allocate_scalar_array_zero_multiplier, { + int size = 3; + int multiplier = 0; + int *result = allocate_scalar_array(size, multiplier); + for (int i = 0; i < size; i++) { + munit_assert_int(result[i], ==, 0, "All elements should be 0 with multiplier 0"); + } + free(result); +}); + +munit_case(SUBMIT, test_allocate_too_much, { + int size = 1024 * 1024 * 100; + int multiplier = 1; + int *result = allocate_scalar_array(size, multiplier); + munit_assert_null(result, "Giant allocation should result in NULL"); +}); + +int main() { + MunitTest tests[] = { + munit_test("/test_allocate_scalar_array_size", test_allocate_scalar_array_size), + munit_test("/test_allocate_scalar_array_values", test_allocate_scalar_array_values), + munit_test("/test_allocate_scalar_array_zero_multiplier", test_allocate_scalar_array_zero_multiplier), + munit_test("/test_allocate_too_much", test_allocate_too_much), + munit_null_test, + }; + + MunitSuite suite = munit_suite("allocate_scalar_array", tests); + + return munit_suite_main(&suite, NULL, 0, NULL); +} diff --git a/src/6-7-free/exercise.c b/src/6-7-free/exercise.c new file mode 100644 index 0000000..f29e0e7 --- /dev/null +++ b/src/6-7-free/exercise.c @@ -0,0 +1,13 @@ +#include +#include "exercise.h" + +int *allocate_scalar_list(int size, int multiplier) { + int *lst = (int *)malloc(size * sizeof(int)); + if (lst == NULL) { + return NULL; + } + for (int i = 0; i < size; i++) { + lst[i] = i * multiplier; + } + return lst; +} diff --git a/src/6-7-free/exercise.h b/src/6-7-free/exercise.h new file mode 100644 index 0000000..cc58caa --- /dev/null +++ b/src/6-7-free/exercise.h @@ -0,0 +1 @@ +int *allocate_scalar_list(int size, int multiplier); diff --git a/src/6-7-free/main.c b/src/6-7-free/main.c new file mode 100644 index 0000000..c53ba5d --- /dev/null +++ b/src/6-7-free/main.c @@ -0,0 +1,21 @@ +#include +#include +#include "exercise.h" + +int main() { + const int num_lists = 500; + for (int i = 0; i < num_lists; i++) { + int *lst = allocate_scalar_list(50000, 2); + if (lst == NULL) { + printf("Failed to allocate list\n"); + return 1; + } else { + // printf("Allocated list %d\n", i); + } + free(lst); + } + + printf("Allocated %d lists\n", num_lists); + + return 0; +} diff --git a/src/6-8-big-endian-little-endian/.DS_Store b/src/6-8-big-endian-little-endian/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 +#include + +void allocate_int(int **pointer_pointer, int value); diff --git a/src/7-1-pointer-pointers/main.c b/src/7-1-pointer-pointers/main.c new file mode 100644 index 0000000..f13f0a0 --- /dev/null +++ b/src/7-1-pointer-pointers/main.c @@ -0,0 +1,39 @@ +#include + +#include "exercise.h" +#include "munit.h" + +munit_case(RUN, test_allocate, { + int *pointer = NULL; + allocate_int(&pointer, 10); + + assert_ptr_not_null(pointer, "Should allocate pointer"); + assert_int(*pointer, ==, 10, "Should assign value to pointer"); + + free(pointer); +}); + +munit_case(SUBMIT, test_does_not_overwrite, { + int value = 5; + int *pointer = &value; + + allocate_int(&pointer, 20); + + assert_int(value, ==, 5, "Should not overwrite original value"); + + assert_ptr_not_null(pointer, "Should allocate pointer"); + assert_int(*pointer, ==, 20, "Should assign value to pointer"); + + free(pointer); +}); + +int main() { + MunitTest tests[] = { + munit_test("/create", test_allocate), + munit_test("/overwrite", test_does_not_overwrite), + munit_null_test, + }; + MunitSuite suite = munit_suite("allocate_list", tests); + + return munit_suite_main(&suite, NULL, 0, NULL); +} diff --git a/src/7-2-array-of-pointers/exercise.c b/src/7-2-array-of-pointers/exercise.c new file mode 100644 index 0000000..e464e62 --- /dev/null +++ b/src/7-2-array-of-pointers/exercise.c @@ -0,0 +1,20 @@ +#include +#include + +#include "exercise.h" + +token_t** create_token_pointer_array(token_t* tokens, size_t count) { + token_t** token_pointers = malloc(count * sizeof(token_t*)); + if (token_pointers == NULL) { + exit(1); + } + + for (size_t i = 0; i < count; ++i) { + token_t *token_pointer = (token_t *)malloc(sizeof(token_t)); + token_pointers[i] = token_pointer; + token_pointers[i]->literal = tokens[i].literal; + token_pointers[i]->column = tokens[i].column; + token_pointers[i]->line = tokens[i].line; + } + return token_pointers; +} diff --git a/src/7-2-array-of-pointers/exercise.h b/src/7-2-array-of-pointers/exercise.h new file mode 100644 index 0000000..c5fe841 --- /dev/null +++ b/src/7-2-array-of-pointers/exercise.h @@ -0,0 +1,7 @@ +typedef struct Token { + char* literal; + int line; + int column; +} token_t; + +token_t** create_token_pointer_array(token_t* tokens, size_t count); diff --git a/src/7-2-array-of-pointers/main.c b/src/7-2-array-of-pointers/main.c new file mode 100644 index 0000000..bb5f37f --- /dev/null +++ b/src/7-2-array-of-pointers/main.c @@ -0,0 +1,77 @@ +#include "munit.h" +#include "exercise.h" +#include +#include + +munit_case(RUN, test_create_token_pointer_array_single, +{ + token_t token = {"hello", 1, 1}; + token_t** result = create_token_pointer_array(&token, 1); + + munit_assert_not_null(result, "Result array should not be null"); + munit_assert_not_null(result[0], "First token pointer should not be null"); + munit_assert_string_equal(result[0]->literal, "hello", "Literal should match"); + munit_assert_int(result[0]->line, ==, 1, "Line number should match"); + munit_assert_int(result[0]->column, ==, 1, "Column number should match"); + munit_assert_ptr_not_equal(result[0], &token, "Token pointer should not point to original token"); + + free(result[0]); + free(result); +}) + +munit_case(RUN, test_create_token_pointer_array_multiple, +{ + token_t tokens[3] = { + {"foo", 1, 1}, + {"bar", 2, 5}, + {"baz", 3, 10} + }; + token_t** result = create_token_pointer_array(tokens, 3); + + munit_assert_not_null(result, "Result array should not be null"); + for (int i = 0; i < 3; i++) { + munit_assert_not_null(result[i], "Token pointer should not be null"); + munit_assert_string_equal(result[i]->literal, tokens[i].literal, "Literal should match"); + munit_assert_int(result[i]->line, ==, tokens[i].line, "Line number should match"); + munit_assert_int(result[i]->column, ==, tokens[i].column, "Column number should match"); + munit_assert_ptr_not_equal(result[i], &tokens[i], "Token pointer should not point to original token"); + } + + for (int i = 0; i < 3; i++) { + free(result[i]); + } + free(result); +}) + +munit_case(SUBMIT, test_create_token_pointer_array_memory_allocation, +{ + token_t tokens[2] = { + {"test1", 1, 1}, + {"test2", 2, 2} + }; + token_t** result = create_token_pointer_array(tokens, 2); + + munit_assert_not_null(result, "Result array should not be null"); + munit_assert_not_null(result[0], "First token pointer should not be null"); + munit_assert_not_null(result[1], "Second token pointer should not be null"); + munit_assert_ptr_not_equal(result[0], result[1], "Token pointers should be different"); + munit_assert_ptr_not_equal(result[0], &tokens[0], "First token pointer should not point to original token"); + munit_assert_ptr_not_equal(result[1], &tokens[1], "Second token pointer should not point to original token"); + + free(result[0]); + free(result[1]); + free(result); +}) + +int main() { + MunitTest tests[] = { + munit_test("/test_create_token_pointer_array_single", test_create_token_pointer_array_single), + munit_test("/test_create_token_pointer_array_multiple", test_create_token_pointer_array_multiple), + munit_test("/test_create_token_pointer_array_memory_allocation", test_create_token_pointer_array_memory_allocation), + munit_null_test, + }; + + MunitSuite suite = munit_suite("create_token_pointer_array", tests); + + return munit_suite_main(&suite, NULL, 0, NULL); +} diff --git a/src/7-3-void-pointers/exercise.c b/src/7-3-void-pointers/exercise.c new file mode 100644 index 0000000..be2e061 --- /dev/null +++ b/src/7-3-void-pointers/exercise.c @@ -0,0 +1,13 @@ +#include "exercise.h" + +void snek_zero_out(void *ptr, snek_object_kind_t kind){ + if (kind == INTEGER) { + ((snek_int_t *)ptr)->value = 0; + } + if (kind == FLOAT) { + ((snek_float_t *)ptr)->value = 0.0; + } + if (kind == BOOL) { + ((snek_bool_t *)ptr)->value = 0; + } +} diff --git a/src/7-3-void-pointers/exercise.h b/src/7-3-void-pointers/exercise.h new file mode 100644 index 0000000..8d98483 --- /dev/null +++ b/src/7-3-void-pointers/exercise.h @@ -0,0 +1,22 @@ +typedef enum SnekObjectKind { + INTEGER, + FLOAT, + BOOL, +} snek_object_kind_t; + +typedef struct SnekInt { + char *name; + int value; +} snek_int_t; + +typedef struct SnekFloat { + char *name; + float value; +} snek_float_t; + +typedef struct SnekBool { + char *name; + unsigned int value; +} snek_bool_t; + +void snek_zero_out(void *ptr, snek_object_kind_t kind); diff --git a/src/7-3-void-pointers/main.c b/src/7-3-void-pointers/main.c new file mode 100644 index 0000000..18f0600 --- /dev/null +++ b/src/7-3-void-pointers/main.c @@ -0,0 +1,55 @@ +#include "munit.h" +#include "exercise.h" + +munit_case(RUN, test_zero_out_integer, { + snek_int_t integer; + integer.value = 42; + snek_zero_out(&integer, INTEGER); + munit_assert_int(integer.value, ==, 0, "Integer should be zeroed out to 0"); +}); + +munit_case(RUN, test_zero_out_float, { + snek_float_t float_num; + float_num.value = 3.14; + snek_zero_out(&float_num, FLOAT); + munit_assert_float(float_num.value, ==, 0.0, "Float should be zeroed out to 0.0"); +}); + +munit_case(SUBMIT, test_zero_out_bool, { + snek_bool_t boolean; + boolean.value = 1; + snek_zero_out(&boolean, BOOL); + munit_assert_int(boolean.value, ==, 0, "Boolean should be zeroed out to 0"); +}); + +munit_case(SUBMIT, test_zero_out_nonzero_values, { + snek_int_t integer; + snek_float_t float_num; + snek_bool_t boolean; + + integer.value = -100; + float_num.value = -99.99; + boolean.value = 255; + + snek_zero_out(&integer, INTEGER); + snek_zero_out(&float_num, FLOAT); + snek_zero_out(&boolean, BOOL); + + munit_assert_int(integer.value, ==, 0, "Negative integer should be zeroed out to 0"); + munit_assert_float(float_num.value, ==, 0.0, "Negative float should be zeroed out to 0.0"); + munit_assert_int(boolean.value, ==, 0, "Non-zero boolean should be zeroed out to 0"); +}); + +int main() { + MunitTest tests[] = { + munit_test("/test_zero_out_integer", test_zero_out_integer), + munit_test("/test_zero_out_float", test_zero_out_float), + munit_test("/test_zero_out_bool", test_zero_out_bool), + munit_test("/test_zero_out_nonzero_values", test_zero_out_nonzero_values), + munit_null_test, + }; + + MunitSuite suite = munit_suite("snek_zero_out", tests); + + return munit_suite_main(&suite, NULL, 0, NULL); +} diff --git a/src/7-4-swapping-integers/exercise.c b/src/7-4-swapping-integers/exercise.c new file mode 100644 index 0000000..a0165c8 --- /dev/null +++ b/src/7-4-swapping-integers/exercise.c @@ -0,0 +1,16 @@ +void swap_ints(int *a, int *b) { + if (a == b) return; + + // Either: + + int tmp = *a; + *a = *b; + *b = tmp; + + // Or: + + // Below works, but is kind of a meme answer + // *a ^= *b; + // *b ^= *a; + // *a ^= *b; +} diff --git a/src/7-4-swapping-integers/exercise.h b/src/7-4-swapping-integers/exercise.h new file mode 100644 index 0000000..fced6db --- /dev/null +++ b/src/7-4-swapping-integers/exercise.h @@ -0,0 +1 @@ +void swap_ints(int *a, int *b); diff --git a/src/7-4-swapping-integers/main.c b/src/7-4-swapping-integers/main.c new file mode 100644 index 0000000..0d625af --- /dev/null +++ b/src/7-4-swapping-integers/main.c @@ -0,0 +1,35 @@ +#include +#include +#include + +#include "exercise.h" +#include "munit.h" + +munit_case(RUN, test_swap_ints, { + int a = 5; + int b = 6; + + swap_ints(&a, &b); + + assert_int(a, ==, 6, "a is now 6"); + assert_int(b, ==, 5, "b is now 5"); +}); + +munit_case(SUBMIT, test_swap_ints_same, { + int a = 5; + + swap_ints(&a, &a); + + assert_int(a, ==, 5, "a is still 5"); +}); + +int main() { + MunitTest tests[] = { + munit_test("/swap_ints", test_swap_ints), + munit_test("/swap_ints_same", test_swap_ints_same), + munit_null_test, + }; + + MunitSuite suite = munit_suite("void-pointer", tests); + return munit_suite_main(&suite, NULL, 0, NULL); +} diff --git a/src/7-5-swapping-strings/exercise.c b/src/7-5-swapping-strings/exercise.c new file mode 100644 index 0000000..3498cf8 --- /dev/null +++ b/src/7-5-swapping-strings/exercise.c @@ -0,0 +1,7 @@ +void swap_strings(char **a, char **b) { + if (a == b) return; + + char *tmp = *a; + *a = *b; + *b = tmp; +} diff --git a/src/7-5-swapping-strings/exercise.h b/src/7-5-swapping-strings/exercise.h new file mode 100644 index 0000000..1f6e904 --- /dev/null +++ b/src/7-5-swapping-strings/exercise.h @@ -0,0 +1 @@ +void swap_strings(char **a, char **b); diff --git a/src/7-5-swapping-strings/main.c b/src/7-5-swapping-strings/main.c new file mode 100644 index 0000000..5d9aff8 --- /dev/null +++ b/src/7-5-swapping-strings/main.c @@ -0,0 +1,37 @@ +#include +#include +#include + +#include "exercise.h" +#include "munit.h" + +munit_case(RUN, test_swap_str, { + char *a = "Hello"; + char *b = "Goodbye"; + + swap_strings(&a, &b); + + assert_string_equal(a, "Goodbye", "a is now 'Goodbye'"); + assert_string_equal(b, "Hello", "b is now 'Hello'"); +}); + +munit_case(SUBMIT, test_swap_str_long, { + char *a = "terminal.shop"; + char *b = "ssh"; + + swap_strings(&a, &b); + + assert_string_equal(a, "ssh", "a is now 'ssh'"); + assert_string_equal(b, "terminal.shop", "b is now 'terminal.shop'"); +}); + +int main() { + MunitTest tests[] = { + munit_test("/swap_str", test_swap_str), + munit_test("/test_swap_str_long", test_swap_str_long), + munit_null_test, + }; + + MunitSuite suite = munit_suite("void-pointer", tests); + return munit_suite_main(&suite, NULL, 0, NULL); +} diff --git a/src/7-6-generic-swap/exercise.c b/src/7-6-generic-swap/exercise.c new file mode 100644 index 0000000..a56b671 --- /dev/null +++ b/src/7-6-generic-swap/exercise.c @@ -0,0 +1,13 @@ +#include +#include + +void swap(void *vp1, void *vp2, size_t size) { + if (vp1 == vp2) return; + + void *tmp = malloc(size); + if (tmp == NULL) return; + memcpy(tmp, vp1, size); + memcpy(vp1, vp2, size); + memcpy(vp2, tmp, size); + free(tmp); +} diff --git a/src/7-6-generic-swap/exercise.h b/src/7-6-generic-swap/exercise.h new file mode 100644 index 0000000..707fe6e --- /dev/null +++ b/src/7-6-generic-swap/exercise.h @@ -0,0 +1,3 @@ +#include + +void swap(void *vp1, void *vp2, size_t size); diff --git a/src/7-6-generic-swap/main.c b/src/7-6-generic-swap/main.c new file mode 100644 index 0000000..0fcce2e --- /dev/null +++ b/src/7-6-generic-swap/main.c @@ -0,0 +1,60 @@ +// #include "bootlib.h" +#include "munit.h" + +#include "exercise.h" +#include + +typedef struct CoffeeShop { + uint64_t quality; + uint64_t taste; + uint64_t branding; +} coffee_shop_t; + +munit_case(RUN, test_generic_ints, { + int i1 = 1234; + int i2 = 5678; + + swap(&i1, &i2, sizeof(int)); + + assert_int(i1, ==, 5678, "i1 should be i2's original value"); + assert_int(i2, ==, 1234, "i2 should be i1's original value"); + // assert_true(boot_all_freed()); +}); + +munit_case(RUN, test_generic_strings, { + char *s1 = "dax"; + char *s2 = "adam"; + + swap(&s1, &s2, sizeof(char *)); + assert_string_equal(s1, "adam", "s1 should be s2's original value"); + assert_string_equal(s2, "dax", "s2 should be s1's original value"); + // assert_true(boot_all_freed()); +}); + +munit_case(SUBMIT, test_generic_structs, { + coffee_shop_t sbucks = {2, 3, 4}; + coffee_shop_t terminalshop = {10, 10, 10}; + + swap(&sbucks, &terminalshop, sizeof(coffee_shop_t)); + + assert_int(sbucks.quality, ==, 10, "sbucks.quality should be terminalshop.quality"); + assert_int(sbucks.taste, ==, 10, "sbucks.taste should be terminalshop.taste"); + assert_int(sbucks.branding, ==, 10, "sbucks.branding should be terminalshop.branding"); + + assert_int(terminalshop.quality, ==, 2, "terminalshop.quality should be sbucks.quality"); + assert_int(terminalshop.taste, ==, 3, "terminalshop.taste should be sbucks.taste"); + assert_int(terminalshop.branding, ==, 4, "terminalshop.branding should be sbucks.branding"); +}); + +int main() { + MunitTest tests[] = { + munit_test("/generic_ints", test_generic_ints), + munit_test("/generic_strings", test_generic_strings), + munit_test("/generic_struct", test_generic_structs), + munit_null_test, + }; + + MunitSuite suite = munit_suite("swap", tests); + + return munit_suite_main(&suite, NULL, 0, NULL); +} diff --git a/src/munit.h b/src/munit.h index bfdda81..d6822d8 100644 --- a/src/munit.h +++ b/src/munit.h @@ -6,12 +6,13 @@ // ----------------------------------------- // Test suite macros -#define munit_case(NAME, FUNCNAME, BODY) \ +#define munit_case(NAME, FUNCNAME, ...) \ static MunitResult FUNCNAME(const MunitParameter params[], void* data) \ { \ (void)params; \ (void)data; \ - BODY return MUNIT_OK; \ + __VA_ARGS__ \ + return MUNIT_OK; \ } #define munit_test(NAME, FN) \ @@ -26,9 +27,17 @@ // ----------------------------------------- // Overwrite assertion macros, extended with "msg" parameter +#undef munit_assert_int +#define munit_assert_int(A, OP, B, MSG) \ + munit_assert_type(int, "d", A, OP, B) + +#undef munit_assert_float +#define munit_assert_float(A, OP, B, MSG) \ + munit_assert_type(float, "f", A, OP, B) + #undef assert_int #define assert_int(A, OP, B, MSG) \ - munit_assert_int(A, OP, B); + munit_assert_int(A, OP, B, MSG); #undef assert_uint #define assert_uint(A, OP, B, MSG) \ @@ -55,3 +64,39 @@ #undef munit_assert_uint32 #define munit_assert_uint32(A, OP, B, MSG) \ munit_assert_type(munit_uint32_t, PRIu32, A, OP, B) + +// string + +#undef munit_assert_string_equal +#define munit_assert_string_equal(A, B, MSG) \ + do { \ + const char* munit_tmp_a_ = (A); \ + const char* munit_tmp_b_ = (B); \ + if (MUNIT_UNLIKELY(strcmp(munit_tmp_a_, munit_tmp_b_) != 0)) { \ + munit_errorf("assertion failed: string %s == %s (\"%s\" == \"%s\")", \ + #A, #B, munit_tmp_a_, munit_tmp_b_); \ + } \ + MUNIT_PUSH_DISABLE_MSVC_C4127_ \ + } while (0) + +#undef assert_string_equal +#define assert_string_equal(A, B, MSG) munit_assert_string_equal(A, B, MSG) + +// null + +#undef munit_assert_null +#define munit_assert_null(PTR, MSG) \ + munit_assert_ptr(PTR, ==, NULL) + +#undef munit_assert_not_null +#define munit_assert_not_null(PTR, MSG) \ + munit_assert_ptr(PTR, !=, NULL) + +// ptr + +#undef assert_ptr_not_null +#define assert_ptr_not_null(PTR, MSG) munit_assert_not_null(PTR, MSG) + +#undef munit_assert_ptr_not_equal +#define munit_assert_ptr_not_equal(A, B, MSG) \ + munit_assert_ptr(A, !=, B)