29 changed files with 588 additions and 5 deletions
@ -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; |
||||
} |
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); |
||||
} |
Loading…
Reference in new issue