aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/descriptor_database_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/descriptor_database_unittest.cc')
-rw-r--r--src/google/protobuf/descriptor_database_unittest.cc601
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