Skip to content

Commit

Permalink
add experimental malloc mocks
Browse files Browse the repository at this point in the history
  • Loading branch information
Totto16 committed Sep 9, 2024
1 parent 86b2118 commit 30621ff
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 4 deletions.
39 changes: 39 additions & 0 deletions tests/malloc_tests.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <criterion/criterion.h>
#include <criterion/new/assert.h>
#include <string.h>

#include "mocks/malloc_mock.h"

#define OOPETRIS_REALLOC(p, s) mock_realloc(p, s)
#define OOPETRIS_FREE(p) mock_free(p)

#include "oopetris_wrapper.h"

// this tests likely fail, if we update the lib, but this failure on version bump serves as remainder,to check, if other things need changing too, since wrapper may become outdated otherwise

Test(MallocTests, LibVersionNoMallocIsUsed) {
MockMallocStats* stats = mock_malloc_create_stats();
const char* lib_version = oopetris_get_lib_version();
char* dynamic_lib_version = malloc(strlen(lib_version) + 1);

strcpy(dynamic_lib_version, lib_version);

cr_assert(eq(str, dynamic_lib_version, "0.5.6"));
free(dynamic_lib_version);

cr_assert(mock_malloc_count_realloc(stats) == 0);
cr_assert(mock_malloc_count_free(stats) == 0);

mock_malloc_free_stats(stats);
}

/*
Test(Information, GridProperties) {
OOPetrisGridProperties* properties = oopetris_get_grid_properties();
cr_assert_not_null(properties, "returned properties are non-NULL");
cr_assert(eq(u32, properties->height, 20));
cr_assert(eq(u32, properties->width, 10));
FREE_AND_SET_NULL(oopetris_free_grid_properties, properties);
cr_assert_null(properties, "properties are freed correctly");
} */
10 changes: 6 additions & 4 deletions tests/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ test_deps = [liboopetris_c_wrapper_dep]
test_deps += dependency('criterion')

tests_config = [
['get_recording_information.c', 'GetRecordingInformation'],
['information.c', 'Information'],
['is_recording_file.c', 'IsRecordingFile'],
['get_recording_information.c', 'GetRecordingInformation', []],
['information.c', 'Information', []],
['is_recording_file.c', 'IsRecordingFile', []],
['malloc_tests.c', 'MallocTests', ['mocks/malloc_mock.c']],
## 'stb_ds.c', this test don't work atm

]
Expand All @@ -16,10 +17,11 @@ foreach config : tests_config

file = config[0]
name = config[1]
additional_files = config[2]

test_exe = executable(
'test_' + name,
files(file),
files(file, additional_files),
dependencies: test_deps,
override_options: {
'warning_level': '3',
Expand Down
129 changes: 129 additions & 0 deletions tests/mocks/malloc_mock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@


#include "malloc_mock.h"


#include <assert.h>
#include <stdio.h>
#include <stdlib.h>


// a simple DynArray, to not use stb_ds.h

typedef struct {
void* ptr;
size_t new_size;
} DynArrayRNode;

typedef struct {
uint64_t size;
DynArrayRNode* nodes;
} DynArrayR;


typedef struct {
void* ptr;
} DynArrayFNode;

typedef struct {
uint64_t size;
DynArrayFNode* nodes;
} DynArrayF;


struct MockMallocStatsImpl {
DynArrayR* realloced_calls;
DynArrayF* free_calls;
};


static MockMallocStats* global_stats = NULL;


void mock_free(void* ptr) {
assert(global_stats);

size_t previous_size = global_stats->free_calls->size;

global_stats->free_calls->size++;

global_stats->free_calls->nodes =
realloc(global_stats->free_calls->nodes,
global_stats->free_calls->size * sizeof(*global_stats->free_calls->nodes));

global_stats->free_calls->nodes[previous_size].ptr = ptr;

free(ptr);
}

void* mock_realloc(void* ptr, size_t new_size) {
assert(global_stats);

size_t previous_size = global_stats->realloced_calls->size;

global_stats->realloced_calls->size++;

global_stats->realloced_calls->nodes =
realloc(global_stats->realloced_calls->nodes,
global_stats->realloced_calls->size * sizeof(*global_stats->realloced_calls->nodes));

global_stats->realloced_calls->nodes[previous_size].ptr = ptr;
global_stats->realloced_calls->nodes[previous_size].new_size = new_size;

return realloc(ptr, new_size);
}


MockMallocStats* mock_malloc_create_stats(void) {
if (global_stats != NULL) {
fprintf(stderr, "Error, stats already created\n");
exit(4);
}

global_stats = malloc(sizeof(MockMallocStats));

global_stats->realloced_calls = malloc(sizeof(DynArrayR));
global_stats->realloced_calls->size = 0;
global_stats->realloced_calls->nodes = NULL;

global_stats->free_calls = malloc(sizeof(DynArrayF));
global_stats->free_calls->size = 0;
global_stats->free_calls->nodes = NULL;

return global_stats;
}

void mock_malloc_free_stats(MockMallocStats* stats) {
if (global_stats == NULL) {
fprintf(stderr, "Error, stats already freed\n");
exit(4);
}

if (global_stats != stats) {
fprintf(stderr, "Error, stats niot the same as the global instance\n");
exit(4);
}


free(global_stats->free_calls->nodes);
free(global_stats->free_calls);

free(global_stats->realloced_calls->nodes);
free(global_stats->realloced_calls);

free(global_stats);

global_stats = NULL;
}


uint64_t mock_malloc_count_realloc(MockMallocStats* stats) {
assert(global_stats);
return stats->realloced_calls->size;
}


uint64_t mock_malloc_count_free(MockMallocStats* stats) {
assert(global_stats);
return stats->free_calls->size;
}
24 changes: 24 additions & 0 deletions tests/mocks/malloc_mock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@


#pragma once

#include <stddef.h>
#include <stdint.h>

// opaque type

void mock_free(void* ptr);

void* mock_realloc(void* ptr, size_t new_size);

struct MockMallocStatsImpl;

typedef struct MockMallocStatsImpl MockMallocStats;

MockMallocStats* mock_malloc_create_stats(void);

void mock_malloc_free_stats(MockMallocStats* stats);

uint64_t mock_malloc_count_realloc(MockMallocStats* stats);

uint64_t mock_malloc_count_free(MockMallocStats* stats);

0 comments on commit 30621ff

Please sign in to comment.