Implement allocation checking in the unit tests
This commit is contained in:
+2
-1
@@ -33,13 +33,14 @@ foreach(LESSON ${LESSONS})
|
||||
if(NOT LESSON_SOURCES)
|
||||
continue()
|
||||
endif()
|
||||
list(APPEND LESSON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/bootlib.c)
|
||||
|
||||
# Get last directory name of the path to use as exe
|
||||
get_filename_component(EXE_NAME ${LESSON} NAME)
|
||||
|
||||
add_executable(${EXE_NAME} ${LESSON_SOURCES})
|
||||
target_include_directories(${EXE_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${LESSON})
|
||||
target_link_libraries(${EXE_NAME} munit)
|
||||
|
||||
|
||||
+6
-3
@@ -13,11 +13,14 @@ The first the 3 chapters of the course can be done interactively on the website.
|
||||
[[./bootdev-c.png]]
|
||||
|
||||
If you're reading this with the intention of completing the exercises yourself,
|
||||
just remove the directories from the =src= directory and recreate the directory
|
||||
with the files from the exercise. Alternatively, just remove the file the
|
||||
exercise is asking you to modify as you go.
|
||||
you can find each exercise is in its own directory inside of the =src= directory.
|
||||
Remove all the files that are not called =main.c= and recreate them from the
|
||||
exercises on the boot.dev website as you go through them, so you won't get spoiled.
|
||||
|
||||
Note:
|
||||
- In order to verify allocations in the unit tests, please use the wrapper
|
||||
functions =boot_malloc=, =boot_calloc=, =boot_realloc= and =boot_free= from
|
||||
=boot_lib.h= instead of the =stdlib.h= allocation functions
|
||||
- In chapter 6 exercise 6, macOS malloc will almost never return a NULL pointer
|
||||
due to virtual memory overcommit, so you should check for
|
||||
~size == 1024 * 1024 * 100)~ instead of ~array == NULL~
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// #include "bootlib.h"
|
||||
#include "bootlib.h"
|
||||
#include "munit.h"
|
||||
#include "snekobject.h"
|
||||
|
||||
@@ -9,7 +9,7 @@ munit_case(RUN, test_int_has_refcount, {
|
||||
snek_object_t *obj = new_snek_integer(10);
|
||||
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation");
|
||||
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
});
|
||||
|
||||
munit_case(RUN, test_inc_refcount, {
|
||||
@@ -19,7 +19,7 @@ munit_case(RUN, test_inc_refcount, {
|
||||
refcount_inc(obj);
|
||||
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
||||
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
});
|
||||
|
||||
munit_case(RUN, test_dec_refcount, {
|
||||
@@ -31,10 +31,10 @@ munit_case(RUN, test_dec_refcount, {
|
||||
refcount_dec(obj);
|
||||
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
||||
|
||||
// assert(!boot_is_freed(obj));
|
||||
assert(!boot_is_freed(obj));
|
||||
|
||||
// Object is still alive, so we will free manually.
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
});
|
||||
|
||||
munit_case(SUBMIT, test_refcount_free_is_called, {
|
||||
@@ -47,8 +47,8 @@ munit_case(SUBMIT, test_refcount_free_is_called, {
|
||||
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
||||
|
||||
refcount_dec(obj);
|
||||
// assert(boot_is_freed(obj));
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_is_freed(obj));
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(SUBMIT, test_allocated_string_is_freed, {
|
||||
@@ -62,8 +62,8 @@ munit_case(SUBMIT, test_allocated_string_is_freed, {
|
||||
assert_string_equal(obj->data.v_string, "Hello @wagslane!", "references str");
|
||||
|
||||
refcount_dec(obj);
|
||||
// assert(boot_is_freed(obj));
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_is_freed(obj));
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
int main() {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bootlib.h"
|
||||
#include "snekobject.h"
|
||||
|
||||
void refcount_dec(snek_object_t *obj) {
|
||||
@@ -14,11 +15,11 @@ void refcount_dec(snek_object_t *obj) {
|
||||
void refcount_free(snek_object_t *obj) {
|
||||
if (obj == NULL) return;
|
||||
if (obj->kind == INTEGER || obj->kind == FLOAT) {
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
}
|
||||
if (obj->kind == STRING) {
|
||||
free(obj->data.v_string);
|
||||
free(obj);
|
||||
boot_free(obj->data.v_string);
|
||||
boot_free(obj);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +35,7 @@ void refcount_inc(snek_object_t *obj) {
|
||||
}
|
||||
|
||||
snek_object_t *_new_snek_object() {
|
||||
snek_object_t *obj = calloc(1, sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_calloc(1, sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -50,9 +51,9 @@ snek_object_t *new_snek_array(size_t size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snek_object_t **elements = calloc(size, sizeof(snek_object_t *));
|
||||
snek_object_t **elements = boot_calloc(size, sizeof(snek_object_t *));
|
||||
if (elements == NULL) {
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -109,9 +110,9 @@ snek_object_t *new_snek_string(char *value) {
|
||||
}
|
||||
|
||||
int len = strlen(value);
|
||||
char *dst = malloc(len + 1);
|
||||
char *dst = boot_malloc(len + 1);
|
||||
if (dst == NULL) {
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
+17
-17
@@ -1,7 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// #include "bootlib.h"
|
||||
#include "bootlib.h"
|
||||
#include "munit.h"
|
||||
#include "snekobject.h"
|
||||
|
||||
@@ -17,20 +17,20 @@ munit_case(RUN, test_vector3_refcounting, {
|
||||
|
||||
// `foo` is stil referenced in the `vec`, so it should not be freed.
|
||||
refcount_dec(foo);
|
||||
// assert(!boot_is_freed(foo));
|
||||
assert(!boot_is_freed(foo));
|
||||
|
||||
refcount_dec(vec);
|
||||
// assert(boot_is_freed(foo));
|
||||
assert(boot_is_freed(foo));
|
||||
|
||||
// These are still alive, they have the original reference still.
|
||||
// assert(!boot_is_freed(bar));
|
||||
// assert(!boot_is_freed(baz));
|
||||
assert(!boot_is_freed(bar));
|
||||
assert(!boot_is_freed(baz));
|
||||
|
||||
// Decrement the last reference to the objects, so they will be freed.
|
||||
refcount_dec(bar);
|
||||
refcount_dec(baz);
|
||||
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(SUBMIT, test_vector3_refcounting_same, {
|
||||
@@ -41,19 +41,19 @@ munit_case(SUBMIT, test_vector3_refcounting_same, {
|
||||
|
||||
// `foo` is stil referenced in the `vec`, so it should not be freed.
|
||||
refcount_dec(foo);
|
||||
// assert(!boot_is_freed(foo));
|
||||
assert(!boot_is_freed(foo));
|
||||
|
||||
refcount_dec(vec);
|
||||
// assert(boot_is_freed(foo));
|
||||
// assert(boot_is_freed(vec));
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_is_freed(foo));
|
||||
assert(boot_is_freed(vec));
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(RUN, test_int_has_refcount, {
|
||||
snek_object_t *obj = new_snek_integer(10);
|
||||
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation");
|
||||
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
});
|
||||
|
||||
munit_case(RUN, test_inc_refcount, {
|
||||
@@ -63,7 +63,7 @@ munit_case(RUN, test_inc_refcount, {
|
||||
refcount_inc(obj);
|
||||
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
||||
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
});
|
||||
|
||||
munit_case(RUN, test_dec_refcount, {
|
||||
@@ -78,7 +78,7 @@ munit_case(RUN, test_dec_refcount, {
|
||||
// assert(!boot_is_freed(obj));
|
||||
|
||||
// Object is still alive, so we will free manually.
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
});
|
||||
|
||||
munit_case(RUN, test_refcount_free_is_called, {
|
||||
@@ -91,8 +91,8 @@ munit_case(RUN, test_refcount_free_is_called, {
|
||||
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
||||
|
||||
refcount_dec(obj);
|
||||
// assert(boot_is_freed(obj));
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_is_freed(obj));
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(RUN, test_allocated_string_is_freed, {
|
||||
@@ -106,8 +106,8 @@ munit_case(RUN, test_allocated_string_is_freed, {
|
||||
assert_string_equal(obj->data.v_string, "Hello @wagslane!", "references str");
|
||||
|
||||
refcount_dec(obj);
|
||||
// assert(boot_is_freed(obj));
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_is_freed(obj));
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
int main() {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bootlib.h"
|
||||
#include "snekobject.h"
|
||||
|
||||
snek_object_t *_new_snek_object();
|
||||
@@ -31,7 +32,7 @@ void refcount_free(snek_object_t *obj)
|
||||
case FLOAT:
|
||||
break;
|
||||
case STRING:
|
||||
free(obj->data.v_string);
|
||||
boot_free(obj->data.v_string);
|
||||
break;
|
||||
case VECTOR3: {
|
||||
refcount_dec(obj->data.v_vector3.x);
|
||||
@@ -43,7 +44,7 @@ void refcount_free(snek_object_t *obj)
|
||||
assert(false);
|
||||
}
|
||||
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
}
|
||||
|
||||
// don't touch below this line
|
||||
@@ -69,7 +70,7 @@ void refcount_dec(snek_object_t *obj) {
|
||||
}
|
||||
|
||||
snek_object_t *_new_snek_object() {
|
||||
snek_object_t *obj = calloc(1, sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_calloc(1, sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -85,9 +86,9 @@ snek_object_t *new_snek_array(size_t size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snek_object_t **elements = calloc(size, sizeof(snek_object_t *));
|
||||
snek_object_t **elements = boot_calloc(size, sizeof(snek_object_t *));
|
||||
if (elements == NULL) {
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -126,9 +127,9 @@ snek_object_t *new_snek_string(char *value) {
|
||||
}
|
||||
|
||||
int len = strlen(value);
|
||||
char *dst = malloc(len + 1);
|
||||
char *dst = boot_malloc(len + 1);
|
||||
if (dst == NULL) {
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
+19
-19
@@ -1,7 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// #include "bootlib.h"
|
||||
#include "bootlib.h"
|
||||
#include "munit.h"
|
||||
#include "snekobject.h"
|
||||
|
||||
@@ -12,11 +12,11 @@ munit_case(RUN, test_array_set, {
|
||||
snek_array_set(array, 0, foo);
|
||||
assert_int(foo->refcount, ==, 2, "foo is now referenced by array");
|
||||
|
||||
// assert(!boot_is_freed(foo));
|
||||
assert(!boot_is_freed(foo));
|
||||
|
||||
refcount_dec(foo);
|
||||
refcount_dec(array);
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(SUBMIT, test_array_free, {
|
||||
@@ -33,17 +33,17 @@ munit_case(SUBMIT, test_array_free, {
|
||||
|
||||
// `foo` is stil referenced in the `array`, so it should not be freed.
|
||||
refcount_dec(foo);
|
||||
// assert(!boot_is_freed(foo));
|
||||
assert(!boot_is_freed(foo));
|
||||
|
||||
// Overwrite index 0, which is `foo`, with `baz`.
|
||||
// Now `foo` is not referenced by `array`, so it should be freed.
|
||||
snek_array_set(array, 0, baz);
|
||||
// assert(boot_is_freed(foo));
|
||||
assert(boot_is_freed(foo));
|
||||
|
||||
refcount_dec(bar);
|
||||
refcount_dec(baz);
|
||||
refcount_dec(array);
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(RUN, test_vector3_refcounting, {
|
||||
@@ -58,27 +58,27 @@ munit_case(RUN, test_vector3_refcounting, {
|
||||
|
||||
// `foo` is stil referenced in the `vec`, so it should not be freed.
|
||||
refcount_dec(foo);
|
||||
// assert(!boot_is_freed(foo));
|
||||
assert(!boot_is_freed(foo));
|
||||
|
||||
refcount_dec(vec);
|
||||
// assert(boot_is_freed(foo));
|
||||
assert(boot_is_freed(foo));
|
||||
|
||||
// These are still alive, they have the original reference still.
|
||||
// assert(!boot_is_freed(bar));
|
||||
// assert(!boot_is_freed(baz));
|
||||
assert(!boot_is_freed(bar));
|
||||
assert(!boot_is_freed(baz));
|
||||
|
||||
// Decrement the last reference to the objects, so they will be freed.
|
||||
refcount_dec(bar);
|
||||
refcount_dec(baz);
|
||||
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(RUN, test_int_has_refcount, {
|
||||
snek_object_t *obj = new_snek_integer(10);
|
||||
assert_int(obj->refcount, ==, 1, "Refcount should be 1 on creation");
|
||||
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
});
|
||||
|
||||
munit_case(RUN, test_inc_refcount, {
|
||||
@@ -88,7 +88,7 @@ munit_case(RUN, test_inc_refcount, {
|
||||
refcount_inc(obj);
|
||||
assert_int(obj->refcount, ==, 2, "Refcount should be incremented");
|
||||
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
});
|
||||
|
||||
munit_case(RUN, test_dec_refcount, {
|
||||
@@ -100,10 +100,10 @@ munit_case(RUN, test_dec_refcount, {
|
||||
refcount_dec(obj);
|
||||
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
||||
|
||||
// assert(!boot_is_freed(obj));
|
||||
assert(!boot_is_freed(obj));
|
||||
|
||||
// Object is still alive, so we will free manually.
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
});
|
||||
|
||||
munit_case(RUN, test_refcount_free_is_called, {
|
||||
@@ -116,8 +116,8 @@ munit_case(RUN, test_refcount_free_is_called, {
|
||||
assert_int(obj->refcount, ==, 1, "Refcount should be decremented");
|
||||
|
||||
refcount_dec(obj);
|
||||
// assert(boot_is_freed(obj));
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_is_freed(obj));
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(RUN, test_allocated_string_is_freed, {
|
||||
@@ -131,8 +131,8 @@ munit_case(RUN, test_allocated_string_is_freed, {
|
||||
assert_string_equal(obj->data.v_string, "Hello @wagslane!", "references str");
|
||||
|
||||
refcount_dec(obj);
|
||||
// assert(boot_is_freed(obj));
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_is_freed(obj));
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
int main() {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bootlib.h"
|
||||
#include "snekobject.h"
|
||||
|
||||
bool snek_array_set(snek_object_t *snek_obj, size_t index, snek_object_t *value)
|
||||
@@ -31,7 +32,7 @@ void refcount_free(snek_object_t *obj)
|
||||
case FLOAT:
|
||||
break;
|
||||
case STRING:
|
||||
free(obj->data.v_string);
|
||||
boot_free(obj->data.v_string);
|
||||
break;
|
||||
case VECTOR3: {
|
||||
snek_vector_t vec = obj->data.v_vector3;
|
||||
@@ -44,13 +45,13 @@ void refcount_free(snek_object_t *obj)
|
||||
for (int i = 0; i < obj->data.v_array.size; i++) {
|
||||
refcount_dec(obj->data.v_array.elements[i]);
|
||||
}
|
||||
free(obj->data.v_array.elements);
|
||||
boot_free(obj->data.v_array.elements);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
}
|
||||
|
||||
// don't touch below this line
|
||||
@@ -92,7 +93,7 @@ void refcount_dec(snek_object_t *obj) {
|
||||
}
|
||||
|
||||
snek_object_t *_new_snek_object() {
|
||||
snek_object_t *obj = calloc(1, sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_calloc(1, sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -108,9 +109,9 @@ snek_object_t *new_snek_array(size_t size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snek_object_t **elements = calloc(size, sizeof(snek_object_t *));
|
||||
snek_object_t **elements = boot_calloc(size, sizeof(snek_object_t *));
|
||||
if (elements == NULL) {
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -149,9 +150,9 @@ snek_object_t *new_snek_string(char *value) {
|
||||
}
|
||||
|
||||
int len = strlen(value);
|
||||
char *dst = malloc(len + 1);
|
||||
char *dst = boot_malloc(len + 1);
|
||||
if (dst == NULL) {
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
// Q: Why doesn't the snek_add function need to take care of
|
||||
// garbage collecting the resulting object?
|
||||
|
||||
// A:
|
||||
// A: Because we've coded the GC logic to happen automatically whenever a
|
||||
// reference count hits 0
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bootlib.h"
|
||||
|
||||
void swap(void *vp1, void *vp2, size_t size) {
|
||||
if (vp1 == vp2) return;
|
||||
|
||||
void *tmp = malloc(size);
|
||||
void *tmp = boot_malloc(size);
|
||||
if (tmp == NULL) return;
|
||||
memcpy(tmp, vp1, size);
|
||||
memcpy(vp1, vp2, size);
|
||||
memcpy(vp2, tmp, size);
|
||||
free(tmp);
|
||||
boot_free(tmp);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// #include "bootlib.h"
|
||||
#include "bootlib.h"
|
||||
#include "munit.h"
|
||||
|
||||
#include "exercise.h"
|
||||
@@ -18,7 +18,7 @@ munit_case(RUN, test_generic_ints, {
|
||||
|
||||
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());
|
||||
assert_true(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(RUN, test_generic_strings, {
|
||||
@@ -28,7 +28,7 @@ munit_case(RUN, test_generic_strings, {
|
||||
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());
|
||||
assert_true(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(SUBMIT, test_generic_structs, {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// #include "bootlib.h"
|
||||
#include "bootlib.h"
|
||||
#include "munit.h"
|
||||
#include "snekstack.h"
|
||||
|
||||
@@ -8,10 +8,10 @@ munit_case(RUN, create_stack_small, {
|
||||
assert_int(s->count, ==, 0, "No elements in the stack yet");
|
||||
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||
|
||||
free(s->data);
|
||||
free(s);
|
||||
boot_free(s->data);
|
||||
boot_free(s);
|
||||
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(SUBMIT, create_stack_large, {
|
||||
@@ -20,10 +20,10 @@ munit_case(SUBMIT, create_stack_large, {
|
||||
assert_int(s->count, ==, 0, "No elements in the stack yet");
|
||||
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||
|
||||
free(s->data);
|
||||
free(s);
|
||||
boot_free(s->data);
|
||||
boot_free(s);
|
||||
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
int main() {
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bootlib.h"
|
||||
#include "snekstack.h"
|
||||
|
||||
my_stack_t *stack_new(size_t capacity)
|
||||
{
|
||||
my_stack_t *stack = (my_stack_t *)malloc(sizeof(my_stack_t));
|
||||
my_stack_t *stack = (my_stack_t *)boot_malloc(sizeof(my_stack_t));
|
||||
if (stack == NULL) return NULL;
|
||||
stack->count = 0;
|
||||
stack->capacity = capacity;
|
||||
stack->data = malloc(sizeof(void*) * capacity);
|
||||
stack->data = boot_malloc(sizeof(void*) * capacity);
|
||||
if (stack->data == NULL) {
|
||||
free(stack);
|
||||
boot_free(stack);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
+11
-11
@@ -1,4 +1,4 @@
|
||||
// #include "bootlib.h"
|
||||
#include "bootlib.h"
|
||||
#include "munit.h"
|
||||
#include "snekstack.h"
|
||||
|
||||
@@ -9,11 +9,11 @@ munit_case(RUN, create_stack, {
|
||||
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||
|
||||
// Clean up our allocated data.
|
||||
free(s->data);
|
||||
free(s);
|
||||
boot_free(s->data);
|
||||
boot_free(s);
|
||||
|
||||
// Should be nothing left that is allocated.
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(RUN, push_stack, {
|
||||
@@ -34,11 +34,11 @@ munit_case(RUN, push_stack, {
|
||||
assert_ptr_equal(s->data[0], &a, "element inserted into stack");
|
||||
|
||||
// Clean up our allocated data.
|
||||
free(s->data);
|
||||
free(s);
|
||||
boot_free(s->data);
|
||||
boot_free(s);
|
||||
|
||||
// Should be nothing left that is allocated.
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(SUBMIT, push_double_capacity, {
|
||||
@@ -62,14 +62,14 @@ munit_case(SUBMIT, push_double_capacity, {
|
||||
assert_int(s->count, ==, 3, "3 elements in the stack");
|
||||
|
||||
// Should reallocate memory.
|
||||
// assert_int_equal(boot_realloc_count(), 1, "Must reallocate memory for stack");
|
||||
assert_int_equal(boot_realloc_count(), 1, "Must reallocate memory for stack");
|
||||
|
||||
// Clean up our allocated data.
|
||||
free(s->data);
|
||||
free(s);
|
||||
boot_free(s->data);
|
||||
boot_free(s);
|
||||
|
||||
// Should be nothing left that is allocated.
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bootlib.h"
|
||||
#include "snekstack.h"
|
||||
|
||||
void stack_push(my_stack_t *stack, void *obj) {
|
||||
|
||||
void stack_push(my_stack_t *stack, void *obj)
|
||||
{
|
||||
if (stack->count >= stack->capacity) {
|
||||
void **data = realloc(stack->data, sizeof(void *) * stack->capacity * 2);
|
||||
void **data = boot_realloc(stack->data, sizeof(void *) * stack->capacity * 2);
|
||||
if (data == NULL) return;
|
||||
stack->data = data;
|
||||
stack->capacity *= 2;
|
||||
@@ -21,16 +22,16 @@ void stack_push(my_stack_t *stack, void *obj) {
|
||||
// don't touch below this line
|
||||
|
||||
my_stack_t *stack_new(size_t capacity) {
|
||||
my_stack_t *stack = malloc(sizeof(my_stack_t));
|
||||
my_stack_t *stack = boot_malloc(sizeof(my_stack_t));
|
||||
if (stack == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stack->count = 0;
|
||||
stack->capacity = capacity;
|
||||
stack->data = malloc(stack->capacity * sizeof(void *));
|
||||
stack->data = boot_malloc(stack->capacity * sizeof(void *));
|
||||
if (stack->data == NULL) {
|
||||
free(stack);
|
||||
boot_free(stack);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
+13
-13
@@ -1,4 +1,4 @@
|
||||
// #include "bootlib.h"
|
||||
#include "bootlib.h"
|
||||
#include "munit.h"
|
||||
#include "snekstack.h"
|
||||
|
||||
@@ -37,11 +37,11 @@ munit_case(RUN, pop_stack, {
|
||||
assert_null(popped, "No remaining elements");
|
||||
|
||||
// Clean up our allocated data.
|
||||
free(s->data);
|
||||
free(s);
|
||||
boot_free(s->data);
|
||||
boot_free(s);
|
||||
|
||||
// Should be nothing left that is allocated.
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(SUBMIT, pop_stack_empty, {
|
||||
@@ -56,11 +56,11 @@ munit_case(SUBMIT, pop_stack_empty, {
|
||||
assert_null(popped, "Should return null when popping an empty stack");
|
||||
|
||||
// Clean up our allocated data.
|
||||
free(s->data);
|
||||
free(s);
|
||||
boot_free(s->data);
|
||||
boot_free(s);
|
||||
|
||||
// Should be nothing left that is allocated.
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(RUN, push_stack, {
|
||||
@@ -84,11 +84,11 @@ munit_case(RUN, push_stack, {
|
||||
assert_int(s->count, ==, 3, "3 elements in the stack");
|
||||
|
||||
// Clean up our allocated data.
|
||||
free(s->data);
|
||||
free(s);
|
||||
boot_free(s->data);
|
||||
boot_free(s);
|
||||
|
||||
// Should be nothing left that is allocated.
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(RUN, create_stack, {
|
||||
@@ -98,11 +98,11 @@ munit_case(RUN, create_stack, {
|
||||
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||
|
||||
// Clean up our allocated data.
|
||||
free(s->data);
|
||||
free(s);
|
||||
boot_free(s->data);
|
||||
boot_free(s);
|
||||
|
||||
// Should be nothing left that is allocated.
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bootlib.h"
|
||||
#include "snekstack.h"
|
||||
|
||||
void *stack_pop(my_stack_t *stack) {
|
||||
@@ -15,7 +16,7 @@ void *stack_pop(my_stack_t *stack) {
|
||||
void stack_push(my_stack_t *stack, void *obj) {
|
||||
if (stack->count == stack->capacity) {
|
||||
stack->capacity *= 2;
|
||||
void **temp = realloc(stack->data, stack->capacity * sizeof(void *));
|
||||
void **temp = boot_realloc(stack->data, stack->capacity * sizeof(void *));
|
||||
if (temp == NULL) {
|
||||
stack->capacity /= 2;
|
||||
|
||||
@@ -29,16 +30,16 @@ void stack_push(my_stack_t *stack, void *obj) {
|
||||
}
|
||||
|
||||
my_stack_t *stack_new(size_t capacity) {
|
||||
my_stack_t *stack = malloc(sizeof(my_stack_t));
|
||||
my_stack_t *stack = boot_malloc(sizeof(my_stack_t));
|
||||
if (stack == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stack->count = 0;
|
||||
stack->capacity = capacity;
|
||||
stack->data = malloc(stack->capacity * sizeof(void *));
|
||||
stack->data = boot_malloc(stack->capacity * sizeof(void *));
|
||||
if (stack->data == NULL) {
|
||||
free(stack);
|
||||
boot_free(stack);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// #include "bootlib.h"
|
||||
#include "bootlib.h"
|
||||
#include "munit.h"
|
||||
#include "snekstack.h"
|
||||
|
||||
@@ -37,7 +37,7 @@ munit_case(RUN, pop_stack, {
|
||||
assert_null(popped, "No remaining elements");
|
||||
|
||||
stack_free(s);
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(RUN, push_stack, {
|
||||
@@ -61,7 +61,7 @@ munit_case(RUN, push_stack, {
|
||||
assert_int(s->count, ==, 3, "3 elements in the stack");
|
||||
|
||||
stack_free(s);
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(RUN, create_stack, {
|
||||
@@ -71,7 +71,7 @@ munit_case(RUN, create_stack, {
|
||||
assert_ptr_not_null(s->data, "Allocates the stack data");
|
||||
|
||||
stack_free(s);
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
int main() {
|
||||
|
||||
@@ -2,17 +2,18 @@
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bootlib.h"
|
||||
#include "snekstack.h"
|
||||
|
||||
void stack_free(my_stack_t *stack) {
|
||||
if (stack == NULL) return;
|
||||
|
||||
if (stack->data != NULL) {
|
||||
free(stack->data);
|
||||
boot_free(stack->data);
|
||||
stack->data = NULL;
|
||||
}
|
||||
|
||||
free(stack);
|
||||
boot_free(stack);
|
||||
}
|
||||
|
||||
// don't touch below this line
|
||||
@@ -29,7 +30,7 @@ void *stack_pop(my_stack_t *stack) {
|
||||
void stack_push(my_stack_t *stack, void *obj) {
|
||||
if (stack->count == stack->capacity) {
|
||||
stack->capacity *= 2;
|
||||
void **temp = realloc(stack->data, stack->capacity * sizeof(void *));
|
||||
void **temp = boot_realloc(stack->data, stack->capacity * sizeof(void *));
|
||||
if (temp == NULL) {
|
||||
stack->capacity /= 2;
|
||||
exit(1);
|
||||
@@ -42,16 +43,16 @@ void stack_push(my_stack_t *stack, void *obj) {
|
||||
}
|
||||
|
||||
my_stack_t *stack_new(size_t capacity) {
|
||||
my_stack_t *stack = malloc(sizeof(my_stack_t));
|
||||
my_stack_t *stack = boot_malloc(sizeof(my_stack_t));
|
||||
if (stack == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stack->count = 0;
|
||||
stack->capacity = capacity;
|
||||
stack->data = malloc(stack->capacity * sizeof(void *));
|
||||
stack->data = boot_malloc(stack->capacity * sizeof(void *));
|
||||
if (stack->data == NULL) {
|
||||
free(stack);
|
||||
boot_free(stack);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bootlib.h"
|
||||
#include "munit.h"
|
||||
#include "snekobject.h"
|
||||
|
||||
@@ -7,8 +8,8 @@ munit_case(RUN, test_positive, {
|
||||
snek_object_t *obj = new_snek_float(42);
|
||||
assert_float(obj->data.v_float, ==, 42, "Must accept positive values");
|
||||
|
||||
free(obj);
|
||||
// assert(boot_all_freed());
|
||||
boot_free(obj);
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(SUBMIT, test_zero, {
|
||||
@@ -17,8 +18,8 @@ munit_case(SUBMIT, test_zero, {
|
||||
assert_float(obj->kind, ==, FLOAT, "Must set type to FLOAT");
|
||||
assert_float(obj->data.v_float, ==, 0.0, "Must accept 0.0");
|
||||
|
||||
free(obj);
|
||||
// assert(boot_all_freed());
|
||||
boot_free(obj);
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(SUBMIT, test_negative, {
|
||||
@@ -27,8 +28,8 @@ munit_case(SUBMIT, test_negative, {
|
||||
assert_float(obj->kind, ==, FLOAT, "Must set type to FLOAT");
|
||||
assert_float(obj->data.v_float, ==, -5.0, "Must accept negative numbers");
|
||||
|
||||
free(obj);
|
||||
// assert(boot_all_freed());
|
||||
boot_free(obj);
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
int main() {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bootlib.h"
|
||||
#include "snekobject.h"
|
||||
|
||||
snek_object_t *new_snek_float(float value) {
|
||||
snek_object_t *obj = (snek_object_t *)malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = (snek_object_t *)boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) return NULL;
|
||||
obj->kind = FLOAT;
|
||||
obj->data.v_float = value;
|
||||
@@ -13,7 +14,7 @@ snek_object_t *new_snek_float(float value) {
|
||||
// don't touch below this line
|
||||
|
||||
snek_object_t *new_snek_integer(int value) {
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bootlib.h"
|
||||
#include "munit.h"
|
||||
#include "snekobject.h"
|
||||
|
||||
@@ -21,12 +23,14 @@ munit_case(RUN, test_str_copied, {
|
||||
);
|
||||
|
||||
// Should allocate memory for the string with null terminator.
|
||||
// assert_int_equal(boot_alloc_size(), 22, "Must allocate memory for string");
|
||||
bool is_32_bit = sizeof(void *) == 4;
|
||||
int allocated = 14 + (is_32_bit ? 8 : 16); // pointers are larger on x64
|
||||
assert_int_equal(boot_alloc_size(), allocated, "Must allocate memory for string");
|
||||
|
||||
// Free the string, and then free the object.
|
||||
free(obj->data.v_string);
|
||||
free(obj);
|
||||
// assert(boot_all_freed());
|
||||
boot_free(obj->data.v_string);
|
||||
boot_free(obj);
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
int main() {
|
||||
|
||||
@@ -2,16 +2,17 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bootlib.h"
|
||||
#include "snekobject.h"
|
||||
|
||||
snek_object_t *new_snek_string(char *value) {
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = (snek_object_t *)boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) return NULL;
|
||||
|
||||
size_t size = strlen(value);
|
||||
char *str = (char *)malloc(sizeof(char) * size + 1);
|
||||
char *str = (char *)boot_malloc(sizeof(char) * size + 1);
|
||||
if (str == NULL) {
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -24,7 +25,7 @@ snek_object_t *new_snek_string(char *value) {
|
||||
// don't touch below this line
|
||||
|
||||
snek_object_t *new_snek_integer(int value) {
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -35,7 +36,7 @@ snek_object_t *new_snek_integer(int value) {
|
||||
}
|
||||
|
||||
snek_object_t *new_snek_float(float value) {
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+10
-9
@@ -1,5 +1,6 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bootlib.h"
|
||||
#include "munit.h"
|
||||
#include "snekobject.h"
|
||||
|
||||
@@ -8,7 +9,7 @@ munit_case(RUN, test_returns_null, {
|
||||
|
||||
assert_null(vec, "Should return null when input is null");
|
||||
|
||||
// assert(boot_all_freed());
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
|
||||
@@ -31,11 +32,11 @@ munit_case(RUN, test_vec_multiple_objects, {
|
||||
assert_int(vec->data.v_vector3.z->data.v_int, ==, 3, "should have correct z");
|
||||
|
||||
// Free all of our objects.
|
||||
free(x);
|
||||
free(y);
|
||||
free(z);
|
||||
free(vec);
|
||||
// assert(boot_all_freed());
|
||||
boot_free(x);
|
||||
boot_free(y);
|
||||
boot_free(z);
|
||||
boot_free(vec);
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(SUBMIT, test_vec_same_object, {
|
||||
@@ -62,9 +63,9 @@ munit_case(SUBMIT, test_vec_same_object, {
|
||||
assert_int(vec->data.v_vector3.z->data.v_int, ==, 2, "should have correct z");
|
||||
|
||||
// Free all of our objects.
|
||||
free(i);
|
||||
free(vec);
|
||||
// assert(boot_all_freed());
|
||||
boot_free(i);
|
||||
boot_free(vec);
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
int main() {
|
||||
|
||||
@@ -1,33 +1,25 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bootlib.h"
|
||||
#include "snekobject.h"
|
||||
|
||||
snek_object_t *new_snek_vector3(snek_object_t *x, snek_object_t *y, snek_object_t *z)
|
||||
{
|
||||
if (x == NULL || y == NULL || z == NULL) return NULL;
|
||||
|
||||
snek_object_t *obj = (snek_object_t *)malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = (snek_object_t *)boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) return NULL;
|
||||
|
||||
snek_vector_t *vec = (snek_vector_t *)malloc(sizeof(snek_vector_t));
|
||||
if (vec == NULL) {
|
||||
free(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vec->x = x;
|
||||
vec->y = y;
|
||||
vec->z = z;
|
||||
obj->kind = VECTOR3;
|
||||
obj->data.v_vector3 = *vec;
|
||||
obj->data.v_vector3 = (snek_vector_t){ .x = x, .y = y, .z = z };
|
||||
return obj;
|
||||
}
|
||||
|
||||
// don't touch below this line
|
||||
|
||||
snek_object_t *new_snek_integer(int value) {
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -38,7 +30,7 @@ snek_object_t *new_snek_integer(int value) {
|
||||
}
|
||||
|
||||
snek_object_t *new_snek_float(float value) {
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -49,15 +41,15 @@ snek_object_t *new_snek_float(float value) {
|
||||
}
|
||||
|
||||
snek_object_t *new_snek_string(char *value) {
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int len = strlen(value);
|
||||
char *dst = malloc(len + 1);
|
||||
char *dst = boot_malloc(len + 1);
|
||||
if (dst == NULL) {
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bootlib.h"
|
||||
#include "munit.h"
|
||||
#include "snekobject.h"
|
||||
|
||||
@@ -9,9 +10,9 @@ munit_case(RUN, test_create_empty_array, {
|
||||
assert_int(obj->kind, ==, ARRAY, "Must set type to ARRAY");
|
||||
assert_int(obj->data.v_array.size, ==, 2, "Must set size to 2");
|
||||
|
||||
free(obj->data.v_array.elements);
|
||||
free(obj);
|
||||
// assert(boot_all_freed());
|
||||
boot_free(obj->data.v_array.elements);
|
||||
boot_free(obj);
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(SUBMIT, test_used_calloc, {
|
||||
@@ -20,9 +21,9 @@ munit_case(SUBMIT, test_used_calloc, {
|
||||
assert_ptr_null(obj->data.v_array.elements[0], "Should use calloc");
|
||||
assert_ptr_null(obj->data.v_array.elements[1], "Should use calloc");
|
||||
|
||||
free(obj->data.v_array.elements);
|
||||
free(obj);
|
||||
// assert(boot_all_freed());
|
||||
boot_free(obj->data.v_array.elements);
|
||||
boot_free(obj);
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
int main() {
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bootlib.h"
|
||||
#include "snekobject.h"
|
||||
|
||||
snek_object_t *new_snek_array(size_t size) {
|
||||
snek_object_t *obj = (snek_object_t *)malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = (snek_object_t *)boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) return NULL;
|
||||
|
||||
snek_object_t **arr = (snek_object_t **)calloc(size, sizeof(snek_object_t *));
|
||||
snek_object_t **arr = (snek_object_t **)boot_calloc(size, sizeof(snek_object_t *));
|
||||
if (arr == NULL) {
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -27,7 +28,7 @@ snek_object_t *new_snek_vector3(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -39,7 +40,7 @@ snek_object_t *new_snek_vector3(
|
||||
}
|
||||
|
||||
snek_object_t *new_snek_integer(int value) {
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -50,7 +51,7 @@ snek_object_t *new_snek_integer(int value) {
|
||||
}
|
||||
|
||||
snek_object_t *new_snek_float(float value) {
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -61,15 +62,15 @@ snek_object_t *new_snek_float(float value) {
|
||||
}
|
||||
|
||||
snek_object_t *new_snek_string(char *value) {
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int len = strlen(value);
|
||||
char *dst = malloc(len + 1);
|
||||
char *dst = boot_malloc(len + 1);
|
||||
if (dst == NULL) {
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
+17
-16
@@ -1,5 +1,6 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bootlib.h"
|
||||
#include "munit.h"
|
||||
#include "snekobject.h"
|
||||
|
||||
@@ -25,12 +26,12 @@ munit_case(RUN, test_array, {
|
||||
assert_int(retrieved_second->kind, ==, INTEGER, "Should be a integer");
|
||||
assert_ptr(second, ==, retrieved_second, "Should be the same object");
|
||||
|
||||
free(first->data.v_string);
|
||||
free(first);
|
||||
free(second);
|
||||
free(obj->data.v_array.elements);
|
||||
free(obj);
|
||||
// assert(boot_all_freed());
|
||||
boot_free(first->data.v_string);
|
||||
boot_free(first);
|
||||
boot_free(second);
|
||||
boot_free(obj->data.v_array.elements);
|
||||
boot_free(obj);
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(RUN, test_set_outside_bounds, {
|
||||
@@ -46,11 +47,11 @@ munit_case(RUN, test_set_outside_bounds, {
|
||||
assert_false(snek_array_set(obj, 100, outside));
|
||||
|
||||
// Free memory
|
||||
free(outside->data.v_string);
|
||||
free(outside);
|
||||
free(obj->data.v_array.elements);
|
||||
free(obj);
|
||||
// assert(boot_all_freed());
|
||||
boot_free(outside->data.v_string);
|
||||
boot_free(outside);
|
||||
boot_free(obj->data.v_array.elements);
|
||||
boot_free(obj);
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(SUBMIT, test_get_outside_bounds, {
|
||||
@@ -62,11 +63,11 @@ munit_case(SUBMIT, test_get_outside_bounds, {
|
||||
// Outside of bound
|
||||
assert_null(snek_array_get(obj, 1), "Should not access outside the array");
|
||||
|
||||
free(first->data.v_string);
|
||||
free(first);
|
||||
free(obj->data.v_array.elements);
|
||||
free(obj);
|
||||
// assert(boot_all_freed());
|
||||
boot_free(first->data.v_string);
|
||||
boot_free(first);
|
||||
boot_free(obj->data.v_array.elements);
|
||||
boot_free(obj);
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
int main() {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bootlib.h"
|
||||
#include "snekobject.h"
|
||||
|
||||
bool snek_array_set(snek_object_t *snek_obj, size_t index, snek_object_t *value) {
|
||||
@@ -24,14 +25,14 @@ snek_object_t *snek_array_get(snek_object_t *snek_obj, size_t index) {
|
||||
// don't touch below this line
|
||||
|
||||
snek_object_t *new_snek_array(size_t size) {
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snek_object_t **elements = calloc(size, sizeof(snek_object_t *));
|
||||
snek_object_t **elements = boot_calloc(size, sizeof(snek_object_t *));
|
||||
if (elements == NULL) {
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -47,7 +48,7 @@ snek_object_t *new_snek_vector3(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -59,7 +60,7 @@ snek_object_t *new_snek_vector3(
|
||||
}
|
||||
|
||||
snek_object_t *new_snek_integer(int value) {
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -70,7 +71,7 @@ snek_object_t *new_snek_integer(int value) {
|
||||
}
|
||||
|
||||
snek_object_t *new_snek_float(float value) {
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -81,15 +82,15 @@ snek_object_t *new_snek_float(float value) {
|
||||
}
|
||||
|
||||
snek_object_t *new_snek_string(char *value) {
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int len = strlen(value);
|
||||
char *dst = malloc(len + 1);
|
||||
char *dst = boot_malloc(len + 1);
|
||||
if (dst == NULL) {
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
+17
-16
@@ -1,3 +1,4 @@
|
||||
#include "bootlib.h"
|
||||
#include "munit.h"
|
||||
#include "snekobject.h"
|
||||
|
||||
@@ -5,16 +6,16 @@ munit_case(RUN, test_integer, {
|
||||
snek_object_t *obj = new_snek_integer(42);
|
||||
assert_int(snek_length(obj), ==, 1, "Integers are length 1");
|
||||
|
||||
free(obj);
|
||||
// assert(boot_all_freed());
|
||||
boot_free(obj);
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(RUN, test_float, {
|
||||
snek_object_t *obj = new_snek_float(3.14);
|
||||
assert_int(snek_length(obj), ==, 1, "Floats are length 1");
|
||||
|
||||
free(obj);
|
||||
// assert(boot_all_freed());
|
||||
boot_free(obj);
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(RUN, test_string, {
|
||||
@@ -26,11 +27,11 @@ munit_case(RUN, test_string, {
|
||||
snek_length(longer), ==, strlen("hello, world"), "Should use strlen"
|
||||
);
|
||||
|
||||
free(shorter->data.v_string);
|
||||
free(shorter);
|
||||
free(longer->data.v_string);
|
||||
free(longer);
|
||||
// assert(boot_all_freed());
|
||||
boot_free(shorter->data.v_string);
|
||||
boot_free(shorter);
|
||||
boot_free(longer->data.v_string);
|
||||
boot_free(longer);
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(SUBMIT, test_vector3, {
|
||||
@@ -38,9 +39,9 @@ munit_case(SUBMIT, test_vector3, {
|
||||
snek_object_t *vec = new_snek_vector3(i, i, i);
|
||||
assert_int(snek_length(vec), ==, 3, "Vec3 always has length 3");
|
||||
|
||||
free(i);
|
||||
free(vec);
|
||||
// assert(boot_all_freed());
|
||||
boot_free(i);
|
||||
boot_free(vec);
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
munit_case(SUBMIT, test_array, {
|
||||
@@ -52,10 +53,10 @@ munit_case(SUBMIT, test_array, {
|
||||
|
||||
assert_int(snek_length(arr), ==, 4, "Length of array should be its size");
|
||||
|
||||
free(i);
|
||||
free(arr->data.v_array.elements);
|
||||
free(arr);
|
||||
// assert(boot_all_freed());
|
||||
boot_free(i);
|
||||
boot_free(arr->data.v_array.elements);
|
||||
boot_free(arr);
|
||||
assert(boot_all_freed());
|
||||
});
|
||||
|
||||
int main() {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "bootlib.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -15,14 +16,14 @@ int snek_length(snek_object_t *obj) {
|
||||
// don't touch below this line
|
||||
|
||||
snek_object_t *new_snek_array(size_t size) {
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snek_object_t **elements = calloc(size, sizeof(snek_object_t *));
|
||||
snek_object_t **elements = boot_calloc(size, sizeof(snek_object_t *));
|
||||
if (elements == NULL) {
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -73,7 +74,7 @@ snek_object_t *new_snek_vector3(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -85,7 +86,7 @@ snek_object_t *new_snek_vector3(
|
||||
}
|
||||
|
||||
snek_object_t *new_snek_integer(int value) {
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -96,7 +97,7 @@ snek_object_t *new_snek_integer(int value) {
|
||||
}
|
||||
|
||||
snek_object_t *new_snek_float(float value) {
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -107,15 +108,15 @@ snek_object_t *new_snek_float(float value) {
|
||||
}
|
||||
|
||||
snek_object_t *new_snek_string(char *value) {
|
||||
snek_object_t *obj = malloc(sizeof(snek_object_t));
|
||||
snek_object_t *obj = boot_malloc(sizeof(snek_object_t));
|
||||
if (obj == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int len = strlen(value);
|
||||
char *dst = malloc(len + 1);
|
||||
char *dst = boot_malloc(len + 1);
|
||||
if (dst == NULL) {
|
||||
free(obj);
|
||||
boot_free(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "bootlib.h"
|
||||
|
||||
typedef struct Allocation {
|
||||
void* ptr;
|
||||
size_t size;
|
||||
bool freed;
|
||||
struct Allocation *next;
|
||||
} Allocation;
|
||||
|
||||
static Allocation *allocations = NULL; // backwards linked list
|
||||
static int allocated_count = 0;
|
||||
static int reallocated_count = 0;
|
||||
static int total_size = 0;
|
||||
|
||||
void *create_allocation(void *allocated, size_t size);
|
||||
Allocation *find_allocation(void *ptr);
|
||||
|
||||
void *boot_malloc(size_t size)
|
||||
{
|
||||
void *allocated = malloc(size);
|
||||
if (allocated == NULL) return NULL;
|
||||
|
||||
return create_allocation(allocated, size);
|
||||
}
|
||||
|
||||
void *boot_calloc (size_t num, size_t size)
|
||||
{
|
||||
void *allocated = calloc(num, size);
|
||||
if (allocated == NULL) return NULL;
|
||||
|
||||
return create_allocation(allocated, num * size);
|
||||
}
|
||||
|
||||
void *boot_realloc(void* ptr, size_t size)
|
||||
{
|
||||
if (ptr == NULL) return NULL;
|
||||
|
||||
void *allocated = realloc(ptr, size);
|
||||
if (allocated == NULL) return NULL;
|
||||
|
||||
reallocated_count++;
|
||||
|
||||
Allocation *allocation = find_allocation(ptr);
|
||||
if (allocated == ptr) { // realloc resized the existing ptr's memory block
|
||||
allocation->size = size;
|
||||
total_size += size - allocation->size;
|
||||
return allocated;
|
||||
}
|
||||
allocation->freed = true;
|
||||
allocated_count--;
|
||||
total_size -= allocation->size;
|
||||
|
||||
return create_allocation(allocated, size);
|
||||
}
|
||||
|
||||
void boot_free (void *ptr)
|
||||
{
|
||||
if (ptr == NULL) return;
|
||||
|
||||
free(ptr);
|
||||
|
||||
Allocation *allocation = find_allocation(ptr);
|
||||
allocation->freed = true;
|
||||
allocated_count--;
|
||||
total_size -= allocation->size;
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
bool boot_all_freed()
|
||||
{
|
||||
return allocated_count == 0;
|
||||
}
|
||||
|
||||
bool boot_is_freed(void *ptr)
|
||||
{
|
||||
return find_allocation(ptr)->freed;
|
||||
}
|
||||
|
||||
int boot_realloc_count()
|
||||
{
|
||||
return reallocated_count;
|
||||
}
|
||||
|
||||
int boot_alloc_size()
|
||||
{
|
||||
return total_size;
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
void *create_allocation(void *allocated, size_t size)
|
||||
{
|
||||
if (allocated == NULL) return NULL;
|
||||
|
||||
total_size += size;
|
||||
|
||||
Allocation *allocation = (Allocation *)malloc(sizeof(Allocation));
|
||||
if (allocation == NULL) return NULL;
|
||||
allocation->ptr = allocated;
|
||||
allocation->size = size;
|
||||
allocation->freed = false;
|
||||
allocation->next = allocations;
|
||||
allocations = allocation;
|
||||
|
||||
allocated_count++;
|
||||
|
||||
return allocated;
|
||||
}
|
||||
|
||||
Allocation *find_allocation(void *ptr)
|
||||
{
|
||||
if (allocations == NULL) return NULL;
|
||||
|
||||
Allocation *current = allocations;
|
||||
while (true) {
|
||||
if (current == NULL) return NULL;
|
||||
if (current->ptr == ptr) return current;
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void *boot_malloc(size_t size);
|
||||
void *boot_calloc (size_t num, size_t size);
|
||||
void *boot_realloc(void* ptr, size_t size);
|
||||
void boot_free (void *ptr);
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
bool boot_all_freed();
|
||||
bool boot_is_freed(void *ptr);
|
||||
int boot_realloc_count();
|
||||
int boot_alloc_size();
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#define MUNIT_ENABLE_ASSERT_ALIASES
|
||||
#include "../vendor/munit/munit.h"
|
||||
|
||||
@@ -40,6 +42,9 @@
|
||||
#define assert_int(A, OP, B, MSG) \
|
||||
munit_assert_int(A, OP, B, MSG);
|
||||
|
||||
#define assert_int_equal(A, B, MSG) \
|
||||
munit_assert_int(A, ==, B, MSG);
|
||||
|
||||
#undef assert_uint
|
||||
#define assert_uint(A, OP, B, MSG) \
|
||||
munit_assert_uint(A, OP, B);
|
||||
|
||||
Reference in New Issue
Block a user