Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(generator): split DescriptorPoolFixture #10676

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions generator/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ cc_library(
":google_cloud_cpp_generator",
"//:common",
"//google/cloud/testing_util:google_cloud_cpp_testing_private",
"@com_google_googleapis//google/longrunning:longrunning_cc_proto",
"@com_google_googletest//:gtest_main",
"@com_google_protobuf//:protoc_lib",
],
Expand Down
11 changes: 8 additions & 3 deletions generator/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,19 @@ function (google_cloud_cpp_generator_define_tests)

add_library(
google_cloud_cpp_generator_testing # cmake-format: sort
testing/error_collectors.cc testing/error_collectors.h
testing/fake_source_tree.cc testing/fake_source_tree.h
testing/descriptor_pool_fixture.cc
testing/descriptor_pool_fixture.h
testing/error_collectors.cc
testing/error_collectors.h
testing/fake_source_tree.cc
testing/fake_source_tree.h
testing/printer_mocks.h)
google_cloud_cpp_add_common_options(google_cloud_cpp_generator_testing)
target_link_libraries(
google_cloud_cpp_generator_testing
PUBLIC google_cloud_cpp_testing GTest::gmock_main GTest::gmock
GTest::gtest protobuf::libprotoc)
GTest::gtest google-cloud-cpp::longrunning_operations_protos
protobuf::libprotoc)
create_bazel_config(google_cloud_cpp_generator_testing YEAR "2020")
target_include_directories(
google_cloud_cpp_generator_testing PUBLIC ${PROJECT_SOURCE_DIR}
Expand Down
2 changes: 2 additions & 0 deletions generator/google_cloud_cpp_generator_testing.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
"""Automatically generated source lists for google_cloud_cpp_generator_testing - DO NOT EDIT."""

google_cloud_cpp_generator_testing_hdrs = [
"testing/descriptor_pool_fixture.h",
"testing/error_collectors.h",
"testing/fake_source_tree.h",
"testing/printer_mocks.h",
]

google_cloud_cpp_generator_testing_srcs = [
"testing/descriptor_pool_fixture.cc",
"testing/error_collectors.cc",
"testing/fake_source_tree.cc",
]
94 changes: 4 additions & 90 deletions generator/internal/resolve_comment_references_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,56 +13,25 @@
// limitations under the License.

#include "generator/internal/resolve_comment_references.h"
#include "generator/testing/error_collectors.h"
#include "generator/testing/fake_source_tree.h"
#include "absl/memory/memory.h"
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor_database.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <google/protobuf/text_format.h>
#include "generator/testing/descriptor_pool_fixture.h"
#include <gmock/gmock.h>

namespace google {
namespace cloud {
namespace generator_internal {
namespace {

using ::google::cloud::generator_testing::FakeSourceTree;
using ::testing::Field;
using ::testing::NotNull;
using ::testing::Pair;

class ResolveCommentsReferenceTest : public ::testing::Test {
class ResolveCommentsReferenceTest
: public generator_testing::DescriptorPoolFixture {
public:
ResolveCommentsReferenceTest();

google::protobuf::FileDescriptor const* FindFile(
std::string const& name) const {
return pool_.FindFileByName(name);
}
bool AddProtoFile(std::string const& name, std::string contents) {
source_tree_.Insert(name, std::move(contents));
return pool_.FindFileByName(name) != nullptr;
}

google::protobuf::MethodDescriptor const* FindMethod(
std::string const& name) {
return pool_.FindMethodByName(name);
return pool().FindMethodByName(name);
}

google::protobuf::DescriptorPool const& pool() const { return pool_; }

private:
std::unique_ptr<google::protobuf::DescriptorPool::ErrorCollector>
descriptor_error_collector_;
std::unique_ptr<google::protobuf::compiler::MultiFileErrorCollector>
multifile_error_collector_;
FakeSourceTree source_tree_;
google::protobuf::SimpleDescriptorDatabase simple_db_;
google::protobuf::compiler::SourceTreeDescriptorDatabase source_tree_db_;
google::protobuf::MergedDescriptorDatabase merged_db_;
google::protobuf::DescriptorPool pool_;
};

TEST_F(ResolveCommentsReferenceTest, Multiple) {
Expand Down Expand Up @@ -318,61 +287,6 @@ service Service {
Field(&ProtoDefinitionLocation::filename, "test/v1/service.proto"))));
}

auto constexpr kLongrunningOperationsContents = R"""(
// This is a (extremely) simplified version of LRO support.
syntax = "proto3";
package google.longrunning;
import "google/protobuf/descriptor.proto";

extend google.protobuf.MethodOptions {
google.longrunning.OperationInfo operation_info = 1049;
}

message OperationInfo {
string response_type = 1;
string metadata_type = 2;
}

message Operation {
string name = 1;
}
)""";

auto constexpr kCommonFileContents = R"""(
// We need to test that our generator handles references to different entities.
// This simulated .proto file provides their definition.

syntax = "proto3";
package test.v1;

// A request type for the methods
message Request {}
// A response type for the methods
message Response {}
// A metadata type for some LROs
message Metadata {}
)""";

ResolveCommentsReferenceTest::ResolveCommentsReferenceTest()
: descriptor_error_collector_(
absl::make_unique<generator_testing::ErrorCollector>()),
multifile_error_collector_(
absl::make_unique<generator_testing::MultiFileErrorCollector>()),
source_tree_({
{"google/longrunning/operation.proto",
kLongrunningOperationsContents},
{"test/v1/common.proto", kCommonFileContents},
}),
source_tree_db_(&source_tree_),
merged_db_(&simple_db_, &source_tree_db_),
pool_(&merged_db_, descriptor_error_collector_.get()) {
source_tree_db_.RecordErrorsTo(multifile_error_collector_.get());
// We need the basic "descriptor" protos to be available.
google::protobuf::FileDescriptorProto proto;
google::protobuf::FileDescriptorProto::descriptor()->file()->CopyTo(&proto);
simple_db_.Add(proto);
}

} // namespace
} // namespace generator_internal
} // namespace cloud
Expand Down
89 changes: 89 additions & 0 deletions generator/testing/descriptor_pool_fixture.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2023 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
//
// https://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 "generator/testing/descriptor_pool_fixture.h"
#include "generator/testing/error_collectors.h"
#include "absl/memory/memory.h"
#include <google/api/annotations.pb.h>
#include <google/api/client.pb.h>
#include <google/longrunning/operations.pb.h>
#include <google/protobuf/any.pb.h>
#include <google/protobuf/duration.pb.h>
#include <google/protobuf/empty.pb.h>
#include <google/rpc/status.pb.h>

namespace google {
namespace cloud {
namespace generator_testing {

auto constexpr kEmptyFile = R"""(syntax = "proto3";)""";

auto constexpr kCommonFileContents = R"""(
// We need to test that our generator handles references to different entities.
// This simulated .proto file provides their definition.

syntax = "proto3";
package test.v1;

// A request type for the methods
message Request {}
// A response type for the methods
message Response {}
// A metadata type for some LROs
message Metadata {}
)""";

DescriptorPoolFixture::DescriptorPoolFixture()
: descriptor_error_collector_(
absl::make_unique<generator_testing::ErrorCollector>()),
multifile_error_collector_(
absl::make_unique<generator_testing::MultiFileErrorCollector>()),
source_tree_db_(&source_tree_),
merged_db_(&simple_db_, &source_tree_db_),
pool_(&merged_db_, descriptor_error_collector_.get()) {
source_tree_db_.RecordErrorsTo(multifile_error_collector_.get());
source_tree_.Insert("test/v1/common.proto", kCommonFileContents);
source_tree_.Insert("google/api/annotations.proto", kEmptyFile);
source_tree_.Insert("google/api/client.proto", kEmptyFile);

// We need google.longrunning.* to be available. This also imports the
// google.protobuf.*Descriptor protos.
for (auto const* descriptor : {
google::protobuf::FileDescriptorProto::descriptor(),
google::rpc::Status::descriptor(),
google::protobuf::Any::descriptor(),
google::protobuf::Duration::descriptor(),
google::protobuf::Empty::descriptor(),
google::longrunning::Operation::descriptor(),
}) {
google::protobuf::FileDescriptorProto proto;
descriptor->file()->CopyTo(&proto);
simple_db_.Add(proto);
}
}

google::protobuf::FileDescriptor const* DescriptorPoolFixture::FindFile(
std::string const& name) const {
return pool_.FindFileByName(name);
}

bool DescriptorPoolFixture::AddProtoFile(std::string const& name,
std::string contents) {
source_tree_.Insert(name, std::move(contents));
return pool_.FindFileByName(name) != nullptr;
}

} // namespace generator_testing
} // namespace cloud
} // namespace google
86 changes: 86 additions & 0 deletions generator/testing/descriptor_pool_fixture.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright 2023 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
//
// https://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.

#ifndef GOOGLE_CLOUD_CPP_GENERATOR_TESTING_DESCRIPTOR_POOL_FIXTURE_H
#define GOOGLE_CLOUD_CPP_GENERATOR_TESTING_DESCRIPTOR_POOL_FIXTURE_H

#include "generator/testing/fake_source_tree.h"
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor_database.h>
#include <gmock/gmock.h>

namespace google {
namespace cloud {
namespace generator_testing {

/**
* Implements a fixture for test using a `google::protobuf::DescriptorPool`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

optional: s/test using/testing with/ ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

*
* Some test need a properly initialized descriptor pool, with:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/test/tests/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

* - the basic protobuf types and options already available
* - connected to error collectors so the test fails with meaningful errors
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/connected to//

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

* if there is a test bug
* - basic Google features, like longrunning operations.
*
* This class provides all these features so we don't duplicate them across
* tests. It also provides helpers to add more (simulated) `.proto` files.
*/
class DescriptorPoolFixture : public ::testing::Test {
public:
DescriptorPoolFixture();

/**
* Returns the descriptor for a given file.
*
* Implicitly, this "compiles" the file and validates it. It can be used
* to verify the imports compile correctly before adding some other test
* proto contents.
*/
google::protobuf::FileDescriptor const* FindFile(
std::string const& name) const;

/**
* Adds a new proto file and "compiles" it.
*
* Typically used to set up the conditions of a test, as in:
*
* @code
* class MyTest : public DescriptorPoolFixture {};
*
* TEST_F(MyTest, Name) {
* ASSERT_TRUE(AddProtoFile("foo.proto", contents));
* }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: @endcode ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, fixed.

*/
bool AddProtoFile(std::string const& name, std::string contents);

google::protobuf::DescriptorPool const& pool() const { return pool_; }

private:
std::unique_ptr<google::protobuf::DescriptorPool::ErrorCollector>
descriptor_error_collector_;
std::unique_ptr<google::protobuf::compiler::MultiFileErrorCollector>
multifile_error_collector_;
FakeSourceTree source_tree_;
google::protobuf::SimpleDescriptorDatabase simple_db_;
google::protobuf::compiler::SourceTreeDescriptorDatabase source_tree_db_;
google::protobuf::MergedDescriptorDatabase merged_db_;
google::protobuf::DescriptorPool pool_;
};

} // namespace generator_testing
} // namespace cloud
} // namespace google

#endif // GOOGLE_CLOUD_CPP_GENERATOR_TESTING_DESCRIPTOR_POOL_FIXTURE_H
1 change: 1 addition & 0 deletions generator/testing/fake_source_tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ namespace generator_testing {

class FakeSourceTree : public google::protobuf::compiler::SourceTree {
public:
FakeSourceTree() = default;
explicit FakeSourceTree(std::map<std::string, std::string> files);

void Insert(std::string const& filename, std::string contents);
Expand Down