1 | // gc_stress_test.cc: Do many allocations and collections under ASAN
|
2 |
|
3 | #include <unistd.h> // STDERR_FILENO
|
4 |
|
5 | #include "mycpp/runtime.h"
|
6 | #include "vendor/greatest.h"
|
7 |
|
8 | // TODO:
|
9 | // - Assert the number of collections
|
10 | // - Assert the number of heap growths
|
11 | // - maybe number of allocations?
|
12 |
|
13 | int count(int n) {
|
14 | int dummy = 42;
|
15 | StackRoots _roots({&dummy});
|
16 | // log("d %p", &dummy);
|
17 |
|
18 | if (n == 0) {
|
19 | return 0;
|
20 | } else {
|
21 | return 1 + count(n - 1);
|
22 | }
|
23 | }
|
24 |
|
25 | TEST overflowing_roots_test() {
|
26 | gHeap.Init();
|
27 |
|
28 | log("count 4000 = %d", count(4000));
|
29 |
|
30 | // When our stack roots were limited, this would crash
|
31 | log("count 5000 = %d", count(5000));
|
32 | log("count 20000 = %d", count(20000));
|
33 | log("count 25000 = %d", count(25000));
|
34 | // Stack overflow in ASAN
|
35 | // log("count 29000 = %d", count(29000));
|
36 | // Stack overflow in dbg
|
37 | // log("count 200000 = %d", count(200000));
|
38 |
|
39 | PASS();
|
40 | }
|
41 |
|
42 | TEST str_simple_test() {
|
43 | gHeap.Init();
|
44 |
|
45 | BigStr* s = nullptr;
|
46 | StackRoots _roots({&s});
|
47 |
|
48 | int total = 0;
|
49 | for (int i = 0; i < 400; ++i) {
|
50 | unsigned char c = i % 256;
|
51 | s = chr(c);
|
52 | /* log("i = %d", i); */
|
53 | ASSERT_EQ_FMT(c, ord(s), "%d"); // Check for memory corruption
|
54 | total += len(s);
|
55 | }
|
56 |
|
57 | log("total = %d", total);
|
58 | gHeap.PrintStats(STDERR_FILENO);
|
59 |
|
60 | PASS();
|
61 | }
|
62 |
|
63 | GLOBAL_STR(b, "b");
|
64 | GLOBAL_STR(bx, "bx");
|
65 |
|
66 | TEST str_growth_test() {
|
67 | gHeap.Init();
|
68 |
|
69 | BigStr* s = nullptr;
|
70 | StackRoots _roots({&s});
|
71 |
|
72 | gHeap.PrintStats(STDERR_FILENO);
|
73 |
|
74 | s = StrFromC("b");
|
75 | int n = 300;
|
76 | int total = 0;
|
77 | for (int i = 0; i < n; ++i) {
|
78 | total += len(s); // count it first
|
79 |
|
80 | // log("--- %p %d", s, len(s));
|
81 | // print(s);
|
82 | s = s->replace(b, bx);
|
83 | // print(s);
|
84 | }
|
85 | log("total = %d", total);
|
86 |
|
87 | int expected = (n * (n + 1)) / 2;
|
88 | ASSERT_EQ_FMT(expected, total, "%d");
|
89 |
|
90 | gHeap.PrintStats(STDERR_FILENO);
|
91 |
|
92 | PASS();
|
93 | }
|
94 |
|
95 | // Simple test with just List on the heap.
|
96 | TEST list_append_test() {
|
97 | gHeap.Init();
|
98 |
|
99 | List<int>* L = nullptr;
|
100 | StackRoots _roots({&L});
|
101 |
|
102 | int length = 1;
|
103 | L = NewList<int>(42, length);
|
104 |
|
105 | int n = 1000;
|
106 | int total = 0;
|
107 | for (int i = 0; i < n; ++i) {
|
108 | total += len(L); // count it first
|
109 |
|
110 | // log("sliced L = %p", L);
|
111 | L->append(43); // append to end
|
112 | }
|
113 | log("total = %d", total);
|
114 | ASSERT_EQ_FMT(500500, total, "%d");
|
115 |
|
116 | PASS();
|
117 | }
|
118 |
|
119 | TEST list_slice_append_test() {
|
120 | gHeap.Init();
|
121 |
|
122 | List<int>* L = nullptr;
|
123 | StackRoots _roots({&L});
|
124 |
|
125 | int length = 5;
|
126 | L = NewList<int>(42, length);
|
127 |
|
128 | int n = 300;
|
129 | int total = 0;
|
130 | for (int i = 0; i < n; ++i) {
|
131 | /* log("i = %d", i); */
|
132 | total += len(L); // count it first
|
133 |
|
134 | L = L->slice(1);
|
135 | assert(len(L) == 4);
|
136 |
|
137 | L->append(43); // append to end
|
138 | assert(len(L) == 5);
|
139 | }
|
140 | log("total = %d", total);
|
141 |
|
142 | int expected = n * length;
|
143 | ASSERT_EQ_FMT(expected, total, "%d");
|
144 |
|
145 | PASS();
|
146 | }
|
147 |
|
148 | TEST list_str_growth_test() {
|
149 | gHeap.Init();
|
150 |
|
151 | BigStr* s = nullptr;
|
152 | List<BigStr*>* L = nullptr;
|
153 | StackRoots _roots({&s, &L});
|
154 | // StackRoots _roots({&L});
|
155 |
|
156 | s = StrFromC("b");
|
157 | L = Alloc<List<BigStr*>>();
|
158 |
|
159 | #if 0
|
160 | int total = 0;
|
161 | int n = 40;
|
162 | for (int i = 0; i < n; ++i) {
|
163 | log("i = %d", i);
|
164 | //total += len(s);
|
165 |
|
166 | L->append(s);
|
167 |
|
168 | // This works if we don't have 's'. Because it's global?
|
169 | //L->append(bx);
|
170 | }
|
171 | log("total = %d", total);
|
172 |
|
173 | int expected = (n * (n + 1)) / 2;
|
174 | ASSERT_EQ_FMT(expected, total, "%d");
|
175 | #endif
|
176 |
|
177 | PASS();
|
178 | }
|
179 |
|
180 | TEST dict_growth_test() {
|
181 | gHeap.Init();
|
182 |
|
183 | BigStr* s = nullptr;
|
184 | Dict<BigStr*, int>* D = nullptr;
|
185 | StackRoots _roots({&s, &D});
|
186 |
|
187 | s = StrFromC("abcdefg");
|
188 | D = Alloc<Dict<BigStr*, int>>();
|
189 |
|
190 | int total = 0;
|
191 | for (int i = 0; i < 40; ++i) {
|
192 | total += len(s);
|
193 | s = s->replace(b, bx);
|
194 | D->set(s, 42);
|
195 | }
|
196 | log("total = %d", total);
|
197 |
|
198 | // TODO: Test NewDict(), etc.
|
199 |
|
200 | PASS();
|
201 | }
|
202 |
|
203 | GREATEST_MAIN_DEFS();
|
204 |
|
205 | int main(int argc, char** argv) {
|
206 | gHeap.Init();
|
207 |
|
208 | GREATEST_MAIN_BEGIN();
|
209 |
|
210 | RUN_TEST(overflowing_roots_test);
|
211 | RUN_TEST(str_simple_test);
|
212 | RUN_TEST(str_growth_test);
|
213 | RUN_TEST(list_append_test);
|
214 | RUN_TEST(list_slice_append_test);
|
215 | RUN_TEST(list_str_growth_test);
|
216 | RUN_TEST(dict_growth_test);
|
217 |
|
218 | gHeap.CleanProcessExit();
|
219 |
|
220 | GREATEST_MAIN_END();
|
221 | return 0;
|
222 | }
|