~ubuntu-branches/ubuntu/trusty/protobuf/trusty-proposed

« back to all changes in this revision

Viewing changes to src/google/protobuf/compiler/parser_unittest.cc

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2011-05-31 14:41:47 UTC
  • mfrom: (2.2.8 sid)
  • Revision ID: james.westby@ubuntu.com-20110531144147-s41g5fozgvyo462l
Tags: 2.4.0a-2ubuntu1
* Merge with Debian; remaining changes:
  - Fix linking with -lpthread.

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
 
35
35
#include <vector>
36
36
#include <algorithm>
 
37
#include <map>
37
38
 
38
39
#include <google/protobuf/compiler/parser.h>
39
40
 
45
46
#include <google/protobuf/unittest.pb.h>
46
47
#include <google/protobuf/stubs/strutil.h>
47
48
#include <google/protobuf/stubs/substitute.h>
 
49
#include <google/protobuf/stubs/map-util.h>
48
50
 
49
51
#include <google/protobuf/testing/googletest.h>
50
52
#include <gtest/gtest.h>
118
120
    EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
119
121
    ASSERT_EQ("", error_collector_.text_);
120
122
 
 
123
    // We don't cover SourceCodeInfo in these tests.
 
124
    actual.clear_source_code_info();
 
125
 
121
126
    // Parse the ASCII representation in order to canonicalize it.  We could
122
127
    // just compare directly to actual.DebugString(), but that would require
123
128
    // that the caller precisely match the formatting that DebugString()
930
935
    "3:25: Expected \";\".\n");
931
936
}
932
937
 
 
938
TEST_F(ParseErrorTest, EofInAggregateValue) {
 
939
  ExpectHasErrors(
 
940
      "option (fileopt) = { i:100\n",
 
941
      "1:0: Unexpected end of stream while parsing aggregate value.\n");
 
942
}
 
943
 
933
944
// -------------------------------------------------------------------
934
945
// Enum errors
935
946
 
1248
1259
}
1249
1260
 
1250
1261
// ===================================================================
 
1262
// SourceCodeInfo tests.
 
1263
 
 
1264
// Follows a path -- as defined by SourceCodeInfo.Location.path -- from a
 
1265
// message to a particular sub-field.
 
1266
// * If the target is itself a message, sets *output_message to point at it,
 
1267
//   *output_field to NULL, and *output_index to -1.
 
1268
// * Otherwise, if the target is an element of a repeated field, sets
 
1269
//   *output_message to the containing message, *output_field to the descriptor
 
1270
//   of the field, and *output_index to the index of the element.
 
1271
// * Otherwise, the target is a field (possibly a repeated field, but not any
 
1272
//   one element).  Sets *output_message to the containing message,
 
1273
//   *output_field to the descriptor of the field, and *output_index to -1.
 
1274
// Returns true if the path was valid, false otherwise.  A gTest failure is
 
1275
// recorded before returning false.
 
1276
bool FollowPath(const Message& root,
 
1277
                const int* path_begin, const int* path_end,
 
1278
                const Message** output_message,
 
1279
                const FieldDescriptor** output_field,
 
1280
                int* output_index) {
 
1281
  if (path_begin == path_end) {
 
1282
    // Path refers to this whole message.
 
1283
    *output_message = &root;
 
1284
    *output_field = NULL;
 
1285
    *output_index = -1;
 
1286
    return true;
 
1287
  }
 
1288
 
 
1289
  const Descriptor* descriptor = root.GetDescriptor();
 
1290
  const Reflection* reflection = root.GetReflection();
 
1291
 
 
1292
  const FieldDescriptor* field = descriptor->FindFieldByNumber(*path_begin);
 
1293
 
 
1294
  if (field == NULL) {
 
1295
    ADD_FAILURE() << descriptor->name() << " has no field number: "
 
1296
                  << *path_begin;
 
1297
    return false;
 
1298
  }
 
1299
 
 
1300
  ++path_begin;
 
1301
 
 
1302
  if (field->is_repeated()) {
 
1303
    if (path_begin == path_end) {
 
1304
      // Path refers to the whole repeated field.
 
1305
      *output_message = &root;
 
1306
      *output_field = field;
 
1307
      *output_index = -1;
 
1308
      return true;
 
1309
    }
 
1310
 
 
1311
    int index = *path_begin++;
 
1312
    int size = reflection->FieldSize(root, field);
 
1313
 
 
1314
    if (index >= size) {
 
1315
      ADD_FAILURE() << descriptor->name() << "." << field->name()
 
1316
                    << " has size " << size << ", but path contained index: "
 
1317
                    << index;
 
1318
      return false;
 
1319
    }
 
1320
 
 
1321
    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
 
1322
      // Descend into child message.
 
1323
      const Message& child = reflection->GetRepeatedMessage(root, field, index);
 
1324
      return FollowPath(child, path_begin, path_end,
 
1325
                        output_message, output_field, output_index);
 
1326
    } else if (path_begin == path_end) {
 
1327
      // Path refers to this element.
 
1328
      *output_message = &root;
 
1329
      *output_field = field;
 
1330
      *output_index = index;
 
1331
      return true;
 
1332
    } else {
 
1333
      ADD_FAILURE() << descriptor->name() << "." << field->name()
 
1334
                    << " is not a message; cannot descend into it.";
 
1335
      return false;
 
1336
    }
 
1337
  } else {
 
1338
    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
 
1339
      const Message& child = reflection->GetMessage(root, field);
 
1340
      return FollowPath(child, path_begin, path_end,
 
1341
                        output_message, output_field, output_index);
 
1342
    } else if (path_begin == path_end) {
 
1343
      // Path refers to this field.
 
1344
      *output_message = &root;
 
1345
      *output_field = field;
 
1346
      *output_index = -1;
 
1347
      return true;
 
1348
    } else {
 
1349
      ADD_FAILURE() << descriptor->name() << "." << field->name()
 
1350
                    << " is not a message; cannot descend into it.";
 
1351
      return false;
 
1352
    }
 
1353
  }
 
1354
}
 
1355
 
 
1356
// Split some text on line breaks.  The line breaks are retained in the output,
 
1357
// so each line (except the last) ends with a '\n', and the lines can be
 
1358
// concatenated to produce the original text.
 
1359
//
 
1360
// I couldn't find the proper string utility function for this.  Our
 
1361
// split-on-delimiter functions don't include the delimiter in the output.
 
1362
void SplitLines(const string& text, vector<string>* lines) {
 
1363
  string::size_type pos = 0;
 
1364
 
 
1365
  while (pos != string::npos) {
 
1366
    string::size_type last_pos = pos;
 
1367
    pos = text.find_first_of('\n', pos);
 
1368
    if (pos != string::npos) ++pos;
 
1369
    lines->push_back(text.substr(last_pos, pos - last_pos));
 
1370
  }
 
1371
}
 
1372
 
 
1373
// Look for the given tags in the given text and construct a span (as defined
 
1374
// by SourceCodeInfo.Location.span) from them.  E.g. for text like:
 
1375
//   /*a*/message /*b*/Foo/*c*/ {}/*d*/
 
1376
// There are four tags:  "a", "b", "c", and "d".  The constructed span starts
 
1377
// immediately after the start tag's trailing '/' and ends immediately before
 
1378
// the end tags leading '/'.
 
1379
void MakeExpectedSpan(const vector<string>& lines,
 
1380
                      const string& start_tag, const string& end_tag,
 
1381
                      RepeatedField<int>* output) {
 
1382
  string start_comment = "/*" + start_tag + "*/";
 
1383
  string end_comment = "/*" + end_tag + "*/";
 
1384
 
 
1385
  int start_line = -1;
 
1386
  int start_column = -1;
 
1387
  for (int i = 0; i < lines.size(); i++) {
 
1388
    string::size_type pos = lines[i].find(start_comment);
 
1389
    if (pos != string::npos) {
 
1390
      start_line = i;
 
1391
      start_column = pos + start_comment.size();
 
1392
      break;
 
1393
    }
 
1394
  }
 
1395
  ASSERT_NE(start_line, -1)
 
1396
      << "Tag \"" << start_comment << "\" not found in text.";
 
1397
 
 
1398
  int end_line = -1;
 
1399
  int end_column = -1;
 
1400
  for (int i = start_line; i < lines.size(); i++) {
 
1401
    string::size_type pos = lines[i].find(end_comment);
 
1402
    if (pos != string::npos) {
 
1403
      end_line = i;
 
1404
      end_column = pos;
 
1405
      break;
 
1406
    }
 
1407
  }
 
1408
  ASSERT_NE(end_line, -1)
 
1409
      << "Tag \"" << end_comment << "\" not found in text.";
 
1410
 
 
1411
  output->Add(start_line);
 
1412
  output->Add(start_column);
 
1413
  if (end_line != start_line) output->Add(end_line);
 
1414
  output->Add(end_column);
 
1415
}
 
1416
 
 
1417
// Check if two spans are equal.
 
1418
bool CompareSpans(const RepeatedField<int>& span1,
 
1419
                  const RepeatedField<int>& span2) {
 
1420
  if (span1.size() != span2.size()) return false;
 
1421
  for (int i = 0; i < span1.size(); i++) {
 
1422
    if (span1.Get(i) != span2.Get(i)) return false;
 
1423
  }
 
1424
  return true;
 
1425
}
 
1426
 
 
1427
// Test fixture for source info tests, which check that source locations are
 
1428
// recorded correctly in FileDescriptorProto.source_code_info.location.
 
1429
class SourceInfoTest : public ParserTest {
 
1430
 protected:
 
1431
  // The parsed file (initialized by Parse()).
 
1432
  FileDescriptorProto file_;
 
1433
 
 
1434
  // Parse the given text as a .proto file and populate the spans_ map with
 
1435
  // all the source location spans in its SourceCodeInfo table.
 
1436
  bool Parse(const char* text) {
 
1437
    SetupParser(text);
 
1438
    SplitLines(text, &lines_);
 
1439
    if (!parser_->Parse(input_.get(), &file_)) {
 
1440
      return false;
 
1441
    }
 
1442
 
 
1443
    const SourceCodeInfo& source_info = file_.source_code_info();
 
1444
    for (int i = 0; i < source_info.location_size(); i++) {
 
1445
      const SourceCodeInfo::Location& location = source_info.location(i);
 
1446
      const Message* descriptor_proto = NULL;
 
1447
      const FieldDescriptor* field = NULL;
 
1448
      int index = 0;
 
1449
      if (!FollowPath(file_, location.path().begin(), location.path().end(),
 
1450
                      &descriptor_proto, &field, &index)) {
 
1451
        return false;
 
1452
      }
 
1453
 
 
1454
      spans_.insert(make_pair(SpanKey(*descriptor_proto, field, index),
 
1455
                              &location));
 
1456
    }
 
1457
 
 
1458
    return true;
 
1459
  }
 
1460
 
 
1461
  virtual void TearDown() {
 
1462
    EXPECT_TRUE(spans_.empty())
 
1463
        << "Forgot to call HasSpan() for:\n"
 
1464
        << spans_.begin()->second->DebugString();
 
1465
  }
 
1466
 
 
1467
  // -----------------------------------------------------------------
 
1468
  // HasSpan() checks that the span of source code delimited by the given
 
1469
  // tags (comments) correspond via the SourceCodeInfo table to the given
 
1470
  // part of the FileDescriptorProto.  (If unclear, look at the actual tests;
 
1471
  // it should quickly become obvious.)
 
1472
 
 
1473
  bool HasSpan(const char* start_tag, const char* end_tag,
 
1474
               const Message& descriptor_proto) {
 
1475
    return HasSpan(start_tag, end_tag, descriptor_proto, NULL, -1);
 
1476
  }
 
1477
 
 
1478
  bool HasSpan(const char* start_tag, const char* end_tag,
 
1479
               const Message& descriptor_proto, const string& field_name) {
 
1480
    return HasSpan(start_tag, end_tag, descriptor_proto, field_name, -1);
 
1481
  }
 
1482
 
 
1483
  bool HasSpan(const char* start_tag, const char* end_tag,
 
1484
               const Message& descriptor_proto, const string& field_name,
 
1485
               int index) {
 
1486
    const FieldDescriptor* field =
 
1487
        descriptor_proto.GetDescriptor()->FindFieldByName(field_name);
 
1488
    if (field == NULL) {
 
1489
      ADD_FAILURE() << descriptor_proto.GetDescriptor()->name()
 
1490
                    << " has no such field: " << field_name;
 
1491
      return false;
 
1492
    }
 
1493
 
 
1494
    return HasSpan(start_tag, end_tag, descriptor_proto, field, index);
 
1495
  }
 
1496
 
 
1497
  bool HasSpan(const Message& descriptor_proto) {
 
1498
    return HasSpan(NULL, NULL, descriptor_proto, NULL, -1);
 
1499
  }
 
1500
 
 
1501
  bool HasSpan(const Message& descriptor_proto, const string& field_name) {
 
1502
    return HasSpan(NULL, NULL, descriptor_proto, field_name, -1);
 
1503
  }
 
1504
 
 
1505
  bool HasSpan(const Message& descriptor_proto, const string& field_name,
 
1506
               int index) {
 
1507
    return HasSpan(NULL, NULL, descriptor_proto, field_name, index);
 
1508
  }
 
1509
 
 
1510
  bool HasSpan(const char* start_tag, const char* end_tag,
 
1511
               const Message& descriptor_proto, const FieldDescriptor* field,
 
1512
               int index) {
 
1513
    pair<SpanMap::iterator, SpanMap::iterator> range =
 
1514
        spans_.equal_range(SpanKey(descriptor_proto, field, index));
 
1515
 
 
1516
    if (start_tag == NULL) {
 
1517
      if (range.first == range.second) {
 
1518
        return false;
 
1519
      } else {
 
1520
        spans_.erase(range.first);
 
1521
        return true;
 
1522
      }
 
1523
    } else {
 
1524
      RepeatedField<int> expected_span;
 
1525
      MakeExpectedSpan(lines_, start_tag, end_tag, &expected_span);
 
1526
 
 
1527
      for (SpanMap::iterator iter = range.first; iter != range.second; ++iter) {
 
1528
        if (CompareSpans(expected_span, iter->second->span())) {
 
1529
          spans_.erase(iter);
 
1530
          return true;
 
1531
        }
 
1532
      }
 
1533
 
 
1534
      return false;
 
1535
    }
 
1536
  }
 
1537
 
 
1538
 private:
 
1539
  struct SpanKey {
 
1540
    const Message* descriptor_proto;
 
1541
    const FieldDescriptor* field;
 
1542
    int index;
 
1543
 
 
1544
    inline SpanKey() {}
 
1545
    inline SpanKey(const Message& descriptor_proto,
 
1546
                   const FieldDescriptor* field,
 
1547
                   int index)
 
1548
        : descriptor_proto(&descriptor_proto), field(field), index(index) {}
 
1549
 
 
1550
    inline bool operator<(const SpanKey& other) const {
 
1551
      if (descriptor_proto < other.descriptor_proto) return true;
 
1552
      if (descriptor_proto > other.descriptor_proto) return false;
 
1553
      if (field < other.field) return true;
 
1554
      if (field > other.field) return false;
 
1555
      return index < other.index;
 
1556
    }
 
1557
  };
 
1558
 
 
1559
  typedef multimap<SpanKey, const SourceCodeInfo::Location*> SpanMap;
 
1560
  SpanMap spans_;
 
1561
  vector<string> lines_;
 
1562
};
 
1563
 
 
1564
TEST_F(SourceInfoTest, BasicFileDecls) {
 
1565
  EXPECT_TRUE(Parse(
 
1566
      "/*a*/syntax = \"proto2\";\n"
 
1567
      "package /*b*/foo.bar/*c*/;\n"
 
1568
      "import /*d*/\"baz.proto\"/*e*/;\n"
 
1569
      "import /*f*/\"qux.proto\"/*g*/;/*h*/\n"
 
1570
      "// comment ignored\n"));
 
1571
 
 
1572
  EXPECT_TRUE(HasSpan("a", "h", file_));
 
1573
  EXPECT_TRUE(HasSpan("b", "c", file_, "package"));
 
1574
  EXPECT_TRUE(HasSpan("d", "e", file_, "dependency", 0));
 
1575
  EXPECT_TRUE(HasSpan("f", "g", file_, "dependency", 1));
 
1576
}
 
1577
 
 
1578
TEST_F(SourceInfoTest, Messages) {
 
1579
  EXPECT_TRUE(Parse(
 
1580
      "/*a*/message /*b*/Foo/*c*/ {}/*d*/\n"
 
1581
      "/*e*/message /*f*/Bar/*g*/ {}/*h*/\n"));
 
1582
 
 
1583
  EXPECT_TRUE(HasSpan("a", "d", file_.message_type(0)));
 
1584
  EXPECT_TRUE(HasSpan("b", "c", file_.message_type(0), "name"));
 
1585
  EXPECT_TRUE(HasSpan("e", "h", file_.message_type(1)));
 
1586
  EXPECT_TRUE(HasSpan("f", "g", file_.message_type(1), "name"));
 
1587
 
 
1588
  // Ignore these.
 
1589
  EXPECT_TRUE(HasSpan(file_));
 
1590
}
 
1591
 
 
1592
TEST_F(SourceInfoTest, Fields) {
 
1593
  EXPECT_TRUE(Parse(
 
1594
      "message Foo {\n"
 
1595
      "  /*a*/optional/*b*/ /*c*/int32/*d*/ /*e*/bar/*f*/ = /*g*/1/*h*/;/*i*/\n"
 
1596
      "  /*j*/repeated/*k*/ /*l*/X.Y/*m*/ /*n*/baz/*o*/ = /*p*/2/*q*/;/*r*/\n"
 
1597
      "}\n"));
 
1598
 
 
1599
  const FieldDescriptorProto& field1 = file_.message_type(0).field(0);
 
1600
  const FieldDescriptorProto& field2 = file_.message_type(0).field(1);
 
1601
 
 
1602
  EXPECT_TRUE(HasSpan("a", "i", field1));
 
1603
  EXPECT_TRUE(HasSpan("a", "b", field1, "label"));
 
1604
  EXPECT_TRUE(HasSpan("c", "d", field1, "type"));
 
1605
  EXPECT_TRUE(HasSpan("e", "f", field1, "name"));
 
1606
  EXPECT_TRUE(HasSpan("g", "h", field1, "number"));
 
1607
 
 
1608
  EXPECT_TRUE(HasSpan("j", "r", field2));
 
1609
  EXPECT_TRUE(HasSpan("j", "k", field2, "label"));
 
1610
  EXPECT_TRUE(HasSpan("l", "m", field2, "type_name"));
 
1611
  EXPECT_TRUE(HasSpan("n", "o", field2, "name"));
 
1612
  EXPECT_TRUE(HasSpan("p", "q", field2, "number"));
 
1613
 
 
1614
  // Ignore these.
 
1615
  EXPECT_TRUE(HasSpan(file_));
 
1616
  EXPECT_TRUE(HasSpan(file_.message_type(0)));
 
1617
  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
 
1618
}
 
1619
 
 
1620
TEST_F(SourceInfoTest, Extensions) {
 
1621
  EXPECT_TRUE(Parse(
 
1622
      "/*a*/extend /*b*/Foo/*c*/ {\n"
 
1623
      "  /*d*/optional/*e*/ int32 bar = 1;/*f*/\n"
 
1624
      "  /*g*/repeated/*h*/ X.Y baz = 2;/*i*/\n"
 
1625
      "}/*j*/\n"
 
1626
      "/*k*/extend /*l*/Bar/*m*/ {\n"
 
1627
      "  /*n*/optional int32 qux = 1;/*o*/\n"
 
1628
      "}/*p*/\n"));
 
1629
 
 
1630
  const FieldDescriptorProto& field1 = file_.extension(0);
 
1631
  const FieldDescriptorProto& field2 = file_.extension(1);
 
1632
  const FieldDescriptorProto& field3 = file_.extension(2);
 
1633
 
 
1634
  EXPECT_TRUE(HasSpan("a", "j", file_, "extension"));
 
1635
  EXPECT_TRUE(HasSpan("k", "p", file_, "extension"));
 
1636
 
 
1637
  EXPECT_TRUE(HasSpan("d", "f", field1));
 
1638
  EXPECT_TRUE(HasSpan("d", "e", field1, "label"));
 
1639
  EXPECT_TRUE(HasSpan("b", "c", field1, "extendee"));
 
1640
 
 
1641
  EXPECT_TRUE(HasSpan("g", "i", field2));
 
1642
  EXPECT_TRUE(HasSpan("g", "h", field2, "label"));
 
1643
  EXPECT_TRUE(HasSpan("b", "c", field2, "extendee"));
 
1644
 
 
1645
  EXPECT_TRUE(HasSpan("n", "o", field3));
 
1646
  EXPECT_TRUE(HasSpan("l", "m", field3, "extendee"));
 
1647
 
 
1648
  // Ignore these.
 
1649
  EXPECT_TRUE(HasSpan(file_));
 
1650
  EXPECT_TRUE(HasSpan(field1, "type"));
 
1651
  EXPECT_TRUE(HasSpan(field1, "name"));
 
1652
  EXPECT_TRUE(HasSpan(field1, "number"));
 
1653
  EXPECT_TRUE(HasSpan(field2, "type_name"));
 
1654
  EXPECT_TRUE(HasSpan(field2, "name"));
 
1655
  EXPECT_TRUE(HasSpan(field2, "number"));
 
1656
  EXPECT_TRUE(HasSpan(field3, "label"));
 
1657
  EXPECT_TRUE(HasSpan(field3, "type"));
 
1658
  EXPECT_TRUE(HasSpan(field3, "name"));
 
1659
  EXPECT_TRUE(HasSpan(field3, "number"));
 
1660
}
 
1661
 
 
1662
TEST_F(SourceInfoTest, NestedExtensions) {
 
1663
  EXPECT_TRUE(Parse(
 
1664
      "message Message {\n"
 
1665
      "  /*a*/extend /*b*/Foo/*c*/ {\n"
 
1666
      "    /*d*/optional/*e*/ int32 bar = 1;/*f*/\n"
 
1667
      "    /*g*/repeated/*h*/ X.Y baz = 2;/*i*/\n"
 
1668
      "  }/*j*/\n"
 
1669
      "  /*k*/extend /*l*/Bar/*m*/ {\n"
 
1670
      "    /*n*/optional int32 qux = 1;/*o*/\n"
 
1671
      "  }/*p*/\n"
 
1672
      "}\n"));
 
1673
 
 
1674
  const FieldDescriptorProto& field1 = file_.message_type(0).extension(0);
 
1675
  const FieldDescriptorProto& field2 = file_.message_type(0).extension(1);
 
1676
  const FieldDescriptorProto& field3 = file_.message_type(0).extension(2);
 
1677
 
 
1678
  EXPECT_TRUE(HasSpan("a", "j", file_.message_type(0), "extension"));
 
1679
  EXPECT_TRUE(HasSpan("k", "p", file_.message_type(0), "extension"));
 
1680
 
 
1681
  EXPECT_TRUE(HasSpan("d", "f", field1));
 
1682
  EXPECT_TRUE(HasSpan("d", "e", field1, "label"));
 
1683
  EXPECT_TRUE(HasSpan("b", "c", field1, "extendee"));
 
1684
 
 
1685
  EXPECT_TRUE(HasSpan("g", "i", field2));
 
1686
  EXPECT_TRUE(HasSpan("g", "h", field2, "label"));
 
1687
  EXPECT_TRUE(HasSpan("b", "c", field2, "extendee"));
 
1688
 
 
1689
  EXPECT_TRUE(HasSpan("n", "o", field3));
 
1690
  EXPECT_TRUE(HasSpan("l", "m", field3, "extendee"));
 
1691
 
 
1692
  // Ignore these.
 
1693
  EXPECT_TRUE(HasSpan(file_));
 
1694
  EXPECT_TRUE(HasSpan(file_.message_type(0)));
 
1695
  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
 
1696
  EXPECT_TRUE(HasSpan(field1, "type"));
 
1697
  EXPECT_TRUE(HasSpan(field1, "name"));
 
1698
  EXPECT_TRUE(HasSpan(field1, "number"));
 
1699
  EXPECT_TRUE(HasSpan(field2, "type_name"));
 
1700
  EXPECT_TRUE(HasSpan(field2, "name"));
 
1701
  EXPECT_TRUE(HasSpan(field2, "number"));
 
1702
  EXPECT_TRUE(HasSpan(field3, "label"));
 
1703
  EXPECT_TRUE(HasSpan(field3, "type"));
 
1704
  EXPECT_TRUE(HasSpan(field3, "name"));
 
1705
  EXPECT_TRUE(HasSpan(field3, "number"));
 
1706
}
 
1707
 
 
1708
TEST_F(SourceInfoTest, ExtensionRanges) {
 
1709
  EXPECT_TRUE(Parse(
 
1710
      "message Message {\n"
 
1711
      "  /*a*/extensions /*b*/1/*c*/ to /*d*/4/*e*/, /*f*/6/*g*/;/*h*/\n"
 
1712
      "  /*i*/extensions /*j*/8/*k*/ to /*l*/max/*m*/;/*n*/\n"
 
1713
      "}\n"));
 
1714
 
 
1715
  const DescriptorProto::ExtensionRange& range1 =
 
1716
      file_.message_type(0).extension_range(0);
 
1717
  const DescriptorProto::ExtensionRange& range2 =
 
1718
      file_.message_type(0).extension_range(1);
 
1719
  const DescriptorProto::ExtensionRange& range3 =
 
1720
      file_.message_type(0).extension_range(2);
 
1721
 
 
1722
  EXPECT_TRUE(HasSpan("a", "h", file_.message_type(0), "extension_range"));
 
1723
  EXPECT_TRUE(HasSpan("i", "n", file_.message_type(0), "extension_range"));
 
1724
 
 
1725
  EXPECT_TRUE(HasSpan("b", "e", range1));
 
1726
  EXPECT_TRUE(HasSpan("b", "c", range1, "start"));
 
1727
  EXPECT_TRUE(HasSpan("d", "e", range1, "end"));
 
1728
 
 
1729
  EXPECT_TRUE(HasSpan("f", "g", range2));
 
1730
  EXPECT_TRUE(HasSpan("f", "g", range2, "start"));
 
1731
  EXPECT_TRUE(HasSpan("f", "g", range2, "end"));
 
1732
 
 
1733
  EXPECT_TRUE(HasSpan("j", "m", range3));
 
1734
  EXPECT_TRUE(HasSpan("j", "k", range3, "start"));
 
1735
  EXPECT_TRUE(HasSpan("l", "m", range3, "end"));
 
1736
 
 
1737
  // Ignore these.
 
1738
  EXPECT_TRUE(HasSpan(file_));
 
1739
  EXPECT_TRUE(HasSpan(file_.message_type(0)));
 
1740
  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
 
1741
}
 
1742
 
 
1743
TEST_F(SourceInfoTest, NestedMessages) {
 
1744
  EXPECT_TRUE(Parse(
 
1745
      "message Foo {\n"
 
1746
      "  /*a*/message /*b*/Bar/*c*/ {\n"
 
1747
      "    /*d*/message /*e*/Baz/*f*/ {}/*g*/\n"
 
1748
      "  }/*h*/\n"
 
1749
      "  /*i*/message /*j*/Qux/*k*/ {}/*l*/\n"
 
1750
      "}\n"));
 
1751
 
 
1752
  const DescriptorProto& bar = file_.message_type(0).nested_type(0);
 
1753
  const DescriptorProto& baz = bar.nested_type(0);
 
1754
  const DescriptorProto& qux = file_.message_type(0).nested_type(1);
 
1755
 
 
1756
  EXPECT_TRUE(HasSpan("a", "h", bar));
 
1757
  EXPECT_TRUE(HasSpan("b", "c", bar, "name"));
 
1758
  EXPECT_TRUE(HasSpan("d", "g", baz));
 
1759
  EXPECT_TRUE(HasSpan("e", "f", baz, "name"));
 
1760
  EXPECT_TRUE(HasSpan("i", "l", qux));
 
1761
  EXPECT_TRUE(HasSpan("j", "k", qux, "name"));
 
1762
 
 
1763
  // Ignore these.
 
1764
  EXPECT_TRUE(HasSpan(file_));
 
1765
  EXPECT_TRUE(HasSpan(file_.message_type(0)));
 
1766
  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
 
1767
}
 
1768
 
 
1769
TEST_F(SourceInfoTest, Groups) {
 
1770
  EXPECT_TRUE(Parse(
 
1771
      "message Foo {\n"
 
1772
      "  message Bar {}\n"
 
1773
      "  /*a*/optional/*b*/ /*c*/group/*d*/ /*e*/Baz/*f*/ = /*g*/1/*h*/ {\n"
 
1774
      "    /*i*/message Qux {}/*j*/\n"
 
1775
      "  }/*k*/\n"
 
1776
      "}\n"));
 
1777
 
 
1778
  const DescriptorProto& bar = file_.message_type(0).nested_type(0);
 
1779
  const DescriptorProto& baz = file_.message_type(0).nested_type(1);
 
1780
  const DescriptorProto& qux = baz.nested_type(0);
 
1781
  const FieldDescriptorProto& field = file_.message_type(0).field(0);
 
1782
 
 
1783
  EXPECT_TRUE(HasSpan("a", "k", field));
 
1784
  EXPECT_TRUE(HasSpan("a", "b", field, "label"));
 
1785
  EXPECT_TRUE(HasSpan("c", "d", field, "type"));
 
1786
  EXPECT_TRUE(HasSpan("e", "f", field, "name"));
 
1787
  EXPECT_TRUE(HasSpan("e", "f", field, "type_name"));
 
1788
  EXPECT_TRUE(HasSpan("g", "h", field, "number"));
 
1789
 
 
1790
  EXPECT_TRUE(HasSpan("a", "k", baz));
 
1791
  EXPECT_TRUE(HasSpan("e", "f", baz, "name"));
 
1792
  EXPECT_TRUE(HasSpan("i", "j", qux));
 
1793
 
 
1794
  // Ignore these.
 
1795
  EXPECT_TRUE(HasSpan(file_));
 
1796
  EXPECT_TRUE(HasSpan(file_.message_type(0)));
 
1797
  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
 
1798
  EXPECT_TRUE(HasSpan(bar));
 
1799
  EXPECT_TRUE(HasSpan(bar, "name"));
 
1800
  EXPECT_TRUE(HasSpan(qux, "name"));
 
1801
}
 
1802
 
 
1803
TEST_F(SourceInfoTest, Enums) {
 
1804
  EXPECT_TRUE(Parse(
 
1805
      "/*a*/enum /*b*/Foo/*c*/ {}/*d*/\n"
 
1806
      "/*e*/enum /*f*/Bar/*g*/ {}/*h*/\n"));
 
1807
 
 
1808
  EXPECT_TRUE(HasSpan("a", "d", file_.enum_type(0)));
 
1809
  EXPECT_TRUE(HasSpan("b", "c", file_.enum_type(0), "name"));
 
1810
  EXPECT_TRUE(HasSpan("e", "h", file_.enum_type(1)));
 
1811
  EXPECT_TRUE(HasSpan("f", "g", file_.enum_type(1), "name"));
 
1812
 
 
1813
  // Ignore these.
 
1814
  EXPECT_TRUE(HasSpan(file_));
 
1815
}
 
1816
 
 
1817
TEST_F(SourceInfoTest, EnumValues) {
 
1818
  EXPECT_TRUE(Parse(
 
1819
      "enum Foo {\n"
 
1820
      "  /*a*/BAR/*b*/ = /*c*/1/*d*/;/*e*/\n"
 
1821
      "  /*f*/BAZ/*g*/ = /*h*/2/*i*/;/*j*/\n"
 
1822
      "}"));
 
1823
 
 
1824
  const EnumValueDescriptorProto& bar = file_.enum_type(0).value(0);
 
1825
  const EnumValueDescriptorProto& baz = file_.enum_type(0).value(1);
 
1826
 
 
1827
  EXPECT_TRUE(HasSpan("a", "e", bar));
 
1828
  EXPECT_TRUE(HasSpan("a", "b", bar, "name"));
 
1829
  EXPECT_TRUE(HasSpan("c", "d", bar, "number"));
 
1830
  EXPECT_TRUE(HasSpan("f", "j", baz));
 
1831
  EXPECT_TRUE(HasSpan("f", "g", baz, "name"));
 
1832
  EXPECT_TRUE(HasSpan("h", "i", baz, "number"));
 
1833
 
 
1834
  // Ignore these.
 
1835
  EXPECT_TRUE(HasSpan(file_));
 
1836
  EXPECT_TRUE(HasSpan(file_.enum_type(0)));
 
1837
  EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
 
1838
}
 
1839
 
 
1840
TEST_F(SourceInfoTest, NestedEnums) {
 
1841
  EXPECT_TRUE(Parse(
 
1842
      "message Foo {\n"
 
1843
      "  /*a*/enum /*b*/Bar/*c*/ {}/*d*/\n"
 
1844
      "  /*e*/enum /*f*/Baz/*g*/ {}/*h*/\n"
 
1845
      "}\n"));
 
1846
 
 
1847
  const EnumDescriptorProto& bar = file_.message_type(0).enum_type(0);
 
1848
  const EnumDescriptorProto& baz = file_.message_type(0).enum_type(1);
 
1849
 
 
1850
  EXPECT_TRUE(HasSpan("a", "d", bar));
 
1851
  EXPECT_TRUE(HasSpan("b", "c", bar, "name"));
 
1852
  EXPECT_TRUE(HasSpan("e", "h", baz));
 
1853
  EXPECT_TRUE(HasSpan("f", "g", baz, "name"));
 
1854
 
 
1855
  // Ignore these.
 
1856
  EXPECT_TRUE(HasSpan(file_));
 
1857
  EXPECT_TRUE(HasSpan(file_.message_type(0)));
 
1858
  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
 
1859
}
 
1860
 
 
1861
TEST_F(SourceInfoTest, Services) {
 
1862
  EXPECT_TRUE(Parse(
 
1863
      "/*a*/service /*b*/Foo/*c*/ {}/*d*/\n"
 
1864
      "/*e*/service /*f*/Bar/*g*/ {}/*h*/\n"));
 
1865
 
 
1866
  EXPECT_TRUE(HasSpan("a", "d", file_.service(0)));
 
1867
  EXPECT_TRUE(HasSpan("b", "c", file_.service(0), "name"));
 
1868
  EXPECT_TRUE(HasSpan("e", "h", file_.service(1)));
 
1869
  EXPECT_TRUE(HasSpan("f", "g", file_.service(1), "name"));
 
1870
 
 
1871
  // Ignore these.
 
1872
  EXPECT_TRUE(HasSpan(file_));
 
1873
}
 
1874
 
 
1875
TEST_F(SourceInfoTest, Methods) {
 
1876
  EXPECT_TRUE(Parse(
 
1877
      "service Foo {\n"
 
1878
      "  /*a*/rpc /*b*/Bar/*c*/(/*d*/X/*e*/) returns(/*f*/Y/*g*/);/*h*/"
 
1879
      "  /*i*/rpc /*j*/Baz/*k*/(/*l*/Z/*m*/) returns(/*n*/W/*o*/);/*p*/"
 
1880
      "}"));
 
1881
 
 
1882
  const MethodDescriptorProto& bar = file_.service(0).method(0);
 
1883
  const MethodDescriptorProto& baz = file_.service(0).method(1);
 
1884
 
 
1885
  EXPECT_TRUE(HasSpan("a", "h", bar));
 
1886
  EXPECT_TRUE(HasSpan("b", "c", bar, "name"));
 
1887
  EXPECT_TRUE(HasSpan("d", "e", bar, "input_type"));
 
1888
  EXPECT_TRUE(HasSpan("f", "g", bar, "output_type"));
 
1889
 
 
1890
  EXPECT_TRUE(HasSpan("i", "p", baz));
 
1891
  EXPECT_TRUE(HasSpan("j", "k", baz, "name"));
 
1892
  EXPECT_TRUE(HasSpan("l", "m", baz, "input_type"));
 
1893
  EXPECT_TRUE(HasSpan("n", "o", baz, "output_type"));
 
1894
 
 
1895
  // Ignore these.
 
1896
  EXPECT_TRUE(HasSpan(file_));
 
1897
  EXPECT_TRUE(HasSpan(file_.service(0)));
 
1898
  EXPECT_TRUE(HasSpan(file_.service(0), "name"));
 
1899
}
 
1900
 
 
1901
TEST_F(SourceInfoTest, Options) {
 
1902
  EXPECT_TRUE(Parse(
 
1903
      "/*a*/option /*b*/foo/*c*/./*d*/(/*e*/bar.baz/*f*/)/*g*/ = "
 
1904
          "/*h*/123/*i*/;/*j*/\n"
 
1905
      "/*k*/option qux = /*l*/-123/*m*/;/*n*/\n"
 
1906
      "/*o*/option corge = /*p*/abc/*q*/;/*r*/\n"
 
1907
      "/*s*/option grault = /*t*/'blah'/*u*/;/*v*/\n"
 
1908
      "/*w*/option garply = /*x*/{ yadda yadda }/*y*/;/*z*/\n"
 
1909
      "/*0*/option waldo = /*1*/123.0/*2*/;/*3*/\n"
 
1910
  ));
 
1911
 
 
1912
  const UninterpretedOption& option1 = file_.options().uninterpreted_option(0);
 
1913
  const UninterpretedOption& option2 = file_.options().uninterpreted_option(1);
 
1914
  const UninterpretedOption& option3 = file_.options().uninterpreted_option(2);
 
1915
  const UninterpretedOption& option4 = file_.options().uninterpreted_option(3);
 
1916
  const UninterpretedOption& option5 = file_.options().uninterpreted_option(4);
 
1917
  const UninterpretedOption& option6 = file_.options().uninterpreted_option(5);
 
1918
 
 
1919
  EXPECT_TRUE(HasSpan("a", "j", file_.options()));
 
1920
  EXPECT_TRUE(HasSpan("b", "i", option1));
 
1921
  EXPECT_TRUE(HasSpan("b", "g", option1, "name"));
 
1922
  EXPECT_TRUE(HasSpan("b", "c", option1.name(0)));
 
1923
  EXPECT_TRUE(HasSpan("b", "c", option1.name(0), "name_part"));
 
1924
  EXPECT_TRUE(HasSpan("d", "g", option1.name(1)));
 
1925
  EXPECT_TRUE(HasSpan("e", "f", option1.name(1), "name_part"));
 
1926
  EXPECT_TRUE(HasSpan("h", "i", option1, "positive_int_value"));
 
1927
 
 
1928
  EXPECT_TRUE(HasSpan("k", "n", file_.options()));
 
1929
  EXPECT_TRUE(HasSpan("l", "m", option2, "negative_int_value"));
 
1930
 
 
1931
  EXPECT_TRUE(HasSpan("o", "r", file_.options()));
 
1932
  EXPECT_TRUE(HasSpan("p", "q", option3, "identifier_value"));
 
1933
 
 
1934
  EXPECT_TRUE(HasSpan("s", "v", file_.options()));
 
1935
  EXPECT_TRUE(HasSpan("t", "u", option4, "string_value"));
 
1936
 
 
1937
  EXPECT_TRUE(HasSpan("w", "z", file_.options()));
 
1938
  EXPECT_TRUE(HasSpan("x", "y", option5, "aggregate_value"));
 
1939
 
 
1940
  EXPECT_TRUE(HasSpan("0", "3", file_.options()));
 
1941
  EXPECT_TRUE(HasSpan("1", "2", option6, "double_value"));
 
1942
 
 
1943
  // Ignore these.
 
1944
  EXPECT_TRUE(HasSpan(file_));
 
1945
  EXPECT_TRUE(HasSpan(option2));
 
1946
  EXPECT_TRUE(HasSpan(option3));
 
1947
  EXPECT_TRUE(HasSpan(option4));
 
1948
  EXPECT_TRUE(HasSpan(option5));
 
1949
  EXPECT_TRUE(HasSpan(option6));
 
1950
  EXPECT_TRUE(HasSpan(option2, "name"));
 
1951
  EXPECT_TRUE(HasSpan(option3, "name"));
 
1952
  EXPECT_TRUE(HasSpan(option4, "name"));
 
1953
  EXPECT_TRUE(HasSpan(option5, "name"));
 
1954
  EXPECT_TRUE(HasSpan(option6, "name"));
 
1955
  EXPECT_TRUE(HasSpan(option2.name(0)));
 
1956
  EXPECT_TRUE(HasSpan(option3.name(0)));
 
1957
  EXPECT_TRUE(HasSpan(option4.name(0)));
 
1958
  EXPECT_TRUE(HasSpan(option5.name(0)));
 
1959
  EXPECT_TRUE(HasSpan(option6.name(0)));
 
1960
  EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
 
1961
  EXPECT_TRUE(HasSpan(option3.name(0), "name_part"));
 
1962
  EXPECT_TRUE(HasSpan(option4.name(0), "name_part"));
 
1963
  EXPECT_TRUE(HasSpan(option5.name(0), "name_part"));
 
1964
  EXPECT_TRUE(HasSpan(option6.name(0), "name_part"));
 
1965
}
 
1966
 
 
1967
TEST_F(SourceInfoTest, ScopedOptions) {
 
1968
  EXPECT_TRUE(Parse(
 
1969
    "message Foo {\n"
 
1970
    "  /*a*/option mopt = 1;/*b*/\n"
 
1971
    "}\n"
 
1972
    "enum Bar {\n"
 
1973
    "  /*c*/option eopt = 1;/*d*/\n"
 
1974
    "}\n"
 
1975
    "service Baz {\n"
 
1976
    "  /*e*/option sopt = 1;/*f*/\n"
 
1977
    "  rpc M(X) returns(Y) {\n"
 
1978
    "    /*g*/option mopt = 1;/*h*/\n"
 
1979
    "  }\n"
 
1980
    "}\n"));
 
1981
 
 
1982
  EXPECT_TRUE(HasSpan("a", "b", file_.message_type(0).options()));
 
1983
  EXPECT_TRUE(HasSpan("c", "d", file_.enum_type(0).options()));
 
1984
  EXPECT_TRUE(HasSpan("e", "f", file_.service(0).options()));
 
1985
  EXPECT_TRUE(HasSpan("g", "h", file_.service(0).method(0).options()));
 
1986
 
 
1987
  // Ignore these.
 
1988
  EXPECT_TRUE(HasSpan(file_));
 
1989
  EXPECT_TRUE(HasSpan(file_.message_type(0)));
 
1990
  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
 
1991
  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
 
1992
                      .uninterpreted_option(0)));
 
1993
  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
 
1994
                      .uninterpreted_option(0), "name"));
 
1995
  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
 
1996
                      .uninterpreted_option(0).name(0)));
 
1997
  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
 
1998
                      .uninterpreted_option(0).name(0), "name_part"));
 
1999
  EXPECT_TRUE(HasSpan(file_.message_type(0).options()
 
2000
                      .uninterpreted_option(0), "positive_int_value"));
 
2001
  EXPECT_TRUE(HasSpan(file_.enum_type(0)));
 
2002
  EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
 
2003
  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
 
2004
                      .uninterpreted_option(0)));
 
2005
  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
 
2006
                      .uninterpreted_option(0), "name"));
 
2007
  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
 
2008
                      .uninterpreted_option(0).name(0)));
 
2009
  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
 
2010
                      .uninterpreted_option(0).name(0), "name_part"));
 
2011
  EXPECT_TRUE(HasSpan(file_.enum_type(0).options()
 
2012
                      .uninterpreted_option(0), "positive_int_value"));
 
2013
  EXPECT_TRUE(HasSpan(file_.service(0)));
 
2014
  EXPECT_TRUE(HasSpan(file_.service(0), "name"));
 
2015
  EXPECT_TRUE(HasSpan(file_.service(0).method(0)));
 
2016
  EXPECT_TRUE(HasSpan(file_.service(0).options()
 
2017
                      .uninterpreted_option(0)));
 
2018
  EXPECT_TRUE(HasSpan(file_.service(0).options()
 
2019
                      .uninterpreted_option(0), "name"));
 
2020
  EXPECT_TRUE(HasSpan(file_.service(0).options()
 
2021
                      .uninterpreted_option(0).name(0)));
 
2022
  EXPECT_TRUE(HasSpan(file_.service(0).options()
 
2023
                      .uninterpreted_option(0).name(0), "name_part"));
 
2024
  EXPECT_TRUE(HasSpan(file_.service(0).options()
 
2025
                      .uninterpreted_option(0), "positive_int_value"));
 
2026
  EXPECT_TRUE(HasSpan(file_.service(0).method(0), "name"));
 
2027
  EXPECT_TRUE(HasSpan(file_.service(0).method(0), "input_type"));
 
2028
  EXPECT_TRUE(HasSpan(file_.service(0).method(0), "output_type"));
 
2029
  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
 
2030
                      .uninterpreted_option(0)));
 
2031
  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
 
2032
                      .uninterpreted_option(0), "name"));
 
2033
  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
 
2034
                      .uninterpreted_option(0).name(0)));
 
2035
  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
 
2036
                      .uninterpreted_option(0).name(0), "name_part"));
 
2037
  EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
 
2038
                      .uninterpreted_option(0), "positive_int_value"));
 
2039
}
 
2040
 
 
2041
TEST_F(SourceInfoTest, FieldOptions) {
 
2042
  // The actual "name = value" pairs are parsed by the same code as for
 
2043
  // top-level options so we won't re-test that -- just make sure that the
 
2044
  // syntax used for field options is understood.
 
2045
  EXPECT_TRUE(Parse(
 
2046
      "message Foo {"
 
2047
      "  optional int32 bar = 1 "
 
2048
          "/*a*/[default=/*b*/123/*c*/,/*d*/opt1=123/*e*/,"
 
2049
          "/*f*/opt2='hi'/*g*/]/*h*/;"
 
2050
      "}\n"
 
2051
  ));
 
2052
 
 
2053
  const FieldDescriptorProto& field = file_.message_type(0).field(0);
 
2054
  const UninterpretedOption& option1 = field.options().uninterpreted_option(0);
 
2055
  const UninterpretedOption& option2 = field.options().uninterpreted_option(1);
 
2056
 
 
2057
  EXPECT_TRUE(HasSpan("a", "h", field.options()));
 
2058
  EXPECT_TRUE(HasSpan("b", "c", field, "default_value"));
 
2059
  EXPECT_TRUE(HasSpan("d", "e", option1));
 
2060
  EXPECT_TRUE(HasSpan("f", "g", option2));
 
2061
 
 
2062
  // Ignore these.
 
2063
  EXPECT_TRUE(HasSpan(file_));
 
2064
  EXPECT_TRUE(HasSpan(file_.message_type(0)));
 
2065
  EXPECT_TRUE(HasSpan(file_.message_type(0), "name"));
 
2066
  EXPECT_TRUE(HasSpan(field));
 
2067
  EXPECT_TRUE(HasSpan(field, "label"));
 
2068
  EXPECT_TRUE(HasSpan(field, "type"));
 
2069
  EXPECT_TRUE(HasSpan(field, "name"));
 
2070
  EXPECT_TRUE(HasSpan(field, "number"));
 
2071
  EXPECT_TRUE(HasSpan(option1, "name"));
 
2072
  EXPECT_TRUE(HasSpan(option2, "name"));
 
2073
  EXPECT_TRUE(HasSpan(option1.name(0)));
 
2074
  EXPECT_TRUE(HasSpan(option2.name(0)));
 
2075
  EXPECT_TRUE(HasSpan(option1.name(0), "name_part"));
 
2076
  EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
 
2077
  EXPECT_TRUE(HasSpan(option1, "positive_int_value"));
 
2078
  EXPECT_TRUE(HasSpan(option2, "string_value"));
 
2079
}
 
2080
 
 
2081
TEST_F(SourceInfoTest, EnumValueOptions) {
 
2082
  // The actual "name = value" pairs are parsed by the same code as for
 
2083
  // top-level options so we won't re-test that -- just make sure that the
 
2084
  // syntax used for enum options is understood.
 
2085
  EXPECT_TRUE(Parse(
 
2086
      "enum Foo {"
 
2087
      "  BAR = 1 /*a*/[/*b*/opt1=123/*c*/,/*d*/opt2='hi'/*e*/]/*f*/;"
 
2088
      "}\n"
 
2089
  ));
 
2090
 
 
2091
  const EnumValueDescriptorProto& value = file_.enum_type(0).value(0);
 
2092
  const UninterpretedOption& option1 = value.options().uninterpreted_option(0);
 
2093
  const UninterpretedOption& option2 = value.options().uninterpreted_option(1);
 
2094
 
 
2095
  EXPECT_TRUE(HasSpan("a", "f", value.options()));
 
2096
  EXPECT_TRUE(HasSpan("b", "c", option1));
 
2097
  EXPECT_TRUE(HasSpan("d", "e", option2));
 
2098
 
 
2099
  // Ignore these.
 
2100
  EXPECT_TRUE(HasSpan(file_));
 
2101
  EXPECT_TRUE(HasSpan(file_.enum_type(0)));
 
2102
  EXPECT_TRUE(HasSpan(file_.enum_type(0), "name"));
 
2103
  EXPECT_TRUE(HasSpan(value));
 
2104
  EXPECT_TRUE(HasSpan(value, "name"));
 
2105
  EXPECT_TRUE(HasSpan(value, "number"));
 
2106
  EXPECT_TRUE(HasSpan(option1, "name"));
 
2107
  EXPECT_TRUE(HasSpan(option2, "name"));
 
2108
  EXPECT_TRUE(HasSpan(option1.name(0)));
 
2109
  EXPECT_TRUE(HasSpan(option2.name(0)));
 
2110
  EXPECT_TRUE(HasSpan(option1.name(0), "name_part"));
 
2111
  EXPECT_TRUE(HasSpan(option2.name(0), "name_part"));
 
2112
  EXPECT_TRUE(HasSpan(option1, "positive_int_value"));
 
2113
  EXPECT_TRUE(HasSpan(option2, "string_value"));
 
2114
}
 
2115
 
 
2116
// ===================================================================
1251
2117
 
1252
2118
}  // anonymous namespace
1253
2119