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
52namespace google {
53namespace protobuf {
54namespace compiler {
55
56namespace {
57
58class MockErrorCollector : public io::ErrorCollector {
59 public:
60  MockErrorCollector() {}
61  ~MockErrorCollector() {}
62
63  string text_;
64
65  // implements ErrorCollector ---------------------------------------
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
72class MockValidationErrorCollector : public DescriptorPool::ErrorCollector {
73 public:
74  MockValidationErrorCollector(const SourceLocationTable& source_locations,
75                               io::ErrorCollector* wrapped_collector)
76    : source_locations_(source_locations),
77      wrapped_collector_(wrapped_collector) {}
78  ~MockValidationErrorCollector() {}
79
80  // implements ErrorCollector ---------------------------------------
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
96class ParserTest : public testing::Test {
97 protected:
98  ParserTest()
99    : require_syntax_identifier_(false) {}
100
101  // Set up the parser to parse the given 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.
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.
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.
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.
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
179TEST_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
190TEST_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
200TEST_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
211typedef ParserTest ParseMessageTest;
212
213TEST_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
225TEST_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
239TEST_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
253TEST_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
268TEST_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
284TEST_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
324TEST_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
394TEST_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
433TEST_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
447TEST_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
462TEST_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
477TEST_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
491TEST_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
507TEST_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
518TEST_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
534TEST_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
549typedef ParserTest ParseEnumTest;
550
551TEST_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
563TEST_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
579TEST_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
615typedef ParserTest ParseServiceTest;
616
617TEST_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
629TEST_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
648typedef ParserTest ParseMiscTest;
649
650TEST_F(ParseMiscTest, ParseImport) {
651  ExpectParsesTo(
652    "import \"foo/bar/baz.proto\";\n",
653    "dependency: \"foo/bar/baz.proto\"");
654}
655
656TEST_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
666TEST_F(ParseMiscTest, ParsePackage) {
667  ExpectParsesTo(
668    "package foo.bar.baz;\n",
669    "package: \"foo.bar.baz\"");
670}
671
672TEST_F(ParseMiscTest, ParsePackageWithSpaces) {
673  ExpectParsesTo(
674    "package foo   .   bar.  \n"
675    "  baz;\n",
676    "package: \"foo.bar.baz\"");
677}
678
679// ===================================================================
680// options
681
682TEST_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
707typedef ParserTest ParseErrorTest;
708
709TEST_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
717TEST_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
725TEST_F(ParseErrorTest, SimpleSyntaxError) {
726  ExpectHasErrors(
727    "message TestMessage @#$ { blah }",
728    "0:20: Expected \"{\".\n");
729  EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier());
730}
731
732TEST_F(ParseErrorTest, ExpectedTopLevel) {
733  ExpectHasErrors(
734    "blah;",
735    "0:0: Expected top-level statement (e.g. \"message\").\n");
736}
737
738TEST_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
749TEST_F(ParseErrorTest, MessageMissingName) {
750  ExpectHasErrors(
751    "message {}",
752    "0:8: Expected message name.\n");
753}
754
755TEST_F(ParseErrorTest, MessageMissingBody) {
756  ExpectHasErrors(
757    "message TestMessage;",
758    "0:19: Expected \"{\".\n");
759}
760
761TEST_F(ParseErrorTest, EofInMessage) {
762  ExpectHasErrors(
763    "message TestMessage {",
764    "0:21: Reached end of input in message definition (missing '}').\n");
765}
766
767TEST_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
775TEST_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
783TEST_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
791TEST_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
799TEST_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
807TEST_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
815TEST_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
823TEST_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
831TEST_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
839TEST_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
847TEST_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
865TEST_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
873TEST_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
881TEST_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
889TEST_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
897TEST_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
905TEST_F(ParseErrorTest, ExtendingPrimitive) {
906  ExpectHasErrors(
907    "extend int32 { optional string foo = 4; }\n",
908    "0:7: Expected message type.\n");
909}
910
911TEST_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
918TEST_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
936TEST_F(ParseErrorTest, EofInEnum) {
937  ExpectHasErrors(
938    "enum TestEnum {",
939    "0:15: Reached end of input in enum definition (missing '}').\n");
940}
941
942TEST_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
953TEST_F(ParseErrorTest, EofInService) {
954  ExpectHasErrors(
955    "service TestService {",
956    "0:21: Reached end of input in service definition (missing '}').\n");
957}
958
959TEST_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
968TEST_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
976TEST_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
984TEST_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
997TEST_F(ParseErrorTest, ImportNotQuoted) {
998  ExpectHasErrors(
999    "import foo;\n",
1000    "0:7: Expected a string naming the file to import.\n");
1001}
1002
1003TEST_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
1015typedef ParserTest ParserValidationErrorTest;
1016
1017TEST_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
1031TEST_F(ParserValidationErrorTest, MessageNameError) {
1032  ExpectHasValidationErrors(
1033    "message Foo {}\n"
1034    "message Foo {}\n",
1035    "1:8: \"Foo\" is already defined.\n");
1036}
1037
1038TEST_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
1047TEST_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
1055TEST_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
1063TEST_F(ParserValidationErrorTest, FieldExtendeeError) {
1064  ExpectHasValidationErrors(
1065    "extend Baz { optional int32 bar = 1; }\n",
1066    "0:7: \"Baz\" is not defined.\n");
1067}
1068
1069TEST_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
1078TEST_F(ParserValidationErrorTest, FileOptionNameError) {
1079  ExpectHasValidationErrors(
1080    "option foo = 5;",
1081    "0:7: Option \"foo\" unknown.\n");
1082}
1083
1084TEST_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
1091TEST_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
1099TEST_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
1108TEST_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
1116TEST_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
1123TEST_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
1132TEST_F(ParserValidationErrorTest, ServiceNameError) {
1133  ExpectHasValidationErrors(
1134    "service Foo {}\n"
1135    "service Foo {}\n",
1136    "1:8: \"Foo\" is already defined.\n");
1137}
1138
1139TEST_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
1149TEST_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
1158TEST_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
1173typedef ParserTest ParseDecriptorDebugTest;
1174
1175class CompareDescriptorNames {
1176 public:
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.
1183void 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.
1195void 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
1206TEST_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