Add more exercises
This commit is contained in:
@@ -5,3 +5,5 @@
|
|||||||
build/
|
build/
|
||||||
|
|
||||||
# Files
|
# Files
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
char* get_full_greeting(char* greeting, char* name, int size)
|
char* get_full_greeting(char* greeting, char* name, int size)
|
||||||
{
|
{
|
||||||
char full_greeting[100];
|
char *full_greeting = (char*)malloc(size * sizeof(char));
|
||||||
snprintf(full_greeting, 100, "%s %s", greeting, name);
|
snprintf(full_greeting, size, "%s %s", greeting, name);
|
||||||
return full_greeting;
|
return full_greeting;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
int *allocate_scalar_array(int size, int multiplier);
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
int *allocate_scalar_list(int size, int multiplier);
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
BIN
Binary file not shown.
@@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
// Q: In a little-endian system, how would the hexadecimal number
|
||||||
|
// 0xA1B2C3D4 be stored in memory?
|
||||||
|
|
||||||
|
// A: 0xD4, 0xC3, 0xB2, 0xA1
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#include "stdlib.h"
|
||||||
|
|
||||||
|
#include "exercise.h"
|
||||||
|
void allocate_int(int **pointer_pointer, int value) {
|
||||||
|
int *number = (int *)malloc(sizeof(int));
|
||||||
|
*pointer_pointer = number;
|
||||||
|
**pointer_pointer = value;
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void allocate_int(int **pointer_pointer, int value);
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
#include "munit.h"
|
||||||
|
#include "exercise.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
void swap_ints(int *a, int *b);
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
void swap_strings(char **a, char **b) {
|
||||||
|
if (a == b) return;
|
||||||
|
|
||||||
|
char *tmp = *a;
|
||||||
|
*a = *b;
|
||||||
|
*b = tmp;
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
void swap_strings(char **a, char **b);
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void swap(void *vp1, void *vp2, size_t size);
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
// #include "bootlib.h"
|
||||||
|
#include "munit.h"
|
||||||
|
|
||||||
|
#include "exercise.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
+48
-3
@@ -6,12 +6,13 @@
|
|||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
// Test suite macros
|
// Test suite macros
|
||||||
|
|
||||||
#define munit_case(NAME, FUNCNAME, BODY) \
|
#define munit_case(NAME, FUNCNAME, ...) \
|
||||||
static MunitResult FUNCNAME(const MunitParameter params[], void* data) \
|
static MunitResult FUNCNAME(const MunitParameter params[], void* data) \
|
||||||
{ \
|
{ \
|
||||||
(void)params; \
|
(void)params; \
|
||||||
(void)data; \
|
(void)data; \
|
||||||
BODY return MUNIT_OK; \
|
__VA_ARGS__ \
|
||||||
|
return MUNIT_OK; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define munit_test(NAME, FN) \
|
#define munit_test(NAME, FN) \
|
||||||
@@ -26,9 +27,17 @@
|
|||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
// Overwrite assertion macros, extended with "msg" parameter
|
// 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
|
#undef assert_int
|
||||||
#define assert_int(A, OP, B, MSG) \
|
#define assert_int(A, OP, B, MSG) \
|
||||||
munit_assert_int(A, OP, B);
|
munit_assert_int(A, OP, B, MSG);
|
||||||
|
|
||||||
#undef assert_uint
|
#undef assert_uint
|
||||||
#define assert_uint(A, OP, B, MSG) \
|
#define assert_uint(A, OP, B, MSG) \
|
||||||
@@ -55,3 +64,39 @@
|
|||||||
#undef munit_assert_uint32
|
#undef munit_assert_uint32
|
||||||
#define munit_assert_uint32(A, OP, B, MSG) \
|
#define munit_assert_uint32(A, OP, B, MSG) \
|
||||||
munit_assert_type(munit_uint32_t, PRIu32, A, OP, B)
|
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)
|
||||||
|
|||||||
Reference in New Issue
Block a user