Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <LibTest/TestCase.h>
8
9#include <AK/Atomic.h>
10
11TEST_CASE(construct_empty)
12{
13 EXPECT(Atomic<bool>().load() == false);
14 EXPECT(Atomic<u32>().load() == 0);
15 EXPECT(Atomic<u16>().load() == 0);
16 EXPECT(Atomic<u8>().load() == 0);
17
18 EXPECT(Atomic<u16*>().load() == nullptr);
19}
20
21TEST_CASE(construct_with_value)
22{
23 EXPECT(Atomic<bool>(false).load() == false);
24 EXPECT(Atomic<bool>(true).load() == true);
25 EXPECT(Atomic<u32>(2).load() == 2);
26 EXPECT(Atomic<u16>(3).load() == 3);
27 EXPECT(Atomic<u8>(4).load() == 4);
28
29 u16 v_u16 = 0;
30 EXPECT(Atomic<u16*>(&v_u16).load() == &v_u16);
31}
32
33TEST_CASE(do_exchange)
34{
35 Atomic<bool> a_bool(false);
36 EXPECT(a_bool.exchange(true) == false);
37 EXPECT(a_bool.load() == true && static_cast<bool>(a_bool) == true);
38
39 Atomic<u32> a_u32(2);
40 EXPECT(a_u32.exchange(22) == 2);
41 EXPECT(a_u32.load() == 22 && static_cast<u8>(a_u32) == 22);
42
43 Atomic<u16> a_u16(3);
44 EXPECT(a_u16.exchange(33) == 3);
45 EXPECT(a_u16.load() == 33 && static_cast<u8>(a_u16) == 33);
46
47 Atomic<u8> a_u8(4);
48 EXPECT(a_u8.exchange(44) == 4);
49 EXPECT(a_u8.load() == 44 && static_cast<u8>(a_u8) == 44);
50
51 u16 v_u16[6];
52 Atomic<u16*> a_pu16(&v_u16[2]);
53 EXPECT(a_pu16.load() == &v_u16[2] && static_cast<u16*>(a_pu16) == &v_u16[2]);
54}
55
56TEST_CASE(do_compare_exchange)
57{
58 Atomic<bool> a_bool(false);
59 bool e_bool = true;
60 EXPECT(a_bool.compare_exchange_strong(e_bool, true) == false);
61 EXPECT(e_bool == false);
62 EXPECT(a_bool.load() == false && static_cast<bool>(a_bool) == false);
63 e_bool = false;
64 EXPECT(a_bool.compare_exchange_strong(e_bool, true) == true);
65 EXPECT(a_bool.load() == true && static_cast<bool>(a_bool) == true);
66
67 Atomic<u32> a_u32(2);
68 u32 e_u32 = 99;
69 EXPECT(a_u32.compare_exchange_strong(e_u32, 22) == false);
70 EXPECT(e_u32 == 2);
71 EXPECT(a_u32.load() == 2 && static_cast<u32>(a_u32) == 2);
72 e_u32 = 2;
73 EXPECT(a_u32.compare_exchange_strong(e_u32, 22) == true);
74 EXPECT(a_u32.load() == 22 && static_cast<u32>(a_u32) == 22);
75
76 Atomic<u16> a_u16(3);
77 u16 e_u16 = 99;
78 EXPECT(a_u16.compare_exchange_strong(e_u16, 33) == false);
79 EXPECT(e_u16 == 3);
80 EXPECT(a_u16.load() == 3 && static_cast<u16>(a_u16) == 3);
81 e_u16 = 3;
82 EXPECT(a_u16.compare_exchange_strong(e_u16, 33) == true);
83 EXPECT(a_u16.load() == 33 && static_cast<u16>(a_u16) == 33);
84
85 Atomic<u8> a_u8(4);
86 u8 e_u8 = 99;
87 EXPECT(a_u8.compare_exchange_strong(e_u8, 44) == false);
88 EXPECT(e_u8 == 4);
89 EXPECT(a_u8.load() == 4 && static_cast<u16>(a_u8) == 4);
90 e_u8 = 4;
91 EXPECT(a_u8.compare_exchange_strong(e_u8, 44) == true);
92 EXPECT(a_u8.load() == 44 && static_cast<u16>(a_u8) == 44);
93}
94
95TEST_CASE(fetch_add)
96{
97 Atomic<u32> a_u32(5);
98 EXPECT(a_u32.fetch_add(2) == 5);
99 EXPECT(a_u32.load() == 7 && static_cast<u32>(a_u32) == 7);
100
101 Atomic<u16> a_u16(5);
102 EXPECT(a_u16.fetch_add(2) == 5);
103 EXPECT(a_u16.load() == 7 && static_cast<u16>(a_u16) == 7);
104
105 Atomic<u8> a_u8(5);
106 EXPECT(a_u8.fetch_add(2) == 5);
107 EXPECT(a_u8.load() == 7 && static_cast<u8>(a_u8) == 7);
108
109 u32 v_u32[6];
110 Atomic<u32*> a_pu32(&v_u32[2]);
111 EXPECT(a_pu32.load() == &v_u32[2] && static_cast<u32*>(a_pu32) == &v_u32[2]);
112 EXPECT(a_pu32.fetch_add(2) == &v_u32[2]);
113 EXPECT(a_pu32.load() == &v_u32[4] && static_cast<u32*>(a_pu32) == &v_u32[4]);
114 EXPECT(a_pu32.fetch_add(-3) == &v_u32[4]);
115 EXPECT(a_pu32.load() == &v_u32[1] && static_cast<u32*>(a_pu32) == &v_u32[1]);
116
117 u16 v_u16[6];
118 Atomic<u16*> a_pu16(&v_u16[2]);
119 EXPECT(a_pu16.load() == &v_u16[2] && static_cast<u16*>(a_pu16) == &v_u16[2]);
120 EXPECT(a_pu16.fetch_add(2) == &v_u16[2]);
121 EXPECT(a_pu16.load() == &v_u16[4] && static_cast<u16*>(a_pu16) == &v_u16[4]);
122 EXPECT(a_pu16.fetch_add(-3) == &v_u16[4]);
123 EXPECT(a_pu16.load() == &v_u16[1] && static_cast<u16*>(a_pu16) == &v_u16[1]);
124
125 u8 v_u8[6];
126 Atomic<u8*> a_pu8(&v_u8[2]);
127 EXPECT(a_pu8.load() == &v_u8[2] && static_cast<u8*>(a_pu8) == &v_u8[2]);
128 EXPECT(a_pu8.fetch_add(2) == &v_u8[2]);
129 EXPECT(a_pu8.load() == &v_u8[4] && static_cast<u8*>(a_pu8) == &v_u8[4]);
130 EXPECT(a_pu8.fetch_add(-3) == &v_u8[4]);
131 EXPECT(a_pu8.load() == &v_u8[1] && static_cast<u8*>(a_pu8) == &v_u8[1]);
132}
133
134TEST_CASE(fetch_sub)
135{
136 Atomic<u32> a_u32(5);
137 EXPECT(a_u32.fetch_sub(2) == 5);
138 EXPECT(a_u32.load() == 3 && static_cast<u32>(a_u32) == 3);
139
140 Atomic<u16> a_u16(5);
141 EXPECT(a_u16.fetch_sub(2) == 5);
142 EXPECT(a_u16.load() == 3 && static_cast<u16>(a_u16) == 3);
143
144 Atomic<u8> a_u8(5);
145 EXPECT(a_u8.fetch_sub(2) == 5);
146 EXPECT(a_u8.load() == 3 && static_cast<u8>(a_u8) == 3);
147
148 u32 v_u32[6];
149 Atomic<u32*> a_pu32(&v_u32[2]);
150 EXPECT(a_pu32.load() == &v_u32[2] && static_cast<u32*>(a_pu32) == &v_u32[2]);
151 EXPECT(a_pu32.fetch_sub(2) == &v_u32[2]);
152 EXPECT(a_pu32.load() == &v_u32[0] && static_cast<u32*>(a_pu32) == &v_u32[0]);
153 EXPECT(a_pu32.fetch_sub(-3) == &v_u32[0]);
154 EXPECT(a_pu32.load() == &v_u32[3] && static_cast<u32*>(a_pu32) == &v_u32[3]);
155
156 u16 v_u16[6];
157 Atomic<u16*> a_pu16(&v_u16[2]);
158 EXPECT(a_pu16.load() == &v_u16[2] && static_cast<u16*>(a_pu16) == &v_u16[2]);
159 EXPECT(a_pu16.fetch_sub(2) == &v_u16[2]);
160 EXPECT(a_pu16.load() == &v_u16[0] && static_cast<u16*>(a_pu16) == &v_u16[0]);
161 EXPECT(a_pu16.fetch_sub(-3) == &v_u16[0]);
162 EXPECT(a_pu16.load() == &v_u16[3] && static_cast<u16*>(a_pu16) == &v_u16[3]);
163
164 u8 v_u8[6];
165 Atomic<u8*> a_pu8(&v_u8[2]);
166 EXPECT(a_pu8.load() == &v_u8[2] && static_cast<u8*>(a_pu8) == &v_u8[2]);
167 EXPECT(a_pu8.fetch_sub(2) == &v_u8[2]);
168 EXPECT(a_pu8.load() == &v_u8[0] && static_cast<u8*>(a_pu8) == &v_u8[0]);
169 EXPECT(a_pu8.fetch_sub(-3) == &v_u8[0]);
170 EXPECT(a_pu8.load() == &v_u8[3] && static_cast<u8*>(a_pu8) == &v_u8[3]);
171}
172
173TEST_CASE(fetch_inc)
174{
175 Atomic<u32> a_u32(5);
176 EXPECT(a_u32++ == 5);
177 EXPECT(a_u32.load() == 6 && a_u32 == 6);
178 EXPECT(++a_u32 == 7);
179 EXPECT(a_u32.load() == 7 && a_u32 == 7);
180 EXPECT((a_u32 += 2) == 9);
181 EXPECT(a_u32.load() == 9 && a_u32 == 9);
182
183 Atomic<u16> a_u16(5);
184 EXPECT(a_u16++ == 5);
185 EXPECT(a_u16.load() == 6 && a_u16 == 6);
186 EXPECT(++a_u16 == 7);
187 EXPECT(a_u16.load() == 7 && a_u16 == 7);
188 EXPECT((a_u16 += 2) == 9);
189 EXPECT(a_u16.load() == 9 && a_u16 == 9);
190
191 Atomic<u8> a_u8(5);
192 EXPECT(a_u8++ == 5);
193 EXPECT(a_u8.load() == 6 && a_u8 == 6);
194 EXPECT(++a_u8 == 7);
195 EXPECT(a_u8.load() == 7 && a_u8 == 7);
196 EXPECT((a_u8 += 2) == 9);
197 EXPECT(a_u8.load() == 9 && a_u8 == 9);
198
199 u32 v_u32[8];
200 Atomic<u32*> a_pu32(&v_u32[2]);
201 EXPECT(a_pu32++ == &v_u32[2]);
202 EXPECT(a_pu32.load() == &v_u32[3] && a_pu32 == &v_u32[3]);
203 EXPECT(++a_pu32 == &v_u32[4]);
204 EXPECT(a_pu32.load() == &v_u32[4] && a_pu32 == &v_u32[4]);
205 EXPECT((a_pu32 += 2) == &v_u32[6]);
206 EXPECT(a_pu32.load() == &v_u32[6] && a_pu32 == &v_u32[6]);
207
208 u16 v_u16[8];
209 Atomic<u16*> a_pu16(&v_u16[2]);
210 EXPECT(a_pu16++ == &v_u16[2]);
211 EXPECT(a_pu16.load() == &v_u16[3] && a_pu16 == &v_u16[3]);
212 EXPECT(++a_pu16 == &v_u16[4]);
213 EXPECT(a_pu16.load() == &v_u16[4] && a_pu16 == &v_u16[4]);
214 EXPECT((a_pu16 += 2) == &v_u16[6]);
215 EXPECT(a_pu16.load() == &v_u16[6] && a_pu16 == &v_u16[6]);
216
217 u8 v_u8[8];
218 Atomic<u8*> a_pu8(&v_u8[2]);
219 EXPECT(a_pu8++ == &v_u8[2]);
220 EXPECT(a_pu8.load() == &v_u8[3] && a_pu8 == &v_u8[3]);
221 EXPECT(++a_pu8 == &v_u8[4]);
222 EXPECT(a_pu8.load() == &v_u8[4] && a_pu8 == &v_u8[4]);
223 EXPECT((a_pu8 += 2) == &v_u8[6]);
224 EXPECT(a_pu8.load() == &v_u8[6] && a_pu8 == &v_u8[6]);
225}
226
227TEST_CASE(fetch_dec)
228{
229 Atomic<u32> a_u32(5);
230 EXPECT(a_u32-- == 5);
231 EXPECT(a_u32.load() == 4 && a_u32 == 4);
232 EXPECT(--a_u32 == 3);
233 EXPECT(a_u32.load() == 3 && a_u32 == 3);
234 EXPECT((a_u32 -= 2) == 1);
235 EXPECT(a_u32.load() == 1 && a_u32 == 1);
236
237 Atomic<u16> a_u16(5);
238 EXPECT(a_u16-- == 5);
239 EXPECT(a_u16.load() == 4 && a_u16 == 4);
240 EXPECT(--a_u16 == 3);
241 EXPECT(a_u16.load() == 3 && a_u16 == 3);
242 EXPECT((a_u16 -= 2) == 1);
243 EXPECT(a_u16.load() == 1 && a_u16 == 1);
244
245 Atomic<u8> a_u8(5);
246 EXPECT(a_u8-- == 5);
247 EXPECT(a_u8.load() == 4 && a_u8 == 4);
248 EXPECT(--a_u8 == 3);
249 EXPECT(a_u8.load() == 3 && a_u8 == 3);
250 EXPECT((a_u8 -= 2) == 1);
251 EXPECT(a_u8.load() == 1 && a_u8 == 1);
252
253 u32 v_u32[8];
254 Atomic<u32*> a_pu32(&v_u32[7]);
255 EXPECT(a_pu32-- == &v_u32[7]);
256 EXPECT(a_pu32.load() == &v_u32[6] && a_pu32 == &v_u32[6]);
257 EXPECT(--a_pu32 == &v_u32[5]);
258 EXPECT(a_pu32.load() == &v_u32[5] && a_pu32 == &v_u32[5]);
259 EXPECT((a_pu32 -= 2) == &v_u32[3]);
260 EXPECT(a_pu32.load() == &v_u32[3] && a_pu32 == &v_u32[3]);
261
262 u16 v_u16[8];
263 Atomic<u16*> a_pu16(&v_u16[7]);
264 EXPECT(a_pu16-- == &v_u16[7]);
265 EXPECT(a_pu16.load() == &v_u16[6] && a_pu16 == &v_u16[6]);
266 EXPECT(--a_pu16 == &v_u16[5]);
267 EXPECT(a_pu16.load() == &v_u16[5] && a_pu16 == &v_u16[5]);
268 EXPECT((a_pu16 -= 2) == &v_u16[3]);
269 EXPECT(a_pu16.load() == &v_u16[3] && a_pu16 == &v_u16[3]);
270
271 u8 v_u8[8];
272 Atomic<u8*> a_pu8(&v_u8[7]);
273 EXPECT(a_pu8-- == &v_u8[7]);
274 EXPECT(a_pu8.load() == &v_u8[6] && a_pu8 == &v_u8[6]);
275 EXPECT(--a_pu8 == &v_u8[5]);
276 EXPECT(a_pu8.load() == &v_u8[5] && a_pu8 == &v_u8[5]);
277 EXPECT((a_pu8 -= 2) == &v_u8[3]);
278 EXPECT(a_pu8.load() == &v_u8[3] && a_pu8 == &v_u8[3]);
279}
280
281TEST_CASE(fetch_and)
282{
283 Atomic<u32> a_u32(0xdeadbeef);
284 EXPECT(a_u32.fetch_and(0x8badf00d) == 0xdeadbeef);
285 EXPECT(a_u32.load() == 0x8aadb00d && static_cast<u32>(a_u32) == 0x8aadb00d);
286 a_u32 = 0xdeadbeef;
287 EXPECT((a_u32 &= 0x8badf00d) == 0x8aadb00d);
288
289 Atomic<u16> a_u16(0xbeef);
290 EXPECT(a_u16.fetch_and(0xf00d) == 0xbeef);
291 EXPECT(a_u16.load() == 0xb00d && static_cast<u16>(a_u16) == 0xb00d);
292 a_u16 = 0xbeef;
293 EXPECT((a_u16 &= 0xf00d) == 0xb00d);
294
295 Atomic<u8> a_u8(0xef);
296 EXPECT(a_u8.fetch_and(0x0d) == 0xef);
297 EXPECT(a_u8.load() == 0x0d && static_cast<u8>(a_u8) == 0x0d);
298 a_u8 = 0xef;
299 EXPECT((a_u8 &= 0x0d) == 0x0d);
300}
301
302TEST_CASE(fetch_or)
303{
304 Atomic<u32> a_u32(0xaadb00d);
305 EXPECT(a_u32.fetch_or(0xdeadbeef) == 0xaadb00d);
306 EXPECT(a_u32.load() == 0xdeadbeef && static_cast<u32>(a_u32) == 0xdeadbeef);
307 a_u32 = 0xaadb00d;
308 EXPECT((a_u32 |= 0xdeadbeef) == 0xdeadbeef);
309
310 Atomic<u16> a_u16(0xb00d);
311 EXPECT(a_u16.fetch_or(0xbeef) == 0xb00d);
312 EXPECT(a_u16.load() == 0xbeef && static_cast<u16>(a_u16) == 0xbeef);
313 a_u16 = 0xb00d;
314 EXPECT((a_u16 |= 0xbeef) == 0xbeef);
315
316 Atomic<u8> a_u8(0x0d);
317 EXPECT(a_u8.fetch_or(0xef) == 0x0d);
318 EXPECT(a_u8.load() == 0xef && static_cast<u8>(a_u8) == 0xef);
319 a_u8 = 0x0d;
320 EXPECT((a_u8 |= 0xef) == 0xef);
321}
322
323TEST_CASE(fetch_xor)
324{
325 Atomic<u32> a_u32(0x55004ee2);
326 EXPECT(a_u32.fetch_xor(0xdeadbeef) == 0x55004ee2);
327 EXPECT(a_u32.load() == 0x8badf00d && static_cast<u32>(a_u32) == 0x8badf00d);
328 a_u32 = 0x55004ee2;
329 EXPECT((a_u32 ^= 0xdeadbeef) == 0x8badf00d);
330
331 Atomic<u16> a_u16(0x4ee2);
332 EXPECT(a_u16.fetch_xor(0xbeef) == 0x4ee2);
333 EXPECT(a_u16.load() == 0xf00d && static_cast<u16>(a_u16) == 0xf00d);
334 a_u16 = 0x4ee2;
335 EXPECT((a_u16 ^= 0xbeef) == 0xf00d);
336
337 Atomic<u8> a_u8(0xe2);
338 EXPECT(a_u8.fetch_xor(0xef) == 0xe2);
339 EXPECT(a_u8.load() == 0x0d && static_cast<u8>(a_u8) == 0x0d);
340 a_u8 = 0xe2;
341 EXPECT((a_u8 ^= 0xef) == 0x0d);
342}