1 // Copyright 2020 google llc 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 SANDBOXED_API_TOOLS_CLANG_GENERATOR_FRONTEND_ACTION_TEST_UTIL_H_ 16 #define SANDBOXED_API_TOOLS_CLANG_GENERATOR_FRONTEND_ACTION_TEST_UTIL_H_ 17 18 #include <memory> 19 #include <string> 20 #include <utility> 21 #include <vector> 22 23 #include "gtest/gtest.h" 24 #include "absl/container/flat_hash_map.h" 25 #include "absl/memory/memory.h" 26 #include "absl/status/status.h" 27 #include "absl/strings/str_cat.h" 28 #include "absl/strings/string_view.h" 29 #include "clang/Frontend/FrontendAction.h" 30 31 namespace sapi { 32 namespace internal { 33 34 absl::Status RunClangTool( 35 const std::vector<std::string>& command_line, 36 const absl::flat_hash_map<std::string, std::string>& file_contents, 37 std::unique_ptr<clang::FrontendAction> action); 38 39 } // namespace internal 40 41 class FrontendActionTest : public ::testing::Test { 42 protected: 43 // Adds code to a virtual filesystem with the given filename. AddCode(const std::string & filename,absl::string_view code)44 void AddCode(const std::string& filename, absl::string_view code) { 45 absl::StrAppend(&file_contents_[filename], code); 46 } 47 48 // Changes the name of the virtual input file. Useful for special cases where 49 // the filenames of compiled sources matter. set_input_file(absl::string_view value)50 void set_input_file(absl::string_view value) { 51 input_file_ = std::string(value); 52 } 53 54 virtual std::vector<std::string> GetCommandLineFlagsForTesting( 55 absl::string_view input_file); 56 57 // Runs the specified frontend action on in-memory source code. RunFrontendAction(absl::string_view code,std::unique_ptr<clang::FrontendAction> action)58 absl::Status RunFrontendAction( 59 absl::string_view code, std::unique_ptr<clang::FrontendAction> action) { 60 std::vector<std::string> command_line = 61 GetCommandLineFlagsForTesting(input_file_); 62 AddCode(input_file_, code); 63 return internal::RunClangTool(command_line, file_contents_, 64 std::move(action)); 65 } 66 67 // Runs the specified frontend action. Provided for compatibility with LLVM < 68 // 10. Takes ownership. RunFrontendAction(absl::string_view code,clang::FrontendAction * action)69 absl::Status RunFrontendAction(absl::string_view code, 70 clang::FrontendAction* action) { 71 return RunFrontendAction(code, absl::WrapUnique(action)); 72 } 73 74 private: 75 std::string input_file_ = "input.cc"; 76 absl::flat_hash_map<std::string, std::string> file_contents_; 77 }; 78 79 // Flattens a piece of C++ code into one line and removes consecutive runs of 80 // whitespace. This makes it easier to compare code snippets for testing. 81 // Note: This is not syntax-aware and will replace characters within strings as 82 // well. 83 std::string Uglify(absl::string_view code); 84 85 std::vector<std::string> UglifyAll(const std::vector<std::string>& snippets); 86 87 } // namespace sapi 88 89 #endif // SANDBOXED_API_TOOLS_CLANG_GENERATOR_FRONTEND_ACTION_TEST_UTIL_H_ 90