TestEnumSet.cpp (9370B)
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 file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/BitSet.h" 8 #include "mozilla/EnumSet.h" 9 #include "mozilla/Vector.h" 10 11 #include <type_traits> 12 13 using namespace mozilla; 14 15 enum SeaBird { 16 PENGUIN, 17 ALBATROSS, 18 FULMAR, 19 PRION, 20 SHEARWATER, 21 GADFLY_PETREL, 22 TRUE_PETREL, 23 DIVING_PETREL, 24 STORM_PETREL, 25 PELICAN, 26 GANNET, 27 BOOBY, 28 CORMORANT, 29 FRIGATEBIRD, 30 TROPICBIRD, 31 SKUA, 32 GULL, 33 TERN, 34 SKIMMER, 35 AUK, 36 37 SEA_BIRD_COUNT 38 }; 39 40 enum class SmallEnum : uint8_t { 41 Foo, 42 Bar, 43 }; 44 45 enum class BigEnum : uint64_t { 46 Foo, 47 Bar = 35, 48 }; 49 50 template <typename Storage = typename std::make_unsigned< 51 typename std::underlying_type<SeaBird>::type>::type> 52 class EnumSetSuite { 53 public: 54 using EnumSetSeaBird = EnumSet<SeaBird, Storage>; 55 56 EnumSetSuite() 57 : mAlcidae(), 58 mDiomedeidae(ALBATROSS), 59 mPetrelProcellariidae(GADFLY_PETREL, TRUE_PETREL), 60 mNonPetrelProcellariidae(FULMAR, PRION, SHEARWATER), 61 mPetrels(GADFLY_PETREL, TRUE_PETREL, DIVING_PETREL, STORM_PETREL) {} 62 63 void runTests() { 64 testSize(); 65 testContains(); 66 testAddTo(); 67 testAdd(); 68 testAddAll(); 69 testUnion(); 70 testRemoveFrom(); 71 testRemove(); 72 testRemoveAllFrom(); 73 testRemoveAll(); 74 testIntersect(); 75 testInsersection(); 76 testEquality(); 77 testDuplicates(); 78 testIteration(); 79 testInitializerListConstuctor(); 80 testBigEnum(); 81 } 82 83 private: 84 void testEnumSetLayout() { 85 #ifndef DEBUG 86 static_assert(sizeof(EnumSet<SmallEnum>) == sizeof(SmallEnum), 87 "EnumSet should be no bigger than the enum by default"); 88 static_assert(sizeof(EnumSet<SmallEnum, uint32_t>) == sizeof(uint32_t), 89 "EnumSet should be able to have its size overriden."); 90 static_assert(std::is_trivially_copyable_v<EnumSet<SmallEnum>>, 91 "EnumSet should be lightweight outside of debug."); 92 #endif 93 } 94 95 void testSize() { 96 MOZ_RELEASE_ASSERT(mAlcidae.size() == 0); 97 MOZ_RELEASE_ASSERT(mDiomedeidae.size() == 1); 98 MOZ_RELEASE_ASSERT(mPetrelProcellariidae.size() == 2); 99 MOZ_RELEASE_ASSERT(mNonPetrelProcellariidae.size() == 3); 100 MOZ_RELEASE_ASSERT(mPetrels.size() == 4); 101 } 102 103 void testContains() { 104 MOZ_RELEASE_ASSERT(!mPetrels.contains(PENGUIN)); 105 MOZ_RELEASE_ASSERT(!mPetrels.contains(ALBATROSS)); 106 MOZ_RELEASE_ASSERT(!mPetrels.contains(FULMAR)); 107 MOZ_RELEASE_ASSERT(!mPetrels.contains(PRION)); 108 MOZ_RELEASE_ASSERT(!mPetrels.contains(SHEARWATER)); 109 MOZ_RELEASE_ASSERT(mPetrels.contains(GADFLY_PETREL)); 110 MOZ_RELEASE_ASSERT(mPetrels.contains(TRUE_PETREL)); 111 MOZ_RELEASE_ASSERT(mPetrels.contains(DIVING_PETREL)); 112 MOZ_RELEASE_ASSERT(mPetrels.contains(STORM_PETREL)); 113 MOZ_RELEASE_ASSERT(!mPetrels.contains(PELICAN)); 114 MOZ_RELEASE_ASSERT(!mPetrels.contains(GANNET)); 115 MOZ_RELEASE_ASSERT(!mPetrels.contains(BOOBY)); 116 MOZ_RELEASE_ASSERT(!mPetrels.contains(CORMORANT)); 117 MOZ_RELEASE_ASSERT(!mPetrels.contains(FRIGATEBIRD)); 118 MOZ_RELEASE_ASSERT(!mPetrels.contains(TROPICBIRD)); 119 MOZ_RELEASE_ASSERT(!mPetrels.contains(SKUA)); 120 MOZ_RELEASE_ASSERT(!mPetrels.contains(GULL)); 121 MOZ_RELEASE_ASSERT(!mPetrels.contains(TERN)); 122 MOZ_RELEASE_ASSERT(!mPetrels.contains(SKIMMER)); 123 MOZ_RELEASE_ASSERT(!mPetrels.contains(AUK)); 124 } 125 126 void testCopy() { 127 EnumSetSeaBird likes = mPetrels; 128 likes -= TRUE_PETREL; 129 MOZ_RELEASE_ASSERT(mPetrels.size() == 4); 130 MOZ_RELEASE_ASSERT(mPetrels.contains(TRUE_PETREL)); 131 132 MOZ_RELEASE_ASSERT(likes.size() == 3); 133 MOZ_RELEASE_ASSERT(likes.contains(GADFLY_PETREL)); 134 MOZ_RELEASE_ASSERT(likes.contains(DIVING_PETREL)); 135 MOZ_RELEASE_ASSERT(likes.contains(STORM_PETREL)); 136 } 137 138 void testAddTo() { 139 EnumSetSeaBird seen = mPetrels; 140 seen += CORMORANT; 141 seen += TRUE_PETREL; 142 MOZ_RELEASE_ASSERT(mPetrels.size() == 4); 143 MOZ_RELEASE_ASSERT(!mPetrels.contains(CORMORANT)); 144 MOZ_RELEASE_ASSERT(seen.size() == 5); 145 MOZ_RELEASE_ASSERT(seen.contains(GADFLY_PETREL)); 146 MOZ_RELEASE_ASSERT(seen.contains(TRUE_PETREL)); 147 MOZ_RELEASE_ASSERT(seen.contains(DIVING_PETREL)); 148 MOZ_RELEASE_ASSERT(seen.contains(STORM_PETREL)); 149 MOZ_RELEASE_ASSERT(seen.contains(CORMORANT)); 150 } 151 152 void testAdd() { 153 EnumSetSeaBird seen = mPetrels + CORMORANT + STORM_PETREL; 154 MOZ_RELEASE_ASSERT(mPetrels.size() == 4); 155 MOZ_RELEASE_ASSERT(!mPetrels.contains(CORMORANT)); 156 MOZ_RELEASE_ASSERT(seen.size() == 5); 157 MOZ_RELEASE_ASSERT(seen.contains(GADFLY_PETREL)); 158 MOZ_RELEASE_ASSERT(seen.contains(TRUE_PETREL)); 159 MOZ_RELEASE_ASSERT(seen.contains(DIVING_PETREL)); 160 MOZ_RELEASE_ASSERT(seen.contains(STORM_PETREL)); 161 MOZ_RELEASE_ASSERT(seen.contains(CORMORANT)); 162 } 163 164 void testAddAll() { 165 EnumSetSeaBird procellariidae; 166 procellariidae += mPetrelProcellariidae; 167 procellariidae += mNonPetrelProcellariidae; 168 MOZ_RELEASE_ASSERT(procellariidae.size() == 5); 169 170 // Both procellariidae and mPetrels include GADFLY_PERTEL and TRUE_PETREL 171 EnumSetSeaBird procellariiformes; 172 procellariiformes += mDiomedeidae; 173 procellariiformes += procellariidae; 174 procellariiformes += mPetrels; 175 MOZ_RELEASE_ASSERT(procellariiformes.size() == 8); 176 } 177 178 void testUnion() { 179 EnumSetSeaBird procellariidae = 180 mPetrelProcellariidae + mNonPetrelProcellariidae; 181 MOZ_RELEASE_ASSERT(procellariidae.size() == 5); 182 183 // Both procellariidae and mPetrels include GADFLY_PETREL and TRUE_PETREL 184 EnumSetSeaBird procellariiformes = mDiomedeidae + procellariidae + mPetrels; 185 MOZ_RELEASE_ASSERT(procellariiformes.size() == 8); 186 } 187 188 void testRemoveFrom() { 189 EnumSetSeaBird likes = mPetrels; 190 likes -= TRUE_PETREL; 191 likes -= DIVING_PETREL; 192 MOZ_RELEASE_ASSERT(likes.size() == 2); 193 MOZ_RELEASE_ASSERT(likes.contains(GADFLY_PETREL)); 194 MOZ_RELEASE_ASSERT(likes.contains(STORM_PETREL)); 195 } 196 197 void testRemove() { 198 EnumSetSeaBird likes = mPetrels - TRUE_PETREL - DIVING_PETREL; 199 MOZ_RELEASE_ASSERT(likes.size() == 2); 200 MOZ_RELEASE_ASSERT(likes.contains(GADFLY_PETREL)); 201 MOZ_RELEASE_ASSERT(likes.contains(STORM_PETREL)); 202 } 203 204 void testRemoveAllFrom() { 205 EnumSetSeaBird likes = mPetrels; 206 likes -= mPetrelProcellariidae; 207 MOZ_RELEASE_ASSERT(likes.size() == 2); 208 MOZ_RELEASE_ASSERT(likes.contains(DIVING_PETREL)); 209 MOZ_RELEASE_ASSERT(likes.contains(STORM_PETREL)); 210 } 211 212 void testRemoveAll() { 213 EnumSetSeaBird likes = mPetrels - mPetrelProcellariidae; 214 MOZ_RELEASE_ASSERT(likes.size() == 2); 215 MOZ_RELEASE_ASSERT(likes.contains(DIVING_PETREL)); 216 MOZ_RELEASE_ASSERT(likes.contains(STORM_PETREL)); 217 } 218 219 void testIntersect() { 220 EnumSetSeaBird likes = mPetrels; 221 likes &= mPetrelProcellariidae; 222 MOZ_RELEASE_ASSERT(likes.size() == 2); 223 MOZ_RELEASE_ASSERT(likes.contains(GADFLY_PETREL)); 224 MOZ_RELEASE_ASSERT(likes.contains(TRUE_PETREL)); 225 } 226 227 void testInsersection() { 228 EnumSetSeaBird likes = mPetrels & mPetrelProcellariidae; 229 MOZ_RELEASE_ASSERT(likes.size() == 2); 230 MOZ_RELEASE_ASSERT(likes.contains(GADFLY_PETREL)); 231 MOZ_RELEASE_ASSERT(likes.contains(TRUE_PETREL)); 232 } 233 234 void testEquality() { 235 EnumSetSeaBird likes = mPetrels & mPetrelProcellariidae; 236 MOZ_RELEASE_ASSERT(likes == EnumSetSeaBird(GADFLY_PETREL, TRUE_PETREL)); 237 } 238 239 void testDuplicates() { 240 EnumSetSeaBird likes = mPetrels; 241 likes += GADFLY_PETREL; 242 likes += TRUE_PETREL; 243 likes += DIVING_PETREL; 244 likes += STORM_PETREL; 245 MOZ_RELEASE_ASSERT(likes.size() == 4); 246 MOZ_RELEASE_ASSERT(likes == mPetrels); 247 } 248 249 void testIteration() { 250 EnumSetSeaBird birds; 251 Vector<SeaBird> vec; 252 253 for (auto bird : birds) { 254 MOZ_RELEASE_ASSERT(vec.append(bird)); 255 } 256 MOZ_RELEASE_ASSERT(vec.length() == 0); 257 258 birds += DIVING_PETREL; 259 birds += GADFLY_PETREL; 260 birds += STORM_PETREL; 261 birds += TRUE_PETREL; 262 for (auto bird : birds) { 263 MOZ_RELEASE_ASSERT(vec.append(bird)); 264 } 265 266 MOZ_RELEASE_ASSERT(vec.length() == 4); 267 MOZ_RELEASE_ASSERT(vec[0] == GADFLY_PETREL); 268 MOZ_RELEASE_ASSERT(vec[1] == TRUE_PETREL); 269 MOZ_RELEASE_ASSERT(vec[2] == DIVING_PETREL); 270 MOZ_RELEASE_ASSERT(vec[3] == STORM_PETREL); 271 } 272 273 void testInitializerListConstuctor() { 274 EnumSetSeaBird empty{}; 275 MOZ_RELEASE_ASSERT(empty.size() == 0); 276 MOZ_RELEASE_ASSERT(empty.isEmpty()); 277 278 EnumSetSeaBird someBirds{SKIMMER, GULL, BOOBY}; 279 MOZ_RELEASE_ASSERT(someBirds.size() == 3); 280 MOZ_RELEASE_ASSERT(someBirds.contains(SKIMMER)); 281 MOZ_RELEASE_ASSERT(someBirds.contains(GULL)); 282 MOZ_RELEASE_ASSERT(someBirds.contains(BOOBY)); 283 } 284 285 void testBigEnum() { 286 EnumSet<BigEnum> set; 287 set += BigEnum::Bar; 288 MOZ_RELEASE_ASSERT(set.serialize() == 289 (uint64_t(1) << uint64_t(BigEnum::Bar))); 290 } 291 292 EnumSetSeaBird mAlcidae; 293 EnumSetSeaBird mDiomedeidae; 294 EnumSetSeaBird mPetrelProcellariidae; 295 EnumSetSeaBird mNonPetrelProcellariidae; 296 EnumSetSeaBird mPetrels; 297 }; 298 299 int main() { 300 EnumSetSuite<uint32_t> suite1; 301 suite1.runTests(); 302 303 EnumSetSuite<BitSet<SEA_BIRD_COUNT>> suite2; 304 suite2.runTests(); 305 return 0; 306 }