1 /*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "include/core/SkTypes.h"
9 #include "src/base/SkArenaAlloc.h"
10 #include "tests/Test.h"
11
12 #include <cstddef>
13 #include <cstdint>
14 #include <limits>
15 #include <memory>
16 #include <new>
17
DEF_TEST(ArenaAlloc,r)18 DEF_TEST(ArenaAlloc, r) {
19 static int created = 0,
20 destroyed = 0;
21
22 struct Foo {
23 Foo() : x(-2), y(-3.0f) { created++; }
24 Foo(int X, float Y) : x(X), y(Y) { created++; }
25 ~Foo() { destroyed++; }
26 int x;
27 float y;
28 };
29
30 struct alignas(8) OddAlignment {
31 char buf[10];
32 };
33
34 // Check construction/destruction counts from SkArenaAlloc.
35 created = 0;
36 destroyed = 0;
37 {
38 SkArenaAlloc arena{0};
39 REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
40 Foo* foo = arena.make<Foo>(3, 4.0f);
41 REPORTER_ASSERT(r, foo->x == 3);
42 REPORTER_ASSERT(r, foo->y == 4.0f);
43 REPORTER_ASSERT(r, created == 1);
44 REPORTER_ASSERT(r, destroyed == 0);
45 arena.makeArrayDefault<int>(10);
46 int* zeroed = arena.makeArray<int>(10);
47 for (int i = 0; i < 10; i++) {
48 REPORTER_ASSERT(r, zeroed[i] == 0);
49 }
50 Foo* fooArray = arena.makeArrayDefault<Foo>(10);
51 REPORTER_ASSERT(r, fooArray[3].x == -2);
52 REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
53 REPORTER_ASSERT(r, created == 11);
54 REPORTER_ASSERT(r, destroyed == 0);
55 arena.make<OddAlignment>();
56 }
57 REPORTER_ASSERT(r, created == 11);
58 REPORTER_ASSERT(r, destroyed == 11);
59
60 // Check construction/destruction counts from SkSTArenaAlloc.
61 created = 0;
62 destroyed = 0;
63 {
64 SkSTArenaAlloc<64> arena;
65 REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
66 Foo* foo = arena.make<Foo>(3, 4.0f);
67 REPORTER_ASSERT(r, foo->x == 3);
68 REPORTER_ASSERT(r, foo->y == 4.0f);
69 REPORTER_ASSERT(r, created == 1);
70 REPORTER_ASSERT(r, destroyed == 0);
71 arena.makeArrayDefault<int>(10);
72 int* zeroed = arena.makeArray<int>(10);
73 for (int i = 0; i < 10; i++) {
74 REPORTER_ASSERT(r, zeroed[i] == 0);
75 }
76 Foo* fooArray = arena.makeArrayDefault<Foo>(10);
77 REPORTER_ASSERT(r, fooArray[3].x == -2);
78 REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
79 REPORTER_ASSERT(r, created == 11);
80 REPORTER_ASSERT(r, destroyed == 0);
81 arena.make<OddAlignment>();
82 }
83 REPORTER_ASSERT(r, created == 11);
84 REPORTER_ASSERT(r, destroyed == 11);
85
86 // Check construction/destruction counts from SkArenaAlloc when passed an initial block.
87 created = 0;
88 destroyed = 0;
89 {
90 std::unique_ptr<char[]> block{new char[1024]};
91 SkArenaAlloc arena{block.get(), 1024, 0};
92 REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
93 Foo* foo = arena.make<Foo>(3, 4.0f);
94 REPORTER_ASSERT(r, foo->x == 3);
95 REPORTER_ASSERT(r, foo->y == 4.0f);
96 REPORTER_ASSERT(r, created == 1);
97 REPORTER_ASSERT(r, destroyed == 0);
98 arena.makeArrayDefault<int>(10);
99 int* zeroed = arena.makeArray<int>(10);
100 for (int i = 0; i < 10; i++) {
101 REPORTER_ASSERT(r, zeroed[i] == 0);
102 }
103 Foo* fooArray = arena.makeArrayDefault<Foo>(10);
104 REPORTER_ASSERT(r, fooArray[3].x == -2);
105 REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
106 REPORTER_ASSERT(r, created == 11);
107 REPORTER_ASSERT(r, destroyed == 0);
108 arena.make<OddAlignment>();
109 }
110 REPORTER_ASSERT(r, created == 11);
111 REPORTER_ASSERT(r, destroyed == 11);
112 }
113
DEF_TEST(ArenaAllocReset,r)114 DEF_TEST(ArenaAllocReset, r) {
115 SkSTArenaAllocWithReset<64> arena;
116 arena.makeArrayDefault<char>(256);
117 arena.reset();
118 arena.reset();
119 }
120
DEF_TEST(ArenaAllocWithMultipleBlocks,r)121 DEF_TEST(ArenaAllocWithMultipleBlocks, r) {
122 // Make sure that multiple blocks are handled correctly.
123 static int created = 0,
124 destroyed = 0;
125 {
126 struct Node {
127 Node(Node* n) : next(n) { created++; }
128 ~Node() { destroyed++; }
129 Node *next;
130 char filler[64];
131 };
132
133 SkSTArenaAlloc<64> arena;
134 Node* current = nullptr;
135 for (int i = 0; i < 128; i++) {
136 current = arena.make<Node>(current);
137 }
138 }
139 REPORTER_ASSERT(r, created == 128);
140 REPORTER_ASSERT(r, destroyed == 128);
141 }
142
DEF_TEST(ArenaAllocDestructionOrder,r)143 DEF_TEST(ArenaAllocDestructionOrder, r) {
144 // Make sure that objects and blocks are destroyed in the correct order. If they are not,
145 // then there will be a use after free error in asan.
146 static int created = 0,
147 destroyed = 0;
148 {
149 struct Node {
150 Node(Node* n) : next(n) { created++; }
151 ~Node() {
152 destroyed++;
153 if (next) {
154 next->~Node();
155 }
156 }
157 Node *next;
158 };
159
160 SkSTArenaAlloc<64> arena;
161 Node* current = nullptr;
162 for (int i = 0; i < 128; i++) {
163 uint64_t* temp = arena.makeArrayDefault<uint64_t>(sizeof(Node) / sizeof(Node*));
164 current = new (temp)Node(current);
165 }
166 current->~Node();
167 }
168 REPORTER_ASSERT(r, created == 128);
169 REPORTER_ASSERT(r, destroyed == 128);
170
171 {
172 SkSTArenaAlloc<64> arena;
173 auto a = arena.makeInitializedArray<int>(8, [](size_t i ) { return i; });
174 for (size_t i = 0; i < 8; i++) {
175 REPORTER_ASSERT(r, a[i] == (int)i);
176 }
177 }
178 }
179
DEF_TEST(ArenaAllocUnusualAlignment,r)180 DEF_TEST(ArenaAllocUnusualAlignment, r) {
181 SkArenaAlloc arena(4096);
182 // Move to a 1 character boundary.
183 arena.make<char>();
184 // Allocate something with interesting alignment.
185 void* ptr = arena.makeBytesAlignedTo(4081, 8);
186 REPORTER_ASSERT(r, ((intptr_t)ptr & 7) == 0);
187 }
188
DEF_TEST(SkFibBlockSizes,r)189 DEF_TEST(SkFibBlockSizes, r) {
190 {
191 SkFibBlockSizes<std::numeric_limits<uint32_t>::max()> fibs{1, 1};
192 uint32_t lastSize = 1;
193 for (int i = 0; i < 64; i++) {
194 uint32_t size = fibs.nextBlockSize();
195 REPORTER_ASSERT(r, lastSize <= size);
196 lastSize = size;
197 }
198 REPORTER_ASSERT(r, lastSize == 2971215073u);
199 }
200 {
201 SkFibBlockSizes<std::numeric_limits<uint32_t>::max()> fibs{0, 1024};
202 uint32_t lastSize = 1;
203 for (int i = 0; i < 64; i++) {
204 uint32_t size = fibs.nextBlockSize();
205 REPORTER_ASSERT(r, lastSize <= size);
206 lastSize = size;
207 REPORTER_ASSERT(r, lastSize <= std::numeric_limits<uint32_t>::max());
208 }
209 REPORTER_ASSERT(r, lastSize == 3524578u * 1024);
210 }
211
212 {
213 SkFibBlockSizes<std::numeric_limits<uint32_t>::max() / 2> fibs{1024, 0};
214 uint32_t lastSize = 1;
215 for (int i = 0; i < 64; i++) {
216 uint32_t size = fibs.nextBlockSize();
217 REPORTER_ASSERT(r, lastSize <= size);
218 lastSize = size;
219 REPORTER_ASSERT(r, lastSize <= std::numeric_limits<uint32_t>::max() / 2);
220 }
221 REPORTER_ASSERT(r, lastSize == 1346269u * 1024);
222 }
223 }
224