Alexis Hetu | 3eb4dd8 | 2020-10-29 21:37:20 -0400 | [diff] [blame] | 1 | // Copyright (c) 2020 Google LLC |
| 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/fuzz/transformation_add_early_terminator_wrapper.h" |
| 16 | |
| 17 | #include "gtest/gtest.h" |
| 18 | #include "source/fuzz/fuzzer_util.h" |
| 19 | #include "test/fuzz/fuzz_test_util.h" |
| 20 | |
| 21 | namespace spvtools { |
| 22 | namespace fuzz { |
| 23 | namespace { |
| 24 | |
| 25 | TEST(TransformationAddEarlyTerminatorWrapperTest, NoVoidType) { |
| 26 | std::string shader = R"( |
| 27 | OpCapability Shader |
| 28 | OpCapability Linkage |
| 29 | %1 = OpExtInstImport "GLSL.std.450" |
| 30 | OpMemoryModel Logical GLSL450 |
| 31 | OpSource ESSL 320 |
| 32 | )"; |
| 33 | |
| 34 | const auto env = SPV_ENV_UNIVERSAL_1_4; |
| 35 | const auto consumer = nullptr; |
| 36 | const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); |
| 37 | spvtools::ValidatorOptions validator_options; |
| 38 | ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, |
| 39 | kConsoleMessageConsumer)); |
| 40 | TransformationContext transformation_context( |
| 41 | MakeUnique<FactManager>(context.get()), validator_options); |
| 42 | |
| 43 | ASSERT_FALSE(TransformationAddEarlyTerminatorWrapper(100, 101, SpvOpKill) |
| 44 | .IsApplicable(context.get(), transformation_context)); |
| 45 | } |
| 46 | |
| 47 | TEST(TransformationAddEarlyTerminatorWrapperTest, NoVoidFunctionType) { |
| 48 | std::string shader = R"( |
| 49 | OpCapability Shader |
| 50 | OpCapability Linkage |
| 51 | %1 = OpExtInstImport "GLSL.std.450" |
| 52 | OpMemoryModel Logical GLSL450 |
| 53 | OpSource ESSL 320 |
| 54 | %2 = OpTypeVoid |
| 55 | )"; |
| 56 | |
| 57 | const auto env = SPV_ENV_UNIVERSAL_1_4; |
| 58 | const auto consumer = nullptr; |
| 59 | const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); |
| 60 | spvtools::ValidatorOptions validator_options; |
| 61 | ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, |
| 62 | kConsoleMessageConsumer)); |
| 63 | TransformationContext transformation_context( |
| 64 | MakeUnique<FactManager>(context.get()), validator_options); |
| 65 | |
| 66 | ASSERT_FALSE(TransformationAddEarlyTerminatorWrapper(100, 101, SpvOpKill) |
| 67 | .IsApplicable(context.get(), transformation_context)); |
| 68 | } |
| 69 | |
| 70 | TEST(TransformationAddEarlyTerminatorWrapperTest, BasicTest) { |
| 71 | std::string shader = R"( |
| 72 | OpCapability Shader |
| 73 | OpExtension "SPV_KHR_terminate_invocation" |
| 74 | %1 = OpExtInstImport "GLSL.std.450" |
| 75 | OpMemoryModel Logical GLSL450 |
| 76 | OpEntryPoint Fragment %4 "main" |
| 77 | OpExecutionMode %4 OriginUpperLeft |
| 78 | OpSource ESSL 320 |
| 79 | %2 = OpTypeVoid |
| 80 | %3 = OpTypeFunction %2 |
| 81 | %4 = OpFunction %2 None %3 |
| 82 | %5 = OpLabel |
| 83 | OpReturn |
| 84 | OpFunctionEnd |
| 85 | )"; |
| 86 | |
| 87 | const auto env = SPV_ENV_UNIVERSAL_1_5; |
| 88 | const auto consumer = nullptr; |
| 89 | const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); |
| 90 | spvtools::ValidatorOptions validator_options; |
| 91 | ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, |
| 92 | kConsoleMessageConsumer)); |
| 93 | TransformationContext transformation_context( |
| 94 | MakeUnique<FactManager>(context.get()), validator_options); |
| 95 | |
| 96 | ASSERT_FALSE(TransformationAddEarlyTerminatorWrapper(2, 101, SpvOpKill) |
| 97 | .IsApplicable(context.get(), transformation_context)); |
| 98 | ASSERT_FALSE(TransformationAddEarlyTerminatorWrapper(100, 4, SpvOpKill) |
| 99 | .IsApplicable(context.get(), transformation_context)); |
| 100 | ASSERT_FALSE(TransformationAddEarlyTerminatorWrapper(100, 100, SpvOpKill) |
| 101 | .IsApplicable(context.get(), transformation_context)); |
| 102 | |
| 103 | #ifndef NDEBUG |
| 104 | ASSERT_DEATH(TransformationAddEarlyTerminatorWrapper(100, 101, SpvOpReturn) |
| 105 | .IsApplicable(context.get(), transformation_context), |
| 106 | "Invalid opcode."); |
| 107 | #endif |
| 108 | |
| 109 | auto transformation1 = |
| 110 | TransformationAddEarlyTerminatorWrapper(100, 101, SpvOpKill); |
| 111 | auto transformation2 = |
| 112 | TransformationAddEarlyTerminatorWrapper(102, 103, SpvOpUnreachable); |
| 113 | auto transformation3 = TransformationAddEarlyTerminatorWrapper( |
| 114 | 104, 105, SpvOpTerminateInvocation); |
| 115 | |
| 116 | ASSERT_TRUE( |
| 117 | transformation1.IsApplicable(context.get(), transformation_context)); |
| 118 | ApplyAndCheckFreshIds(transformation1, context.get(), |
| 119 | &transformation_context); |
| 120 | ASSERT_TRUE( |
| 121 | transformation2.IsApplicable(context.get(), transformation_context)); |
| 122 | ApplyAndCheckFreshIds(transformation2, context.get(), |
| 123 | &transformation_context); |
| 124 | ASSERT_TRUE( |
| 125 | transformation3.IsApplicable(context.get(), transformation_context)); |
| 126 | ApplyAndCheckFreshIds(transformation3, context.get(), |
| 127 | &transformation_context); |
| 128 | ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, |
| 129 | kConsoleMessageConsumer)); |
| 130 | |
| 131 | std::string after_transformation = R"( |
| 132 | OpCapability Shader |
| 133 | OpExtension "SPV_KHR_terminate_invocation" |
| 134 | %1 = OpExtInstImport "GLSL.std.450" |
| 135 | OpMemoryModel Logical GLSL450 |
| 136 | OpEntryPoint Fragment %4 "main" |
| 137 | OpExecutionMode %4 OriginUpperLeft |
| 138 | OpSource ESSL 320 |
| 139 | %2 = OpTypeVoid |
| 140 | %3 = OpTypeFunction %2 |
| 141 | %4 = OpFunction %2 None %3 |
| 142 | %5 = OpLabel |
| 143 | OpReturn |
| 144 | OpFunctionEnd |
| 145 | %100 = OpFunction %2 None %3 |
| 146 | %101 = OpLabel |
| 147 | OpKill |
| 148 | OpFunctionEnd |
| 149 | %102 = OpFunction %2 None %3 |
| 150 | %103 = OpLabel |
| 151 | OpUnreachable |
| 152 | OpFunctionEnd |
| 153 | %104 = OpFunction %2 None %3 |
| 154 | %105 = OpLabel |
| 155 | OpTerminateInvocation |
| 156 | OpFunctionEnd |
| 157 | )"; |
| 158 | ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); |
| 159 | } |
| 160 | |
| 161 | } // namespace |
| 162 | } // namespace fuzz |
| 163 | } // namespace spvtools |