Index: third_party/protobuf/src/google/protobuf/io/printer_unittest.cc |
diff --git a/third_party/protobuf/src/google/protobuf/io/printer_unittest.cc b/third_party/protobuf/src/google/protobuf/io/printer_unittest.cc |
index 258dd9861f7d2c062c7860ccd69a65fcd44ea86e..95f3afa2182e0bf10c747c76ca719ab90e441326 100644 |
--- a/third_party/protobuf/src/google/protobuf/io/printer_unittest.cc |
+++ b/third_party/protobuf/src/google/protobuf/io/printer_unittest.cc |
@@ -36,6 +36,7 @@ |
#include <google/protobuf/io/printer.h> |
#include <google/protobuf/io/zero_copy_stream_impl.h> |
+#include <google/protobuf/descriptor.pb.h> |
#include <google/protobuf/stubs/logging.h> |
#include <google/protobuf/stubs/common.h> |
@@ -169,6 +170,196 @@ TEST(Printer, InlineVariableSubstitution) { |
buffer); |
} |
+// MockDescriptorFile defines only those members that Printer uses to write out |
+// annotations. |
+class MockDescriptorFile { |
+ public: |
+ explicit MockDescriptorFile(const string& file) : file_(file) {} |
+ |
+ // The mock filename for this file. |
+ const string& name() const { return file_; } |
+ |
+ private: |
+ string file_; |
+}; |
+ |
+// MockDescriptor defines only those members that Printer uses to write out |
+// annotations. |
+class MockDescriptor { |
+ public: |
+ MockDescriptor(const string& file, const vector<int>& path) |
+ : file_(file), path_(path) {} |
+ |
+ // The mock file in which this descriptor was defined. |
+ const MockDescriptorFile* file() const { return &file_; } |
+ |
+ private: |
+ // Allows access to GetLocationPath. |
+ friend class ::google::protobuf::io::Printer; |
+ |
+ // Copies the pre-stored path to output. |
+ void GetLocationPath(std::vector<int>* output) const { *output = path_; } |
+ |
+ MockDescriptorFile file_; |
+ vector<int> path_; |
+}; |
+ |
+TEST(Printer, AnnotateMap) { |
+ char buffer[8192]; |
+ ArrayOutputStream output(buffer, sizeof(buffer)); |
+ GeneratedCodeInfo info; |
+ AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info); |
+ { |
+ Printer printer(&output, '$', &info_collector); |
+ map<string, string> vars; |
+ vars["foo"] = "3"; |
+ vars["bar"] = "5"; |
+ printer.Print(vars, "012$foo$4$bar$\n"); |
+ vector<int> path_1; |
+ path_1.push_back(33); |
+ vector<int> path_2; |
+ path_2.push_back(11); |
+ path_2.push_back(22); |
+ MockDescriptor descriptor_1("path_1", path_1); |
+ MockDescriptor descriptor_2("path_2", path_2); |
+ printer.Annotate("foo", "foo", &descriptor_1); |
+ printer.Annotate("bar", "bar", &descriptor_2); |
+ } |
+ buffer[output.ByteCount()] = '\0'; |
+ EXPECT_STREQ("012345\n", buffer); |
+ ASSERT_EQ(2, info.annotation_size()); |
+ const GeneratedCodeInfo::Annotation* foo = info.annotation(0).path_size() == 1 |
+ ? &info.annotation(0) |
+ : &info.annotation(1); |
+ const GeneratedCodeInfo::Annotation* bar = info.annotation(0).path_size() == 1 |
+ ? &info.annotation(1) |
+ : &info.annotation(0); |
+ ASSERT_EQ(1, foo->path_size()); |
+ ASSERT_EQ(2, bar->path_size()); |
+ EXPECT_EQ(33, foo->path(0)); |
+ EXPECT_EQ(11, bar->path(0)); |
+ EXPECT_EQ(22, bar->path(1)); |
+ EXPECT_EQ("path_1", foo->source_file()); |
+ EXPECT_EQ("path_2", bar->source_file()); |
+ EXPECT_EQ(3, foo->begin()); |
+ EXPECT_EQ(4, foo->end()); |
+ EXPECT_EQ(5, bar->begin()); |
+ EXPECT_EQ(6, bar->end()); |
+} |
+ |
+TEST(Printer, AnnotateInline) { |
+ char buffer[8192]; |
+ ArrayOutputStream output(buffer, sizeof(buffer)); |
+ GeneratedCodeInfo info; |
+ AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info); |
+ { |
+ Printer printer(&output, '$', &info_collector); |
+ printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5"); |
+ vector<int> path_1; |
+ path_1.push_back(33); |
+ vector<int> path_2; |
+ path_2.push_back(11); |
+ path_2.push_back(22); |
+ MockDescriptor descriptor_1("path_1", path_1); |
+ MockDescriptor descriptor_2("path_2", path_2); |
+ printer.Annotate("foo", "foo", &descriptor_1); |
+ printer.Annotate("bar", "bar", &descriptor_2); |
+ } |
+ buffer[output.ByteCount()] = '\0'; |
+ EXPECT_STREQ("012345\n", buffer); |
+ ASSERT_EQ(2, info.annotation_size()); |
+ const GeneratedCodeInfo::Annotation* foo = info.annotation(0).path_size() == 1 |
+ ? &info.annotation(0) |
+ : &info.annotation(1); |
+ const GeneratedCodeInfo::Annotation* bar = info.annotation(0).path_size() == 1 |
+ ? &info.annotation(1) |
+ : &info.annotation(0); |
+ ASSERT_EQ(1, foo->path_size()); |
+ ASSERT_EQ(2, bar->path_size()); |
+ EXPECT_EQ(33, foo->path(0)); |
+ EXPECT_EQ(11, bar->path(0)); |
+ EXPECT_EQ(22, bar->path(1)); |
+ EXPECT_EQ("path_1", foo->source_file()); |
+ EXPECT_EQ("path_2", bar->source_file()); |
+ EXPECT_EQ(3, foo->begin()); |
+ EXPECT_EQ(4, foo->end()); |
+ EXPECT_EQ(5, bar->begin()); |
+ EXPECT_EQ(6, bar->end()); |
+} |
+ |
+TEST(Printer, AnnotateRange) { |
+ char buffer[8192]; |
+ ArrayOutputStream output(buffer, sizeof(buffer)); |
+ GeneratedCodeInfo info; |
+ AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info); |
+ { |
+ Printer printer(&output, '$', &info_collector); |
+ printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5"); |
+ vector<int> path; |
+ path.push_back(33); |
+ MockDescriptor descriptor("path", path); |
+ printer.Annotate("foo", "bar", &descriptor); |
+ } |
+ buffer[output.ByteCount()] = '\0'; |
+ EXPECT_STREQ("012345\n", buffer); |
+ ASSERT_EQ(1, info.annotation_size()); |
+ const GeneratedCodeInfo::Annotation* foobar = &info.annotation(0); |
+ ASSERT_EQ(1, foobar->path_size()); |
+ EXPECT_EQ(33, foobar->path(0)); |
+ EXPECT_EQ("path", foobar->source_file()); |
+ EXPECT_EQ(3, foobar->begin()); |
+ EXPECT_EQ(6, foobar->end()); |
+} |
+ |
+TEST(Printer, AnnotateEmptyRange) { |
+ char buffer[8192]; |
+ ArrayOutputStream output(buffer, sizeof(buffer)); |
+ GeneratedCodeInfo info; |
+ AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info); |
+ { |
+ Printer printer(&output, '$', &info_collector); |
+ printer.Print("012$foo$4$baz$$bam$$bar$\n", "foo", "3", "bar", "5", "baz", |
+ "", "bam", ""); |
+ vector<int> path; |
+ path.push_back(33); |
+ MockDescriptor descriptor("path", path); |
+ printer.Annotate("baz", "bam", &descriptor); |
+ } |
+ buffer[output.ByteCount()] = '\0'; |
+ EXPECT_STREQ("012345\n", buffer); |
+ ASSERT_EQ(1, info.annotation_size()); |
+ const GeneratedCodeInfo::Annotation* bazbam = &info.annotation(0); |
+ ASSERT_EQ(1, bazbam->path_size()); |
+ EXPECT_EQ(33, bazbam->path(0)); |
+ EXPECT_EQ("path", bazbam->source_file()); |
+ EXPECT_EQ(5, bazbam->begin()); |
+ EXPECT_EQ(5, bazbam->end()); |
+} |
+ |
+TEST(Printer, AnnotateDespiteUnrelatedMultipleUses) { |
+ char buffer[8192]; |
+ ArrayOutputStream output(buffer, sizeof(buffer)); |
+ GeneratedCodeInfo info; |
+ AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info); |
+ { |
+ Printer printer(&output, '$', &info_collector); |
+ printer.Print("012$foo$4$foo$$bar$\n", "foo", "3", "bar", "5"); |
+ vector<int> path; |
+ path.push_back(33); |
+ MockDescriptor descriptor("path", path); |
+ printer.Annotate("bar", "bar", &descriptor); |
+ } |
+ buffer[output.ByteCount()] = '\0'; |
+ EXPECT_STREQ("0123435\n", buffer); |
+ ASSERT_EQ(1, info.annotation_size()); |
+ const GeneratedCodeInfo::Annotation* bar = &info.annotation(0); |
+ ASSERT_EQ(1, bar->path_size()); |
+ EXPECT_EQ(33, bar->path(0)); |
+ EXPECT_EQ("path", bar->source_file()); |
+ EXPECT_EQ(6, bar->begin()); |
+ EXPECT_EQ(7, bar->end()); |
+} |
+ |
TEST(Printer, Indenting) { |
char buffer[8192]; |
@@ -232,6 +423,52 @@ TEST(Printer, Death) { |
EXPECT_DEBUG_DEATH(printer.Print("$unclosed"), "Unclosed variable name"); |
EXPECT_DEBUG_DEATH(printer.Outdent(), "without matching Indent"); |
} |
+ |
+TEST(Printer, AnnotateMultipleUsesDeath) { |
+ char buffer[8192]; |
+ ArrayOutputStream output(buffer, sizeof(buffer)); |
+ GeneratedCodeInfo info; |
+ AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info); |
+ { |
+ Printer printer(&output, '$', &info_collector); |
+ printer.Print("012$foo$4$foo$\n", "foo", "3"); |
+ vector<int> path; |
+ path.push_back(33); |
+ MockDescriptor descriptor("path", path); |
+ EXPECT_DEBUG_DEATH(printer.Annotate("foo", "foo", &descriptor), "multiple"); |
+ } |
+} |
+ |
+TEST(Printer, AnnotateNegativeLengthDeath) { |
+ char buffer[8192]; |
+ ArrayOutputStream output(buffer, sizeof(buffer)); |
+ GeneratedCodeInfo info; |
+ AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info); |
+ { |
+ Printer printer(&output, '$', &info_collector); |
+ printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5"); |
+ vector<int> path; |
+ path.push_back(33); |
+ MockDescriptor descriptor("path", path); |
+ EXPECT_DEBUG_DEATH(printer.Annotate("bar", "foo", &descriptor), "negative"); |
+ } |
+} |
+ |
+TEST(Printer, AnnotateUndefinedDeath) { |
+ char buffer[8192]; |
+ ArrayOutputStream output(buffer, sizeof(buffer)); |
+ GeneratedCodeInfo info; |
+ AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info); |
+ { |
+ Printer printer(&output, '$', &info_collector); |
+ printer.Print("012$foo$4$foo$\n", "foo", "3"); |
+ vector<int> path; |
+ path.push_back(33); |
+ MockDescriptor descriptor("path", path); |
+ EXPECT_DEBUG_DEATH(printer.Annotate("bar", "bar", &descriptor), |
+ "Undefined"); |
+ } |
+} |
#endif // PROTOBUF_HAS_DEATH_TEST |
TEST(Printer, WriteFailurePartial) { |