1// Copyright 2010 The Kyua Authors. 2// All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions are 6// met: 7// 8// * Redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer. 10// * Redistributions in binary form must reproduce the above copyright 11// notice, this list of conditions and the following disclaimer in the 12// documentation and/or other materials provided with the distribution. 13// * Neither the name of Google Inc. nor the names of its contributors 14// may be used to endorse or promote products derived from this software 15// without specific prior written permission. 16// 17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29#include "utils/format/formatter.hpp" 30 31#include <ostream> 32 33#include <atf-c++.hpp> 34 35#include "utils/format/exceptions.hpp" 36#include "utils/format/macros.hpp" 37 38namespace format = utils::format; 39 40 41namespace { 42 43 44/// Wraps an integer in a C++ class. 45/// 46/// This custom type exists to ensure that we can feed arbitrary objects that 47/// support operator<< to the formatter; 48class int_wrapper { 49 /// The wrapped integer. 50 int _value; 51 52public: 53 /// Constructs a new wrapper. 54 /// 55 /// \param value_ The value to wrap. 56 int_wrapper(const int value_) : _value(value_) 57 { 58 } 59 60 /// Returns the wrapped value. 61 /// 62 /// \return An integer. 63 int 64 value(void) const 65 { 66 return _value; 67 } 68}; 69 70 71/// Writes a wrapped integer into an output stream. 72/// 73/// \param output The output stream into which to place the integer. 74/// \param wrapper The wrapped integer. 75/// 76/// \return The output stream. 77std::ostream& 78operator<<(std::ostream& output, const int_wrapper& wrapper) 79{ 80 return (output << wrapper.value()); 81} 82 83 84} // anonymous namespace 85 86 87/// Calls ATF_REQUIRE_EQ on an expected string and a formatter. 88/// 89/// This is pure syntactic sugar to avoid calling the str() method on all the 90/// individual tests below, which results in very long lines that require 91/// wrapping and clutter readability. 92/// 93/// \param expected The expected string generated by the formatter. 94/// \param formatter The formatter to test. 95#define EQ(expected, formatter) ATF_REQUIRE_EQ(expected, (formatter).str()) 96 97 98ATF_TEST_CASE_WITHOUT_HEAD(no_fields); 99ATF_TEST_CASE_BODY(no_fields) 100{ 101 EQ("Plain string", F("Plain string")); 102} 103 104 105ATF_TEST_CASE_WITHOUT_HEAD(one_field); 106ATF_TEST_CASE_BODY(one_field) 107{ 108 EQ("foo", F("%sfoo") % ""); 109 EQ(" foo", F("%sfoo") % " "); 110 EQ("foo ", F("foo %s") % ""); 111 EQ("foo bar", F("foo %s") % "bar"); 112 EQ("foo bar baz", F("foo %s baz") % "bar"); 113 EQ("foo %s %s", F("foo %s %s") % "%s" % "%s"); 114} 115 116 117ATF_TEST_CASE_WITHOUT_HEAD(many_fields); 118ATF_TEST_CASE_BODY(many_fields) 119{ 120 EQ("", F("%s%s") % "" % ""); 121 EQ("foo", F("%s%s%s") % "" % "foo" % ""); 122 EQ("some 5 text", F("%s %s %s") % "some" % 5 % "text"); 123 EQ("f%s 5 text", F("%s %s %s") % "f%s" % 5 % "text"); 124} 125 126 127ATF_TEST_CASE_WITHOUT_HEAD(escape); 128ATF_TEST_CASE_BODY(escape) 129{ 130 EQ("%", F("%%")); 131 EQ("% %", F("%% %%")); 132 EQ("%% %%", F("%%%% %%%%")); 133 134 EQ("foo %", F("foo %%")); 135 EQ("foo bar %", F("foo %s %%") % "bar"); 136 EQ("foo % bar", F("foo %% %s") % "bar"); 137 138 EQ("foo %%", F("foo %s") % "%%"); 139 EQ("foo a%%b", F("foo a%sb") % "%%"); 140 EQ("foo a%%b", F("foo %s") % "a%%b"); 141 142 EQ("foo % bar %%", F("foo %% %s %%%%") % "bar"); 143} 144 145 146ATF_TEST_CASE_WITHOUT_HEAD(extra_args_error); 147ATF_TEST_CASE_BODY(extra_args_error) 148{ 149 using format::extra_args_error; 150 151 ATF_REQUIRE_THROW(extra_args_error, F("foo") % "bar"); 152 ATF_REQUIRE_THROW(extra_args_error, F("foo %%") % "bar"); 153 ATF_REQUIRE_THROW(extra_args_error, F("foo %s") % "bar" % "baz"); 154 ATF_REQUIRE_THROW(extra_args_error, F("foo %s") % "%s" % "bar"); 155 ATF_REQUIRE_THROW(extra_args_error, F("%s foo %s") % "bar" % "baz" % "foo"); 156 157 try { 158 F("foo %s %s") % "bar" % "baz" % "something extra"; 159 fail("extra_args_error not raised"); 160 } catch (const extra_args_error& e) { 161 ATF_REQUIRE_EQ("foo %s %s", e.format()); 162 ATF_REQUIRE_EQ("something extra", e.arg()); 163 } 164} 165 166 167ATF_TEST_CASE_WITHOUT_HEAD(format__class); 168ATF_TEST_CASE_BODY(format__class) 169{ 170 EQ("foo bar", F("%s") % std::string("foo bar")); 171 EQ("3", F("%s") % int_wrapper(3)); 172} 173 174 175ATF_TEST_CASE_WITHOUT_HEAD(format__pointer); 176ATF_TEST_CASE_BODY(format__pointer) 177{ 178 EQ("0xcafebabe", F("%s") % reinterpret_cast< void* >(0xcafebabe)); 179 EQ("foo bar", F("%s") % "foo bar"); 180} 181 182 183ATF_TEST_CASE_WITHOUT_HEAD(format__bool); 184ATF_TEST_CASE_BODY(format__bool) 185{ 186 EQ("true", F("%s") % true); 187 EQ("false", F("%s") % false); 188} 189 190 191ATF_TEST_CASE_WITHOUT_HEAD(format__char); 192ATF_TEST_CASE_BODY(format__char) 193{ 194 EQ("Z", F("%s") % 'Z'); 195} 196 197 198ATF_TEST_CASE_WITHOUT_HEAD(format__float); 199ATF_TEST_CASE_BODY(format__float) 200{ 201 EQ("3", F("%s") % 3.0); 202 EQ("3.0", F("%.1s") % 3.0); 203 EQ("3.0", F("%0.1s") % 3.0); 204 EQ(" 15.600", F("%8.3s") % 15.6); 205 EQ("01.52", F("%05.2s") % 1.52); 206} 207 208 209ATF_TEST_CASE_WITHOUT_HEAD(format__int); 210ATF_TEST_CASE_BODY(format__int) 211{ 212 EQ("3", F("%s") % 3); 213 EQ("3", F("%0s") % 3); 214 EQ(" -123", F("%5s") % -123); 215 EQ("00078", F("%05s") % 78); 216} 217 218 219ATF_TEST_CASE_WITHOUT_HEAD(format__error); 220ATF_TEST_CASE_BODY(format__error) 221{ 222 using format::bad_format_error; 223 224 ATF_REQUIRE_THROW_RE(bad_format_error, "Trailing %", F("%")); 225 ATF_REQUIRE_THROW_RE(bad_format_error, "Trailing %", F("f%")); 226 ATF_REQUIRE_THROW_RE(bad_format_error, "Trailing %", F("f%%%")); 227 ATF_REQUIRE_THROW_RE(bad_format_error, "Trailing %", F("ab %s cd%") % "cd"); 228 229 ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid width", F("%1bs")); 230 231 ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid precision", F("%.s")); 232 ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid precision", F("%0.s")); 233 ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid precision", F("%123.s")); 234 ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid precision", F("%.12bs")); 235 236 ATF_REQUIRE_THROW_RE(bad_format_error, "Unterminated", F("%c") % 'Z'); 237 ATF_REQUIRE_THROW_RE(bad_format_error, "Unterminated", F("%d") % 5); 238 ATF_REQUIRE_THROW_RE(bad_format_error, "Unterminated", F("%.1f") % 3); 239 ATF_REQUIRE_THROW_RE(bad_format_error, "Unterminated", F("%d%s") % 3 % "a"); 240 241 try { 242 F("foo %s%") % "bar"; 243 fail("bad_format_error not raised"); 244 } catch (const bad_format_error& e) { 245 ATF_REQUIRE_EQ("foo %s%", e.format()); 246 } 247} 248 249 250ATF_INIT_TEST_CASES(tcs) 251{ 252 ATF_ADD_TEST_CASE(tcs, no_fields); 253 ATF_ADD_TEST_CASE(tcs, one_field); 254 ATF_ADD_TEST_CASE(tcs, many_fields); 255 ATF_ADD_TEST_CASE(tcs, escape); 256 ATF_ADD_TEST_CASE(tcs, extra_args_error); 257 258 ATF_ADD_TEST_CASE(tcs, format__class); 259 ATF_ADD_TEST_CASE(tcs, format__pointer); 260 ATF_ADD_TEST_CASE(tcs, format__bool); 261 ATF_ADD_TEST_CASE(tcs, format__char); 262 ATF_ADD_TEST_CASE(tcs, format__float); 263 ATF_ADD_TEST_CASE(tcs, format__int); 264 ATF_ADD_TEST_CASE(tcs, format__error); 265} 266