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