1fd4e5da5Sopenharmony_ci// Copyright (c) 2020 Vasyl Teliman
2fd4e5da5Sopenharmony_ci//
3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License.
5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at
6fd4e5da5Sopenharmony_ci//
7fd4e5da5Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8fd4e5da5Sopenharmony_ci//
9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and
13fd4e5da5Sopenharmony_ci// limitations under the License.
14fd4e5da5Sopenharmony_ci
15fd4e5da5Sopenharmony_ci#include "gtest/gtest.h"
16fd4e5da5Sopenharmony_ci#include "source/fuzz/fuzzer_pass_add_opphi_synonyms.h"
17fd4e5da5Sopenharmony_ci#include "source/fuzz/fuzzer_util.h"
18fd4e5da5Sopenharmony_ci#include "source/fuzz/pseudo_random_generator.h"
19fd4e5da5Sopenharmony_ci#include "test/fuzz/fuzz_test_util.h"
20fd4e5da5Sopenharmony_ci
21fd4e5da5Sopenharmony_cinamespace spvtools {
22fd4e5da5Sopenharmony_cinamespace fuzz {
23fd4e5da5Sopenharmony_cinamespace {
24fd4e5da5Sopenharmony_ci
25fd4e5da5Sopenharmony_ciclass FuzzerPassMock : public FuzzerPass {
26fd4e5da5Sopenharmony_ci public:
27fd4e5da5Sopenharmony_ci  FuzzerPassMock(opt::IRContext* ir_context,
28fd4e5da5Sopenharmony_ci                 TransformationContext* transformation_context,
29fd4e5da5Sopenharmony_ci                 FuzzerContext* fuzzer_context,
30fd4e5da5Sopenharmony_ci                 protobufs::TransformationSequence* transformations)
31fd4e5da5Sopenharmony_ci      : FuzzerPass(ir_context, transformation_context, fuzzer_context,
32fd4e5da5Sopenharmony_ci                   transformations, false) {}
33fd4e5da5Sopenharmony_ci
34fd4e5da5Sopenharmony_ci  ~FuzzerPassMock() override = default;
35fd4e5da5Sopenharmony_ci
36fd4e5da5Sopenharmony_ci  const std::unordered_set<uint32_t>& GetReachedInstructions() const {
37fd4e5da5Sopenharmony_ci    return reached_ids_;
38fd4e5da5Sopenharmony_ci  }
39fd4e5da5Sopenharmony_ci
40fd4e5da5Sopenharmony_ci  void Apply() override {
41fd4e5da5Sopenharmony_ci    ForEachInstructionWithInstructionDescriptor(
42fd4e5da5Sopenharmony_ci        [this](opt::Function* /*unused*/, opt::BasicBlock* /*unused*/,
43fd4e5da5Sopenharmony_ci               opt::BasicBlock::iterator inst_it,
44fd4e5da5Sopenharmony_ci               const protobufs::InstructionDescriptor& /*unused*/) {
45fd4e5da5Sopenharmony_ci          if (inst_it->result_id()) {
46fd4e5da5Sopenharmony_ci            reached_ids_.insert(inst_it->result_id());
47fd4e5da5Sopenharmony_ci          }
48fd4e5da5Sopenharmony_ci        });
49fd4e5da5Sopenharmony_ci  }
50fd4e5da5Sopenharmony_ci
51fd4e5da5Sopenharmony_ci private:
52fd4e5da5Sopenharmony_ci  std::unordered_set<uint32_t> reached_ids_;
53fd4e5da5Sopenharmony_ci};
54fd4e5da5Sopenharmony_ci
55fd4e5da5Sopenharmony_ciTEST(FuzzerPassTest, ForEachInstructionWithInstructionDescriptor) {
56fd4e5da5Sopenharmony_ci  std::string shader = R"(
57fd4e5da5Sopenharmony_ci               OpCapability Shader
58fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
59fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
60fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
61fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
62fd4e5da5Sopenharmony_ci               OpSource ESSL 310
63fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
64fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
65fd4e5da5Sopenharmony_ci          %6 = OpTypeFloat 32
66fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
67fd4e5da5Sopenharmony_ci          %5 = OpLabel
68fd4e5da5Sopenharmony_ci          %7 = OpUndef %6
69fd4e5da5Sopenharmony_ci               OpReturn
70fd4e5da5Sopenharmony_ci          %8 = OpLabel
71fd4e5da5Sopenharmony_ci          %9 = OpUndef %6
72fd4e5da5Sopenharmony_ci               OpReturn
73fd4e5da5Sopenharmony_ci               OpFunctionEnd
74fd4e5da5Sopenharmony_ci  )";
75fd4e5da5Sopenharmony_ci
76fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
77fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
78fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
79fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
80fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
81fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
82fd4e5da5Sopenharmony_ci  TransformationContext transformation_context(
83fd4e5da5Sopenharmony_ci      MakeUnique<FactManager>(context.get()), validator_options);
84fd4e5da5Sopenharmony_ci  // Check that %5 is reachable and %8 is unreachable as expected.
85fd4e5da5Sopenharmony_ci  const auto* dominator_analysis =
86fd4e5da5Sopenharmony_ci      context->GetDominatorAnalysis(context->GetFunction(4));
87fd4e5da5Sopenharmony_ci  ASSERT_TRUE(dominator_analysis->IsReachable(5));
88fd4e5da5Sopenharmony_ci  ASSERT_FALSE(dominator_analysis->IsReachable(8));
89fd4e5da5Sopenharmony_ci
90fd4e5da5Sopenharmony_ci  FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
91fd4e5da5Sopenharmony_ci                               false);
92fd4e5da5Sopenharmony_ci  protobufs::TransformationSequence transformations;
93fd4e5da5Sopenharmony_ci  FuzzerPassMock fuzzer_pass_mock(context.get(), &transformation_context,
94fd4e5da5Sopenharmony_ci                                  &fuzzer_context, &transformations);
95fd4e5da5Sopenharmony_ci  fuzzer_pass_mock.Apply();
96fd4e5da5Sopenharmony_ci
97fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzer_pass_mock.GetReachedInstructions().count(7));
98fd4e5da5Sopenharmony_ci  ASSERT_FALSE(fuzzer_pass_mock.GetReachedInstructions().count(9));
99fd4e5da5Sopenharmony_ci}
100fd4e5da5Sopenharmony_ci
101fd4e5da5Sopenharmony_ci}  // namespace
102fd4e5da5Sopenharmony_ci}  // namespace fuzz
103fd4e5da5Sopenharmony_ci}  // namespace spvtools
104