// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "google/cloud/internal/absl_str_cat_quiet.h" #include "google/cloud/internal/absl_str_replace_quiet.h" #include "google/cloud/internal/getenv.h" #include "google/cloud/status_or.h" #include "absl/strings/string_view.h" #include "generator/generator.h" #include #include #include #include namespace google { namespace cloud { namespace generator_internal { namespace { StatusOr> ReadFile(std::string const& filepath) { std::string line; std::vector file_contents; std::ifstream input_file(filepath); if (!input_file) return Status(StatusCode::kNotFound, "Cannot open: " + filepath); while (std::getline(input_file, line)) { file_contents.push_back(line); } return file_contents; } class GeneratorIntegrationTest : public testing::TestWithParam { protected: void SetUp() override { auto run_integration_tests = google::cloud::internal::GetEnv( "GOOGLE_CLOUD_CPP_GENERATOR_RUN_INTEGRATION_TESTS") .value_or(""); if (run_integration_tests != "yes") { GTEST_SKIP(); } EXPECT_EQ(run_integration_tests, "yes"); ASSERT_TRUE( google::cloud::internal::GetEnv("GOOGLE_CLOUD_CPP_GENERATOR_PROTO_PATH") .has_value()); ASSERT_TRUE(google::cloud::internal::GetEnv( "GOOGLE_CLOUD_CPP_GENERATOR_GOOGLEAPIS_PATH") .has_value()); // Path to find .proto files distributed with protobuf. auto proto_path = google::cloud::internal::GetEnv("GOOGLE_CLOUD_CPP_GENERATOR_PROTO_PATH") .value(); // Path to find .proto files distributed with googleapis/googleapis repo. auto googleapis_path = google::cloud::internal::GetEnv( "GOOGLE_CLOUD_CPP_GENERATOR_GOOGLEAPIS_PATH") .value(); // Path to find .proto files defined for these tests. auto code_path = google::cloud::internal::GetEnv("GOOGLE_CLOUD_CPP_GENERATOR_CODE_PATH") .value_or("/v"); golden_path_ = google::cloud::internal::GetEnv( "GOOGLE_CLOUD_CPP_GENERATOR_GOLDEN_PATH") .value_or("") + "generator/integration_tests/golden/"; // Path to location where generated code is written. output_path_ = google::cloud::internal::GetEnv( "GOOGLE_CLOUD_CPP_GENERATOR_OUTPUT_PATH") .value_or(::testing::TempDir()); google::cloud::generator::Generator generator; google::protobuf::compiler::CommandLineInterface cli; cli.RegisterGenerator("--cpp_codegen_out", "--cpp_codegen_opt", &generator, "Codegen C++ Generator"); product_path_ = "generator/integration_tests/golden/"; std::vector args; // empty arg keeps first real arg from being ignored. args.emplace_back(""); args.emplace_back("--proto_path=" + proto_path); args.emplace_back("--proto_path=" + googleapis_path); args.emplace_back("--proto_path=" + code_path); args.emplace_back("--cpp_codegen_out=" + output_path_); args.emplace_back("--cpp_codegen_opt=product_path=" + product_path_); args.emplace_back("generator/integration_tests/test.proto"); std::vector c_args; c_args.reserve(args.size()); for (auto const& arg : args) { std::cout << "args : " << arg << "\n"; c_args.push_back(arg.c_str()); } static int const kResult = cli.Run(static_cast(c_args.size()), c_args.data()); EXPECT_EQ(0, kResult); } std::string product_path_; std::string output_path_; std::string golden_path_; }; TEST_P(GeneratorIntegrationTest, CompareGeneratedToGolden) { auto golden_file = ReadFile(absl::StrCat(golden_path_, GetParam())); EXPECT_TRUE(golden_file.ok()); auto generated_file = ReadFile(absl::StrCat(output_path_, product_path_, GetParam())); EXPECT_TRUE(generated_file.ok()); EXPECT_EQ(golden_file->size(), generated_file->size()); for (unsigned int i = 0; i < golden_file->size(); ++i) { EXPECT_EQ((*golden_file)[i], (*generated_file)[i]); } } INSTANTIATE_TEST_SUITE_P( Generator, GeneratorIntegrationTest, testing::Values("connection_options.gcpcxx.pb.h", "connection_options.gcpcxx.pb.cc", "database_admin_client.gcpcxx.pb.h", "database_admin_client.gcpcxx.pb.cc", "database_admin_connection.gcpcxx.pb.h", "database_admin_connection.gcpcxx.pb.cc", "database_admin_connection_idempotency_policy.gcpcxx.pb.h", "database_admin_connection_idempotency_policy.gcpcxx.pb.cc", "internal/database_admin_logging_decorator.gcpcxx.pb.h", "internal/database_admin_logging_decorator.gcpcxx.pb.cc", "internal/database_admin_metadata_decorator.gcpcxx.pb.h", "internal/database_admin_metadata_decorator.gcpcxx.pb.cc", "internal/database_admin_stub_factory.gcpcxx.pb.h", "internal/database_admin_stub_factory.gcpcxx.pb.cc", "internal/database_admin_stub.gcpcxx.pb.h", "internal/database_admin_stub.gcpcxx.pb.cc", "mocks/mock_database_admin_connection.gcpcxx.pb.h", "retry_policy.gcpcxx.pb.h"), [](testing::TestParamInfo const& info) { return absl::StrReplaceAll(std::string(info.param), {{".", "_"}, {"/", "_"}}); }); } // namespace } // namespace generator_internal } // namespace cloud } // namespace google