blob: 75bc232b4b63cbfcaefb0a19665059a0bdb3455f [file] [log] [blame]
Mike Klein58b13062016-11-11 10:38:49 -05001/*
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 "Test.h"
9#include "SkFixedAlloc.h"
10
11namespace {
12
Mike Klein526525a2016-11-15 17:58:33 +000013 static int created, destroyed;
Mike Klein58b13062016-11-11 10:38:49 -050014
15 struct Foo {
Herb Derby0497f082017-01-13 11:30:44 -050016 Foo() : x(-2), y(-3.0f) { created++; }
17 Foo(int X, float Y) : x(X), y(Y) { created++; }
Mike Klein526525a2016-11-15 17:58:33 +000018 ~Foo() { destroyed++; }
Mike Klein58b13062016-11-11 10:38:49 -050019
20 int x;
21 float y;
22 };
23
24 struct Big {
25 Big() {}
26 uint32_t array[128];
27 };
28
29}
30
31DEF_TEST(FixedAlloc, r) {
32 // Basic mechanics.
33 {
34 uint8_t buf[128];
35 SkFixedAlloc fa(buf, sizeof(buf));
36
37 Foo* foo = fa.make<Foo>(3, 4.0f);
38 REPORTER_ASSERT(r, foo);
39 REPORTER_ASSERT(r, foo->x == 3);
40 REPORTER_ASSERT(r, foo->y == 4.0f);
41 REPORTER_ASSERT(r, created == 1);
Mike Klein526525a2016-11-15 17:58:33 +000042 REPORTER_ASSERT(r, destroyed == 0);
Mike Klein58b13062016-11-11 10:38:49 -050043
44 Foo* bar = fa.make<Foo>(8, 1.0f);
45 REPORTER_ASSERT(r, bar);
46 REPORTER_ASSERT(r, bar->x == 8);
47 REPORTER_ASSERT(r, bar->y == 1.0f);
48 REPORTER_ASSERT(r, created == 2);
Mike Klein526525a2016-11-15 17:58:33 +000049 REPORTER_ASSERT(r, destroyed == 0);
Mike Klein58b13062016-11-11 10:38:49 -050050
51 fa.undo();
Mike Klein526525a2016-11-15 17:58:33 +000052 REPORTER_ASSERT(r, created == 2);
53 REPORTER_ASSERT(r, destroyed == 1);
Mike Klein58b13062016-11-11 10:38:49 -050054 }
Mike Klein526525a2016-11-15 17:58:33 +000055 REPORTER_ASSERT(r, created == 2);
56 REPORTER_ASSERT(r, destroyed == 2);
Mike Klein58b13062016-11-11 10:38:49 -050057
58 {
59 // Test alignment gurantees.
60 uint8_t buf[64];
61 SkFixedAlloc fa(buf+3, sizeof(buf)-3);
62
63 Foo* foo = fa.make<Foo>(3, 4.0f);
64 REPORTER_ASSERT(r, SkIsAlign4((uintptr_t)foo));
65 REPORTER_ASSERT(r, created == 3);
Mike Klein526525a2016-11-15 17:58:33 +000066 REPORTER_ASSERT(r, destroyed == 2);
Mike Klein58b13062016-11-11 10:38:49 -050067
68 // Might as well test reset() while we're at it.
69 fa.reset();
Mike Klein526525a2016-11-15 17:58:33 +000070 REPORTER_ASSERT(r, created == 3);
71 REPORTER_ASSERT(r, destroyed == 3);
Mike Klein58b13062016-11-11 10:38:49 -050072 }
Mike Klein526525a2016-11-15 17:58:33 +000073 REPORTER_ASSERT(r, created == 3);
74 REPORTER_ASSERT(r, destroyed == 3);
Mike Klein58b13062016-11-11 10:38:49 -050075}
76
77DEF_TEST(FallbackAlloc, r) {
78 // SkFixedAlloc will eventually fail when it runs out of space in its buffer.
79 int buf[32];
80 SkFixedAlloc fixed(buf, sizeof(buf));
81 bool fixed_failed = false;
82 for (int i = 0; i < 32; i++) {
Mike Klein526525a2016-11-15 17:58:33 +000083 // (Remember, there is some overhead to each make() call.)
84 fixed_failed = fixed_failed || (fixed.make<int>(i) == nullptr);
Mike Klein58b13062016-11-11 10:38:49 -050085 }
86 REPORTER_ASSERT(r, fixed_failed);
87
88
89 // SkFallbackAlloc will always succeed, using the heap as required.
90 fixed.reset();
91 SkFallbackAlloc fallback(&fixed);
92
93 bool fallback_failed = false;
94 for (int i = 0; i < 32; i++) {
Mike Klein526525a2016-11-15 17:58:33 +000095 fallback_failed = fallback_failed || (fallback.make<int>(i) == nullptr);
Mike Klein58b13062016-11-11 10:38:49 -050096 }
97 REPORTER_ASSERT(r, !fallback_failed);
98
99
100 // Test small, big, small allocations to make sure once we go to the heap we stay there.
101 fallback.reset();
102 auto smallA = fallback.make<int>(2);
103 auto big = fallback.make<Big>();
104 auto smallB = fallback.make<int>(3);
105
106 auto in_buf = [&](void* ptr) {
107 return (uintptr_t)(buf+0 ) <= (uintptr_t)ptr
108 && (uintptr_t)(buf+32) > (uintptr_t)ptr;
109 };
110
111 REPORTER_ASSERT(r, in_buf(smallA));
112 REPORTER_ASSERT(r, !in_buf(big));
113 REPORTER_ASSERT(r, !in_buf(smallB));
114}
Herb Derby0497f082017-01-13 11:30:44 -0500115
116struct WithDtor {
117 ~WithDtor() { }
118};
119
120DEF_TEST(ArenaAlloc, r) {
121
122 {
123 created = 0;
124 destroyed = 0;
125
126 SkArenaAlloc arena{nullptr, 0};
127 REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
128 Foo* foo = arena.make<Foo>(3, 4.0f);
129 REPORTER_ASSERT(r, foo->x == 3);
130 REPORTER_ASSERT(r, foo->y == 4.0f);
131 REPORTER_ASSERT(r, created == 1);
132 REPORTER_ASSERT(r, destroyed == 0);
133 arena.makeArrayDefault<int>(10);
134 int* zeroed = arena.makeArray<int>(10);
135 for (int i = 0; i < 10; i++) {
136 REPORTER_ASSERT(r, zeroed[i] == 0);
137 }
138 Foo* fooArray = arena.makeArrayDefault<Foo>(10);
139 REPORTER_ASSERT(r, fooArray[3].x == -2);
140 REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
141 REPORTER_ASSERT(r, created == 11);
142 REPORTER_ASSERT(r, destroyed == 0);
143 arena.make<typename std::aligned_storage<10,8>::type>();
144 }
145 REPORTER_ASSERT(r, created == 11);
146 REPORTER_ASSERT(r, destroyed == 11);
147
148 {
149 created = 0;
150 destroyed = 0;
151 char block[1024];
152 SkArenaAlloc arena{block};
153
154 REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
155 Foo* foo = arena.make<Foo>(3, 4.0f);
156 REPORTER_ASSERT(r, foo->x == 3);
157 REPORTER_ASSERT(r, foo->y == 4.0f);
158 REPORTER_ASSERT(r, created == 1);
159 REPORTER_ASSERT(r, destroyed == 0);
160 arena.makeArrayDefault<int>(10);
161 int* zeroed = arena.makeArray<int>(10);
162 for (int i = 0; i < 10; i++) {
163 REPORTER_ASSERT(r, zeroed[i] == 0);
164 }
165 Foo* fooArray = arena.makeArrayDefault<Foo>(10);
166 REPORTER_ASSERT(r, fooArray[3].x == -2);
167 REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
168 REPORTER_ASSERT(r, created == 11);
169 REPORTER_ASSERT(r, destroyed == 0);
170 arena.make<typename std::aligned_storage<10,8>::type>();
171 }
172 REPORTER_ASSERT(r, created == 11);
173 REPORTER_ASSERT(r, destroyed == 11);
174
175 {
176 created = 0;
177 destroyed = 0;
178 std::unique_ptr<char[]> block{new char[1024]};
179 SkArenaAlloc arena{block.get(), 1024};
180
181 REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
182 Foo* foo = arena.make<Foo>(3, 4.0f);
183 REPORTER_ASSERT(r, foo->x == 3);
184 REPORTER_ASSERT(r, foo->y == 4.0f);
185 REPORTER_ASSERT(r, created == 1);
186 REPORTER_ASSERT(r, destroyed == 0);
187 arena.makeArrayDefault<int>(10);
188 int* zeroed = arena.makeArray<int>(10);
189 for (int i = 0; i < 10; i++) {
190 REPORTER_ASSERT(r, zeroed[i] == 0);
191 }
192 Foo* fooArray = arena.makeArrayDefault<Foo>(10);
193 REPORTER_ASSERT(r, fooArray[3].x == -2);
194 REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
195 REPORTER_ASSERT(r, created == 11);
196 REPORTER_ASSERT(r, destroyed == 0);
197 arena.make<typename std::aligned_storage<10,8>::type>();
198 }
199 REPORTER_ASSERT(r, created == 11);
200 REPORTER_ASSERT(r, destroyed == 11);
201
202}