• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 // Author: kenton@google.com (Kenton Varda)
9 //  Based on original Protocol Buffers design by
10 //  Sanjay Ghemawat, Jeff Dean, and others.
11 
12 #include "google/protobuf/compiler/parser.h"
13 
14 #include <algorithm>
15 #include <cmath>
16 #include <memory>
17 #include <string>
18 #include <utility>
19 #include <vector>
20 
21 #include "google/protobuf/any.pb.h"
22 #include "google/protobuf/descriptor.pb.h"
23 #include <gmock/gmock.h>
24 #include "google/protobuf/testing/googletest.h"
25 #include <gtest/gtest.h>
26 #include "absl/container/flat_hash_map.h"
27 #include "absl/log/absl_check.h"
28 #include "absl/memory/memory.h"
29 #include "absl/strings/str_cat.h"
30 #include "absl/strings/str_join.h"
31 #include "absl/strings/substitute.h"
32 #include "google/protobuf/compiler/retention.h"
33 #include "google/protobuf/test_util2.h"
34 #include "google/protobuf/text_format.h"
35 #include "google/protobuf/unittest.pb.h"
36 #include "google/protobuf/unittest_custom_options.pb.h"
37 #include "google/protobuf/unittest_import.pb.h"
38 #include "google/protobuf/unittest_import_public.pb.h"
39 #include "google/protobuf/wire_format.h"
40 
41 
42 // Must be included last.
43 #include "google/protobuf/port_def.inc"
44 
45 namespace google {
46 namespace protobuf {
47 namespace compiler {
48 
49 namespace {
50 
51 class MockErrorCollector : public io::ErrorCollector {
52  public:
53   MockErrorCollector() = default;
54   ~MockErrorCollector() override = default;
55 
56   std::string warning_;
57   std::string text_;
58 
59   // implements ErrorCollector ---------------------------------------
RecordWarning(int line,int column,absl::string_view message)60   void RecordWarning(int line, int column, absl::string_view message) override {
61     absl::SubstituteAndAppend(&warning_, "$0:$1: $2\n", line, column, message);
62   }
63 
RecordError(int line,int column,absl::string_view message)64   void RecordError(int line, int column, absl::string_view message) override {
65     absl::SubstituteAndAppend(&text_, "$0:$1: $2\n", line, column, message);
66   }
67 };
68 
69 class MockValidationErrorCollector : public DescriptorPool::ErrorCollector {
70  public:
MockValidationErrorCollector(const SourceLocationTable & source_locations,io::ErrorCollector * wrapped_collector)71   MockValidationErrorCollector(const SourceLocationTable& source_locations,
72                                io::ErrorCollector* wrapped_collector)
73       : source_locations_(source_locations),
74         wrapped_collector_(wrapped_collector) {}
75   ~MockValidationErrorCollector() override = default;
76 
77   // implements ErrorCollector ---------------------------------------
RecordError(absl::string_view filename,absl::string_view element_name,const Message * descriptor,ErrorLocation location,absl::string_view message)78   void RecordError(absl::string_view filename, absl::string_view element_name,
79                    const Message* descriptor, ErrorLocation location,
80                    absl::string_view message) override {
81     int line, column;
82     if (location == DescriptorPool::ErrorCollector::IMPORT) {
83       source_locations_.FindImport(descriptor, element_name, &line, &column);
84     } else {
85       source_locations_.Find(descriptor, location, &line, &column);
86     }
87     wrapped_collector_->RecordError(line, column, message);
88   }
89 
90  private:
91   const SourceLocationTable& source_locations_;
92   io::ErrorCollector* wrapped_collector_;
93 };
94 
95 class ParserTest : public testing::Test {
96  protected:
ParserTest()97   ParserTest() : require_syntax_identifier_(false) {}
98 
99   // Set up the parser to parse the given text.
SetupParser(absl::string_view text)100   void SetupParser(absl::string_view text) {
101     raw_input_ =
102         absl::make_unique<io::ArrayInputStream>(text.data(), text.size());
103     input_ =
104         absl::make_unique<io::Tokenizer>(raw_input_.get(), &error_collector_);
105     parser_ = absl::make_unique<Parser>();
106     parser_->RecordErrorsTo(&error_collector_);
107     parser_->SetRequireSyntaxIdentifier(require_syntax_identifier_);
108   }
109 
110   // Parse the input and expect that the resulting FileDescriptorProto matches
111   // the given output.  The output is a FileDescriptorProto in protocol buffer
112   // text format.
ExpectParsesTo(const char * input,const char * output)113   void ExpectParsesTo(const char* input, const char* output) {
114     SetupParser(input);
115     FileDescriptorProto actual, expected;
116 
117     EXPECT_TRUE(parser_->Parse(input_.get(), &actual));
118     EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
119     ASSERT_EQ("", error_collector_.text_);
120 
121     // We don't cover SourceCodeInfo in these tests.
122     actual.clear_source_code_info();
123 
124 
125     // Parse the ASCII representation in order to canonicalize it.  We could
126     // just compare directly to actual.DebugString(), but that would require
127     // that the caller precisely match the formatting that DebugString()
128     // produces.
129     ASSERT_TRUE(TextFormat::ParseFromString(output, &expected));
130 
131     // Compare by comparing debug strings.
132     // TODO:  Use differencer, once it is available.
133     EXPECT_EQ(expected.DebugString(), actual.DebugString());
134   }
135 
136   // Parse the text and expect that the given errors are reported.
ExpectHasErrors(absl::string_view text,const testing::Matcher<std::string> & expected_errors)137   void ExpectHasErrors(absl::string_view text,
138                        const testing::Matcher<std::string>& expected_errors) {
139     ExpectHasEarlyExitErrors(text, expected_errors);
140     EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
141   }
142 
143   // Parse the text and expect that the given warnings are reported.
ExpectHasWarnings(const char * text,const char * expected_warnings)144   void ExpectHasWarnings(const char* text, const char* expected_warnings) {
145     SetupParser(text);
146     FileDescriptorProto file;
147     ASSERT_TRUE(parser_->Parse(input_.get(), &file));
148     EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
149     ASSERT_EQ("", error_collector_.text_);
150     EXPECT_EQ(expected_warnings, error_collector_.warning_);
151   }
152 
153   // Same as above but does not expect that the parser parses the complete
154   // input.
ExpectHasEarlyExitErrors(absl::string_view text,const testing::Matcher<std::string> & expected_errors)155   void ExpectHasEarlyExitErrors(
156       absl::string_view text,
157       const testing::Matcher<std::string>& expected_errors) {
158     SetupParser(text);
159     SourceLocationTable source_locations;
160     parser_->RecordSourceLocationsTo(&source_locations);
161     FileDescriptorProto file;
162     EXPECT_FALSE(parser_->Parse(input_.get(), &file));
163     EXPECT_THAT(error_collector_.text_, expected_errors);
164   }
165 
166   // Parse the text as a file and validate it (with a DescriptorPool), and
167   // expect that the validation step reports the given errors.
ExpectHasValidationErrors(absl::string_view text,const testing::Matcher<std::string> & expected_errors)168   void ExpectHasValidationErrors(
169       absl::string_view text,
170       const testing::Matcher<std::string>& expected_errors) {
171     SetupParser(text);
172     SourceLocationTable source_locations;
173     parser_->RecordSourceLocationsTo(&source_locations);
174 
175     FileDescriptorProto file;
176     file.set_name("foo.proto");
177     parser_->Parse(input_.get(), &file);
178     EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
179     ASSERT_EQ("", error_collector_.text_);
180 
181     MockValidationErrorCollector validation_error_collector(source_locations,
182                                                             &error_collector_);
183     EXPECT_TRUE(pool_.BuildFileCollectingErrors(
184                     file, &validation_error_collector) == nullptr);
185     EXPECT_THAT(error_collector_.text_, expected_errors);
186   }
187 
188   MockErrorCollector error_collector_;
189   DescriptorPool pool_;
190 
191   std::unique_ptr<io::ZeroCopyInputStream> raw_input_;
192   std::unique_ptr<io::Tokenizer> input_;
193   std::unique_ptr<Parser> parser_;
194   bool require_syntax_identifier_;
195 };
196 
197 // ===================================================================
198 
TEST_F(ParserTest,StopAfterSyntaxIdentifier)199 TEST_F(ParserTest, StopAfterSyntaxIdentifier) {
200   SetupParser(
201       "// blah\n"
202       "syntax = \"foobar\";\n"
203       "this line will not be parsed\n");
204   parser_->SetStopAfterSyntaxIdentifier(true);
205   EXPECT_TRUE(parser_->Parse(input_.get(), nullptr));
206   EXPECT_EQ("", error_collector_.text_);
207   EXPECT_EQ("foobar", parser_->GetSyntaxIdentifier());
208 }
209 
TEST_F(ParserTest,StopAfterOmittedSyntaxIdentifier)210 TEST_F(ParserTest, StopAfterOmittedSyntaxIdentifier) {
211   SetupParser(
212       "// blah\n"
213       "this line will not be parsed\n");
214   parser_->SetStopAfterSyntaxIdentifier(true);
215   EXPECT_TRUE(parser_->Parse(input_.get(), nullptr));
216   EXPECT_EQ("", error_collector_.text_);
217   EXPECT_EQ("", parser_->GetSyntaxIdentifier());
218 }
219 
TEST_F(ParserTest,StopAfterSyntaxIdentifierWithErrors)220 TEST_F(ParserTest, StopAfterSyntaxIdentifierWithErrors) {
221   SetupParser(
222       "// blah\n"
223       "syntax = error;\n");
224   parser_->SetStopAfterSyntaxIdentifier(true);
225   EXPECT_FALSE(parser_->Parse(input_.get(), nullptr));
226   EXPECT_EQ("1:9: Expected syntax identifier.\n", error_collector_.text_);
227 }
228 
TEST_F(ParserTest,WarnIfSyntaxIdentifierOmitted)229 TEST_F(ParserTest, WarnIfSyntaxIdentifierOmitted) {
230   SetupParser("message A {}");
231   FileDescriptorProto file;
232   CaptureTestStderr();
233   EXPECT_TRUE(parser_->Parse(input_.get(), &file));
234   EXPECT_TRUE(GetCapturedTestStderr().find("No syntax specified") !=
235               std::string::npos);
236 }
237 
TEST_F(ParserTest,WarnIfFieldNameIsNotUpperCamel)238 TEST_F(ParserTest, WarnIfFieldNameIsNotUpperCamel) {
239   SetupParser(
240       "syntax = \"proto2\";"
241       "message abc {}");
242   FileDescriptorProto file;
243   EXPECT_TRUE(parser_->Parse(input_.get(), &file));
244   EXPECT_TRUE(error_collector_.warning_.find(
245                   "Message name should be in UpperCamelCase. Found: abc.") !=
246               std::string::npos);
247 }
248 
TEST_F(ParserTest,WarnIfFieldNameIsNotLowerUnderscore)249 TEST_F(ParserTest, WarnIfFieldNameIsNotLowerUnderscore) {
250   SetupParser(
251       "syntax = \"proto2\";"
252       "message A {"
253       "  optional string SongName = 1;"
254       "}");
255   FileDescriptorProto file;
256   EXPECT_TRUE(parser_->Parse(input_.get(), &file));
257   EXPECT_TRUE(error_collector_.warning_.find(
258                   "Field name should be lowercase. Found: SongName") !=
259               std::string::npos);
260 }
261 
TEST_F(ParserTest,WarnIfFieldNameContainsNumberImmediatelyFollowUnderscore)262 TEST_F(ParserTest, WarnIfFieldNameContainsNumberImmediatelyFollowUnderscore) {
263   SetupParser(
264       "syntax = \"proto2\";"
265       "message A {"
266       "  optional string song_name_1 = 1;"
267       "}");
268   FileDescriptorProto file;
269   EXPECT_TRUE(parser_->Parse(input_.get(), &file));
270   EXPECT_TRUE(error_collector_.warning_.find(
271                   "Number should not come right after an underscore. Found: "
272                   "song_name_1.") != std::string::npos);
273 }
274 
TEST_F(ParserTest,RegressionNestedOpenBraceDoNotStackOverflow)275 TEST_F(ParserTest, RegressionNestedOpenBraceDoNotStackOverflow) {
276   std::string input("edition=\"a\000;", 12);
277   input += std::string(100000, '{');
278   ExpectHasEarlyExitErrors(
279       input,
280       "0:10: Unexpected end of string.\n"
281       "0:10: Invalid control characters encountered in text.\n"
282       "0:8: Unknown edition \"a\".\n");
283 }
284 
285 // ===================================================================
286 
287 typedef ParserTest ParseMessageTest;
288 
TEST_F(ParseMessageTest,IgnoreBOM)289 TEST_F(ParseMessageTest, IgnoreBOM) {
290   char input[] =
291       "   message TestMessage {\n"
292       "  required int32 foo = 1;\n"
293       "}\n";
294   // Set UTF-8 BOM.
295   input[0] = (char)0xEF;
296   input[1] = (char)0xBB;
297   input[2] = (char)0xBF;
298   ExpectParsesTo(
299       input,
300       "message_type {"
301       "  name: \"TestMessage\""
302       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
303       "}");
304 }
305 
TEST_F(ParseMessageTest,BOMError)306 TEST_F(ParseMessageTest, BOMError) {
307   char input[] =
308       "   message TestMessage {\n"
309       "  required int32 foo = 1;\n"
310       "}\n";
311   input[0] = (char)0xEF;
312   ExpectHasErrors(input,
313                   "0:1: Proto file starts with 0xEF but not UTF-8 BOM. "
314                   "Only UTF-8 is accepted for proto file.\n"
315                   "0:0: Expected top-level statement (e.g. \"message\").\n");
316 }
317 
TEST_F(ParseMessageTest,SimpleMessage)318 TEST_F(ParseMessageTest, SimpleMessage) {
319   ExpectParsesTo(
320       "message TestMessage {\n"
321       "  required int32 foo = 1;\n"
322       "}\n",
323 
324       "message_type {"
325       "  name: \"TestMessage\""
326       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
327       "}");
328 }
329 
TEST_F(ParseMessageTest,ImplicitSyntaxIdentifier)330 TEST_F(ParseMessageTest, ImplicitSyntaxIdentifier) {
331   require_syntax_identifier_ = false;
332   ExpectParsesTo(
333       "message TestMessage {\n"
334       "  required int32 foo = 1;\n"
335       "}\n",
336 
337       "message_type {"
338       "  name: \"TestMessage\""
339       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
340       "}");
341   EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
342 }
343 
TEST_F(ParseMessageTest,ExplicitSyntaxIdentifier)344 TEST_F(ParseMessageTest, ExplicitSyntaxIdentifier) {
345   ExpectParsesTo(
346       "syntax = \"proto2\";\n"
347       "message TestMessage {\n"
348       "  required int32 foo = 1;\n"
349       "}\n",
350 
351       "syntax: 'proto2' "
352       "message_type {"
353       "  name: \"TestMessage\""
354       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
355       "}");
356   EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
357 }
358 
TEST_F(ParseMessageTest,ExplicitRequiredSyntaxIdentifier)359 TEST_F(ParseMessageTest, ExplicitRequiredSyntaxIdentifier) {
360   require_syntax_identifier_ = true;
361   ExpectParsesTo(
362       "syntax = \"proto2\";\n"
363       "message TestMessage {\n"
364       "  required int32 foo = 1;\n"
365       "}\n",
366 
367       "syntax: 'proto2' "
368       "message_type {"
369       "  name: \"TestMessage\""
370       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
371       "}");
372   EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
373 }
374 
TEST_F(ParseMessageTest,SimpleFields)375 TEST_F(ParseMessageTest, SimpleFields) {
376   ExpectParsesTo(
377       "message TestMessage {\n"
378       "  required int32 foo = 15;\n"
379       "  optional int32 bar = 34;\n"
380       "  repeated int32 baz = 3;\n"
381       "}\n",
382 
383       "message_type {"
384       "  name: \"TestMessage\""
385       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:15 }"
386       "  field { name:\"bar\" label:LABEL_OPTIONAL type:TYPE_INT32 number:34 }"
387       "  field { name:\"baz\" label:LABEL_REPEATED type:TYPE_INT32 number:3  }"
388       "}");
389 }
390 
TEST_F(ParseMessageTest,PrimitiveFieldTypes)391 TEST_F(ParseMessageTest, PrimitiveFieldTypes) {
392   ExpectParsesTo(
393       "message TestMessage {\n"
394       "  required int32    foo = 1;\n"
395       "  required int64    foo = 1;\n"
396       "  required uint32   foo = 1;\n"
397       "  required uint64   foo = 1;\n"
398       "  required sint32   foo = 1;\n"
399       "  required sint64   foo = 1;\n"
400       "  required fixed32  foo = 1;\n"
401       "  required fixed64  foo = 1;\n"
402       "  required sfixed32 foo = 1;\n"
403       "  required sfixed64 foo = 1;\n"
404       "  required float    foo = 1;\n"
405       "  required double   foo = 1;\n"
406       "  required string   foo = 1;\n"
407       "  required bytes    foo = 1;\n"
408       "  required bool     foo = 1;\n"
409       "}\n",
410 
411       "message_type {"
412       "  name: \"TestMessage\""
413       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32    number:1 "
414       "}"
415       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT64    number:1 "
416       "}"
417       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_UINT32   number:1 "
418       "}"
419       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_UINT64   number:1 "
420       "}"
421       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SINT32   number:1 "
422       "}"
423       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SINT64   number:1 "
424       "}"
425       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FIXED32  number:1 "
426       "}"
427       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FIXED64  number:1 "
428       "}"
429       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SFIXED32 number:1 "
430       "}"
431       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SFIXED64 number:1 "
432       "}"
433       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FLOAT    number:1 "
434       "}"
435       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_DOUBLE   number:1 "
436       "}"
437       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_STRING   number:1 "
438       "}"
439       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_BYTES    number:1 "
440       "}"
441       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_BOOL     number:1 "
442       "}"
443       "}");
444 }
445 
TEST_F(ParseMessageTest,FieldDefaults)446 TEST_F(ParseMessageTest, FieldDefaults) {
447   ExpectParsesTo(
448       "message TestMessage {\n"
449       "  required int32  foo = 1 [default=  1  ];\n"
450       "  required int32  foo = 1 [default= -2  ];\n"
451       "  required int64  foo = 1 [default=  3  ];\n"
452       "  required int64  foo = 1 [default= -4  ];\n"
453       "  required uint32 foo = 1 [default=  5  ];\n"
454       "  required uint64 foo = 1 [default=  6  ];\n"
455       "  required float  foo = 1 [default=  7.5];\n"
456       "  required float  foo = 1 [default= -8.5];\n"
457       "  required float  foo = 1 [default=  9  ];\n"
458       "  required double foo = 1 [default= 10.5];\n"
459       "  required double foo = 1 [default=-11.5];\n"
460       "  required double foo = 1 [default= 12  ];\n"
461       "  required double foo = 1 [default= inf ];\n"
462       "  required double foo = 1 [default=-inf ];\n"
463       "  required double foo = 1 [default= nan ];\n"
464       "  required double foo = 1 [default= -nan ];\n"
465       "  required string foo = 1 [default='13\\001'];\n"
466       "  required string foo = 1 [default='a' \"b\" \n \"c\"];\n"
467       "  required bytes  foo = 1 [default='14\\002'];\n"
468       "  required bytes  foo = 1 [default='a' \"b\" \n 'c'];\n"
469       "  required bool   foo = 1 [default=true ];\n"
470       "  required Foo    foo = 1 [default=FOO  ];\n"
471 
472       "  required int32  foo = 1 [default= 0x7FFFFFFF];\n"
473       "  required int32  foo = 1 [default=-0x80000000];\n"
474       "  required uint32 foo = 1 [default= 0xFFFFFFFF];\n"
475       "  required int64  foo = 1 [default= 0x7FFFFFFFFFFFFFFF];\n"
476       "  required int64  foo = 1 [default=-0x8000000000000000];\n"
477       "  required uint64 foo = 1 [default= 0xFFFFFFFFFFFFFFFF];\n"
478       "  required double foo = 1 [default= 0xabcd];\n"
479       "}\n",
480 
481 #define ETC "name:\"foo\" label:LABEL_REQUIRED number:1"
482       "message_type {"
483       "  name: \"TestMessage\""
484       "  field { type:TYPE_INT32   default_value:\"1\"         " ETC
485       " }"
486       "  field { type:TYPE_INT32   default_value:\"-2\"        " ETC
487       " }"
488       "  field { type:TYPE_INT64   default_value:\"3\"         " ETC
489       " }"
490       "  field { type:TYPE_INT64   default_value:\"-4\"        " ETC
491       " }"
492       "  field { type:TYPE_UINT32  default_value:\"5\"         " ETC
493       " }"
494       "  field { type:TYPE_UINT64  default_value:\"6\"         " ETC
495       " }"
496       "  field { type:TYPE_FLOAT   default_value:\"7.5\"       " ETC
497       " }"
498       "  field { type:TYPE_FLOAT   default_value:\"-8.5\"      " ETC
499       " }"
500       "  field { type:TYPE_FLOAT   default_value:\"9\"         " ETC
501       " }"
502       "  field { type:TYPE_DOUBLE  default_value:\"10.5\"      " ETC
503       " }"
504       "  field { type:TYPE_DOUBLE  default_value:\"-11.5\"     " ETC
505       " }"
506       "  field { type:TYPE_DOUBLE  default_value:\"12\"        " ETC
507       " }"
508       "  field { type:TYPE_DOUBLE  default_value:\"inf\"       " ETC
509       " }"
510       "  field { type:TYPE_DOUBLE  default_value:\"-inf\"      " ETC
511       " }"
512       "  field { type:TYPE_DOUBLE  default_value:\"nan\"       " ETC
513       " }"
514       "  field { type:TYPE_DOUBLE  default_value:\"-nan\"      " ETC
515       " }"
516       "  field { type:TYPE_STRING  default_value:\"13\\001\"   " ETC
517       " }"
518       "  field { type:TYPE_STRING  default_value:\"abc\"       " ETC
519       " }"
520       "  field { type:TYPE_BYTES   default_value:\"14\\\\002\" " ETC
521       " }"
522       "  field { type:TYPE_BYTES   default_value:\"abc\"       " ETC
523       " }"
524       "  field { type:TYPE_BOOL    default_value:\"true\"      " ETC
525       " }"
526       "  field { type_name:\"Foo\" default_value:\"FOO\"       " ETC
527       " }"
528 
529       "  field {"
530       "    type:TYPE_INT32   default_value:\"2147483647\"           " ETC
531       "  }"
532       "  field {"
533       "    type:TYPE_INT32   default_value:\"-2147483648\"          " ETC
534       "  }"
535       "  field {"
536       "    type:TYPE_UINT32  default_value:\"4294967295\"           " ETC
537       "  }"
538       "  field {"
539       "    type:TYPE_INT64   default_value:\"9223372036854775807\"  " ETC
540       "  }"
541       "  field {"
542       "    type:TYPE_INT64   default_value:\"-9223372036854775808\" " ETC
543       "  }"
544       "  field {"
545       "    type:TYPE_UINT64  default_value:\"18446744073709551615\" " ETC
546       "  }"
547       "  field {"
548       "    type:TYPE_DOUBLE  default_value:\"43981\"                " ETC
549       "  }"
550       "}");
551 #undef ETC
552 }
553 
TEST_F(ParseMessageTest,FieldJsonName)554 TEST_F(ParseMessageTest, FieldJsonName) {
555   ExpectParsesTo(
556       "message TestMessage {\n"
557       "  optional string foo = 1 [json_name = \"@type\"];\n"
558       "}\n",
559       "message_type {"
560       "  name: \"TestMessage\""
561       "  field {\n"
562       "    name: \"foo\" label: LABEL_OPTIONAL type: TYPE_STRING number: 1"
563       "    json_name: \"@type\"\n"
564       "  }\n"
565       "}\n");
566 }
567 
TEST_F(ParseMessageTest,FieldOptions)568 TEST_F(ParseMessageTest, FieldOptions) {
569   ExpectParsesTo(
570       "message TestMessage {\n"
571       "  optional string foo = 1\n"
572       "      [ctype=CORD, (foo)=7, foo.(.bar.baz).qux.quux.(corge)=-33, \n"
573       "       (quux)=\"x\040y\", (baz.qux)=hey];\n"
574       "}\n",
575 
576       "message_type {"
577       "  name: \"TestMessage\""
578       "  field { name: \"foo\" label: LABEL_OPTIONAL type: TYPE_STRING number: "
579       "1"
580       "          options { uninterpreted_option: { name { name_part: \"ctype\" "
581       "                                                   is_extension: false "
582       "} "
583       "                                            identifier_value: \"CORD\"  "
584       "}"
585       "                    uninterpreted_option: { name { name_part: \"foo\" "
586       "                                                   is_extension: true } "
587       "                                            positive_int_value: 7  }"
588       "                    uninterpreted_option: { name { name_part: \"foo\" "
589       "                                                   is_extension: false "
590       "} "
591       "                                            name { name_part: "
592       "\".bar.baz\""
593       "                                                   is_extension: true } "
594       "                                            name { name_part: \"qux\" "
595       "                                                   is_extension: false "
596       "} "
597       "                                            name { name_part: \"quux\" "
598       "                                                   is_extension: false "
599       "} "
600       "                                            name { name_part: \"corge\" "
601       "                                                   is_extension: true } "
602       "                                            negative_int_value: -33 }"
603       "                    uninterpreted_option: { name { name_part: \"quux\" "
604       "                                                   is_extension: true } "
605       "                                            string_value: \"x y\" }"
606       "                    uninterpreted_option: { name { name_part: "
607       "\"baz.qux\" "
608       "                                                   is_extension: true } "
609       "                                            identifier_value: \"hey\" }"
610       "          }"
611       "  }"
612       "}");
613 }
614 
TEST_F(ParseMessageTest,FieldOptionsSupportLargeDecimalLiteral)615 TEST_F(ParseMessageTest, FieldOptionsSupportLargeDecimalLiteral) {
616   // decimal integer literal > uint64 max
617   ExpectParsesTo(
618       "import \"google/protobuf/descriptor.proto\";\n"
619       "extend google.protobuf.FieldOptions {\n"
620       "  optional double f = 10101;\n"
621       "}\n"
622       "message TestMessage {\n"
623       "  optional double a = 1 [default = 18446744073709551616];\n"
624       "  optional double b = 2 [default = -18446744073709551616];\n"
625       "  optional double c = 3 [(f) = 18446744073709551616];\n"
626       "  optional double d = 4 [(f) = -18446744073709551616];\n"
627       "}\n",
628 
629       "dependency: \"google/protobuf/descriptor.proto\""
630       "extension {"
631       "  name: \"f\" label: LABEL_OPTIONAL type: TYPE_DOUBLE number: 10101"
632       "  extendee: \"google.protobuf.FieldOptions\""
633       "}"
634       "message_type {"
635       "  name: \"TestMessage\""
636       "  field {"
637       "    name: \"a\" label: LABEL_OPTIONAL type: TYPE_DOUBLE number: 1"
638       "    default_value: \"1.8446744073709552e+19\""
639       "  }"
640       "  field {"
641       "    name: \"b\" label: LABEL_OPTIONAL type: TYPE_DOUBLE number: 2"
642       "    default_value: \"-1.8446744073709552e+19\""
643       "  }"
644       "  field {"
645       "    name: \"c\" label: LABEL_OPTIONAL type: TYPE_DOUBLE number: 3"
646       "    options{"
647       "      uninterpreted_option{"
648       "        name{ name_part: \"f\" is_extension: true }"
649       "        double_value: 1.8446744073709552e+19"
650       "      }"
651       "    }"
652       "  }"
653       "  field {"
654       "    name: \"d\" label: LABEL_OPTIONAL type: TYPE_DOUBLE number: 4"
655       "    options{"
656       "      uninterpreted_option{"
657       "        name{ name_part: \"f\" is_extension: true }"
658       "        double_value: -1.8446744073709552e+19"
659       "      }"
660       "    }"
661       "  }"
662       "}");
663 }
664 
TEST_F(ParseMessageTest,FieldOptionsSupportInfAndNan)665 TEST_F(ParseMessageTest, FieldOptionsSupportInfAndNan) {
666   ExpectParsesTo(
667       "import \"google/protobuf/descriptor.proto\";\n"
668       "extend google.protobuf.FieldOptions {\n"
669       "  optional double f = 10101;\n"
670       "}\n"
671       "message TestMessage {\n"
672       "  optional double a = 1 [(f) = inf];\n"
673       "  optional double b = 2 [(f) = -inf];\n"
674       "  optional double c = 3 [(f) = nan];\n"
675       "  optional double d = 4 [(f) = -nan];\n"
676       "}\n",
677 
678       "dependency: \"google/protobuf/descriptor.proto\""
679       "extension {"
680       "  name: \"f\" label: LABEL_OPTIONAL type: TYPE_DOUBLE number: 10101"
681       "  extendee: \"google.protobuf.FieldOptions\""
682       "}"
683       "message_type {"
684       "  name: \"TestMessage\""
685       "  field {"
686       "    name: \"a\" label: LABEL_OPTIONAL type: TYPE_DOUBLE number: 1"
687       "    options{"
688       "      uninterpreted_option{"
689       "        name{ name_part: \"f\" is_extension: true }"
690       "        identifier_value: \"inf\""
691       "      }"
692       "    }"
693       "  }"
694       "  field {"
695       "    name: \"b\" label: LABEL_OPTIONAL type: TYPE_DOUBLE number: 2"
696       "    options{"
697       "      uninterpreted_option{"
698       "        name{ name_part: \"f\" is_extension: true }"
699       "        double_value: -infinity"
700       "      }"
701       "    }"
702       "  }"
703       "  field {"
704       "    name: \"c\" label: LABEL_OPTIONAL type: TYPE_DOUBLE number: 3"
705       "    options{"
706       "      uninterpreted_option{"
707       "        name{ name_part: \"f\" is_extension: true }"
708       "        identifier_value: \"nan\""
709       "      }"
710       "    }"
711       "  }"
712       "  field {"
713       "    name: \"d\" label: LABEL_OPTIONAL type: TYPE_DOUBLE number: 4"
714       "    options{"
715       "      uninterpreted_option{"
716       "        name{ name_part: \"f\" is_extension: true }"
717       "        double_value: nan"
718       "      }"
719       "    }"
720       "  }"
721       "}");
722 }
723 
TEST_F(ParseMessageTest,Oneof)724 TEST_F(ParseMessageTest, Oneof) {
725   ExpectParsesTo(
726       "message TestMessage {\n"
727       "  oneof foo {\n"
728       "    int32 a = 1;\n"
729       "    string b = 2;\n"
730       "    TestMessage c = 3;\n"
731       "    group D = 4 { optional int32 i = 5; }\n"
732       "  }\n"
733       "}\n",
734 
735       "message_type {"
736       "  name: \"TestMessage\""
737       "  field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 "
738       "          oneof_index:0 }"
739       "  field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 "
740       "          oneof_index:0 }"
741       "  field { name:\"c\" label:LABEL_OPTIONAL type_name:\"TestMessage\" "
742       "          number:3 oneof_index:0 }"
743       "  field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_GROUP "
744       "          type_name:\"D\" number:4 oneof_index:0 }"
745       "  oneof_decl {"
746       "    name: \"foo\""
747       "  }"
748       "  nested_type {"
749       "    name: \"D\""
750       "    field { name:\"i\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 }"
751       "  }"
752       "}");
753 }
754 
TEST_F(ParseMessageTest,MultipleOneofs)755 TEST_F(ParseMessageTest, MultipleOneofs) {
756   ExpectParsesTo(
757       "message TestMessage {\n"
758       "  oneof foo {\n"
759       "    int32 a = 1;\n"
760       "    string b = 2;\n"
761       "  }\n"
762       "  oneof bar {\n"
763       "    int32 c = 3;\n"
764       "    string d = 4;\n"
765       "  }\n"
766       "}\n",
767 
768       "message_type {"
769       "  name: \"TestMessage\""
770       "  field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 "
771       "          oneof_index:0 }"
772       "  field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 "
773       "          oneof_index:0 }"
774       "  field { name:\"c\" label:LABEL_OPTIONAL type:TYPE_INT32 number:3 "
775       "          oneof_index:1 }"
776       "  field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_STRING number:4 "
777       "          oneof_index:1 }"
778       "  oneof_decl {"
779       "    name: \"foo\""
780       "  }"
781       "  oneof_decl {"
782       "    name: \"bar\""
783       "  }"
784       "}");
785 }
786 
TEST_F(ParseMessageTest,Maps)787 TEST_F(ParseMessageTest, Maps) {
788   ExpectParsesTo(
789       "message TestMessage {\n"
790       "  map<int32, string> primitive_type_map = 1;\n"
791       "  map<KeyType, ValueType> composite_type_map = 2;\n"
792       "}\n",
793 
794       "message_type {"
795       "  name: \"TestMessage\""
796       "  nested_type {"
797       "    name: \"PrimitiveTypeMapEntry\""
798       "    field { "
799       "       name: \"key\" number: 1 label:LABEL_OPTIONAL"
800       "       type:TYPE_INT32"
801       "    }"
802       "    field { "
803       "       name: \"value\" number: 2 label:LABEL_OPTIONAL"
804       "       type:TYPE_STRING"
805       "    }"
806       "    options { map_entry: true }"
807       "  }"
808       "  nested_type {"
809       "    name: \"CompositeTypeMapEntry\""
810       "    field { "
811       "       name: \"key\" number: 1 label:LABEL_OPTIONAL"
812       "       type_name: \"KeyType\""
813       "    }"
814       "    field { "
815       "       name: \"value\" number: 2 label:LABEL_OPTIONAL"
816       "       type_name: \"ValueType\""
817       "    }"
818       "    options { map_entry: true }"
819       "  }"
820       "  field {"
821       "    name: \"primitive_type_map\""
822       "    label: LABEL_REPEATED"
823       "    type_name: \"PrimitiveTypeMapEntry\""
824       "    number: 1"
825       "  }"
826       "  field {"
827       "    name: \"composite_type_map\""
828       "    label: LABEL_REPEATED"
829       "    type_name: \"CompositeTypeMapEntry\""
830       "    number: 2"
831       "  }"
832       "}");
833 }
834 
TEST_F(ParseMessageTest,Group)835 TEST_F(ParseMessageTest, Group) {
836   ExpectParsesTo(
837       "message TestMessage {\n"
838       "  optional group TestGroup = 1 {};\n"
839       "}\n",
840 
841       "message_type {"
842       "  name: \"TestMessage\""
843       "  nested_type { name: \"TestGroup\" }"
844       "  field { name:\"testgroup\" label:LABEL_OPTIONAL number:1"
845       "          type:TYPE_GROUP type_name: \"TestGroup\" }"
846       "}");
847 }
848 
TEST_F(ParseMessageTest,NestedMessage)849 TEST_F(ParseMessageTest, NestedMessage) {
850   ExpectParsesTo(
851       "message TestMessage {\n"
852       "  message Nested {}\n"
853       "  optional Nested test_nested = 1;\n"
854       "}\n",
855 
856       "message_type {"
857       "  name: \"TestMessage\""
858       "  nested_type { name: \"Nested\" }"
859       "  field { name:\"test_nested\" label:LABEL_OPTIONAL number:1"
860       "          type_name: \"Nested\" }"
861       "}");
862 }
863 
TEST_F(ParseMessageTest,NestedEnum)864 TEST_F(ParseMessageTest, NestedEnum) {
865   ExpectParsesTo(
866       "message TestMessage {\n"
867       "  enum NestedEnum {}\n"
868       "  optional NestedEnum test_enum = 1;\n"
869       "}\n",
870 
871       "message_type {"
872       "  name: \"TestMessage\""
873       "  enum_type { name: \"NestedEnum\" }"
874       "  field { name:\"test_enum\" label:LABEL_OPTIONAL number:1"
875       "          type_name: \"NestedEnum\" }"
876       "}");
877 }
878 
TEST_F(ParseMessageTest,ReservedRange)879 TEST_F(ParseMessageTest, ReservedRange) {
880   ExpectParsesTo(
881       "message TestMessage {\n"
882       "  required int32 foo = 1;\n"
883       "  reserved 2, 15, 9 to 11, 3, 20 to max;\n"
884       "}\n",
885 
886       "message_type {"
887       "  name: \"TestMessage\""
888       "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
889       "  reserved_range { start:2   end:3         }"
890       "  reserved_range { start:15  end:16        }"
891       "  reserved_range { start:9   end:12        }"
892       "  reserved_range { start:3   end:4         }"
893       "  reserved_range { start:20  end:536870912 }"
894       "}");
895 }
896 
TEST_F(ParseMessageTest,ReservedRangeOnMessageSet)897 TEST_F(ParseMessageTest, ReservedRangeOnMessageSet) {
898   ExpectParsesTo(
899       "message TestMessage {\n"
900       "  option message_set_wire_format = true;\n"
901       "  reserved 20 to max;\n"
902       "}\n",
903 
904       "message_type {"
905       "  name: \"TestMessage\""
906       "  options {"
907       "    uninterpreted_option {"
908       "      name {"
909       "        name_part: \"message_set_wire_format\""
910       "        is_extension: false"
911       "      }"
912       "      identifier_value: \"true\""
913       "    }"
914       "  }"
915       "  reserved_range { start:20  end:2147483647 }"
916       "}");
917 }
918 
TEST_F(ParseMessageTest,ReservedNames)919 TEST_F(ParseMessageTest, ReservedNames) {
920   ExpectParsesTo(
921       "message TestMessage {\n"
922       "  reserved \"foo\", \"bar\";\n"
923       "}\n",
924 
925       "message_type {"
926       "  name: \"TestMessage\""
927       "  reserved_name: \"foo\""
928       "  reserved_name: \"bar\""
929       "}");
930 }
931 
TEST_F(ParseMessageTest,ReservedIdentifiers)932 TEST_F(ParseMessageTest, ReservedIdentifiers) {
933   ExpectParsesTo(
934       "edition = \"2023\";\n"
935       "message TestMessage {\n"
936       "  reserved foo, bar;\n"
937       "}\n",
938 
939       "syntax: \"editions\" "
940       "edition: EDITION_2023 "
941       "message_type {"
942       "  name: \"TestMessage\""
943       "  reserved_name: \"foo\""
944       "  reserved_name: \"bar\""
945       "}");
946 }
947 
TEST_F(ParseMessageTest,ExtensionRange)948 TEST_F(ParseMessageTest, ExtensionRange) {
949   ExpectParsesTo(
950       "message TestMessage {\n"
951       "  extensions 10 to 19;\n"
952       "  extensions 30 to max;\n"
953       "}\n",
954 
955       "message_type {"
956       "  name: \"TestMessage\""
957       "  extension_range { start:10 end:20        }"
958       "  extension_range { start:30 end:536870912 }"
959       "}");
960 }
961 
TEST_F(ParseMessageTest,ExtensionRangeWithOptions)962 TEST_F(ParseMessageTest, ExtensionRangeWithOptions) {
963   ExpectParsesTo(
964       "message TestMessage {\n"
965       "  extensions 10 to 19 [(i) = 5];\n"
966       "}\n",
967 
968       "message_type {"
969       "  name: \"TestMessage\""
970       "  extension_range {"
971       "    start:10"
972       "    end:20"
973       "    options {"
974       "      uninterpreted_option {"
975       "        name {"
976       "          name_part: \"i\""
977       "          is_extension: true"
978       "        }"
979       "        positive_int_value: 5"
980       "      }"
981       "    }"
982       "  }"
983       "}");
984 }
985 
TEST_F(ParseMessageTest,CompoundExtensionRange)986 TEST_F(ParseMessageTest, CompoundExtensionRange) {
987   ExpectParsesTo(
988       "message TestMessage {\n"
989       "  extensions 2, 15, 9 to 11, 100 to max, 3;\n"
990       "}\n",
991 
992       "message_type {"
993       "  name: \"TestMessage\""
994       "  extension_range { start:2   end:3         }"
995       "  extension_range { start:15  end:16        }"
996       "  extension_range { start:9   end:12        }"
997       "  extension_range { start:100 end:536870912 }"
998       "  extension_range { start:3   end:4         }"
999       "}");
1000 }
1001 
TEST_F(ParseMessageTest,MaxIntExtensionDoesNotOverflow)1002 TEST_F(ParseMessageTest, MaxIntExtensionDoesNotOverflow) {
1003   ExpectHasErrors(
1004       R"(
1005         syntax = "proto2";
1006         message TestMessage {
1007           extensions 2147483647;
1008         }
1009       )",
1010       "3:31: Field number out of bounds.\n");
1011   error_collector_.text_.clear();
1012   ExpectHasErrors(
1013       R"(
1014         syntax = "proto2";
1015         message TestMessage {
1016           extensions 1 to 2147483647;
1017         }
1018       )",
1019       "3:36: Field number out of bounds.\n");
1020   error_collector_.text_.clear();
1021   ExpectHasErrors(
1022       R"(
1023         syntax = "proto2";
1024         message TestMessage {
1025           extensions 2147483647 to 2147483647;
1026         }
1027       )",
1028       "3:32: Field number out of bounds.\n");
1029 }
1030 
TEST_F(ParseMessageTest,CompoundExtensionRangeWithOptions)1031 TEST_F(ParseMessageTest, CompoundExtensionRangeWithOptions) {
1032   ExpectParsesTo(
1033       "message TestMessage {\n"
1034       "  extensions 2, 15, 9 to 11, 100 to max, 3 [(i) = 5];\n"
1035       "}\n",
1036 
1037       "message_type {"
1038       "  name: \"TestMessage\""
1039       "  extension_range {"
1040       "    start:2"
1041       "    end:3"
1042       "    options {"
1043       "      uninterpreted_option {"
1044       "        name {"
1045       "          name_part: \"i\""
1046       "          is_extension: true"
1047       "        }"
1048       "        positive_int_value: 5"
1049       "      }"
1050       "    }"
1051       "  }"
1052       "  extension_range {"
1053       "    start:15"
1054       "    end:16"
1055       "    options {"
1056       "      uninterpreted_option {"
1057       "        name {"
1058       "          name_part: \"i\""
1059       "          is_extension: true"
1060       "        }"
1061       "        positive_int_value: 5"
1062       "      }"
1063       "    }"
1064       "  }"
1065       "  extension_range {"
1066       "    start:9"
1067       "    end:12"
1068       "    options {"
1069       "      uninterpreted_option {"
1070       "        name {"
1071       "          name_part: \"i\""
1072       "          is_extension: true"
1073       "        }"
1074       "        positive_int_value: 5"
1075       "      }"
1076       "    }"
1077       "  }"
1078       "  extension_range {"
1079       "    start:100"
1080       "    end:536870912"
1081       "    options {"
1082       "      uninterpreted_option {"
1083       "        name {"
1084       "          name_part: \"i\""
1085       "          is_extension: true"
1086       "        }"
1087       "        positive_int_value: 5"
1088       "      }"
1089       "    }"
1090       "  }"
1091       "  extension_range {"
1092       "    start:3"
1093       "    end:4"
1094       "    options {"
1095       "      uninterpreted_option {"
1096       "        name {"
1097       "          name_part: \"i\""
1098       "          is_extension: true"
1099       "        }"
1100       "        positive_int_value: 5"
1101       "      }"
1102       "    }"
1103       "  }"
1104       "}");
1105 }
1106 
TEST_F(ParseMessageTest,LargerMaxForMessageSetWireFormatMessages)1107 TEST_F(ParseMessageTest, LargerMaxForMessageSetWireFormatMessages) {
1108   // Messages using the message_set_wire_format option can accept larger
1109   // extension numbers, as the numbers are not encoded as int32 field values
1110   // rather than tags.
1111   ExpectParsesTo(
1112       "message TestMessage {\n"
1113       "  extensions 4 to max;\n"
1114       "  option message_set_wire_format = true;\n"
1115       "}\n",
1116 
1117       "message_type {"
1118       "  name: \"TestMessage\""
1119       "    extension_range { start:4 end: 0x7fffffff }"
1120       "  options {\n"
1121       "    uninterpreted_option { \n"
1122       "      name {\n"
1123       "        name_part: \"message_set_wire_format\"\n"
1124       "        is_extension: false\n"
1125       "      }\n"
1126       "      identifier_value: \"true\"\n"
1127       "    }\n"
1128       "  }\n"
1129       "}");
1130 }
1131 
TEST_F(ParseMessageTest,Extensions)1132 TEST_F(ParseMessageTest, Extensions) {
1133   ExpectParsesTo(
1134       "extend Extendee1 { optional int32 foo = 12; }\n"
1135       "extend Extendee2 { repeated TestMessage bar = 22; }\n",
1136 
1137       "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12"
1138       "            extendee: \"Extendee1\" } "
1139       "extension { name:\"bar\" label:LABEL_REPEATED number:22"
1140       "            type_name:\"TestMessage\" extendee: \"Extendee2\" }");
1141 }
1142 
TEST_F(ParseMessageTest,ExtensionsInMessageScope)1143 TEST_F(ParseMessageTest, ExtensionsInMessageScope) {
1144   ExpectParsesTo(
1145       "message TestMessage {\n"
1146       "  extend Extendee1 { optional int32 foo = 12; }\n"
1147       "  extend Extendee2 { repeated TestMessage bar = 22; }\n"
1148       "}\n",
1149 
1150       "message_type {"
1151       "  name: \"TestMessage\""
1152       "  extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 "
1153       "number:12"
1154       "              extendee: \"Extendee1\" }"
1155       "  extension { name:\"bar\" label:LABEL_REPEATED number:22"
1156       "              type_name:\"TestMessage\" extendee: \"Extendee2\" }"
1157       "}");
1158 }
1159 
TEST_F(ParseMessageTest,MultipleExtensionsOneExtendee)1160 TEST_F(ParseMessageTest, MultipleExtensionsOneExtendee) {
1161   ExpectParsesTo(
1162       "extend Extendee1 {\n"
1163       "  optional int32 foo = 12;\n"
1164       "  repeated TestMessage bar = 22;\n"
1165       "}\n",
1166 
1167       "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12"
1168       "            extendee: \"Extendee1\" } "
1169       "extension { name:\"bar\" label:LABEL_REPEATED number:22"
1170       "            type_name:\"TestMessage\" extendee: \"Extendee1\" }");
1171 }
1172 
TEST_F(ParseMessageTest,OptionalLabelProto3)1173 TEST_F(ParseMessageTest, OptionalLabelProto3) {
1174   ExpectParsesTo(
1175       "syntax = \"proto3\";\n"
1176       "message TestMessage {\n"
1177       "  int32 foo = 1;\n"
1178       "}\n",
1179 
1180       "syntax: \"proto3\" "
1181       "message_type {"
1182       "  name: \"TestMessage\""
1183       "  field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 } "
1184       "}");
1185 }
1186 
TEST_F(ParseMessageTest,ExplicitOptionalLabelProto3)1187 TEST_F(ParseMessageTest, ExplicitOptionalLabelProto3) {
1188   ExpectParsesTo(
1189       "syntax = 'proto3';\n"
1190       "message TestMessage {\n"
1191       "  optional int32 foo = 1;\n"
1192       "}\n",
1193 
1194       "syntax: \"proto3\" "
1195       "message_type {"
1196       "  name: \"TestMessage\""
1197       "  field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 "
1198       "          proto3_optional: true oneof_index: 0 } "
1199       "  oneof_decl { name:\"_foo\" } "
1200       "}");
1201 
1202   // Handle collisions in the synthetic oneof name.
1203   ExpectParsesTo(
1204       "syntax = 'proto3';\n"
1205       "message TestMessage {\n"
1206       "  optional int32 foo = 1;\n"
1207       "  oneof _foo {\n"
1208       "    int32 __foo = 2;\n"
1209       "  }\n"
1210       "}\n",
1211 
1212       "syntax: \"proto3\" "
1213       "message_type {"
1214       "  name: \"TestMessage\""
1215       "  field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 "
1216       "          proto3_optional: true oneof_index: 1 } "
1217       "  field { name:\"__foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:2 "
1218       "          oneof_index: 0 } "
1219       "  oneof_decl { name:\"_foo\" } "
1220       "  oneof_decl { name:\"X_foo\" } "
1221       "}");
1222 }
1223 
TEST_F(ParseMessageTest,CanHandleErrorOnFirstToken)1224 TEST_F(ParseMessageTest, CanHandleErrorOnFirstToken) {
1225   require_syntax_identifier_ = false;
1226   ExpectHasEarlyExitErrors(
1227       "/", "0:0: Expected top-level statement (e.g. \"message\").\n");
1228 
1229   require_syntax_identifier_ = true;
1230   ExpectHasEarlyExitErrors(
1231       "/",
1232       "0:0: Expected top-level statement (e.g. \"message\").\n"
1233       "0:0: File must begin with a syntax statement, e.g. 'syntax = "
1234       "\"proto2\";'.\n");
1235 }
1236 
1237 // ===================================================================
1238 
1239 typedef ParserTest ParseEnumTest;
1240 
TEST_F(ParseEnumTest,SimpleEnum)1241 TEST_F(ParseEnumTest, SimpleEnum) {
1242   ExpectParsesTo(
1243       "enum TestEnum {\n"
1244       "  FOO = 0;\n"
1245       "}\n",
1246 
1247       "enum_type {"
1248       "  name: \"TestEnum\""
1249       "  value { name:\"FOO\" number:0 }"
1250       "}");
1251 }
1252 
TEST_F(ParseEnumTest,Values)1253 TEST_F(ParseEnumTest, Values) {
1254   ExpectParsesTo(
1255       "enum TestEnum {\n"
1256       "  FOO = 13;\n"
1257       "  BAR = -10;\n"
1258       "  BAZ = 500;\n"
1259       "  HEX_MAX = 0x7FFFFFFF;\n"
1260       "  HEX_MIN = -0x80000000;\n"
1261       "  INT_MAX = 2147483647;\n"
1262       "  INT_MIN = -2147483648;\n"
1263       "}\n",
1264 
1265       "enum_type {"
1266       "  name: \"TestEnum\""
1267       "  value { name:\"FOO\" number:13 }"
1268       "  value { name:\"BAR\" number:-10 }"
1269       "  value { name:\"BAZ\" number:500 }"
1270       "  value { name:\"HEX_MAX\" number:2147483647 }"
1271       "  value { name:\"HEX_MIN\" number:-2147483648 }"
1272       "  value { name:\"INT_MAX\" number:2147483647 }"
1273       "  value { name:\"INT_MIN\" number:-2147483648 }"
1274       "}");
1275 }
1276 
TEST_F(ParseEnumTest,ValueOptions)1277 TEST_F(ParseEnumTest, ValueOptions) {
1278   ExpectParsesTo(
1279       "enum TestEnum {\n"
1280       "  FOO = 13;\n"
1281       "  BAR = -10 [ (something.text) = 'abc' ];\n"
1282       "  BAZ = 500 [ (something.text) = 'def', other = 1 ];\n"
1283       "}\n",
1284 
1285       "enum_type {"
1286       "  name: \"TestEnum\""
1287       "  value { name: \"FOO\" number: 13 }"
1288       "  value { name: \"BAR\" number: -10 "
1289       "    options { "
1290       "      uninterpreted_option { "
1291       "        name { name_part: \"something.text\" is_extension: true } "
1292       "        string_value: \"abc\" "
1293       "      } "
1294       "    } "
1295       "  } "
1296       "  value { name: \"BAZ\" number: 500 "
1297       "    options { "
1298       "      uninterpreted_option { "
1299       "        name { name_part: \"something.text\" is_extension: true } "
1300       "        string_value: \"def\" "
1301       "      } "
1302       "      uninterpreted_option { "
1303       "        name { name_part: \"other\" is_extension: false } "
1304       "        positive_int_value: 1 "
1305       "      } "
1306       "    } "
1307       "  } "
1308       "}");
1309 }
1310 
TEST_F(ParseEnumTest,ReservedRange)1311 TEST_F(ParseEnumTest, ReservedRange) {
1312   ExpectParsesTo(
1313       "enum TestEnum {\n"
1314       "  FOO = 0;\n"
1315       "  reserved -2147483648, -6 to -4, -1 to 1, 2, 15, 9 to 11, 3, 20 to "
1316       "max;\n"
1317       "}\n",
1318 
1319       "enum_type {"
1320       "  name: \"TestEnum\""
1321       "  value { name:\"FOO\" number:0 }"
1322       "  reserved_range { start:-2147483648  end:-2147483648 }"
1323       "  reserved_range { start:-6           end:-4          }"
1324       "  reserved_range { start:-1           end:1           }"
1325       "  reserved_range { start:2            end:2           }"
1326       "  reserved_range { start:15           end:15          }"
1327       "  reserved_range { start:9            end:11          }"
1328       "  reserved_range { start:3            end:3           }"
1329       "  reserved_range { start:20           end:2147483647  }"
1330       "}");
1331 }
1332 
TEST_F(ParseEnumTest,ReservedNames)1333 TEST_F(ParseEnumTest, ReservedNames) {
1334   ExpectParsesTo(
1335       "enum TestEnum {\n"
1336       "  FOO = 0;\n"
1337       "  reserved \"foo\", \"bar\";\n"
1338       "}\n",
1339 
1340       "enum_type {"
1341       "  name: \"TestEnum\""
1342       "  value { name:\"FOO\" number:0 }"
1343       "  reserved_name: \"foo\""
1344       "  reserved_name: \"bar\""
1345       "}");
1346 }
1347 
TEST_F(ParseEnumTest,ReservedIdentifiers)1348 TEST_F(ParseEnumTest, ReservedIdentifiers) {
1349   ExpectParsesTo(
1350       "edition = \"2023\";\n"
1351       "enum TestEnum {\n"
1352       "  FOO = 0;\n"
1353       "  reserved foo, bar;\n"
1354       "}\n",
1355 
1356       "syntax: \"editions\" "
1357       "edition: EDITION_2023 "
1358       "enum_type {"
1359       "  name: \"TestEnum\""
1360       "  value { name:\"FOO\" number:0 }"
1361       "  reserved_name: \"foo\""
1362       "  reserved_name: \"bar\""
1363       "}");
1364 }
1365 
1366 // ===================================================================
1367 
1368 typedef ParserTest ParseServiceTest;
1369 
TEST_F(ParseServiceTest,SimpleService)1370 TEST_F(ParseServiceTest, SimpleService) {
1371   ExpectParsesTo(
1372       "service TestService {\n"
1373       "  rpc Foo(In) returns (Out);\n"
1374       "}\n",
1375 
1376       "service {"
1377       "  name: \"TestService\""
1378       "  method { name:\"Foo\" input_type:\"In\" output_type:\"Out\" }"
1379       "}");
1380 }
1381 
TEST_F(ParseServiceTest,MethodsAndStreams)1382 TEST_F(ParseServiceTest, MethodsAndStreams) {
1383   ExpectParsesTo(
1384       "service TestService {\n"
1385       "  rpc Foo(In1) returns (Out1);\n"
1386       "  rpc Bar(In2) returns (Out2);\n"
1387       "  rpc Baz(In3) returns (Out3);\n"
1388       "}\n",
1389 
1390       "service {"
1391       "  name: \"TestService\""
1392       "  method { name:\"Foo\" input_type:\"In1\" output_type:\"Out1\" }"
1393       "  method { name:\"Bar\" input_type:\"In2\" output_type:\"Out2\" }"
1394       "  method { name:\"Baz\" input_type:\"In3\" output_type:\"Out3\" }"
1395       "}");
1396 }
1397 
1398 
1399 // ===================================================================
1400 // imports and packages
1401 
1402 typedef ParserTest ParseMiscTest;
1403 
TEST_F(ParseMiscTest,ParseImport)1404 TEST_F(ParseMiscTest, ParseImport) {
1405   ExpectParsesTo("import \"foo/bar/baz.proto\";\n",
1406                  "dependency: \"foo/bar/baz.proto\"");
1407 }
1408 
TEST_F(ParseMiscTest,ParseMultipleImports)1409 TEST_F(ParseMiscTest, ParseMultipleImports) {
1410   ExpectParsesTo(
1411       "import \"foo.proto\";\n"
1412       "import \"bar.proto\";\n"
1413       "import \"baz.proto\";\n",
1414       "dependency: \"foo.proto\""
1415       "dependency: \"bar.proto\""
1416       "dependency: \"baz.proto\"");
1417 }
1418 
TEST_F(ParseMiscTest,ParsePublicImports)1419 TEST_F(ParseMiscTest, ParsePublicImports) {
1420   ExpectParsesTo(
1421       "import \"foo.proto\";\n"
1422       "import public \"bar.proto\";\n"
1423       "import \"baz.proto\";\n"
1424       "import public \"qux.proto\";\n",
1425       "dependency: \"foo.proto\""
1426       "dependency: \"bar.proto\""
1427       "dependency: \"baz.proto\""
1428       "dependency: \"qux.proto\""
1429       "public_dependency: 1 "
1430       "public_dependency: 3 ");
1431 }
1432 
TEST_F(ParseMiscTest,ParsePackage)1433 TEST_F(ParseMiscTest, ParsePackage) {
1434   ExpectParsesTo("package foo.bar.baz;\n", "package: \"foo.bar.baz\"");
1435 }
1436 
TEST_F(ParseMiscTest,ParsePackageWithSpaces)1437 TEST_F(ParseMiscTest, ParsePackageWithSpaces) {
1438   ExpectParsesTo(
1439       "package foo   .   bar.  \n"
1440       "  baz;\n",
1441       "package: \"foo.bar.baz\"");
1442 }
1443 
1444 // ===================================================================
1445 // options
1446 
TEST_F(ParseMiscTest,ParseFileOptions)1447 TEST_F(ParseMiscTest, ParseFileOptions) {
1448   ExpectParsesTo(
1449       "option java_package = \"com.google.foo\";\n"
1450       "option optimize_for = CODE_SIZE;",
1451 
1452       "options {"
1453       "uninterpreted_option { name { name_part: \"java_package\" "
1454       "                              is_extension: false }"
1455       "                       string_value: \"com.google.foo\"} "
1456       "uninterpreted_option { name { name_part: \"optimize_for\" "
1457       "                              is_extension: false }"
1458       "                       identifier_value: \"CODE_SIZE\" } "
1459       "}");
1460 }
1461 
TEST_F(ParseMiscTest,InterpretedOptions)1462 TEST_F(ParseMiscTest, InterpretedOptions) {
1463   // Since we're importing the generated code from parsing/compiling
1464   // unittest_custom_options.proto, we can just look at the option
1465   // values from that file's descriptor in the generated code.
1466   {
1467     const MessageOptions& options =
1468         protobuf_unittest::SettingRealsFromInf ::descriptor()->options();
1469     float float_val = options.GetExtension(protobuf_unittest::float_opt);
1470     ASSERT_TRUE(std::isinf(float_val));
1471     ASSERT_GT(float_val, 0);
1472     double double_val = options.GetExtension(protobuf_unittest::double_opt);
1473     ASSERT_TRUE(std::isinf(double_val));
1474     ASSERT_GT(double_val, 0);
1475   }
1476   {
1477     const MessageOptions& options =
1478         protobuf_unittest::SettingRealsFromNegativeInf ::descriptor()->options();
1479     float float_val = options.GetExtension(protobuf_unittest::float_opt);
1480     ASSERT_TRUE(std::isinf(float_val));
1481     ASSERT_LT(float_val, 0);
1482     double double_val = options.GetExtension(protobuf_unittest::double_opt);
1483     ASSERT_TRUE(std::isinf(double_val));
1484     ASSERT_LT(double_val, 0);
1485   }
1486   {
1487     const MessageOptions& options =
1488         protobuf_unittest::SettingRealsFromNan ::descriptor()->options();
1489     float float_val = options.GetExtension(protobuf_unittest::float_opt);
1490     ASSERT_TRUE(std::isnan(float_val));
1491     double double_val = options.GetExtension(protobuf_unittest::double_opt);
1492     ASSERT_TRUE(std::isnan(double_val));
1493   }
1494   {
1495     const MessageOptions& options =
1496         protobuf_unittest::SettingRealsFromNegativeNan ::descriptor()->options();
1497     float float_val = options.GetExtension(protobuf_unittest::float_opt);
1498     ASSERT_TRUE(std::isnan(float_val));
1499     double double_val = options.GetExtension(protobuf_unittest::double_opt);
1500     ASSERT_TRUE(std::isnan(double_val));
1501   }
1502 }
1503 
1504 // ===================================================================
1505 // Error tests
1506 //
1507 // There are a very large number of possible errors that the parser could
1508 // report, so it's infeasible to test every single one of them.  Instead,
1509 // we test each unique call to AddError() in parser.h.  This does not mean
1510 // we are testing every possible error that Parser can generate because
1511 // each variant of the Consume() helper only counts as one unique call to
1512 // AddError().
1513 
1514 typedef ParserTest ParseErrorTest;
1515 
TEST_F(ParseErrorTest,MissingSyntaxIdentifier)1516 TEST_F(ParseErrorTest, MissingSyntaxIdentifier) {
1517   require_syntax_identifier_ = true;
1518   ExpectHasEarlyExitErrors("message TestMessage {}",
1519                            "0:0: File must begin with a syntax statement, e.g. "
1520                            "'syntax = \"proto2\";'.\n");
1521   EXPECT_EQ("", parser_->GetSyntaxIdentifier());
1522 }
1523 
TEST_F(ParseErrorTest,UnknownSyntaxIdentifier)1524 TEST_F(ParseErrorTest, UnknownSyntaxIdentifier) {
1525   ExpectHasEarlyExitErrors(
1526       "syntax = \"no_such_syntax\";",
1527       "0:9: Unrecognized syntax identifier \"no_such_syntax\".  This parser "
1528       "only recognizes \"proto2\" and \"proto3\".\n");
1529   EXPECT_EQ("no_such_syntax", parser_->GetSyntaxIdentifier());
1530 }
1531 
TEST_F(ParseErrorTest,SimpleSyntaxError)1532 TEST_F(ParseErrorTest, SimpleSyntaxError) {
1533   ExpectHasErrors("message TestMessage @#$ { blah }",
1534                   "0:20: Expected \"{\".\n");
1535   EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
1536 }
1537 
TEST_F(ParseErrorTest,ExpectedTopLevel)1538 TEST_F(ParseErrorTest, ExpectedTopLevel) {
1539   ExpectHasErrors("blah;",
1540                   "0:0: Expected top-level statement (e.g. \"message\").\n");
1541 }
1542 
TEST_F(ParseErrorTest,UnmatchedCloseBrace)1543 TEST_F(ParseErrorTest, UnmatchedCloseBrace) {
1544   // This used to cause an infinite loop.  Doh.
1545   ExpectHasErrors("}",
1546                   "0:0: Expected top-level statement (e.g. \"message\").\n"
1547                   "0:0: Unmatched \"}\".\n");
1548 }
1549 
1550 // -------------------------------------------------------------------
1551 // Message errors
1552 
TEST_F(ParseErrorTest,MessageMissingName)1553 TEST_F(ParseErrorTest, MessageMissingName) {
1554   ExpectHasErrors("message {}", "0:8: Expected message name.\n");
1555 }
1556 
TEST_F(ParseErrorTest,MessageMissingBody)1557 TEST_F(ParseErrorTest, MessageMissingBody) {
1558   ExpectHasErrors("message TestMessage;", "0:19: Expected \"{\".\n");
1559 }
1560 
TEST_F(ParseErrorTest,EofInMessage)1561 TEST_F(ParseErrorTest, EofInMessage) {
1562   ExpectHasErrors(
1563       "message TestMessage {",
1564       "0:21: Reached end of input in message definition (missing '}').\n");
1565 }
1566 
TEST_F(ParseErrorTest,NestingIsLimitedWithoutCrashing)1567 TEST_F(ParseErrorTest, NestingIsLimitedWithoutCrashing) {
1568   std::string start = "syntax = \"proto2\";\n";
1569   std::string end;
1570 
1571   const auto add = [&] {
1572     absl::StrAppend(&start, "message M {");
1573     absl::StrAppend(&end, "}");
1574   };
1575   const auto input = [&] { return absl::StrCat(start, end); };
1576 
1577   // The first ones work correctly.
1578   for (int i = 1; i < internal::cpp::MaxMessageDeclarationNestingDepth(); ++i) {
1579     add();
1580     const std::string str = input();
1581     SetupParser(str);
1582     FileDescriptorProto proto;
1583     proto.set_name("foo.proto");
1584     EXPECT_TRUE(parser_->Parse(input_.get(), &proto)) << input();
1585     EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
1586     ASSERT_EQ("", error_collector_.text_);
1587     DescriptorPool pool;
1588     ASSERT_TRUE(pool.BuildFile(proto));
1589   }
1590   // The rest have parsing errors but they don't crash no matter how deep we
1591   // make them.
1592   const auto error = testing::HasSubstr(
1593       "Reached maximum recursion limit for nested messages.");
1594   add();
1595   ExpectHasErrors(input(), error);
1596   for (int i = 0; i < 100000; ++i) {
1597     add();
1598   }
1599   ExpectHasErrors(input(), error);
1600 }
1601 
TEST_F(ParseErrorTest,MissingFieldNumber)1602 TEST_F(ParseErrorTest, MissingFieldNumber) {
1603   ExpectHasErrors(
1604       "message TestMessage {\n"
1605       "  optional int32 foo;\n"
1606       "}\n",
1607       "1:20: Missing field number.\n");
1608 }
1609 
TEST_F(ParseErrorTest,ExpectedFieldNumber)1610 TEST_F(ParseErrorTest, ExpectedFieldNumber) {
1611   ExpectHasErrors(
1612       "message TestMessage {\n"
1613       "  optional int32 foo = ;\n"
1614       "}\n",
1615       "1:23: Expected field number.\n");
1616 }
1617 
TEST_F(ParseErrorTest,FieldNumberOutOfRange)1618 TEST_F(ParseErrorTest, FieldNumberOutOfRange) {
1619   ExpectHasErrors(
1620       "message TestMessage {\n"
1621       "  optional int32 foo = 0x100000000;\n"
1622       "}\n",
1623       "1:23: Integer out of range.\n");
1624 }
1625 
TEST_F(ParseErrorTest,MissingLabel)1626 TEST_F(ParseErrorTest, MissingLabel) {
1627   ExpectHasErrors(
1628       "message TestMessage {\n"
1629       "  int32 foo = 1;\n"
1630       "}\n",
1631       "1:2: Expected \"required\", \"optional\", or \"repeated\".\n");
1632 }
1633 
TEST_F(ParseErrorTest,ExpectedOptionName)1634 TEST_F(ParseErrorTest, ExpectedOptionName) {
1635   ExpectHasErrors(
1636       "message TestMessage {\n"
1637       "  optional uint32 foo = 1 [];\n"
1638       "}\n",
1639       "1:27: Expected identifier.\n");
1640 }
1641 
TEST_F(ParseErrorTest,NonExtensionOptionNameBeginningWithDot)1642 TEST_F(ParseErrorTest, NonExtensionOptionNameBeginningWithDot) {
1643   ExpectHasErrors(
1644       "message TestMessage {\n"
1645       "  optional uint32 foo = 1 [.foo=1];\n"
1646       "}\n",
1647       "1:27: Expected identifier.\n");
1648 }
1649 
TEST_F(ParseErrorTest,DefaultValueTypeMismatch)1650 TEST_F(ParseErrorTest, DefaultValueTypeMismatch) {
1651   ExpectHasErrors(
1652       "message TestMessage {\n"
1653       "  optional uint32 foo = 1 [default=true];\n"
1654       "}\n",
1655       "1:35: Expected integer for field default value.\n");
1656 }
1657 
TEST_F(ParseErrorTest,DefaultValueNotBoolean)1658 TEST_F(ParseErrorTest, DefaultValueNotBoolean) {
1659   ExpectHasErrors(
1660       "message TestMessage {\n"
1661       "  optional bool foo = 1 [default=blah];\n"
1662       "}\n",
1663       "1:33: Expected \"true\" or \"false\".\n");
1664 }
1665 
TEST_F(ParseErrorTest,DefaultValueNotString)1666 TEST_F(ParseErrorTest, DefaultValueNotString) {
1667   ExpectHasErrors(
1668       "message TestMessage {\n"
1669       "  optional string foo = 1 [default=1];\n"
1670       "}\n",
1671       "1:35: Expected string for field default value.\n");
1672 }
1673 
TEST_F(ParseErrorTest,DefaultValueUnsignedNegative)1674 TEST_F(ParseErrorTest, DefaultValueUnsignedNegative) {
1675   ExpectHasErrors(
1676       "message TestMessage {\n"
1677       "  optional uint32 foo = 1 [default=-1];\n"
1678       "}\n",
1679       "1:36: Unsigned field can't have negative default value.\n");
1680 }
1681 
TEST_F(ParseErrorTest,DefaultValueTooLarge)1682 TEST_F(ParseErrorTest, DefaultValueTooLarge) {
1683   ExpectHasErrors(
1684       "message TestMessage {\n"
1685       "  optional int32  foo = 1 [default= 0x80000000];\n"
1686       "  optional int32  foo = 1 [default=-0x80000001];\n"
1687       "  optional uint32 foo = 1 [default= 0x100000000];\n"
1688       "  optional int64  foo = 1 [default= 0x80000000000000000];\n"
1689       "  optional int64  foo = 1 [default=-0x80000000000000001];\n"
1690       "  optional uint64 foo = 1 [default= 0x100000000000000000];\n"
1691       "}\n",
1692       "1:36: Integer out of range.\n"
1693       "2:36: Integer out of range.\n"
1694       "3:36: Integer out of range.\n"
1695       "4:36: Integer out of range.\n"
1696       "5:36: Integer out of range.\n"
1697       "6:36: Integer out of range.\n");
1698 }
1699 
TEST_F(ParseErrorTest,JsonNameNotString)1700 TEST_F(ParseErrorTest, JsonNameNotString) {
1701   ExpectHasErrors(
1702       "message TestMessage {\n"
1703       "  optional string foo = 1 [json_name=1];\n"
1704       "}\n",
1705       "1:37: Expected string for JSON name.\n");
1706 }
1707 
TEST_F(ParseErrorTest,DuplicateJsonName)1708 TEST_F(ParseErrorTest, DuplicateJsonName) {
1709   ExpectHasErrors(
1710       "message TestMessage {\n"
1711       "  optional uint32 foo = 1 [json_name=\"a\",json_name=\"b\"];\n"
1712       "}\n",
1713       "1:41: Already set option \"json_name\".\n");
1714 }
1715 
TEST_F(ParseErrorTest,MsgReservedIdentifierOnlyInEditions)1716 TEST_F(ParseErrorTest, MsgReservedIdentifierOnlyInEditions) {
1717   ExpectHasErrors(
1718       "message TestMessage {\n"
1719       "  reserved foo, bar;\n"
1720       "}\n",
1721       "1:11: Reserved names must be string literals. (Only editions supports "
1722       "identifiers.)\n");
1723 }
TEST_F(ParseErrorTest,MsgReservedNameStringNotInEditions)1724 TEST_F(ParseErrorTest, MsgReservedNameStringNotInEditions) {
1725   ExpectHasErrors(
1726       "edition = \"2023\";\n"
1727       "message TestMessage {\n"
1728       "  reserved \"foo\", \"bar\";\n"
1729       "}\n",
1730       "2:11: Reserved names must be identifiers in editions, not string "
1731       "literals.\n");
1732 }
1733 
TEST_F(ParseErrorTest,EnumReservedIdentifierOnlyInEditions)1734 TEST_F(ParseErrorTest, EnumReservedIdentifierOnlyInEditions) {
1735   ExpectHasErrors(
1736       "enum TestEnum {\n"
1737       "  FOO = 0;\n"
1738       "  reserved foo, bar;\n"
1739       "}\n",
1740       "2:11: Reserved names must be string literals. (Only editions supports "
1741       "identifiers.)\n");
1742 }
TEST_F(ParseErrorTest,EnumReservedNameStringNotInEditions)1743 TEST_F(ParseErrorTest, EnumReservedNameStringNotInEditions) {
1744   ExpectHasErrors(
1745       "edition = \"2023\";\n"
1746       "enum TestEnum {\n"
1747       "  FOO = 0;\n"
1748       "  reserved \"foo\", \"bar\";\n"
1749       "}\n",
1750       "3:11: Reserved names must be identifiers in editions, not string "
1751       "literals.\n");
1752 }
1753 
TEST_F(ParseErrorTest,EnumValueOutOfRange)1754 TEST_F(ParseErrorTest, EnumValueOutOfRange) {
1755   ExpectHasErrors(
1756       "enum TestEnum {\n"
1757       "  HEX_TOO_BIG   =  0x80000000;\n"
1758       "  HEX_TOO_SMALL = -0x80000001;\n"
1759       "  INT_TOO_BIG   =  2147483648;\n"
1760       "  INT_TOO_SMALL = -2147483649;\n"
1761       "}\n",
1762       "1:19: Integer out of range.\n"
1763       "2:19: Integer out of range.\n"
1764       "3:19: Integer out of range.\n"
1765       "4:19: Integer out of range.\n");
1766 }
1767 
TEST_F(ParseErrorTest,EnumAllowAliasFalse)1768 TEST_F(ParseErrorTest, EnumAllowAliasFalse) {
1769   ExpectHasErrors(
1770       "enum Foo {\n"
1771       "  option allow_alias = false;\n"
1772       "  BAR = 1;\n"
1773       "  BAZ = 2;\n"
1774       "}\n",
1775       "5:0: \"Foo\" declares 'option allow_alias = false;' which has no "
1776       "effect. "
1777       "Please remove the declaration.\n");
1778 }
1779 
TEST_F(ParseErrorTest,UnnecessaryEnumAllowAlias)1780 TEST_F(ParseErrorTest, UnnecessaryEnumAllowAlias) {
1781   ExpectHasErrors(
1782       "enum Foo {\n"
1783       "  option allow_alias = true;\n"
1784       "  BAR = 1;\n"
1785       "  BAZ = 2;\n"
1786       "}\n",
1787       "5:0: \"Foo\" declares support for enum aliases but no enum values share "
1788       "field numbers. Please remove the unnecessary 'option allow_alias = "
1789       "true;' "
1790       "declaration.\n");
1791 }
1792 
TEST_F(ParseErrorTest,DefaultValueMissing)1793 TEST_F(ParseErrorTest, DefaultValueMissing) {
1794   ExpectHasErrors(
1795       "message TestMessage {\n"
1796       "  optional uint32 foo = 1 [default=];\n"
1797       "}\n",
1798       "1:35: Expected integer for field default value.\n");
1799 }
1800 
TEST_F(ParseErrorTest,DefaultValueForGroup)1801 TEST_F(ParseErrorTest, DefaultValueForGroup) {
1802   ExpectHasErrors(
1803       "message TestMessage {\n"
1804       "  optional group Foo = 1 [default=blah] {}\n"
1805       "}\n",
1806       "1:34: Messages can't have default values.\n");
1807 }
1808 
TEST_F(ParseErrorTest,DuplicateDefaultValue)1809 TEST_F(ParseErrorTest, DuplicateDefaultValue) {
1810   ExpectHasErrors(
1811       "message TestMessage {\n"
1812       "  optional uint32 foo = 1 [default=1,default=2];\n"
1813       "}\n",
1814       "1:37: Already set option \"default\".\n");
1815 }
1816 
TEST_F(ParseErrorTest,MissingOneofName)1817 TEST_F(ParseErrorTest, MissingOneofName) {
1818   ExpectHasErrors(
1819       "message TestMessage {\n"
1820       "  oneof {\n"
1821       "    int32 bar = 1;\n"
1822       "  }\n"
1823       "}\n",
1824       "1:8: Expected oneof name.\n");
1825 }
1826 
TEST_F(ParseErrorTest,LabelInOneof)1827 TEST_F(ParseErrorTest, LabelInOneof) {
1828   ExpectHasErrors(
1829       "message TestMessage {\n"
1830       "  oneof foo {\n"
1831       "    optional int32 bar = 1;\n"
1832       "  }\n"
1833       "}\n",
1834       "2:4: Fields in oneofs must not have labels (required / optional "
1835       "/ repeated).\n");
1836 }
1837 
TEST_F(ParseErrorTest,MapInOneof)1838 TEST_F(ParseErrorTest, MapInOneof) {
1839   ExpectHasErrors(
1840       "message TestMessage {\n"
1841       "  oneof foo {\n"
1842       "    map<int32, int32> foo_map = 1;\n"
1843       "    map message_field = 2;\n"  // a normal message field is OK
1844       "  }\n"
1845       "}\n",
1846       "2:7: Map fields are not allowed in oneofs.\n");
1847 }
1848 
TEST_F(ParseErrorTest,LabelForMap)1849 TEST_F(ParseErrorTest, LabelForMap) {
1850   ExpectHasErrors(
1851       "message TestMessage {\n"
1852       "  optional map<int32, int32> int_map = 1;\n"
1853       "  required map<int32, int32> int_map2 = 2;\n"
1854       "  repeated map<int32, int32> int_map3 = 3;\n"
1855       "  optional map map_message = 4;\n"  // a normal message field is OK
1856       "}\n",
1857       "1:14: Field labels (required/optional/repeated) are not allowed on map "
1858       "fields.\n"
1859       "2:14: Field labels (required/optional/repeated) are not allowed on map "
1860       "fields.\n"
1861       "3:14: Field labels (required/optional/repeated) are not allowed on map "
1862       "fields.\n");
1863 }
1864 
TEST_F(ParseErrorTest,MalformedMaps)1865 TEST_F(ParseErrorTest, MalformedMaps) {
1866   ExpectHasErrors(
1867       "message TestMessage {\n"
1868       "  map map_message = 1;\n"  // a normal message field lacking label
1869       "  map<string> str_map = 2;\n"
1870       "  map<string,> str_map2 = 3;\n"
1871       "  map<,string> str_map3 = 4;\n"
1872       "  map<> empty_map = 5;\n"
1873       "  map<string,string str_map6 = 6;\n"
1874       "}"
1875       "extend SomeMessage {\n"
1876       "  map<int32, int32> int_map = 1;\n"
1877       "}",
1878       "1:6: Expected \"required\", \"optional\", or \"repeated\".\n"
1879       "2:12: Expected \",\".\n"
1880       "3:13: Expected type name.\n"
1881       "4:6: Expected type name.\n"
1882       "5:6: Expected type name.\n"
1883       "6:20: Expected \">\".\n"
1884       "8:5: Map fields are not allowed to be extensions.\n");
1885 }
1886 
TEST_F(ParseErrorTest,GroupNotCapitalized)1887 TEST_F(ParseErrorTest, GroupNotCapitalized) {
1888   ExpectHasErrors(
1889       "message TestMessage {\n"
1890       "  optional group foo = 1 {}\n"
1891       "}\n",
1892       "1:17: Group names must start with a capital letter.\n");
1893 }
1894 
TEST_F(ParseErrorTest,GroupMissingBody)1895 TEST_F(ParseErrorTest, GroupMissingBody) {
1896   ExpectHasErrors(
1897       "message TestMessage {\n"
1898       "  optional group Foo = 1;\n"
1899       "}\n",
1900       "1:24: Missing group body.\n");
1901 }
1902 
TEST_F(ParseErrorTest,ExtendingPrimitive)1903 TEST_F(ParseErrorTest, ExtendingPrimitive) {
1904   ExpectHasErrors("extend int32 { optional string foo = 4; }\n",
1905                   "0:7: Expected message type.\n");
1906 }
1907 
TEST_F(ParseErrorTest,ErrorInExtension)1908 TEST_F(ParseErrorTest, ErrorInExtension) {
1909   ExpectHasErrors(
1910       "message Foo { extensions 100 to 199; }\n"
1911       "extend Foo { optional string foo; }\n",
1912       "1:32: Missing field number.\n");
1913 }
1914 
TEST_F(ParseErrorTest,MultipleParseErrors)1915 TEST_F(ParseErrorTest, MultipleParseErrors) {
1916   // When a statement has a parse error, the parser should be able to continue
1917   // parsing at the next statement.
1918   ExpectHasErrors(
1919       "message TestMessage {\n"
1920       "  optional int32 foo;\n"
1921       "  !invalid statement ending in a block { blah blah { blah } blah }\n"
1922       "  optional int32 bar = 3 {}\n"
1923       "}\n",
1924       "1:20: Missing field number.\n"
1925       "2:2: Expected \"required\", \"optional\", or \"repeated\".\n"
1926       "2:2: Expected type name.\n"
1927       "3:25: Expected \";\".\n");
1928 }
1929 
TEST_F(ParseErrorTest,EofInAggregateValue)1930 TEST_F(ParseErrorTest, EofInAggregateValue) {
1931   ExpectHasErrors(
1932       "option (fileopt) = { i:100\n",
1933       "1:0: Unexpected end of stream while parsing aggregate value.\n");
1934 }
1935 
1936 // -------------------------------------------------------------------
1937 // Enum errors
1938 
TEST_F(ParseErrorTest,EofInEnum)1939 TEST_F(ParseErrorTest, EofInEnum) {
1940   ExpectHasErrors(
1941       "enum TestEnum {",
1942       "0:15: Reached end of input in enum definition (missing '}').\n");
1943 }
1944 
TEST_F(ParseErrorTest,EnumValueMissingNumber)1945 TEST_F(ParseErrorTest, EnumValueMissingNumber) {
1946   ExpectHasErrors(
1947       "enum TestEnum {\n"
1948       "  FOO;\n"
1949       "}\n",
1950       "1:5: Missing numeric value for enum constant.\n");
1951 }
1952 
1953 // NB: with editions, this would be accepted and would reserve a value name of
1954 // "max"
TEST_F(ParseErrorTest,EnumReservedStandaloneMaxNotAllowed)1955 TEST_F(ParseErrorTest, EnumReservedStandaloneMaxNotAllowed) {
1956   ExpectHasErrors(
1957       "enum TestEnum {\n"
1958       "  FOO = 1;\n"
1959       "  reserved max;\n"
1960       "}\n",
1961       "2:11: Reserved names must be string literals. (Only editions supports "
1962       "identifiers.)\n");
1963 }
1964 
TEST_F(ParseErrorTest,EnumReservedMixNameAndNumber)1965 TEST_F(ParseErrorTest, EnumReservedMixNameAndNumber) {
1966   ExpectHasErrors(
1967       "enum TestEnum {\n"
1968       "  FOO = 1;\n"
1969       "  reserved 10, \"foo\";\n"
1970       "}\n",
1971       "2:15: Expected enum number range.\n");
1972 }
TEST_F(ParseErrorTest,EnumReservedMixNameAndNumberEditions)1973 TEST_F(ParseErrorTest, EnumReservedMixNameAndNumberEditions) {
1974   ExpectHasErrors(
1975       "edition = \"2023\";\n"
1976       "enum TestEnum {\n"
1977       "  FOO = 1;\n"
1978       "  reserved 10, foo;\n"
1979       "}\n",
1980       "3:15: Expected enum number range.\n");
1981 }
1982 
TEST_F(ParseErrorTest,EnumReservedPositiveNumberOutOfRange)1983 TEST_F(ParseErrorTest, EnumReservedPositiveNumberOutOfRange) {
1984   ExpectHasErrors(
1985       "enum TestEnum {\n"
1986       "FOO = 1;\n"
1987       "  reserved 2147483648;\n"
1988       "}\n",
1989       "2:11: Integer out of range.\n");
1990 }
1991 
TEST_F(ParseErrorTest,EnumReservedNegativeNumberOutOfRange)1992 TEST_F(ParseErrorTest, EnumReservedNegativeNumberOutOfRange) {
1993   ExpectHasErrors(
1994       "enum TestEnum {\n"
1995       "FOO = 1;\n"
1996       "  reserved -2147483649;\n"
1997       "}\n",
1998       "2:12: Integer out of range.\n");
1999 }
2000 
TEST_F(ParseErrorTest,EnumReservedMissingQuotes)2001 TEST_F(ParseErrorTest, EnumReservedMissingQuotes) {
2002   ExpectHasErrors(
2003       "enum TestEnum {\n"
2004       "  FOO = 1;\n"
2005       "  reserved foo;\n"
2006       "}\n",
2007       "2:11: Reserved names must be string literals. (Only editions supports "
2008       "identifiers.)\n");
2009 }
2010 
TEST_F(ParseErrorTest,EnumReservedInvalidIdentifier)2011 TEST_F(ParseErrorTest, EnumReservedInvalidIdentifier) {
2012   ExpectHasWarnings(
2013       R"schema(
2014         enum TestEnum {
2015           FOO = 1;
2016           reserved "foo bar";
2017         }
2018       )schema",
2019       "3:19: Reserved name \"foo bar\" is not a valid identifier.\n");
2020 }
2021 
2022 // -------------------------------------------------------------------
2023 // Reserved field number errors
2024 
2025 // NB: with editions, this would be accepted and would reserve a field name of
2026 // "max"
TEST_F(ParseErrorTest,ReservedStandaloneMaxNotAllowed)2027 TEST_F(ParseErrorTest, ReservedStandaloneMaxNotAllowed) {
2028   ExpectHasErrors(
2029       "message Foo {\n"
2030       "  reserved max;\n"
2031       "}\n",
2032       "1:11: Reserved names must be string literals. (Only editions supports "
2033       "identifiers.)\n");
2034 }
2035 
TEST_F(ParseErrorTest,ReservedMixNameAndNumber)2036 TEST_F(ParseErrorTest, ReservedMixNameAndNumber) {
2037   ExpectHasErrors(
2038       "message Foo {\n"
2039       "  reserved 10, \"foo\";\n"
2040       "}\n",
2041       "1:15: Expected field number range.\n");
2042 }
TEST_F(ParseErrorTest,ReservedMixNameAndNumberEditions)2043 TEST_F(ParseErrorTest, ReservedMixNameAndNumberEditions) {
2044   ExpectHasErrors(
2045       "edition = \"2023\";\n"
2046       "message Foo {\n"
2047       "  reserved 10, foo;\n"
2048       "}\n",
2049       "2:15: Expected field number range.\n");
2050 }
2051 
TEST_F(ParseErrorTest,ReservedMissingQuotes)2052 TEST_F(ParseErrorTest, ReservedMissingQuotes) {
2053   ExpectHasErrors(
2054       "message Foo {\n"
2055       "  reserved foo;\n"
2056       "}\n",
2057       "1:11: Reserved names must be string literals. (Only editions supports "
2058       "identifiers.)\n");
2059 }
2060 
TEST_F(ParseErrorTest,ReservedInvalidIdentifier)2061 TEST_F(ParseErrorTest, ReservedInvalidIdentifier) {
2062   ExpectHasWarnings(
2063       R"schema(
2064         message Foo {
2065           reserved "foo bar";
2066         }
2067       )schema",
2068       "2:19: Reserved name \"foo bar\" is not a valid identifier.\n");
2069 }
2070 
TEST_F(ParseErrorTest,ReservedNegativeNumber)2071 TEST_F(ParseErrorTest, ReservedNegativeNumber) {
2072   ExpectHasErrors(
2073       "message Foo {\n"
2074       "  reserved -10;\n"
2075       "}\n",
2076       "1:11: Expected field name or number range.\n");
2077 }
2078 
TEST_F(ParseErrorTest,ReservedNumberOutOfRange)2079 TEST_F(ParseErrorTest, ReservedNumberOutOfRange) {
2080   ExpectHasErrors(
2081       "message Foo {\n"
2082       "  reserved 2147483648;\n"
2083       "}\n",
2084       "1:11: Integer out of range.\n");
2085 }
2086 
2087 // -------------------------------------------------------------------
2088 // Service errors
2089 
TEST_F(ParseErrorTest,EofInService)2090 TEST_F(ParseErrorTest, EofInService) {
2091   ExpectHasErrors(
2092       "service TestService {",
2093       "0:21: Reached end of input in service definition (missing '}').\n");
2094 }
2095 
TEST_F(ParseErrorTest,ServiceMethodPrimitiveParams)2096 TEST_F(ParseErrorTest, ServiceMethodPrimitiveParams) {
2097   ExpectHasErrors(
2098       "service TestService {\n"
2099       "  rpc Foo(int32) returns (string);\n"
2100       "}\n",
2101       "1:10: Expected message type.\n"
2102       "1:26: Expected message type.\n");
2103 }
2104 
2105 
TEST_F(ParseErrorTest,EofInMethodOptions)2106 TEST_F(ParseErrorTest, EofInMethodOptions) {
2107   ExpectHasErrors(
2108       "service TestService {\n"
2109       "  rpc Foo(Bar) returns(Bar) {",
2110       "1:29: Reached end of input in method options (missing '}').\n"
2111       "1:29: Reached end of input in service definition (missing '}').\n");
2112 }
2113 
2114 
TEST_F(ParseErrorTest,PrimitiveMethodInput)2115 TEST_F(ParseErrorTest, PrimitiveMethodInput) {
2116   ExpectHasErrors(
2117       "service TestService {\n"
2118       "  rpc Foo(int32) returns(Bar);\n"
2119       "}\n",
2120       "1:10: Expected message type.\n");
2121 }
2122 
2123 
TEST_F(ParseErrorTest,MethodOptionTypeError)2124 TEST_F(ParseErrorTest, MethodOptionTypeError) {
2125   // This used to cause an infinite loop.
2126   ExpectHasErrors(
2127       "message Baz {}\n"
2128       "service Foo {\n"
2129       "  rpc Bar(Baz) returns(Baz) { option invalid syntax; }\n"
2130       "}\n",
2131       "2:45: Expected \"=\".\n");
2132 }
2133 
2134 
2135 // -------------------------------------------------------------------
2136 // Import and package errors
2137 
TEST_F(ParseErrorTest,ImportNotQuoted)2138 TEST_F(ParseErrorTest, ImportNotQuoted) {
2139   ExpectHasErrors("import foo;\n",
2140                   "0:7: Expected a string naming the file to import.\n");
2141 }
2142 
TEST_F(ParseErrorTest,MultiplePackagesInFile)2143 TEST_F(ParseErrorTest, MultiplePackagesInFile) {
2144   ExpectHasErrors(
2145       "package foo;\n"
2146       "package bar;\n",
2147       "1:0: Multiple package definitions.\n");
2148 }
2149 
2150 // ===================================================================
2151 // Test that errors detected by DescriptorPool correctly report line and
2152 // column numbers.  We have one test for every call to RecordLocation() in
2153 // parser.cc.
2154 
2155 typedef ParserTest ParserValidationErrorTest;
2156 
TEST_F(ParserValidationErrorTest,PackageNameError)2157 TEST_F(ParserValidationErrorTest, PackageNameError) {
2158   // Create another file which defines symbol "foo".
2159   FileDescriptorProto other_file;
2160   other_file.set_name("bar.proto");
2161   other_file.add_message_type()->set_name("foo");
2162   EXPECT_TRUE(pool_.BuildFile(other_file) != nullptr);
2163 
2164   // Now try to define it as a package.
2165   ExpectHasValidationErrors(
2166       "package foo.bar;",
2167       "0:0: \"foo\" is already defined (as something other than a package) "
2168       "in file \"bar.proto\".\n");
2169 }
2170 
TEST_F(ParserValidationErrorTest,ImportUnloadedError)2171 TEST_F(ParserValidationErrorTest, ImportUnloadedError) {
2172   ExpectHasValidationErrors(
2173       "package test;\n"
2174       "\n"
2175       "import \"unloaded.proto\";",
2176       "2:0: Import \"unloaded.proto\" has not been loaded.\n");
2177 }
2178 
TEST_F(ParserValidationErrorTest,ImportTwice)2179 TEST_F(ParserValidationErrorTest, ImportTwice) {
2180   FileDescriptorProto other_file;
2181   other_file.set_name("bar.proto");
2182   other_file.add_message_type()->set_name("foo");
2183   EXPECT_TRUE(pool_.BuildFile(other_file) != nullptr);
2184 
2185   ExpectHasValidationErrors(
2186       "package test;\n"
2187       "\n"
2188       "import \"bar.proto\";\n"
2189       "  import \"bar.proto\";",
2190       "3:2: Import \"bar.proto\" was listed twice.\n");
2191 }
2192 
TEST_F(ParserValidationErrorTest,DuplicateFileError)2193 TEST_F(ParserValidationErrorTest, DuplicateFileError) {
2194   FileDescriptorProto other_file;
2195   other_file.set_name("foo.proto");
2196   EXPECT_TRUE(pool_.BuildFile(other_file) != nullptr);
2197 
2198   ExpectHasValidationErrors(
2199       "package test;", "0:0: A file with this name is already in the pool.\n");
2200 }
2201 
TEST_F(ParserValidationErrorTest,MessageNameError)2202 TEST_F(ParserValidationErrorTest, MessageNameError) {
2203   ExpectHasValidationErrors(
2204       "message Foo {}\n"
2205       "message Foo {}\n",
2206       "1:8: \"Foo\" is already defined.\n");
2207 }
2208 
TEST_F(ParserValidationErrorTest,FieldNameError)2209 TEST_F(ParserValidationErrorTest, FieldNameError) {
2210   ExpectHasValidationErrors(
2211       "message Foo {\n"
2212       "  optional int32 bar = 1;\n"
2213       "  optional int32 bar = 2;\n"
2214       "}\n",
2215       "2:17: \"bar\" is already defined in \"Foo\".\n");
2216 }
2217 
TEST_F(ParserValidationErrorTest,FieldTypeError)2218 TEST_F(ParserValidationErrorTest, FieldTypeError) {
2219   ExpectHasValidationErrors(
2220       "message Foo {\n"
2221       "  optional Baz bar = 1;\n"
2222       "}\n",
2223       "1:11: \"Baz\" is not defined.\n");
2224 }
2225 
TEST_F(ParserValidationErrorTest,FieldNumberError)2226 TEST_F(ParserValidationErrorTest, FieldNumberError) {
2227   ExpectHasValidationErrors(
2228       "message Foo {\n"
2229       "  optional int32 bar = 0;\n"
2230       "}\n",
2231       "1:23: Field numbers must be positive integers.\n"
2232       "1:23: Suggested field numbers for Foo: 1\n");
2233 }
2234 
TEST_F(ParserValidationErrorTest,FieldExtendeeError)2235 TEST_F(ParserValidationErrorTest, FieldExtendeeError) {
2236   ExpectHasValidationErrors("extend Baz { optional int32 bar = 1; }\n",
2237                             "0:7: \"Baz\" is not defined.\n");
2238 }
2239 
TEST_F(ParserValidationErrorTest,ExtensionJsonNameError)2240 TEST_F(ParserValidationErrorTest, ExtensionJsonNameError) {
2241   ExpectHasValidationErrors(
2242       "message TestMessage {\n"
2243       "  extensions 1 to 100;\n"
2244       "}\n"
2245       "extend TestMessage {\n"
2246       "  optional int32 foo = 12 [json_name = \"bar\"];\n"
2247       "}",
2248       "4:27: option json_name is not allowed on extension fields.\n");
2249 }
2250 
TEST_F(ParserValidationErrorTest,FieldDefaultValueError)2251 TEST_F(ParserValidationErrorTest, FieldDefaultValueError) {
2252   ExpectHasValidationErrors(
2253       "enum Baz { QUX = 1; }\n"
2254       "message Foo {\n"
2255       "  optional Baz bar = 1 [default=NO_SUCH_VALUE];\n"
2256       "}\n",
2257       "2:32: Enum type \"Baz\" has no value named \"NO_SUCH_VALUE\".\n");
2258 }
2259 
TEST_F(ParserValidationErrorTest,FieldDefaultIntegerOutOfRange)2260 TEST_F(ParserValidationErrorTest, FieldDefaultIntegerOutOfRange) {
2261   ExpectHasErrors(
2262       "message Foo {\n"
2263       "  optional double bar = 1 [default = 0x10000000000000000];\n"
2264       "}\n",
2265       "1:37: Integer out of range.\n");
2266 }
2267 
TEST_F(ParserValidationErrorTest,FieldOptionOutOfRange)2268 TEST_F(ParserValidationErrorTest, FieldOptionOutOfRange) {
2269   ExpectHasErrors(
2270       "message Foo {\n"
2271       "  optional double bar = 1 [foo = 0x10000000000000000];\n"
2272       "}\n",
2273       "1:33: Integer out of range.\n");
2274 }
2275 
TEST_F(ParserValidationErrorTest,FileOptionNameError)2276 TEST_F(ParserValidationErrorTest, FileOptionNameError) {
2277   ExpectHasValidationErrors(
2278       "option foo = 5;",
2279       "0:7: Option \"foo\" unknown. Ensure that your proto definition file "
2280       "imports the proto which defines the option.\n");
2281 }
2282 
TEST_F(ParserValidationErrorTest,FileOptionValueError)2283 TEST_F(ParserValidationErrorTest, FileOptionValueError) {
2284   ExpectHasValidationErrors(
2285       "option java_outer_classname = 5;",
2286       "0:30: Value must be quoted string for string option "
2287       "\"google.protobuf.FileOptions.java_outer_classname\".\n");
2288 }
2289 
TEST_F(ParserValidationErrorTest,FieldOptionNameError)2290 TEST_F(ParserValidationErrorTest, FieldOptionNameError) {
2291   ExpectHasValidationErrors(
2292       "message Foo {\n"
2293       "  optional bool bar = 1 [foo=1];\n"
2294       "}\n",
2295       "1:25: Option \"foo\" unknown. Ensure that your proto definition file "
2296       "imports the proto which defines the option.\n");
2297 }
2298 
TEST_F(ParserValidationErrorTest,FieldOptionValueError)2299 TEST_F(ParserValidationErrorTest, FieldOptionValueError) {
2300   ExpectHasValidationErrors(
2301       "message Foo {\n"
2302       "  optional int32 bar = 1 [ctype=1];\n"
2303       "}\n",
2304       "1:32: Value must be identifier for enum-valued option "
2305       "\"google.protobuf.FieldOptions.ctype\".\n");
2306 }
2307 
TEST_F(ParserValidationErrorTest,ExtensionRangeNumberError)2308 TEST_F(ParserValidationErrorTest, ExtensionRangeNumberError) {
2309   ExpectHasValidationErrors(
2310       "message Foo {\n"
2311       "  extensions 0;\n"
2312       "}\n",
2313       "1:13: Extension numbers must be positive integers.\n"
2314       "1:13: Suggested field numbers for Foo: 1\n");
2315 }
2316 
TEST_F(ParserValidationErrorTest,ExtensionRangeNumberOrderError)2317 TEST_F(ParserValidationErrorTest, ExtensionRangeNumberOrderError) {
2318   ExpectHasValidationErrors(
2319       "message Foo {\n"
2320       "  extensions 2 to 1;\n"
2321       "}\n",
2322       "1:13: Extension range end number must be greater than start number.\n");
2323 }
2324 
TEST_F(ParserValidationErrorTest,ReservedRangeError)2325 TEST_F(ParserValidationErrorTest, ReservedRangeError) {
2326   ExpectHasValidationErrors(
2327       "message Foo {\n"
2328       "  reserved 2 to 1;\n"
2329       "}\n",
2330       "1:11: Reserved range end number must be greater than start number.\n");
2331 }
2332 
TEST_F(ParserValidationErrorTest,Proto3ExtensionError)2333 TEST_F(ParserValidationErrorTest, Proto3ExtensionError) {
2334   ExpectHasValidationErrors(
2335       "syntax = 'proto3';\n"
2336       "message Foo { \n"
2337       "  extensions 100 to 199;\n"
2338       "}\n"
2339       "extend Foo { string foo = 101; }\n",
2340       "4:7: Extensions in proto3 are only allowed for defining options.\n"
2341       "2:13: Extension ranges are not allowed in proto3.\n");
2342 }
2343 
TEST_F(ParserValidationErrorTest,Proto3MessageSet)2344 TEST_F(ParserValidationErrorTest, Proto3MessageSet) {
2345   ExpectHasValidationErrors(
2346       "syntax = 'proto3';\n"
2347       "message Foo { \n"
2348       "  option message_set_wire_format = true;\n"
2349       "}\n",
2350       "1:8: MessageSet is not supported in proto3.\n");
2351 }
2352 
TEST_F(ParserValidationErrorTest,Proto3Required)2353 TEST_F(ParserValidationErrorTest, Proto3Required) {
2354   ExpectHasValidationErrors(
2355       "syntax = 'proto3';\n"
2356       "message Foo { \n"
2357       "  required int32 field = 1;"
2358       "}\n",
2359       "2:11: Required fields are not allowed in proto3.\n");
2360 }
2361 
TEST_F(ParserValidationErrorTest,Proto3Default)2362 TEST_F(ParserValidationErrorTest, Proto3Default) {
2363   ExpectHasValidationErrors(
2364       "syntax = 'proto3';\n"
2365       "message Foo { \n"
2366       "  int32 field = 1 [default = 12];"
2367       "}\n",
2368       "2:29: Explicit default values are not allowed in proto3.\n");
2369 }
2370 
TEST_F(ParserValidationErrorTest,Proto3JsonConflictError)2371 TEST_F(ParserValidationErrorTest, Proto3JsonConflictError) {
2372   ExpectHasValidationErrors(
2373       "syntax = 'proto3';\n"
2374       "message TestMessage {\n"
2375       "  uint32 _foo = 1;\n"
2376       "  uint32 Foo = 2;\n"
2377       "}\n",
2378       "3:9: The default JSON name of field \"Foo\" (\"Foo\") conflicts "
2379       "with the default JSON name of field \"_foo\".\n");
2380 }
2381 
TEST_F(ParserValidationErrorTest,Proto2JsonConflictError)2382 TEST_F(ParserValidationErrorTest, Proto2JsonConflictError) {
2383   ExpectParsesTo(
2384       "syntax = 'proto2';\n"
2385       "message TestMessage {\n"
2386       "  optional uint32 _foo = 1;\n"
2387       "  optional uint32 Foo = 2;\n"
2388       "}\n",
2389       "syntax: 'proto2'\n"
2390       "message_type {\n"
2391       "  name: 'TestMessage'\n"
2392       "  field {\n"
2393       "    label: LABEL_OPTIONAL type: TYPE_UINT32 name: '_foo' number: 1\n"
2394       "  }\n"
2395       "  field {\n"
2396       "    label: LABEL_OPTIONAL type: TYPE_UINT32 name: 'Foo' number: 2\n"
2397       "  }\n"
2398       "}\n");
2399 }
2400 
TEST_F(ParserValidationErrorTest,Proto3CustomJsonConflictWithDefaultError)2401 TEST_F(ParserValidationErrorTest, Proto3CustomJsonConflictWithDefaultError) {
2402   ExpectHasValidationErrors(
2403       "syntax = 'proto3';\n"
2404       "message TestMessage {\n"
2405       "  uint32 foo = 1 [json_name='bar'];\n"
2406       "  uint32 bar = 2;\n"
2407       "}\n",
2408       "3:9: The default JSON name of field \"bar\" (\"bar\") conflicts "
2409       "with the custom JSON name of field \"foo\".\n");
2410 }
2411 
TEST_F(ParserValidationErrorTest,Proto2CustomJsonConflictWithDefaultError)2412 TEST_F(ParserValidationErrorTest, Proto2CustomJsonConflictWithDefaultError) {
2413   ExpectParsesTo(
2414       "syntax = 'proto2';\n"
2415       "message TestMessage {\n"
2416       "  optional uint32 foo = 1 [json_name='bar'];\n"
2417       "  optional uint32 bar = 2;\n"
2418       "}\n",
2419       "syntax: 'proto2'\n"
2420       "message_type {\n"
2421       "  name: 'TestMessage'\n"
2422       "  field {\n"
2423       "    label: LABEL_OPTIONAL type: TYPE_UINT32 name: 'foo' number: 1 "
2424       "json_name: 'bar'\n"
2425       "  }\n"
2426       "  field {\n"
2427       "    label: LABEL_OPTIONAL type: TYPE_UINT32 name: 'bar' number: 2\n"
2428       "  }\n"
2429       "}\n");
2430 }
2431 
TEST_F(ParserValidationErrorTest,Proto3CustomJsonConflictError)2432 TEST_F(ParserValidationErrorTest, Proto3CustomJsonConflictError) {
2433   ExpectHasValidationErrors(
2434       "syntax = 'proto3';\n"
2435       "message TestMessage {\n"
2436       "  uint32 foo = 1 [json_name='baz'];\n"
2437       "  uint32 bar = 2 [json_name='baz'];\n"
2438       "}\n",
2439       "3:9: The custom JSON name of field \"bar\" (\"baz\") conflicts "
2440       "with the custom JSON name of field \"foo\".\n");
2441 }
2442 
TEST_F(ParserValidationErrorTest,Proto2CustomJsonConflictError)2443 TEST_F(ParserValidationErrorTest, Proto2CustomJsonConflictError) {
2444   ExpectHasValidationErrors(
2445       "syntax = 'proto2';\n"
2446       "message TestMessage {\n"
2447       "  optional uint32 foo = 1 [json_name='baz'];\n"
2448       "  optional uint32 bar = 2 [json_name='baz'];\n"
2449       "}\n",
2450       "3:18: The custom JSON name of field \"bar\" (\"baz\") conflicts "
2451       "with the custom JSON name of field \"foo\".\n");
2452 }
2453 
TEST_F(ParserValidationErrorTest,Proto3JsonConflictLegacy)2454 TEST_F(ParserValidationErrorTest, Proto3JsonConflictLegacy) {
2455   ExpectParsesTo(
2456       "syntax = 'proto3';\n"
2457       "message TestMessage {\n"
2458       "  option deprecated_legacy_json_field_conflicts = true;\n"
2459       "  uint32 fooBar = 1;\n"
2460       "  uint32 foo_bar = 2;\n"
2461       "}\n",
2462       "syntax: 'proto3'\n"
2463       "message_type {\n"
2464       "  name: 'TestMessage'\n"
2465       "  field {\n"
2466       "    label: LABEL_OPTIONAL type: TYPE_UINT32 name: 'fooBar' number: 1\n"
2467       "  }\n"
2468       "  field {\n"
2469       "    label: LABEL_OPTIONAL type: TYPE_UINT32 name: 'foo_bar' number: 2\n"
2470       "  }\n"
2471       "  options {\n"
2472       "    uninterpreted_option {\n"
2473       "      name {\n"
2474       "        name_part: 'deprecated_legacy_json_field_conflicts'\n"
2475       "        is_extension: false\n"
2476       "      }\n"
2477       "      identifier_value: 'true'\n"
2478       "    }\n"
2479       "  }\n"
2480       "}\n");
2481 }
2482 
TEST_F(ParserValidationErrorTest,Proto2JsonConflictLegacy)2483 TEST_F(ParserValidationErrorTest, Proto2JsonConflictLegacy) {
2484   ExpectParsesTo(
2485       "syntax = 'proto2';\n"
2486       "message TestMessage {\n"
2487       "  option deprecated_legacy_json_field_conflicts = true;\n"
2488       "  optional uint32 fooBar = 1;\n"
2489       "  optional uint32 foo_bar = 2;\n"
2490       "}\n",
2491       "syntax: 'proto2'\n"
2492       "message_type {\n"
2493       "  name: 'TestMessage'\n"
2494       "  field {\n"
2495       "    label: LABEL_OPTIONAL type: TYPE_UINT32 name: 'fooBar' number: 1\n"
2496       "  }\n"
2497       "  field {\n"
2498       "    label: LABEL_OPTIONAL type: TYPE_UINT32 name: 'foo_bar' number: 2\n"
2499       "  }\n"
2500       "  options {\n"
2501       "    uninterpreted_option {\n"
2502       "      name {\n"
2503       "        name_part: 'deprecated_legacy_json_field_conflicts'\n"
2504       "        is_extension: false\n"
2505       "      }\n"
2506       "      identifier_value: 'true'\n"
2507       "    }\n"
2508       "  }\n"
2509       "}\n");
2510 }
2511 
TEST_F(ParserValidationErrorTest,EnumNameError)2512 TEST_F(ParserValidationErrorTest, EnumNameError) {
2513   ExpectHasValidationErrors(
2514       "enum Foo {A = 1;}\n"
2515       "enum Foo {B = 1;}\n",
2516       "1:5: \"Foo\" is already defined.\n");
2517 }
2518 
TEST_F(ParserValidationErrorTest,Proto3EnumError)2519 TEST_F(ParserValidationErrorTest, Proto3EnumError) {
2520   ExpectHasValidationErrors(
2521       "syntax = 'proto3';\n"
2522       "enum Foo {A = 1;}\n",
2523       "1:14: The first enum value must be zero for open enums.\n");
2524 }
2525 
TEST_F(ParserValidationErrorTest,EnumValueNameError)2526 TEST_F(ParserValidationErrorTest, EnumValueNameError) {
2527   ExpectHasValidationErrors(
2528       "enum Foo {\n"
2529       "  BAR = 1;\n"
2530       "  BAR = 1;\n"
2531       "}\n",
2532       "2:2: \"BAR\" is already defined.\n");
2533 }
2534 
TEST_F(ParserValidationErrorTest,EnumValueAliasError)2535 TEST_F(ParserValidationErrorTest, EnumValueAliasError) {
2536   ExpectHasValidationErrors(
2537       "enum Foo {\n"
2538       "  BAR = 1;\n"
2539       "  BAZ = 1;\n"
2540       "}\n",
2541       "2:8: \"BAZ\" uses the same enum value as \"BAR\". If this is "
2542       "intended, set 'option allow_alias = true;' to the enum "
2543       "definition. The next available enum value is 2.\n");
2544 }
2545 
TEST_F(ParserValidationErrorTest,EnumReservedRangeError)2546 TEST_F(ParserValidationErrorTest, EnumReservedRangeError) {
2547   ExpectHasValidationErrors(
2548       "enum Foo {\n"
2549       "  BAR = 1;\n"
2550       "  reserved 2 to 1;\n"
2551       "}\n",
2552       "2:11: Reserved range end number must be greater than start number.\n");
2553 }
2554 
TEST_F(ParserValidationErrorTest,ExplicitlyMapEntryError)2555 TEST_F(ParserValidationErrorTest, ExplicitlyMapEntryError) {
2556   ExpectHasErrors(
2557       "message Foo {\n"
2558       "  message ValueEntry {\n"
2559       "    option map_entry = true;\n"
2560       "    optional int32 key = 1;\n"
2561       "    optional int32 value = 2;\n"
2562       "    extensions 99 to 999;\n"
2563       "  }\n"
2564       "}",
2565       "2:11: map_entry should not be set explicitly. Use "
2566       "map<KeyType, ValueType> instead.\n");
2567 }
2568 
TEST_F(ParserValidationErrorTest,ServiceNameError)2569 TEST_F(ParserValidationErrorTest, ServiceNameError) {
2570   ExpectHasValidationErrors(
2571       "service Foo {}\n"
2572       "service Foo {}\n",
2573       "1:8: \"Foo\" is already defined.\n");
2574 }
2575 
TEST_F(ParserValidationErrorTest,MethodNameError)2576 TEST_F(ParserValidationErrorTest, MethodNameError) {
2577   ExpectHasValidationErrors(
2578       "message Baz {}\n"
2579       "service Foo {\n"
2580       "  rpc Bar(Baz) returns(Baz);\n"
2581       "  rpc Bar(Baz) returns(Baz);\n"
2582       "}\n",
2583       "3:6: \"Bar\" is already defined in \"Foo\".\n");
2584 }
2585 
2586 
TEST_F(ParserValidationErrorTest,MethodInputTypeError)2587 TEST_F(ParserValidationErrorTest, MethodInputTypeError) {
2588   ExpectHasValidationErrors(
2589       "message Baz {}\n"
2590       "service Foo {\n"
2591       "  rpc Bar(Qux) returns(Baz);\n"
2592       "}\n",
2593       "2:10: \"Qux\" is not defined.\n");
2594 }
2595 
2596 
TEST_F(ParserValidationErrorTest,MethodOutputTypeError)2597 TEST_F(ParserValidationErrorTest, MethodOutputTypeError) {
2598   ExpectHasValidationErrors(
2599       "message Baz {}\n"
2600       "service Foo {\n"
2601       "  rpc Bar(Baz) returns(Qux);\n"
2602       "}\n",
2603       "2:23: \"Qux\" is not defined.\n");
2604 }
2605 
2606 
TEST_F(ParserValidationErrorTest,ResolvedUndefinedError)2607 TEST_F(ParserValidationErrorTest, ResolvedUndefinedError) {
2608   // Create another file which defines symbol ".base.bar".
2609   FileDescriptorProto other_file;
2610   other_file.set_name("base.proto");
2611   other_file.set_package("base");
2612   other_file.add_message_type()->set_name("bar");
2613   EXPECT_TRUE(pool_.BuildFile(other_file) != nullptr);
2614 
2615   // Define "foo.base" and try "base.bar".
2616   // "base.bar" is resolved to "foo.base.bar" which is not defined.
2617   ExpectHasValidationErrors(
2618       "package foo.base;\n"
2619       "import \"base.proto\";\n"
2620       "message qux {\n"
2621       "  optional base.bar baz = 1;\n"
2622       "  optional .base.bar quz = 2;\n"
2623       "}\n",
2624       "3:11: \"base.bar\" is resolved to \"foo.base.bar\","
2625       " which is not defined. The innermost scope is searched first "
2626       "in name resolution. Consider using a leading '.'(i.e., \".base.bar\")"
2627       " to start from the outermost scope.\n");
2628 }
2629 
TEST_F(ParserValidationErrorTest,ResolvedUndefinedOptionError)2630 TEST_F(ParserValidationErrorTest, ResolvedUndefinedOptionError) {
2631   // Build descriptor message in test pool
2632   FileDescriptorProto descriptor_proto;
2633   DescriptorProto::descriptor()->file()->CopyTo(&descriptor_proto);
2634   ASSERT_TRUE(pool_.BuildFile(descriptor_proto) != nullptr);
2635 
2636   // base2.proto:
2637   //   package baz
2638   //   import google/protobuf/descriptor.proto
2639   //   message Bar { optional int32 foo = 1; }
2640   //   extend FileOptions { optional Bar bar = 7672757; }
2641   FileDescriptorProto other_file;
2642   other_file.set_name("base2.proto");
2643   other_file.set_package("baz");
2644   other_file.add_dependency();
2645   other_file.set_dependency(0, descriptor_proto.name());
2646 
2647   DescriptorProto* message(other_file.add_message_type());
2648   message->set_name("Bar");
2649   FieldDescriptorProto* field(message->add_field());
2650   field->set_name("foo");
2651   field->set_number(1);
2652   field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
2653   field->set_type(FieldDescriptorProto::TYPE_INT32);
2654 
2655   FieldDescriptorProto* extension(other_file.add_extension());
2656   extension->set_name("bar");
2657   extension->set_number(7672757);
2658   extension->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
2659   extension->set_type(FieldDescriptorProto::TYPE_MESSAGE);
2660   extension->set_type_name("Bar");
2661   extension->set_extendee("google.protobuf.FileOptions");
2662 
2663   EXPECT_TRUE(pool_.BuildFile(other_file) != nullptr);
2664 
2665   // qux.proto:
2666   //   package qux.baz
2667   //   option (baz.bar).foo = 1;
2668   //
2669   // Although "baz.bar" is already defined, the lookup code will try
2670   // "qux.baz.bar", since it's the match from the innermost scope,
2671   // which will cause a symbol not defined error.
2672   ExpectHasValidationErrors(
2673       "package qux.baz;\n"
2674       "import \"base2.proto\";\n"
2675       "option (baz.bar).foo = 1;\n",
2676       "2:7: Option \"(baz.bar)\" is resolved to \"(qux.baz.bar)\","
2677       " which is not defined. The innermost scope is searched first "
2678       "in name resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\")"
2679       " to start from the outermost scope.\n");
2680 }
2681 
2682 // ===================================================================
2683 // Test that the output from FileDescriptor::DebugString() (and all other
2684 // descriptor types) is parseable, and results in the same Descriptor
2685 // definitions again afoter parsing (note, however, that the order of messages
2686 // cannot be guaranteed to be the same)
2687 
2688 typedef ParserTest ParseDescriptorDebugTest;
2689 
2690 class CompareDescriptorNames {
2691  public:
operator ()(const DescriptorProto * left,const DescriptorProto * right) const2692   bool operator()(const DescriptorProto* left,
2693                   const DescriptorProto* right) const {
2694     return left->name() < right->name();
2695   }
2696 };
2697 
2698 // Sorts nested DescriptorProtos of a DescriptorProto, by name.
SortMessages(DescriptorProto * descriptor_proto)2699 void SortMessages(DescriptorProto* descriptor_proto) {
2700   int size = descriptor_proto->nested_type_size();
2701   // recursively sort; we can't guarantee the order of nested messages either
2702   for (int i = 0; i < size; ++i) {
2703     SortMessages(descriptor_proto->mutable_nested_type(i));
2704   }
2705   DescriptorProto** data =
2706       descriptor_proto->mutable_nested_type()->mutable_data();
2707   std::sort(data, data + size, CompareDescriptorNames());
2708 }
2709 
2710 // Sorts DescriptorProtos belonging to a FileDescriptorProto, by name.
SortMessages(FileDescriptorProto * file_descriptor_proto)2711 void SortMessages(FileDescriptorProto* file_descriptor_proto) {
2712   int size = file_descriptor_proto->message_type_size();
2713   // recursively sort; we can't guarantee the order of nested messages either
2714   for (int i = 0; i < size; ++i) {
2715     SortMessages(file_descriptor_proto->mutable_message_type(i));
2716   }
2717   DescriptorProto** data =
2718       file_descriptor_proto->mutable_message_type()->mutable_data();
2719   std::sort(data, data + size, CompareDescriptorNames());
2720 }
2721 
2722 // Strips the message and enum field type names for comparison purpose only.
StripFieldTypeName(DescriptorProto * proto)2723 void StripFieldTypeName(DescriptorProto* proto) {
2724   for (int i = 0; i < proto->field_size(); ++i) {
2725     std::string type_name = proto->field(i).type_name();
2726     std::string::size_type pos = type_name.find_last_of('.');
2727     if (pos != std::string::npos) {
2728       proto->mutable_field(i)->mutable_type_name()->assign(
2729           type_name.begin() + pos + 1, type_name.end());
2730     }
2731   }
2732   for (int i = 0; i < proto->nested_type_size(); ++i) {
2733     StripFieldTypeName(proto->mutable_nested_type(i));
2734   }
2735 }
2736 
StripFieldTypeName(FileDescriptorProto * file_proto)2737 void StripFieldTypeName(FileDescriptorProto* file_proto) {
2738   for (int i = 0; i < file_proto->message_type_size(); ++i) {
2739     StripFieldTypeName(file_proto->mutable_message_type(i));
2740   }
2741 }
2742 
StripEmptyOptions(DescriptorProto & proto)2743 void StripEmptyOptions(DescriptorProto& proto) {
2744   for (auto& ext : *proto.mutable_extension_range()) {
2745     if (ext.has_options() && ext.options().DebugString().empty()) {
2746       ext.clear_options();
2747     }
2748   }
2749 }
2750 
StripEmptyOptions(FileDescriptorProto & file_proto)2751 void StripEmptyOptions(FileDescriptorProto& file_proto) {
2752   if (file_proto.message_type_size() == 0) {
2753     return;
2754   }
2755   for (auto& msg : *file_proto.mutable_message_type()) {
2756     StripEmptyOptions(msg);
2757   }
2758 }
2759 
TEST_F(ParseDescriptorDebugTest,TestAllDescriptorTypes)2760 TEST_F(ParseDescriptorDebugTest, TestAllDescriptorTypes) {
2761   const FileDescriptor* original_file =
2762       protobuf_unittest::TestAllTypes::descriptor()->file();
2763   FileDescriptorProto expected;
2764   original_file->CopyTo(&expected);
2765   StripEmptyOptions(expected);
2766 
2767   // Get the DebugString of the unittest.proto FileDescriptor, which includes
2768   // all other descriptor types
2769   std::string debug_string = original_file->DebugString();
2770 
2771   // Parse the debug string
2772   SetupParser(debug_string.c_str());
2773   FileDescriptorProto parsed;
2774   parser_->Parse(input_.get(), &parsed);
2775   EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
2776   ASSERT_EQ("", error_collector_.text_) << "Failed to parse:\n" << debug_string;
2777 
2778   // We now have a FileDescriptorProto, but to compare with the expected we
2779   // need to link to a FileDescriptor, then output back to a proto. We'll
2780   // also need to give it the same name as the original.
2781   parsed.set_name("google/protobuf/unittest.proto");
2782   // We need the imported dependency before we can build our parsed proto
2783   const FileDescriptor* public_import =
2784       protobuf_unittest_import::PublicImportMessage::descriptor()->file();
2785   FileDescriptorProto public_import_proto;
2786   public_import->CopyTo(&public_import_proto);
2787   ASSERT_TRUE(pool_.BuildFile(public_import_proto) != nullptr);
2788   const FileDescriptor* import =
2789       protobuf_unittest_import::ImportMessage::descriptor()->file();
2790   FileDescriptorProto import_proto;
2791   import->CopyTo(&import_proto);
2792   ASSERT_TRUE(pool_.BuildFile(import_proto) != nullptr);
2793   const FileDescriptor* actual = pool_.BuildFile(parsed);
2794   parsed.Clear();
2795   ASSERT_TRUE(actual != nullptr) << "Failed to validate:\n" << debug_string;
2796   actual->CopyTo(&parsed);
2797   ASSERT_TRUE(actual != nullptr);
2798 
2799   // The messages might be in different orders, making them hard to compare.
2800   // So, sort the messages in the descriptor protos (including nested messages,
2801   // recursively).
2802   SortMessages(&expected);
2803   SortMessages(&parsed);
2804 
2805   // I really wanted to use StringDiff here for the debug output on fail,
2806   // but the strings are too long for it, and if I increase its max size,
2807   // we get a memory allocation failure :(
2808   EXPECT_EQ(expected.DebugString(), parsed.DebugString());
2809 }
2810 
TEST_F(ParseDescriptorDebugTest,TestCustomOptions)2811 TEST_F(ParseDescriptorDebugTest, TestCustomOptions) {
2812   const FileDescriptor* original_file =
2813       protobuf_unittest::AggregateMessage::descriptor()->file();
2814   FileDescriptorProto expected;
2815   original_file->CopyTo(&expected);
2816 
2817   std::string debug_string = original_file->DebugString();
2818 
2819   // Parse the debug string
2820   SetupParser(debug_string.c_str());
2821   FileDescriptorProto parsed;
2822   parser_->Parse(input_.get(), &parsed);
2823   EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
2824   ASSERT_EQ("", error_collector_.text_);
2825 
2826   // We now have a FileDescriptorProto, but to compare with the expected we
2827   // need to link to a FileDescriptor, then output back to a proto. We'll
2828   // also need to give it the same name as the original.
2829   parsed.set_name(original_file->name());
2830 
2831   // unittest_custom_options.proto depends on descriptor.proto.
2832   const FileDescriptor* import = FileDescriptorProto::descriptor()->file();
2833   FileDescriptorProto import_proto;
2834   import->CopyTo(&import_proto);
2835   ASSERT_TRUE(pool_.BuildFile(import_proto) != nullptr);
2836 
2837   FileDescriptorProto any_import;
2838   google::protobuf::Any::descriptor()->file()->CopyTo(&any_import);
2839   ASSERT_TRUE(pool_.BuildFile(any_import) != nullptr);
2840 
2841   const FileDescriptor* actual = pool_.BuildFile(parsed);
2842   ASSERT_TRUE(actual != nullptr) << error_collector_.text_;
2843   parsed.Clear();
2844   actual->CopyTo(&parsed);
2845 
2846   // The messages might be in different orders, making them hard to compare.
2847   // So, sort the messages in the descriptor protos (including nested messages,
2848   // recursively).
2849   SortMessages(&expected);
2850   SortMessages(&parsed);
2851 
2852   EXPECT_EQ(expected.DebugString(), parsed.DebugString());
2853 }
2854 
2855 // Ensure that DebugStringWithOptions(), with |include_comments| set to true,
2856 // includes comments from the original parser input in all of the appropriate
2857 // places.
TEST_F(ParseDescriptorDebugTest,TestCommentsInDebugString)2858 TEST_F(ParseDescriptorDebugTest, TestCommentsInDebugString) {
2859   SetupParser(
2860       "// Detached comment before syntax.\n"
2861       "\n"
2862       "// Syntax comment.\n"
2863       "syntax = \"proto2\";\n"
2864       "\n"
2865       "// Detached comment before package.\n"
2866       "\n"
2867       "// Package comment.\n"
2868       "package comment_test;\n"
2869       "\n"
2870       "// Detached comment before TestMessage1.\n"
2871       "\n"
2872       "// Message comment.\n"
2873       "//\n"
2874       "// More detail in message comment.\n"
2875       "message TestMessage1 {\n"
2876       "\n"
2877       "  // Detached comment before foo.\n"
2878       "\n"
2879       "  // Field comment.\n"
2880       "  optional int32 foo = 1;\n"
2881       "\n"
2882       "  // Detached comment before NestedMessage.\n"
2883       "\n"
2884       "  // Nested-message comment.\n"
2885       "  message NestedMessage {\n"
2886       "    optional int32 bar = 1;\n"
2887       "  }\n"
2888       "}\n"
2889       "\n"
2890       "// Detached comment before MyEnumType.\n"
2891       "\n"
2892       "// Enum comment.\n"
2893       "enum MyEnumType {\n"
2894       "\n"
2895       "  // Detached comment before ASDF.\n"
2896       "\n"
2897       "  // Enum-value comment.\n"
2898       "  ASDF = 1;\n"
2899       "}\n"
2900       "\n"
2901       "// Detached comment before MyService.\n"
2902       "\n"
2903       "// Service comment.\n"
2904       "service MyService {\n"
2905       "\n"
2906       "  // Detached comment before MyRPCCall.\n"
2907       "\n"
2908       "  // RPC comment.\n"
2909       "  rpc MyRPCCall(TestMessage1) returns (TestMessage1) { }\n"
2910       "}\n");
2911 
2912   FileDescriptorProto parsed_desc;
2913   parsed_desc.set_name("foo.proto");
2914   SourceLocationTable source_locations;
2915   parser_->RecordSourceLocationsTo(&source_locations);
2916   parser_->Parse(input_.get(), &parsed_desc);
2917   EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
2918   ASSERT_EQ("", error_collector_.text_);
2919 
2920   // We need to import the FileDescriptorProto to get a FileDescriptor.
2921   MockValidationErrorCollector collector(source_locations, &error_collector_);
2922   const FileDescriptor* descriptor =
2923       pool_.BuildFileCollectingErrors(parsed_desc, &collector);
2924   ASSERT_TRUE(descriptor != nullptr);
2925 
2926   // Ensure that each of the comments appears somewhere in the DebugString().
2927   // We don't test the exact comment placement or formatting, because we do not
2928   // want to be too fragile here.
2929   const char* expected_comments[] = {
2930       "Detached comment before syntax.",
2931       "Syntax comment.",
2932       "Detached comment before package.",
2933       "Package comment.",
2934       "Detached comment before TestMessage1.",
2935       "Message comment.",
2936       "More detail in message comment.",
2937       "Detached comment before foo.",
2938       "Field comment",
2939       "Detached comment before NestedMessage.",
2940       "Nested-message comment",
2941       "Detached comment before MyEnumType.",
2942       "Enum comment",
2943       "Detached comment before ASDF.",
2944       "Enum-value comment",
2945       "Detached comment before MyService.",
2946       "Service comment",
2947       "Detached comment before MyRPCCall.",
2948       "RPC comment",
2949   };
2950 
2951   DebugStringOptions debug_string_options;
2952   debug_string_options.include_comments = true;
2953 
2954   {
2955     const std::string debug_string =
2956         descriptor->DebugStringWithOptions(debug_string_options);
2957 
2958     for (int i = 0; i < ABSL_ARRAYSIZE(expected_comments); ++i) {
2959       std::string::size_type found_pos =
2960           debug_string.find(expected_comments[i]);
2961       EXPECT_TRUE(found_pos != std::string::npos)
2962           << "\"" << expected_comments[i] << "\" not found.";
2963     }
2964 
2965     // Result of DebugStringWithOptions should be parseable.
2966     SetupParser(debug_string.c_str());
2967     FileDescriptorProto parsed;
2968     parser_->Parse(input_.get(), &parsed);
2969     EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
2970     ASSERT_EQ("", error_collector_.text_) << "Failed to parse:\n"
2971                                           << debug_string;
2972   }
2973 
2974 }
2975 
TEST_F(ParseDescriptorDebugTest,TestMaps)2976 TEST_F(ParseDescriptorDebugTest, TestMaps) {
2977   SetupParser(
2978       "syntax = \"proto3\"; "
2979       "message Foo { "
2980       "  message Bar { } "
2981       "  map<int32, Bar> enum_message_map = 1; "
2982       "  map<string, float> primitive_map = 2; "
2983       "} ");
2984   FileDescriptorProto original;
2985   EXPECT_TRUE(parser_->Parse(input_.get(), &original));
2986   original.set_name("foo.proto");
2987   const FileDescriptor* file = pool_.BuildFile(original);
2988   ASSERT_TRUE(file != nullptr);
2989 
2990   // Make sure the debug string uses map syntax and does not have the auto
2991   // generated entry.
2992   std::string debug_string = file->DebugString();
2993   EXPECT_TRUE(debug_string.find("map<") != std::string::npos);
2994   EXPECT_TRUE(debug_string.find("option map_entry") == std::string::npos);
2995   EXPECT_TRUE(debug_string.find("MapEntry") == std::string::npos);
2996 
2997   // Make sure the descriptor debug string is parsable.
2998   FileDescriptorProto parsed;
2999   SetupParser(debug_string.c_str());
3000   parsed.set_name("foo.proto");
3001   ASSERT_TRUE(parser_->Parse(input_.get(), &parsed));
3002 
3003   original.clear_source_code_info();
3004   parsed.clear_source_code_info();
3005   StripFieldTypeName(&original);
3006   StripFieldTypeName(&parsed);
3007   EXPECT_EQ(original.DebugString(), parsed.DebugString());
3008 }
3009 
3010 // ===================================================================
3011 // SourceCodeInfo tests.
3012 
3013 // Follows a path -- as defined by SourceCodeInfo.Location.path -- from a
3014 // message to a particular sub-field.
3015 // * If the target is itself a message, sets *output_message to point at it,
3016 //   *output_field to NULL, and *output_index to -1.
3017 // * Otherwise, if the target is an element of a repeated field, sets
3018 //   *output_message to the containing message, *output_field to the descriptor
3019 //   of the field, and *output_index to the index of the element.
3020 // * Otherwise, the target is a field (possibly a repeated field, but not any
3021 //   one element).  Sets *output_message to the containing message,
3022 //   *output_field to the descriptor of the field, and *output_index to -1.
3023 // Returns true if the path was valid, false otherwise.  A gTest failure is
3024 // recorded before returning false.
FollowPath(const Message & root,RepeatedField<int>::const_iterator path_begin,RepeatedField<int>::const_iterator path_end,const Message ** output_message,const FieldDescriptor ** output_field,int * output_index)3025 bool FollowPath(const Message& root,
3026                 RepeatedField<int>::const_iterator path_begin,
3027                 RepeatedField<int>::const_iterator path_end,
3028                 const Message** output_message,
3029                 const FieldDescriptor** output_field, int* output_index) {
3030   if (path_begin == path_end) {
3031     // Path refers to this whole message.
3032     *output_message = &root;
3033     *output_field = nullptr;
3034     *output_index = -1;
3035     return true;
3036   }
3037 
3038   const Descriptor* descriptor = root.GetDescriptor();
3039   const Reflection* reflection = root.GetReflection();
3040 
3041   const FieldDescriptor* field = descriptor->FindFieldByNumber(*path_begin);
3042 
3043   if (field == nullptr) {
3044     ADD_FAILURE() << descriptor->name()
3045                   << " has no field number: " << *path_begin;
3046     return false;
3047   }
3048 
3049   ++path_begin;
3050 
3051   if (field->is_repeated()) {
3052     if (path_begin == path_end) {
3053       // Path refers to the whole repeated field.
3054       *output_message = &root;
3055       *output_field = field;
3056       *output_index = -1;
3057       return true;
3058     }
3059 
3060     int index = *path_begin++;
3061     int size = reflection->FieldSize(root, field);
3062 
3063     if (index >= size) {
3064       ADD_FAILURE() << descriptor->name() << "." << field->name()
3065                     << " has size " << size
3066                     << ", but path contained index: " << index;
3067       return false;
3068     }
3069 
3070     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
3071       // Descend into child message.
3072       const Message& child = reflection->GetRepeatedMessage(root, field, index);
3073       return FollowPath(child, path_begin, path_end, output_message,
3074                         output_field, output_index);
3075     } else if (path_begin == path_end) {
3076       // Path refers to this element.
3077       *output_message = &root;
3078       *output_field = field;
3079       *output_index = index;
3080       return true;
3081     } else {
3082       ADD_FAILURE() << descriptor->name() << "." << field->name()
3083                     << " is not a message; cannot descend into it.";
3084       return false;
3085     }
3086   } else {
3087     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
3088       const Message& child = reflection->GetMessage(root, field);
3089       return FollowPath(child, path_begin, path_end, output_message,
3090                         output_field, output_index);
3091     } else if (path_begin == path_end) {
3092       // Path refers to this field.
3093       *output_message = &root;
3094       *output_field = field;
3095       *output_index = -1;
3096       return true;
3097     } else {
3098       ADD_FAILURE() << descriptor->name() << "." << field->name()
3099                     << " is not a message; cannot descend into it.";
3100       return false;
3101     }
3102   }
3103 }
3104 
3105 // Check if two spans are equal.
CompareSpans(const RepeatedField<int> & span1,const RepeatedField<int> & span2)3106 bool CompareSpans(const RepeatedField<int>& span1,
3107                   const RepeatedField<int>& span2) {
3108   if (span1.size() != span2.size()) return false;
3109   for (int i = 0; i < span1.size(); i++) {
3110     if (span1.Get(i) != span2.Get(i)) return false;
3111   }
3112   return true;
3113 }
3114 
3115 // Test fixture for source info tests, which check that source locations are
3116 // recorded correctly in FileDescriptorProto.source_code_info.location.
3117 class SourceInfoTest : public ParserTest {
3118  protected:
3119   // The parsed file (initialized by Parse()).
3120   FileDescriptorProto file_;
3121 
3122   // Parse the given text as a .proto file and populate the spans_ map with
3123   // all the source location spans in its SourceCodeInfo table.
Parse(const char * text)3124   bool Parse(const char* text) {
3125     ExtractMarkers(text);
3126     SetupParser(text_without_markers_.c_str());
3127     if (!parser_->Parse(input_.get(), &file_)) {
3128       return false;
3129     }
3130 
3131     const SourceCodeInfo& source_info = file_.source_code_info();
3132     for (int i = 0; i < source_info.location_size(); i++) {
3133       const SourceCodeInfo::Location& location = source_info.location(i);
3134       const Message* descriptor_proto = nullptr;
3135       const FieldDescriptor* field = nullptr;
3136       int index = 0;
3137       if (!FollowPath(file_, location.path().begin(), location.path().end(),
3138                       &descriptor_proto, &field, &index)) {
3139         return false;
3140       }
3141 
3142       spans_[SpanKey(*descriptor_proto, field, index)].push_back(&location);
3143     }
3144 
3145     return true;
3146   }
3147 
TearDown()3148   void TearDown() override {
3149     for (auto& kv : spans_) {
3150       EXPECT_TRUE(kv.second.empty())
3151           << "Forgot to call HasSpan() for "
3152           << (*kv.second.begin())->DebugString() << " spans.";
3153     }
3154   }
3155 
3156   // -----------------------------------------------------------------
3157   // HasSpan() checks that the span of source code delimited by the given
3158   // tags (comments) correspond via the SourceCodeInfo table to the given
3159   // part of the FileDescriptorProto.  (If unclear, look at the actual tests;
3160   // it should quickly become obvious.)
3161 
HasSpan(char start_marker,char end_marker,const Message & descriptor_proto)3162   bool HasSpan(char start_marker, char end_marker,
3163                const Message& descriptor_proto) {
3164     return HasSpanWithComment(start_marker, end_marker, descriptor_proto,
3165                               nullptr, -1, nullptr, nullptr, nullptr);
3166   }
3167 
HasSpanWithComment(char start_marker,char end_marker,const Message & descriptor_proto,const char * expected_leading_comments,const char * expected_trailing_comments,const char * expected_leading_detached_comments)3168   bool HasSpanWithComment(char start_marker, char end_marker,
3169                           const Message& descriptor_proto,
3170                           const char* expected_leading_comments,
3171                           const char* expected_trailing_comments,
3172                           const char* expected_leading_detached_comments) {
3173     return HasSpanWithComment(start_marker, end_marker, descriptor_proto,
3174                               nullptr, -1, expected_leading_comments,
3175                               expected_trailing_comments,
3176                               expected_leading_detached_comments);
3177   }
3178 
HasSpan(char start_marker,char end_marker,const Message & descriptor_proto,const std::string & field_name)3179   bool HasSpan(char start_marker, char end_marker,
3180                const Message& descriptor_proto, const std::string& field_name) {
3181     return HasSpan(start_marker, end_marker, descriptor_proto, field_name, -1);
3182   }
3183 
HasSpan(char start_marker,char end_marker,const Message & descriptor_proto,const std::string & field_name,int index)3184   bool HasSpan(char start_marker, char end_marker,
3185                const Message& descriptor_proto, const std::string& field_name,
3186                int index) {
3187     return HasSpan(start_marker, end_marker, descriptor_proto, field_name,
3188                    index, nullptr, nullptr, nullptr);
3189   }
3190 
HasSpan(char start_marker,char end_marker,const Message & descriptor_proto,const std::string & field_name,int index,const char * expected_leading_comments,const char * expected_trailing_comments,const char * expected_leading_detached_comments)3191   bool HasSpan(char start_marker, char end_marker,
3192                const Message& descriptor_proto, const std::string& field_name,
3193                int index, const char* expected_leading_comments,
3194                const char* expected_trailing_comments,
3195                const char* expected_leading_detached_comments) {
3196     const FieldDescriptor* field =
3197         descriptor_proto.GetDescriptor()->FindFieldByName(field_name);
3198     if (field == nullptr) {
3199       ADD_FAILURE() << descriptor_proto.GetDescriptor()->name()
3200                     << " has no such field: " << field_name;
3201       return false;
3202     }
3203 
3204     return HasSpanWithComment(start_marker, end_marker, descriptor_proto, field,
3205                               index, expected_leading_comments,
3206                               expected_trailing_comments,
3207                               expected_leading_detached_comments);
3208   }
3209 
HasSpan(const Message & descriptor_proto)3210   bool HasSpan(const Message& descriptor_proto) {
3211     return HasSpanWithComment('\0', '\0', descriptor_proto, nullptr, -1,
3212                               nullptr, nullptr, nullptr);
3213   }
3214 
HasSpan(const Message & descriptor_proto,const std::string & field_name)3215   bool HasSpan(const Message& descriptor_proto, const std::string& field_name) {
3216     return HasSpan('\0', '\0', descriptor_proto, field_name, -1);
3217   }
3218 
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,const char * expected_leading_detached_comments)3219   bool HasSpanWithComment(char start_marker, char end_marker,
3220                           const Message& descriptor_proto,
3221                           const FieldDescriptor* field, int index,
3222                           const char* expected_leading_comments,
3223                           const char* expected_trailing_comments,
3224                           const char* expected_leading_detached_comments) {
3225     SpanKey key(descriptor_proto, field, index);
3226     if (start_marker == '\0') {
3227       auto old = spans_.extract(key);
3228       // Return true if we actually removed something.
3229       return !(old.empty() || old.mapped().empty());
3230     }
3231 
3232     std::vector<const SourceCodeInfo::Location*>& range = spans_[key];
3233     std::pair<int, int> start_pos = markers_.at(start_marker);
3234     std::pair<int, int> end_pos = markers_.at(end_marker);
3235 
3236     RepeatedField<int> expected_span;
3237     expected_span.Add(start_pos.first);
3238     expected_span.Add(start_pos.second);
3239     if (end_pos.first != start_pos.first) {
3240       expected_span.Add(end_pos.first);
3241     }
3242     expected_span.Add(end_pos.second);
3243 
3244     for (auto iter = range.begin(); iter != range.end(); ++iter) {
3245       const SourceCodeInfo::Location* location = *iter;
3246       if (CompareSpans(expected_span, location->span())) {
3247         if (expected_leading_comments == nullptr) {
3248           EXPECT_FALSE(location->has_leading_comments());
3249         } else {
3250           EXPECT_TRUE(location->has_leading_comments());
3251           EXPECT_EQ(expected_leading_comments, location->leading_comments());
3252         }
3253         if (expected_trailing_comments == nullptr) {
3254           EXPECT_FALSE(location->has_trailing_comments());
3255         } else {
3256           EXPECT_TRUE(location->has_trailing_comments());
3257           EXPECT_EQ(expected_trailing_comments, location->trailing_comments());
3258         }
3259         if (expected_leading_detached_comments == nullptr) {
3260           EXPECT_EQ(0, location->leading_detached_comments_size());
3261         } else {
3262           EXPECT_EQ(expected_leading_detached_comments,
3263                     absl::StrJoin(location->leading_detached_comments(), "\n"));
3264         }
3265         range.erase(iter);
3266         return true;
3267       }
3268     }
3269 
3270     return false;
3271   }
3272 
3273  private:
3274   struct SpanKey {
3275     const Message* descriptor_proto;
3276     const FieldDescriptor* field;
3277     int index;
3278 
3279     inline SpanKey() = default;
SpanKeygoogle::protobuf::compiler::__anon78e44b510111::SourceInfoTest::SpanKey3280     inline SpanKey(const Message& descriptor_proto_param,
3281                    const FieldDescriptor* field_param, int index_param)
3282         : descriptor_proto(&descriptor_proto_param),
3283           field(field_param),
3284           index(index_param) {}
3285 
3286     template <typename H>
AbslHashValue(H h,const SpanKey & key)3287     friend H AbslHashValue(H h, const SpanKey& key) {
3288       return H::combine(std::move(h), key.descriptor_proto, key.field,
3289                         key.index);
3290     }
3291 
operator ==(const SpanKey & lhs,const SpanKey & rhs)3292     friend bool operator==(const SpanKey& lhs, const SpanKey& rhs) {
3293       return lhs.descriptor_proto == rhs.descriptor_proto &&  //
3294              lhs.field == rhs.field &&                        //
3295              lhs.index == rhs.index;
3296     }
3297   };
3298 
3299   absl::flat_hash_map<SpanKey, std::vector<const SourceCodeInfo::Location*>>
3300       spans_;
3301   absl::flat_hash_map<char, std::pair<int, int>> markers_;
3302   std::string text_without_markers_;
3303 
ExtractMarkers(const char * text)3304   void ExtractMarkers(const char* text) {
3305     markers_.clear();
3306     text_without_markers_.clear();
3307     int line = 0;
3308     int column = 0;
3309     while (*text != '\0') {
3310       if (*text == '$') {
3311         ++text;
3312         ABSL_CHECK_NE('\0', *text);
3313         if (*text == '$') {
3314           text_without_markers_ += '$';
3315           ++column;
3316         } else {
3317           markers_[*text] = std::make_pair(line, column);
3318           ++text;
3319           ABSL_CHECK_EQ('$', *text);
3320         }
3321       } else if (*text == '\n') {
3322         ++line;
3323         column = 0;
3324         text_without_markers_ += *text;
3325       } else {
3326         text_without_markers_ += *text;
3327         ++column;
3328       }
3329       ++text;
3330     }
3331   }
3332 };
3333 
TEST_F(SourceInfoTest,BasicFileDecls)3334 TEST_F(SourceInfoTest, BasicFileDecls) {
3335   EXPECT_TRUE(
3336       Parse("$a$syntax = \"proto2\";$i$\n"
3337             "$b$package foo.bar;$c$\n"
3338             "$d$import \"baz.proto\";$e$\n"
3339             "$f$import\"qux.proto\";$h$\n"
3340             "$j$import $k$public$l$ \"bar.proto\";$m$\n"
3341             "$n$import $o$weak$p$ \"bar.proto\";$q$\n"
3342             "\n"
3343             "// comment ignored\n"));
3344 
3345   EXPECT_TRUE(HasSpan('a', 'q', file_));
3346   EXPECT_TRUE(HasSpan('b', 'c', file_, "package"));
3347   EXPECT_TRUE(HasSpan('d', 'e', file_, "dependency", 0));
3348   EXPECT_TRUE(HasSpan('f', 'h', file_, "dependency", 1));
3349   EXPECT_TRUE(HasSpan('j', 'm', file_, "dependency", 2));
3350   EXPECT_TRUE(HasSpan('k', 'l', file_, "public_dependency", 0));
3351   EXPECT_TRUE(HasSpan('n', 'q', file_, "dependency", 3));
3352   EXPECT_TRUE(HasSpan('o', 'p', file_, "weak_dependency", 0));
3353   EXPECT_TRUE(HasSpan('a', 'i', file_, "syntax"));
3354 }
3355 
TEST_F(SourceInfoTest,Messages)3356 TEST_F(SourceInfoTest, Messages) {
3357   EXPECT_TRUE(
3358       Parse("$a$message $b$Foo$c$ {}$d$\n"
3359             "$e$message $f$Bar$g$ {}$h$\n"));
3360 
3361   EXPECT_TRUE(HasSpan('a', 'd', file_.message_type(0)));
3362   EXPECT_TRUE(HasSpan('b', 'c', file_.message_type(0), "name"));
3363   EXPECT_TRUE(HasSpan('e', 'h', file_.message_type(1)));
3364   EXPECT_TRUE(HasSpan('f', 'g', file_.message_type(1), "name"));
3365 
3366   // Ignore these.
3367   EXPECT_TRUE(HasSpan(file_));
3368 }
3369 
TEST_F(SourceInfoTest,Fields)3370 TEST_F(SourceInfoTest, Fields) {
3371   EXPECT_TRUE(
3372       Parse("message Foo {\n"
3373             "  $a$optional$b$ $c$int32$d$ $e$bar$f$ = $g$1$h$;$i$\n"
3374             "  $j$repeated$k$ $l$X.Y$m$ $n$baz$o$ = $p$2$q$;$r$\n"
3375             "}\n"));
3376 
3377   const FieldDescriptorProto& field1 = file_.message_type(0).field(0);
3378   const FieldDescriptorProto& field2 = file_.message_type(0).field(1);
3379 
3380   EXPECT_TRUE(HasSpan('a', 'i', field1));
3381   EXPECT_TRUE(HasSpan('a', 'b', field1, "label"));
3382   EXPECT_TRUE(HasSpan('c', 'd', field1, "type"));
3383   EXPECT_TRUE(HasSpan('e', 'f', field1, "name"));
3384   EXPECT_TRUE(HasSpan('g', 'h', field1, "number"));
3385 
3386   EXPECT_TRUE(HasSpan('j', 'r', field2));
3387   EXPECT_TRUE(HasSpan('j', 'k', field2, "label"));
3388   EXPECT_TRUE(HasSpan('l', 'm', field2, "type_name"));
3389   EXPECT_TRUE(HasSpan('n', 'o', field2, "name"));
3390   EXPECT_TRUE(HasSpan('p', 'q', field2, "number"));
3391 
3392   // Ignore these.
3393   EXPECT_TRUE(HasSpan(file_));
3394   EXPECT_TRUE(HasSpan(file_.message_type(0)));
3395   EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
3396 }
3397 
TEST_F(SourceInfoTest,Proto3Fields)3398 TEST_F(SourceInfoTest, Proto3Fields) {
3399   EXPECT_TRUE(
3400       Parse("syntax = \"proto3\";\n"
3401             "message Foo {\n"
3402             "  $a$int32$b$ $c$bar$d$ = $e$1$f$;$g$\n"
3403             "  $h$repeated$i$ $j$X.Y$k$ $l$baz$m$ = $n$2$o$;$p$\n"
3404             "}\n"));
3405 
3406   const FieldDescriptorProto& field1 = file_.message_type(0).field(0);
3407   const FieldDescriptorProto& field2 = file_.message_type(0).field(1);
3408 
3409   EXPECT_TRUE(HasSpan('a', 'g', field1));
3410   EXPECT_TRUE(HasSpan('a', 'b', field1, "type"));
3411   EXPECT_TRUE(HasSpan('c', 'd', field1, "name"));
3412   EXPECT_TRUE(HasSpan('e', 'f', field1, "number"));
3413 
3414   EXPECT_TRUE(HasSpan('h', 'p', field2));
3415   EXPECT_TRUE(HasSpan('h', 'i', field2, "label"));
3416   EXPECT_TRUE(HasSpan('j', 'k', field2, "type_name"));
3417   EXPECT_TRUE(HasSpan('l', 'm', field2, "name"));
3418   EXPECT_TRUE(HasSpan('n', 'o', field2, "number"));
3419 
3420   // Ignore these.
3421   EXPECT_TRUE(HasSpan(file_));
3422   EXPECT_TRUE(HasSpan(file_, "syntax"));
3423   EXPECT_TRUE(HasSpan(file_.message_type(0)));
3424   EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
3425 }
3426 
TEST_F(SourceInfoTest,Extensions)3427 TEST_F(SourceInfoTest, Extensions) {
3428   EXPECT_TRUE(
3429       Parse("$a$extend $b$Foo$c$ {\n"
3430             "  $d$optional$e$ int32 bar = 1;$f$\n"
3431             "  $g$repeated$h$ X.Y baz = 2;$i$\n"
3432             "}$j$\n"
3433             "$k$extend $l$Bar$m$ {\n"
3434             "  $n$optional int32 qux = 1;$o$\n"
3435             "}$p$\n"));
3436 
3437   const FieldDescriptorProto& field1 = file_.extension(0);
3438   const FieldDescriptorProto& field2 = file_.extension(1);
3439   const FieldDescriptorProto& field3 = file_.extension(2);
3440 
3441   EXPECT_TRUE(HasSpan('a', 'j', file_, "extension"));
3442   EXPECT_TRUE(HasSpan('k', 'p', file_, "extension"));
3443 
3444   EXPECT_TRUE(HasSpan('d', 'f', field1));
3445   EXPECT_TRUE(HasSpan('d', 'e', field1, "label"));
3446   EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee"));
3447 
3448   EXPECT_TRUE(HasSpan('g', 'i', field2));
3449   EXPECT_TRUE(HasSpan('g', 'h', field2, "label"));
3450   EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee"));
3451 
3452   EXPECT_TRUE(HasSpan('n', 'o', field3));
3453   EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee"));
3454 
3455   // Ignore these.
3456   EXPECT_TRUE(HasSpan(file_));
3457   EXPECT_TRUE(HasSpan(field1, "type"));
3458   EXPECT_TRUE(HasSpan(field1, "name"));
3459   EXPECT_TRUE(HasSpan(field1, "number"));
3460   EXPECT_TRUE(HasSpan(field2, "type_name"));
3461   EXPECT_TRUE(HasSpan(field2, "name"));
3462   EXPECT_TRUE(HasSpan(field2, "number"));
3463   EXPECT_TRUE(HasSpan(field3, "label"));
3464   EXPECT_TRUE(HasSpan(field3, "type"));
3465   EXPECT_TRUE(HasSpan(field3, "name"));
3466   EXPECT_TRUE(HasSpan(field3, "number"));
3467 }
3468 
TEST_F(SourceInfoTest,NestedExtensions)3469 TEST_F(SourceInfoTest, NestedExtensions) {
3470   EXPECT_TRUE(
3471       Parse("message Message {\n"
3472             "  $a$extend $b$Foo$c$ {\n"
3473             "    $d$optional$e$ int32 bar = 1;$f$\n"
3474             "    $g$repeated$h$ X.Y baz = 2;$i$\n"
3475             "  }$j$\n"
3476             "  $k$extend $l$Bar$m$ {\n"
3477             "    $n$optional int32 qux = 1;$o$\n"
3478             "  }$p$\n"
3479             "}\n"));
3480 
3481   const FieldDescriptorProto& field1 = file_.message_type(0).extension(0);
3482   const FieldDescriptorProto& field2 = file_.message_type(0).extension(1);
3483   const FieldDescriptorProto& field3 = file_.message_type(0).extension(2);
3484 
3485   EXPECT_TRUE(HasSpan('a', 'j', file_.message_type(0), "extension"));
3486   EXPECT_TRUE(HasSpan('k', 'p', file_.message_type(0), "extension"));
3487 
3488   EXPECT_TRUE(HasSpan('d', 'f', field1));
3489   EXPECT_TRUE(HasSpan('d', 'e', field1, "label"));
3490   EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee"));
3491 
3492   EXPECT_TRUE(HasSpan('g', 'i', field2));
3493   EXPECT_TRUE(HasSpan('g', 'h', field2, "label"));
3494   EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee"));
3495 
3496   EXPECT_TRUE(HasSpan('n', 'o', field3));
3497   EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee"));
3498 
3499   // Ignore these.
3500   EXPECT_TRUE(HasSpan(file_));
3501   EXPECT_TRUE(HasSpan(file_.message_type(0)));
3502   EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
3503   EXPECT_TRUE(HasSpan(field1, "type"));
3504   EXPECT_TRUE(HasSpan(field1, "name"));
3505   EXPECT_TRUE(HasSpan(field1, "number"));
3506   EXPECT_TRUE(HasSpan(field2, "type_name"));
3507   EXPECT_TRUE(HasSpan(field2, "name"));
3508   EXPECT_TRUE(HasSpan(field2, "number"));
3509   EXPECT_TRUE(HasSpan(field3, "label"));
3510   EXPECT_TRUE(HasSpan(field3, "type"));
3511   EXPECT_TRUE(HasSpan(field3, "name"));
3512   EXPECT_TRUE(HasSpan(field3, "number"));
3513 }
3514 
TEST_F(SourceInfoTest,ExtensionRanges)3515 TEST_F(SourceInfoTest, ExtensionRanges) {
3516   EXPECT_TRUE(
3517       Parse("message Message {\n"
3518             "  $a$extensions $b$1$c$ to $d$4$e$, $f$6$g$;$h$\n"
3519             "  $i$extensions $j$8$k$ to $l$max$m$;$n$\n"
3520             "}\n"));
3521 
3522   const DescriptorProto::ExtensionRange& range1 =
3523       file_.message_type(0).extension_range(0);
3524   const DescriptorProto::ExtensionRange& range2 =
3525       file_.message_type(0).extension_range(1);
3526   const DescriptorProto::ExtensionRange& range3 =
3527       file_.message_type(0).extension_range(2);
3528 
3529   EXPECT_TRUE(HasSpan('a', 'h', file_.message_type(0), "extension_range"));
3530   EXPECT_TRUE(HasSpan('i', 'n', file_.message_type(0), "extension_range"));
3531 
3532   EXPECT_TRUE(HasSpan('b', 'e', range1));
3533   EXPECT_TRUE(HasSpan('b', 'c', range1, "start"));
3534   EXPECT_TRUE(HasSpan('d', 'e', range1, "end"));
3535 
3536   EXPECT_TRUE(HasSpan('f', 'g', range2));
3537   EXPECT_TRUE(HasSpan('f', 'g', range2, "start"));
3538   EXPECT_TRUE(HasSpan('f', 'g', range2, "end"));
3539 
3540   EXPECT_TRUE(HasSpan('j', 'm', range3));
3541   EXPECT_TRUE(HasSpan('j', 'k', range3, "start"));
3542   EXPECT_TRUE(HasSpan('l', 'm', range3, "end"));
3543 
3544   // Ignore these.
3545   EXPECT_TRUE(HasSpan(file_));
3546   EXPECT_TRUE(HasSpan(file_.message_type(0)));
3547   EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
3548 }
3549 
TEST_F(SourceInfoTest,ReservedRanges)3550 TEST_F(SourceInfoTest, ReservedRanges) {
3551   EXPECT_TRUE(
3552       Parse("message Message {\n"
3553             "  $a$reserved $b$1$c$ to $d$4$e$, $f$6$g$;$h$\n"
3554             "}\n"));
3555 
3556   const DescriptorProto::ReservedRange& range1 =
3557       file_.message_type(0).reserved_range(0);
3558   const DescriptorProto::ReservedRange& range2 =
3559       file_.message_type(0).reserved_range(1);
3560 
3561   EXPECT_TRUE(HasSpan('a', 'h', file_.message_type(0), "reserved_range"));
3562 
3563   EXPECT_TRUE(HasSpan('b', 'e', range1));
3564   EXPECT_TRUE(HasSpan('b', 'c', range1, "start"));
3565   EXPECT_TRUE(HasSpan('d', 'e', range1, "end"));
3566 
3567   EXPECT_TRUE(HasSpan('f', 'g', range2));
3568   EXPECT_TRUE(HasSpan('f', 'g', range2, "start"));
3569   EXPECT_TRUE(HasSpan('f', 'g', range2, "end"));
3570 
3571   // Ignore these.
3572   EXPECT_TRUE(HasSpan(file_));
3573   EXPECT_TRUE(HasSpan(file_.message_type(0)));
3574   EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
3575 }
3576 
TEST_F(SourceInfoTest,Oneofs)3577 TEST_F(SourceInfoTest, Oneofs) {
3578   EXPECT_TRUE(
3579       Parse("message Foo {\n"
3580             "  $a$oneof $c$foo$d$ {\n"
3581             "    $e$int32$f$ $g$a$h$ = $i$1$j$;$k$\n"
3582             "  }$r$\n"
3583             "}\n"));
3584 
3585   const OneofDescriptorProto& oneof_decl = file_.message_type(0).oneof_decl(0);
3586   const FieldDescriptorProto& field = file_.message_type(0).field(0);
3587 
3588   EXPECT_TRUE(HasSpan('a', 'r', oneof_decl));
3589   EXPECT_TRUE(HasSpan('c', 'd', oneof_decl, "name"));
3590 
3591   EXPECT_TRUE(HasSpan('e', 'k', field));
3592   EXPECT_TRUE(HasSpan('e', 'f', field, "type"));
3593   EXPECT_TRUE(HasSpan('g', 'h', field, "name"));
3594   EXPECT_TRUE(HasSpan('i', 'j', field, "number"));
3595 
3596   // Ignore these.
3597   EXPECT_TRUE(HasSpan(file_));
3598   EXPECT_TRUE(HasSpan(file_.message_type(0)));
3599   EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
3600 }
3601 
TEST_F(SourceInfoTest,NestedMessages)3602 TEST_F(SourceInfoTest, NestedMessages) {
3603   EXPECT_TRUE(
3604       Parse("message Foo {\n"
3605             "  $a$message $b$Bar$c$ {\n"
3606             "    $d$message $e$Baz$f$ {}$g$\n"
3607             "  }$h$\n"
3608             "  $i$message $j$Qux$k$ {}$l$\n"
3609             "}\n"));
3610 
3611   const DescriptorProto& bar = file_.message_type(0).nested_type(0);
3612   const DescriptorProto& baz = bar.nested_type(0);
3613   const DescriptorProto& qux = file_.message_type(0).nested_type(1);
3614 
3615   EXPECT_TRUE(HasSpan('a', 'h', bar));
3616   EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
3617   EXPECT_TRUE(HasSpan('d', 'g', baz));
3618   EXPECT_TRUE(HasSpan('e', 'f', baz, "name"));
3619   EXPECT_TRUE(HasSpan('i', 'l', qux));
3620   EXPECT_TRUE(HasSpan('j', 'k', qux, "name"));
3621 
3622   // Ignore these.
3623   EXPECT_TRUE(HasSpan(file_));
3624   EXPECT_TRUE(HasSpan(file_.message_type(0)));
3625   EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
3626 }
3627 
TEST_F(SourceInfoTest,Groups)3628 TEST_F(SourceInfoTest, Groups) {
3629   EXPECT_TRUE(
3630       Parse("message Foo {\n"
3631             "  message Bar {}\n"
3632             "  $a$optional$b$ $c$group$d$ $e$Baz$f$ = $g$1$h$ {\n"
3633             "    $i$message Qux {}$j$\n"
3634             "  }$k$\n"
3635             "}\n"));
3636 
3637   const DescriptorProto& bar = file_.message_type(0).nested_type(0);
3638   const DescriptorProto& baz = file_.message_type(0).nested_type(1);
3639   const DescriptorProto& qux = baz.nested_type(0);
3640   const FieldDescriptorProto& field = file_.message_type(0).field(0);
3641 
3642   EXPECT_TRUE(HasSpan('a', 'k', field));
3643   EXPECT_TRUE(HasSpan('a', 'b', field, "label"));
3644   EXPECT_TRUE(HasSpan('c', 'd', field, "type"));
3645   EXPECT_TRUE(HasSpan('e', 'f', field, "name"));
3646   EXPECT_TRUE(HasSpan('e', 'f', field, "type_name"));
3647   EXPECT_TRUE(HasSpan('g', 'h', field, "number"));
3648 
3649   EXPECT_TRUE(HasSpan('a', 'k', baz));
3650   EXPECT_TRUE(HasSpan('e', 'f', baz, "name"));
3651   EXPECT_TRUE(HasSpan('i', 'j', qux));
3652 
3653   // Ignore these.
3654   EXPECT_TRUE(HasSpan(file_));
3655   EXPECT_TRUE(HasSpan(file_.message_type(0)));
3656   EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
3657   EXPECT_TRUE(HasSpan(bar));
3658   EXPECT_TRUE(HasSpan(bar, "name"));
3659   EXPECT_TRUE(HasSpan(qux, "name"));
3660 }
3661 
TEST_F(SourceInfoTest,Enums)3662 TEST_F(SourceInfoTest, Enums) {
3663   EXPECT_TRUE(
3664       Parse("$a$enum $b$Foo$c$ {}$d$\n"
3665             "$e$enum $f$Bar$g$ {}$h$\n"));
3666 
3667   EXPECT_TRUE(HasSpan('a', 'd', file_.enum_type(0)));
3668   EXPECT_TRUE(HasSpan('b', 'c', file_.enum_type(0), "name"));
3669   EXPECT_TRUE(HasSpan('e', 'h', file_.enum_type(1)));
3670   EXPECT_TRUE(HasSpan('f', 'g', file_.enum_type(1), "name"));
3671 
3672   // Ignore these.
3673   EXPECT_TRUE(HasSpan(file_));
3674 }
3675 
TEST_F(SourceInfoTest,EnumValues)3676 TEST_F(SourceInfoTest, EnumValues) {
3677   EXPECT_TRUE(
3678       Parse("enum Foo {\n"
3679             "  $a$BAR$b$ = $c$1$d$;$e$\n"
3680             "  $f$BAZ$g$ = $h$2$i$;$j$\n"
3681             "}"));
3682 
3683   const EnumValueDescriptorProto& bar = file_.enum_type(0).value(0);
3684   const EnumValueDescriptorProto& baz = file_.enum_type(0).value(1);
3685 
3686   EXPECT_TRUE(HasSpan('a', 'e', bar));
3687   EXPECT_TRUE(HasSpan('a', 'b', bar, "name"));
3688   EXPECT_TRUE(HasSpan('c', 'd', bar, "number"));
3689   EXPECT_TRUE(HasSpan('f', 'j', baz));
3690   EXPECT_TRUE(HasSpan('f', 'g', baz, "name"));
3691   EXPECT_TRUE(HasSpan('h', 'i', baz, "number"));
3692 
3693   // Ignore these.
3694   EXPECT_TRUE(HasSpan(file_));
3695   EXPECT_TRUE(HasSpan(file_.enum_type(0)));
3696   EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
3697 }
3698 
TEST_F(SourceInfoTest,EnumReservedRange)3699 TEST_F(SourceInfoTest, EnumReservedRange) {
3700   EXPECT_TRUE(
3701       Parse("enum TestEnum {\n"
3702             "  $a$reserved $b$1$c$ to $d$10$e$;$f$\n"
3703             "}"));
3704 
3705   const EnumDescriptorProto::EnumReservedRange& bar =
3706       file_.enum_type(0).reserved_range(0);
3707 
3708   EXPECT_TRUE(HasSpan('a', 'f', file_.enum_type(0), "reserved_range"));
3709   EXPECT_TRUE(HasSpan('b', 'e', bar));
3710   EXPECT_TRUE(HasSpan('b', 'c', bar, "start"));
3711   EXPECT_TRUE(HasSpan('d', 'e', bar, "end"));
3712 
3713   // Ignore these.
3714   EXPECT_TRUE(HasSpan(file_));
3715   EXPECT_TRUE(HasSpan(file_.enum_type(0)));
3716   EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
3717 }
3718 
TEST_F(SourceInfoTest,EnumReservedName)3719 TEST_F(SourceInfoTest, EnumReservedName) {
3720   EXPECT_TRUE(
3721       Parse("enum TestEnum {\n"
3722             "  $a$reserved $b$'foo'$c$;$d$\n"
3723             "}"));
3724 
3725   const EnumDescriptorProto& bar = file_.enum_type(0);
3726 
3727   EXPECT_TRUE(HasSpan('a', 'd', bar, "reserved_name"));
3728   EXPECT_TRUE(HasSpan('b', 'c', bar, "reserved_name", 0));
3729 
3730   // Ignore these.
3731   EXPECT_TRUE(HasSpan(file_));
3732   EXPECT_TRUE(HasSpan(file_.enum_type(0)));
3733   EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
3734 }
3735 
TEST_F(SourceInfoTest,NestedEnums)3736 TEST_F(SourceInfoTest, NestedEnums) {
3737   EXPECT_TRUE(
3738       Parse("message Foo {\n"
3739             "  $a$enum $b$Bar$c$ {}$d$\n"
3740             "  $e$enum $f$Baz$g$ {}$h$\n"
3741             "}\n"));
3742 
3743   const EnumDescriptorProto& bar = file_.message_type(0).enum_type(0);
3744   const EnumDescriptorProto& baz = file_.message_type(0).enum_type(1);
3745 
3746   EXPECT_TRUE(HasSpan('a', 'd', bar));
3747   EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
3748   EXPECT_TRUE(HasSpan('e', 'h', baz));
3749   EXPECT_TRUE(HasSpan('f', 'g', baz, "name"));
3750 
3751   // Ignore these.
3752   EXPECT_TRUE(HasSpan(file_));
3753   EXPECT_TRUE(HasSpan(file_.message_type(0)));
3754   EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
3755 }
3756 
TEST_F(SourceInfoTest,Services)3757 TEST_F(SourceInfoTest, Services) {
3758   EXPECT_TRUE(
3759       Parse("$a$service $b$Foo$c$ {}$d$\n"
3760             "$e$service $f$Bar$g$ {}$h$\n"));
3761 
3762   EXPECT_TRUE(HasSpan('a', 'd', file_.service(0)));
3763   EXPECT_TRUE(HasSpan('b', 'c', file_.service(0), "name"));
3764   EXPECT_TRUE(HasSpan('e', 'h', file_.service(1)));
3765   EXPECT_TRUE(HasSpan('f', 'g', file_.service(1), "name"));
3766 
3767   // Ignore these.
3768   EXPECT_TRUE(HasSpan(file_));
3769 }
3770 
TEST_F(SourceInfoTest,MethodsAndStreams)3771 TEST_F(SourceInfoTest, MethodsAndStreams) {
3772   EXPECT_TRUE(
3773       Parse("service Foo {\n"
3774             "  $a$rpc $b$Bar$c$($d$X$e$) returns($f$Y$g$);$h$"
3775             "  $i$rpc $j$Baz$k$($l$Z$m$) returns($n$W$o$);$p$"
3776             "}"));
3777 
3778   const MethodDescriptorProto& bar = file_.service(0).method(0);
3779   const MethodDescriptorProto& baz = file_.service(0).method(1);
3780 
3781   EXPECT_TRUE(HasSpan('a', 'h', bar));
3782   EXPECT_TRUE(HasSpan('b', 'c', bar, "name"));
3783   EXPECT_TRUE(HasSpan('d', 'e', bar, "input_type"));
3784   EXPECT_TRUE(HasSpan('f', 'g', bar, "output_type"));
3785 
3786   EXPECT_TRUE(HasSpan('i', 'p', baz));
3787   EXPECT_TRUE(HasSpan('j', 'k', baz, "name"));
3788   EXPECT_TRUE(HasSpan('l', 'm', baz, "input_type"));
3789   EXPECT_TRUE(HasSpan('n', 'o', baz, "output_type"));
3790 
3791   // Ignore these.
3792   EXPECT_TRUE(HasSpan(file_));
3793   EXPECT_TRUE(HasSpan(file_.service(0)));
3794   EXPECT_TRUE(HasSpan(file_.service(0), "name"));
3795 }
3796 
3797 
TEST_F(SourceInfoTest,Options)3798 TEST_F(SourceInfoTest, Options) {
3799   EXPECT_TRUE(
3800       Parse("$a$option $b$foo$c$.$d$($e$bar.baz$f$)$g$ = "
3801             "$h$123$i$;$j$\n"
3802             "$k$option qux = $l$-123$m$;$n$\n"
3803             "$o$option corge = $p$abc$q$;$r$\n"
3804             "$s$option grault = $t$'blah'$u$;$v$\n"
3805             "$w$option garply = $x${ yadda yadda }$y$;$z$\n"
3806             "$0$option waldo = $1$123.0$2$;$3$\n"));
3807 
3808   const UninterpretedOption& option1 = file_.options().uninterpreted_option(0);
3809   const UninterpretedOption& option2 = file_.options().uninterpreted_option(1);
3810   const UninterpretedOption& option3 = file_.options().uninterpreted_option(2);
3811   const UninterpretedOption& option4 = file_.options().uninterpreted_option(3);
3812   const UninterpretedOption& option5 = file_.options().uninterpreted_option(4);
3813   const UninterpretedOption& option6 = file_.options().uninterpreted_option(5);
3814 
3815   EXPECT_TRUE(HasSpan('a', 'j', file_.options()));
3816   EXPECT_TRUE(HasSpan('a', 'j', option1));
3817   EXPECT_TRUE(HasSpan('b', 'g', option1, "name"));
3818   EXPECT_TRUE(HasSpan('b', 'c', option1.name(0)));
3819   EXPECT_TRUE(HasSpan('b', 'c', option1.name(0), "name_part"));
3820   EXPECT_TRUE(HasSpan('d', 'g', option1.name(1)));
3821   EXPECT_TRUE(HasSpan('e', 'f', option1.name(1), "name_part"));
3822   EXPECT_TRUE(HasSpan('h', 'i', option1, "positive_int_value"));
3823 
3824   EXPECT_TRUE(HasSpan('k', 'n', file_.options()));
3825   EXPECT_TRUE(HasSpan('l', 'm', option2, "negative_int_value"));
3826 
3827   EXPECT_TRUE(HasSpan('o', 'r', file_.options()));
3828   EXPECT_TRUE(HasSpan('p', 'q', option3, "identifier_value"));
3829 
3830   EXPECT_TRUE(HasSpan('s', 'v', file_.options()));
3831   EXPECT_TRUE(HasSpan('t', 'u', option4, "string_value"));
3832 
3833   EXPECT_TRUE(HasSpan('w', 'z', file_.options()));
3834   EXPECT_TRUE(HasSpan('x', 'y', option5, "aggregate_value"));
3835 
3836   EXPECT_TRUE(HasSpan('0', '3', file_.options()));
3837   EXPECT_TRUE(HasSpan('1', '2', option6, "double_value"));
3838 
3839   // Ignore these.
3840   EXPECT_TRUE(HasSpan(file_));
3841   EXPECT_TRUE(HasSpan(option2));
3842   EXPECT_TRUE(HasSpan(option3));
3843   EXPECT_TRUE(HasSpan(option4));
3844   EXPECT_TRUE(HasSpan(option5));
3845   EXPECT_TRUE(HasSpan(option6));
3846   EXPECT_TRUE(HasSpan(option2, "name"));
3847   EXPECT_TRUE(HasSpan(option3, "name"));
3848   EXPECT_TRUE(HasSpan(option4, "name"));
3849   EXPECT_TRUE(HasSpan(option5, "name"));
3850   EXPECT_TRUE(HasSpan(option6, "name"));
3851   EXPECT_TRUE(HasSpan(option2.name(0)));
3852   EXPECT_TRUE(HasSpan(option3.name(0)));
3853   EXPECT_TRUE(HasSpan(option4.name(0)));
3854   EXPECT_TRUE(HasSpan(option5.name(0)));
3855   EXPECT_TRUE(HasSpan(option6.name(0)));
3856   EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
3857   EXPECT_TRUE(HasSpan(option3.name(0), "name_part"));
3858   EXPECT_TRUE(HasSpan(option4.name(0), "name_part"));
3859   EXPECT_TRUE(HasSpan(option5.name(0), "name_part"));
3860   EXPECT_TRUE(HasSpan(option6.name(0), "name_part"));
3861 }
3862 
TEST_F(SourceInfoTest,ScopedOptions)3863 TEST_F(SourceInfoTest, ScopedOptions) {
3864   EXPECT_TRUE(
3865       Parse("message Foo {\n"
3866             "  $a$option mopt = 1;$b$\n"
3867             "}\n"
3868             "enum Bar {\n"
3869             "  $c$option eopt = 1;$d$\n"
3870             "}\n"
3871             "service Baz {\n"
3872             "  $e$option sopt = 1;$f$\n"
3873             "  rpc M(X) returns(Y) {\n"
3874             "    $g$option mopt = 1;$h$\n"
3875             "  }\n"
3876             "  rpc MS4($1$stream$2$ X) returns($3$stream$4$ Y) {\n"
3877             "    $k$option mopt = 1;$l$\n"
3878             "  }\n"
3879             "}\n"));
3880 
3881   EXPECT_TRUE(HasSpan('a', 'b', file_.message_type(0).options()));
3882   EXPECT_TRUE(HasSpan('c', 'd', file_.enum_type(0).options()));
3883   EXPECT_TRUE(HasSpan('e', 'f', file_.service(0).options()));
3884   EXPECT_TRUE(HasSpan('g', 'h', file_.service(0).method(0).options()));
3885 
3886   // Ignore these.
3887   EXPECT_TRUE(HasSpan(file_));
3888   EXPECT_TRUE(HasSpan(file_.message_type(0)));
3889   EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
3890   EXPECT_TRUE(HasSpan(file_.message_type(0).options().uninterpreted_option(0)));
3891   EXPECT_TRUE(
3892       HasSpan(file_.message_type(0).options().uninterpreted_option(0), "name"));
3893   EXPECT_TRUE(
3894       HasSpan(file_.message_type(0).options().uninterpreted_option(0).name(0)));
3895   EXPECT_TRUE(
3896       HasSpan(file_.message_type(0).options().uninterpreted_option(0).name(0),
3897               "name_part"));
3898   EXPECT_TRUE(HasSpan(file_.message_type(0).options().uninterpreted_option(0),
3899                       "positive_int_value"));
3900   EXPECT_TRUE(HasSpan(file_.enum_type(0)));
3901   EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
3902   EXPECT_TRUE(HasSpan(file_.enum_type(0).options().uninterpreted_option(0)));
3903   EXPECT_TRUE(
3904       HasSpan(file_.enum_type(0).options().uninterpreted_option(0), "name"));
3905   EXPECT_TRUE(
3906       HasSpan(file_.enum_type(0).options().uninterpreted_option(0).name(0)));
3907   EXPECT_TRUE(
3908       HasSpan(file_.enum_type(0).options().uninterpreted_option(0).name(0),
3909               "name_part"));
3910   EXPECT_TRUE(HasSpan(file_.enum_type(0).options().uninterpreted_option(0),
3911                       "positive_int_value"));
3912   EXPECT_TRUE(HasSpan(file_.service(0)));
3913   EXPECT_TRUE(HasSpan(file_.service(0), "name"));
3914   EXPECT_TRUE(HasSpan(file_.service(0).method(0)));
3915   EXPECT_TRUE(HasSpan(file_.service(0).options().uninterpreted_option(0)));
3916   EXPECT_TRUE(
3917       HasSpan(file_.service(0).options().uninterpreted_option(0), "name"));
3918   EXPECT_TRUE(
3919       HasSpan(file_.service(0).options().uninterpreted_option(0).name(0)));
3920   EXPECT_TRUE(HasSpan(
3921       file_.service(0).options().uninterpreted_option(0).name(0), "name_part"));
3922   EXPECT_TRUE(HasSpan(file_.service(0).options().uninterpreted_option(0),
3923                       "positive_int_value"));
3924   EXPECT_TRUE(HasSpan(file_.service(0).method(0), "name"));
3925   EXPECT_TRUE(HasSpan(file_.service(0).method(0), "input_type"));
3926   EXPECT_TRUE(HasSpan(file_.service(0).method(0), "output_type"));
3927   EXPECT_TRUE(
3928       HasSpan(file_.service(0).method(0).options().uninterpreted_option(0)));
3929   EXPECT_TRUE(HasSpan(
3930       file_.service(0).method(0).options().uninterpreted_option(0), "name"));
3931   EXPECT_TRUE(HasSpan(
3932       file_.service(0).method(0).options().uninterpreted_option(0).name(0)));
3933   EXPECT_TRUE(HasSpan(
3934       file_.service(0).method(0).options().uninterpreted_option(0).name(0),
3935       "name_part"));
3936   EXPECT_TRUE(
3937       HasSpan(file_.service(0).method(0).options().uninterpreted_option(0),
3938               "positive_int_value"));
3939 
3940   EXPECT_TRUE(HasSpan('k', 'l', file_.service(0).method(1).options()));
3941   EXPECT_TRUE(HasSpan(file_.service(0).method(1)));
3942   EXPECT_TRUE(HasSpan(file_.service(0).method(1), "name"));
3943   EXPECT_TRUE(HasSpan(file_.service(0).method(1), "input_type"));
3944   EXPECT_TRUE(HasSpan(file_.service(0).method(1), "output_type"));
3945   EXPECT_TRUE(
3946       HasSpan(file_.service(0).method(1).options().uninterpreted_option(0)));
3947   EXPECT_TRUE(HasSpan(
3948       file_.service(0).method(1).options().uninterpreted_option(0), "name"));
3949   EXPECT_TRUE(HasSpan(
3950       file_.service(0).method(1).options().uninterpreted_option(0).name(0)));
3951   EXPECT_TRUE(HasSpan(
3952       file_.service(0).method(1).options().uninterpreted_option(0).name(0),
3953       "name_part"));
3954   EXPECT_TRUE(
3955       HasSpan(file_.service(0).method(1).options().uninterpreted_option(0),
3956               "positive_int_value"));
3957   EXPECT_TRUE(
3958       HasSpan('1', '2', file_.service(0).method(1), "client_streaming"));
3959   EXPECT_TRUE(
3960       HasSpan('3', '4', file_.service(0).method(1), "server_streaming"));
3961 }
3962 
TEST_F(SourceInfoTest,FieldOptions)3963 TEST_F(SourceInfoTest, FieldOptions) {
3964   // The actual "name = value" pairs are parsed by the same code as for
3965   // top-level options so we won't re-test that -- just make sure that the
3966   // syntax used for field options is understood.
3967   EXPECT_TRUE(
3968       Parse("message Foo {"
3969             "  optional int32 bar = 1 "
3970             "$a$[default=$b$123$c$,$d$opt1=123$e$,"
3971             "$f$opt2='hi'$g$]$h$;"
3972             "}\n"));
3973 
3974   const FieldDescriptorProto& field = file_.message_type(0).field(0);
3975   const UninterpretedOption& option1 = field.options().uninterpreted_option(0);
3976   const UninterpretedOption& option2 = field.options().uninterpreted_option(1);
3977 
3978   EXPECT_TRUE(HasSpan('a', 'h', field.options()));
3979   EXPECT_TRUE(HasSpan('b', 'c', field, "default_value"));
3980   EXPECT_TRUE(HasSpan('d', 'e', option1));
3981   EXPECT_TRUE(HasSpan('f', 'g', option2));
3982 
3983   // Ignore these.
3984   EXPECT_TRUE(HasSpan(file_));
3985   EXPECT_TRUE(HasSpan(file_.message_type(0)));
3986   EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
3987   EXPECT_TRUE(HasSpan(field));
3988   EXPECT_TRUE(HasSpan(field, "label"));
3989   EXPECT_TRUE(HasSpan(field, "type"));
3990   EXPECT_TRUE(HasSpan(field, "name"));
3991   EXPECT_TRUE(HasSpan(field, "number"));
3992   EXPECT_TRUE(HasSpan(option1, "name"));
3993   EXPECT_TRUE(HasSpan(option2, "name"));
3994   EXPECT_TRUE(HasSpan(option1.name(0)));
3995   EXPECT_TRUE(HasSpan(option2.name(0)));
3996   EXPECT_TRUE(HasSpan(option1.name(0), "name_part"));
3997   EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
3998   EXPECT_TRUE(HasSpan(option1, "positive_int_value"));
3999   EXPECT_TRUE(HasSpan(option2, "string_value"));
4000 }
4001 
TEST_F(SourceInfoTest,EnumValueOptions)4002 TEST_F(SourceInfoTest, EnumValueOptions) {
4003   // The actual "name = value" pairs are parsed by the same code as for
4004   // top-level options so we won't re-test that -- just make sure that the
4005   // syntax used for enum options is understood.
4006   EXPECT_TRUE(
4007       Parse("enum Foo {"
4008             "  BAR = 1 $a$[$b$opt1=123$c$,$d$opt2='hi'$e$]$f$;"
4009             "}\n"));
4010 
4011   const EnumValueDescriptorProto& value = file_.enum_type(0).value(0);
4012   const UninterpretedOption& option1 = value.options().uninterpreted_option(0);
4013   const UninterpretedOption& option2 = value.options().uninterpreted_option(1);
4014 
4015   EXPECT_TRUE(HasSpan('a', 'f', value.options()));
4016   EXPECT_TRUE(HasSpan('b', 'c', option1));
4017   EXPECT_TRUE(HasSpan('d', 'e', option2));
4018 
4019   // Ignore these.
4020   EXPECT_TRUE(HasSpan(file_));
4021   EXPECT_TRUE(HasSpan(file_.enum_type(0)));
4022   EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
4023   EXPECT_TRUE(HasSpan(value));
4024   EXPECT_TRUE(HasSpan(value, "name"));
4025   EXPECT_TRUE(HasSpan(value, "number"));
4026   EXPECT_TRUE(HasSpan(option1, "name"));
4027   EXPECT_TRUE(HasSpan(option2, "name"));
4028   EXPECT_TRUE(HasSpan(option1.name(0)));
4029   EXPECT_TRUE(HasSpan(option2.name(0)));
4030   EXPECT_TRUE(HasSpan(option1.name(0), "name_part"));
4031   EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
4032   EXPECT_TRUE(HasSpan(option1, "positive_int_value"));
4033   EXPECT_TRUE(HasSpan(option2, "string_value"));
4034 }
4035 
TEST_F(SourceInfoTest,DocComments)4036 TEST_F(SourceInfoTest, DocComments) {
4037   EXPECT_TRUE(
4038       Parse("// Foo leading\n"
4039             "// line 2\n"
4040             "$a$message Foo {\n"
4041             "  // Foo trailing\n"
4042             "  // line 2\n"
4043             "\n"
4044             "  // detached\n"
4045             "\n"
4046             "  // bar leading\n"
4047             "  $b$optional int32 bar = 1;$c$\n"
4048             "  // bar trailing\n"
4049             "}$d$\n"
4050             "// ignored\n"));
4051 
4052   const DescriptorProto& foo = file_.message_type(0);
4053   const FieldDescriptorProto& bar = foo.field(0);
4054 
4055   EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, " Foo leading\n line 2\n",
4056                                  " Foo trailing\n line 2\n", nullptr));
4057   EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, " bar leading\n",
4058                                  " bar trailing\n", " detached\n"));
4059 
4060   // Ignore these.
4061   EXPECT_TRUE(HasSpan(file_));
4062   EXPECT_TRUE(HasSpan(foo, "name"));
4063   EXPECT_TRUE(HasSpan(bar, "label"));
4064   EXPECT_TRUE(HasSpan(bar, "type"));
4065   EXPECT_TRUE(HasSpan(bar, "name"));
4066   EXPECT_TRUE(HasSpan(bar, "number"));
4067 }
4068 
TEST_F(SourceInfoTest,DocComments2)4069 TEST_F(SourceInfoTest, DocComments2) {
4070   EXPECT_TRUE(
4071       Parse("// detached before message.\n"
4072             "\n"
4073             "// Foo leading\n"
4074             "// line 2\n"
4075             "$a$message Foo {\n"
4076             "  /* Foo trailing\n"
4077             "   * line 2 */\n"
4078             "  // detached\n"
4079             "  /* bar leading\n"
4080             "   */"
4081             "  $b$optional int32 bar = 1;$c$  // bar trailing\n"
4082             "  // ignored detached\n"
4083             "}$d$\n"
4084             "// ignored\n"
4085             "\n"
4086             "// detached before option\n"
4087             "\n"
4088             "// option leading\n"
4089             "$e$option baz = 123;$f$\n"
4090             "// option trailing\n"));
4091 
4092   const DescriptorProto& foo = file_.message_type(0);
4093   const FieldDescriptorProto& bar = foo.field(0);
4094   const UninterpretedOption& baz = file_.options().uninterpreted_option(0);
4095 
4096   EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, " Foo leading\n line 2\n",
4097                                  " Foo trailing\n line 2 ",
4098                                  " detached before message.\n"));
4099   EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, " bar leading\n",
4100                                  " bar trailing\n", " detached\n"));
4101   EXPECT_TRUE(HasSpanWithComment('e', 'f', baz, " option leading\n",
4102                                  " option trailing\n",
4103                                  " detached before option\n"));
4104 
4105   // Ignore these.
4106   EXPECT_TRUE(HasSpan(file_));
4107   EXPECT_TRUE(HasSpan(foo, "name"));
4108   EXPECT_TRUE(HasSpan(bar, "label"));
4109   EXPECT_TRUE(HasSpan(bar, "type"));
4110   EXPECT_TRUE(HasSpan(bar, "name"));
4111   EXPECT_TRUE(HasSpan(bar, "number"));
4112   EXPECT_TRUE(HasSpan(file_.options()));
4113   EXPECT_TRUE(HasSpan(baz, "name"));
4114   EXPECT_TRUE(HasSpan(baz.name(0)));
4115   EXPECT_TRUE(HasSpan(baz.name(0), "name_part"));
4116   EXPECT_TRUE(HasSpan(baz, "positive_int_value"));
4117 }
4118 
TEST_F(SourceInfoTest,DocComments3)4119 TEST_F(SourceInfoTest, DocComments3) {
4120   EXPECT_TRUE(
4121       Parse("$a$message Foo {\n"
4122             "  // bar leading\n"
4123             "  $b$optional int32 bar = 1 [(baz.qux) = {}];$c$\n"
4124             "  // bar trailing\n"
4125             "}$d$\n"
4126             "// ignored\n"));
4127 
4128   const DescriptorProto& foo = file_.message_type(0);
4129   const FieldDescriptorProto& bar = foo.field(0);
4130 
4131   EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, " bar leading\n",
4132                                  " bar trailing\n", nullptr));
4133 
4134   // Ignore these.
4135   EXPECT_TRUE(HasSpan(file_));
4136   EXPECT_TRUE(HasSpan(foo));
4137   EXPECT_TRUE(HasSpan(foo, "name"));
4138   EXPECT_TRUE(HasSpan(bar, "label"));
4139   EXPECT_TRUE(HasSpan(bar, "type"));
4140   EXPECT_TRUE(HasSpan(bar, "name"));
4141   EXPECT_TRUE(HasSpan(bar, "number"));
4142   EXPECT_TRUE(HasSpan(bar.options()));
4143   EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0)));
4144   EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0), "name"));
4145   EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0).name(0)));
4146   EXPECT_TRUE(
4147       HasSpan(bar.options().uninterpreted_option(0).name(0), "name_part"));
4148   EXPECT_TRUE(
4149       HasSpan(bar.options().uninterpreted_option(0), "aggregate_value"));
4150 }
4151 
TEST_F(SourceInfoTest,DocCommentsTopLevel)4152 TEST_F(SourceInfoTest, DocCommentsTopLevel) {
4153   EXPECT_TRUE(
4154       Parse("// detached before syntax paragraph 1\n"
4155             "\n"
4156             "// detached before syntax paragraph 2\n"
4157             "\n"
4158             "// syntax leading\n"
4159             "$a$syntax = \"proto2\";$b$\n"
4160             "// syntax trailing\n"
4161             "\n"
4162             "// syntax-package detached comments\n"
4163             "\n"
4164             ";\n"
4165             "\n"
4166             "// detached after empty before package\n"
4167             "\n"
4168             "// package leading\n"
4169             "$c$package foo;$d$\n"
4170             "// package trailing\n"
4171             "\n"
4172             "// ignored detach\n"
4173             "\n"));
4174 
4175   EXPECT_TRUE(HasSpan('a', 'b', file_, "syntax", -1, " syntax leading\n",
4176                       " syntax trailing\n",
4177                       " detached before syntax paragraph 1\n"
4178                       "\n"
4179                       " detached before syntax paragraph 2\n"));
4180   EXPECT_TRUE(HasSpan('c', 'd', file_, "package", -1, " package leading\n",
4181                       " package trailing\n",
4182                       " syntax-package detached comments\n"
4183                       "\n"
4184                       " detached after empty before package\n"));
4185 
4186   // ignore these.
4187   EXPECT_TRUE(HasSpan(file_));
4188 }
4189 
TEST_F(SourceInfoTest,DocCommentsOneof)4190 TEST_F(SourceInfoTest, DocCommentsOneof) {
4191   EXPECT_TRUE(
4192       Parse("// Foo leading\n"
4193             "$a$message Foo {\n"
4194             "  /* Foo trailing\n"
4195             "   */\n"
4196             "  // detached before oneof\n"
4197             "  /* bar leading\n"
4198             "   * line 2 */\n"
4199             "  $b$oneof bar {\n"
4200             "  /* bar trailing\n"
4201             "   * line 2 */\n"
4202             "  // detached before bar_int\n"
4203             "  /* bar_int leading\n"
4204             "   */\n"
4205             "  $c$int32 bar_int = 1;$d$  // bar_int trailing\n"
4206             "  // detach comment ignored\n"
4207             "  }$e$\n"
4208             "}$f$\n"));
4209 
4210   const DescriptorProto& foo = file_.message_type(0);
4211   const OneofDescriptorProto& bar = foo.oneof_decl(0);
4212   const FieldDescriptorProto& bar_int = foo.field(0);
4213 
4214   EXPECT_TRUE(HasSpanWithComment('a', 'f', foo, " Foo leading\n",
4215                                  " Foo trailing\n", nullptr));
4216   EXPECT_TRUE(HasSpanWithComment('b', 'e', bar, " bar leading\n line 2 ",
4217                                  " bar trailing\n line 2 ",
4218                                  " detached before oneof\n"));
4219   EXPECT_TRUE(HasSpanWithComment('c', 'd', bar_int, " bar_int leading\n",
4220                                  " bar_int trailing\n",
4221                                  " detached before bar_int\n"));
4222 
4223   // Ignore these.
4224   EXPECT_TRUE(HasSpan(file_));
4225   EXPECT_TRUE(HasSpan(foo, "name"));
4226   EXPECT_TRUE(HasSpan(bar, "name"));
4227   EXPECT_TRUE(HasSpan(bar_int, "type"));
4228   EXPECT_TRUE(HasSpan(bar_int, "name"));
4229   EXPECT_TRUE(HasSpan(bar_int, "number"));
4230 }
4231 
4232 // ===================================================================
4233 
4234 typedef ParserTest ParseEditionsTest;
4235 
TEST_F(ParseEditionsTest,Editions)4236 TEST_F(ParseEditionsTest, Editions) {
4237   ExpectParsesTo(
4238       R"schema(
4239         edition = "2023";
4240         message A {
4241           int32 b = 1;
4242         })schema",
4243       "message_type \t {"
4244       "  name: \"A\""
4245       "  field {"
4246       "    name: \"b\""
4247       "    number: 1"
4248       "    label: LABEL_OPTIONAL"
4249       "    type: TYPE_INT32"
4250       "  }"
4251       "}"
4252       "syntax: \"editions\""
4253       "edition: EDITION_2023\n");
4254 }
4255 
TEST_F(ParseEditionsTest,TestEdition)4256 TEST_F(ParseEditionsTest, TestEdition) {
4257   ExpectParsesTo(
4258       R"schema(
4259         edition = "99998_TEST_ONLY";
4260       )schema",
4261       "syntax: \"editions\""
4262       "edition: EDITION_99998_TEST_ONLY\n");
4263 }
4264 
TEST_F(ParseEditionsTest,ExtensionsParse)4265 TEST_F(ParseEditionsTest, ExtensionsParse) {
4266   ExpectParsesTo(
4267       R"schema(
4268         edition = '2023';
4269         message Foo {
4270           extensions 100 to 199;
4271         }
4272         extend Foo { string foo = 101; })schema",
4273       "message_type \t {"
4274       "  name: \"Foo\""
4275       "  extension_range {"
4276       "    start: 100"
4277       "    end: 200"
4278       "  }"
4279       "}"
4280       "extension {"
4281       "  name: \"foo\""
4282       "  extendee: \"Foo\""
4283       "  number: 101"
4284       "  label: LABEL_OPTIONAL"
4285       "  type: TYPE_STRING"
4286       "}"
4287       "syntax: \"editions\""
4288       "edition: EDITION_2023\n");
4289 }
4290 
TEST_F(ParseEditionsTest,MapFeatures)4291 TEST_F(ParseEditionsTest, MapFeatures) {
4292   ExpectParsesTo(
4293       R"schema(
4294         edition = '2023';
4295         message Foo {
4296           map<string, int> map_field = 1 [
4297             features.my_feature = SOMETHING
4298           ];
4299         })schema",
4300       R"pb(message_type {
4301              name: "Foo"
4302              field {
4303                name: "map_field"
4304                number: 1
4305                label: LABEL_REPEATED
4306                type_name: "MapFieldEntry"
4307                options {
4308                  uninterpreted_option {
4309                    name { name_part: "features" is_extension: false }
4310                    name { name_part: "my_feature" is_extension: false }
4311                    identifier_value: "SOMETHING"
4312                  }
4313                }
4314              }
4315              nested_type {
4316                name: "MapFieldEntry"
4317                field {
4318                  name: "key"
4319                  number: 1
4320                  label: LABEL_OPTIONAL
4321                  type: TYPE_STRING
4322                  options {
4323                    uninterpreted_option {
4324                      name { name_part: "features" is_extension: false }
4325                      name { name_part: "my_feature" is_extension: false }
4326                      identifier_value: "SOMETHING"
4327                    }
4328                  }
4329                }
4330                field {
4331                  name: "value"
4332                  number: 2
4333                  label: LABEL_OPTIONAL
4334                  type_name: "int"
4335                  options {
4336                    uninterpreted_option {
4337                      name { name_part: "features" is_extension: false }
4338                      name { name_part: "my_feature" is_extension: false }
4339                      identifier_value: "SOMETHING"
4340                    }
4341                  }
4342                }
4343                options { map_entry: true }
4344              }
4345            }
4346            syntax: "editions"
4347            edition: EDITION_2023)pb");
4348 }
4349 
TEST_F(ParseEditionsTest,EmptyEdition)4350 TEST_F(ParseEditionsTest, EmptyEdition) {
4351   ExpectHasEarlyExitErrors(
4352       R"schema(
4353         edition = "";
4354         message A {
4355           optional int32 b = 1;
4356         })schema",
4357       "1:18: Unknown edition \"\".\n");
4358 }
4359 
TEST_F(ParseEditionsTest,InvalidEdition)4360 TEST_F(ParseEditionsTest, InvalidEdition) {
4361   ExpectHasEarlyExitErrors(
4362       R"schema(
4363         edition = "2023_INVALID";
4364         message A {
4365           optional int32 b = 1;
4366         })schema",
4367       "1:18: Unknown edition \"2023_INVALID\".\n");
4368 }
4369 
TEST_F(ParseEditionsTest,UnknownEdition)4370 TEST_F(ParseEditionsTest, UnknownEdition) {
4371   ExpectHasEarlyExitErrors(
4372       R"schema(
4373         edition = "UNKNOWN";
4374         message A {
4375           optional int32 b = 1;
4376         })schema",
4377       "1:18: Unknown edition \"UNKNOWN\".\n");
4378 }
4379 
TEST_F(ParseEditionsTest,LegacyProto2Edition)4380 TEST_F(ParseEditionsTest, LegacyProto2Edition) {
4381   ExpectHasEarlyExitErrors(
4382       R"schema(
4383         edition = "PROTO2";
4384         message A {
4385           optional int32 b = 1;
4386         })schema",
4387       "1:18: Unknown edition \"PROTO2\".\n");
4388 }
4389 
TEST_F(ParseEditionsTest,LegacyProto3Edition)4390 TEST_F(ParseEditionsTest, LegacyProto3Edition) {
4391   ExpectHasEarlyExitErrors(
4392       R"schema(
4393         edition = "PROTO3";
4394         message A {
4395           optional int32 b = 1;
4396         })schema",
4397       "1:18: Unknown edition \"PROTO3\".\n");
4398 }
4399 
TEST_F(ParseEditionsTest,SyntaxEditions)4400 TEST_F(ParseEditionsTest, SyntaxEditions) {
4401   ExpectHasEarlyExitErrors(
4402       R"schema(
4403         syntax = "editions";
4404         message A {
4405           optional int32 b = 1;
4406         })schema",
4407       "1:17: Unrecognized syntax identifier \"editions\".  This parser only "
4408       "recognizes \"proto2\" and \"proto3\".\n");
4409 }
4410 
TEST_F(ParseEditionsTest,MixedSyntaxAndEdition)4411 TEST_F(ParseEditionsTest, MixedSyntaxAndEdition) {
4412   ExpectHasErrors(
4413       R"schema(
4414         syntax = "proto2";
4415         edition = "2023";
4416         message A {
4417           optional int32 b = 1;
4418         })schema",
4419       "2:8: Expected top-level statement (e.g. \"message\").\n");
4420 }
4421 
TEST_F(ParseEditionsTest,MixedEditionAndSyntax)4422 TEST_F(ParseEditionsTest, MixedEditionAndSyntax) {
4423   ExpectHasErrors(
4424       R"schema(
4425         edition = "2023";
4426         syntax = "proto2";
4427         message A {
4428           int32 b = 1;
4429         })schema",
4430       "2:8: Expected top-level statement (e.g. \"message\").\n");
4431 }
4432 
TEST_F(ParseEditionsTest,OptionalKeywordBanned)4433 TEST_F(ParseEditionsTest, OptionalKeywordBanned) {
4434   ExpectHasErrors(
4435       R"schema(
4436         edition = "2023";
4437         message A {
4438           optional int32 b = 1;
4439         })schema",
4440       "3:10: Label \"optional\" is not supported in editions. By default, all "
4441       "singular fields have presence unless features.field_presence is set.\n");
4442 }
4443 
TEST_F(ParseEditionsTest,RequiredKeywordBanned)4444 TEST_F(ParseEditionsTest, RequiredKeywordBanned) {
4445   ExpectHasErrors(
4446       R"schema(
4447         edition = "2023";
4448         message A {
4449           required int32 b = 1;
4450         })schema",
4451       "3:10: Label \"required\" is not supported in editions, use "
4452       "features.field_presence = LEGACY_REQUIRED.\n");
4453 }
4454 
TEST_F(ParseEditionsTest,GroupsBanned)4455 TEST_F(ParseEditionsTest, GroupsBanned) {
4456   ExpectHasErrors(
4457       R"schema(
4458         edition = "2023";
4459         message TestMessage {
4460           group TestGroup = 1 {};
4461         })schema",
4462       "3:10: Group syntax is no longer supported in editions. To get group "
4463       "behavior you can specify features.message_encoding = DELIMITED on a "
4464       "message field.\n");
4465 }
4466 
TEST_F(ParseEditionsTest,ValidationError)4467 TEST_F(ParseEditionsTest, ValidationError) {
4468   ExpectHasValidationErrors(
4469       R"schema(
4470         edition = "2023";
4471         option features.field_presence = IMPLICIT;
4472         option java_package = "blah";
4473         message TestMessage {
4474           string foo = 1 [default = "hello"];
4475         })schema",
4476       "5:17: Implicit presence fields can't specify defaults.\n");
4477 }
4478 
TEST_F(ParseEditionsTest,InvalidMerge)4479 TEST_F(ParseEditionsTest, InvalidMerge) {
4480   ExpectHasValidationErrors(
4481       R"schema(
4482         edition = "2023";
4483         option features.field_presence = IMPLICIT;
4484         option java_package = "blah";
4485         message TestMessage {
4486           string foo = 1 [
4487             default = "hello",
4488             features.field_presence = FIELD_PRESENCE_UNKNOWN,
4489             features.enum_type = ENUM_TYPE_UNKNOWN
4490           ];
4491         })schema",
4492       "5:17: Feature field `field_presence` must resolve to a known value, "
4493       "found FIELD_PRESENCE_UNKNOWN\n");
4494 }
4495 
TEST_F(ParseEditionsTest,FeaturesWithoutEditions)4496 TEST_F(ParseEditionsTest, FeaturesWithoutEditions) {
4497   ExpectHasValidationErrors(
4498       R"schema(
4499         syntax = "proto3";
4500         option features.field_presence = IMPLICIT;
4501         message TestMessage {
4502           string foo = 1 [
4503             default = "hello",
4504             features.field_presence = EXPLICIT
4505           ];
4506         })schema",
4507       "1:8: Features are only valid under editions.\n"
4508       "4:17: Features are only valid under editions.\n");
4509 }
4510 
4511 
4512 }  // anonymous namespace
4513 
4514 }  // namespace compiler
4515 }  // namespace protobuf
4516 }  // namespace google
4517 
4518 #include "google/protobuf/port_undef.inc"
4519