Skip to content

Commit e0ae0a1

Browse files
committed
refactor: [c] Separate tests.h from offsetof.c
1 parent 124f5c0 commit e0ae0a1

File tree

2 files changed

+99
-90
lines changed

2 files changed

+99
-90
lines changed

c/includes/tests.h

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
4+
/* ===========================================================================
5+
* Test helpers
6+
* ===========================================================================
7+
*/
8+
#define array_size(a) (sizeof(a) / sizeof(a[0]))
9+
10+
#define fii(n) for (int i = 0; i < (n); i++)
11+
12+
static int check_eq_n(int *l, int *r, int n)
13+
{
14+
fii (n) {
15+
if (l[i] != r[i]) return 0;
16+
}
17+
return 1;
18+
}
19+
20+
static void _a2s(int *a, int n, char *b)
21+
{
22+
int l = 0, f = 1;
23+
b[l++] = '{';
24+
fii (n) {
25+
l += sprintf(&b[l], "%s%d", (f ? "" : ", "), a[i]);
26+
f = 0;
27+
}
28+
b[l++] = '}';
29+
b[l] = '\0';
30+
}
31+
32+
#define CHECK_EQ_N(l, r, n) \
33+
{ \
34+
char ab[100], eb[100]; \
35+
_a2s(l, n, ab); \
36+
_a2s(r, n, eb); \
37+
if (!check_eq_n(l, r, n)) { \
38+
fprintf(stderr, \
39+
" test-%d failed! " \
40+
"expected %s, actual %s.\n", \
41+
tc, ab, eb); \
42+
exit(1); \
43+
} else { \
44+
if (getenv("SHOW_TEST_OUTPUT")) \
45+
fprintf( \
46+
stdout, \
47+
" test-%d: input: %s, output: %s.\n", \
48+
tc, ab, eb); \
49+
} \
50+
}
51+
52+
#define RUN_ALL_TESTS() \
53+
size_t tc = 0, ts = 0; \
54+
for (; ts < array_size(_tests); ts++) { \
55+
if (getenv("SHOW_TEST_OUTPUT")) \
56+
fprintf(stdout, "Testing implementation %d %s\n", \
57+
ts + 1, _tests[ts].desc); \
58+
tc += _tests[ts].func(); \
59+
} \
60+
fprintf(stdout, "Executed %d implementations with %d tests.", ts, tc);
61+
62+
typedef int (*TestFuncPtr)();
63+
64+
struct TestsStruct {
65+
const char *desc;
66+
TestFuncPtr func;
67+
};
68+
69+
#define TEST_LIST static struct TestsStruct _tests[]
70+
71+
#define INIT_TEST_MAIN() \
72+
int main(int, char **) \
73+
{ \
74+
RUN_ALL_TESTS(); \
75+
return 0; \
76+
}

c/structs/offsetof.c

Lines changed: 23 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,31 @@
11
/*
2-
* struct - Offset of & Container of macros
2+
* _offset_of & _container_of macros
3+
* =================================
34
*
4-
* Refer
5+
* Access a container using its member.
6+
*
7+
* Refer:
58
*
69
* https://stackoverflow.com/a/39805594
710
* https://radek.io/posts/magical-container_of-macro/
811
* https://www.kernel.org/doc/Documentation/driver-model/design-patterns.txt
912
*/
1013

11-
#include <stdio.h>
12-
#include <stdlib.h>
14+
#include "tests.h"
1315

1416
/* ===========================================================================
1517
* Macro implementations
1618
* ===========================================================================
1719
*/
1820
// also defined in stddef.h
1921
// clang-format off
20-
#define offsetof(st, m) ((size_t) &((st *)0)->m)
22+
#define _offset_of(st, m) ((size_t) &((st *)0)->m)
2123
// clang-format on
2224

23-
#define container_of(ptr, type, member) \
25+
#define _container_of(ptr, type, member) \
2426
({ \
2527
const typeof(((type *)0)->member) *__mptr = (ptr); \
26-
(type *)((char *)__mptr - offsetof(type, member)); \
28+
(type *)((char *)__mptr - _offset_of(type, member)); \
2729
})
2830

2931
/* ===========================================================================
@@ -41,14 +43,13 @@ struct task_struct {
4143
int flags;
4244
};
4345

44-
static inline void list_add_tail(struct list_head *new,
45-
struct list_head *head)
46+
void _list_append(struct list_head *head, struct list_head *node)
4647
{
4748
struct list_head *last = head->prev;
48-
new->next = head;
49-
new->prev = last;
50-
last->next = new;
51-
head->prev = new;
49+
node->next = head;
50+
node->prev = last;
51+
last->next = node;
52+
head->prev = node;
5253
}
5354

5455
#define list_for_each(pos, head) \
@@ -69,92 +70,28 @@ void get_task_states(int *a)
6970
task3.state = 3;
7071

7172
// Add tasks to list
72-
list_add_tail(&task1.tasks, &task_list);
73-
list_add_tail(&task2.tasks, &task_list);
74-
list_add_tail(&task3.tasks, &task_list);
73+
_list_append(&task_list, &task1.tasks);
74+
_list_append(&task_list, &task2.tasks);
75+
_list_append(&task_list, &task3.tasks);
7576

7677
// Iterate over tasks
7778
int i = 0;
7879
struct list_head *curr = NULL;
7980
list_for_each(curr, &task_list)
8081
{
8182
struct task_struct *task =
82-
container_of(curr, struct task_struct, tasks);
83+
_container_of(curr, struct task_struct, tasks);
8384
a[i++] = task->state;
8485
}
8586
}
8687

87-
/* ===========================================================================
88-
* Test helpers
89-
* ===========================================================================
90-
*/
91-
#define array_size(a) (sizeof(a) / sizeof(a[0]))
92-
93-
#define fii(n) for (int i = 0; i < (n); i++)
94-
95-
static int check_eq_n(int *l, int *r, int n)
96-
{
97-
fii (n) {
98-
if (l[i] != r[i]) return 0;
99-
}
100-
return 1;
101-
}
102-
103-
static void _a2s(int *a, int n, char *b)
104-
{
105-
int l = 0, f = 1;
106-
b[l++] = '{';
107-
fii (n) {
108-
l += sprintf(&b[l], "%s%d", (f ? "" : ", "), a[i]);
109-
f = 0;
110-
}
111-
b[l++] = '}';
112-
b[l] = '\0';
113-
}
114-
115-
#define CHECK_EQ_N(l, r, n) \
116-
{ \
117-
char ab[100], eb[100]; \
118-
_a2s(l, n, ab); \
119-
_a2s(r, n, eb); \
120-
if (!check_eq_n(l, r, n)) { \
121-
fprintf(stderr, \
122-
" test-%d failed! " \
123-
"expected %s, actual %s.\n", \
124-
tc, ab, eb); \
125-
exit(1); \
126-
} else { \
127-
if (getenv("SHOW_TEST_OUTPUT")) \
128-
fprintf( \
129-
stdout, \
130-
" test-%d: input: %s, output: %s.\n", \
131-
tc, ab, eb); \
132-
} \
133-
}
134-
135-
#define RUN_ALL_TESTS() \
136-
size_t tc = 0, ts = 0; \
137-
for (; ts < array_size(_tests); ts++) { \
138-
if (getenv("SHOW_TEST_OUTPUT")) \
139-
fprintf(stdout, "Testing implementation %d %s\n", \
140-
ts + 1, _tests[ts].desc); \
141-
tc += _tests[ts].func(); \
142-
} \
143-
fprintf(stdout, "Executed %d implementations with %d tests.", ts, tc);
144-
145-
typedef int (*TestFuncPtr)();
146-
147-
struct TestsStruct {
148-
const char *desc;
149-
TestFuncPtr func;
150-
};
151-
152-
#define TEST_LIST static struct TestsStruct _tests[]
153-
15488
/* ===========================================================================
15589
* Test code
15690
* ===========================================================================
15791
*/
92+
#define _of_desc_prefix "_offset_of & _container_of macros"
93+
#define _of_desc_suffix "Access a container using its member"
94+
#define _of_desc _of_desc_prefix " - " _of_desc_suffix
15895

15996
int test_iterate_list()
16097
{
@@ -168,11 +105,7 @@ int test_iterate_list()
168105
}
169106

170107
TEST_LIST = {
171-
{"container_of: Access a container using its member", test_iterate_list},
108+
{_of_desc, test_iterate_list},
172109
};
173110

174-
int main(int, char **)
175-
{
176-
RUN_ALL_TESTS();
177-
return 0;
178-
}
111+
INIT_TEST_MAIN();

0 commit comments

Comments
 (0)