protobuf/src/google/protobuf/io/printer_unittest.cc
Go to the documentation of this file.
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
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 <google/protobuf/io/printer.h>
36 
37 #include <vector>
38 
39 #include <google/protobuf/stubs/logging.h>
40 #include <google/protobuf/stubs/common.h>
41 #include <google/protobuf/descriptor.pb.h>
42 #include <google/protobuf/testing/googletest.h>
43 #include <gtest/gtest.h>
44 #include <google/protobuf/io/zero_copy_stream_impl.h>
45 
46 namespace google {
47 namespace protobuf {
48 namespace io {
49 
50 // Each test repeats over several block sizes in order to test both cases
51 // where particular writes cross a buffer boundary and cases where they do
52 // not.
53 
54 TEST(Printer, EmptyPrinter) {
55  char buffer[8192];
56  const int block_size = 100;
57  ArrayOutputStream output(buffer, GOOGLE_ARRAYSIZE(buffer), block_size);
58  Printer printer(&output, '\0');
59  EXPECT_TRUE(!printer.failed());
60 }
61 
62 TEST(Printer, BasicPrinting) {
63  char buffer[8192];
64 
65  for (int block_size = 1; block_size < 512; block_size *= 2) {
66  ArrayOutputStream output(buffer, sizeof(buffer), block_size);
67 
68  {
69  Printer printer(&output, '\0');
70 
71  printer.Print("Hello World!");
72  printer.Print(" This is the same line.\n");
73  printer.Print("But this is a new one.\nAnd this is another one.");
74 
75  EXPECT_FALSE(printer.failed());
76  }
77 
78  buffer[output.ByteCount()] = '\0';
79 
81  "Hello World! This is the same line.\n"
82  "But this is a new one.\n"
83  "And this is another one.",
84  buffer);
85  }
86 }
87 
88 TEST(Printer, WriteRaw) {
89  char buffer[8192];
90 
91  for (int block_size = 1; block_size < 512; block_size *= 2) {
92  ArrayOutputStream output(buffer, sizeof(buffer), block_size);
93 
94  {
95  std::string string_obj = "From an object\n";
96  Printer printer(&output, '$');
97  printer.WriteRaw("Hello World!", 12);
98  printer.PrintRaw(" This is the same line.\n");
99  printer.PrintRaw("But this is a new one.\nAnd this is another one.");
100  printer.WriteRaw("\n", 1);
101  printer.PrintRaw(string_obj);
102  EXPECT_FALSE(printer.failed());
103  }
104 
105  buffer[output.ByteCount()] = '\0';
106 
107  EXPECT_STREQ(
108  "Hello World! This is the same line.\n"
109  "But this is a new one.\n"
110  "And this is another one."
111  "\n"
112  "From an object\n",
113  buffer);
114  }
115 }
116 
117 TEST(Printer, VariableSubstitution) {
118  char buffer[8192];
119 
120  for (int block_size = 1; block_size < 512; block_size *= 2) {
121  ArrayOutputStream output(buffer, sizeof(buffer), block_size);
122 
123  {
124  Printer printer(&output, '$');
125  std::map<std::string, std::string> vars;
126 
127  vars["foo"] = "World";
128  vars["bar"] = "$foo$";
129  vars["abcdefg"] = "1234";
130 
131  printer.Print(vars, "Hello $foo$!\nbar = $bar$\n");
132  printer.PrintRaw("RawBit\n");
133  printer.Print(vars, "$abcdefg$\nA literal dollar sign: $$");
134 
135  vars["foo"] = "blah";
136  printer.Print(vars, "\nNow foo = $foo$.");
137 
138  EXPECT_FALSE(printer.failed());
139  }
140 
141  buffer[output.ByteCount()] = '\0';
142 
143  EXPECT_STREQ(
144  "Hello World!\n"
145  "bar = $foo$\n"
146  "RawBit\n"
147  "1234\n"
148  "A literal dollar sign: $\n"
149  "Now foo = blah.",
150  buffer);
151  }
152 }
153 
154 TEST(Printer, InlineVariableSubstitution) {
155  char buffer[8192];
156 
157  ArrayOutputStream output(buffer, sizeof(buffer));
158 
159  {
160  Printer printer(&output, '$');
161  printer.Print("Hello $foo$!\n", "foo", "World");
162  printer.PrintRaw("RawBit\n");
163  printer.Print("$foo$ $bar$\n", "foo", "one", "bar", "two");
164  EXPECT_FALSE(printer.failed());
165  }
166 
167  buffer[output.ByteCount()] = '\0';
168 
169  EXPECT_STREQ(
170  "Hello World!\n"
171  "RawBit\n"
172  "one two\n",
173  buffer);
174 }
175 
176 // MockDescriptorFile defines only those members that Printer uses to write out
177 // annotations.
178 class MockDescriptorFile {
179  public:
181 
182  // The mock filename for this file.
183  const std::string& name() const { return file_; }
184 
185  private:
187 };
188 
189 // MockDescriptor defines only those members that Printer uses to write out
190 // annotations.
191 class MockDescriptor {
192  public:
193  MockDescriptor(const std::string& file, const std::vector<int>& path)
194  : file_(file), path_(path) {}
195 
196  // The mock file in which this descriptor was defined.
197  const MockDescriptorFile* file() const { return &file_; }
198 
199  private:
200  // Allows access to GetLocationPath.
201  friend class Printer;
202 
203  // Copies the pre-stored path to output.
204  void GetLocationPath(std::vector<int>* output) const { *output = path_; }
205 
207  std::vector<int> path_;
208 };
209 
210 TEST(Printer, AnnotateMap) {
211  char buffer[8192];
212  ArrayOutputStream output(buffer, sizeof(buffer));
213  GeneratedCodeInfo info;
214  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
215  {
216  Printer printer(&output, '$', &info_collector);
217  std::map<std::string, std::string> vars;
218  vars["foo"] = "3";
219  vars["bar"] = "5";
220  printer.Print(vars, "012$foo$4$bar$\n");
221  std::vector<int> path_1;
222  path_1.push_back(33);
223  std::vector<int> path_2;
224  path_2.push_back(11);
225  path_2.push_back(22);
226  MockDescriptor descriptor_1("path_1", path_1);
227  MockDescriptor descriptor_2("path_2", path_2);
228  printer.Annotate("foo", "foo", &descriptor_1);
229  printer.Annotate("bar", "bar", &descriptor_2);
230  }
231  buffer[output.ByteCount()] = '\0';
232  EXPECT_STREQ("012345\n", buffer);
233  ASSERT_EQ(2, info.annotation_size());
234  const GeneratedCodeInfo::Annotation* foo = info.annotation(0).path_size() == 1
235  ? &info.annotation(0)
236  : &info.annotation(1);
237  const GeneratedCodeInfo::Annotation* bar = info.annotation(0).path_size() == 1
238  ? &info.annotation(1)
239  : &info.annotation(0);
240  ASSERT_EQ(1, foo->path_size());
241  ASSERT_EQ(2, bar->path_size());
242  EXPECT_EQ(33, foo->path(0));
243  EXPECT_EQ(11, bar->path(0));
244  EXPECT_EQ(22, bar->path(1));
245  EXPECT_EQ("path_1", foo->source_file());
246  EXPECT_EQ("path_2", bar->source_file());
247  EXPECT_EQ(3, foo->begin());
248  EXPECT_EQ(4, foo->end());
249  EXPECT_EQ(5, bar->begin());
250  EXPECT_EQ(6, bar->end());
251 }
252 
253 TEST(Printer, AnnotateInline) {
254  char buffer[8192];
255  ArrayOutputStream output(buffer, sizeof(buffer));
256  GeneratedCodeInfo info;
257  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
258  {
259  Printer printer(&output, '$', &info_collector);
260  printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5");
261  std::vector<int> path_1;
262  path_1.push_back(33);
263  std::vector<int> path_2;
264  path_2.push_back(11);
265  path_2.push_back(22);
266  MockDescriptor descriptor_1("path_1", path_1);
267  MockDescriptor descriptor_2("path_2", path_2);
268  printer.Annotate("foo", "foo", &descriptor_1);
269  printer.Annotate("bar", "bar", &descriptor_2);
270  }
271  buffer[output.ByteCount()] = '\0';
272  EXPECT_STREQ("012345\n", buffer);
273  ASSERT_EQ(2, info.annotation_size());
274  const GeneratedCodeInfo::Annotation* foo = info.annotation(0).path_size() == 1
275  ? &info.annotation(0)
276  : &info.annotation(1);
277  const GeneratedCodeInfo::Annotation* bar = info.annotation(0).path_size() == 1
278  ? &info.annotation(1)
279  : &info.annotation(0);
280  ASSERT_EQ(1, foo->path_size());
281  ASSERT_EQ(2, bar->path_size());
282  EXPECT_EQ(33, foo->path(0));
283  EXPECT_EQ(11, bar->path(0));
284  EXPECT_EQ(22, bar->path(1));
285  EXPECT_EQ("path_1", foo->source_file());
286  EXPECT_EQ("path_2", bar->source_file());
287  EXPECT_EQ(3, foo->begin());
288  EXPECT_EQ(4, foo->end());
289  EXPECT_EQ(5, bar->begin());
290  EXPECT_EQ(6, bar->end());
291 }
292 
293 TEST(Printer, AnnotateRange) {
294  char buffer[8192];
295  ArrayOutputStream output(buffer, sizeof(buffer));
296  GeneratedCodeInfo info;
297  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
298  {
299  Printer printer(&output, '$', &info_collector);
300  printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5");
301  std::vector<int> path;
302  path.push_back(33);
303  MockDescriptor descriptor("path", path);
304  printer.Annotate("foo", "bar", &descriptor);
305  }
306  buffer[output.ByteCount()] = '\0';
307  EXPECT_STREQ("012345\n", buffer);
308  ASSERT_EQ(1, info.annotation_size());
309  const GeneratedCodeInfo::Annotation* foobar = &info.annotation(0);
310  ASSERT_EQ(1, foobar->path_size());
311  EXPECT_EQ(33, foobar->path(0));
312  EXPECT_EQ("path", foobar->source_file());
313  EXPECT_EQ(3, foobar->begin());
314  EXPECT_EQ(6, foobar->end());
315 }
316 
317 TEST(Printer, AnnotateEmptyRange) {
318  char buffer[8192];
319  ArrayOutputStream output(buffer, sizeof(buffer));
320  GeneratedCodeInfo info;
321  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
322  {
323  Printer printer(&output, '$', &info_collector);
324  printer.Print("012$foo$4$baz$$bam$$bar$\n", "foo", "3", "bar", "5", "baz",
325  "", "bam", "");
326  std::vector<int> path;
327  path.push_back(33);
328  MockDescriptor descriptor("path", path);
329  printer.Annotate("baz", "bam", &descriptor);
330  }
331  buffer[output.ByteCount()] = '\0';
332  EXPECT_STREQ("012345\n", buffer);
333  ASSERT_EQ(1, info.annotation_size());
334  const GeneratedCodeInfo::Annotation* bazbam = &info.annotation(0);
335  ASSERT_EQ(1, bazbam->path_size());
336  EXPECT_EQ(33, bazbam->path(0));
337  EXPECT_EQ("path", bazbam->source_file());
338  EXPECT_EQ(5, bazbam->begin());
339  EXPECT_EQ(5, bazbam->end());
340 }
341 
342 TEST(Printer, AnnotateDespiteUnrelatedMultipleUses) {
343  char buffer[8192];
344  ArrayOutputStream output(buffer, sizeof(buffer));
345  GeneratedCodeInfo info;
346  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
347  {
348  Printer printer(&output, '$', &info_collector);
349  printer.Print("012$foo$4$foo$$bar$\n", "foo", "3", "bar", "5");
350  std::vector<int> path;
351  path.push_back(33);
352  MockDescriptor descriptor("path", path);
353  printer.Annotate("bar", "bar", &descriptor);
354  }
355  buffer[output.ByteCount()] = '\0';
356  EXPECT_STREQ("0123435\n", buffer);
357  ASSERT_EQ(1, info.annotation_size());
358  const GeneratedCodeInfo::Annotation* bar = &info.annotation(0);
359  ASSERT_EQ(1, bar->path_size());
360  EXPECT_EQ(33, bar->path(0));
361  EXPECT_EQ("path", bar->source_file());
362  EXPECT_EQ(6, bar->begin());
363  EXPECT_EQ(7, bar->end());
364 }
365 
366 TEST(Printer, AnnotateIndent) {
367  char buffer[8192];
368  ArrayOutputStream output(buffer, sizeof(buffer));
369  GeneratedCodeInfo info;
370  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
371  {
372  Printer printer(&output, '$', &info_collector);
373  printer.Print("0\n");
374  printer.Indent();
375  printer.Print("$foo$", "foo", "4");
376  std::vector<int> path;
377  path.push_back(44);
378  MockDescriptor descriptor("path", path);
379  printer.Annotate("foo", &descriptor);
380  printer.Print(",\n");
381  printer.Print("$bar$", "bar", "9");
382  path[0] = 99;
383  MockDescriptor descriptor_two("path", path);
384  printer.Annotate("bar", &descriptor_two);
385  printer.Print("\n${$$D$$}$\n", "{", "", "}", "", "D", "d");
386  path[0] = 1313;
387  MockDescriptor descriptor_three("path", path);
388  printer.Annotate("{", "}", &descriptor_three);
389  printer.Outdent();
390  printer.Print("\n");
391  }
392  buffer[output.ByteCount()] = '\0';
393  EXPECT_STREQ("0\n 4,\n 9\n d\n\n", buffer);
394  ASSERT_EQ(3, info.annotation_size());
395  const GeneratedCodeInfo::Annotation* foo = &info.annotation(0);
396  ASSERT_EQ(1, foo->path_size());
397  EXPECT_EQ(44, foo->path(0));
398  EXPECT_EQ("path", foo->source_file());
399  EXPECT_EQ(4, foo->begin());
400  EXPECT_EQ(5, foo->end());
401  const GeneratedCodeInfo::Annotation* bar = &info.annotation(1);
402  ASSERT_EQ(1, bar->path_size());
403  EXPECT_EQ(99, bar->path(0));
404  EXPECT_EQ("path", bar->source_file());
405  EXPECT_EQ(9, bar->begin());
406  EXPECT_EQ(10, bar->end());
407  const GeneratedCodeInfo::Annotation* braces = &info.annotation(2);
408  ASSERT_EQ(1, braces->path_size());
409  EXPECT_EQ(1313, braces->path(0));
410  EXPECT_EQ("path", braces->source_file());
411  EXPECT_EQ(13, braces->begin());
412  EXPECT_EQ(14, braces->end());
413 }
414 
415 TEST(Printer, AnnotateIndentNewline) {
416  char buffer[8192];
417  ArrayOutputStream output(buffer, sizeof(buffer));
418  GeneratedCodeInfo info;
419  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
420  {
421  Printer printer(&output, '$', &info_collector);
422  printer.Indent();
423  printer.Print("$A$$N$$B$C\n", "A", "", "N", "\nz", "B", "");
424  std::vector<int> path;
425  path.push_back(0);
426  MockDescriptor descriptor("path", path);
427  printer.Annotate("A", "B", &descriptor);
428  printer.Outdent();
429  printer.Print("\n");
430  }
431  buffer[output.ByteCount()] = '\0';
432  EXPECT_STREQ("\nz C\n\n", buffer);
433  ASSERT_EQ(1, info.annotation_size());
434  const GeneratedCodeInfo::Annotation* ab = &info.annotation(0);
435  ASSERT_EQ(1, ab->path_size());
436  EXPECT_EQ(0, ab->path(0));
437  EXPECT_EQ("path", ab->source_file());
438  EXPECT_EQ(0, ab->begin());
439  EXPECT_EQ(4, ab->end());
440 }
441 
442 TEST(Printer, Indenting) {
443  char buffer[8192];
444 
445  for (int block_size = 1; block_size < 512; block_size *= 2) {
446  ArrayOutputStream output(buffer, sizeof(buffer), block_size);
447 
448  {
449  Printer printer(&output, '$');
450  std::map<std::string, std::string> vars;
451 
452  vars["newline"] = "\n";
453 
454  printer.Print("This is not indented.\n");
455  printer.Indent();
456  printer.Print("This is indented\nAnd so is this\n");
457  printer.Outdent();
458  printer.Print("But this is not.");
459  printer.Indent();
460  printer.Print(
461  " And this is still the same line.\n"
462  "But this is indented.\n");
463  printer.PrintRaw("RawBit has indent at start\n");
464  printer.PrintRaw("but not after a raw newline\n");
465  printer.Print(vars,
466  "Note that a newline in a variable will break "
467  "indenting, as we see$newline$here.\n");
468  printer.Indent();
469  printer.Print("And this");
470  printer.Outdent();
471  printer.Outdent();
472  printer.Print(" is double-indented\nBack to normal.");
473 
474  EXPECT_FALSE(printer.failed());
475  }
476 
477  buffer[output.ByteCount()] = '\0';
478 
479  EXPECT_STREQ(
480  "This is not indented.\n"
481  " This is indented\n"
482  " And so is this\n"
483  "But this is not. And this is still the same line.\n"
484  " But this is indented.\n"
485  " RawBit has indent at start\n"
486  "but not after a raw newline\n"
487  "Note that a newline in a variable will break indenting, as we see\n"
488  "here.\n"
489  " And this is double-indented\n"
490  "Back to normal.",
491  buffer);
492  }
493 }
494 
495 // Death tests do not work on Windows as of yet.
496 #ifdef PROTOBUF_HAS_DEATH_TEST
497 TEST(Printer, Death) {
498  char buffer[8192];
499 
500  ArrayOutputStream output(buffer, sizeof(buffer));
501  Printer printer(&output, '$');
502 
503  EXPECT_DEBUG_DEATH(printer.Print("$nosuchvar$"), "Undefined variable");
504  EXPECT_DEBUG_DEATH(printer.Print("$unclosed"), "Unclosed variable name");
505  EXPECT_DEBUG_DEATH(printer.Outdent(), "without matching Indent");
506 }
507 
508 TEST(Printer, AnnotateMultipleUsesDeath) {
509  char buffer[8192];
510  ArrayOutputStream output(buffer, sizeof(buffer));
511  GeneratedCodeInfo info;
512  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
513  {
514  Printer printer(&output, '$', &info_collector);
515  printer.Print("012$foo$4$foo$\n", "foo", "3");
516  std::vector<int> path;
517  path.push_back(33);
518  MockDescriptor descriptor("path", path);
519  EXPECT_DEBUG_DEATH(printer.Annotate("foo", "foo", &descriptor), "multiple");
520  }
521 }
522 
523 TEST(Printer, AnnotateNegativeLengthDeath) {
524  char buffer[8192];
525  ArrayOutputStream output(buffer, sizeof(buffer));
526  GeneratedCodeInfo info;
527  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
528  {
529  Printer printer(&output, '$', &info_collector);
530  printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5");
531  std::vector<int> path;
532  path.push_back(33);
533  MockDescriptor descriptor("path", path);
534  EXPECT_DEBUG_DEATH(printer.Annotate("bar", "foo", &descriptor), "negative");
535  }
536 }
537 
538 TEST(Printer, AnnotateUndefinedDeath) {
539  char buffer[8192];
540  ArrayOutputStream output(buffer, sizeof(buffer));
541  GeneratedCodeInfo info;
542  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
543  {
544  Printer printer(&output, '$', &info_collector);
545  printer.Print("012$foo$4$foo$\n", "foo", "3");
546  std::vector<int> path;
547  path.push_back(33);
548  MockDescriptor descriptor("path", path);
549  EXPECT_DEBUG_DEATH(printer.Annotate("bar", "bar", &descriptor),
550  "Undefined");
551  }
552 }
553 #endif // PROTOBUF_HAS_DEATH_TEST
554 
555 TEST(Printer, WriteFailurePartial) {
556  char buffer[17];
557 
558  ArrayOutputStream output(buffer, sizeof(buffer));
559  Printer printer(&output, '$');
560 
561  // Print 16 bytes to almost fill the buffer (should not fail).
562  printer.Print("0123456789abcdef");
563  EXPECT_FALSE(printer.failed());
564 
565  // Try to print 2 chars. Only one fits.
566  printer.Print("<>");
567  EXPECT_TRUE(printer.failed());
568 
569  // Anything else should fail too.
570  printer.Print(" ");
571  EXPECT_TRUE(printer.failed());
572  printer.Print("blah");
573  EXPECT_TRUE(printer.failed());
574 
575  // Buffer should contain the first 17 bytes written.
576  EXPECT_EQ("0123456789abcdef<", std::string(buffer, sizeof(buffer)));
577 }
578 
579 TEST(Printer, WriteFailureExact) {
580  char buffer[16];
581 
582  ArrayOutputStream output(buffer, sizeof(buffer));
583  Printer printer(&output, '$');
584 
585  // Print 16 bytes to fill the buffer exactly (should not fail).
586  printer.Print("0123456789abcdef");
587  EXPECT_FALSE(printer.failed());
588 
589  // Try to print one more byte (should fail).
590  printer.Print(" ");
591  EXPECT_TRUE(printer.failed());
592 
593  // Should not crash
594  printer.Print("blah");
595  EXPECT_TRUE(printer.failed());
596 
597  // Buffer should contain the first 16 bytes written.
598  EXPECT_EQ("0123456789abcdef", std::string(buffer, sizeof(buffer)));
599 }
600 
601 TEST(Printer, FormatInternal) {
602  std::vector<std::string> args{"arg1", "arg2"};
603  std::map<std::string, std::string> vars{
604  {"foo", "bar"}, {"baz", "bla"}, {"empty", ""}};
605  // Substitution tests
606  {
607  // Direct arg substitution
608  std::string s;
609  {
611  Printer printer(&output, '$');
612  printer.FormatInternal(args, vars, "$1$ $2$");
613  }
614  EXPECT_EQ("arg1 arg2", s);
615  }
616  {
617  // Variable substitution including spaces left
618  std::string s;
619  {
621  Printer printer(&output, '$');
622  printer.FormatInternal({}, vars, "$foo$$ baz$$ empty$");
623  }
624  EXPECT_EQ("bar bla", s);
625  }
626  {
627  // Variable substitution including spaces right
628  std::string s;
629  {
631  Printer printer(&output, '$');
632  printer.FormatInternal({}, vars, "$empty $$foo $$baz$");
633  }
634  EXPECT_EQ("bar bla", s);
635  }
636  {
637  // Mixed variable substitution
638  std::string s;
639  {
641  Printer printer(&output, '$');
642  printer.FormatInternal(args, vars, "$empty $$1$ $foo $$2$ $baz$");
643  }
644  EXPECT_EQ("arg1 bar arg2 bla", s);
645  }
646 
647  // Indentation tests
648  {
649  // Empty lines shouldn't indent.
650  std::string s;
651  {
653  Printer printer(&output, '$');
654  printer.Indent();
655  printer.FormatInternal(args, vars, "$empty $\n\n$1$ $foo $$2$\n$baz$");
656  printer.Outdent();
657  }
658  EXPECT_EQ("\n\n arg1 bar arg2\n bla", s);
659  }
660  {
661  // Annotations should respect indentation.
662  std::string s;
663  GeneratedCodeInfo info;
664  {
666  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
667  Printer printer(&output, '$', &info_collector);
668  printer.Indent();
670  annotation.set_source_file("file.proto");
671  annotation.add_path(33);
672  std::vector<std::string> args{annotation.SerializeAsString(), "arg1",
673  "arg2"};
674  printer.FormatInternal(args, vars, "$empty $\n\n${1$$2$$}$ $3$\n$baz$");
675  printer.Outdent();
676  }
677  EXPECT_EQ("\n\n arg1 arg2\n bla", s);
678  ASSERT_EQ(1, info.annotation_size());
679  const GeneratedCodeInfo::Annotation* arg1 = &info.annotation(0);
680  ASSERT_EQ(1, arg1->path_size());
681  EXPECT_EQ(33, arg1->path(0));
682  EXPECT_EQ("file.proto", arg1->source_file());
683  EXPECT_EQ(4, arg1->begin());
684  EXPECT_EQ(8, arg1->end());
685  }
686 #ifdef PROTOBUF_HAS_DEATH_TEST
687  // Death tests in case of illegal format strings.
688  {
689  // Unused arguments
690  std::string s;
692  Printer printer(&output, '$');
693  EXPECT_DEATH(printer.FormatInternal(args, vars, "$empty $$1$"), "Unused");
694  }
695  {
696  // Wrong order arguments
697  std::string s;
699  Printer printer(&output, '$');
700  EXPECT_DEATH(printer.FormatInternal(args, vars, "$2$ $1$"), "order");
701  }
702  {
703  // Zero is illegal argument
704  std::string s;
706  Printer printer(&output, '$');
707  EXPECT_DEATH(printer.FormatInternal(args, vars, "$0$"), "failed");
708  }
709  {
710  // Argument out of bounds
711  std::string s;
713  Printer printer(&output, '$');
714  EXPECT_DEATH(printer.FormatInternal(args, vars, "$1$ $2$ $3$"), "bounds");
715  }
716  {
717  // Unknown variable
718  std::string s;
720  Printer printer(&output, '$');
721  EXPECT_DEATH(printer.FormatInternal(args, vars, "$huh$ $1$$2$"), "Unknown");
722  }
723  {
724  // Illegal variable
725  std::string s;
727  Printer printer(&output, '$');
728  EXPECT_DEATH(printer.FormatInternal({}, vars, "$ $"), "Empty");
729  }
730 #endif // PROTOBUF_HAS_DEATH_TEST
731 }
732 
733 } // namespace io
734 } // namespace protobuf
735 } // namespace google
EXPECT_FALSE
#define EXPECT_FALSE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1970
GeneratedCodeInfo::annotation
const PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation & annotation(int index) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:13952
bar
Definition: bloaty/third_party/googletest/googletest/test/googletest-output-test_.cc:562
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
google::protobuf::io::MockDescriptorFile::name
const std::string & name() const
Definition: protobuf/src/google/protobuf/io/printer_unittest.cc:183
file
Definition: bloaty/third_party/zlib/examples/gzappend.c:170
grpc::protobuf::io::Printer
GRPC_CUSTOM_PRINTER Printer
Definition: src/compiler/config.h:54
google::protobuf
Definition: bloaty/third_party/protobuf/benchmarks/util/data_proto2_to_proto3_util.h:12
foo
Definition: bloaty/third_party/googletest/googletest/test/googletest-output-test_.cc:546
GeneratedCodeInfo_Annotation::add_path
void add_path(::PROTOBUF_NAMESPACE_ID::int32 value)
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:13754
absl::FormatConversionChar::s
@ s
GeneratedCodeInfo_Annotation::set_source_file
void set_source_file(const std::string &value)
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:13793
check_documentation.path
path
Definition: check_documentation.py:57
GeneratedCodeInfo_Annotation::source_file
const std::string & source_file() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:13789
GeneratedCodeInfo::annotation_size
int annotation_size() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:13934
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: iomgr/time_averaged_stats_test.cc:27
google::protobuf::io::MockDescriptor::file
const MockDescriptorFile * file() const
Definition: protobuf/src/google/protobuf/io/printer_unittest.cc:197
google::protobuf::io::MockDescriptorFile::file_
std::string file_
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/printer_unittest.cc:186
google::protobuf::io::TEST
TEST(Printer, EmptyPrinter)
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/printer_unittest.cc:54
grpc::protobuf::io::StringOutputStream
GRPC_CUSTOM_STRINGOUTPUTSTREAM StringOutputStream
Definition: src/compiler/config.h:56
google::protobuf::io::MockDescriptor::file_
MockDescriptorFile file_
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/printer_unittest.cc:206
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
gmock_output_test.output
output
Definition: bloaty/third_party/googletest/googlemock/test/gmock_output_test.py:175
GeneratedCodeInfo_Annotation
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:6853
io
GeneratedCodeInfo_Annotation::path_size
int path_size() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:13734
buffer
char buffer[1024]
Definition: libuv/docs/code/idle-compute/main.c:8
google::protobuf::io::MockDescriptor::MockDescriptor
MockDescriptor(const std::string &file, const std::vector< int > &path)
Definition: protobuf/src/google/protobuf/io/printer_unittest.cc:193
google::protobuf::io::Printer
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/printer.h:181
EXPECT_STREQ
#define EXPECT_STREQ(s1, s2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2095
google::protobuf::io::MockDescriptorFile::MockDescriptorFile
MockDescriptorFile(const std::string &file)
Definition: protobuf/src/google/protobuf/io/printer_unittest.cc:180
google::protobuf::io::MockDescriptor::GetLocationPath
void GetLocationPath(std::vector< int > *output) const
Definition: protobuf/src/google/protobuf/io/printer_unittest.cc:204
GeneratedCodeInfo_Annotation::path
::PROTOBUF_NAMESPACE_ID::int32 path(int index) const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:13743
GOOGLE_ARRAYSIZE
#define GOOGLE_ARRAYSIZE(a)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/macros.h:88
GeneratedCodeInfo_Annotation::end
::PROTOBUF_NAMESPACE_ID::int32 end() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:13913
google::protobuf::io::MockDescriptorFile
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/printer_unittest.cc:178
EXPECT_TRUE
#define EXPECT_TRUE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1967
GeneratedCodeInfo
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:7087
google::protobuf::io::MockDescriptor::path_
std::vector< int > path_
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/printer_unittest.cc:207
descriptor
static const char descriptor[1336]
Definition: certs.upbdefs.c:16
google
Definition: bloaty/third_party/protobuf/benchmarks/util/data_proto2_to_proto3_util.h:11
ASSERT_EQ
#define ASSERT_EQ(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2056
GeneratedCodeInfo_Annotation::begin
::PROTOBUF_NAMESPACE_ID::int32 begin() const
Definition: bloaty/third_party/protobuf/src/google/protobuf/descriptor.pb.h:13885


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:45