诸暨麻将添加redis
您不能選擇超過 %s 個話題 話題必須以字母或數字為開頭,可包含連接號 ('-') 且最長為 35 個字
 
 
 
 
 
 

736 行
24 KiB

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