aboutsummaryrefslogtreecommitdiffstats
path: root/src/google/protobuf/compiler/parser_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/compiler/parser_unittest.cc')
-rw-r--r--src/google/protobuf/compiler/parser_unittest.cc1372
1 files changed, 8 insertions, 1364 deletions
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index 9ec29a4..e2262b8 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -1,6 +1,6 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
+// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -32,10 +32,8 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-#include <memory>
#include <vector>
#include <algorithm>
-#include <map>
#include <google/protobuf/compiler/parser.h>
@@ -45,10 +43,8 @@
#include <google/protobuf/wire_format.h>
#include <google/protobuf/text_format.h>
#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/unittest_custom_options.pb.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
@@ -122,9 +118,6 @@ class ParserTest : public testing::Test {
EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
ASSERT_EQ("", error_collector_.text_);
- // We don't cover SourceCodeInfo in these tests.
- actual.clear_source_code_info();
-
// Parse the ASCII representation in order to canonicalize it. We could
// just compare directly to actual.DebugString(), but that would require
// that the caller precisely match the formatting that DebugString()
@@ -437,69 +430,6 @@ TEST_F(ParseMessageTest, FieldOptions) {
"}");
}
-TEST_F(ParseMessageTest, Oneof) {
- ExpectParsesTo(
- "message TestMessage {\n"
- " oneof foo {\n"
- " int32 a = 1;\n"
- " string b = 2;\n"
- " TestMessage c = 3;\n"
- " group D = 4 { optional int32 i = 5; }\n"
- " }\n"
- "}\n",
-
- "message_type {"
- " name: \"TestMessage\""
- " field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 "
- " oneof_index:0 }"
- " field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 "
- " oneof_index:0 }"
- " field { name:\"c\" label:LABEL_OPTIONAL type_name:\"TestMessage\" "
- " number:3 oneof_index:0 }"
- " field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_GROUP "
- " type_name:\"D\" number:4 oneof_index:0 }"
- " oneof_decl {"
- " name: \"foo\""
- " }"
- " nested_type {"
- " name: \"D\""
- " field { name:\"i\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 }"
- " }"
- "}");
-}
-
-TEST_F(ParseMessageTest, MultipleOneofs) {
- ExpectParsesTo(
- "message TestMessage {\n"
- " oneof foo {\n"
- " int32 a = 1;\n"
- " string b = 2;\n"
- " }\n"
- " oneof bar {\n"
- " int32 c = 3;\n"
- " string d = 4;\n"
- " }\n"
- "}\n",
-
- "message_type {"
- " name: \"TestMessage\""
- " field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 "
- " oneof_index:0 }"
- " field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 "
- " oneof_index:0 }"
- " field { name:\"c\" label:LABEL_OPTIONAL type:TYPE_INT32 number:3 "
- " oneof_index:1 }"
- " field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_STRING number:4 "
- " oneof_index:1 }"
- " oneof_decl {"
- " name: \"foo\""
- " }"
- " oneof_decl {"
- " name: \"bar\""
- " }"
- "}");
-}
-
TEST_F(ParseMessageTest, Group) {
ExpectParsesTo(
"message TestMessage {\n"
@@ -574,31 +504,6 @@ TEST_F(ParseMessageTest, CompoundExtensionRange) {
"}");
}
-TEST_F(ParseMessageTest, LargerMaxForMessageSetWireFormatMessages) {
- // Messages using the message_set_wire_format option can accept larger
- // extension numbers, as the numbers are not encoded as int32 field values
- // rather than tags.
- ExpectParsesTo(
- "message TestMessage {\n"
- " extensions 4 to max;\n"
- " option message_set_wire_format = true;\n"
- "}\n",
-
- "message_type {"
- " name: \"TestMessage\""
- " extension_range { start:4 end: 0x7fffffff }"
- " options {\n"
- " uninterpreted_option { \n"
- " name {\n"
- " name_part: \"message_set_wire_format\"\n"
- " is_extension: false\n"
- " }\n"
- " identifier_value: \"true\"\n"
- " }\n"
- " }\n"
- "}");
-}
-
TEST_F(ParseMessageTest, Extensions) {
ExpectParsesTo(
"extend Extendee1 { optional int32 foo = 12; }\n"
@@ -639,7 +544,6 @@ TEST_F(ParseMessageTest, MultipleExtensionsOneExtendee) {
" type_name:\"TestMessage\" extendee: \"Extendee1\" }");
}
-
// ===================================================================
typedef ParserTest ParseEnumTest;
@@ -662,10 +566,6 @@ TEST_F(ParseEnumTest, Values) {
" FOO = 13;\n"
" BAR = -10;\n"
" BAZ = 500;\n"
- " HEX_MAX = 0x7FFFFFFF;\n"
- " HEX_MIN = -0x80000000;\n"
- " INT_MAX = 2147483647;\n"
- " INT_MIN = -2147483648;\n"
"}\n",
"enum_type {"
@@ -673,10 +573,6 @@ TEST_F(ParseEnumTest, Values) {
" value { name:\"FOO\" number:13 }"
" value { name:\"BAR\" number:-10 }"
" value { name:\"BAZ\" number:500 }"
- " value { name:\"HEX_MAX\" number:2147483647 }"
- " value { name:\"HEX_MIN\" number:-2147483648 }"
- " value { name:\"INT_MAX\" number:2147483647 }"
- " value { name:\"INT_MIN\" number:-2147483648 }"
"}");
}
@@ -730,7 +626,7 @@ TEST_F(ParseServiceTest, SimpleService) {
"}");
}
-TEST_F(ParseServiceTest, MethodsAndStreams) {
+TEST_F(ParseServiceTest, Methods) {
ExpectParsesTo(
"service TestService {\n"
" rpc Foo(In1) returns (Out1);\n"
@@ -746,8 +642,6 @@ TEST_F(ParseServiceTest, MethodsAndStreams) {
"}");
}
-
-
// ===================================================================
// imports and packages
@@ -769,20 +663,6 @@ TEST_F(ParseMiscTest, ParseMultipleImports) {
"dependency: \"baz.proto\"");
}
-TEST_F(ParseMiscTest, ParsePublicImports) {
- ExpectParsesTo(
- "import \"foo.proto\";\n"
- "import public \"bar.proto\";\n"
- "import \"baz.proto\";\n"
- "import public \"qux.proto\";\n",
- "dependency: \"foo.proto\""
- "dependency: \"bar.proto\""
- "dependency: \"baz.proto\""
- "dependency: \"qux.proto\""
- "public_dependency: 1 "
- "public_dependency: 3 ");
-}
-
TEST_F(ParseMiscTest, ParsePackage) {
ExpectParsesTo(
"package foo.bar.baz;\n",
@@ -937,7 +817,7 @@ TEST_F(ParseErrorTest, DefaultValueTypeMismatch) {
"message TestMessage {\n"
" optional uint32 foo = 1 [default=true];\n"
"}\n",
- "1:35: Expected integer for field default value.\n");
+ "1:35: Expected integer.\n");
}
TEST_F(ParseErrorTest, DefaultValueNotBoolean) {
@@ -953,7 +833,7 @@ TEST_F(ParseErrorTest, DefaultValueNotString) {
"message TestMessage {\n"
" optional string foo = 1 [default=1];\n"
"}\n",
- "1:35: Expected string for field default value.\n");
+ "1:35: Expected string.\n");
}
TEST_F(ParseErrorTest, DefaultValueUnsignedNegative) {
@@ -982,26 +862,12 @@ TEST_F(ParseErrorTest, DefaultValueTooLarge) {
"6:36: Integer out of range.\n");
}
-TEST_F(ParseErrorTest, EnumValueOutOfRange) {
- ExpectHasErrors(
- "enum TestEnum {\n"
- " HEX_TOO_BIG = 0x80000000;\n"
- " HEX_TOO_SMALL = -0x80000001;\n"
- " INT_TOO_BIG = 2147483648;\n"
- " INT_TOO_SMALL = -2147483649;\n"
- "}\n",
- "1:19: Integer out of range.\n"
- "2:19: Integer out of range.\n"
- "3:19: Integer out of range.\n"
- "4:19: Integer out of range.\n");
-}
-
TEST_F(ParseErrorTest, DefaultValueMissing) {
ExpectHasErrors(
"message TestMessage {\n"
" optional uint32 foo = 1 [default=];\n"
"}\n",
- "1:35: Expected integer for field default value.\n");
+ "1:35: Expected integer.\n");
}
TEST_F(ParseErrorTest, DefaultValueForGroup) {
@@ -1020,27 +886,6 @@ TEST_F(ParseErrorTest, DuplicateDefaultValue) {
"1:37: Already set option \"default\".\n");
}
-TEST_F(ParseErrorTest, MissingOneofName) {
- ExpectHasErrors(
- "message TestMessage {\n"
- " oneof {\n"
- " int32 bar = 1;\n"
- " }\n"
- "}\n",
- "1:8: Expected oneof name.\n");
-}
-
-TEST_F(ParseErrorTest, LabelInOneof) {
- ExpectHasErrors(
- "message TestMessage {\n"
- " oneof foo {\n"
- " optional int32 bar = 1;\n"
- " }\n"
- "}\n",
- "2:4: Fields in oneofs must not have labels (required / optional "
- "/ repeated).\n");
-}
-
TEST_F(ParseErrorTest, GroupNotCapitalized) {
ExpectHasErrors(
"message TestMessage {\n"
@@ -1085,12 +930,6 @@ TEST_F(ParseErrorTest, MultipleParseErrors) {
"3:25: Expected \";\".\n");
}
-TEST_F(ParseErrorTest, EofInAggregateValue) {
- ExpectHasErrors(
- "option (fileopt) = { i:100\n",
- "1:0: Unexpected end of stream while parsing aggregate value.\n");
-}
-
// -------------------------------------------------------------------
// Enum errors
@@ -1126,7 +965,6 @@ TEST_F(ParseErrorTest, ServiceMethodPrimitiveParams) {
"1:26: Expected message type.\n");
}
-
TEST_F(ParseErrorTest, EofInMethodOptions) {
ExpectHasErrors(
"service TestService {\n"
@@ -1135,7 +973,6 @@ TEST_F(ParseErrorTest, EofInMethodOptions) {
"1:29: Reached end of input in service definition (missing '}').\n");
}
-
TEST_F(ParseErrorTest, PrimitiveMethodInput) {
ExpectHasErrors(
"service TestService {\n"
@@ -1144,7 +981,6 @@ TEST_F(ParseErrorTest, PrimitiveMethodInput) {
"1:10: Expected message type.\n");
}
-
TEST_F(ParseErrorTest, MethodOptionTypeError) {
// This used to cause an infinite loop.
ExpectHasErrors(
@@ -1155,7 +991,6 @@ TEST_F(ParseErrorTest, MethodOptionTypeError) {
"2:45: Expected \"=\".\n");
}
-
// -------------------------------------------------------------------
// Import and package errors
@@ -1311,7 +1146,6 @@ TEST_F(ParserValidationErrorTest, MethodNameError) {
"3:6: \"Bar\" is already defined in \"Foo\".\n");
}
-
TEST_F(ParserValidationErrorTest, MethodInputTypeError) {
ExpectHasValidationErrors(
"message Baz {}\n"
@@ -1321,7 +1155,6 @@ TEST_F(ParserValidationErrorTest, MethodInputTypeError) {
"2:10: \"Qux\" is not defined.\n");
}
-
TEST_F(ParserValidationErrorTest, MethodOutputTypeError) {
ExpectHasValidationErrors(
"message Baz {}\n"
@@ -1331,94 +1164,17 @@ TEST_F(ParserValidationErrorTest, MethodOutputTypeError) {
"2:23: \"Qux\" is not defined.\n");
}
-
-TEST_F(ParserValidationErrorTest, ResovledUndefinedError) {
- // Create another file which defines symbol ".base.bar".
- FileDescriptorProto other_file;
- other_file.set_name("base.proto");
- other_file.set_package("base");
- other_file.add_message_type()->set_name("bar");
- EXPECT_TRUE(pool_.BuildFile(other_file) != NULL);
-
- // Define "foo.base" and try "base.bar".
- // "base.bar" is resolved to "foo.base.bar" which is not defined.
- ExpectHasValidationErrors(
- "package foo.base;\n"
- "import \"base.proto\";\n"
- "message qux {\n"
- " optional base.bar baz = 1;\n"
- " optional .base.bar quz = 2;\n"
- "}\n",
- "3:11: \"base.bar\" is resolved to \"foo.base.bar\","
- " which is not defined. The innermost scope is searched first "
- "in name resolution. Consider using a leading '.'(i.e., \".base.bar\")"
- " to start from the outermost scope.\n");
-}
-
-TEST_F(ParserValidationErrorTest, ResovledUndefinedOptionError) {
- // Build descriptor message in test pool
- FileDescriptorProto descriptor_proto;
- DescriptorProto::descriptor()->file()->CopyTo(&descriptor_proto);
- ASSERT_TRUE(pool_.BuildFile(descriptor_proto) != NULL);
-
- // base2.proto:
- // package baz
- // import google/protobuf/descriptor.proto
- // message Bar { optional int32 foo = 1; }
- // extend FileOptions { optional Bar bar = 7672757; }
- FileDescriptorProto other_file;
- other_file.set_name("base2.proto");
- other_file.set_package("baz");
- other_file.add_dependency();
- other_file.set_dependency(0, descriptor_proto.name());
-
- DescriptorProto* message(other_file.add_message_type());
- message->set_name("Bar");
- FieldDescriptorProto* field(message->add_field());
- field->set_name("foo");
- field->set_number(1);
- field->set_label(FieldDescriptorProto_Label_LABEL_OPTIONAL);
- field->set_type(FieldDescriptorProto_Type_TYPE_INT32);
-
- FieldDescriptorProto* extension(other_file.add_extension());
- extension->set_name("bar");
- extension->set_number(7672757);
- extension->set_label(FieldDescriptorProto_Label_LABEL_OPTIONAL);
- extension->set_type(FieldDescriptorProto_Type_TYPE_MESSAGE);
- extension->set_type_name("Bar");
- extension->set_extendee("google.protobuf.FileOptions");
-
- EXPECT_TRUE(pool_.BuildFile(other_file) != NULL);
-
- // qux.proto:
- // package qux.baz
- // option (baz.bar).foo = 1;
- //
- // Although "baz.bar" is already defined, the lookup code will try
- // "qux.baz.bar", since it's the match from the innermost scope,
- // which will cause a symbol not defined error.
- ExpectHasValidationErrors(
- "package qux.baz;\n"
- "import \"base2.proto\";\n"
- "option (baz.bar).foo = 1;\n",
- "2:7: Option \"(baz.bar)\" is resolved to \"(qux.baz.bar)\","
- " which is not defined. The innermost scope is searched first "
- "in name resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\")"
- " to start from the outermost scope.\n");
-}
-
// ===================================================================
// Test that the output from FileDescriptor::DebugString() (and all other
// descriptor types) is parseable, and results in the same Descriptor
-// definitions again afoter parsing (note, however, that the order of messages
+// definitions again afoter parsing (not, however, that the order of messages
// cannot be guaranteed to be the same)
typedef ParserTest ParseDecriptorDebugTest;
class CompareDescriptorNames {
public:
- bool operator()(const DescriptorProto* left,
- const DescriptorProto* right) const {
+ bool operator()(const DescriptorProto* left, const DescriptorProto* right) {
return left->name() < right->name();
}
};
@@ -1462,19 +1218,13 @@ TEST_F(ParseDecriptorDebugTest, TestAllDescriptorTypes) {
FileDescriptorProto parsed;
parser_->Parse(input_.get(), &parsed);
EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
- ASSERT_EQ("", error_collector_.text_)
- << "Failed to parse:\n" << debug_string;
+ ASSERT_EQ("", error_collector_.text_);
// We now have a FileDescriptorProto, but to compare with the expected we
// need to link to a FileDecriptor, then output back to a proto. We'll
// also need to give it the same name as the original.
parsed.set_name("google/protobuf/unittest.proto");
// We need the imported dependency before we can build our parsed proto
- const FileDescriptor* public_import =
- protobuf_unittest_import::PublicImportMessage::descriptor()->file();
- FileDescriptorProto public_import_proto;
- public_import->CopyTo(&public_import_proto);
- ASSERT_TRUE(pool_.BuildFile(public_import_proto) != NULL);
const FileDescriptor* import =
protobuf_unittest_import::ImportMessage::descriptor()->file();
FileDescriptorProto import_proto;
@@ -1482,8 +1232,6 @@ TEST_F(ParseDecriptorDebugTest, TestAllDescriptorTypes) {
ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL);
const FileDescriptor* actual = pool_.BuildFile(parsed);
parsed.Clear();
- ASSERT_TRUE(actual != NULL)
- << "Failed to validate:\n" << debug_string;
actual->CopyTo(&parsed);
ASSERT_TRUE(actual != NULL);
@@ -1499,1110 +1247,6 @@ TEST_F(ParseDecriptorDebugTest, TestAllDescriptorTypes) {
EXPECT_EQ(expected.DebugString(), parsed.DebugString());
}
-TEST_F(ParseDecriptorDebugTest, TestCustomOptions) {
- const FileDescriptor* original_file =
- protobuf_unittest::AggregateMessage::descriptor()->file();
- FileDescriptorProto expected;
- original_file->CopyTo(&expected);
-
- string debug_string = original_file->DebugString();
-
- // Parse the debug string
- SetupParser(debug_string.c_str());
- FileDescriptorProto parsed;
- parser_->Parse(input_.get(), &parsed);
- EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
- ASSERT_EQ("", error_collector_.text_);
-
- // We now have a FileDescriptorProto, but to compare with the expected we
- // need to link to a FileDecriptor, then output back to a proto. We'll
- // also need to give it the same name as the original.
- parsed.set_name(original_file->name());
-
- // unittest_custom_options.proto depends on descriptor.proto.
- const FileDescriptor* import = FileDescriptorProto::descriptor()->file();
- FileDescriptorProto import_proto;
- import->CopyTo(&import_proto);
- ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL);
- const FileDescriptor* actual = pool_.BuildFile(parsed);
- ASSERT_TRUE(actual != NULL);
- parsed.Clear();
- actual->CopyTo(&parsed);
-
- // The messages might be in different orders, making them hard to compare.
- // So, sort the messages in the descriptor protos (including nested messages,
- // recursively).
- SortMessages(&expected);
- SortMessages(&parsed);
-
- EXPECT_EQ(expected.DebugString(), parsed.DebugString());
-}
-
-// ===================================================================
-// SourceCodeInfo tests.
-
-// Follows a path -- as defined by SourceCodeInfo.Location.path -- from a
-// message to a particular sub-field.
-// * If the target is itself a message, sets *output_message to point at it,
-// *output_field to NULL, and *output_index to -1.
-// * Otherwise, if the target is an element of a repeated field, sets
-// *output_message to the containing message, *output_field to the descriptor
-// of the field, and *output_index to the index of the element.
-// * Otherwise, the target is a field (possibly a repeated field, but not any
-// one element). Sets *output_message to the containing message,
-// *output_field to the descriptor of the field, and *output_index to -1.
-// Returns true if the path was valid, false otherwise. A gTest failure is
-// recorded before returning false.
-bool FollowPath(const Message& root,
- const int* path_begin, const int* path_end,
- const Message** output_message,
- const FieldDescriptor** output_field,
- int* output_index) {
- if (path_begin == path_end) {
- // Path refers to this whole message.
- *output_message = &root;
- *output_field = NULL;
- *output_index = -1;
- return true;
- }
-
- const Descriptor* descriptor = root.GetDescriptor();
- const Reflection* reflection = root.GetReflection();
-
- const FieldDescriptor* field = descriptor->FindFieldByNumber(*path_begin);
-
- if (field == NULL) {
- ADD_FAILURE() << descriptor->name() << " has no field number: "
- << *path_begin;
- return false;
- }
-
- ++path_begin;
-
- if (field->is_repeated()) {
- if (path_begin == path_end) {
- // Path refers to the whole repeated field.
- *output_message = &root;
- *output_field = field;
- *output_index = -1;
- return true;
- }
-
- int index = *path_begin++;
- int size = reflection->FieldSize(root, field);
-
- if (index >= size) {
- ADD_FAILURE() << descriptor->name() << "." << field->name()
- << " has size " << size << ", but path contained index: "
- << index;
- return false;
- }
-
- if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
- // Descend into child message.
- const Message& child = reflection->GetRepeatedMessage(root, field, index);
- return FollowPath(child, path_begin, path_end,
- output_message, output_field, output_index);
- } else if (path_begin == path_end) {
- // Path refers to this element.
- *output_message = &root;
- *output_field = field;
- *output_index = index;
- return true;
- } else {
- ADD_FAILURE() << descriptor->name() << "." << field->name()
- << " is not a message; cannot descend into it.";
- return false;
- }
- } else {
- if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
- const Message& child = reflection->GetMessage(root, field);
- return FollowPath(child, path_begin, path_end,
- output_message, output_field, output_index);
- } else if (path_begin == path_end) {
- // Path refers to this field.
- *output_message = &root;
- *output_field = field;
- *output_index = -1;
- return true;
- } else {
- ADD_FAILURE() << descriptor->name() << "." << field->name()
- << " is not a message; cannot descend into it.";
- return false;
- }
- }
-}
-
-// Check if two spans are equal.
-bool CompareSpans(const RepeatedField<int>& span1,
- const RepeatedField<int>& span2) {
- if (span1.size() != span2.size()) return false;
- for (int i = 0; i < span1.size(); i++) {
- if (span1.Get(i) != span2.Get(i)) return false;
- }
- return true;
-}
-
-// Test fixture for source info tests, which check that source locations are
-// recorded correctly in FileDescriptorProto.source_code_info.location.
-class SourceInfoTest : public ParserTest {
- protected:
- // The parsed file (initialized by Parse()).
- FileDescriptorProto file_;
-
- // Parse the given text as a .proto file and populate the spans_ map with
- // all the source location spans in its SourceCodeInfo table.
- bool Parse(const char* text) {
- ExtractMarkers(text);
- SetupParser(text_without_markers_.c_str());
- if (!parser_->Parse(input_.get(), &file_)) {
- return false;
- }
-
- const SourceCodeInfo& source_info = file_.source_code_info();
- for (int i = 0; i < source_info.location_size(); i++) {
- const SourceCodeInfo::Location& location = source_info.location(i);
- const Message* descriptor_proto = NULL;
- const FieldDescriptor* field = NULL;
- int index = 0;
- if (!FollowPath(file_, location.path().begin(), location.path().end(),
- &descriptor_proto, &field, &index)) {
- return false;
- }
-
- spans_.insert(make_pair(SpanKey(*descriptor_proto, field, index),
- &location));
- }
-
- return true;
- }
-
- virtual void TearDown() {
- EXPECT_TRUE(spans_.empty())
- << "Forgot to call HasSpan() for:\n"
- << spans_.begin()->second->DebugString();
- }
-
- // -----------------------------------------------------------------
- // HasSpan() checks that the span of source code delimited by the given
- // tags (comments) correspond via the SourceCodeInfo table to the given
- // part of the FileDescriptorProto. (If unclear, look at the actual tests;
- // it should quickly become obvious.)
-
- bool HasSpan(char start_marker, char end_marker,
- const Message& descriptor_proto) {
- return HasSpanWithComment(
- start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL);
- }
-
- bool HasSpanWithComment(char start_marker, char end_marker,
- const Message& descriptor_proto,
- const char* expected_leading_comments,
- const char* expected_trailing_comments) {
- return HasSpanWithComment(
- start_marker, end_marker, descriptor_proto, NULL, -1,
- expected_leading_comments, expected_trailing_comments);
- }
-
- bool HasSpan(char start_marker, char end_marker,
- const Message& descriptor_proto, const string& field_name) {
- return HasSpan(start_marker, end_marker, descriptor_proto, field_name, -1);
- }
-
- bool HasSpan(char start_marker, char end_marker,
- const Message& descriptor_proto, const string& field_name,
- int index) {
- return HasSpan(start_marker, end_marker, descriptor_proto,
- field_name, index, NULL, NULL);
- }
-
- bool HasSpan(char start_marker, char end_marker,
- const Message& descriptor_proto,
- const string& field_name, int index,
- const char* expected_leading_comments,
- const char* expected_trailing_comments) {
- const FieldDescriptor* field =
- descriptor_proto.GetDescriptor()->FindFieldByName(field_name);
- if (field == NULL) {
- ADD_FAILURE() << descriptor_proto.GetDescriptor()->name()
- << " has no such field: " << field_name;
- return false;
- }
-
- return HasSpanWithComment(
- start_marker, end_marker, descriptor_proto, field, index,
- expected_leading_comments, expected_trailing_comments);
- }
-
- bool HasSpan(const Message& descriptor_proto) {
- return HasSpanWithComment(
- '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL);
- }
-
- bool HasSpan(const Message& descriptor_proto, const string& field_name) {
- return HasSpan('\0', '\0', descriptor_proto, field_name, -1);
- }
-
- bool HasSpan(const Message& descriptor_proto, const string& field_name,
- int index) {
- return HasSpan('\0', '\0', descriptor_proto, field_name, index);
- }
-
- bool HasSpanWithComment(char start_marker, char end_marker,
- const Message& descriptor_proto,
- const FieldDescriptor* field, int index,
- const char* expected_leading_comments,
- const char* expected_trailing_comments) {
- pair<SpanMap::iterator, SpanMap::iterator> range =
- spans_.equal_range(SpanKey(descriptor_proto, field, index));
-
- if (start_marker == '\0') {
- if (range.first == range.second) {
- return false;
- } else {
- spans_.erase(range.first);
- return true;
- }
- } else {
- pair<int, int> start_pos = FindOrDie(markers_, start_marker);
- pair<int, int> end_pos = FindOrDie(markers_, end_marker);
-
- RepeatedField<int> expected_span;
- expected_span.Add(start_pos.first);
- expected_span.Add(start_pos.second);
- if (end_pos.first != start_pos.first) {
- expected_span.Add(end_pos.first);
- }
- expected_span.Add(end_pos.second);
-
- for (SpanMap::iterator iter = range.first; iter != range.second; ++iter) {
- if (CompareSpans(expected_span, iter->second->span())) {
- if (expected_leading_comments == NULL) {
- EXPECT_FALSE(iter->second->has_leading_comments());
- } else {
- EXPECT_TRUE(iter->second->has_leading_comments());
- EXPECT_EQ(expected_leading_comments,
- iter->second->leading_comments());
- }
- if (expected_trailing_comments == NULL) {
- EXPECT_FALSE(iter->second->has_trailing_comments());
- } else {
- EXPECT_TRUE(iter->second->has_trailing_comments());
- EXPECT_EQ(expected_trailing_comments,
- iter->second->trailing_comments());
- }
-
- spans_.erase(iter);
- return true;
- }
- }
-
- return false;
- }
- }
-
- private:
- struct SpanKey {
- const Message* descriptor_proto;
- const FieldDescriptor* field;
- int index;
-
- inline SpanKey() {}
- inline SpanKey(const Message& descriptor_proto_param,
- const FieldDescriptor* field_param,
- int index_param)
- : descriptor_proto(&descriptor_proto_param), field(field_param),
- index(index_param) {}
-
- inline bool operator<(const SpanKey& other) const {
- if (descriptor_proto < other.descriptor_proto) return true;
- if (descriptor_proto > other.descriptor_proto) return false;
- if (field < other.field) return true;
- if (field > other.field) return false;
- return index < other.index;
- }
- };
-
- typedef multimap<SpanKey, const SourceCodeInfo::Location*> SpanMap;
- SpanMap spans_;
- map<char, pair<int, int> > markers_;
- string text_without_markers_;
-
- void ExtractMarkers(const char* text) {
- markers_.clear();
- text_without_markers_.clear();
- int line = 0;
- int column = 0;
- while (*text != '\0') {
- if (*text == '$') {
- ++text;
- GOOGLE_CHECK_NE('\0', *text);
- if (*text == '$') {
- text_without_markers_ += '$';
- ++column;
- } else {
- markers_[*text] = make_pair(line, column);
- ++text;
- GOOGLE_CHECK_EQ('$', *text);
- }
- } else if (*text == '\n') {
- ++line;
- column = 0;
- text_without_markers_ += *text;
- } else {
- text_without_markers_ += *text;
- ++column;
- }
- ++text;
- }
- }
-};
-
-TEST_F(SourceInfoTest, BasicFileDecls) {
- EXPECT_TRUE(Parse(
- "$a$syntax = \"proto2\";\n"
- "package $b$foo.bar$c$;\n"
- "import $d$\"baz.proto\"$e$;\n"
- "import $f$\"qux.proto\"$g$;$h$\n"
- "\n"
- "// comment ignored\n"));
-
- EXPECT_TRUE(HasSpan('a', 'h', file_));
- EXPECT_TRUE(HasSpan('b', 'c', file_, "package"));
- EXPECT_TRUE(HasSpan('d', 'e', file_, "dependency", 0));
- EXPECT_TRUE(HasSpan('f', 'g', file_, "dependency", 1));
-}
-
-TEST_F(SourceInfoTest, Messages) {
- EXPECT_TRUE(Parse(
- "$a$message $b$Foo$c$ {}$d$\n"
- "$e$message $f$Bar$g$ {}$h$\n"));
-
- EXPECT_TRUE(HasSpan('a', 'd', file_.message_type(0)));
- EXPECT_TRUE(HasSpan('b', 'c', file_.message_type(0), "name"));
- EXPECT_TRUE(HasSpan('e', 'h', file_.message_type(1)));
- EXPECT_TRUE(HasSpan('f', 'g', file_.message_type(1), "name"));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
-}
-
-TEST_F(SourceInfoTest, Fields) {
- EXPECT_TRUE(Parse(
- "message Foo {\n"
- " $a$optional$b$ $c$int32$d$ $e$bar$f$ = $g$1$h$;$i$\n"
- " $j$repeated$k$ $l$X.Y$m$ $n$baz$o$ = $p$2$q$;$r$\n"
- "}\n"));
-
- const FieldDescriptorProto& field1 = file_.message_type(0).field(0);
- const FieldDescriptorProto& field2 = file_.message_type(0).field(1);
-
- EXPECT_TRUE(HasSpan('a', 'i', field1));
- EXPECT_TRUE(HasSpan('a', 'b', field1, "label"));
- EXPECT_TRUE(HasSpan('c', 'd', field1, "type"));
- EXPECT_TRUE(HasSpan('e', 'f', field1, "name"));
- EXPECT_TRUE(HasSpan('g', 'h', field1, "number"));
-
- EXPECT_TRUE(HasSpan('j', 'r', field2));
- EXPECT_TRUE(HasSpan('j', 'k', field2, "label"));
- EXPECT_TRUE(HasSpan('l', 'm', field2, "type_name"));
- EXPECT_TRUE(HasSpan('n', 'o', field2, "name"));
- EXPECT_TRUE(HasSpan('p', 'q', field2, "number"));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
- EXPECT_TRUE(HasSpan(file_.message_type(0)));
- EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
-}
-
-TEST_F(SourceInfoTest, Extensions) {
- EXPECT_TRUE(Parse(
- "$a$extend $b$Foo$c$ {\n"
- " $d$optional$e$ int32 bar = 1;$f$\n"
- " $g$repeated$h$ X.Y baz = 2;$i$\n"
- "}$j$\n"
- "$k$extend $l$Bar$m$ {\n"
- " $n$optional int32 qux = 1;$o$\n"
- "}$p$\n"));
-
- const FieldDescriptorProto& field1 = file_.extension(0);
- const FieldDescriptorProto& field2 = file_.extension(1);
- const FieldDescriptorProto& field3 = file_.extension(2);
-
- EXPECT_TRUE(HasSpan('a', 'j', file_, "extension"));
- EXPECT_TRUE(HasSpan('k', 'p', file_, "extension"));
-
- EXPECT_TRUE(HasSpan('d', 'f', field1));
- EXPECT_TRUE(HasSpan('d', 'e', field1, "label"));
- EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee"));
-
- EXPECT_TRUE(HasSpan('g', 'i', field2));
- EXPECT_TRUE(HasSpan('g', 'h', field2, "label"));
- EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee"));
-
- EXPECT_TRUE(HasSpan('n', 'o', field3));
- EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee"));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
- EXPECT_TRUE(HasSpan(field1, "type"));
- EXPECT_TRUE(HasSpan(field1, "name"));
- EXPECT_TRUE(HasSpan(field1, "number"));
- EXPECT_TRUE(HasSpan(field2, "type_name"));
- EXPECT_TRUE(HasSpan(field2, "name"));
- EXPECT_TRUE(HasSpan(field2, "number"));
- EXPECT_TRUE(HasSpan(field3, "label"));
- EXPECT_TRUE(HasSpan(field3, "type"));
- EXPECT_TRUE(HasSpan(field3, "name"));
- EXPECT_TRUE(HasSpan(field3, "number"));
-}
-
-TEST_F(SourceInfoTest, NestedExtensions) {
- EXPECT_TRUE(Parse(
- "message Message {\n"
- " $a$extend $b$Foo$c$ {\n"
- " $d$optional$e$ int32 bar = 1;$f$\n"
- " $g$repeated$h$ X.Y baz = 2;$i$\n"
- " }$j$\n"
- " $k$extend $l$Bar$m$ {\n"
- " $n$optional int32 qux = 1;$o$\n"
- " }$p$\n"
- "}\n"));
-
- const FieldDescriptorProto& field1 = file_.message_type(0).extension(0);
- const FieldDescriptorProto& field2 = file_.message_type(0).extension(1);
- const FieldDescriptorProto& field3 = file_.message_type(0).extension(2);
-
- EXPECT_TRUE(HasSpan('a', 'j', file_.message_type(0), "extension"));
- EXPECT_TRUE(HasSpan('k', 'p', file_.message_type(0), "extension"));
-
- EXPECT_TRUE(HasSpan('d', 'f', field1));
- EXPECT_TRUE(HasSpan('d', 'e', field1, "label"));
- EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee"));
-
- EXPECT_TRUE(HasSpan('g', 'i', field2));
- EXPECT_TRUE(HasSpan('g', 'h', field2, "label"));
- EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee"));
-
- EXPECT_TRUE(HasSpan('n', 'o', field3));
- EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee"));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
- EXPECT_TRUE(HasSpan(file_.message_type(0)));
- EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
- EXPECT_TRUE(HasSpan(field1, "type"));
- EXPECT_TRUE(HasSpan(field1, "name"));
- EXPECT_TRUE(HasSpan(field1, "number"));
- EXPECT_TRUE(HasSpan(field2, "type_name"));
- EXPECT_TRUE(HasSpan(field2, "name"));
- EXPECT_TRUE(HasSpan(field2, "number"));
- EXPECT_TRUE(HasSpan(field3, "label"));
- EXPECT_TRUE(HasSpan(field3, "type"));
- EXPECT_TRUE(HasSpan(field3, "name"));
- EXPECT_TRUE(HasSpan(field3, "number"));
-}
-
-TEST_F(SourceInfoTest, ExtensionRanges) {
- EXPECT_TRUE(Parse(
- "message Message {\n"
- " $a$extensions $b$1$c$ to $d$4$e$, $f$6$g$;$h$\n"
- " $i$extensions $j$8$k$ to $l$max$m$;$n$\n"
- "}\n"));
-
- const DescriptorProto::ExtensionRange& range1 =
- file_.message_type(0).extension_range(0);
- const DescriptorProto::ExtensionRange& range2 =
- file_.message_type(0).extension_range(1);
- const DescriptorProto::ExtensionRange& range3 =
- file_.message_type(0).extension_range(2);
-
- EXPECT_TRUE(HasSpan('a', 'h', file_.message_type(0), "extension_range"));
- EXPECT_TRUE(HasSpan('i', 'n', file_.message_type(0), "extension_range"));
-
- EXPECT_TRUE(HasSpan('b', 'e', range1));
- EXPECT_TRUE(HasSpan('b', 'c', range1, "start"));
- EXPECT_TRUE(HasSpan('d', 'e', range1, "end"));
-
- EXPECT_TRUE(HasSpan('f', 'g', range2));
- EXPECT_TRUE(HasSpan('f', 'g', range2, "start"));
- EXPECT_TRUE(HasSpan('f', 'g', range2, "end"));
-
- EXPECT_TRUE(HasSpan('j', 'm', range3));
- EXPECT_TRUE(HasSpan('j', 'k', range3, "start"));
- EXPECT_TRUE(HasSpan('l', 'm', range3, "end"));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
- EXPECT_TRUE(HasSpan(file_.message_type(0)));
- EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
-}
-
-TEST_F(SourceInfoTest, Oneofs) {
- EXPECT_TRUE(Parse(
- "message Foo {\n"
- " $a$oneof $c$foo$d$ {\n"
- " $e$int32$f$ $g$a$h$ = $i$1$j$;$k$\n"
- " }$r$\n"
- "}\n"));
-
- const OneofDescriptorProto& oneof_decl = file_.message_type(0).oneof_decl(0);
- const FieldDescriptorProto& field = file_.message_type(0).field(0);
-
- EXPECT_TRUE(HasSpan('a', 'r', oneof_decl));
- EXPECT_TRUE(HasSpan('c', 'd', oneof_decl, "name"));
-
- EXPECT_TRUE(HasSpan('e', 'k', field));
- EXPECT_TRUE(HasSpan('e', 'f', field, "type"));
- EXPECT_TRUE(HasSpan('g', 'h', field, "name"));
- EXPECT_TRUE(HasSpan('i', 'j', field, "number"));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
- EXPECT_TRUE(HasSpan(file_.message_type(0)));
- EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
-}
-
-TEST_F(SourceInfoTest, NestedMessages) {
- EXPECT_TRUE(Parse(
- "message Foo {\n"
- " $a$message $b$Bar$c$ {\n"
- " $d$message $e$Baz$f$ {}$g$\n"
- " }$h$\n"
- " $i$message $j$Qux$k$ {}$l$\n"
- "}\n"));
-
- const DescriptorProto& bar = file_.message_type(0).nested_type(0);
- const DescriptorProto& baz = bar.nested_type(0);
- const DescriptorProto& qux = file_.message_type(0).nested_type(1);
-
- EXPECT_TRUE(HasSpan('a', 'h', bar));
- EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
- EXPECT_TRUE(HasSpan('d', 'g', baz));
- EXPECT_TRUE(HasSpan('e', 'f', baz, "name"));
- EXPECT_TRUE(HasSpan('i', 'l', qux));
- EXPECT_TRUE(HasSpan('j', 'k', qux, "name"));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
- EXPECT_TRUE(HasSpan(file_.message_type(0)));
- EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
-}
-
-TEST_F(SourceInfoTest, Groups) {
- EXPECT_TRUE(Parse(
- "message Foo {\n"
- " message Bar {}\n"
- " $a$optional$b$ $c$group$d$ $e$Baz$f$ = $g$1$h$ {\n"
- " $i$message Qux {}$j$\n"
- " }$k$\n"
- "}\n"));
-
- const DescriptorProto& bar = file_.message_type(0).nested_type(0);
- const DescriptorProto& baz = file_.message_type(0).nested_type(1);
- const DescriptorProto& qux = baz.nested_type(0);
- const FieldDescriptorProto& field = file_.message_type(0).field(0);
-
- EXPECT_TRUE(HasSpan('a', 'k', field));
- EXPECT_TRUE(HasSpan('a', 'b', field, "label"));
- EXPECT_TRUE(HasSpan('c', 'd', field, "type"));
- EXPECT_TRUE(HasSpan('e', 'f', field, "name"));
- EXPECT_TRUE(HasSpan('e', 'f', field, "type_name"));
- EXPECT_TRUE(HasSpan('g', 'h', field, "number"));
-
- EXPECT_TRUE(HasSpan('a', 'k', baz));
- EXPECT_TRUE(HasSpan('e', 'f', baz, "name"));
- EXPECT_TRUE(HasSpan('i', 'j', qux));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
- EXPECT_TRUE(HasSpan(file_.message_type(0)));
- EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
- EXPECT_TRUE(HasSpan(bar));
- EXPECT_TRUE(HasSpan(bar, "name"));
- EXPECT_TRUE(HasSpan(qux, "name"));
-}
-
-TEST_F(SourceInfoTest, Enums) {
- EXPECT_TRUE(Parse(
- "$a$enum $b$Foo$c$ {}$d$\n"
- "$e$enum $f$Bar$g$ {}$h$\n"));
-
- EXPECT_TRUE(HasSpan('a', 'd', file_.enum_type(0)));
- EXPECT_TRUE(HasSpan('b', 'c', file_.enum_type(0), "name"));
- EXPECT_TRUE(HasSpan('e', 'h', file_.enum_type(1)));
- EXPECT_TRUE(HasSpan('f', 'g', file_.enum_type(1), "name"));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
-}
-
-TEST_F(SourceInfoTest, EnumValues) {
- EXPECT_TRUE(Parse(
- "enum Foo {\n"
- " $a$BAR$b$ = $c$1$d$;$e$\n"
- " $f$BAZ$g$ = $h$2$i$;$j$\n"
- "}"));
-
- const EnumValueDescriptorProto& bar = file_.enum_type(0).value(0);
- const EnumValueDescriptorProto& baz = file_.enum_type(0).value(1);
-
- EXPECT_TRUE(HasSpan('a', 'e', bar));
- EXPECT_TRUE(HasSpan('a', 'b', bar, "name"));
- EXPECT_TRUE(HasSpan('c', 'd', bar, "number"));
- EXPECT_TRUE(HasSpan('f', 'j', baz));
- EXPECT_TRUE(HasSpan('f', 'g', baz, "name"));
- EXPECT_TRUE(HasSpan('h', 'i', baz, "number"));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
- EXPECT_TRUE(HasSpan(file_.enum_type(0)));
- EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
-}
-
-TEST_F(SourceInfoTest, NestedEnums) {
- EXPECT_TRUE(Parse(
- "message Foo {\n"
- " $a$enum $b$Bar$c$ {}$d$\n"
- " $e$enum $f$Baz$g$ {}$h$\n"
- "}\n"));
-
- const EnumDescriptorProto& bar = file_.message_type(0).enum_type(0);
- const EnumDescriptorProto& baz = file_.message_type(0).enum_type(1);
-
- EXPECT_TRUE(HasSpan('a', 'd', bar));
- EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
- EXPECT_TRUE(HasSpan('e', 'h', baz));
- EXPECT_TRUE(HasSpan('f', 'g', baz, "name"));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
- EXPECT_TRUE(HasSpan(file_.message_type(0)));
- EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
-}
-
-TEST_F(SourceInfoTest, Services) {
- EXPECT_TRUE(Parse(
- "$a$service $b$Foo$c$ {}$d$\n"
- "$e$service $f$Bar$g$ {}$h$\n"));
-
- EXPECT_TRUE(HasSpan('a', 'd', file_.service(0)));
- EXPECT_TRUE(HasSpan('b', 'c', file_.service(0), "name"));
- EXPECT_TRUE(HasSpan('e', 'h', file_.service(1)));
- EXPECT_TRUE(HasSpan('f', 'g', file_.service(1), "name"));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
-}
-
-TEST_F(SourceInfoTest, MethodsAndStreams) {
- EXPECT_TRUE(Parse(
- "service Foo {\n"
- " $a$rpc $b$Bar$c$($d$X$e$) returns($f$Y$g$);$h$"
- " $i$rpc $j$Baz$k$($l$Z$m$) returns($n$W$o$);$p$"
- "}"));
-
- const MethodDescriptorProto& bar = file_.service(0).method(0);
- const MethodDescriptorProto& baz = file_.service(0).method(1);
-
- EXPECT_TRUE(HasSpan('a', 'h', bar));
- EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
- EXPECT_TRUE(HasSpan('d', 'e', bar, "input_type"));
- EXPECT_TRUE(HasSpan('f', 'g', bar, "output_type"));
-
- EXPECT_TRUE(HasSpan('i', 'p', baz));
- EXPECT_TRUE(HasSpan('j', 'k', baz, "name"));
- EXPECT_TRUE(HasSpan('l', 'm', baz, "input_type"));
- EXPECT_TRUE(HasSpan('n', 'o', baz, "output_type"));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
- EXPECT_TRUE(HasSpan(file_.service(0)));
- EXPECT_TRUE(HasSpan(file_.service(0), "name"));
-}
-
-
-TEST_F(SourceInfoTest, Options) {
- EXPECT_TRUE(Parse(
- "$a$option $b$foo$c$.$d$($e$bar.baz$f$)$g$ = "
- "$h$123$i$;$j$\n"
- "$k$option qux = $l$-123$m$;$n$\n"
- "$o$option corge = $p$abc$q$;$r$\n"
- "$s$option grault = $t$'blah'$u$;$v$\n"
- "$w$option garply = $x${ yadda yadda }$y$;$z$\n"
- "$0$option waldo = $1$123.0$2$;$3$\n"
- ));
-
- const UninterpretedOption& option1 = file_.options().uninterpreted_option(0);
- const UninterpretedOption& option2 = file_.options().uninterpreted_option(1);
- const UninterpretedOption& option3 = file_.options().uninterpreted_option(2);
- const UninterpretedOption& option4 = file_.options().uninterpreted_option(3);
- const UninterpretedOption& option5 = file_.options().uninterpreted_option(4);
- const UninterpretedOption& option6 = file_.options().uninterpreted_option(5);
-
- EXPECT_TRUE(HasSpan('a', 'j', file_.options()));
- EXPECT_TRUE(HasSpan('a', 'j', option1));
- EXPECT_TRUE(HasSpan('b', 'g', option1, "name"));
- EXPECT_TRUE(HasSpan('b', 'c', option1.name(0)));
- EXPECT_TRUE(HasSpan('b', 'c', option1.name(0), "name_part"));
- EXPECT_TRUE(HasSpan('d', 'g', option1.name(1)));
- EXPECT_TRUE(HasSpan('e', 'f', option1.name(1), "name_part"));
- EXPECT_TRUE(HasSpan('h', 'i', option1, "positive_int_value"));
-
- EXPECT_TRUE(HasSpan('k', 'n', file_.options()));
- EXPECT_TRUE(HasSpan('l', 'm', option2, "negative_int_value"));
-
- EXPECT_TRUE(HasSpan('o', 'r', file_.options()));
- EXPECT_TRUE(HasSpan('p', 'q', option3, "identifier_value"));
-
- EXPECT_TRUE(HasSpan('s', 'v', file_.options()));
- EXPECT_TRUE(HasSpan('t', 'u', option4, "string_value"));
-
- EXPECT_TRUE(HasSpan('w', 'z', file_.options()));
- EXPECT_TRUE(HasSpan('x', 'y', option5, "aggregate_value"));
-
- EXPECT_TRUE(HasSpan('0', '3', file_.options()));
- EXPECT_TRUE(HasSpan('1', '2', option6, "double_value"));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
- EXPECT_TRUE(HasSpan(option2));
- EXPECT_TRUE(HasSpan(option3));
- EXPECT_TRUE(HasSpan(option4));
- EXPECT_TRUE(HasSpan(option5));
- EXPECT_TRUE(HasSpan(option6));
- EXPECT_TRUE(HasSpan(option2, "name"));
- EXPECT_TRUE(HasSpan(option3, "name"));
- EXPECT_TRUE(HasSpan(option4, "name"));
- EXPECT_TRUE(HasSpan(option5, "name"));
- EXPECT_TRUE(HasSpan(option6, "name"));
- EXPECT_TRUE(HasSpan(option2.name(0)));
- EXPECT_TRUE(HasSpan(option3.name(0)));
- EXPECT_TRUE(HasSpan(option4.name(0)));
- EXPECT_TRUE(HasSpan(option5.name(0)));
- EXPECT_TRUE(HasSpan(option6.name(0)));
- EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
- EXPECT_TRUE(HasSpan(option3.name(0), "name_part"));
- EXPECT_TRUE(HasSpan(option4.name(0), "name_part"));
- EXPECT_TRUE(HasSpan(option5.name(0), "name_part"));
- EXPECT_TRUE(HasSpan(option6.name(0), "name_part"));
-}
-
-TEST_F(SourceInfoTest, ScopedOptions) {
- EXPECT_TRUE(Parse(
- "message Foo {\n"
- " $a$option mopt = 1;$b$\n"
- "}\n"
- "enum Bar {\n"
- " $c$option eopt = 1;$d$\n"
- "}\n"
- "service Baz {\n"
- " $e$option sopt = 1;$f$\n"
- " rpc M(X) returns(Y) {\n"
- " $g$option mopt = 1;$h$\n"
- " }\n"
- "}\n"));
-
- EXPECT_TRUE(HasSpan('a', 'b', file_.message_type(0).options()));
- EXPECT_TRUE(HasSpan('c', 'd', file_.enum_type(0).options()));
- EXPECT_TRUE(HasSpan('e', 'f', file_.service(0).options()));
- EXPECT_TRUE(HasSpan('g', 'h', file_.service(0).method(0).options()));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
- EXPECT_TRUE(HasSpan(file_.message_type(0)));
- EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
- EXPECT_TRUE(HasSpan(file_.message_type(0).options()
- .uninterpreted_option(0)));
- EXPECT_TRUE(HasSpan(file_.message_type(0).options()
- .uninterpreted_option(0), "name"));
- EXPECT_TRUE(HasSpan(file_.message_type(0).options()
- .uninterpreted_option(0).name(0)));
- EXPECT_TRUE(HasSpan(file_.message_type(0).options()
- .uninterpreted_option(0).name(0), "name_part"));
- EXPECT_TRUE(HasSpan(file_.message_type(0).options()
- .uninterpreted_option(0), "positive_int_value"));
- EXPECT_TRUE(HasSpan(file_.enum_type(0)));
- EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
- EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
- .uninterpreted_option(0)));
- EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
- .uninterpreted_option(0), "name"));
- EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
- .uninterpreted_option(0).name(0)));
- EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
- .uninterpreted_option(0).name(0), "name_part"));
- EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
- .uninterpreted_option(0), "positive_int_value"));
- EXPECT_TRUE(HasSpan(file_.service(0)));
- EXPECT_TRUE(HasSpan(file_.service(0), "name"));
- EXPECT_TRUE(HasSpan(file_.service(0).method(0)));
- EXPECT_TRUE(HasSpan(file_.service(0).options()
- .uninterpreted_option(0)));
- EXPECT_TRUE(HasSpan(file_.service(0).options()
- .uninterpreted_option(0), "name"));
- EXPECT_TRUE(HasSpan(file_.service(0).options()
- .uninterpreted_option(0).name(0)));
- EXPECT_TRUE(HasSpan(file_.service(0).options()
- .uninterpreted_option(0).name(0), "name_part"));
- EXPECT_TRUE(HasSpan(file_.service(0).options()
- .uninterpreted_option(0), "positive_int_value"));
- EXPECT_TRUE(HasSpan(file_.service(0).method(0), "name"));
- EXPECT_TRUE(HasSpan(file_.service(0).method(0), "input_type"));
- EXPECT_TRUE(HasSpan(file_.service(0).method(0), "output_type"));
- EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
- .uninterpreted_option(0)));
- EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
- .uninterpreted_option(0), "name"));
- EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
- .uninterpreted_option(0).name(0)));
- EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
- .uninterpreted_option(0).name(0), "name_part"));
- EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
- .uninterpreted_option(0), "positive_int_value"));
-}
-
-TEST_F(SourceInfoTest, FieldOptions) {
- // The actual "name = value" pairs are parsed by the same code as for
- // top-level options so we won't re-test that -- just make sure that the
- // syntax used for field options is understood.
- EXPECT_TRUE(Parse(
- "message Foo {"
- " optional int32 bar = 1 "
- "$a$[default=$b$123$c$,$d$opt1=123$e$,"
- "$f$opt2='hi'$g$]$h$;"
- "}\n"
- ));
-
- const FieldDescriptorProto& field = file_.message_type(0).field(0);
- const UninterpretedOption& option1 = field.options().uninterpreted_option(0);
- const UninterpretedOption& option2 = field.options().uninterpreted_option(1);
-
- EXPECT_TRUE(HasSpan('a', 'h', field.options()));
- EXPECT_TRUE(HasSpan('b', 'c', field, "default_value"));
- EXPECT_TRUE(HasSpan('d', 'e', option1));
- EXPECT_TRUE(HasSpan('f', 'g', option2));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
- EXPECT_TRUE(HasSpan(file_.message_type(0)));
- EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
- EXPECT_TRUE(HasSpan(field));
- EXPECT_TRUE(HasSpan(field, "label"));
- EXPECT_TRUE(HasSpan(field, "type"));
- EXPECT_TRUE(HasSpan(field, "name"));
- EXPECT_TRUE(HasSpan(field, "number"));
- EXPECT_TRUE(HasSpan(option1, "name"));
- EXPECT_TRUE(HasSpan(option2, "name"));
- EXPECT_TRUE(HasSpan(option1.name(0)));
- EXPECT_TRUE(HasSpan(option2.name(0)));
- EXPECT_TRUE(HasSpan(option1.name(0), "name_part"));
- EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
- EXPECT_TRUE(HasSpan(option1, "positive_int_value"));
- EXPECT_TRUE(HasSpan(option2, "string_value"));
-}
-
-TEST_F(SourceInfoTest, EnumValueOptions) {
- // The actual "name = value" pairs are parsed by the same code as for
- // top-level options so we won't re-test that -- just make sure that the
- // syntax used for enum options is understood.
- EXPECT_TRUE(Parse(
- "enum Foo {"
- " BAR = 1 $a$[$b$opt1=123$c$,$d$opt2='hi'$e$]$f$;"
- "}\n"
- ));
-
- const EnumValueDescriptorProto& value = file_.enum_type(0).value(0);
- const UninterpretedOption& option1 = value.options().uninterpreted_option(0);
- const UninterpretedOption& option2 = value.options().uninterpreted_option(1);
-
- EXPECT_TRUE(HasSpan('a', 'f', value.options()));
- EXPECT_TRUE(HasSpan('b', 'c', option1));
- EXPECT_TRUE(HasSpan('d', 'e', option2));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
- EXPECT_TRUE(HasSpan(file_.enum_type(0)));
- EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
- EXPECT_TRUE(HasSpan(value));
- EXPECT_TRUE(HasSpan(value, "name"));
- EXPECT_TRUE(HasSpan(value, "number"));
- EXPECT_TRUE(HasSpan(option1, "name"));
- EXPECT_TRUE(HasSpan(option2, "name"));
- EXPECT_TRUE(HasSpan(option1.name(0)));
- EXPECT_TRUE(HasSpan(option2.name(0)));
- EXPECT_TRUE(HasSpan(option1.name(0), "name_part"));
- EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
- EXPECT_TRUE(HasSpan(option1, "positive_int_value"));
- EXPECT_TRUE(HasSpan(option2, "string_value"));
-}
-
-TEST_F(SourceInfoTest, DocComments) {
- EXPECT_TRUE(Parse(
- "// Foo leading\n"
- "// line 2\n"
- "$a$message Foo {\n"
- " // Foo trailing\n"
- " // line 2\n"
- "\n"
- " // ignored\n"
- "\n"
- " // bar leading\n"
- " $b$optional int32 bar = 1;$c$\n"
- " // bar trailing\n"
- "}$d$\n"
- "// ignored\n"
- ));
-
- const DescriptorProto& foo = file_.message_type(0);
- const FieldDescriptorProto& bar = foo.field(0);
-
- EXPECT_TRUE(HasSpanWithComment('a', 'd', foo,
- " Foo leading\n line 2\n",
- " Foo trailing\n line 2\n"));
- EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
- " bar leading\n",
- " bar trailing\n"));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
- EXPECT_TRUE(HasSpan(foo, "name"));
- EXPECT_TRUE(HasSpan(bar, "label"));
- EXPECT_TRUE(HasSpan(bar, "type"));
- EXPECT_TRUE(HasSpan(bar, "name"));
- EXPECT_TRUE(HasSpan(bar, "number"));
-}
-
-TEST_F(SourceInfoTest, DocComments2) {
- EXPECT_TRUE(Parse(
- "// ignored\n"
- "syntax = \"proto2\";\n"
- "// Foo leading\n"
- "// line 2\n"
- "$a$message Foo {\n"
- " /* Foo trailing\n"
- " * line 2 */\n"
- " // ignored\n"
- " /* bar leading\n"
- " */"
- " $b$optional int32 bar = 1;$c$ // bar trailing\n"
- " // ignored\n"
- "}$d$\n"
- "// ignored\n"
- "\n"
- "// option leading\n"
- "$e$option baz = 123;$f$\n"
- "// option trailing\n"
- ));
-
- const DescriptorProto& foo = file_.message_type(0);
- const FieldDescriptorProto& bar = foo.field(0);
- const UninterpretedOption& baz = file_.options().uninterpreted_option(0);
-
- EXPECT_TRUE(HasSpanWithComment('a', 'd', foo,
- " Foo leading\n line 2\n",
- " Foo trailing\n line 2 "));
- EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
- " bar leading\n",
- " bar trailing\n"));
- EXPECT_TRUE(HasSpanWithComment('e', 'f', baz,
- " option leading\n",
- " option trailing\n"));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
- EXPECT_TRUE(HasSpan(foo, "name"));
- EXPECT_TRUE(HasSpan(bar, "label"));
- EXPECT_TRUE(HasSpan(bar, "type"));
- EXPECT_TRUE(HasSpan(bar, "name"));
- EXPECT_TRUE(HasSpan(bar, "number"));
- EXPECT_TRUE(HasSpan(file_.options()));
- EXPECT_TRUE(HasSpan(baz, "name"));
- EXPECT_TRUE(HasSpan(baz.name(0)));
- EXPECT_TRUE(HasSpan(baz.name(0), "name_part"));
- EXPECT_TRUE(HasSpan(baz, "positive_int_value"));
-}
-
-TEST_F(SourceInfoTest, DocComments3) {
- EXPECT_TRUE(Parse(
- "$a$message Foo {\n"
- " // bar leading\n"
- " $b$optional int32 bar = 1 [(baz.qux) = {}];$c$\n"
- " // bar trailing\n"
- "}$d$\n"
- "// ignored\n"
- ));
-
- const DescriptorProto& foo = file_.message_type(0);
- const FieldDescriptorProto& bar = foo.field(0);
-
- EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
- " bar leading\n",
- " bar trailing\n"));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
- EXPECT_TRUE(HasSpan(foo));
- EXPECT_TRUE(HasSpan(foo, "name"));
- EXPECT_TRUE(HasSpan(bar, "label"));
- EXPECT_TRUE(HasSpan(bar, "type"));
- EXPECT_TRUE(HasSpan(bar, "name"));
- EXPECT_TRUE(HasSpan(bar, "number"));
- EXPECT_TRUE(HasSpan(bar.options()));
- EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0)));
- EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0), "name"));
- EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0).name(0)));
- EXPECT_TRUE(HasSpan(
- bar.options().uninterpreted_option(0).name(0), "name_part"));
- EXPECT_TRUE(HasSpan(
- bar.options().uninterpreted_option(0), "aggregate_value"));
-}
-
-TEST_F(SourceInfoTest, DocCommentsOneof) {
- EXPECT_TRUE(Parse(
- "// ignored\n"
- "syntax = \"proto2\";\n"
- "// Foo leading\n"
- "$a$message Foo {\n"
- " /* Foo trailing\n"
- " */\n"
- " // ignored\n"
- " /* bar leading\n"
- " * line 2 */\n"
- " $b$oneof bar {\n"
- " /* bar trailing\n"
- " * line 2 */\n"
- " // ignored\n"
- " /* bar_int leading\n"
- " */\n"
- " $c$int32 bar_int = 1;$d$ // bar_int trailing\n"
- " // ignored\n"
- " }$e$\n"
- "}$f$\n"));
-
- const DescriptorProto& foo = file_.message_type(0);
- const OneofDescriptorProto& bar = foo.oneof_decl(0);
- const FieldDescriptorProto& bar_int = foo.field(0);
-
- EXPECT_TRUE(HasSpanWithComment('a', 'f', foo,
- " Foo leading\n",
- " Foo trailing\n"));
- EXPECT_TRUE(HasSpanWithComment('b', 'e', bar,
- " bar leading\n line 2 ",
- " bar trailing\n line 2 "));
- EXPECT_TRUE(HasSpanWithComment('c', 'd', bar_int,
- " bar_int leading\n",
- " bar_int trailing\n"));
-
- // Ignore these.
- EXPECT_TRUE(HasSpan(file_));
- EXPECT_TRUE(HasSpan(foo, "name"));
- EXPECT_TRUE(HasSpan(bar, "name"));
- EXPECT_TRUE(HasSpan(bar_int, "type"));
- EXPECT_TRUE(HasSpan(bar_int, "name"));
- EXPECT_TRUE(HasSpan(bar_int, "number"));
-}
-
// ===================================================================
} // anonymous namespace