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
26namespace spvtools {
27namespace {
28
29using spvtest::ElementsIn;
30using ::testing::Eq;
31using ::testing::Values;
32using ::testing::ValuesIn;
33
34enum 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
54constexpr 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::LongCompositesINTEL,
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
289namespace {
290std::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
300EnumSet<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
313TEST(EnumSet, IsEmpty1) {
314  EnumSet<TestEnum> set;
315  EXPECT_TRUE(set.empty());
316  set.insert(TestEnum::ZERO);
317  EXPECT_FALSE(set.empty());
318}
319
320TEST(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
327TEST(EnumSet, IsEmpty3) {
328  EnumSet<TestEnum> set(TestEnum::FOUR);
329  EXPECT_FALSE(set.empty());
330}
331
332TEST(EnumSet, IsEmpty4) {
333  EnumSet<TestEnum> set(TestEnum::THREE_HUNDRED);
334  EXPECT_FALSE(set.empty());
335}
336
337TEST(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
344TEST(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
352TEST(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
360TEST(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
370TEST(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
381TEST(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
388TEST(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
395TEST(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
403TEST(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
414TEST(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
427TEST(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
440TEST(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
459TEST(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
466TEST(EnumSet, EqualityCompareEmpty) {
467  EnumSet<TestEnum> set1;
468  EnumSet<TestEnum> set2;
469
470  EXPECT_TRUE(set1 == set2);
471  EXPECT_FALSE(set1 != set2);
472}
473
474TEST(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
487TEST(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
500TEST(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
509TEST(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
519TEST(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
530TEST(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
537TEST(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
546TEST(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
556TEST(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
565TEST(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
575TEST(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
584TEST(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
601TEST(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
611TEST(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
621TEST(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
644TEST(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
654TEST(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
664TEST(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
674TEST(CapabilitySet, IteratorBeginOnEmpty) {
675  CapabilitySet set;
676
677  auto begin = set.begin();
678  auto end = set.end();
679  ASSERT_EQ(begin, end);
680}
681
682TEST(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
693TEST(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
712TEST(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
729TEST(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
754TEST(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
765TEST(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
772TEST(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
788TEST(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
808TEST(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
828struct ForEachCase {
829  CapabilitySet capabilities;
830  std::vector<spv::Capability> expected;
831};
832
833using CapabilitySetForEachTest = ::testing::TestWithParam<ForEachCase>;
834
835TEST_P(CapabilitySetForEachTest, CallsAsExpected) {
836  EXPECT_THAT(ElementsIn(GetParam().capabilities), Eq(GetParam().expected));
837}
838
839TEST_P(CapabilitySetForEachTest, CopyConstructor) {
840  CapabilitySet copy(GetParam().capabilities);
841  EXPECT_THAT(ElementsIn(copy), Eq(GetParam().expected));
842}
843
844TEST_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
854TEST_P(CapabilitySetForEachTest, OperatorEquals) {
855  CapabilitySet assigned = GetParam().capabilities;
856  EXPECT_THAT(ElementsIn(assigned), Eq(GetParam().expected));
857}
858
859TEST_P(CapabilitySetForEachTest, OperatorEqualsSelfAssign) {
860  CapabilitySet assigned{GetParam().capabilities};
861  assigned = assigned;
862  EXPECT_THAT(ElementsIn(assigned), Eq(GetParam().expected));
863}
864
865INSTANTIATE_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
885using BoundaryTestWithParam = ::testing::TestWithParam<spv::Capability>;
886
887TEST_P(BoundaryTestWithParam, InsertedContains) {
888  CapabilitySet set;
889  set.insert(GetParam());
890  EXPECT_TRUE(set.contains(GetParam()));
891}
892
893INSTANTIATE_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