1 // Copyright (c) 2016 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "source/enum_set.h"
16
17 #include <algorithm>
18 #include <array>
19 #include <random>
20 #include <utility>
21 #include <vector>
22
23 #include "gmock/gmock.h"
24 #include "test/unit_spirv.h"
25
26 namespace spvtools {
27 namespace {
28
29 using spvtest::ElementsIn;
30 using ::testing::Eq;
31 using ::testing::Values;
32 using ::testing::ValuesIn;
33
34 enum class TestEnum : uint32_t {
35 ZERO = 0,
36 ONE = 1,
37 TWO = 2,
38 THREE = 3,
39 FOUR = 4,
40 FIVE = 5,
41 EIGHT = 8,
42 TWENTY = 20,
43 TWENTY_FOUR = 24,
44 THIRTY = 30,
45 ONE_HUNDRED = 100,
46 ONE_HUNDRED_FIFTY = 150,
47 TWO_HUNDRED = 200,
48 THREE_HUNDRED = 300,
49 FOUR_HUNDRED = 400,
50 FIVE_HUNDRED = 500,
51 SIX_HUNDRED = 600,
52 };
53
54 constexpr std::array kCapabilities{
55 spv::Capability::Matrix,
56 spv::Capability::Shader,
57 spv::Capability::Geometry,
58 spv::Capability::Tessellation,
59 spv::Capability::Addresses,
60 spv::Capability::Linkage,
61 spv::Capability::Kernel,
62 spv::Capability::Vector16,
63 spv::Capability::Float16Buffer,
64 spv::Capability::Float16,
65 spv::Capability::Float64,
66 spv::Capability::Int64,
67 spv::Capability::Int64Atomics,
68 spv::Capability::ImageBasic,
69 spv::Capability::ImageReadWrite,
70 spv::Capability::ImageMipmap,
71 spv::Capability::Pipes,
72 spv::Capability::Groups,
73 spv::Capability::DeviceEnqueue,
74 spv::Capability::LiteralSampler,
75 spv::Capability::AtomicStorage,
76 spv::Capability::Int16,
77 spv::Capability::TessellationPointSize,
78 spv::Capability::GeometryPointSize,
79 spv::Capability::ImageGatherExtended,
80 spv::Capability::StorageImageMultisample,
81 spv::Capability::UniformBufferArrayDynamicIndexing,
82 spv::Capability::SampledImageArrayDynamicIndexing,
83 spv::Capability::StorageBufferArrayDynamicIndexing,
84 spv::Capability::StorageImageArrayDynamicIndexing,
85 spv::Capability::ClipDistance,
86 spv::Capability::CullDistance,
87 spv::Capability::ImageCubeArray,
88 spv::Capability::SampleRateShading,
89 spv::Capability::ImageRect,
90 spv::Capability::SampledRect,
91 spv::Capability::GenericPointer,
92 spv::Capability::Int8,
93 spv::Capability::InputAttachment,
94 spv::Capability::SparseResidency,
95 spv::Capability::MinLod,
96 spv::Capability::Sampled1D,
97 spv::Capability::Image1D,
98 spv::Capability::SampledCubeArray,
99 spv::Capability::SampledBuffer,
100 spv::Capability::ImageBuffer,
101 spv::Capability::ImageMSArray,
102 spv::Capability::StorageImageExtendedFormats,
103 spv::Capability::ImageQuery,
104 spv::Capability::DerivativeControl,
105 spv::Capability::InterpolationFunction,
106 spv::Capability::TransformFeedback,
107 spv::Capability::GeometryStreams,
108 spv::Capability::StorageImageReadWithoutFormat,
109 spv::Capability::StorageImageWriteWithoutFormat,
110 spv::Capability::MultiViewport,
111 spv::Capability::SubgroupDispatch,
112 spv::Capability::NamedBarrier,
113 spv::Capability::PipeStorage,
114 spv::Capability::GroupNonUniform,
115 spv::Capability::GroupNonUniformVote,
116 spv::Capability::GroupNonUniformArithmetic,
117 spv::Capability::GroupNonUniformBallot,
118 spv::Capability::GroupNonUniformShuffle,
119 spv::Capability::GroupNonUniformShuffleRelative,
120 spv::Capability::GroupNonUniformClustered,
121 spv::Capability::GroupNonUniformQuad,
122 spv::Capability::ShaderLayer,
123 spv::Capability::ShaderViewportIndex,
124 spv::Capability::UniformDecoration,
125 spv::Capability::CoreBuiltinsARM,
126 spv::Capability::FragmentShadingRateKHR,
127 spv::Capability::SubgroupBallotKHR,
128 spv::Capability::DrawParameters,
129 spv::Capability::WorkgroupMemoryExplicitLayoutKHR,
130 spv::Capability::WorkgroupMemoryExplicitLayout8BitAccessKHR,
131 spv::Capability::WorkgroupMemoryExplicitLayout16BitAccessKHR,
132 spv::Capability::SubgroupVoteKHR,
133 spv::Capability::StorageBuffer16BitAccess,
134 spv::Capability::StorageUniformBufferBlock16,
135 spv::Capability::StorageUniform16,
136 spv::Capability::UniformAndStorageBuffer16BitAccess,
137 spv::Capability::StoragePushConstant16,
138 spv::Capability::StorageInputOutput16,
139 spv::Capability::DeviceGroup,
140 spv::Capability::MultiView,
141 spv::Capability::VariablePointersStorageBuffer,
142 spv::Capability::VariablePointers,
143 spv::Capability::AtomicStorageOps,
144 spv::Capability::SampleMaskPostDepthCoverage,
145 spv::Capability::StorageBuffer8BitAccess,
146 spv::Capability::UniformAndStorageBuffer8BitAccess,
147 spv::Capability::StoragePushConstant8,
148 spv::Capability::DenormPreserve,
149 spv::Capability::DenormFlushToZero,
150 spv::Capability::SignedZeroInfNanPreserve,
151 spv::Capability::RoundingModeRTE,
152 spv::Capability::RoundingModeRTZ,
153 spv::Capability::RayQueryProvisionalKHR,
154 spv::Capability::RayQueryKHR,
155 spv::Capability::RayTraversalPrimitiveCullingKHR,
156 spv::Capability::RayTracingKHR,
157 spv::Capability::Float16ImageAMD,
158 spv::Capability::ImageGatherBiasLodAMD,
159 spv::Capability::FragmentMaskAMD,
160 spv::Capability::StencilExportEXT,
161 spv::Capability::ImageReadWriteLodAMD,
162 spv::Capability::Int64ImageEXT,
163 spv::Capability::ShaderClockKHR,
164 spv::Capability::SampleMaskOverrideCoverageNV,
165 spv::Capability::GeometryShaderPassthroughNV,
166 spv::Capability::ShaderViewportIndexLayerEXT,
167 spv::Capability::ShaderViewportIndexLayerNV,
168 spv::Capability::ShaderViewportMaskNV,
169 spv::Capability::ShaderStereoViewNV,
170 spv::Capability::PerViewAttributesNV,
171 spv::Capability::FragmentFullyCoveredEXT,
172 spv::Capability::MeshShadingNV,
173 spv::Capability::ImageFootprintNV,
174 spv::Capability::MeshShadingEXT,
175 spv::Capability::FragmentBarycentricKHR,
176 spv::Capability::FragmentBarycentricNV,
177 spv::Capability::ComputeDerivativeGroupQuadsNV,
178 spv::Capability::FragmentDensityEXT,
179 spv::Capability::ShadingRateNV,
180 spv::Capability::GroupNonUniformPartitionedNV,
181 spv::Capability::ShaderNonUniform,
182 spv::Capability::ShaderNonUniformEXT,
183 spv::Capability::RuntimeDescriptorArray,
184 spv::Capability::RuntimeDescriptorArrayEXT,
185 spv::Capability::InputAttachmentArrayDynamicIndexing,
186 spv::Capability::InputAttachmentArrayDynamicIndexingEXT,
187 spv::Capability::UniformTexelBufferArrayDynamicIndexing,
188 spv::Capability::UniformTexelBufferArrayDynamicIndexingEXT,
189 spv::Capability::StorageTexelBufferArrayDynamicIndexing,
190 spv::Capability::StorageTexelBufferArrayDynamicIndexingEXT,
191 spv::Capability::UniformBufferArrayNonUniformIndexing,
192 spv::Capability::UniformBufferArrayNonUniformIndexingEXT,
193 spv::Capability::SampledImageArrayNonUniformIndexing,
194 spv::Capability::SampledImageArrayNonUniformIndexingEXT,
195 spv::Capability::StorageBufferArrayNonUniformIndexing,
196 spv::Capability::StorageBufferArrayNonUniformIndexingEXT,
197 spv::Capability::StorageImageArrayNonUniformIndexing,
198 spv::Capability::StorageImageArrayNonUniformIndexingEXT,
199 spv::Capability::InputAttachmentArrayNonUniformIndexing,
200 spv::Capability::InputAttachmentArrayNonUniformIndexingEXT,
201 spv::Capability::UniformTexelBufferArrayNonUniformIndexing,
202 spv::Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
203 spv::Capability::StorageTexelBufferArrayNonUniformIndexing,
204 spv::Capability::StorageTexelBufferArrayNonUniformIndexingEXT,
205 spv::Capability::RayTracingNV,
206 spv::Capability::RayTracingMotionBlurNV,
207 spv::Capability::VulkanMemoryModel,
208 spv::Capability::VulkanMemoryModelKHR,
209 spv::Capability::VulkanMemoryModelDeviceScope,
210 spv::Capability::VulkanMemoryModelDeviceScopeKHR,
211 spv::Capability::PhysicalStorageBufferAddresses,
212 spv::Capability::PhysicalStorageBufferAddressesEXT,
213 spv::Capability::ComputeDerivativeGroupLinearNV,
214 spv::Capability::RayTracingProvisionalKHR,
215 spv::Capability::CooperativeMatrixNV,
216 spv::Capability::FragmentShaderSampleInterlockEXT,
217 spv::Capability::FragmentShaderShadingRateInterlockEXT,
218 spv::Capability::ShaderSMBuiltinsNV,
219 spv::Capability::FragmentShaderPixelInterlockEXT,
220 spv::Capability::DemoteToHelperInvocation,
221 spv::Capability::DemoteToHelperInvocationEXT,
222 spv::Capability::RayTracingOpacityMicromapEXT,
223 spv::Capability::ShaderInvocationReorderNV,
224 spv::Capability::BindlessTextureNV,
225 spv::Capability::SubgroupShuffleINTEL,
226 spv::Capability::SubgroupBufferBlockIOINTEL,
227 spv::Capability::SubgroupImageBlockIOINTEL,
228 spv::Capability::SubgroupImageMediaBlockIOINTEL,
229 spv::Capability::RoundToInfinityINTEL,
230 spv::Capability::FloatingPointModeINTEL,
231 spv::Capability::IntegerFunctions2INTEL,
232 spv::Capability::FunctionPointersINTEL,
233 spv::Capability::IndirectReferencesINTEL,
234 spv::Capability::AsmINTEL,
235 spv::Capability::AtomicFloat32MinMaxEXT,
236 spv::Capability::AtomicFloat64MinMaxEXT,
237 spv::Capability::AtomicFloat16MinMaxEXT,
238 spv::Capability::VectorComputeINTEL,
239 spv::Capability::VectorAnyINTEL,
240 spv::Capability::ExpectAssumeKHR,
241 spv::Capability::SubgroupAvcMotionEstimationINTEL,
242 spv::Capability::SubgroupAvcMotionEstimationIntraINTEL,
243 spv::Capability::SubgroupAvcMotionEstimationChromaINTEL,
244 spv::Capability::VariableLengthArrayINTEL,
245 spv::Capability::FunctionFloatControlINTEL,
246 spv::Capability::FPGAMemoryAttributesINTEL,
247 spv::Capability::FPFastMathModeINTEL,
248 spv::Capability::ArbitraryPrecisionIntegersINTEL,
249 spv::Capability::ArbitraryPrecisionFloatingPointINTEL,
250 spv::Capability::UnstructuredLoopControlsINTEL,
251 spv::Capability::FPGALoopControlsINTEL,
252 spv::Capability::KernelAttributesINTEL,
253 spv::Capability::FPGAKernelAttributesINTEL,
254 spv::Capability::FPGAMemoryAccessesINTEL,
255 spv::Capability::FPGAClusterAttributesINTEL,
256 spv::Capability::LoopFuseINTEL,
257 spv::Capability::FPGADSPControlINTEL,
258 spv::Capability::MemoryAccessAliasingINTEL,
259 spv::Capability::FPGAInvocationPipeliningAttributesINTEL,
260 spv::Capability::FPGABufferLocationINTEL,
261 spv::Capability::ArbitraryPrecisionFixedPointINTEL,
262 spv::Capability::USMStorageClassesINTEL,
263 spv::Capability::RuntimeAlignedAttributeINTEL,
264 spv::Capability::IOPipesINTEL,
265 spv::Capability::BlockingPipesINTEL,
266 spv::Capability::FPGARegINTEL,
267 spv::Capability::DotProductInputAll,
268 spv::Capability::DotProductInputAllKHR,
269 spv::Capability::DotProductInput4x8Bit,
270 spv::Capability::DotProductInput4x8BitKHR,
271 spv::Capability::DotProductInput4x8BitPacked,
272 spv::Capability::DotProductInput4x8BitPackedKHR,
273 spv::Capability::DotProduct,
274 spv::Capability::DotProductKHR,
275 spv::Capability::RayCullMaskKHR,
276 spv::Capability::BitInstructions,
277 spv::Capability::GroupNonUniformRotateKHR,
278 spv::Capability::AtomicFloat32AddEXT,
279 spv::Capability::AtomicFloat64AddEXT,
280 spv::Capability::LongConstantCompositeINTEL,
281 spv::Capability::OptNoneINTEL,
282 spv::Capability::AtomicFloat16AddEXT,
283 spv::Capability::DebugInfoModuleINTEL,
284 spv::Capability::SplitBarrierINTEL,
285 spv::Capability::GroupUniformArithmeticKHR,
286 spv::Capability::Max,
287 };
288
289 namespace {
enumerateValuesFromToWithStep(size_t start,size_t end,size_t step)290 std::vector<TestEnum> enumerateValuesFromToWithStep(size_t start, size_t end,
291 size_t step) {
292 assert(end > start && "end > start");
293 std::vector<TestEnum> orderedValues;
294 for (size_t i = start; i < end; i += step) {
295 orderedValues.push_back(static_cast<TestEnum>(i));
296 }
297 return orderedValues;
298 }
299
createSetUnorderedInsertion(const std::vector<TestEnum> & values)300 EnumSet<TestEnum> createSetUnorderedInsertion(
301 const std::vector<TestEnum>& values) {
302 std::vector shuffledValues(values.cbegin(), values.cend());
303 std::mt19937 rng(0);
304 std::shuffle(shuffledValues.begin(), shuffledValues.end(), rng);
305 EnumSet<TestEnum> set;
306 for (auto value : shuffledValues) {
307 set.insert(value);
308 }
309 return set;
310 }
311 } // namespace
312
TEST(EnumSet,IsEmpty1)313 TEST(EnumSet, IsEmpty1) {
314 EnumSet<TestEnum> set;
315 EXPECT_TRUE(set.empty());
316 set.insert(TestEnum::ZERO);
317 EXPECT_FALSE(set.empty());
318 }
319
TEST(EnumSet,IsEmpty2)320 TEST(EnumSet, IsEmpty2) {
321 EnumSet<TestEnum> set;
322 EXPECT_TRUE(set.empty());
323 set.insert(TestEnum::ONE_HUNDRED_FIFTY);
324 EXPECT_FALSE(set.empty());
325 }
326
TEST(EnumSet,IsEmpty3)327 TEST(EnumSet, IsEmpty3) {
328 EnumSet<TestEnum> set(TestEnum::FOUR);
329 EXPECT_FALSE(set.empty());
330 }
331
TEST(EnumSet,IsEmpty4)332 TEST(EnumSet, IsEmpty4) {
333 EnumSet<TestEnum> set(TestEnum::THREE_HUNDRED);
334 EXPECT_FALSE(set.empty());
335 }
336
TEST(EnumSetHasAnyOf,EmptySetEmptyQuery)337 TEST(EnumSetHasAnyOf, EmptySetEmptyQuery) {
338 const EnumSet<TestEnum> set;
339 const EnumSet<TestEnum> empty;
340 EXPECT_TRUE(set.HasAnyOf(empty));
341 EXPECT_TRUE(EnumSet<TestEnum>().HasAnyOf(EnumSet<TestEnum>()));
342 }
343
TEST(EnumSetHasAnyOf,MaskSetEmptyQuery)344 TEST(EnumSetHasAnyOf, MaskSetEmptyQuery) {
345 EnumSet<TestEnum> set;
346 const EnumSet<TestEnum> empty;
347 set.insert(TestEnum::FIVE);
348 set.insert(TestEnum::EIGHT);
349 EXPECT_TRUE(set.HasAnyOf(empty));
350 }
351
TEST(EnumSetHasAnyOf,OverflowSetEmptyQuery)352 TEST(EnumSetHasAnyOf, OverflowSetEmptyQuery) {
353 EnumSet<TestEnum> set;
354 const EnumSet<TestEnum> empty;
355 set.insert(TestEnum::TWO_HUNDRED);
356 set.insert(TestEnum::THREE_HUNDRED);
357 EXPECT_TRUE(set.HasAnyOf(empty));
358 }
359
TEST(EnumSetHasAnyOf,EmptyQuery)360 TEST(EnumSetHasAnyOf, EmptyQuery) {
361 EnumSet<TestEnum> set;
362 const EnumSet<TestEnum> empty;
363 set.insert(TestEnum::FIVE);
364 set.insert(TestEnum::EIGHT);
365 set.insert(TestEnum::TWO_HUNDRED);
366 set.insert(TestEnum::THREE_HUNDRED);
367 EXPECT_TRUE(set.HasAnyOf(empty));
368 }
369
TEST(EnumSetHasAnyOf,EmptyQueryAlwaysTrue)370 TEST(EnumSetHasAnyOf, EmptyQueryAlwaysTrue) {
371 EnumSet<TestEnum> set;
372 const EnumSet<TestEnum> empty;
373 EXPECT_TRUE(set.HasAnyOf(empty));
374 set.insert(TestEnum::FIVE);
375 EXPECT_TRUE(set.HasAnyOf(empty));
376
377 EXPECT_TRUE(
378 EnumSet<TestEnum>(TestEnum::ONE_HUNDRED).HasAnyOf(EnumSet<TestEnum>()));
379 }
380
TEST(EnumSetHasAnyOf,ReflexiveMask)381 TEST(EnumSetHasAnyOf, ReflexiveMask) {
382 EnumSet<TestEnum> set(TestEnum::THREE);
383 set.insert(TestEnum::TWENTY_FOUR);
384 set.insert(TestEnum::THIRTY);
385 EXPECT_TRUE(set.HasAnyOf(set));
386 }
387
TEST(EnumSetHasAnyOf,ReflexiveOverflow)388 TEST(EnumSetHasAnyOf, ReflexiveOverflow) {
389 EnumSet<TestEnum> set(TestEnum::TWO_HUNDRED);
390 set.insert(TestEnum::TWO_HUNDRED);
391 set.insert(TestEnum::FOUR_HUNDRED);
392 EXPECT_TRUE(set.HasAnyOf(set));
393 }
394
TEST(EnumSetHasAnyOf,Reflexive)395 TEST(EnumSetHasAnyOf, Reflexive) {
396 EnumSet<TestEnum> set(TestEnum::THREE);
397 set.insert(TestEnum::TWENTY_FOUR);
398 set.insert(TestEnum::THREE_HUNDRED);
399 set.insert(TestEnum::FOUR_HUNDRED);
400 EXPECT_TRUE(set.HasAnyOf(set));
401 }
402
TEST(EnumSetHasAnyOf,EmptySetHasNone)403 TEST(EnumSetHasAnyOf, EmptySetHasNone) {
404 EnumSet<TestEnum> set;
405 EnumSet<TestEnum> items;
406 for (uint32_t i = 0; i < 200; ++i) {
407 TestEnum enumValue = static_cast<TestEnum>(i);
408 items.insert(enumValue);
409 EXPECT_FALSE(set.HasAnyOf(items));
410 EXPECT_FALSE(set.HasAnyOf(EnumSet<TestEnum>(enumValue)));
411 }
412 }
413
TEST(EnumSetHasAnyOf,MaskSetMaskQuery)414 TEST(EnumSetHasAnyOf, MaskSetMaskQuery) {
415 EnumSet<TestEnum> set(TestEnum::ZERO);
416 EnumSet<TestEnum> items(TestEnum::ONE);
417 EXPECT_FALSE(set.HasAnyOf(items));
418 set.insert(TestEnum::TWO);
419 items.insert(TestEnum::THREE);
420 EXPECT_FALSE(set.HasAnyOf(items));
421 set.insert(TestEnum::THREE);
422 EXPECT_TRUE(set.HasAnyOf(items));
423 set.insert(TestEnum::FOUR);
424 EXPECT_TRUE(set.HasAnyOf(items));
425 }
426
TEST(EnumSetHasAnyOf,OverflowSetOverflowQuery)427 TEST(EnumSetHasAnyOf, OverflowSetOverflowQuery) {
428 EnumSet<TestEnum> set(TestEnum::ONE_HUNDRED);
429 EnumSet<TestEnum> items(TestEnum::TWO_HUNDRED);
430 EXPECT_FALSE(set.HasAnyOf(items));
431 set.insert(TestEnum::THREE_HUNDRED);
432 items.insert(TestEnum::FOUR_HUNDRED);
433 EXPECT_FALSE(set.HasAnyOf(items));
434 set.insert(TestEnum::TWO_HUNDRED);
435 EXPECT_TRUE(set.HasAnyOf(items));
436 set.insert(TestEnum::FIVE_HUNDRED);
437 EXPECT_TRUE(set.HasAnyOf(items));
438 }
439
TEST(EnumSetHasAnyOf,GeneralCase)440 TEST(EnumSetHasAnyOf, GeneralCase) {
441 EnumSet<TestEnum> set(TestEnum::ZERO);
442 EnumSet<TestEnum> items(TestEnum::ONE_HUNDRED);
443 EXPECT_FALSE(set.HasAnyOf(items));
444 set.insert(TestEnum::THREE_HUNDRED);
445 items.insert(TestEnum::FOUR);
446 EXPECT_FALSE(set.HasAnyOf(items));
447 set.insert(TestEnum::FIVE);
448 items.insert(TestEnum::FIVE_HUNDRED);
449 EXPECT_FALSE(set.HasAnyOf(items));
450 set.insert(TestEnum::FIVE_HUNDRED);
451 EXPECT_TRUE(set.HasAnyOf(items));
452 EXPECT_FALSE(set.HasAnyOf(EnumSet<TestEnum>(TestEnum::TWENTY)));
453 EXPECT_FALSE(set.HasAnyOf(EnumSet<TestEnum>(TestEnum::SIX_HUNDRED)));
454 EXPECT_TRUE(set.HasAnyOf(EnumSet<TestEnum>(TestEnum::FIVE)));
455 EXPECT_TRUE(set.HasAnyOf(EnumSet<TestEnum>(TestEnum::THREE_HUNDRED)));
456 EXPECT_TRUE(set.HasAnyOf(EnumSet<TestEnum>(TestEnum::ZERO)));
457 }
458
TEST(EnumSet,DefaultIsEmpty)459 TEST(EnumSet, DefaultIsEmpty) {
460 EnumSet<TestEnum> set;
461 for (uint32_t i = 0; i < 1000; ++i) {
462 EXPECT_FALSE(set.contains(static_cast<TestEnum>(i)));
463 }
464 }
465
TEST(EnumSet,EqualityCompareEmpty)466 TEST(EnumSet, EqualityCompareEmpty) {
467 EnumSet<TestEnum> set1;
468 EnumSet<TestEnum> set2;
469
470 EXPECT_TRUE(set1 == set2);
471 EXPECT_FALSE(set1 != set2);
472 }
473
TEST(EnumSet,EqualityCompareSame)474 TEST(EnumSet, EqualityCompareSame) {
475 EnumSet<TestEnum> set1;
476 EnumSet<TestEnum> set2;
477
478 set1.insert(TestEnum::ONE);
479 set1.insert(TestEnum::TWENTY);
480 set2.insert(TestEnum::TWENTY);
481 set2.insert(TestEnum::ONE);
482
483 EXPECT_TRUE(set1 == set2);
484 EXPECT_FALSE(set1 != set2);
485 }
486
TEST(EnumSet,EqualityCompareDifferent)487 TEST(EnumSet, EqualityCompareDifferent) {
488 EnumSet<TestEnum> set1;
489 EnumSet<TestEnum> set2;
490
491 set1.insert(TestEnum::ONE);
492 set1.insert(TestEnum::TWENTY);
493 set2.insert(TestEnum::FIVE);
494 set2.insert(TestEnum::ONE);
495
496 EXPECT_FALSE(set1 == set2);
497 EXPECT_TRUE(set1 != set2);
498 }
499
TEST(EnumSet,ConstructFromIterators)500 TEST(EnumSet, ConstructFromIterators) {
501 auto orderedValues = enumerateValuesFromToWithStep(0, 2, /* step= */ 1);
502 EnumSet<TestEnum> set1 = createSetUnorderedInsertion(orderedValues);
503
504 EnumSet<TestEnum> set2(orderedValues.cbegin(), orderedValues.cend());
505
506 EXPECT_EQ(set1, set2);
507 }
508
TEST(EnumSet,InsertUsingIteratorRange)509 TEST(EnumSet, InsertUsingIteratorRange) {
510 auto orderedValues = enumerateValuesFromToWithStep(0, 2, /* step= */ 1);
511 EnumSet<TestEnum> set1 = createSetUnorderedInsertion(orderedValues);
512
513 EnumSet<TestEnum> set2;
514 set2.insert(orderedValues.cbegin(), orderedValues.cend());
515
516 EXPECT_EQ(set1, set2);
517 }
518
TEST(CapabilitySet,RangeBasedLoopOrderIsEnumOrder)519 TEST(CapabilitySet, RangeBasedLoopOrderIsEnumOrder) {
520 auto orderedValues = enumerateValuesFromToWithStep(0, 2, /* step= */ 1);
521 auto set = createSetUnorderedInsertion(orderedValues);
522
523 size_t index = 0;
524 for (auto value : set) {
525 ASSERT_THAT(value, Eq(orderedValues[index]));
526 index++;
527 }
528 }
529
TEST(CapabilitySet,ConstructSingleMemberMatrix)530 TEST(CapabilitySet, ConstructSingleMemberMatrix) {
531 CapabilitySet s(spv::Capability::Matrix);
532 EXPECT_TRUE(s.contains(spv::Capability::Matrix));
533 EXPECT_FALSE(s.contains(spv::Capability::Shader));
534 EXPECT_FALSE(s.contains(static_cast<spv::Capability>(1000)));
535 }
536
TEST(CapabilitySet,ConstructSingleMemberMaxInMask)537 TEST(CapabilitySet, ConstructSingleMemberMaxInMask) {
538 CapabilitySet s(static_cast<spv::Capability>(63));
539 EXPECT_FALSE(s.contains(spv::Capability::Matrix));
540 EXPECT_FALSE(s.contains(spv::Capability::Shader));
541 EXPECT_TRUE(s.contains(static_cast<spv::Capability>(63)));
542 EXPECT_FALSE(s.contains(static_cast<spv::Capability>(64)));
543 EXPECT_FALSE(s.contains(static_cast<spv::Capability>(1000)));
544 }
545
TEST(CapabilitySet,ConstructSingleMemberMinOverflow)546 TEST(CapabilitySet, ConstructSingleMemberMinOverflow) {
547 // Check the first one that forces overflow beyond the mask.
548 CapabilitySet s(static_cast<spv::Capability>(64));
549 EXPECT_FALSE(s.contains(spv::Capability::Matrix));
550 EXPECT_FALSE(s.contains(spv::Capability::Shader));
551 EXPECT_FALSE(s.contains(static_cast<spv::Capability>(63)));
552 EXPECT_TRUE(s.contains(static_cast<spv::Capability>(64)));
553 EXPECT_FALSE(s.contains(static_cast<spv::Capability>(1000)));
554 }
555
TEST(CapabilitySet,ConstructSingleMemberMaxOverflow)556 TEST(CapabilitySet, ConstructSingleMemberMaxOverflow) {
557 // Check the max 32-bit signed int.
558 CapabilitySet s(static_cast<spv::Capability>(0x7fffffffu));
559 EXPECT_FALSE(s.contains(spv::Capability::Matrix));
560 EXPECT_FALSE(s.contains(spv::Capability::Shader));
561 EXPECT_FALSE(s.contains(static_cast<spv::Capability>(1000)));
562 EXPECT_TRUE(s.contains(static_cast<spv::Capability>(0x7fffffffu)));
563 }
564
TEST(CapabilitySet,AddEnum)565 TEST(CapabilitySet, AddEnum) {
566 CapabilitySet s(spv::Capability::Shader);
567 s.insert(spv::Capability::Kernel);
568 s.insert(static_cast<spv::Capability>(42));
569 EXPECT_FALSE(s.contains(spv::Capability::Matrix));
570 EXPECT_TRUE(s.contains(spv::Capability::Shader));
571 EXPECT_TRUE(s.contains(spv::Capability::Kernel));
572 EXPECT_TRUE(s.contains(static_cast<spv::Capability>(42)));
573 }
574
TEST(CapabilitySet,InsertReturnsIteratorToInserted)575 TEST(CapabilitySet, InsertReturnsIteratorToInserted) {
576 CapabilitySet set;
577
578 auto[it, inserted] = set.insert(spv::Capability::Kernel);
579
580 EXPECT_TRUE(inserted);
581 EXPECT_EQ(*it, spv::Capability::Kernel);
582 }
583
TEST(CapabilitySet,InsertReturnsIteratorToElementOnDoubleInsertion)584 TEST(CapabilitySet, InsertReturnsIteratorToElementOnDoubleInsertion) {
585 CapabilitySet set;
586 EXPECT_FALSE(set.contains(spv::Capability::Shader));
587 {
588 auto[it, inserted] = set.insert(spv::Capability::Shader);
589 EXPECT_TRUE(inserted);
590 EXPECT_EQ(*it, spv::Capability::Shader);
591 }
592 EXPECT_TRUE(set.contains(spv::Capability::Shader));
593
594 auto[it, inserted] = set.insert(spv::Capability::Shader);
595
596 EXPECT_FALSE(inserted);
597 EXPECT_EQ(*it, spv::Capability::Shader);
598 EXPECT_TRUE(set.contains(spv::Capability::Shader));
599 }
600
TEST(CapabilitySet,InsertWithHintWorks)601 TEST(CapabilitySet, InsertWithHintWorks) {
602 CapabilitySet set;
603 EXPECT_FALSE(set.contains(spv::Capability::Shader));
604
605 auto it = set.insert(set.begin(), spv::Capability::Shader);
606
607 EXPECT_EQ(*it, spv::Capability::Shader);
608 EXPECT_TRUE(set.contains(spv::Capability::Shader));
609 }
610
TEST(CapabilitySet,InsertWithEndHintWorks)611 TEST(CapabilitySet, InsertWithEndHintWorks) {
612 CapabilitySet set;
613 EXPECT_FALSE(set.contains(spv::Capability::Shader));
614
615 auto it = set.insert(set.end(), spv::Capability::Shader);
616
617 EXPECT_EQ(*it, spv::Capability::Shader);
618 EXPECT_TRUE(set.contains(spv::Capability::Shader));
619 }
620
TEST(CapabilitySet,IteratorCanBeCopied)621 TEST(CapabilitySet, IteratorCanBeCopied) {
622 CapabilitySet set;
623 set.insert(spv::Capability::Matrix);
624 set.insert(spv::Capability::Shader);
625 set.insert(spv::Capability::Geometry);
626 set.insert(spv::Capability::Float64);
627 set.insert(spv::Capability::Float16);
628
629 auto a = set.begin();
630 ++a;
631 auto b = a;
632
633 EXPECT_EQ(*b, *a);
634 ++b;
635 EXPECT_NE(*b, *a);
636
637 ++a;
638 EXPECT_EQ(*b, *a);
639
640 ++a;
641 EXPECT_NE(*b, *a);
642 }
643
TEST(CapabilitySet,IteratorBeginToEndPostfix)644 TEST(CapabilitySet, IteratorBeginToEndPostfix) {
645 auto orderedValues = enumerateValuesFromToWithStep(0, 100, /* step= */ 1);
646 auto set = createSetUnorderedInsertion(orderedValues);
647
648 size_t index = 0;
649 for (auto it = set.cbegin(); it != set.cend(); it++, index++) {
650 EXPECT_EQ(*it, orderedValues[index]);
651 }
652 }
653
TEST(CapabilitySet,IteratorBeginToEndPrefix)654 TEST(CapabilitySet, IteratorBeginToEndPrefix) {
655 auto orderedValues = enumerateValuesFromToWithStep(0, 100, /* step= */ 1);
656 auto set = createSetUnorderedInsertion(orderedValues);
657
658 size_t index = 0;
659 for (auto it = set.cbegin(); it != set.cend(); ++it, index++) {
660 EXPECT_EQ(*it, orderedValues[index]);
661 }
662 }
663
TEST(CapabilitySet,IteratorBeginToEndPrefixStep)664 TEST(CapabilitySet, IteratorBeginToEndPrefixStep) {
665 auto orderedValues = enumerateValuesFromToWithStep(0, 100, /* step= */ 8);
666 auto set = createSetUnorderedInsertion(orderedValues);
667
668 size_t index = 0;
669 for (auto it = set.cbegin(); it != set.cend(); ++it, index++) {
670 ASSERT_EQ(*it, orderedValues[index]);
671 }
672 }
673
TEST(CapabilitySet,IteratorBeginOnEmpty)674 TEST(CapabilitySet, IteratorBeginOnEmpty) {
675 CapabilitySet set;
676
677 auto begin = set.begin();
678 auto end = set.end();
679 ASSERT_EQ(begin, end);
680 }
681
TEST(CapabilitySet,IteratorBeginOnSingleNonZeroValue)682 TEST(CapabilitySet, IteratorBeginOnSingleNonZeroValue) {
683 CapabilitySet set;
684 set.insert(spv::Capability::Shader);
685
686 auto begin = set.begin();
687 auto end = set.end();
688
689 ASSERT_NE(begin, end);
690 ASSERT_EQ(*begin, spv::Capability::Shader);
691 }
692
TEST(CapabilitySet,IteratorForLoopNonZeroValue)693 TEST(CapabilitySet, IteratorForLoopNonZeroValue) {
694 CapabilitySet set;
695 set.insert(spv::Capability::Shader);
696 set.insert(spv::Capability::Tessellation);
697
698 auto begin = set.begin();
699 auto end = set.end();
700
701 ASSERT_NE(begin, end);
702 ASSERT_EQ(*begin, spv::Capability::Shader);
703
704 begin++;
705 ASSERT_NE(begin, end);
706 ASSERT_EQ(*begin, spv::Capability::Tessellation);
707
708 begin++;
709 ASSERT_EQ(begin, end);
710 }
711
TEST(CapabilitySet,IteratorPastEnd)712 TEST(CapabilitySet, IteratorPastEnd) {
713 CapabilitySet set;
714 set.insert(spv::Capability::Shader);
715
716 auto begin = set.begin();
717 auto end = set.end();
718
719 ASSERT_NE(begin, end);
720 ASSERT_EQ(*begin, spv::Capability::Shader);
721
722 begin++;
723 ASSERT_EQ(begin, end);
724
725 begin++;
726 ASSERT_EQ(begin, end);
727 }
728
TEST(CapabilitySet,CompatibleWithSTLFind)729 TEST(CapabilitySet, CompatibleWithSTLFind) {
730 CapabilitySet set;
731 set.insert(spv::Capability::Matrix);
732 set.insert(spv::Capability::Shader);
733 set.insert(spv::Capability::Geometry);
734 set.insert(spv::Capability::Tessellation);
735 set.insert(spv::Capability::Addresses);
736 set.insert(spv::Capability::Linkage);
737 set.insert(spv::Capability::Kernel);
738 set.insert(spv::Capability::Vector16);
739 set.insert(spv::Capability::Float16Buffer);
740 set.insert(spv::Capability::Float64);
741
742 {
743 auto it = std::find(set.cbegin(), set.cend(), spv::Capability::Vector16);
744 ASSERT_NE(it, set.end());
745 ASSERT_EQ(*it, spv::Capability::Vector16);
746 }
747
748 {
749 auto it = std::find(set.cbegin(), set.cend(), spv::Capability::Float16);
750 ASSERT_EQ(it, set.end());
751 }
752 }
753
TEST(CapabilitySet,CompatibleWithSTLForEach)754 TEST(CapabilitySet, CompatibleWithSTLForEach) {
755 auto orderedValues = enumerateValuesFromToWithStep(0, 100, /* step= */ 15);
756 auto set = createSetUnorderedInsertion(orderedValues);
757
758 size_t index = 0;
759 std::for_each(set.cbegin(), set.cend(), [&](auto item) {
760 ASSERT_EQ(item, orderedValues[index]);
761 index++;
762 });
763 }
764
TEST(CapabilitySet,InitializerListEmpty)765 TEST(CapabilitySet, InitializerListEmpty) {
766 CapabilitySet s{};
767 for (uint32_t i = 0; i < 1000; i++) {
768 EXPECT_FALSE(s.contains(static_cast<spv::Capability>(i)));
769 }
770 }
771
TEST(CapabilitySet,LargeSetHasInsertedElements)772 TEST(CapabilitySet, LargeSetHasInsertedElements) {
773 CapabilitySet set;
774 for (auto c : kCapabilities) {
775 EXPECT_FALSE(set.contains(c));
776 }
777
778 for (auto c : kCapabilities) {
779 set.insert(c);
780 EXPECT_TRUE(set.contains(c));
781 }
782
783 for (auto c : kCapabilities) {
784 EXPECT_TRUE(set.contains(c));
785 }
786 }
787
TEST(CapabilitySet,LargeSetHasUnsortedInsertedElements)788 TEST(CapabilitySet, LargeSetHasUnsortedInsertedElements) {
789 std::vector shuffledCapabilities(kCapabilities.cbegin(),
790 kCapabilities.cend());
791 std::mt19937 rng(0);
792 std::shuffle(shuffledCapabilities.begin(), shuffledCapabilities.end(), rng);
793 CapabilitySet set;
794 for (auto c : shuffledCapabilities) {
795 EXPECT_FALSE(set.contains(c));
796 }
797
798 for (auto c : shuffledCapabilities) {
799 set.insert(c);
800 EXPECT_TRUE(set.contains(c));
801 }
802
803 for (auto c : shuffledCapabilities) {
804 EXPECT_TRUE(set.contains(c));
805 }
806 }
807
TEST(CapabilitySet,LargeSetHasUnsortedRemovedElement)808 TEST(CapabilitySet, LargeSetHasUnsortedRemovedElement) {
809 std::vector shuffledCapabilities(kCapabilities.cbegin(),
810 kCapabilities.cend());
811 std::mt19937 rng(0);
812 std::shuffle(shuffledCapabilities.begin(), shuffledCapabilities.end(), rng);
813 CapabilitySet set;
814 for (auto c : shuffledCapabilities) {
815 set.insert(c);
816 EXPECT_TRUE(set.contains(c));
817 }
818
819 for (auto c : kCapabilities) {
820 set.erase(c);
821 }
822
823 for (auto c : shuffledCapabilities) {
824 EXPECT_FALSE(set.contains(c));
825 }
826 }
827
828 struct ForEachCase {
829 CapabilitySet capabilities;
830 std::vector<spv::Capability> expected;
831 };
832
833 using CapabilitySetForEachTest = ::testing::TestWithParam<ForEachCase>;
834
TEST_P(CapabilitySetForEachTest,CallsAsExpected)835 TEST_P(CapabilitySetForEachTest, CallsAsExpected) {
836 EXPECT_THAT(ElementsIn(GetParam().capabilities), Eq(GetParam().expected));
837 }
838
TEST_P(CapabilitySetForEachTest,CopyConstructor)839 TEST_P(CapabilitySetForEachTest, CopyConstructor) {
840 CapabilitySet copy(GetParam().capabilities);
841 EXPECT_THAT(ElementsIn(copy), Eq(GetParam().expected));
842 }
843
TEST_P(CapabilitySetForEachTest,MoveConstructor)844 TEST_P(CapabilitySetForEachTest, MoveConstructor) {
845 // We need a writable copy to move from.
846 CapabilitySet copy(GetParam().capabilities);
847 CapabilitySet moved(std::move(copy));
848 EXPECT_THAT(ElementsIn(moved), Eq(GetParam().expected));
849
850 // The moved-from set is empty.
851 EXPECT_THAT(ElementsIn(copy), Eq(std::vector<spv::Capability>{}));
852 }
853
TEST_P(CapabilitySetForEachTest,OperatorEquals)854 TEST_P(CapabilitySetForEachTest, OperatorEquals) {
855 CapabilitySet assigned = GetParam().capabilities;
856 EXPECT_THAT(ElementsIn(assigned), Eq(GetParam().expected));
857 }
858
TEST_P(CapabilitySetForEachTest,OperatorEqualsSelfAssign)859 TEST_P(CapabilitySetForEachTest, OperatorEqualsSelfAssign) {
860 CapabilitySet assigned{GetParam().capabilities};
861 assigned = assigned;
862 EXPECT_THAT(ElementsIn(assigned), Eq(GetParam().expected));
863 }
864
865 INSTANTIATE_TEST_SUITE_P(
866 Samples, CapabilitySetForEachTest,
867 ValuesIn(std::vector<ForEachCase>{
868 {{}, {}},
869 {{spv::Capability::Matrix}, {spv::Capability::Matrix}},
870 {{spv::Capability::Kernel, spv::Capability::Shader},
871 {spv::Capability::Shader, spv::Capability::Kernel}},
872 {{static_cast<spv::Capability>(999)},
873 {static_cast<spv::Capability>(999)}},
874 {{static_cast<spv::Capability>(0x7fffffff)},
875 {static_cast<spv::Capability>(0x7fffffff)}},
876 // Mixture and out of order
877 {{static_cast<spv::Capability>(0x7fffffff),
878 static_cast<spv::Capability>(100), spv::Capability::Shader,
879 spv::Capability::Matrix},
880 {spv::Capability::Matrix, spv::Capability::Shader,
881 static_cast<spv::Capability>(100),
882 static_cast<spv::Capability>(0x7fffffff)}},
883 }));
884
885 using BoundaryTestWithParam = ::testing::TestWithParam<spv::Capability>;
886
TEST_P(BoundaryTestWithParam,InsertedContains)887 TEST_P(BoundaryTestWithParam, InsertedContains) {
888 CapabilitySet set;
889 set.insert(GetParam());
890 EXPECT_TRUE(set.contains(GetParam()));
891 }
892
893 INSTANTIATE_TEST_SUITE_P(
894 Samples, BoundaryTestWithParam,
895 Values(static_cast<spv::Capability>(0), static_cast<spv::Capability>(63),
896 static_cast<spv::Capability>(64), static_cast<spv::Capability>(65),
897 static_cast<spv::Capability>(127), static_cast<spv::Capability>(128),
898 static_cast<spv::Capability>(129)));
899
900 } // namespace
901 } // namespace spvtools
902