printer_unittest.cc revision fbaaef999ba563838ebd00874ed8a1c01fbf286d
1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// http://code.google.com/p/protobuf/ 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are 7// met: 8// 9// * Redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above 12// copyright notice, this list of conditions and the following disclaimer 13// in the documentation and/or other materials provided with the 14// distribution. 15// * Neither the name of Google Inc. nor the names of its 16// contributors may be used to endorse or promote products derived from 17// this software without specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31// Author: kenton@google.com (Kenton Varda) 32// Based on original Protocol Buffers design by 33// Sanjay Ghemawat, Jeff Dean, and others. 34 35#include <vector> 36 37#include <google/protobuf/io/printer.h> 38#include <google/protobuf/io/zero_copy_stream_impl.h> 39 40#include <google/protobuf/stubs/common.h> 41#include <google/protobuf/testing/googletest.h> 42#include <gtest/gtest.h> 43 44namespace google { 45namespace protobuf { 46namespace io { 47namespace { 48 49// Each test repeats over several block sizes in order to test both cases 50// where particular writes cross a buffer boundary and cases where they do 51// not. 52 53TEST(Printer, EmptyPrinter) { 54 char buffer[8192]; 55 const int block_size = 100; 56 ArrayOutputStream output(buffer, GOOGLE_ARRAYSIZE(buffer), block_size); 57 Printer printer(&output, '\0'); 58 EXPECT_TRUE(!printer.failed()); 59} 60 61TEST(Printer, BasicPrinting) { 62 char buffer[8192]; 63 64 for (int block_size = 1; block_size < 512; block_size *= 2) { 65 ArrayOutputStream output(buffer, sizeof(buffer), block_size); 66 67 { 68 Printer printer(&output, '\0'); 69 70 printer.Print("Hello World!"); 71 printer.Print(" This is the same line.\n"); 72 printer.Print("But this is a new one.\nAnd this is another one."); 73 74 EXPECT_FALSE(printer.failed()); 75 } 76 77 buffer[output.ByteCount()] = '\0'; 78 79 EXPECT_STREQ(buffer, 80 "Hello World! This is the same line.\n" 81 "But this is a new one.\n" 82 "And this is another one."); 83 } 84} 85 86TEST(Printer, VariableSubstitution) { 87 char buffer[8192]; 88 89 for (int block_size = 1; block_size < 512; block_size *= 2) { 90 ArrayOutputStream output(buffer, sizeof(buffer), block_size); 91 92 { 93 Printer printer(&output, '$'); 94 map<string, string> vars; 95 96 vars["foo"] = "World"; 97 vars["bar"] = "$foo$"; 98 vars["abcdefg"] = "1234"; 99 100 printer.Print(vars, "Hello $foo$!\nbar = $bar$\n"); 101 printer.Print(vars, "$abcdefg$\nA literal dollar sign: $$"); 102 103 vars["foo"] = "blah"; 104 printer.Print(vars, "\nNow foo = $foo$."); 105 106 EXPECT_FALSE(printer.failed()); 107 } 108 109 buffer[output.ByteCount()] = '\0'; 110 111 EXPECT_STREQ(buffer, 112 "Hello World!\n" 113 "bar = $foo$\n" 114 "1234\n" 115 "A literal dollar sign: $\n" 116 "Now foo = blah."); 117 } 118} 119 120TEST(Printer, InlineVariableSubstitution) { 121 char buffer[8192]; 122 123 ArrayOutputStream output(buffer, sizeof(buffer)); 124 125 { 126 Printer printer(&output, '$'); 127 printer.Print("Hello $foo$!\n", "foo", "World"); 128 printer.Print("$foo$ $bar$\n", "foo", "one", "bar", "two"); 129 EXPECT_FALSE(printer.failed()); 130 } 131 132 buffer[output.ByteCount()] = '\0'; 133 134 EXPECT_STREQ(buffer, 135 "Hello World!\n" 136 "one two\n"); 137} 138 139TEST(Printer, Indenting) { 140 char buffer[8192]; 141 142 for (int block_size = 1; block_size < 512; block_size *= 2) { 143 ArrayOutputStream output(buffer, sizeof(buffer), block_size); 144 145 { 146 Printer printer(&output, '$'); 147 map<string, string> vars; 148 149 vars["newline"] = "\n"; 150 151 printer.Print("This is not indented.\n"); 152 printer.Indent(); 153 printer.Print("This is indented\nAnd so is this\n"); 154 printer.Outdent(); 155 printer.Print("But this is not."); 156 printer.Indent(); 157 printer.Print(" And this is still the same line.\n" 158 "But this is indented.\n"); 159 printer.Print(vars, "Note that a newline in a variable will break " 160 "indenting, as we see$newline$here.\n"); 161 printer.Indent(); 162 printer.Print("And this"); 163 printer.Outdent(); 164 printer.Outdent(); 165 printer.Print(" is double-indented\nBack to normal."); 166 167 EXPECT_FALSE(printer.failed()); 168 } 169 170 buffer[output.ByteCount()] = '\0'; 171 172 EXPECT_STREQ(buffer, 173 "This is not indented.\n" 174 " This is indented\n" 175 " And so is this\n" 176 "But this is not. And this is still the same line.\n" 177 " But this is indented.\n" 178 " Note that a newline in a variable will break indenting, as we see\n" 179 "here.\n" 180 " And this is double-indented\n" 181 "Back to normal."); 182 } 183} 184 185// Death tests do not work on Windows as of yet. 186#ifdef GTEST_HAS_DEATH_TEST 187TEST(Printer, Death) { 188 char buffer[8192]; 189 190 ArrayOutputStream output(buffer, sizeof(buffer)); 191 Printer printer(&output, '$'); 192 193 EXPECT_DEBUG_DEATH(printer.Print("$nosuchvar$"), "Undefined variable"); 194 EXPECT_DEBUG_DEATH(printer.Print("$unclosed"), "Unclosed variable name"); 195 EXPECT_DEBUG_DEATH(printer.Outdent(), "without matching Indent"); 196} 197#endif // GTEST_HAS_DEATH_TEST 198 199TEST(Printer, WriteFailure) { 200 char buffer[16]; 201 202 ArrayOutputStream output(buffer, sizeof(buffer)); 203 Printer printer(&output, '$'); 204 205 // Print 16 bytes to fill the buffer exactly (should not fail). 206 printer.Print("0123456789abcdef"); 207 EXPECT_FALSE(printer.failed()); 208 209 // Try to print one more byte (should fail). 210 printer.Print(" "); 211 EXPECT_TRUE(printer.failed()); 212 213 // Should not crash 214 printer.Print("blah"); 215 EXPECT_TRUE(printer.failed()); 216 217 // Buffer should contain the first 16 bytes written. 218 EXPECT_EQ("0123456789abcdef", string(buffer, sizeof(buffer))); 219} 220 221} // namespace 222} // namespace io 223} // namespace protobuf 224} // namespace google 225