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