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