• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2020 Vasyl Teliman
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 "gtest/gtest.h"
16 #include "source/fuzz/fuzzer_pass_add_opphi_synonyms.h"
17 #include "source/fuzz/fuzzer_util.h"
18 #include "source/fuzz/pseudo_random_generator.h"
19 #include "test/fuzz/fuzz_test_util.h"
20 
21 namespace spvtools {
22 namespace fuzz {
23 namespace {
24 
25 class FuzzerPassMock : public FuzzerPass {
26  public:
FuzzerPassMock(opt::IRContext * ir_context,TransformationContext * transformation_context,FuzzerContext * fuzzer_context,protobufs::TransformationSequence * transformations)27   FuzzerPassMock(opt::IRContext* ir_context,
28                  TransformationContext* transformation_context,
29                  FuzzerContext* fuzzer_context,
30                  protobufs::TransformationSequence* transformations)
31       : FuzzerPass(ir_context, transformation_context, fuzzer_context,
32                    transformations, false) {}
33 
34   ~FuzzerPassMock() override = default;
35 
GetReachedInstructions() const36   const std::unordered_set<uint32_t>& GetReachedInstructions() const {
37     return reached_ids_;
38   }
39 
Apply()40   void Apply() override {
41     ForEachInstructionWithInstructionDescriptor(
42         [this](opt::Function* /*unused*/, opt::BasicBlock* /*unused*/,
43                opt::BasicBlock::iterator inst_it,
44                const protobufs::InstructionDescriptor& /*unused*/) {
45           if (inst_it->result_id()) {
46             reached_ids_.insert(inst_it->result_id());
47           }
48         });
49   }
50 
51  private:
52   std::unordered_set<uint32_t> reached_ids_;
53 };
54 
TEST(FuzzerPassTest,ForEachInstructionWithInstructionDescriptor)55 TEST(FuzzerPassTest, ForEachInstructionWithInstructionDescriptor) {
56   std::string shader = R"(
57                OpCapability Shader
58           %1 = OpExtInstImport "GLSL.std.450"
59                OpMemoryModel Logical GLSL450
60                OpEntryPoint Fragment %4 "main"
61                OpExecutionMode %4 OriginUpperLeft
62                OpSource ESSL 310
63           %2 = OpTypeVoid
64           %3 = OpTypeFunction %2
65           %6 = OpTypeFloat 32
66           %4 = OpFunction %2 None %3
67           %5 = OpLabel
68           %7 = OpUndef %6
69                OpReturn
70           %8 = OpLabel
71           %9 = OpUndef %6
72                OpReturn
73                OpFunctionEnd
74   )";
75 
76   const auto env = SPV_ENV_UNIVERSAL_1_3;
77   const auto consumer = nullptr;
78   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
79   spvtools::ValidatorOptions validator_options;
80   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
81                                                kConsoleMessageConsumer));
82   TransformationContext transformation_context(
83       MakeUnique<FactManager>(context.get()), validator_options);
84   // Check that %5 is reachable and %8 is unreachable as expected.
85   const auto* dominator_analysis =
86       context->GetDominatorAnalysis(context->GetFunction(4));
87   ASSERT_TRUE(dominator_analysis->IsReachable(5));
88   ASSERT_FALSE(dominator_analysis->IsReachable(8));
89 
90   FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
91                                false);
92   protobufs::TransformationSequence transformations;
93   FuzzerPassMock fuzzer_pass_mock(context.get(), &transformation_context,
94                                   &fuzzer_context, &transformations);
95   fuzzer_pass_mock.Apply();
96 
97   ASSERT_TRUE(fuzzer_pass_mock.GetReachedInstructions().count(7));
98   ASSERT_FALSE(fuzzer_pass_mock.GetReachedInstructions().count(9));
99 }
100 
101 }  // namespace
102 }  // namespace fuzz
103 }  // namespace spvtools
104