Home | History | Annotate | Download | only in test
      1 // Copyright (c) 2015-2016 The Khronos Group 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 <vector>
     16 
     17 #include "gmock/gmock.h"
     18 #include "source/operand.h"
     19 #include "test/unit_spirv.h"
     20 
     21 namespace spvtools {
     22 namespace {
     23 
     24 using ::testing::Eq;
     25 
     26 TEST(OperandPattern, InitiallyEmpty) {
     27   spv_operand_pattern_t empty;
     28   EXPECT_THAT(empty, Eq(spv_operand_pattern_t{}));
     29   EXPECT_EQ(0u, empty.size());
     30   EXPECT_TRUE(empty.empty());
     31 }
     32 
     33 TEST(OperandPattern, PushBacksAreOnTheRight) {
     34   spv_operand_pattern_t pattern;
     35 
     36   pattern.push_back(SPV_OPERAND_TYPE_ID);
     37   EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_ID}));
     38   EXPECT_EQ(1u, pattern.size());
     39   EXPECT_TRUE(!pattern.empty());
     40   EXPECT_EQ(SPV_OPERAND_TYPE_ID, pattern.back());
     41 
     42   pattern.push_back(SPV_OPERAND_TYPE_NONE);
     43   EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_ID,
     44                                                 SPV_OPERAND_TYPE_NONE}));
     45   EXPECT_EQ(2u, pattern.size());
     46   EXPECT_TRUE(!pattern.empty());
     47   EXPECT_EQ(SPV_OPERAND_TYPE_NONE, pattern.back());
     48 }
     49 
     50 TEST(OperandPattern, PopBacksAreOnTheRight) {
     51   spv_operand_pattern_t pattern{SPV_OPERAND_TYPE_ID,
     52                                 SPV_OPERAND_TYPE_LITERAL_INTEGER};
     53 
     54   pattern.pop_back();
     55   EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_ID}));
     56 
     57   pattern.pop_back();
     58   EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{}));
     59 }
     60 
     61 // A test case for typed mask expansion
     62 struct MaskExpansionCase {
     63   spv_operand_type_t type;
     64   uint32_t mask;
     65   spv_operand_pattern_t initial;
     66   spv_operand_pattern_t expected;
     67 };
     68 
     69 using MaskExpansionTest = ::testing::TestWithParam<MaskExpansionCase>;
     70 
     71 TEST_P(MaskExpansionTest, Sample) {
     72   spv_operand_table operandTable = nullptr;
     73   auto env = SPV_ENV_UNIVERSAL_1_0;
     74   ASSERT_EQ(SPV_SUCCESS, spvOperandTableGet(&operandTable, env));
     75 
     76   spv_operand_pattern_t pattern(GetParam().initial);
     77   spvPushOperandTypesForMask(env, operandTable, GetParam().type,
     78                              GetParam().mask, &pattern);
     79   EXPECT_THAT(pattern, Eq(GetParam().expected));
     80 }
     81 
     82 // These macros let us write non-trivial examples without too much text.
     83 #define PREFIX0 SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE
     84 #define PREFIX1                                                         \
     85   SPV_OPERAND_TYPE_STORAGE_CLASS, SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE, \
     86       SPV_OPERAND_TYPE_ID
     87 INSTANTIATE_TEST_CASE_P(
     88     OperandPattern, MaskExpansionTest,
     89     ::testing::ValuesIn(std::vector<MaskExpansionCase>{
     90         // No bits means no change.
     91         {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS, 0, {PREFIX0}, {PREFIX0}},
     92         // Unknown bits means no change.  Use all bits that aren't in the
     93         // grammar.
     94         // The last mask enum is 0x20
     95         {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
     96          0xffffffc0,
     97          {PREFIX1},
     98          {PREFIX1}},
     99         // Volatile has no operands.
    100         {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
    101          SpvMemoryAccessVolatileMask,
    102          {PREFIX0},
    103          {PREFIX0}},
    104         // Aligned has one literal number operand.
    105         {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
    106          SpvMemoryAccessAlignedMask,
    107          {PREFIX1},
    108          {PREFIX1, SPV_OPERAND_TYPE_LITERAL_INTEGER}},
    109         // Volatile with Aligned still has just one literal number operand.
    110         {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
    111          SpvMemoryAccessVolatileMask | SpvMemoryAccessAlignedMask,
    112          {PREFIX1},
    113          {PREFIX1, SPV_OPERAND_TYPE_LITERAL_INTEGER}},
    114     }), );
    115 #undef PREFIX0
    116 #undef PREFIX1
    117 
    118 // Returns a vector of all operand types that can be used in a pattern.
    119 std::vector<spv_operand_type_t> allOperandTypes() {
    120   std::vector<spv_operand_type_t> result;
    121   for (int i = 0; i < SPV_OPERAND_TYPE_NUM_OPERAND_TYPES; i++) {
    122     result.push_back(spv_operand_type_t(i));
    123   }
    124   return result;
    125 }
    126 
    127 using MatchableOperandExpansionTest =
    128     ::testing::TestWithParam<spv_operand_type_t>;
    129 
    130 TEST_P(MatchableOperandExpansionTest, MatchableOperandsDontExpand) {
    131   const spv_operand_type_t type = GetParam();
    132   if (!spvOperandIsVariable(type)) {
    133     spv_operand_pattern_t pattern;
    134     const bool did_expand = spvExpandOperandSequenceOnce(type, &pattern);
    135     EXPECT_FALSE(did_expand);
    136     EXPECT_THAT(pattern, Eq(spv_operand_pattern_t{}));
    137   }
    138 }
    139 
    140 INSTANTIATE_TEST_CASE_P(MatchableOperandExpansion,
    141                         MatchableOperandExpansionTest,
    142                         ::testing::ValuesIn(allOperandTypes()), );
    143 
    144 using VariableOperandExpansionTest =
    145     ::testing::TestWithParam<spv_operand_type_t>;
    146 
    147 TEST_P(VariableOperandExpansionTest, NonMatchableOperandsExpand) {
    148   const spv_operand_type_t type = GetParam();
    149   if (spvOperandIsVariable(type)) {
    150     spv_operand_pattern_t pattern;
    151     const bool did_expand = spvExpandOperandSequenceOnce(type, &pattern);
    152     EXPECT_TRUE(did_expand);
    153     EXPECT_FALSE(pattern.empty());
    154     // For the existing rules, the first expansion of a zero-or-more operand
    155     // type yields a matchable operand type.  This isn't strictly necessary.
    156     EXPECT_FALSE(spvOperandIsVariable(pattern.back()));
    157   }
    158 }
    159 
    160 INSTANTIATE_TEST_CASE_P(NonMatchableOperandExpansion,
    161                         VariableOperandExpansionTest,
    162                         ::testing::ValuesIn(allOperandTypes()), );
    163 
    164 TEST(AlternatePatternFollowingImmediate, Empty) {
    165   EXPECT_THAT(spvAlternatePatternFollowingImmediate({}),
    166               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
    167 }
    168 
    169 TEST(AlternatePatternFollowingImmediate, SingleElement) {
    170   // Spot-check a random selection of types.
    171   EXPECT_THAT(spvAlternatePatternFollowingImmediate(
    172                   {SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER}),
    173               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
    174   EXPECT_THAT(
    175       spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_CAPABILITY}),
    176       Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
    177   EXPECT_THAT(
    178       spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_LOOP_CONTROL}),
    179       Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
    180   EXPECT_THAT(spvAlternatePatternFollowingImmediate(
    181                   {SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER}),
    182               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
    183   EXPECT_THAT(spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_ID}),
    184               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
    185 }
    186 
    187 TEST(AlternatePatternFollowingImmediate, SingleResultId) {
    188   EXPECT_THAT(
    189       spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_RESULT_ID}),
    190       Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
    191                                SPV_OPERAND_TYPE_RESULT_ID}));
    192 }
    193 
    194 TEST(AlternatePatternFollowingImmediate, MultipleNonResultIds) {
    195   EXPECT_THAT(
    196       spvAlternatePatternFollowingImmediate(
    197           {SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER,
    198            SPV_OPERAND_TYPE_CAPABILITY, SPV_OPERAND_TYPE_LOOP_CONTROL,
    199            SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID}),
    200       Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
    201 }
    202 
    203 TEST(AlternatePatternFollowingImmediate, ResultIdFront) {
    204   EXPECT_THAT(spvAlternatePatternFollowingImmediate(
    205                   {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}),
    206               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
    207                                        SPV_OPERAND_TYPE_RESULT_ID,
    208                                        SPV_OPERAND_TYPE_OPTIONAL_CIV}));
    209   EXPECT_THAT(
    210       spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_RESULT_ID,
    211                                              SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
    212                                              SPV_OPERAND_TYPE_ID}),
    213       Eq(spv_operand_pattern_t{
    214           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_RESULT_ID,
    215           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV}));
    216   EXPECT_THAT(
    217       spvAlternatePatternFollowingImmediate(
    218           {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_DIMENSIONALITY,
    219            SPV_OPERAND_TYPE_LINKAGE_TYPE,
    220            SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
    221            SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID,
    222            SPV_OPERAND_TYPE_VARIABLE_ID}),
    223       Eq(spv_operand_pattern_t{
    224           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_RESULT_ID,
    225           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
    226           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
    227           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV}));
    228 }
    229 
    230 TEST(AlternatePatternFollowingImmediate, ResultIdMiddle) {
    231   EXPECT_THAT(spvAlternatePatternFollowingImmediate(
    232                   {SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
    233                    SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}),
    234               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
    235                                        SPV_OPERAND_TYPE_RESULT_ID,
    236                                        SPV_OPERAND_TYPE_OPTIONAL_CIV}));
    237   EXPECT_THAT(
    238       spvAlternatePatternFollowingImmediate(
    239           {SPV_OPERAND_TYPE_DIMENSIONALITY, SPV_OPERAND_TYPE_LINKAGE_TYPE,
    240            SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
    241            SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_FP_ROUNDING_MODE,
    242            SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}),
    243       Eq(spv_operand_pattern_t{
    244           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_RESULT_ID,
    245           SPV_OPERAND_TYPE_OPTIONAL_CIV, SPV_OPERAND_TYPE_OPTIONAL_CIV,
    246           SPV_OPERAND_TYPE_OPTIONAL_CIV}));
    247 }
    248 
    249 TEST(AlternatePatternFollowingImmediate, ResultIdBack) {
    250   EXPECT_THAT(spvAlternatePatternFollowingImmediate(
    251                   {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}),
    252               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
    253                                        SPV_OPERAND_TYPE_RESULT_ID}));
    254   EXPECT_THAT(spvAlternatePatternFollowingImmediate(
    255                   {SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID,
    256                    SPV_OPERAND_TYPE_RESULT_ID}),
    257               Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
    258                                        SPV_OPERAND_TYPE_RESULT_ID}));
    259   EXPECT_THAT(
    260       spvAlternatePatternFollowingImmediate(
    261           {SPV_OPERAND_TYPE_DIMENSIONALITY, SPV_OPERAND_TYPE_LINKAGE_TYPE,
    262            SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE,
    263            SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_ID,
    264            SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_RESULT_ID}),
    265       Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV,
    266                                SPV_OPERAND_TYPE_RESULT_ID}));
    267 }
    268 
    269 }  // namespace
    270 }  // namespace spvtools
    271