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