• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // http://code.google.com/p/protobuf/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Author: kenton@google.com (Kenton Varda)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 
35 #include <vector>
36 #include <algorithm>
37 
38 #include <google/protobuf/compiler/parser.h>
39 
40 #include <google/protobuf/io/tokenizer.h>
41 #include <google/protobuf/io/zero_copy_stream_impl.h>
42 #include <google/protobuf/descriptor.pb.h>
43 #include <google/protobuf/wire_format.h>
44 #include <google/protobuf/text_format.h>
45 #include <google/protobuf/unittest.pb.h>
46 #include <google/protobuf/stubs/strutil.h>
47 #include <google/protobuf/stubs/substitute.h>
48 
49 #include <google/protobuf/testing/googletest.h>
50 #include <gtest/gtest.h>
51 
52 namespace google {
53 namespace protobuf {
54 namespace compiler {
55 
56 namespace {
57 
58 class MockErrorCollector : public io::ErrorCollector {
59  public:
MockErrorCollector()60   MockErrorCollector() {}
~MockErrorCollector()61   ~MockErrorCollector() {}
62 
63   string text_;
64 
65   // implements ErrorCollector ---------------------------------------
AddError(int line,int column,const string & message)66   void AddError(int line, int column, const string& message) {
67     strings::SubstituteAndAppend(&text_, "$0:$1: $2\n",
68                                  line, column, message);
69   }
70 };
71 
72 class MockValidationErrorCollector : public DescriptorPool::ErrorCollector {
73  public:
MockValidationErrorCollector(const SourceLocationTable & source_locations,io::ErrorCollector * wrapped_collector)74   MockValidationErrorCollector(const SourceLocationTable& source_locations,
75                                io::ErrorCollector* wrapped_collector)
76     : source_locations_(source_locations),
77       wrapped_collector_(wrapped_collector) {}
~MockValidationErrorCollector()78   ~MockValidationErrorCollector() {}
79 
80   // implements ErrorCollector ---------------------------------------
AddError(const string & filename,const string & element_name,const Message * descriptor,ErrorLocation location,const string & message)81   void AddError(const string& filename,
82                 const string& element_name,
83                 const Message* descriptor,
84                 ErrorLocation location,
85                 const string& message) {
86     int line, column;
87     source_locations_.Find(descriptor, location, &line, &column);
88     wrapped_collector_->AddError(line, column, message);
89   }
90 
91  private:
92   const SourceLocationTable& source_locations_;
93   io::ErrorCollector* wrapped_collector_;
94 };
95 
96 class ParserTest : public testing::Test {
97  protected:
ParserTest()98   ParserTest()
99     : require_syntax_identifier_(false) {}
100 
101   // Set up the parser to parse the given text.
SetupParser(const char * text)102   void SetupParser(const char* text) {
103     raw_input_.reset(new io::ArrayInputStream(text, strlen(text)));
104     input_.reset(new io::Tokenizer(raw_input_.get(), &error_collector_));
105     parser_.reset(new 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     parser_->Parse(input_.get(), &actual);
118     EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
119     ASSERT_EQ("", error_collector_.text_);
120 
121     // Parse the ASCII representation in order to canonicalize it.  We could
122     // just compare directly to actual.DebugString(), but that would require
123     // that the caller precisely match the formatting that DebugString()
124     // produces.
125     ASSERT_TRUE(TextFormat::ParseFromString(output, &expected));
126 
127     // Compare by comparing debug strings.
128     // TODO(kenton):  Use differencer, once it is available.
129     EXPECT_EQ(expected.DebugString(), actual.DebugString());
130   }
131 
132   // Parse the text and expect that the given errors are reported.
ExpectHasErrors(const char * text,const char * expected_errors)133   void ExpectHasErrors(const char* text, const char* expected_errors) {
134     ExpectHasEarlyExitErrors(text, expected_errors);
135     EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
136   }
137 
138   // Same as above but does not expect that the parser parses the complete
139   // input.
ExpectHasEarlyExitErrors(const char * text,const char * expected_errors)140   void ExpectHasEarlyExitErrors(const char* text, const char* expected_errors) {
141     SetupParser(text);
142     FileDescriptorProto file;
143     parser_->Parse(input_.get(), &file);
144     EXPECT_EQ(expected_errors, error_collector_.text_);
145   }
146 
147   // Parse the text as a file and validate it (with a DescriptorPool), and
148   // expect that the validation step reports the given errors.
ExpectHasValidationErrors(const char * text,const char * expected_errors)149   void ExpectHasValidationErrors(const char* text,
150                                  const char* expected_errors) {
151     SetupParser(text);
152     SourceLocationTable source_locations;
153     parser_->RecordSourceLocationsTo(&source_locations);
154 
155     FileDescriptorProto file;
156     file.set_name("foo.proto");
157     parser_->Parse(input_.get(), &file);
158     EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
159     ASSERT_EQ("", error_collector_.text_);
160 
161     MockValidationErrorCollector validation_error_collector(
162       source_locations, &error_collector_);
163     EXPECT_TRUE(pool_.BuildFileCollectingErrors(
164       file, &validation_error_collector) == NULL);
165     EXPECT_EQ(expected_errors, error_collector_.text_);
166   }
167 
168   MockErrorCollector error_collector_;
169   DescriptorPool pool_;
170 
171   scoped_ptr<io::ZeroCopyInputStream> raw_input_;
172   scoped_ptr<io::Tokenizer> input_;
173   scoped_ptr<Parser> parser_;
174   bool require_syntax_identifier_;
175 };
176 
177 // ===================================================================
178 
TEST_F(ParserTest,StopAfterSyntaxIdentifier)179 TEST_F(ParserTest, StopAfterSyntaxIdentifier) {
180   SetupParser(
181     "// blah\n"
182     "syntax = \"foobar\";\n"
183     "this line will not be parsed\n");
184   parser_->SetStopAfterSyntaxIdentifier(true);
185   EXPECT_TRUE(parser_->Parse(input_.get(), NULL));
186   EXPECT_EQ("", error_collector_.text_);
187   EXPECT_EQ("foobar", parser_->GetSyntaxIdentifier());
188 }
189 
TEST_F(ParserTest,StopAfterOmittedSyntaxIdentifier)190 TEST_F(ParserTest, StopAfterOmittedSyntaxIdentifier) {
191   SetupParser(
192     "// blah\n"
193     "this line will not be parsed\n");
194   parser_->SetStopAfterSyntaxIdentifier(true);
195   EXPECT_TRUE(parser_->Parse(input_.get(), NULL));
196   EXPECT_EQ("", error_collector_.text_);
197   EXPECT_EQ("", parser_->GetSyntaxIdentifier());
198 }
199 
TEST_F(ParserTest,StopAfterSyntaxIdentifierWithErrors)200 TEST_F(ParserTest, StopAfterSyntaxIdentifierWithErrors) {
201   SetupParser(
202     "// blah\n"
203     "syntax = error;\n");
204   parser_->SetStopAfterSyntaxIdentifier(true);
205   EXPECT_FALSE(parser_->Parse(input_.get(), NULL));
206   EXPECT_EQ("1:9: Expected syntax identifier.\n", error_collector_.text_);
207 }
208 
209 // ===================================================================
210 
211 typedef ParserTest ParseMessageTest;
212 
TEST_F(ParseMessageTest,SimpleMessage)213 TEST_F(ParseMessageTest, SimpleMessage) {
214   ExpectParsesTo(
215     "message TestMessage {\n"
216     "  required int32 foo = 1;\n"
217     "}\n",
218 
219     "message_type {"
220     "  name: \"TestMessage\""
221     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
222     "}");
223 }
224 
TEST_F(ParseMessageTest,ImplicitSyntaxIdentifier)225 TEST_F(ParseMessageTest, ImplicitSyntaxIdentifier) {
226   require_syntax_identifier_ = false;
227   ExpectParsesTo(
228     "message TestMessage {\n"
229     "  required int32 foo = 1;\n"
230     "}\n",
231 
232     "message_type {"
233     "  name: \"TestMessage\""
234     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
235     "}");
236   EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
237 }
238 
TEST_F(ParseMessageTest,ExplicitSyntaxIdentifier)239 TEST_F(ParseMessageTest, ExplicitSyntaxIdentifier) {
240   ExpectParsesTo(
241     "syntax = \"proto2\";\n"
242     "message TestMessage {\n"
243     "  required int32 foo = 1;\n"
244     "}\n",
245 
246     "message_type {"
247     "  name: \"TestMessage\""
248     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
249     "}");
250   EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
251 }
252 
TEST_F(ParseMessageTest,ExplicitRequiredSyntaxIdentifier)253 TEST_F(ParseMessageTest, ExplicitRequiredSyntaxIdentifier) {
254   require_syntax_identifier_ = true;
255   ExpectParsesTo(
256     "syntax = \"proto2\";\n"
257     "message TestMessage {\n"
258     "  required int32 foo = 1;\n"
259     "}\n",
260 
261     "message_type {"
262     "  name: \"TestMessage\""
263     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
264     "}");
265   EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
266 }
267 
TEST_F(ParseMessageTest,SimpleFields)268 TEST_F(ParseMessageTest, SimpleFields) {
269   ExpectParsesTo(
270     "message TestMessage {\n"
271     "  required int32 foo = 15;\n"
272     "  optional int32 bar = 34;\n"
273     "  repeated int32 baz = 3;\n"
274     "}\n",
275 
276     "message_type {"
277     "  name: \"TestMessage\""
278     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:15 }"
279     "  field { name:\"bar\" label:LABEL_OPTIONAL type:TYPE_INT32 number:34 }"
280     "  field { name:\"baz\" label:LABEL_REPEATED type:TYPE_INT32 number:3  }"
281     "}");
282 }
283 
TEST_F(ParseMessageTest,PrimitiveFieldTypes)284 TEST_F(ParseMessageTest, PrimitiveFieldTypes) {
285   ExpectParsesTo(
286     "message TestMessage {\n"
287     "  required int32    foo = 1;\n"
288     "  required int64    foo = 1;\n"
289     "  required uint32   foo = 1;\n"
290     "  required uint64   foo = 1;\n"
291     "  required sint32   foo = 1;\n"
292     "  required sint64   foo = 1;\n"
293     "  required fixed32  foo = 1;\n"
294     "  required fixed64  foo = 1;\n"
295     "  required sfixed32 foo = 1;\n"
296     "  required sfixed64 foo = 1;\n"
297     "  required float    foo = 1;\n"
298     "  required double   foo = 1;\n"
299     "  required string   foo = 1;\n"
300     "  required bytes    foo = 1;\n"
301     "  required bool     foo = 1;\n"
302     "}\n",
303 
304     "message_type {"
305     "  name: \"TestMessage\""
306     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32    number:1 }"
307     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT64    number:1 }"
308     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_UINT32   number:1 }"
309     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_UINT64   number:1 }"
310     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SINT32   number:1 }"
311     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SINT64   number:1 }"
312     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FIXED32  number:1 }"
313     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FIXED64  number:1 }"
314     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SFIXED32 number:1 }"
315     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SFIXED64 number:1 }"
316     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FLOAT    number:1 }"
317     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_DOUBLE   number:1 }"
318     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_STRING   number:1 }"
319     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_BYTES    number:1 }"
320     "  field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_BOOL     number:1 }"
321     "}");
322 }
323 
TEST_F(ParseMessageTest,FieldDefaults)324 TEST_F(ParseMessageTest, FieldDefaults) {
325   ExpectParsesTo(
326     "message TestMessage {\n"
327     "  required int32  foo = 1 [default=  1  ];\n"
328     "  required int32  foo = 1 [default= -2  ];\n"
329     "  required int64  foo = 1 [default=  3  ];\n"
330     "  required int64  foo = 1 [default= -4  ];\n"
331     "  required uint32 foo = 1 [default=  5  ];\n"
332     "  required uint64 foo = 1 [default=  6  ];\n"
333     "  required float  foo = 1 [default=  7.5];\n"
334     "  required float  foo = 1 [default= -8.5];\n"
335     "  required float  foo = 1 [default=  9  ];\n"
336     "  required double foo = 1 [default= 10.5];\n"
337     "  required double foo = 1 [default=-11.5];\n"
338     "  required double foo = 1 [default= 12  ];\n"
339     "  required double foo = 1 [default= inf ];\n"
340     "  required double foo = 1 [default=-inf ];\n"
341     "  required double foo = 1 [default= nan ];\n"
342     "  required string foo = 1 [default='13\\001'];\n"
343     "  required string foo = 1 [default='a' \"b\" \n \"c\"];\n"
344     "  required bytes  foo = 1 [default='14\\002'];\n"
345     "  required bytes  foo = 1 [default='a' \"b\" \n 'c'];\n"
346     "  required bool   foo = 1 [default=true ];\n"
347     "  required Foo    foo = 1 [default=FOO  ];\n"
348 
349     "  required int32  foo = 1 [default= 0x7FFFFFFF];\n"
350     "  required int32  foo = 1 [default=-0x80000000];\n"
351     "  required uint32 foo = 1 [default= 0xFFFFFFFF];\n"
352     "  required int64  foo = 1 [default= 0x7FFFFFFFFFFFFFFF];\n"
353     "  required int64  foo = 1 [default=-0x8000000000000000];\n"
354     "  required uint64 foo = 1 [default= 0xFFFFFFFFFFFFFFFF];\n"
355     "  required double foo = 1 [default= 0xabcd];\n"
356     "}\n",
357 
358 #define ETC "name:\"foo\" label:LABEL_REQUIRED number:1"
359     "message_type {"
360     "  name: \"TestMessage\""
361     "  field { type:TYPE_INT32   default_value:\"1\"         "ETC" }"
362     "  field { type:TYPE_INT32   default_value:\"-2\"        "ETC" }"
363     "  field { type:TYPE_INT64   default_value:\"3\"         "ETC" }"
364     "  field { type:TYPE_INT64   default_value:\"-4\"        "ETC" }"
365     "  field { type:TYPE_UINT32  default_value:\"5\"         "ETC" }"
366     "  field { type:TYPE_UINT64  default_value:\"6\"         "ETC" }"
367     "  field { type:TYPE_FLOAT   default_value:\"7.5\"       "ETC" }"
368     "  field { type:TYPE_FLOAT   default_value:\"-8.5\"      "ETC" }"
369     "  field { type:TYPE_FLOAT   default_value:\"9\"         "ETC" }"
370     "  field { type:TYPE_DOUBLE  default_value:\"10.5\"      "ETC" }"
371     "  field { type:TYPE_DOUBLE  default_value:\"-11.5\"     "ETC" }"
372     "  field { type:TYPE_DOUBLE  default_value:\"12\"        "ETC" }"
373     "  field { type:TYPE_DOUBLE  default_value:\"inf\"       "ETC" }"
374     "  field { type:TYPE_DOUBLE  default_value:\"-inf\"      "ETC" }"
375     "  field { type:TYPE_DOUBLE  default_value:\"nan\"       "ETC" }"
376     "  field { type:TYPE_STRING  default_value:\"13\\001\"   "ETC" }"
377     "  field { type:TYPE_STRING  default_value:\"abc\"       "ETC" }"
378     "  field { type:TYPE_BYTES   default_value:\"14\\\\002\" "ETC" }"
379     "  field { type:TYPE_BYTES   default_value:\"abc\"       "ETC" }"
380     "  field { type:TYPE_BOOL    default_value:\"true\"      "ETC" }"
381     "  field { type_name:\"Foo\" default_value:\"FOO\"       "ETC" }"
382 
383     "  field { type:TYPE_INT32   default_value:\"2147483647\"           "ETC" }"
384     "  field { type:TYPE_INT32   default_value:\"-2147483648\"          "ETC" }"
385     "  field { type:TYPE_UINT32  default_value:\"4294967295\"           "ETC" }"
386     "  field { type:TYPE_INT64   default_value:\"9223372036854775807\"  "ETC" }"
387     "  field { type:TYPE_INT64   default_value:\"-9223372036854775808\" "ETC" }"
388     "  field { type:TYPE_UINT64  default_value:\"18446744073709551615\" "ETC" }"
389     "  field { type:TYPE_DOUBLE  default_value:\"43981\"                "ETC" }"
390     "}");
391 #undef ETC
392 }
393 
TEST_F(ParseMessageTest,FieldOptions)394 TEST_F(ParseMessageTest, FieldOptions) {
395   ExpectParsesTo(
396     "message TestMessage {\n"
397     "  optional string foo = 1\n"
398     "      [ctype=CORD, (foo)=7, foo.(.bar.baz).qux.quux.(corge)=-33, \n"
399     "       (quux)=\"x\040y\", (baz.qux)=hey];\n"
400     "}\n",
401 
402     "message_type {"
403     "  name: \"TestMessage\""
404     "  field { name: \"foo\" label: LABEL_OPTIONAL type: TYPE_STRING number: 1"
405     "          options { uninterpreted_option: { name { name_part: \"ctype\" "
406     "                                                   is_extension: false } "
407     "                                            identifier_value: \"CORD\"  }"
408     "                    uninterpreted_option: { name { name_part: \"foo\" "
409     "                                                   is_extension: true } "
410     "                                            positive_int_value: 7  }"
411     "                    uninterpreted_option: { name { name_part: \"foo\" "
412     "                                                   is_extension: false } "
413     "                                            name { name_part: \".bar.baz\""
414     "                                                   is_extension: true } "
415     "                                            name { name_part: \"qux\" "
416     "                                                   is_extension: false } "
417     "                                            name { name_part: \"quux\" "
418     "                                                   is_extension: false } "
419     "                                            name { name_part: \"corge\" "
420     "                                                   is_extension: true } "
421     "                                            negative_int_value: -33 }"
422     "                    uninterpreted_option: { name { name_part: \"quux\" "
423     "                                                   is_extension: true } "
424     "                                            string_value: \"x y\" }"
425     "                    uninterpreted_option: { name { name_part: \"baz.qux\" "
426     "                                                   is_extension: true } "
427     "                                            identifier_value: \"hey\" }"
428     "          }"
429     "  }"
430     "}");
431 }
432 
TEST_F(ParseMessageTest,Group)433 TEST_F(ParseMessageTest, Group) {
434   ExpectParsesTo(
435     "message TestMessage {\n"
436     "  optional group TestGroup = 1 {};\n"
437     "}\n",
438 
439     "message_type {"
440     "  name: \"TestMessage\""
441     "  nested_type { name: \"TestGroup\" }"
442     "  field { name:\"testgroup\" label:LABEL_OPTIONAL number:1"
443     "          type:TYPE_GROUP type_name: \"TestGroup\" }"
444     "}");
445 }
446 
TEST_F(ParseMessageTest,NestedMessage)447 TEST_F(ParseMessageTest, NestedMessage) {
448   ExpectParsesTo(
449     "message TestMessage {\n"
450     "  message Nested {}\n"
451     "  optional Nested test_nested = 1;\n"
452     "}\n",
453 
454     "message_type {"
455     "  name: \"TestMessage\""
456     "  nested_type { name: \"Nested\" }"
457     "  field { name:\"test_nested\" label:LABEL_OPTIONAL number:1"
458     "          type_name: \"Nested\" }"
459     "}");
460 }
461 
TEST_F(ParseMessageTest,NestedEnum)462 TEST_F(ParseMessageTest, NestedEnum) {
463   ExpectParsesTo(
464     "message TestMessage {\n"
465     "  enum NestedEnum {}\n"
466     "  optional NestedEnum test_enum = 1;\n"
467     "}\n",
468 
469     "message_type {"
470     "  name: \"TestMessage\""
471     "  enum_type { name: \"NestedEnum\" }"
472     "  field { name:\"test_enum\" label:LABEL_OPTIONAL number:1"
473     "          type_name: \"NestedEnum\" }"
474     "}");
475 }
476 
TEST_F(ParseMessageTest,ExtensionRange)477 TEST_F(ParseMessageTest, ExtensionRange) {
478   ExpectParsesTo(
479     "message TestMessage {\n"
480     "  extensions 10 to 19;\n"
481     "  extensions 30 to max;\n"
482     "}\n",
483 
484     "message_type {"
485     "  name: \"TestMessage\""
486     "  extension_range { start:10 end:20        }"
487     "  extension_range { start:30 end:536870912 }"
488     "}");
489 }
490 
TEST_F(ParseMessageTest,CompoundExtensionRange)491 TEST_F(ParseMessageTest, CompoundExtensionRange) {
492   ExpectParsesTo(
493     "message TestMessage {\n"
494     "  extensions 2, 15, 9 to 11, 100 to max, 3;\n"
495     "}\n",
496 
497     "message_type {"
498     "  name: \"TestMessage\""
499     "  extension_range { start:2   end:3         }"
500     "  extension_range { start:15  end:16        }"
501     "  extension_range { start:9   end:12        }"
502     "  extension_range { start:100 end:536870912 }"
503     "  extension_range { start:3   end:4         }"
504     "}");
505 }
506 
TEST_F(ParseMessageTest,Extensions)507 TEST_F(ParseMessageTest, Extensions) {
508   ExpectParsesTo(
509     "extend Extendee1 { optional int32 foo = 12; }\n"
510     "extend Extendee2 { repeated TestMessage bar = 22; }\n",
511 
512     "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12"
513     "            extendee: \"Extendee1\" } "
514     "extension { name:\"bar\" label:LABEL_REPEATED number:22"
515     "            type_name:\"TestMessage\" extendee: \"Extendee2\" }");
516 }
517 
TEST_F(ParseMessageTest,ExtensionsInMessageScope)518 TEST_F(ParseMessageTest, ExtensionsInMessageScope) {
519   ExpectParsesTo(
520     "message TestMessage {\n"
521     "  extend Extendee1 { optional int32 foo = 12; }\n"
522     "  extend Extendee2 { repeated TestMessage bar = 22; }\n"
523     "}\n",
524 
525     "message_type {"
526     "  name: \"TestMessage\""
527     "  extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12"
528     "              extendee: \"Extendee1\" }"
529     "  extension { name:\"bar\" label:LABEL_REPEATED number:22"
530     "              type_name:\"TestMessage\" extendee: \"Extendee2\" }"
531     "}");
532 }
533 
TEST_F(ParseMessageTest,MultipleExtensionsOneExtendee)534 TEST_F(ParseMessageTest, MultipleExtensionsOneExtendee) {
535   ExpectParsesTo(
536     "extend Extendee1 {\n"
537     "  optional int32 foo = 12;\n"
538     "  repeated TestMessage bar = 22;\n"
539     "}\n",
540 
541     "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12"
542     "            extendee: \"Extendee1\" } "
543     "extension { name:\"bar\" label:LABEL_REPEATED number:22"
544     "            type_name:\"TestMessage\" extendee: \"Extendee1\" }");
545 }
546 
547 // ===================================================================
548 
549 typedef ParserTest ParseEnumTest;
550 
TEST_F(ParseEnumTest,SimpleEnum)551 TEST_F(ParseEnumTest, SimpleEnum) {
552   ExpectParsesTo(
553     "enum TestEnum {\n"
554     "  FOO = 0;\n"
555     "}\n",
556 
557     "enum_type {"
558     "  name: \"TestEnum\""
559     "  value { name:\"FOO\" number:0 }"
560     "}");
561 }
562 
TEST_F(ParseEnumTest,Values)563 TEST_F(ParseEnumTest, Values) {
564   ExpectParsesTo(
565     "enum TestEnum {\n"
566     "  FOO = 13;\n"
567     "  BAR = -10;\n"
568     "  BAZ = 500;\n"
569     "}\n",
570 
571     "enum_type {"
572     "  name: \"TestEnum\""
573     "  value { name:\"FOO\" number:13 }"
574     "  value { name:\"BAR\" number:-10 }"
575     "  value { name:\"BAZ\" number:500 }"
576     "}");
577 }
578 
TEST_F(ParseEnumTest,ValueOptions)579 TEST_F(ParseEnumTest, ValueOptions) {
580   ExpectParsesTo(
581     "enum TestEnum {\n"
582     "  FOO = 13;\n"
583     "  BAR = -10 [ (something.text) = 'abc' ];\n"
584     "  BAZ = 500 [ (something.text) = 'def', other = 1 ];\n"
585     "}\n",
586 
587     "enum_type {"
588     "  name: \"TestEnum\""
589     "  value { name: \"FOO\" number: 13 }"
590     "  value { name: \"BAR\" number: -10 "
591     "    options { "
592     "      uninterpreted_option { "
593     "        name { name_part: \"something.text\" is_extension: true } "
594     "        string_value: \"abc\" "
595     "      } "
596     "    } "
597     "  } "
598     "  value { name: \"BAZ\" number: 500 "
599     "    options { "
600     "      uninterpreted_option { "
601     "        name { name_part: \"something.text\" is_extension: true } "
602     "        string_value: \"def\" "
603     "      } "
604     "      uninterpreted_option { "
605     "        name { name_part: \"other\" is_extension: false } "
606     "        positive_int_value: 1 "
607     "      } "
608     "    } "
609     "  } "
610     "}");
611 }
612 
613 // ===================================================================
614 
615 typedef ParserTest ParseServiceTest;
616 
TEST_F(ParseServiceTest,SimpleService)617 TEST_F(ParseServiceTest, SimpleService) {
618   ExpectParsesTo(
619     "service TestService {\n"
620     "  rpc Foo(In) returns (Out);\n"
621     "}\n",
622 
623     "service {"
624     "  name: \"TestService\""
625     "  method { name:\"Foo\" input_type:\"In\" output_type:\"Out\" }"
626     "}");
627 }
628 
TEST_F(ParseServiceTest,Methods)629 TEST_F(ParseServiceTest, Methods) {
630   ExpectParsesTo(
631     "service TestService {\n"
632     "  rpc Foo(In1) returns (Out1);\n"
633     "  rpc Bar(In2) returns (Out2);\n"
634     "  rpc Baz(In3) returns (Out3);\n"
635     "}\n",
636 
637     "service {"
638     "  name: \"TestService\""
639     "  method { name:\"Foo\" input_type:\"In1\" output_type:\"Out1\" }"
640     "  method { name:\"Bar\" input_type:\"In2\" output_type:\"Out2\" }"
641     "  method { name:\"Baz\" input_type:\"In3\" output_type:\"Out3\" }"
642     "}");
643 }
644 
645 // ===================================================================
646 // imports and packages
647 
648 typedef ParserTest ParseMiscTest;
649 
TEST_F(ParseMiscTest,ParseImport)650 TEST_F(ParseMiscTest, ParseImport) {
651   ExpectParsesTo(
652     "import \"foo/bar/baz.proto\";\n",
653     "dependency: \"foo/bar/baz.proto\"");
654 }
655 
TEST_F(ParseMiscTest,ParseMultipleImports)656 TEST_F(ParseMiscTest, ParseMultipleImports) {
657   ExpectParsesTo(
658     "import \"foo.proto\";\n"
659     "import \"bar.proto\";\n"
660     "import \"baz.proto\";\n",
661     "dependency: \"foo.proto\""
662     "dependency: \"bar.proto\""
663     "dependency: \"baz.proto\"");
664 }
665 
TEST_F(ParseMiscTest,ParsePackage)666 TEST_F(ParseMiscTest, ParsePackage) {
667   ExpectParsesTo(
668     "package foo.bar.baz;\n",
669     "package: \"foo.bar.baz\"");
670 }
671 
TEST_F(ParseMiscTest,ParsePackageWithSpaces)672 TEST_F(ParseMiscTest, ParsePackageWithSpaces) {
673   ExpectParsesTo(
674     "package foo   .   bar.  \n"
675     "  baz;\n",
676     "package: \"foo.bar.baz\"");
677 }
678 
679 // ===================================================================
680 // options
681 
TEST_F(ParseMiscTest,ParseFileOptions)682 TEST_F(ParseMiscTest, ParseFileOptions) {
683   ExpectParsesTo(
684     "option java_package = \"com.google.foo\";\n"
685     "option optimize_for = CODE_SIZE;",
686 
687     "options {"
688     "uninterpreted_option { name { name_part: \"java_package\" "
689     "                              is_extension: false }"
690     "                       string_value: \"com.google.foo\"} "
691     "uninterpreted_option { name { name_part: \"optimize_for\" "
692     "                              is_extension: false }"
693     "                       identifier_value: \"CODE_SIZE\" } "
694     "}");
695 }
696 
697 // ===================================================================
698 // Error tests
699 //
700 // There are a very large number of possible errors that the parser could
701 // report, so it's infeasible to test every single one of them.  Instead,
702 // we test each unique call to AddError() in parser.h.  This does not mean
703 // we are testing every possible error that Parser can generate because
704 // each variant of the Consume() helper only counts as one unique call to
705 // AddError().
706 
707 typedef ParserTest ParseErrorTest;
708 
TEST_F(ParseErrorTest,MissingSyntaxIdentifier)709 TEST_F(ParseErrorTest, MissingSyntaxIdentifier) {
710   require_syntax_identifier_ = true;
711   ExpectHasEarlyExitErrors(
712     "message TestMessage {}",
713     "0:0: File must begin with 'syntax = \"proto2\";'.\n");
714   EXPECT_EQ("", parser_->GetSyntaxIdentifier());
715 }
716 
TEST_F(ParseErrorTest,UnknownSyntaxIdentifier)717 TEST_F(ParseErrorTest, UnknownSyntaxIdentifier) {
718   ExpectHasEarlyExitErrors(
719     "syntax = \"no_such_syntax\";",
720     "0:9: Unrecognized syntax identifier \"no_such_syntax\".  This parser "
721       "only recognizes \"proto2\".\n");
722   EXPECT_EQ("no_such_syntax", parser_->GetSyntaxIdentifier());
723 }
724 
TEST_F(ParseErrorTest,SimpleSyntaxError)725 TEST_F(ParseErrorTest, SimpleSyntaxError) {
726   ExpectHasErrors(
727     "message TestMessage @#$ { blah }",
728     "0:20: Expected \"{\".\n");
729   EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
730 }
731 
TEST_F(ParseErrorTest,ExpectedTopLevel)732 TEST_F(ParseErrorTest, ExpectedTopLevel) {
733   ExpectHasErrors(
734     "blah;",
735     "0:0: Expected top-level statement (e.g. \"message\").\n");
736 }
737 
TEST_F(ParseErrorTest,UnmatchedCloseBrace)738 TEST_F(ParseErrorTest, UnmatchedCloseBrace) {
739   // This used to cause an infinite loop.  Doh.
740   ExpectHasErrors(
741     "}",
742     "0:0: Expected top-level statement (e.g. \"message\").\n"
743     "0:0: Unmatched \"}\".\n");
744 }
745 
746 // -------------------------------------------------------------------
747 // Message errors
748 
TEST_F(ParseErrorTest,MessageMissingName)749 TEST_F(ParseErrorTest, MessageMissingName) {
750   ExpectHasErrors(
751     "message {}",
752     "0:8: Expected message name.\n");
753 }
754 
TEST_F(ParseErrorTest,MessageMissingBody)755 TEST_F(ParseErrorTest, MessageMissingBody) {
756   ExpectHasErrors(
757     "message TestMessage;",
758     "0:19: Expected \"{\".\n");
759 }
760 
TEST_F(ParseErrorTest,EofInMessage)761 TEST_F(ParseErrorTest, EofInMessage) {
762   ExpectHasErrors(
763     "message TestMessage {",
764     "0:21: Reached end of input in message definition (missing '}').\n");
765 }
766 
TEST_F(ParseErrorTest,MissingFieldNumber)767 TEST_F(ParseErrorTest, MissingFieldNumber) {
768   ExpectHasErrors(
769     "message TestMessage {\n"
770     "  optional int32 foo;\n"
771     "}\n",
772     "1:20: Missing field number.\n");
773 }
774 
TEST_F(ParseErrorTest,ExpectedFieldNumber)775 TEST_F(ParseErrorTest, ExpectedFieldNumber) {
776   ExpectHasErrors(
777     "message TestMessage {\n"
778     "  optional int32 foo = ;\n"
779     "}\n",
780     "1:23: Expected field number.\n");
781 }
782 
TEST_F(ParseErrorTest,FieldNumberOutOfRange)783 TEST_F(ParseErrorTest, FieldNumberOutOfRange) {
784   ExpectHasErrors(
785     "message TestMessage {\n"
786     "  optional int32 foo = 0x100000000;\n"
787     "}\n",
788     "1:23: Integer out of range.\n");
789 }
790 
TEST_F(ParseErrorTest,MissingLabel)791 TEST_F(ParseErrorTest, MissingLabel) {
792   ExpectHasErrors(
793     "message TestMessage {\n"
794     "  int32 foo = 1;\n"
795     "}\n",
796     "1:2: Expected \"required\", \"optional\", or \"repeated\".\n");
797 }
798 
TEST_F(ParseErrorTest,ExpectedOptionName)799 TEST_F(ParseErrorTest, ExpectedOptionName) {
800   ExpectHasErrors(
801     "message TestMessage {\n"
802     "  optional uint32 foo = 1 [];\n"
803     "}\n",
804     "1:27: Expected identifier.\n");
805 }
806 
TEST_F(ParseErrorTest,NonExtensionOptionNameBeginningWithDot)807 TEST_F(ParseErrorTest, NonExtensionOptionNameBeginningWithDot) {
808   ExpectHasErrors(
809     "message TestMessage {\n"
810     "  optional uint32 foo = 1 [.foo=1];\n"
811     "}\n",
812     "1:27: Expected identifier.\n");
813 }
814 
TEST_F(ParseErrorTest,DefaultValueTypeMismatch)815 TEST_F(ParseErrorTest, DefaultValueTypeMismatch) {
816   ExpectHasErrors(
817     "message TestMessage {\n"
818     "  optional uint32 foo = 1 [default=true];\n"
819     "}\n",
820     "1:35: Expected integer.\n");
821 }
822 
TEST_F(ParseErrorTest,DefaultValueNotBoolean)823 TEST_F(ParseErrorTest, DefaultValueNotBoolean) {
824   ExpectHasErrors(
825     "message TestMessage {\n"
826     "  optional bool foo = 1 [default=blah];\n"
827     "}\n",
828     "1:33: Expected \"true\" or \"false\".\n");
829 }
830 
TEST_F(ParseErrorTest,DefaultValueNotString)831 TEST_F(ParseErrorTest, DefaultValueNotString) {
832   ExpectHasErrors(
833     "message TestMessage {\n"
834     "  optional string foo = 1 [default=1];\n"
835     "}\n",
836     "1:35: Expected string.\n");
837 }
838 
TEST_F(ParseErrorTest,DefaultValueUnsignedNegative)839 TEST_F(ParseErrorTest, DefaultValueUnsignedNegative) {
840   ExpectHasErrors(
841     "message TestMessage {\n"
842     "  optional uint32 foo = 1 [default=-1];\n"
843     "}\n",
844     "1:36: Unsigned field can't have negative default value.\n");
845 }
846 
TEST_F(ParseErrorTest,DefaultValueTooLarge)847 TEST_F(ParseErrorTest, DefaultValueTooLarge) {
848   ExpectHasErrors(
849     "message TestMessage {\n"
850     "  optional int32  foo = 1 [default= 0x80000000];\n"
851     "  optional int32  foo = 1 [default=-0x80000001];\n"
852     "  optional uint32 foo = 1 [default= 0x100000000];\n"
853     "  optional int64  foo = 1 [default= 0x80000000000000000];\n"
854     "  optional int64  foo = 1 [default=-0x80000000000000001];\n"
855     "  optional uint64 foo = 1 [default= 0x100000000000000000];\n"
856     "}\n",
857     "1:36: Integer out of range.\n"
858     "2:36: Integer out of range.\n"
859     "3:36: Integer out of range.\n"
860     "4:36: Integer out of range.\n"
861     "5:36: Integer out of range.\n"
862     "6:36: Integer out of range.\n");
863 }
864 
TEST_F(ParseErrorTest,DefaultValueMissing)865 TEST_F(ParseErrorTest, DefaultValueMissing) {
866   ExpectHasErrors(
867     "message TestMessage {\n"
868     "  optional uint32 foo = 1 [default=];\n"
869     "}\n",
870     "1:35: Expected integer.\n");
871 }
872 
TEST_F(ParseErrorTest,DefaultValueForGroup)873 TEST_F(ParseErrorTest, DefaultValueForGroup) {
874   ExpectHasErrors(
875     "message TestMessage {\n"
876     "  optional group Foo = 1 [default=blah] {}\n"
877     "}\n",
878     "1:34: Messages can't have default values.\n");
879 }
880 
TEST_F(ParseErrorTest,DuplicateDefaultValue)881 TEST_F(ParseErrorTest, DuplicateDefaultValue) {
882   ExpectHasErrors(
883     "message TestMessage {\n"
884     "  optional uint32 foo = 1 [default=1,default=2];\n"
885     "}\n",
886     "1:37: Already set option \"default\".\n");
887 }
888 
TEST_F(ParseErrorTest,GroupNotCapitalized)889 TEST_F(ParseErrorTest, GroupNotCapitalized) {
890   ExpectHasErrors(
891     "message TestMessage {\n"
892     "  optional group foo = 1 {}\n"
893     "}\n",
894     "1:17: Group names must start with a capital letter.\n");
895 }
896 
TEST_F(ParseErrorTest,GroupMissingBody)897 TEST_F(ParseErrorTest, GroupMissingBody) {
898   ExpectHasErrors(
899     "message TestMessage {\n"
900     "  optional group Foo = 1;\n"
901     "}\n",
902     "1:24: Missing group body.\n");
903 }
904 
TEST_F(ParseErrorTest,ExtendingPrimitive)905 TEST_F(ParseErrorTest, ExtendingPrimitive) {
906   ExpectHasErrors(
907     "extend int32 { optional string foo = 4; }\n",
908     "0:7: Expected message type.\n");
909 }
910 
TEST_F(ParseErrorTest,ErrorInExtension)911 TEST_F(ParseErrorTest, ErrorInExtension) {
912   ExpectHasErrors(
913     "message Foo { extensions 100 to 199; }\n"
914     "extend Foo { optional string foo; }\n",
915     "1:32: Missing field number.\n");
916 }
917 
TEST_F(ParseErrorTest,MultipleParseErrors)918 TEST_F(ParseErrorTest, MultipleParseErrors) {
919   // When a statement has a parse error, the parser should be able to continue
920   // parsing at the next statement.
921   ExpectHasErrors(
922     "message TestMessage {\n"
923     "  optional int32 foo;\n"
924     "  !invalid statement ending in a block { blah blah { blah } blah }\n"
925     "  optional int32 bar = 3 {}\n"
926     "}\n",
927     "1:20: Missing field number.\n"
928     "2:2: Expected \"required\", \"optional\", or \"repeated\".\n"
929     "2:2: Expected type name.\n"
930     "3:25: Expected \";\".\n");
931 }
932 
933 // -------------------------------------------------------------------
934 // Enum errors
935 
TEST_F(ParseErrorTest,EofInEnum)936 TEST_F(ParseErrorTest, EofInEnum) {
937   ExpectHasErrors(
938     "enum TestEnum {",
939     "0:15: Reached end of input in enum definition (missing '}').\n");
940 }
941 
TEST_F(ParseErrorTest,EnumValueMissingNumber)942 TEST_F(ParseErrorTest, EnumValueMissingNumber) {
943   ExpectHasErrors(
944     "enum TestEnum {\n"
945     "  FOO;\n"
946     "}\n",
947     "1:5: Missing numeric value for enum constant.\n");
948 }
949 
950 // -------------------------------------------------------------------
951 // Service errors
952 
TEST_F(ParseErrorTest,EofInService)953 TEST_F(ParseErrorTest, EofInService) {
954   ExpectHasErrors(
955     "service TestService {",
956     "0:21: Reached end of input in service definition (missing '}').\n");
957 }
958 
TEST_F(ParseErrorTest,ServiceMethodPrimitiveParams)959 TEST_F(ParseErrorTest, ServiceMethodPrimitiveParams) {
960   ExpectHasErrors(
961     "service TestService {\n"
962     "  rpc Foo(int32) returns (string);\n"
963     "}\n",
964     "1:10: Expected message type.\n"
965     "1:26: Expected message type.\n");
966 }
967 
TEST_F(ParseErrorTest,EofInMethodOptions)968 TEST_F(ParseErrorTest, EofInMethodOptions) {
969   ExpectHasErrors(
970     "service TestService {\n"
971     "  rpc Foo(Bar) returns(Bar) {",
972     "1:29: Reached end of input in method options (missing '}').\n"
973     "1:29: Reached end of input in service definition (missing '}').\n");
974 }
975 
TEST_F(ParseErrorTest,PrimitiveMethodInput)976 TEST_F(ParseErrorTest, PrimitiveMethodInput) {
977   ExpectHasErrors(
978     "service TestService {\n"
979     "  rpc Foo(int32) returns(Bar);\n"
980     "}\n",
981     "1:10: Expected message type.\n");
982 }
983 
TEST_F(ParseErrorTest,MethodOptionTypeError)984 TEST_F(ParseErrorTest, MethodOptionTypeError) {
985   // This used to cause an infinite loop.
986   ExpectHasErrors(
987     "message Baz {}\n"
988     "service Foo {\n"
989     "  rpc Bar(Baz) returns(Baz) { option invalid syntax; }\n"
990     "}\n",
991     "2:45: Expected \"=\".\n");
992 }
993 
994 // -------------------------------------------------------------------
995 // Import and package errors
996 
TEST_F(ParseErrorTest,ImportNotQuoted)997 TEST_F(ParseErrorTest, ImportNotQuoted) {
998   ExpectHasErrors(
999     "import foo;\n",
1000     "0:7: Expected a string naming the file to import.\n");
1001 }
1002 
TEST_F(ParseErrorTest,MultiplePackagesInFile)1003 TEST_F(ParseErrorTest, MultiplePackagesInFile) {
1004   ExpectHasErrors(
1005     "package foo;\n"
1006     "package bar;\n",
1007     "1:0: Multiple package definitions.\n");
1008 }
1009 
1010 // ===================================================================
1011 // Test that errors detected by DescriptorPool correctly report line and
1012 // column numbers.  We have one test for every call to RecordLocation() in
1013 // parser.cc.
1014 
1015 typedef ParserTest ParserValidationErrorTest;
1016 
TEST_F(ParserValidationErrorTest,PackageNameError)1017 TEST_F(ParserValidationErrorTest, PackageNameError) {
1018   // Create another file which defines symbol "foo".
1019   FileDescriptorProto other_file;
1020   other_file.set_name("bar.proto");
1021   other_file.add_message_type()->set_name("foo");
1022   EXPECT_TRUE(pool_.BuildFile(other_file) != NULL);
1023 
1024   // Now try to define it as a package.
1025   ExpectHasValidationErrors(
1026     "package foo.bar;",
1027     "0:8: \"foo\" is already defined (as something other than a package) "
1028       "in file \"bar.proto\".\n");
1029 }
1030 
TEST_F(ParserValidationErrorTest,MessageNameError)1031 TEST_F(ParserValidationErrorTest, MessageNameError) {
1032   ExpectHasValidationErrors(
1033     "message Foo {}\n"
1034     "message Foo {}\n",
1035     "1:8: \"Foo\" is already defined.\n");
1036 }
1037 
TEST_F(ParserValidationErrorTest,FieldNameError)1038 TEST_F(ParserValidationErrorTest, FieldNameError) {
1039   ExpectHasValidationErrors(
1040     "message Foo {\n"
1041     "  optional int32 bar = 1;\n"
1042     "  optional int32 bar = 2;\n"
1043     "}\n",
1044     "2:17: \"bar\" is already defined in \"Foo\".\n");
1045 }
1046 
TEST_F(ParserValidationErrorTest,FieldTypeError)1047 TEST_F(ParserValidationErrorTest, FieldTypeError) {
1048   ExpectHasValidationErrors(
1049     "message Foo {\n"
1050     "  optional Baz bar = 1;\n"
1051     "}\n",
1052     "1:11: \"Baz\" is not defined.\n");
1053 }
1054 
TEST_F(ParserValidationErrorTest,FieldNumberError)1055 TEST_F(ParserValidationErrorTest, FieldNumberError) {
1056   ExpectHasValidationErrors(
1057     "message Foo {\n"
1058     "  optional int32 bar = 0;\n"
1059     "}\n",
1060     "1:23: Field numbers must be positive integers.\n");
1061 }
1062 
TEST_F(ParserValidationErrorTest,FieldExtendeeError)1063 TEST_F(ParserValidationErrorTest, FieldExtendeeError) {
1064   ExpectHasValidationErrors(
1065     "extend Baz { optional int32 bar = 1; }\n",
1066     "0:7: \"Baz\" is not defined.\n");
1067 }
1068 
TEST_F(ParserValidationErrorTest,FieldDefaultValueError)1069 TEST_F(ParserValidationErrorTest, FieldDefaultValueError) {
1070   ExpectHasValidationErrors(
1071     "enum Baz { QUX = 1; }\n"
1072     "message Foo {\n"
1073     "  optional Baz bar = 1 [default=NO_SUCH_VALUE];\n"
1074     "}\n",
1075     "2:32: Enum type \"Baz\" has no value named \"NO_SUCH_VALUE\".\n");
1076 }
1077 
TEST_F(ParserValidationErrorTest,FileOptionNameError)1078 TEST_F(ParserValidationErrorTest, FileOptionNameError) {
1079   ExpectHasValidationErrors(
1080     "option foo = 5;",
1081     "0:7: Option \"foo\" unknown.\n");
1082 }
1083 
TEST_F(ParserValidationErrorTest,FileOptionValueError)1084 TEST_F(ParserValidationErrorTest, FileOptionValueError) {
1085   ExpectHasValidationErrors(
1086     "option java_outer_classname = 5;",
1087     "0:30: Value must be quoted string for string option "
1088     "\"google.protobuf.FileOptions.java_outer_classname\".\n");
1089 }
1090 
TEST_F(ParserValidationErrorTest,FieldOptionNameError)1091 TEST_F(ParserValidationErrorTest, FieldOptionNameError) {
1092   ExpectHasValidationErrors(
1093     "message Foo {\n"
1094     "  optional bool bar = 1 [foo=1];\n"
1095     "}\n",
1096     "1:25: Option \"foo\" unknown.\n");
1097 }
1098 
TEST_F(ParserValidationErrorTest,FieldOptionValueError)1099 TEST_F(ParserValidationErrorTest, FieldOptionValueError) {
1100   ExpectHasValidationErrors(
1101     "message Foo {\n"
1102     "  optional int32 bar = 1 [ctype=1];\n"
1103     "}\n",
1104     "1:32: Value must be identifier for enum-valued option "
1105     "\"google.protobuf.FieldOptions.ctype\".\n");
1106 }
1107 
TEST_F(ParserValidationErrorTest,ExtensionRangeNumberError)1108 TEST_F(ParserValidationErrorTest, ExtensionRangeNumberError) {
1109   ExpectHasValidationErrors(
1110     "message Foo {\n"
1111     "  extensions 0;\n"
1112     "}\n",
1113     "1:13: Extension numbers must be positive integers.\n");
1114 }
1115 
TEST_F(ParserValidationErrorTest,EnumNameError)1116 TEST_F(ParserValidationErrorTest, EnumNameError) {
1117   ExpectHasValidationErrors(
1118     "enum Foo {A = 1;}\n"
1119     "enum Foo {B = 1;}\n",
1120     "1:5: \"Foo\" is already defined.\n");
1121 }
1122 
TEST_F(ParserValidationErrorTest,EnumValueNameError)1123 TEST_F(ParserValidationErrorTest, EnumValueNameError) {
1124   ExpectHasValidationErrors(
1125     "enum Foo {\n"
1126     "  BAR = 1;\n"
1127     "  BAR = 1;\n"
1128     "}\n",
1129     "2:2: \"BAR\" is already defined.\n");
1130 }
1131 
TEST_F(ParserValidationErrorTest,ServiceNameError)1132 TEST_F(ParserValidationErrorTest, ServiceNameError) {
1133   ExpectHasValidationErrors(
1134     "service Foo {}\n"
1135     "service Foo {}\n",
1136     "1:8: \"Foo\" is already defined.\n");
1137 }
1138 
TEST_F(ParserValidationErrorTest,MethodNameError)1139 TEST_F(ParserValidationErrorTest, MethodNameError) {
1140   ExpectHasValidationErrors(
1141     "message Baz {}\n"
1142     "service Foo {\n"
1143     "  rpc Bar(Baz) returns(Baz);\n"
1144     "  rpc Bar(Baz) returns(Baz);\n"
1145     "}\n",
1146     "3:6: \"Bar\" is already defined in \"Foo\".\n");
1147 }
1148 
TEST_F(ParserValidationErrorTest,MethodInputTypeError)1149 TEST_F(ParserValidationErrorTest, MethodInputTypeError) {
1150   ExpectHasValidationErrors(
1151     "message Baz {}\n"
1152     "service Foo {\n"
1153     "  rpc Bar(Qux) returns(Baz);\n"
1154     "}\n",
1155     "2:10: \"Qux\" is not defined.\n");
1156 }
1157 
TEST_F(ParserValidationErrorTest,MethodOutputTypeError)1158 TEST_F(ParserValidationErrorTest, MethodOutputTypeError) {
1159   ExpectHasValidationErrors(
1160     "message Baz {}\n"
1161     "service Foo {\n"
1162     "  rpc Bar(Baz) returns(Qux);\n"
1163     "}\n",
1164     "2:23: \"Qux\" is not defined.\n");
1165 }
1166 
1167 // ===================================================================
1168 // Test that the output from FileDescriptor::DebugString() (and all other
1169 // descriptor types) is parseable, and results in the same Descriptor
1170 // definitions again afoter parsing (not, however, that the order of messages
1171 // cannot be guaranteed to be the same)
1172 
1173 typedef ParserTest ParseDecriptorDebugTest;
1174 
1175 class CompareDescriptorNames {
1176  public:
operator ()(const DescriptorProto * left,const DescriptorProto * right)1177   bool operator()(const DescriptorProto* left, const DescriptorProto* right) {
1178     return left->name() < right->name();
1179   }
1180 };
1181 
1182 // Sorts nested DescriptorProtos of a DescriptoProto, by name.
SortMessages(DescriptorProto * descriptor_proto)1183 void SortMessages(DescriptorProto *descriptor_proto) {
1184   int size = descriptor_proto->nested_type_size();
1185   // recursively sort; we can't guarantee the order of nested messages either
1186   for (int i = 0; i < size; ++i) {
1187     SortMessages(descriptor_proto->mutable_nested_type(i));
1188   }
1189   DescriptorProto **data =
1190     descriptor_proto->mutable_nested_type()->mutable_data();
1191   sort(data, data + size, CompareDescriptorNames());
1192 }
1193 
1194 // Sorts DescriptorProtos belonging to a FileDescriptorProto, by name.
SortMessages(FileDescriptorProto * file_descriptor_proto)1195 void SortMessages(FileDescriptorProto *file_descriptor_proto) {
1196   int size = file_descriptor_proto->message_type_size();
1197   // recursively sort; we can't guarantee the order of nested messages either
1198   for (int i = 0; i < size; ++i) {
1199     SortMessages(file_descriptor_proto->mutable_message_type(i));
1200   }
1201   DescriptorProto **data =
1202     file_descriptor_proto->mutable_message_type()->mutable_data();
1203   sort(data, data + size, CompareDescriptorNames());
1204 }
1205 
TEST_F(ParseDecriptorDebugTest,TestAllDescriptorTypes)1206 TEST_F(ParseDecriptorDebugTest, TestAllDescriptorTypes) {
1207   const FileDescriptor* original_file =
1208      protobuf_unittest::TestAllTypes::descriptor()->file();
1209   FileDescriptorProto expected;
1210   original_file->CopyTo(&expected);
1211 
1212   // Get the DebugString of the unittest.proto FileDecriptor, which includes
1213   // all other descriptor types
1214   string debug_string = original_file->DebugString();
1215 
1216   // Parse the debug string
1217   SetupParser(debug_string.c_str());
1218   FileDescriptorProto parsed;
1219   parser_->Parse(input_.get(), &parsed);
1220   EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
1221   ASSERT_EQ("", error_collector_.text_);
1222 
1223   // We now have a FileDescriptorProto, but to compare with the expected we
1224   // need to link to a FileDecriptor, then output back to a proto. We'll
1225   // also need to give it the same name as the original.
1226   parsed.set_name("google/protobuf/unittest.proto");
1227   // We need the imported dependency before we can build our parsed proto
1228   const FileDescriptor* import =
1229        protobuf_unittest_import::ImportMessage::descriptor()->file();
1230   FileDescriptorProto import_proto;
1231   import->CopyTo(&import_proto);
1232   ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL);
1233   const FileDescriptor* actual = pool_.BuildFile(parsed);
1234   parsed.Clear();
1235   actual->CopyTo(&parsed);
1236   ASSERT_TRUE(actual != NULL);
1237 
1238   // The messages might be in different orders, making them hard to compare.
1239   // So, sort the messages in the descriptor protos (including nested messages,
1240   // recursively).
1241   SortMessages(&expected);
1242   SortMessages(&parsed);
1243 
1244   // I really wanted to use StringDiff here for the debug output on fail,
1245   // but the strings are too long for it, and if I increase its max size,
1246   // we get a memory allocation failure :(
1247   EXPECT_EQ(expected.DebugString(), parsed.DebugString());
1248 }
1249 
1250 // ===================================================================
1251 
1252 }  // anonymous namespace
1253 
1254 }  // namespace compiler
1255 }  // namespace protobuf
1256 }  // namespace google
1257