aboutsummaryrefslogtreecommitdiff
path: root/src/google/protobuf/descriptor_unittest.cc
diff options
context:
space:
mode:
authorAdam Cozzette <acozzette@google.com>2016-11-17 16:48:38 -0800
committerAdam Cozzette <acozzette@google.com>2016-11-17 16:59:59 -0800
commit5a76e633ea9b5adb215e93fdc11e1c0c08b3fc74 (patch)
tree0276f81f8848a05d84cd7e287b43d665e30f04e3 /src/google/protobuf/descriptor_unittest.cc
parente28286fa05d8327fd6c5aa70cfb3be558f0932b8 (diff)
downloadprotobuf-5a76e633ea9b5adb215e93fdc11e1c0c08b3fc74.tar.gz
protobuf-5a76e633ea9b5adb215e93fdc11e1c0c08b3fc74.tar.bz2
protobuf-5a76e633ea9b5adb215e93fdc11e1c0c08b3fc74.zip
Integrated internal changes from Google
Diffstat (limited to 'src/google/protobuf/descriptor_unittest.cc')
-rw-r--r--src/google/protobuf/descriptor_unittest.cc160
1 files changed, 151 insertions, 9 deletions
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index f6b3f1c5..7ec75156 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -41,8 +41,11 @@
#include <vector>
#include <google/protobuf/compiler/importer.h>
+#include <google/protobuf/compiler/parser.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/unittest_custom_options.pb.h>
+#include <google/protobuf/unittest_proto3_arena.pb.h>
+#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
@@ -55,6 +58,7 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
@@ -488,6 +492,65 @@ TEST_F(FileDescriptorTest, Syntax) {
}
}
+void ExtractDebugString(
+ const FileDescriptor* file, std::set<string>* visited,
+ std::vector<std::pair<string, string> >* debug_strings) {
+ if (!visited->insert(file->name()).second) {
+ return;
+ }
+ for (int i = 0; i < file->dependency_count(); ++i) {
+ ExtractDebugString(file->dependency(i), visited, debug_strings);
+ }
+ debug_strings->push_back(make_pair(file->name(), file->DebugString()));
+}
+
+class SimpleErrorCollector : public google::protobuf::io::ErrorCollector {
+ public:
+ // implements ErrorCollector ---------------------------------------
+ void AddError(int line, int column, const string& message) {
+ last_error_ = StringPrintf("%d:%d:", line, column) + message;
+ }
+
+ const string& last_error() { return last_error_; }
+
+ private:
+ string last_error_;
+};
+// Test that the result of FileDescriptor::DebugString() can be used to create
+// the original descriptors.
+TEST_F(FileDescriptorTest, DebugStringRoundTrip) {
+ std::set<string> visited;
+ std::vector<std::pair<string, string> > debug_strings;
+ ExtractDebugString(protobuf_unittest::TestAllTypes::descriptor()->file(),
+ &visited, &debug_strings);
+ ExtractDebugString(
+ protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file(),
+ &visited, &debug_strings);
+ ExtractDebugString(proto3_arena_unittest::TestAllTypes::descriptor()->file(),
+ &visited, &debug_strings);
+ ASSERT_GE(debug_strings.size(), 3);
+
+ DescriptorPool pool;
+ for (int i = 0; i < debug_strings.size(); ++i) {
+ const string& name = debug_strings[i].first;
+ const string& content = debug_strings[i].second;
+ google::protobuf::io::ArrayInputStream input_stream(content.data(), content.size());
+ SimpleErrorCollector error_collector;
+ google::protobuf::io::Tokenizer tokenizer(&input_stream, &error_collector);
+ google::protobuf::compiler::Parser parser;
+ parser.RecordErrorsTo(&error_collector);
+ FileDescriptorProto proto;
+ ASSERT_TRUE(parser.Parse(&tokenizer, &proto))
+ << error_collector.last_error() << "\n"
+ << content;
+ ASSERT_EQ("", error_collector.last_error());
+ proto.set_name(name);
+ const FileDescriptor* descriptor = pool.BuildFile(proto);
+ ASSERT_TRUE(descriptor != NULL) << proto.DebugString();
+ EXPECT_EQ(content, descriptor->DebugString());
+ }
+}
+
// ===================================================================
// Test simple flat messages and fields.
@@ -1861,7 +1924,7 @@ TEST_F(ExtensionDescriptorTest, FindExtensionByName) {
}
TEST_F(ExtensionDescriptorTest, FindAllExtensions) {
- vector<const FieldDescriptor*> extensions;
+ std::vector<const FieldDescriptor*> extensions;
pool_.FindAllExtensions(foo_, &extensions);
ASSERT_EQ(4, extensions.size());
EXPECT_EQ(10, extensions[0]->number());
@@ -2625,7 +2688,7 @@ TEST_P(AllowUnknownDependenciesTest, CustomOption) {
// Verify that no extension options were set, but they were left as
// uninterpreted_options.
- vector<const FieldDescriptor*> fields;
+ std::vector<const FieldDescriptor*> fields;
file->options().GetReflection()->ListFields(file->options(), &fields);
ASSERT_EQ(2, fields.size());
EXPECT_TRUE(file->options().has_optimize_for());
@@ -3276,6 +3339,85 @@ TEST(CustomOptions, OptionsWithRequiredEnums) {
EXPECT_EQ(protobuf_unittest::NewOptionType::NEW_VALUE, new_enum_opt.value());
}
+// Test that FileDescriptor::DebugString() formats custom options correctly.
+TEST(CustomOptions, DebugString) {
+ DescriptorPool pool;
+
+ FileDescriptorProto file_proto;
+ MessageOptions::descriptor()->file()->CopyTo(&file_proto);
+ ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+
+ // Add "foo.proto":
+ // import "google/protobuf/descriptor.proto";
+ // package "protobuf_unittest";
+ // option (protobuf_unittest.cc_option1) = 1;
+ // option (protobuf_unittest.cc_option2) = 2;
+ // extend google.protobuf.FieldOptions {
+ // optional int32 cc_option1 = 7736974;
+ // optional int32 cc_option2 = 7736975;
+ // }
+ ASSERT_TRUE(TextFormat::ParseFromString(
+ "name: \"foo.proto\" "
+ "package: \"protobuf_unittest\" "
+ "dependency: \"google/protobuf/descriptor.proto\" "
+ "options { "
+ " uninterpreted_option { "
+ " name { "
+ " name_part: \"protobuf_unittest.cc_option1\" "
+ " is_extension: true "
+ " } "
+ " positive_int_value: 1 "
+ " } "
+ " uninterpreted_option { "
+ " name { "
+ " name_part: \"protobuf_unittest.cc_option2\" "
+ " is_extension: true "
+ " } "
+ " positive_int_value: 2 "
+ " } "
+ "} "
+ "extension { "
+ " name: \"cc_option1\" "
+ " extendee: \".google.protobuf.FileOptions\" "
+ // This field number is intentionally chosen to be the same as
+ // (.fileopt1) defined in unittest_custom_options.proto (linked
+ // in this test binary). This is to test whether we are messing
+ // generated pool with custom descriptor pools when dealing with
+ // custom options.
+ " number: 7736974 "
+ " label: LABEL_OPTIONAL "
+ " type: TYPE_INT32 "
+ "}"
+ "extension { "
+ " name: \"cc_option2\" "
+ " extendee: \".google.protobuf.FileOptions\" "
+ " number: 7736975 "
+ " label: LABEL_OPTIONAL "
+ " type: TYPE_INT32 "
+ "}",
+ &file_proto));
+ const FileDescriptor* descriptor = pool.BuildFile(file_proto);
+ ASSERT_TRUE(descriptor != NULL);
+
+ EXPECT_EQ(2, descriptor->extension_count());
+
+ ASSERT_EQ(
+ "syntax = \"proto2\";\n"
+ "\n"
+ "import \"google/protobuf/descriptor.proto\";\n"
+ "package protobuf_unittest;\n"
+ "\n"
+ "option (.protobuf_unittest.cc_option1) = 1;\n"
+ "option (.protobuf_unittest.cc_option2) = 2;\n"
+ "\n"
+ "extend .google.protobuf.FileOptions {\n"
+ " optional int32 cc_option1 = 7736974;\n"
+ " optional int32 cc_option2 = 7736975;\n"
+ "}\n"
+ "\n",
+ descriptor->DebugString());
+}
+
// ===================================================================
class ValidationErrorTest : public testing::Test {
@@ -5169,7 +5311,7 @@ TEST_F(ValidationErrorTest, ErrorsReportedToLogError) {
"message_type { name: \"Foo\" } ",
&file_proto));
- vector<string> errors;
+ std::vector<string> errors;
{
ScopedMemoryLog log;
@@ -5598,8 +5740,8 @@ TEST_F(ValidationErrorTest, EnumValuesConflictWhenPrefixesStripped) {
"}",
"foo.proto: BAR__BAZ: NAME: When enum name is stripped and label is "
"PascalCased (BarBaz), this value label conflicts with "
- "FOO_ENUM_BAR_BAZ. This "
- "will make the proto fail to compile for some languages, such as C#.\n");
+ "FOO_ENUM_BAR_BAZ. This will make the proto fail to compile for some "
+ "languages, such as C#.\n");
BuildFileWithErrors(
"syntax: 'proto3'"
@@ -5611,8 +5753,8 @@ TEST_F(ValidationErrorTest, EnumValuesConflictWhenPrefixesStripped) {
"}",
"foo.proto: BAR_BAZ: NAME: When enum name is stripped and label is "
"PascalCased (BarBaz), this value label conflicts with "
- "FOO_ENUM__BAR_BAZ. This "
- "will make the proto fail to compile for some languages, such as C#.\n");
+ "FOO_ENUM__BAR_BAZ. This will make the proto fail to compile for some "
+ "languages, such as C#.\n");
// This isn't an error because the underscore will cause the PascalCase to
// differ by case (BarBaz vs. Barbaz).
@@ -6159,7 +6301,7 @@ TEST_F(DatabaseBackedPoolTest, FindAllExtensions) {
for (int i = 0; i < 2; ++i) {
// Repeat the lookup twice, to check that we get consistent
// results despite the fallback database lookup mutating the pool.
- vector<const FieldDescriptor*> extensions;
+ std::vector<const FieldDescriptor*> extensions;
pool.FindAllExtensions(foo, &extensions);
ASSERT_EQ(1, extensions.size());
EXPECT_EQ(5, extensions[0]->number());
@@ -6170,7 +6312,7 @@ TEST_F(DatabaseBackedPoolTest, ErrorWithoutErrorCollector) {
ErrorDescriptorDatabase error_database;
DescriptorPool pool(&error_database);
- vector<string> errors;
+ std::vector<string> errors;
{
ScopedMemoryLog log;