1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/Assertions.h"
8 #include "mozilla/AtomicBitfields.h"
10 // This is a big macro mess, so let's summarize what's in here right up front:
12 // |TestDocumentationExample| is intended to be a copy-paste of the example
13 // in the macro's documentation, to make sure it's correct.
16 // |TestJammedWithFlags| tests using every bit of the type for bool flags.
17 // 64-bit isn't tested due to macro limitations.
20 // |TestLopsided| tests an instance with the following configuration:
23 // * an (N-1)-bit uintN_t
25 // It tests both orderings of these fields.
27 // Hopefully these are enough to cover all the nasty boundary conditions
28 // (that still compile).
30 // ==================== TestDocumentationExample ========================
33 MOZ_ATOMIC_BITFIELDS(mAtomicFields
, 8,
34 ((bool, IsDownloaded
, 1), (uint32_t, SomeData
, 2),
35 (uint8_t, OtherData
, 5)))
37 int32_t aNormalInteger
;
39 explicit MyType(uint32_t aSomeData
) : aNormalInteger(7) {
40 StoreSomeData(aSomeData
);
41 // Other bitfields were already default initialized to 0/false
45 void TestDocumentationExample() {
48 if (!val
.LoadIsDownloaded()) {
49 val
.StoreOtherData(2);
50 val
.StoreIsDownloaded(true);
54 // ====================== TestJammedWithFlags =========================
56 #define TIMES_8(aFunc, aSeparator, aArgs) \
57 MOZ_FOR_EACH_SEPARATED(aFunc, aSeparator, aArgs, (1, 2, 3, 4, 5, 6, 7, 8))
58 #define TIMES_16(aFunc, aSeparator, aArgs) \
59 MOZ_FOR_EACH_SEPARATED( \
60 aFunc, aSeparator, aArgs, \
61 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16))
62 #define TIMES_32(aFunc, aSeparator, aArgs) \
63 MOZ_FOR_EACH_SEPARATED( \
64 aFunc, aSeparator, aArgs, \
65 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, \
66 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32))
68 #define CHECK_BOOL(aIndex) \
69 MOZ_ASSERT(val.LoadFlag##aIndex() == false); \
70 val.StoreFlag##aIndex(true); \
71 MOZ_ASSERT(val.LoadFlag##aIndex() == true); \
72 val.StoreFlag##aIndex(false); \
73 MOZ_ASSERT(val.LoadFlag##aIndex() == false);
75 #define GENERATE_TEST_JAMMED_WITH_FLAGS(aSize) \
76 void TestJammedWithFlags##aSize() { \
77 JammedWithFlags##aSize val; \
78 TIMES_##aSize(CHECK_BOOL, (;), ()); \
81 #define TEST_JAMMED_WITH_FLAGS(aSize) TestJammedWithFlags##aSize();
83 // ========================= TestLopsided ===========================
85 #define GENERATE_TEST_LOPSIDED_FUNC(aSide, aSize) \
86 void TestLopsided##aSide##aSize() { \
87 Lopsided##aSide##aSize val; \
88 MOZ_ASSERT(val.LoadHappyLittleBit() == false); \
89 MOZ_ASSERT(val.LoadLargeAndInCharge() == 0); \
90 val.StoreHappyLittleBit(true); \
91 MOZ_ASSERT(val.LoadHappyLittleBit() == true); \
92 MOZ_ASSERT(val.LoadLargeAndInCharge() == 0); \
93 val.StoreLargeAndInCharge(1); \
94 MOZ_ASSERT(val.LoadHappyLittleBit() == true); \
95 MOZ_ASSERT(val.LoadLargeAndInCharge() == 1); \
96 val.StoreLargeAndInCharge(0); \
97 MOZ_ASSERT(val.LoadHappyLittleBit() == true); \
98 MOZ_ASSERT(val.LoadLargeAndInCharge() == 0); \
99 uint##aSize##_t size = aSize; \
100 uint##aSize##_t int_max = (~(1ull << (size - 1))) - 1; \
101 val.StoreLargeAndInCharge(int_max); \
102 MOZ_ASSERT(val.LoadHappyLittleBit() == true); \
103 MOZ_ASSERT(val.LoadLargeAndInCharge() == int_max); \
104 val.StoreHappyLittleBit(false); \
105 MOZ_ASSERT(val.LoadHappyLittleBit() == false); \
106 MOZ_ASSERT(val.LoadLargeAndInCharge() == int_max); \
107 val.StoreLargeAndInCharge(int_max); \
108 MOZ_ASSERT(val.LoadHappyLittleBit() == false); \
109 MOZ_ASSERT(val.LoadLargeAndInCharge() == int_max); \
112 #define GENERATE_TEST_LOPSIDED(aSize) \
113 struct LopsidedA##aSize { \
114 MOZ_ATOMIC_BITFIELDS(mAtomicFields, aSize, \
115 ((bool, HappyLittleBit, 1), \
116 (uint##aSize##_t, LargeAndInCharge, ((aSize)-1)))) \
118 struct LopsidedB##aSize { \
119 MOZ_ATOMIC_BITFIELDS(mAtomicFields, aSize, \
120 ((uint##aSize##_t, LargeAndInCharge, ((aSize)-1)), \
121 (bool, HappyLittleBit, 1))) \
123 GENERATE_TEST_LOPSIDED_FUNC(A, aSize); \
124 GENERATE_TEST_LOPSIDED_FUNC(B, aSize);
126 #define TEST_LOPSIDED(aSize) \
127 TestLopsidedA##aSize(); \
128 TestLopsidedB##aSize();
130 // ==================== generate and run the tests ======================
132 // There's an unknown bug in clang-cl-9 (used for win64-ccov) that makes
133 // generating these with the TIMES_N macro not work. So these are written out
134 // explicitly to unbork CI.
135 struct JammedWithFlags8
{
136 MOZ_ATOMIC_BITFIELDS(mAtomicFields
, 8,
137 ((bool, Flag1
, 1), (bool, Flag2
, 1), (bool, Flag3
, 1),
138 (bool, Flag4
, 1), (bool, Flag5
, 1), (bool, Flag6
, 1),
139 (bool, Flag7
, 1), (bool, Flag8
, 1)))
142 struct JammedWithFlags16
{
143 MOZ_ATOMIC_BITFIELDS(mAtomicFields
, 16,
144 ((bool, Flag1
, 1), (bool, Flag2
, 1), (bool, Flag3
, 1),
145 (bool, Flag4
, 1), (bool, Flag5
, 1), (bool, Flag6
, 1),
146 (bool, Flag7
, 1), (bool, Flag8
, 1), (bool, Flag9
, 1),
147 (bool, Flag10
, 1), (bool, Flag11
, 1), (bool, Flag12
, 1),
148 (bool, Flag13
, 1), (bool, Flag14
, 1), (bool, Flag15
, 1),
152 struct JammedWithFlags32
{
153 MOZ_ATOMIC_BITFIELDS(mAtomicFields
, 32,
154 ((bool, Flag1
, 1), (bool, Flag2
, 1), (bool, Flag3
, 1),
155 (bool, Flag4
, 1), (bool, Flag5
, 1), (bool, Flag6
, 1),
156 (bool, Flag7
, 1), (bool, Flag8
, 1), (bool, Flag9
, 1),
157 (bool, Flag10
, 1), (bool, Flag11
, 1), (bool, Flag12
, 1),
158 (bool, Flag13
, 1), (bool, Flag14
, 1), (bool, Flag15
, 1),
159 (bool, Flag16
, 1), (bool, Flag17
, 1), (bool, Flag18
, 1),
160 (bool, Flag19
, 1), (bool, Flag20
, 1), (bool, Flag21
, 1),
161 (bool, Flag22
, 1), (bool, Flag23
, 1), (bool, Flag24
, 1),
162 (bool, Flag25
, 1), (bool, Flag26
, 1), (bool, Flag27
, 1),
163 (bool, Flag28
, 1), (bool, Flag29
, 1), (bool, Flag30
, 1),
164 (bool, Flag31
, 1), (bool, Flag32
, 1)))
167 GENERATE_TEST_JAMMED_WITH_FLAGS(8)
168 GENERATE_TEST_JAMMED_WITH_FLAGS(16)
169 GENERATE_TEST_JAMMED_WITH_FLAGS(32)
170 // MOZ_FOR_EACH_64 doesn't exist :(
172 GENERATE_TEST_LOPSIDED(8)
173 GENERATE_TEST_LOPSIDED(16)
174 GENERATE_TEST_LOPSIDED(32)
175 GENERATE_TEST_LOPSIDED(64)
178 TestDocumentationExample();
180 TEST_JAMMED_WITH_FLAGS(8);
181 TEST_JAMMED_WITH_FLAGS(16);
182 TEST_JAMMED_WITH_FLAGS(32);