Skip to content

Commit 30621ff

Browse files
committed
add experimental malloc mocks
1 parent 86b2118 commit 30621ff

File tree

4 files changed

+198
-4
lines changed

4 files changed

+198
-4
lines changed

tests/malloc_tests.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#include <criterion/criterion.h>
2+
#include <criterion/new/assert.h>
3+
#include <string.h>
4+
5+
#include "mocks/malloc_mock.h"
6+
7+
#define OOPETRIS_REALLOC(p, s) mock_realloc(p, s)
8+
#define OOPETRIS_FREE(p) mock_free(p)
9+
10+
#include "oopetris_wrapper.h"
11+
12+
// 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
13+
14+
Test(MallocTests, LibVersionNoMallocIsUsed) {
15+
MockMallocStats* stats = mock_malloc_create_stats();
16+
const char* lib_version = oopetris_get_lib_version();
17+
char* dynamic_lib_version = malloc(strlen(lib_version) + 1);
18+
19+
strcpy(dynamic_lib_version, lib_version);
20+
21+
cr_assert(eq(str, dynamic_lib_version, "0.5.6"));
22+
free(dynamic_lib_version);
23+
24+
cr_assert(mock_malloc_count_realloc(stats) == 0);
25+
cr_assert(mock_malloc_count_free(stats) == 0);
26+
27+
mock_malloc_free_stats(stats);
28+
}
29+
30+
/*
31+
Test(Information, GridProperties) {
32+
OOPetrisGridProperties* properties = oopetris_get_grid_properties();
33+
cr_assert_not_null(properties, "returned properties are non-NULL");
34+
cr_assert(eq(u32, properties->height, 20));
35+
cr_assert(eq(u32, properties->width, 10));
36+
37+
FREE_AND_SET_NULL(oopetris_free_grid_properties, properties);
38+
cr_assert_null(properties, "properties are freed correctly");
39+
} */

tests/meson.build

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ test_deps = [liboopetris_c_wrapper_dep]
33
test_deps += dependency('criterion')
44

55
tests_config = [
6-
['get_recording_information.c', 'GetRecordingInformation'],
7-
['information.c', 'Information'],
8-
['is_recording_file.c', 'IsRecordingFile'],
6+
['get_recording_information.c', 'GetRecordingInformation', []],
7+
['information.c', 'Information', []],
8+
['is_recording_file.c', 'IsRecordingFile', []],
9+
['malloc_tests.c', 'MallocTests', ['mocks/malloc_mock.c']],
910
## 'stb_ds.c', this test don't work atm
1011

1112
]
@@ -16,10 +17,11 @@ foreach config : tests_config
1617

1718
file = config[0]
1819
name = config[1]
20+
additional_files = config[2]
1921

2022
test_exe = executable(
2123
'test_' + name,
22-
files(file),
24+
files(file, additional_files),
2325
dependencies: test_deps,
2426
override_options: {
2527
'warning_level': '3',

tests/mocks/malloc_mock.c

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
2+
3+
#include "malloc_mock.h"
4+
5+
6+
#include <assert.h>
7+
#include <stdio.h>
8+
#include <stdlib.h>
9+
10+
11+
// a simple DynArray, to not use stb_ds.h
12+
13+
typedef struct {
14+
void* ptr;
15+
size_t new_size;
16+
} DynArrayRNode;
17+
18+
typedef struct {
19+
uint64_t size;
20+
DynArrayRNode* nodes;
21+
} DynArrayR;
22+
23+
24+
typedef struct {
25+
void* ptr;
26+
} DynArrayFNode;
27+
28+
typedef struct {
29+
uint64_t size;
30+
DynArrayFNode* nodes;
31+
} DynArrayF;
32+
33+
34+
struct MockMallocStatsImpl {
35+
DynArrayR* realloced_calls;
36+
DynArrayF* free_calls;
37+
};
38+
39+
40+
static MockMallocStats* global_stats = NULL;
41+
42+
43+
void mock_free(void* ptr) {
44+
assert(global_stats);
45+
46+
size_t previous_size = global_stats->free_calls->size;
47+
48+
global_stats->free_calls->size++;
49+
50+
global_stats->free_calls->nodes =
51+
realloc(global_stats->free_calls->nodes,
52+
global_stats->free_calls->size * sizeof(*global_stats->free_calls->nodes));
53+
54+
global_stats->free_calls->nodes[previous_size].ptr = ptr;
55+
56+
free(ptr);
57+
}
58+
59+
void* mock_realloc(void* ptr, size_t new_size) {
60+
assert(global_stats);
61+
62+
size_t previous_size = global_stats->realloced_calls->size;
63+
64+
global_stats->realloced_calls->size++;
65+
66+
global_stats->realloced_calls->nodes =
67+
realloc(global_stats->realloced_calls->nodes,
68+
global_stats->realloced_calls->size * sizeof(*global_stats->realloced_calls->nodes));
69+
70+
global_stats->realloced_calls->nodes[previous_size].ptr = ptr;
71+
global_stats->realloced_calls->nodes[previous_size].new_size = new_size;
72+
73+
return realloc(ptr, new_size);
74+
}
75+
76+
77+
MockMallocStats* mock_malloc_create_stats(void) {
78+
if (global_stats != NULL) {
79+
fprintf(stderr, "Error, stats already created\n");
80+
exit(4);
81+
}
82+
83+
global_stats = malloc(sizeof(MockMallocStats));
84+
85+
global_stats->realloced_calls = malloc(sizeof(DynArrayR));
86+
global_stats->realloced_calls->size = 0;
87+
global_stats->realloced_calls->nodes = NULL;
88+
89+
global_stats->free_calls = malloc(sizeof(DynArrayF));
90+
global_stats->free_calls->size = 0;
91+
global_stats->free_calls->nodes = NULL;
92+
93+
return global_stats;
94+
}
95+
96+
void mock_malloc_free_stats(MockMallocStats* stats) {
97+
if (global_stats == NULL) {
98+
fprintf(stderr, "Error, stats already freed\n");
99+
exit(4);
100+
}
101+
102+
if (global_stats != stats) {
103+
fprintf(stderr, "Error, stats niot the same as the global instance\n");
104+
exit(4);
105+
}
106+
107+
108+
free(global_stats->free_calls->nodes);
109+
free(global_stats->free_calls);
110+
111+
free(global_stats->realloced_calls->nodes);
112+
free(global_stats->realloced_calls);
113+
114+
free(global_stats);
115+
116+
global_stats = NULL;
117+
}
118+
119+
120+
uint64_t mock_malloc_count_realloc(MockMallocStats* stats) {
121+
assert(global_stats);
122+
return stats->realloced_calls->size;
123+
}
124+
125+
126+
uint64_t mock_malloc_count_free(MockMallocStats* stats) {
127+
assert(global_stats);
128+
return stats->free_calls->size;
129+
}

tests/mocks/malloc_mock.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
2+
3+
#pragma once
4+
5+
#include <stddef.h>
6+
#include <stdint.h>
7+
8+
// opaque type
9+
10+
void mock_free(void* ptr);
11+
12+
void* mock_realloc(void* ptr, size_t new_size);
13+
14+
struct MockMallocStatsImpl;
15+
16+
typedef struct MockMallocStatsImpl MockMallocStats;
17+
18+
MockMallocStats* mock_malloc_create_stats(void);
19+
20+
void mock_malloc_free_stats(MockMallocStats* stats);
21+
22+
uint64_t mock_malloc_count_realloc(MockMallocStats* stats);
23+
24+
uint64_t mock_malloc_count_free(MockMallocStats* stats);

0 commit comments

Comments
 (0)