1 // Copyright 2020 The Tint Authors.
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 #ifndef SRC_WRITER_MSL_TEST_HELPER_H_
16 #define SRC_WRITER_MSL_TEST_HELPER_H_
17 
18 #include <memory>
19 #include <string>
20 #include <utility>
21 
22 #include "gtest/gtest.h"
23 #include "src/program_builder.h"
24 #include "src/writer/msl/generator.h"
25 #include "src/writer/msl/generator_impl.h"
26 
27 namespace tint {
28 namespace writer {
29 namespace msl {
30 
31 /// Helper class for testing
32 template <typename BASE>
33 class TestHelperBase : public BASE, public ProgramBuilder {
34  public:
35   TestHelperBase() = default;
36   ~TestHelperBase() override = default;
37 
38   /// Builds and returns a GeneratorImpl from the program.
39   /// @note The generator is only built once. Multiple calls to Build() will
40   /// return the same GeneratorImpl without rebuilding.
41   /// @return the built generator
Build()42   GeneratorImpl& Build() {
43     if (gen_) {
44       return *gen_;
45     }
46     [&]() {
47       ASSERT_TRUE(IsValid()) << "Builder program is not valid\n"
48                              << diag::Formatter().format(Diagnostics());
49     }();
50     program = std::make_unique<Program>(std::move(*this));
51     [&]() {
52       ASSERT_TRUE(program->IsValid())
53           << diag::Formatter().format(program->Diagnostics());
54     }();
55     gen_ = std::make_unique<GeneratorImpl>(program.get());
56     return *gen_;
57   }
58 
59   /// Builds the program, runs the program through the transform::Msl sanitizer
60   /// and returns a GeneratorImpl from the sanitized program.
61   /// @param options The MSL generator options.
62   /// @note The generator is only built once. Multiple calls to Build() will
63   /// return the same GeneratorImpl without rebuilding.
64   /// @return the built generator
SanitizeAndBuild(const Options& options = {})65   GeneratorImpl& SanitizeAndBuild(const Options& options = {}) {
66     if (gen_) {
67       return *gen_;
68     }
69     [&]() {
70       ASSERT_TRUE(IsValid()) << "Builder program is not valid\n"
71                              << diag::Formatter().format(Diagnostics());
72     }();
73     program = std::make_unique<Program>(std::move(*this));
74     [&]() {
75       ASSERT_TRUE(program->IsValid())
76           << diag::Formatter().format(program->Diagnostics());
77     }();
78 
79     auto result = Sanitize(
80         program.get(), options.buffer_size_ubo_index, options.fixed_sample_mask,
81         options.emit_vertex_point_size, options.disable_workgroup_init,
82         options.array_length_from_uniform);
83     [&]() {
84       ASSERT_TRUE(result.program.IsValid())
85           << diag::Formatter().format(result.program.Diagnostics());
86     }();
87     *program = std::move(result.program);
88     gen_ = std::make_unique<GeneratorImpl>(program.get());
89     return *gen_;
90   }
91 
92   /// The program built with a call to Build()
93   std::unique_ptr<Program> program;
94 
95  private:
96   std::unique_ptr<GeneratorImpl> gen_;
97 };
98 using TestHelper = TestHelperBase<testing::Test>;
99 
100 template <typename T>
101 using TestParamHelper = TestHelperBase<testing::TestWithParam<T>>;
102 
103 }  // namespace msl
104 }  // namespace writer
105 }  // namespace tint
106 
107 #endif  // SRC_WRITER_MSL_TEST_HELPER_H_
108