1 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
3 #ident "$Id$"
4 /*======
5 This file is part of PerconaFT.
6
7
8 Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
9
10 PerconaFT is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License, version 2,
12 as published by the Free Software Foundation.
13
14 PerconaFT is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
21
22 ----------------------------------------
23
24 PerconaFT is free software: you can redistribute it and/or modify
25 it under the terms of the GNU Affero General Public License, version 3,
26 as published by the Free Software Foundation.
27
28 PerconaFT is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU Affero General Public License for more details.
32
33 You should have received a copy of the GNU Affero General Public License
34 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
35 ======= */
36
37 #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
38
39 #include <string.h>
40
41 #include "portability/toku_assert.h"
42
43 #include "util/memarena.h"
44
45 class memarena_unit_test {
46 private:
47 static const int magic = 37;
48
49 template <typename F>
iterate_chunks(memarena * ma,F & fn)50 void iterate_chunks(memarena *ma, F &fn) {
51 for (memarena::chunk_iterator it(ma); it.more(); it.next()) {
52 size_t used = 0;
53 const void *buf = it.current(&used);
54 fn(buf, used);
55 }
56 }
57
test_create(size_t size)58 void test_create(size_t size) {
59 memarena ma;
60 ma.create(size);
61 invariant(ma._current_chunk.size == size);
62 invariant(ma._current_chunk.used == 0);
63 if (size == 0) {
64 invariant_null(ma._current_chunk.buf);
65 } else {
66 invariant_notnull(ma._current_chunk.buf);
67 }
68
69 // make sure memory was allocated ok by
70 // writing to buf and reading it back
71 if (size > 0) {
72 memset(ma._current_chunk.buf, magic, size);
73 }
74 for (size_t i = 0; i < size; i++) {
75 const char *buf = reinterpret_cast<char *>(ma._current_chunk.buf);
76 invariant(buf[i] == magic);
77 }
78 ma.destroy();
79 }
80
test_malloc(size_t size)81 void test_malloc(size_t size) {
82 memarena ma;
83 ma.create(14);
84 void *v = ma.malloc_from_arena(size);
85 invariant_notnull(v);
86
87 // make sure memory was allocated ok by
88 // writing to buf and reading it back
89 if (size > 0) {
90 memset(ma._current_chunk.buf, magic, size);
91 }
92 for (size_t i = 0; i < size; i++) {
93 const char *c = reinterpret_cast<char *>(ma._current_chunk.buf);
94 invariant(c[i] == magic);
95 }
96 ma.destroy();
97 }
98
test_iterate_fn(const void * buf,size_t used)99 static void test_iterate_fn(const void *buf, size_t used) {
100 for (size_t i = 0; i < used; i++) {
101 const char *c = reinterpret_cast<const char *>(buf);
102 invariant(c[i] == (char) ((intptr_t) &c[i]));
103 }
104 }
105
test_iterate(size_t size)106 void test_iterate(size_t size) {
107 memarena ma;
108 ma.create(14);
109 for (size_t k = 0; k < size / 64; k += 64) {
110 void *v = ma.malloc_from_arena(64);
111 for (size_t i = 0; i < 64; i++) {
112 char *c = reinterpret_cast<char *>(v);
113 c[i] = (char) ((intptr_t) &c[i]);
114 }
115 }
116 size_t rest = size % 64;
117 if (rest != 0) {
118 void *v = ma.malloc_from_arena(64);
119 for (size_t i = 0; i < 64; i++) {
120 char *c = reinterpret_cast<char *>(v);
121 c[i] = (char) ((intptr_t) &c[i]);
122 }
123 }
124
125 iterate_chunks(&ma, test_iterate_fn);
126 ma.destroy();
127 }
128
test_move_memory(size_t size)129 void test_move_memory(size_t size) {
130 memarena ma;
131 ma.create(14);
132 for (size_t k = 0; k < size / 64; k += 64) {
133 void *v = ma.malloc_from_arena(64);
134 for (size_t i = 0; i < 64; i++) {
135 char *c = reinterpret_cast<char *>(v);
136 c[i] = (char) ((intptr_t) &c[i]);
137 }
138 }
139 size_t rest = size % 64;
140 if (rest != 0) {
141 void *v = ma.malloc_from_arena(64);
142 for (size_t i = 0; i < 64; i++) {
143 char *c = reinterpret_cast<char *>(v);
144 c[i] = (char) ((intptr_t) &c[i]);
145 }
146 }
147
148 memarena ma2;
149 ma.move_memory(&ma2);
150 iterate_chunks(&ma2, test_iterate_fn);
151
152 ma.destroy();
153 ma2.destroy();
154 }
155
156 public:
test()157 void test() {
158 test_create(0);
159 test_create(64);
160 test_create(128 * 1024 * 1024);
161 test_malloc(0);
162 test_malloc(63);
163 test_malloc(64);
164 test_malloc(64 * 1024 * 1024);
165 test_malloc((64 * 1024 * 1024) + 1);
166 test_iterate(0);
167 test_iterate(63);
168 test_iterate(128 * 1024);
169 test_iterate(64 * 1024 * 1024);
170 test_iterate((64 * 1024 * 1024) + 1);
171 test_move_memory(0);
172 test_move_memory(1);
173 test_move_memory(63);
174 test_move_memory(65);
175 test_move_memory(65 * 1024 * 1024);
176 test_move_memory(101 * 1024 * 1024);
177 }
178 };
179
main(void)180 int main(void) {
181 memarena_unit_test test;
182 test.test();
183 return 0;
184 }
185