1 // Copyright 2012 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/text/table.hpp" 30 31 #include <algorithm> 32 33 #include <atf-c++.hpp> 34 35 #include "utils/text/operations.ipp" 36 37 namespace text = utils::text; 38 39 40 /// Performs a check on text::table_formatter. 41 /// 42 /// This is provided for test simplicity's sake. Having to match the result of 43 /// the formatting on a line by line basis would result in too verbose tests 44 /// (maybe not with C++11, but not using this yet). 45 /// 46 /// Because of the flattening of the formatted table into a string, we risk 47 /// misdetecting problems when the algorithm bundles newlines into the lines of 48 /// a table. This should not happen, and not accounting for this little detail 49 /// makes testing so much easier. 50 /// 51 /// \param expected Textual representation of the table, as a collection of 52 /// lines separated by newline characters. 53 /// \param formatter The formatter to use. 54 /// \param table The table to format. 55 static void 56 table_formatter_check(const std::string& expected, 57 const text::table_formatter& formatter, 58 const text::table& table) 59 { 60 ATF_REQUIRE_EQ(expected, text::join(formatter.format(table), "\n") + "\n"); 61 } 62 63 64 65 ATF_TEST_CASE_WITHOUT_HEAD(table__ncolumns); 66 ATF_TEST_CASE_BODY(table__ncolumns) 67 { 68 ATF_REQUIRE_EQ(5, text::table(5).ncolumns()); 69 ATF_REQUIRE_EQ(10, text::table(10).ncolumns()); 70 } 71 72 73 ATF_TEST_CASE_WITHOUT_HEAD(table__column_width); 74 ATF_TEST_CASE_BODY(table__column_width) 75 { 76 text::table_row row1; 77 row1.push_back("1234"); 78 row1.push_back("123456"); 79 text::table_row row2; 80 row2.push_back("12"); 81 row2.push_back("12345678"); 82 83 text::table table(2); 84 table.add_row(row1); 85 table.add_row(row2); 86 87 ATF_REQUIRE_EQ(4, table.column_width(0)); 88 ATF_REQUIRE_EQ(8, table.column_width(1)); 89 } 90 91 92 ATF_TEST_CASE_WITHOUT_HEAD(table__column_widths); 93 ATF_TEST_CASE_BODY(table__column_widths) 94 { 95 text::table_row row1; 96 row1.push_back("1234"); 97 row1.push_back("123456"); 98 text::table_row row2; 99 row2.push_back("12"); 100 row2.push_back("12345678"); 101 102 text::table table(2); 103 table.add_row(row1); 104 table.add_row(row2); 105 106 ATF_REQUIRE_EQ(4, table.column_widths()[0]); 107 ATF_REQUIRE_EQ(8, table.column_widths()[1]); 108 } 109 110 111 ATF_TEST_CASE_WITHOUT_HEAD(table__empty); 112 ATF_TEST_CASE_BODY(table__empty) 113 { 114 text::table table(2); 115 ATF_REQUIRE(table.empty()); 116 table.add_row(text::table_row(2)); 117 ATF_REQUIRE(!table.empty()); 118 } 119 120 121 ATF_TEST_CASE_WITHOUT_HEAD(table__iterate); 122 ATF_TEST_CASE_BODY(table__iterate) 123 { 124 text::table_row row1; 125 row1.push_back("foo"); 126 text::table_row row2; 127 row2.push_back("bar"); 128 129 text::table table(1); 130 table.add_row(row1); 131 table.add_row(row2); 132 133 text::table::const_iterator iter = table.begin(); 134 ATF_REQUIRE(iter != table.end()); 135 ATF_REQUIRE(row1 == *iter); 136 ++iter; 137 ATF_REQUIRE(iter != table.end()); 138 ATF_REQUIRE(row2 == *iter); 139 ++iter; 140 ATF_REQUIRE(iter == table.end()); 141 } 142 143 144 ATF_TEST_CASE_WITHOUT_HEAD(table_formatter__empty); 145 ATF_TEST_CASE_BODY(table_formatter__empty) 146 { 147 ATF_REQUIRE(text::table_formatter().set_separator(" ") 148 .format(text::table(1)).empty()); 149 ATF_REQUIRE(text::table_formatter().set_separator(" ") 150 .format(text::table(10)).empty()); 151 } 152 153 154 ATF_TEST_CASE_WITHOUT_HEAD(table_formatter__defaults); 155 ATF_TEST_CASE_BODY(table_formatter__defaults) 156 { 157 text::table table(3); 158 { 159 text::table_row row; 160 row.push_back("First"); 161 row.push_back("Second"); 162 row.push_back("Third"); 163 table.add_row(row); 164 } 165 { 166 text::table_row row; 167 row.push_back("Fourth with some text"); 168 row.push_back("Fifth with some more text"); 169 row.push_back("Sixth foo"); 170 table.add_row(row); 171 } 172 173 table_formatter_check( 174 "First Second Third\n" 175 "Fourth with some textFifth with some more textSixth foo\n", 176 text::table_formatter(), table); 177 } 178 179 180 ATF_TEST_CASE_WITHOUT_HEAD(table_formatter__one_column__no_max_width); 181 ATF_TEST_CASE_BODY(table_formatter__one_column__no_max_width) 182 { 183 text::table table(1); 184 { 185 text::table_row row; 186 row.push_back("First row with some words"); 187 table.add_row(row); 188 } 189 { 190 text::table_row row; 191 row.push_back("Second row with some words"); 192 table.add_row(row); 193 } 194 195 table_formatter_check( 196 "First row with some words\n" 197 "Second row with some words\n", 198 text::table_formatter().set_separator(" | "), table); 199 } 200 201 202 ATF_TEST_CASE_WITHOUT_HEAD(table_formatter__one_column__explicit_width); 203 ATF_TEST_CASE_BODY(table_formatter__one_column__explicit_width) 204 { 205 text::table table(1); 206 { 207 text::table_row row; 208 row.push_back("First row with some words"); 209 table.add_row(row); 210 } 211 { 212 text::table_row row; 213 row.push_back("Second row with some words"); 214 table.add_row(row); 215 } 216 217 table_formatter_check( 218 "First row with some words\n" 219 "Second row with some words\n", 220 text::table_formatter().set_separator(" | ").set_column_width(0, 1024), 221 table); 222 } 223 224 225 ATF_TEST_CASE_WITHOUT_HEAD(table_formatter__one_column__max_width); 226 ATF_TEST_CASE_BODY(table_formatter__one_column__max_width) 227 { 228 text::table table(1); 229 { 230 text::table_row row; 231 row.push_back("First row with some words"); 232 table.add_row(row); 233 } 234 { 235 text::table_row row; 236 row.push_back("Second row with some words"); 237 table.add_row(row); 238 } 239 240 table_formatter_check( 241 "First row\nwith some\nwords\n" 242 "Second row\nwith some\nwords\n", 243 text::table_formatter().set_separator(" | ").set_table_width(11), 244 table); 245 } 246 247 248 ATF_TEST_CASE_WITHOUT_HEAD(table_formatter__many_columns__no_max_width); 249 ATF_TEST_CASE_BODY(table_formatter__many_columns__no_max_width) 250 { 251 text::table table(3); 252 { 253 text::table_row row; 254 row.push_back("First"); 255 row.push_back("Second"); 256 row.push_back("Third"); 257 table.add_row(row); 258 } 259 { 260 text::table_row row; 261 row.push_back("Fourth with some text"); 262 row.push_back("Fifth with some more text"); 263 row.push_back("Sixth foo"); 264 table.add_row(row); 265 } 266 267 table_formatter_check( 268 "First | Second | Third\n" 269 "Fourth with some text | Fifth with some more text | Sixth foo\n", 270 text::table_formatter().set_separator(" | "), table); 271 } 272 273 274 ATF_TEST_CASE_WITHOUT_HEAD(table_formatter__many_columns__explicit_width); 275 ATF_TEST_CASE_BODY(table_formatter__many_columns__explicit_width) 276 { 277 text::table table(3); 278 { 279 text::table_row row; 280 row.push_back("First"); 281 row.push_back("Second"); 282 row.push_back("Third"); 283 table.add_row(row); 284 } 285 { 286 text::table_row row; 287 row.push_back("Fourth with some text"); 288 row.push_back("Fifth with some more text"); 289 row.push_back("Sixth foo"); 290 table.add_row(row); 291 } 292 293 table_formatter_check( 294 "First | Second | Third\n" 295 "Fourth with some text | Fifth with some more text | Sixth foo\n", 296 text::table_formatter().set_separator(" | ").set_column_width(0, 23) 297 .set_column_width(1, 28), table); 298 } 299 300 301 ATF_TEST_CASE_WITHOUT_HEAD(table_formatter__many_columns__max_width); 302 ATF_TEST_CASE_BODY(table_formatter__many_columns__max_width) 303 { 304 text::table table(3); 305 { 306 text::table_row row; 307 row.push_back("First"); 308 row.push_back("Second"); 309 row.push_back("Third"); 310 table.add_row(row); 311 } 312 { 313 text::table_row row; 314 row.push_back("Fourth with some text"); 315 row.push_back("Fifth with some more text"); 316 row.push_back("Sixth foo"); 317 table.add_row(row); 318 } 319 320 table_formatter_check( 321 "First | Second | Third\n" 322 "Fourth with some text | Fifth with | Sixth foo\n" 323 " | some more | \n" 324 " | text | \n", 325 text::table_formatter().set_separator(" | ").set_table_width(46) 326 .set_column_width(1, text::table_formatter::width_refill) 327 .set_column_width(0, text::table_formatter::width_auto), table); 328 329 table_formatter_check( 330 "First | Second | Third\n" 331 "Fourth with some text | Fifth with | Sixth foo\n" 332 " | some more | \n" 333 " | text | \n", 334 text::table_formatter().set_separator(" | ").set_table_width(48) 335 .set_column_width(1, text::table_formatter::width_refill) 336 .set_column_width(0, 23), table); 337 } 338 339 340 ATF_TEST_CASE_WITHOUT_HEAD(table_formatter__use_case__cli_help); 341 ATF_TEST_CASE_BODY(table_formatter__use_case__cli_help) 342 { 343 text::table options_table(2); 344 { 345 text::table_row row; 346 row.push_back("-a a_value"); 347 row.push_back("This is the description of the first flag"); 348 options_table.add_row(row); 349 } 350 { 351 text::table_row row; 352 row.push_back("-b"); 353 row.push_back("And this is the text for the second flag"); 354 options_table.add_row(row); 355 } 356 357 text::table commands_table(2); 358 { 359 text::table_row row; 360 row.push_back("first"); 361 row.push_back("This is the first command"); 362 commands_table.add_row(row); 363 } 364 { 365 text::table_row row; 366 row.push_back("second"); 367 row.push_back("And this is the second command"); 368 commands_table.add_row(row); 369 } 370 371 const text::widths_vector::value_type first_width = 372 std::max(options_table.column_width(0), commands_table.column_width(0)); 373 374 table_formatter_check( 375 "-a a_value This is the description\n" 376 " of the first flag\n" 377 "-b And this is the text for\n" 378 " the second flag\n", 379 text::table_formatter().set_separator(" ").set_table_width(36) 380 .set_column_width(0, first_width) 381 .set_column_width(1, text::table_formatter::width_refill), 382 options_table); 383 384 table_formatter_check( 385 "first This is the first\n" 386 " command\n" 387 "second And this is the second\n" 388 " command\n", 389 text::table_formatter().set_separator(" ").set_table_width(36) 390 .set_column_width(0, first_width) 391 .set_column_width(1, text::table_formatter::width_refill), 392 commands_table); 393 } 394 395 396 ATF_INIT_TEST_CASES(tcs) 397 { 398 ATF_ADD_TEST_CASE(tcs, table__ncolumns); 399 ATF_ADD_TEST_CASE(tcs, table__column_width); 400 ATF_ADD_TEST_CASE(tcs, table__column_widths); 401 ATF_ADD_TEST_CASE(tcs, table__empty); 402 ATF_ADD_TEST_CASE(tcs, table__iterate); 403 404 ATF_ADD_TEST_CASE(tcs, table_formatter__empty); 405 ATF_ADD_TEST_CASE(tcs, table_formatter__defaults); 406 ATF_ADD_TEST_CASE(tcs, table_formatter__one_column__no_max_width); 407 ATF_ADD_TEST_CASE(tcs, table_formatter__one_column__explicit_width); 408 ATF_ADD_TEST_CASE(tcs, table_formatter__one_column__max_width); 409 ATF_ADD_TEST_CASE(tcs, table_formatter__many_columns__no_max_width); 410 ATF_ADD_TEST_CASE(tcs, table_formatter__many_columns__explicit_width); 411 ATF_ADD_TEST_CASE(tcs, table_formatter__many_columns__max_width); 412 ATF_ADD_TEST_CASE(tcs, table_formatter__use_case__cli_help); 413 } 414