|
1 /* |
|
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
|
3 * |
|
4 * Copyright 2014 Olaf Wintermann. All rights reserved. |
|
5 * |
|
6 * Redistribution and use in source and binary forms, with or without |
|
7 * modification, are permitted provided that the following conditions are met: |
|
8 * |
|
9 * 1. Redistributions of source code must retain the above copyright |
|
10 * notice, this list of conditions and the following disclaimer. |
|
11 * |
|
12 * 2. Redistributions in binary form must reproduce the above copyright |
|
13 * notice, this list of conditions and the following disclaimer in the |
|
14 * documentation and/or other materials provided with the distribution. |
|
15 * |
|
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
26 * POSSIBILITY OF SUCH DAMAGE. |
|
27 */ |
|
28 |
|
29 #include "stack_tests.h" |
|
30 |
|
31 #define test_ucx_stack_before \ |
|
32 char space[100]; \ |
|
33 UcxStack stack; \ |
|
34 ucx_stack_init(&stack, space, 100) \ |
|
35 |
|
36 UCX_TEST(test_ucx_stack_init) { |
|
37 |
|
38 test_ucx_stack_before; |
|
39 |
|
40 UCX_TEST_BEGIN |
|
41 |
|
42 UCX_TEST_ASSERT( |
|
43 stack.allocator.malloc == (ucx_allocator_malloc) ucx_stack_malloc && |
|
44 stack.allocator.calloc == (ucx_allocator_calloc) ucx_stack_calloc && |
|
45 stack.allocator.realloc == (ucx_allocator_realloc) ucx_stack_realloc && |
|
46 stack.allocator.free == (ucx_allocator_free) ucx_stack_free && |
|
47 stack.allocator.pool == &stack, |
|
48 "allocator not properly set"); |
|
49 |
|
50 UCX_TEST_ASSERT(!stack.top && stack.space == space |
|
51 && stack.size == 100 - 100 % sizeof(void*), |
|
52 "struct fields not properly set"); |
|
53 |
|
54 UCX_TEST_END |
|
55 } |
|
56 |
|
57 UCX_TEST(test_ucx_stack_malloc) { |
|
58 |
|
59 test_ucx_stack_before; |
|
60 |
|
61 const size_t metasize = sizeof(struct ucx_stack_metadata); |
|
62 |
|
63 |
|
64 char* first = (char*) ucx_stack_malloc(&stack, 30); |
|
65 char* second = (char*) ucx_stack_malloc(&stack, 30); |
|
66 char* full = (char*) ucx_stack_malloc(&stack, 30); |
|
67 |
|
68 memcpy(first, "012345678901234567890123456789", 30); |
|
69 memcpy(second, "abcdefghijklmnopqrstuvwxyzABCD", 30); |
|
70 |
|
71 UCX_TEST_BEGIN |
|
72 |
|
73 UCX_TEST_ASSERT(!memcmp(space + metasize, |
|
74 "012345678901234567890123456789", 30), "first element corrupted"); |
|
75 UCX_TEST_ASSERT(!memcmp(space + 32+2*metasize, |
|
76 "abcdefghijklmnopqrstuvwxyzABCD", 30), "first element corrupted"); |
|
77 |
|
78 UCX_TEST_ASSERT(!full, "stack can be overflowed"); |
|
79 UCX_TEST_ASSERT(stack.top == space + 32 + 2*metasize, "wrong top pointer"); |
|
80 |
|
81 if (3*metasize < 32) { |
|
82 UCX_TEST_ASSERT(ucx_stack_avail(&stack) == 32-3*metasize, |
|
83 "wrong remaining available memory"); |
|
84 } else { |
|
85 UCX_TEST_ASSERT(ucx_stack_avail(&stack) == 0, |
|
86 "wrong remaining available memory"); |
|
87 } |
|
88 |
|
89 UCX_TEST_END |
|
90 } |
|
91 |
|
92 UCX_TEST(test_ucx_stack_calloc) { |
|
93 |
|
94 test_ucx_stack_before; |
|
95 |
|
96 char zeros[100]; |
|
97 memset(zeros, 0, 100); |
|
98 memset(space, 32, 100); |
|
99 ucx_stack_calloc(&stack, 4, sizeof(int)); |
|
100 |
|
101 UCX_TEST_BEGIN |
|
102 |
|
103 UCX_TEST_ASSERT(!memcmp(space+sizeof(struct ucx_stack_metadata), |
|
104 zeros, 4*sizeof(int)), "memory not nulled"); |
|
105 UCX_TEST_ASSERT(!memcmp(space+sizeof(struct ucx_stack_metadata) |
|
106 +4*sizeof(int), " ", 10), "too much memory nulled"); |
|
107 |
|
108 UCX_TEST_END |
|
109 } |
|
110 |
|
111 UCX_TEST(test_ucx_stack_free) { |
|
112 |
|
113 test_ucx_stack_before; |
|
114 |
|
115 void *fst = ucx_stack_malloc(&stack, 10); |
|
116 void *snd = ucx_stack_malloc(&stack, 10); |
|
117 void *thrd = ucx_stack_malloc(&stack, 10); |
|
118 |
|
119 UCX_TEST_BEGIN |
|
120 |
|
121 UCX_TEST_ASSERT(stack.top == thrd, "wrong stack"); |
|
122 UCX_TEST_ASSERT(((struct ucx_stack_metadata*) thrd - 1)->prev == snd, |
|
123 "wrong thrd prev pointer before free"); |
|
124 |
|
125 ucx_stack_free(&stack, snd); |
|
126 |
|
127 UCX_TEST_ASSERT(((struct ucx_stack_metadata*) thrd - 1)->prev == fst, |
|
128 "wrong thrd prev pointer after freeing snd"); |
|
129 UCX_TEST_ASSERT(stack.top == thrd, "wrong top after freeing snd"); |
|
130 |
|
131 ucx_stack_free(&stack, thrd); |
|
132 |
|
133 UCX_TEST_ASSERT(stack.top == fst, "wrong top after freeing thrd"); |
|
134 |
|
135 UCX_TEST_END |
|
136 } |
|
137 |
|
138 UCX_TEST(test_ucx_stack_realloc) { |
|
139 |
|
140 test_ucx_stack_before; |
|
141 |
|
142 void *fst = ucx_stack_malloc(&stack, 10); |
|
143 void *snd = ucx_stack_malloc(&stack, 10); |
|
144 |
|
145 UCX_TEST_BEGIN |
|
146 |
|
147 void *nfst = ucx_stack_realloc(&stack, fst, 16); |
|
148 UCX_TEST_ASSERT(nfst == fst, "unnecessary move on reallocation"); |
|
149 UCX_TEST_ASSERT(((struct ucx_stack_metadata*)fst - 1)->size == 16, |
|
150 "wrong size after reallocation"); |
|
151 |
|
152 void *nsnd = ucx_stack_realloc(&stack, snd, 30); |
|
153 UCX_TEST_ASSERT(nsnd == snd, "unnecessary move on top reallocation"); |
|
154 UCX_TEST_ASSERT(ucx_stack_topsize(&stack) == 30, |
|
155 "wrong size after top reallocation"); |
|
156 |
|
157 nsnd = ucx_stack_realloc(&stack, snd, 5); |
|
158 UCX_TEST_ASSERT(nsnd == snd, "unnecessary move on top shrink"); |
|
159 UCX_TEST_ASSERT(ucx_stack_topsize(&stack) == 5, |
|
160 "wrong size after top shrink"); |
|
161 UCX_TEST_ASSERT(ucx_stack_avail(&stack) == |
|
162 72-3*sizeof(struct ucx_stack_metadata), "wrong size after top shrink"); |
|
163 |
|
164 nfst = ucx_stack_realloc(&stack, fst, 24); |
|
165 UCX_TEST_ASSERT(nfst != fst, "missing move on huge reallocation"); |
|
166 UCX_TEST_ASSERT(stack.top == nfst, "wrong top after huge reallocation"); |
|
167 UCX_TEST_ASSERT(ucx_stack_topsize(&stack) == 24, |
|
168 "wrong size after huge reallocation"); |
|
169 UCX_TEST_ASSERT(!((struct ucx_stack_metadata*)snd - 1)->prev, |
|
170 "element not freed after huge reallocation"); |
|
171 |
|
172 UCX_TEST_END |
|
173 } |
|
174 |
|
175 UCX_TEST(test_ucx_stack_pop) { |
|
176 |
|
177 test_ucx_stack_before; |
|
178 memset(space, 32, 100); |
|
179 |
|
180 void *fst = ucx_stack_malloc(&stack, 10); |
|
181 void *snd = ucx_stack_malloc(&stack, 10); |
|
182 ucx_stack_malloc(&stack, 10); |
|
183 |
|
184 char buf[16]; |
|
185 |
|
186 UCX_TEST_BEGIN |
|
187 |
|
188 memset(buf, '0', 16); |
|
189 ucx_stack_pop(&stack, buf); |
|
190 UCX_TEST_ASSERT(memcmp(buf, " 000000", 16) == 0, |
|
191 "popped wrong content"); |
|
192 UCX_TEST_ASSERT(stack.top == snd, "wrong top after pop"); |
|
193 |
|
194 memset(buf, '0', 16); |
|
195 ucx_stack_popn(&stack, buf, 5); |
|
196 UCX_TEST_ASSERT(memcmp(buf, " 00000000000", 16) == 0, |
|
197 "n-popped wrong content"); |
|
198 UCX_TEST_ASSERT(stack.top == fst, "wrong top after pop"); |
|
199 |
|
200 ucx_stack_pop(&stack, buf); |
|
201 UCX_TEST_ASSERT(!stack.top, "top not NULL after last pop"); |
|
202 |
|
203 memset(buf, '0', 16); |
|
204 ucx_stack_pop(&stack, buf); |
|
205 UCX_TEST_ASSERT(memcmp(buf, "0000000000000000", 16) == 0, |
|
206 "content not unchanged after empty pop"); |
|
207 |
|
208 UCX_TEST_END |
|
209 } |