1 // Copyright (c) 2019 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_constant_boolean.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
TEST(TransformationAddConstantBooleanTest,NeitherPresentInitiallyAddBoth)25 TEST(TransformationAddConstantBooleanTest, NeitherPresentInitiallyAddBoth) {
26 std::string shader = R"(
27 OpCapability Shader
28 %1 = OpExtInstImport "GLSL.std.450"
29 OpMemoryModel Logical GLSL450
30 OpEntryPoint Fragment %4 "main"
31 OpExecutionMode %4 OriginUpperLeft
32 OpSource ESSL 310
33 OpName %4 "main"
34 %2 = OpTypeVoid
35 %6 = OpTypeBool
36 %3 = OpTypeFunction %2
37 %4 = OpFunction %2 None %3
38 %5 = OpLabel
39 OpReturn
40 OpFunctionEnd
41 )";
42
43 const auto env = SPV_ENV_UNIVERSAL_1_3;
44 const auto consumer = nullptr;
45 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
46 spvtools::ValidatorOptions validator_options;
47 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
48 kConsoleMessageConsumer));
49 TransformationContext transformation_context(
50 MakeUnique<FactManager>(context.get()), validator_options);
51 // True and false can both be added as neither is present.
52 ASSERT_TRUE(TransformationAddConstantBoolean(7, true, false)
53 .IsApplicable(context.get(), transformation_context));
54 ASSERT_TRUE(TransformationAddConstantBoolean(7, false, false)
55 .IsApplicable(context.get(), transformation_context));
56
57 // Irrelevant true and false can both be added as neither is present.
58 ASSERT_TRUE(TransformationAddConstantBoolean(7, true, true)
59 .IsApplicable(context.get(), transformation_context));
60 ASSERT_TRUE(TransformationAddConstantBoolean(7, false, true)
61 .IsApplicable(context.get(), transformation_context));
62
63 // Id 5 is already taken.
64 ASSERT_FALSE(TransformationAddConstantBoolean(5, true, false)
65 .IsApplicable(context.get(), transformation_context));
66
67 auto add_true = TransformationAddConstantBoolean(7, true, false);
68 auto add_false = TransformationAddConstantBoolean(8, false, false);
69
70 ASSERT_TRUE(add_true.IsApplicable(context.get(), transformation_context));
71 ApplyAndCheckFreshIds(add_true, context.get(), &transformation_context);
72 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
73 kConsoleMessageConsumer));
74
75 // Having added true, we cannot add it again with the same id.
76 ASSERT_FALSE(add_true.IsApplicable(context.get(), transformation_context));
77 // But we can add it with a different id.
78 auto add_true_again = TransformationAddConstantBoolean(100, true, false);
79 ASSERT_TRUE(
80 add_true_again.IsApplicable(context.get(), transformation_context));
81 ApplyAndCheckFreshIds(add_true_again, context.get(), &transformation_context);
82 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
83 kConsoleMessageConsumer));
84
85 ASSERT_TRUE(add_false.IsApplicable(context.get(), transformation_context));
86 ApplyAndCheckFreshIds(add_false, context.get(), &transformation_context);
87 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
88 kConsoleMessageConsumer));
89
90 // Having added false, we cannot add it again with the same id.
91 ASSERT_FALSE(add_false.IsApplicable(context.get(), transformation_context));
92 // But we can add it with a different id.
93 auto add_false_again = TransformationAddConstantBoolean(101, false, false);
94 ASSERT_TRUE(
95 add_false_again.IsApplicable(context.get(), transformation_context));
96 ApplyAndCheckFreshIds(add_false_again, context.get(),
97 &transformation_context);
98 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
99 kConsoleMessageConsumer));
100
101 // We can create an irrelevant OpConstantTrue.
102 TransformationAddConstantBoolean irrelevant_true(102, true, true);
103 ASSERT_TRUE(
104 irrelevant_true.IsApplicable(context.get(), transformation_context));
105 ApplyAndCheckFreshIds(irrelevant_true, context.get(),
106 &transformation_context);
107 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
108 kConsoleMessageConsumer));
109
110 // We can create an irrelevant OpConstantFalse.
111 TransformationAddConstantBoolean irrelevant_false(103, false, true);
112 ASSERT_TRUE(
113 irrelevant_false.IsApplicable(context.get(), transformation_context));
114 ApplyAndCheckFreshIds(irrelevant_false, context.get(),
115 &transformation_context);
116 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
117 kConsoleMessageConsumer));
118
119 ASSERT_FALSE(transformation_context.GetFactManager()->IdIsIrrelevant(100));
120 ASSERT_FALSE(transformation_context.GetFactManager()->IdIsIrrelevant(101));
121 ASSERT_TRUE(transformation_context.GetFactManager()->IdIsIrrelevant(102));
122 ASSERT_TRUE(transformation_context.GetFactManager()->IdIsIrrelevant(103));
123
124 std::string after_transformation = R"(
125 OpCapability Shader
126 %1 = OpExtInstImport "GLSL.std.450"
127 OpMemoryModel Logical GLSL450
128 OpEntryPoint Fragment %4 "main"
129 OpExecutionMode %4 OriginUpperLeft
130 OpSource ESSL 310
131 OpName %4 "main"
132 %2 = OpTypeVoid
133 %6 = OpTypeBool
134 %3 = OpTypeFunction %2
135 %7 = OpConstantTrue %6
136 %100 = OpConstantTrue %6
137 %8 = OpConstantFalse %6
138 %101 = OpConstantFalse %6
139 %102 = OpConstantTrue %6
140 %103 = OpConstantFalse %6
141 %4 = OpFunction %2 None %3
142 %5 = OpLabel
143 OpReturn
144 OpFunctionEnd
145 )";
146
147 ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
148 }
149
TEST(TransformationAddConstantBooleanTest,NoOpTypeBoolPresent)150 TEST(TransformationAddConstantBooleanTest, NoOpTypeBoolPresent) {
151 std::string shader = R"(
152 OpCapability Shader
153 %1 = OpExtInstImport "GLSL.std.450"
154 OpMemoryModel Logical GLSL450
155 OpEntryPoint Fragment %4 "main"
156 OpExecutionMode %4 OriginUpperLeft
157 OpSource ESSL 310
158 OpName %4 "main"
159 %2 = OpTypeVoid
160 %3 = OpTypeFunction %2
161 %4 = OpFunction %2 None %3
162 %5 = OpLabel
163 OpReturn
164 OpFunctionEnd
165 )";
166
167 const auto env = SPV_ENV_UNIVERSAL_1_3;
168 const auto consumer = nullptr;
169 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
170 spvtools::ValidatorOptions validator_options;
171 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
172 kConsoleMessageConsumer));
173 TransformationContext transformation_context(
174 MakeUnique<FactManager>(context.get()), validator_options);
175 // Neither true nor false can be added as OpTypeBool is not present.
176 ASSERT_FALSE(TransformationAddConstantBoolean(6, true, false)
177 .IsApplicable(context.get(), transformation_context));
178 ASSERT_FALSE(TransformationAddConstantBoolean(6, false, false)
179 .IsApplicable(context.get(), transformation_context));
180
181 // This does not depend on whether the constant is relevant or not.
182 ASSERT_FALSE(TransformationAddConstantBoolean(6, true, true)
183 .IsApplicable(context.get(), transformation_context));
184 ASSERT_FALSE(TransformationAddConstantBoolean(6, false, true)
185 .IsApplicable(context.get(), transformation_context));
186 }
187
188 } // namespace
189 } // namespace fuzz
190 } // namespace spvtools
191