mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-12-27 10:20:14 +00:00
d35a78db57
Fixes #4960 * Switches to using enum classes with an underlying type to avoid undefined behaviour
292 lines
8.3 KiB
C++
292 lines
8.3 KiB
C++
// Copyright (c) 2016 Google Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include <algorithm>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "gmock/gmock.h"
|
|
#include "source/enum_set.h"
|
|
#include "test/unit_spirv.h"
|
|
|
|
namespace spvtools {
|
|
namespace {
|
|
|
|
using spvtest::ElementsIn;
|
|
using ::testing::Eq;
|
|
using ::testing::ValuesIn;
|
|
|
|
TEST(EnumSet, IsEmpty1) {
|
|
EnumSet<uint32_t> set;
|
|
EXPECT_TRUE(set.IsEmpty());
|
|
set.Add(0);
|
|
EXPECT_FALSE(set.IsEmpty());
|
|
}
|
|
|
|
TEST(EnumSet, IsEmpty2) {
|
|
EnumSet<uint32_t> set;
|
|
EXPECT_TRUE(set.IsEmpty());
|
|
set.Add(150);
|
|
EXPECT_FALSE(set.IsEmpty());
|
|
}
|
|
|
|
TEST(EnumSet, IsEmpty3) {
|
|
EnumSet<uint32_t> set(4);
|
|
EXPECT_FALSE(set.IsEmpty());
|
|
}
|
|
|
|
TEST(EnumSet, IsEmpty4) {
|
|
EnumSet<uint32_t> set(300);
|
|
EXPECT_FALSE(set.IsEmpty());
|
|
}
|
|
|
|
TEST(EnumSetHasAnyOf, EmptySetEmptyQuery) {
|
|
const EnumSet<uint32_t> set;
|
|
const EnumSet<uint32_t> empty;
|
|
EXPECT_TRUE(set.HasAnyOf(empty));
|
|
EXPECT_TRUE(EnumSet<uint32_t>().HasAnyOf(EnumSet<uint32_t>()));
|
|
}
|
|
|
|
TEST(EnumSetHasAnyOf, MaskSetEmptyQuery) {
|
|
EnumSet<uint32_t> set;
|
|
const EnumSet<uint32_t> empty;
|
|
set.Add(5);
|
|
set.Add(8);
|
|
EXPECT_TRUE(set.HasAnyOf(empty));
|
|
}
|
|
|
|
TEST(EnumSetHasAnyOf, OverflowSetEmptyQuery) {
|
|
EnumSet<uint32_t> set;
|
|
const EnumSet<uint32_t> empty;
|
|
set.Add(200);
|
|
set.Add(300);
|
|
EXPECT_TRUE(set.HasAnyOf(empty));
|
|
}
|
|
|
|
TEST(EnumSetHasAnyOf, EmptyQuery) {
|
|
EnumSet<uint32_t> set;
|
|
const EnumSet<uint32_t> empty;
|
|
set.Add(5);
|
|
set.Add(8);
|
|
set.Add(200);
|
|
set.Add(300);
|
|
EXPECT_TRUE(set.HasAnyOf(empty));
|
|
}
|
|
|
|
TEST(EnumSetHasAnyOf, EmptyQueryAlwaysTrue) {
|
|
EnumSet<uint32_t> set;
|
|
const EnumSet<uint32_t> empty;
|
|
EXPECT_TRUE(set.HasAnyOf(empty));
|
|
set.Add(5);
|
|
EXPECT_TRUE(set.HasAnyOf(empty));
|
|
|
|
EXPECT_TRUE(EnumSet<uint32_t>(100).HasAnyOf(EnumSet<uint32_t>()));
|
|
}
|
|
|
|
TEST(EnumSetHasAnyOf, ReflexiveMask) {
|
|
EnumSet<uint32_t> set(3);
|
|
set.Add(24);
|
|
set.Add(30);
|
|
EXPECT_TRUE(set.HasAnyOf(set));
|
|
}
|
|
|
|
TEST(EnumSetHasAnyOf, ReflexiveOverflow) {
|
|
EnumSet<uint32_t> set(200);
|
|
set.Add(300);
|
|
set.Add(400);
|
|
EXPECT_TRUE(set.HasAnyOf(set));
|
|
}
|
|
|
|
TEST(EnumSetHasAnyOf, Reflexive) {
|
|
EnumSet<uint32_t> set(3);
|
|
set.Add(24);
|
|
set.Add(300);
|
|
set.Add(400);
|
|
EXPECT_TRUE(set.HasAnyOf(set));
|
|
}
|
|
|
|
TEST(EnumSetHasAnyOf, EmptySetHasNone) {
|
|
EnumSet<uint32_t> set;
|
|
EnumSet<uint32_t> items;
|
|
for (uint32_t i = 0; i < 200; ++i) {
|
|
items.Add(i);
|
|
EXPECT_FALSE(set.HasAnyOf(items));
|
|
EXPECT_FALSE(set.HasAnyOf(EnumSet<uint32_t>(i)));
|
|
}
|
|
}
|
|
|
|
TEST(EnumSetHasAnyOf, MaskSetMaskQuery) {
|
|
EnumSet<uint32_t> set(0);
|
|
EnumSet<uint32_t> items(1);
|
|
EXPECT_FALSE(set.HasAnyOf(items));
|
|
set.Add(2);
|
|
items.Add(3);
|
|
EXPECT_FALSE(set.HasAnyOf(items));
|
|
set.Add(3);
|
|
EXPECT_TRUE(set.HasAnyOf(items));
|
|
set.Add(4);
|
|
EXPECT_TRUE(set.HasAnyOf(items));
|
|
}
|
|
|
|
TEST(EnumSetHasAnyOf, OverflowSetOverflowQuery) {
|
|
EnumSet<uint32_t> set(100);
|
|
EnumSet<uint32_t> items(200);
|
|
EXPECT_FALSE(set.HasAnyOf(items));
|
|
set.Add(300);
|
|
items.Add(400);
|
|
EXPECT_FALSE(set.HasAnyOf(items));
|
|
set.Add(200);
|
|
EXPECT_TRUE(set.HasAnyOf(items));
|
|
set.Add(500);
|
|
EXPECT_TRUE(set.HasAnyOf(items));
|
|
}
|
|
|
|
TEST(EnumSetHasAnyOf, GeneralCase) {
|
|
EnumSet<uint32_t> set(0);
|
|
EnumSet<uint32_t> items(100);
|
|
EXPECT_FALSE(set.HasAnyOf(items));
|
|
set.Add(300);
|
|
items.Add(4);
|
|
EXPECT_FALSE(set.HasAnyOf(items));
|
|
set.Add(5);
|
|
items.Add(500);
|
|
EXPECT_FALSE(set.HasAnyOf(items));
|
|
set.Add(500);
|
|
EXPECT_TRUE(set.HasAnyOf(items));
|
|
EXPECT_FALSE(set.HasAnyOf(EnumSet<uint32_t>(20)));
|
|
EXPECT_FALSE(set.HasAnyOf(EnumSet<uint32_t>(600)));
|
|
EXPECT_TRUE(set.HasAnyOf(EnumSet<uint32_t>(5)));
|
|
EXPECT_TRUE(set.HasAnyOf(EnumSet<uint32_t>(300)));
|
|
EXPECT_TRUE(set.HasAnyOf(EnumSet<uint32_t>(0)));
|
|
}
|
|
|
|
TEST(EnumSet, DefaultIsEmpty) {
|
|
EnumSet<uint32_t> set;
|
|
for (uint32_t i = 0; i < 1000; ++i) {
|
|
EXPECT_FALSE(set.Contains(i));
|
|
}
|
|
}
|
|
|
|
TEST(CapabilitySet, ConstructSingleMemberMatrix) {
|
|
CapabilitySet s(spv::Capability::Matrix);
|
|
EXPECT_TRUE(s.Contains(spv::Capability::Matrix));
|
|
EXPECT_FALSE(s.Contains(spv::Capability::Shader));
|
|
EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(1000)));
|
|
}
|
|
|
|
TEST(CapabilitySet, ConstructSingleMemberMaxInMask) {
|
|
CapabilitySet s(static_cast<spv::Capability>(63));
|
|
EXPECT_FALSE(s.Contains(spv::Capability::Matrix));
|
|
EXPECT_FALSE(s.Contains(spv::Capability::Shader));
|
|
EXPECT_TRUE(s.Contains(static_cast<spv::Capability>(63)));
|
|
EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(64)));
|
|
EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(1000)));
|
|
}
|
|
|
|
TEST(CapabilitySet, ConstructSingleMemberMinOverflow) {
|
|
// Check the first one that forces overflow beyond the mask.
|
|
CapabilitySet s(static_cast<spv::Capability>(64));
|
|
EXPECT_FALSE(s.Contains(spv::Capability::Matrix));
|
|
EXPECT_FALSE(s.Contains(spv::Capability::Shader));
|
|
EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(63)));
|
|
EXPECT_TRUE(s.Contains(static_cast<spv::Capability>(64)));
|
|
EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(1000)));
|
|
}
|
|
|
|
TEST(CapabilitySet, ConstructSingleMemberMaxOverflow) {
|
|
// Check the max 32-bit signed int.
|
|
CapabilitySet s(static_cast<spv::Capability>(0x7fffffffu));
|
|
EXPECT_FALSE(s.Contains(spv::Capability::Matrix));
|
|
EXPECT_FALSE(s.Contains(spv::Capability::Shader));
|
|
EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(1000)));
|
|
EXPECT_TRUE(s.Contains(static_cast<spv::Capability>(0x7fffffffu)));
|
|
}
|
|
|
|
TEST(CapabilitySet, AddEnum) {
|
|
CapabilitySet s(spv::Capability::Shader);
|
|
s.Add(spv::Capability::Kernel);
|
|
s.Add(static_cast<spv::Capability>(42));
|
|
EXPECT_FALSE(s.Contains(spv::Capability::Matrix));
|
|
EXPECT_TRUE(s.Contains(spv::Capability::Shader));
|
|
EXPECT_TRUE(s.Contains(spv::Capability::Kernel));
|
|
EXPECT_TRUE(s.Contains(static_cast<spv::Capability>(42)));
|
|
}
|
|
|
|
TEST(CapabilitySet, InitializerListEmpty) {
|
|
CapabilitySet s{};
|
|
for (uint32_t i = 0; i < 1000; i++) {
|
|
EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(i)));
|
|
}
|
|
}
|
|
|
|
struct ForEachCase {
|
|
CapabilitySet capabilities;
|
|
std::vector<spv::Capability> expected;
|
|
};
|
|
|
|
using CapabilitySetForEachTest = ::testing::TestWithParam<ForEachCase>;
|
|
|
|
TEST_P(CapabilitySetForEachTest, CallsAsExpected) {
|
|
EXPECT_THAT(ElementsIn(GetParam().capabilities), Eq(GetParam().expected));
|
|
}
|
|
|
|
TEST_P(CapabilitySetForEachTest, CopyConstructor) {
|
|
CapabilitySet copy(GetParam().capabilities);
|
|
EXPECT_THAT(ElementsIn(copy), Eq(GetParam().expected));
|
|
}
|
|
|
|
TEST_P(CapabilitySetForEachTest, MoveConstructor) {
|
|
// We need a writable copy to move from.
|
|
CapabilitySet copy(GetParam().capabilities);
|
|
CapabilitySet moved(std::move(copy));
|
|
EXPECT_THAT(ElementsIn(moved), Eq(GetParam().expected));
|
|
|
|
// The moved-from set is empty.
|
|
EXPECT_THAT(ElementsIn(copy), Eq(std::vector<spv::Capability>{}));
|
|
}
|
|
|
|
TEST_P(CapabilitySetForEachTest, OperatorEquals) {
|
|
CapabilitySet assigned = GetParam().capabilities;
|
|
EXPECT_THAT(ElementsIn(assigned), Eq(GetParam().expected));
|
|
}
|
|
|
|
TEST_P(CapabilitySetForEachTest, OperatorEqualsSelfAssign) {
|
|
CapabilitySet assigned{GetParam().capabilities};
|
|
assigned = assigned;
|
|
EXPECT_THAT(ElementsIn(assigned), Eq(GetParam().expected));
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(
|
|
Samples, CapabilitySetForEachTest,
|
|
ValuesIn(std::vector<ForEachCase>{
|
|
{{}, {}},
|
|
{{spv::Capability::Matrix}, {spv::Capability::Matrix}},
|
|
{{spv::Capability::Kernel, spv::Capability::Shader},
|
|
{spv::Capability::Shader, spv::Capability::Kernel}},
|
|
{{static_cast<spv::Capability>(999)},
|
|
{static_cast<spv::Capability>(999)}},
|
|
{{static_cast<spv::Capability>(0x7fffffff)},
|
|
{static_cast<spv::Capability>(0x7fffffff)}},
|
|
// Mixture and out of order
|
|
{{static_cast<spv::Capability>(0x7fffffff),
|
|
static_cast<spv::Capability>(100), spv::Capability::Shader,
|
|
spv::Capability::Matrix},
|
|
{spv::Capability::Matrix, spv::Capability::Shader,
|
|
static_cast<spv::Capability>(100),
|
|
static_cast<spv::Capability>(0x7fffffff)}},
|
|
}));
|
|
|
|
} // namespace
|
|
} // namespace spvtools
|