diff options
Diffstat (limited to 'src/google/protobuf/descriptor_database_unittest.cc')
-rw-r--r-- | src/google/protobuf/descriptor_database_unittest.cc | 601 |
1 files changed, 601 insertions, 0 deletions
diff --git a/src/google/protobuf/descriptor_database_unittest.cc b/src/google/protobuf/descriptor_database_unittest.cc new file mode 100644 index 00000000..cbbf5927 --- /dev/null +++ b/src/google/protobuf/descriptor_database_unittest.cc @@ -0,0 +1,601 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file makes extensive use of RFC 3092. :) + +#include <google/protobuf/descriptor_database.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/text_format.h> +#include <google/protobuf/stubs/strutil.h> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/testing/googletest.h> +#include <gtest/gtest.h> + +namespace google { +namespace protobuf { +namespace { + +static bool AddToPool(DescriptorPool* pool, const char* file_text) { + FileDescriptorProto file_proto; + if (!TextFormat::ParseFromString(file_text, &file_proto)) return false; + if (pool->BuildFile(file_proto) == NULL) return false; + return true; +} + +static void AddToDatabase(SimpleDescriptorDatabase* database, + const char* file_text) { + FileDescriptorProto file_proto; + EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto)); + database->Add(file_proto); +} + +static void ExpectContainsType(const FileDescriptorProto& proto, + const string& type_name) { + for (int i = 0; i < proto.message_type_size(); i++) { + if (proto.message_type(i).name() == type_name) return; + } + ADD_FAILURE() << "\"" << proto.name() + << "\" did not contain expected type \"" + << type_name << "\"."; +} + +// =================================================================== + +TEST(SimpleDescriptorDatabaseTest, FindFileByName) { + SimpleDescriptorDatabase database; + AddToDatabase(&database, + "name: \"foo.proto\" " + "message_type { name:\"Foo\" }"); + AddToDatabase(&database, + "name: \"bar.proto\" " + "message_type { name:\"Bar\" }"); + + { + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileByName("foo.proto", &file)); + EXPECT_EQ("foo.proto", file.name()); + ExpectContainsType(file, "Foo"); + } + + { + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileByName("bar.proto", &file)); + EXPECT_EQ("bar.proto", file.name()); + ExpectContainsType(file, "Bar"); + } + + { + // Fails to find undefined files. + FileDescriptorProto file; + EXPECT_FALSE(database.FindFileByName("baz.proto", &file)); + } +} + +TEST(SimpleDescriptorDatabaseTest, FindFileContainingSymbol) { + SimpleDescriptorDatabase database; + AddToDatabase(&database, + "name: \"foo.proto\" " + "message_type { " + " name: \"Foo\" " + " field { name:\"qux\" }" + " nested_type { name: \"Grault\" } " + " enum_type { name: \"Garply\" } " + "} " + "enum_type { " + " name: \"Waldo\" " + " value { name:\"FRED\" } " + "} " + "extension { name: \"plugh\" } " + "service { " + " name: \"Xyzzy\" " + " method { name: \"Thud\" } " + "}" + ); + AddToDatabase(&database, + "name: \"bar.proto\" " + "package: \"corge\" " + "message_type { name: \"Bar\" }"); + + { + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileContainingSymbol("Foo", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find fields. + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileContainingSymbol("Foo.qux", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find nested types. + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileContainingSymbol("Foo.Grault", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find nested enums. + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileContainingSymbol("Foo.Garply", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find enum types. + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileContainingSymbol("Waldo", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find enum values. + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileContainingSymbol("Waldo.FRED", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find extensions. + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileContainingSymbol("plugh", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find services. + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileContainingSymbol("Xyzzy", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find methods. + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileContainingSymbol("Xyzzy.Thud", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find things in packages. + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileContainingSymbol("corge.Bar", &file)); + EXPECT_EQ("bar.proto", file.name()); + } + + { + // Fails to find undefined symbols. + FileDescriptorProto file; + EXPECT_FALSE(database.FindFileContainingSymbol("Baz", &file)); + } + + { + // Names must be fully-qualified. + FileDescriptorProto file; + EXPECT_FALSE(database.FindFileContainingSymbol("Bar", &file)); + } +} + +TEST(SimpleDescriptorDatabaseTest, FindFileContainingExtension) { + SimpleDescriptorDatabase database; + AddToDatabase(&database, + "name: \"foo.proto\" " + "message_type { " + " name: \"Foo\" " + " extension_range { start: 1 end: 1000 } " + " extension { name:\"qux\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 " + " extendee: \".Foo\" }" + "}"); + AddToDatabase(&database, + "name: \"bar.proto\" " + "package: \"corge\" " + "dependency: \"foo.proto\" " + "message_type { " + " name: \"Bar\" " + " extension_range { start: 1 end: 1000 } " + "} " + "extension { name:\"grault\" extendee: \".Foo\" number:32 } " + "extension { name:\"garply\" extendee: \".corge.Bar\" number:70 } " + "extension { name:\"waldo\" extendee: \"Bar\" number:56 } "); + + { + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileContainingExtension("Foo", 5, &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileContainingExtension("Foo", 32, &file)); + EXPECT_EQ("bar.proto", file.name()); + } + + { + // Can find extensions for qualified type names. + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileContainingExtension("corge.Bar", 70, &file)); + EXPECT_EQ("bar.proto", file.name()); + } + + { + // Can't find extensions whose extendee was not fully-qualified in the + // FileDescriptorProto. + FileDescriptorProto file; + EXPECT_FALSE(database.FindFileContainingExtension("Bar", 56, &file)); + EXPECT_FALSE(database.FindFileContainingExtension("corge.Bar", 56, &file)); + } + + { + // Can't find non-existent extension numbers. + FileDescriptorProto file; + EXPECT_FALSE(database.FindFileContainingExtension("Foo", 12, &file)); + } + + { + // Can't find extensions for non-existent types. + FileDescriptorProto file; + EXPECT_FALSE(database.FindFileContainingExtension("NoSuchType", 5, &file)); + } + + { + // Can't find extensions for unqualified type names. + FileDescriptorProto file; + EXPECT_FALSE(database.FindFileContainingExtension("Bar", 70, &file)); + } +} + +// =================================================================== + +TEST(DescriptorPoolDatabaseTest, FindFileByName) { + DescriptorPool pool; + ASSERT_TRUE(AddToPool(&pool, + "name: \"foo.proto\" " + "message_type { name:\"Foo\" }")); + ASSERT_TRUE(AddToPool(&pool, + "name: \"bar.proto\" " + "message_type { name:\"Bar\" }")); + + DescriptorPoolDatabase database(pool); + + { + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileByName("foo.proto", &file)); + EXPECT_EQ("foo.proto", file.name()); + ExpectContainsType(file, "Foo"); + } + + { + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileByName("bar.proto", &file)); + EXPECT_EQ("bar.proto", file.name()); + ExpectContainsType(file, "Bar"); + } + + { + // Fails to find undefined files. + FileDescriptorProto file; + EXPECT_FALSE(database.FindFileByName("baz.proto", &file)); + } +} + +TEST(DescriptorPoolDatabaseTest, FindFileContainingSymbol) { + DescriptorPool pool; + ASSERT_TRUE(AddToPool(&pool, + "name: \"foo.proto\" " + "message_type { " + " name: \"Foo\" " + " field { name:\"qux\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }" + "}")); + ASSERT_TRUE(AddToPool(&pool, + "name: \"bar.proto\" " + "package: \"corge\" " + "message_type { name: \"Bar\" }")); + + DescriptorPoolDatabase database(pool); + + { + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileContainingSymbol("Foo", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find fields. + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileContainingSymbol("Foo.qux", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find things in packages. + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileContainingSymbol("corge.Bar", &file)); + EXPECT_EQ("bar.proto", file.name()); + } + + { + // Fails to find undefined symbols. + FileDescriptorProto file; + EXPECT_FALSE(database.FindFileContainingSymbol("Baz", &file)); + } + + { + // Names must be fully-qualified. + FileDescriptorProto file; + EXPECT_FALSE(database.FindFileContainingSymbol("Bar", &file)); + } +} + +TEST(DescriptorPoolDatabaseTest, FindFileContainingExtension) { + DescriptorPool pool; + ASSERT_TRUE(AddToPool(&pool, + "name: \"foo.proto\" " + "message_type { " + " name: \"Foo\" " + " extension_range { start: 1 end: 1000 } " + " extension { name:\"qux\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 " + " extendee: \"Foo\" }" + "}")); + ASSERT_TRUE(AddToPool(&pool, + "name: \"bar.proto\" " + "package: \"corge\" " + "dependency: \"foo.proto\" " + "message_type { " + " name: \"Bar\" " + " extension_range { start: 1 end: 1000 } " + "} " + "extension { name:\"grault\" label:LABEL_OPTIONAL type:TYPE_BOOL number:32 " + " extendee: \"Foo\" } " + "extension { name:\"garply\" label:LABEL_OPTIONAL type:TYPE_BOOL number:70 " + " extendee: \"Bar\" } ")); + + DescriptorPoolDatabase database(pool); + + { + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileContainingExtension("Foo", 5, &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileContainingExtension("Foo", 32, &file)); + EXPECT_EQ("bar.proto", file.name()); + } + + { + // Can find extensions for qualified type names.. + FileDescriptorProto file; + EXPECT_TRUE(database.FindFileContainingExtension("corge.Bar", 70, &file)); + EXPECT_EQ("bar.proto", file.name()); + } + + { + // Can't find non-existent extension numbers. + FileDescriptorProto file; + EXPECT_FALSE(database.FindFileContainingExtension("Foo", 12, &file)); + } + + { + // Can't find extensions for non-existent types. + FileDescriptorProto file; + EXPECT_FALSE(database.FindFileContainingExtension("NoSuchType", 5, &file)); + } + + { + // Can't find extensions for unqualified type names. + FileDescriptorProto file; + EXPECT_FALSE(database.FindFileContainingExtension("Bar", 70, &file)); + } +} + +// =================================================================== + +class MergedDescriptorDatabaseTest : public testing::Test { + protected: + MergedDescriptorDatabaseTest() + : forward_merged_(&database1_, &database2_), + reverse_merged_(&database2_, &database1_) {} + + virtual void SetUp() { + AddToDatabase(&database1_, + "name: \"foo.proto\" " + "message_type { name:\"Foo\" extension_range { start: 1 end: 100 } } " + "extension { name:\"foo_ext\" extendee: \".Foo\" number:3 " + " label:LABEL_OPTIONAL type:TYPE_INT32 } "); + AddToDatabase(&database2_, + "name: \"bar.proto\" " + "message_type { name:\"Bar\" extension_range { start: 1 end: 100 } } " + "extension { name:\"bar_ext\" extendee: \".Bar\" number:5 " + " label:LABEL_OPTIONAL type:TYPE_INT32 } "); + + // baz.proto exists in both pools, with different definitions. + AddToDatabase(&database1_, + "name: \"baz.proto\" " + "message_type { name:\"Baz\" extension_range { start: 1 end: 100 } } " + "message_type { name:\"FromPool1\" } " + "extension { name:\"baz_ext\" extendee: \".Baz\" number:12 " + " label:LABEL_OPTIONAL type:TYPE_INT32 } " + "extension { name:\"database1_only_ext\" extendee: \".Baz\" number:13 " + " label:LABEL_OPTIONAL type:TYPE_INT32 } "); + AddToDatabase(&database2_, + "name: \"baz.proto\" " + "message_type { name:\"Baz\" extension_range { start: 1 end: 100 } } " + "message_type { name:\"FromPool2\" } " + "extension { name:\"baz_ext\" extendee: \".Baz\" number:12 " + " label:LABEL_OPTIONAL type:TYPE_INT32 } "); + } + + SimpleDescriptorDatabase database1_; + SimpleDescriptorDatabase database2_; + + MergedDescriptorDatabase forward_merged_; + MergedDescriptorDatabase reverse_merged_; +}; + +TEST_F(MergedDescriptorDatabaseTest, FindFileByName) { + { + // Can find file that is only in database1_. + FileDescriptorProto file; + EXPECT_TRUE(forward_merged_.FindFileByName("foo.proto", &file)); + EXPECT_EQ("foo.proto", file.name()); + ExpectContainsType(file, "Foo"); + } + + { + // Can find file that is only in database2_. + FileDescriptorProto file; + EXPECT_TRUE(forward_merged_.FindFileByName("bar.proto", &file)); + EXPECT_EQ("bar.proto", file.name()); + ExpectContainsType(file, "Bar"); + } + + { + // In forward_merged_, database1_'s baz.proto takes precedence. + FileDescriptorProto file; + EXPECT_TRUE(forward_merged_.FindFileByName("baz.proto", &file)); + EXPECT_EQ("baz.proto", file.name()); + ExpectContainsType(file, "FromPool1"); + } + + { + // In reverse_merged_, database2_'s baz.proto takes precedence. + FileDescriptorProto file; + EXPECT_TRUE(reverse_merged_.FindFileByName("baz.proto", &file)); + EXPECT_EQ("baz.proto", file.name()); + ExpectContainsType(file, "FromPool2"); + } + + { + // Can't find non-existent file. + FileDescriptorProto file; + EXPECT_FALSE(forward_merged_.FindFileByName("no_such.proto", &file)); + } +} + +TEST_F(MergedDescriptorDatabaseTest, FindFileContainingSymbol) { + { + // Can find file that is only in database1_. + FileDescriptorProto file; + EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("Foo", &file)); + EXPECT_EQ("foo.proto", file.name()); + ExpectContainsType(file, "Foo"); + } + + { + // Can find file that is only in database2_. + FileDescriptorProto file; + EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("Bar", &file)); + EXPECT_EQ("bar.proto", file.name()); + ExpectContainsType(file, "Bar"); + } + + { + // In forward_merged_, database1_'s baz.proto takes precedence. + FileDescriptorProto file; + EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("Baz", &file)); + EXPECT_EQ("baz.proto", file.name()); + ExpectContainsType(file, "FromPool1"); + } + + { + // In reverse_merged_, database2_'s baz.proto takes precedence. + FileDescriptorProto file; + EXPECT_TRUE(reverse_merged_.FindFileContainingSymbol("Baz", &file)); + EXPECT_EQ("baz.proto", file.name()); + ExpectContainsType(file, "FromPool2"); + } + + { + // FromPool1 only shows up in forward_merged_ because it is masked by + // database2_'s baz.proto in reverse_merged_. + FileDescriptorProto file; + EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("FromPool1", &file)); + EXPECT_FALSE(reverse_merged_.FindFileContainingSymbol("FromPool1", &file)); + } + + { + // Can't find non-existent symbol. + FileDescriptorProto file; + EXPECT_FALSE( + forward_merged_.FindFileContainingSymbol("NoSuchType", &file)); + } +} + +TEST_F(MergedDescriptorDatabaseTest, FindFileContainingExtension) { + { + // Can find file that is only in database1_. + FileDescriptorProto file; + EXPECT_TRUE( + forward_merged_.FindFileContainingExtension("Foo", 3, &file)); + EXPECT_EQ("foo.proto", file.name()); + ExpectContainsType(file, "Foo"); + } + + { + // Can find file that is only in database2_. + FileDescriptorProto file; + EXPECT_TRUE( + forward_merged_.FindFileContainingExtension("Bar", 5, &file)); + EXPECT_EQ("bar.proto", file.name()); + ExpectContainsType(file, "Bar"); + } + + { + // In forward_merged_, database1_'s baz.proto takes precedence. + FileDescriptorProto file; + EXPECT_TRUE( + forward_merged_.FindFileContainingExtension("Baz", 12, &file)); + EXPECT_EQ("baz.proto", file.name()); + ExpectContainsType(file, "FromPool1"); + } + + { + // In reverse_merged_, database2_'s baz.proto takes precedence. + FileDescriptorProto file; + EXPECT_TRUE( + reverse_merged_.FindFileContainingExtension("Baz", 12, &file)); + EXPECT_EQ("baz.proto", file.name()); + ExpectContainsType(file, "FromPool2"); + } + + { + // Baz's extension 13 only shows up in forward_merged_ because it is + // masked by database2_'s baz.proto in reverse_merged_. + FileDescriptorProto file; + EXPECT_TRUE(forward_merged_.FindFileContainingExtension("Baz", 13, &file)); + EXPECT_FALSE(reverse_merged_.FindFileContainingExtension("Baz", 13, &file)); + } + + { + // Can't find non-existent extension. + FileDescriptorProto file; + EXPECT_FALSE( + forward_merged_.FindFileContainingExtension("Foo", 6, &file)); + } +} + +} // anonymous namespace +} // namespace protobuf +} // namespace google |