gout

A static git page generator
git clone https://git.bracken.jp/gout.git
Log | Files | Refs | README | LICENSE

format_tests.c (15574B)


      1 #include "format.h"
      2 
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <time.h>
      6 
      7 #include "utest.h"
      8 
      9 UTEST(print_time, PositiveOffset) {
     10   char* buf = NULL;
     11   size_t size = 0;
     12   FILE* out = open_memstream(&buf, &size);
     13   ASSERT_NE(NULL, out);
     14 
     15   /* Test time: 2023-12-08 10:30:00 UTC */
     16   time_t test_time = 1702031400;
     17   int timezone_offset = 540; /* +09:00 */
     18 
     19   print_time(out, test_time, timezone_offset);
     20   fclose(out);
     21 
     22   EXPECT_STREQ("Fri,  8 Dec 2023 19:30:00 +0900", buf);
     23 
     24   free(buf);
     25 }
     26 
     27 UTEST(print_time, NegativeOffset) {
     28   char* buf = NULL;
     29   size_t size = 0;
     30   FILE* out = open_memstream(&buf, &size);
     31   ASSERT_NE(NULL, out);
     32 
     33   /* Test time: 2023-12-08 10:30:00 UTC */
     34   time_t test_time = 1702031400;
     35   int timezone_offset = -300; /* -05:00 */
     36 
     37   print_time(out, test_time, timezone_offset);
     38   fclose(out);
     39 
     40   EXPECT_STREQ("Fri,  8 Dec 2023 05:30:00 -0500", buf);
     41 
     42   free(buf);
     43 }
     44 
     45 UTEST(print_time, ZeroOffset) {
     46   char* buf = NULL;
     47   size_t size = 0;
     48   FILE* out = open_memstream(&buf, &size);
     49   ASSERT_NE(NULL, out);
     50 
     51   /* Test time: 2023-12-08 10:30:00 UTC */
     52   time_t test_time = 1702031400;
     53   int timezone_offset = 0; /* UTC */
     54 
     55   print_time(out, test_time, timezone_offset);
     56   fclose(out);
     57 
     58   EXPECT_STREQ("Fri,  8 Dec 2023 10:30:00 +0000", buf);
     59 
     60   free(buf);
     61 }
     62 
     63 UTEST(print_time, IllegalOffset) {
     64   char* buf = NULL;
     65   size_t size = 0;
     66   FILE* out = open_memstream(&buf, &size);
     67   ASSERT_NE(NULL, out);
     68 
     69   /* Test time: 2023-12-08 10:30:00 UTC */
     70   time_t test_time = 1702031400;
     71   int timezone_offset = 1441; /* 24 hours + 1 minute */
     72 
     73   print_time(out, test_time, timezone_offset);
     74   fclose(out);
     75 
     76   EXPECT_STREQ("", buf);
     77 
     78   free(buf);
     79 }
     80 
     81 UTEST(print_time_z, Basic) {
     82   char* buf = NULL;
     83   size_t size = 0;
     84   FILE* out = open_memstream(&buf, &size);
     85   ASSERT_NE(NULL, out);
     86 
     87   /* Test time: 2023-12-08 10:30:00 UTC */
     88   time_t test_time = 1702031400;
     89 
     90   print_time_z(out, test_time);
     91   fclose(out);
     92 
     93   EXPECT_STREQ("2023-12-08T10:30:00Z", buf);
     94 
     95   free(buf);
     96 }
     97 
     98 UTEST(print_time_short, Basic) {
     99   char* buf = NULL;
    100   size_t size = 0;
    101   FILE* out = open_memstream(&buf, &size);
    102   ASSERT_NE(NULL, out);
    103 
    104   /* Test time: 2023-12-08 10:30:00 UTC */
    105   time_t test_time = 1702031400;
    106 
    107   print_time_short(out, test_time);
    108   fclose(out);
    109 
    110   EXPECT_STREQ("2023-12-08 10:30", buf);
    111 
    112   free(buf);
    113 }
    114 
    115 UTEST(print_percent_encoded, NoEncoding) {
    116   char* buf = NULL;
    117   size_t size = 0;
    118   FILE* out = open_memstream(&buf, &size);
    119   ASSERT_NE(NULL, out);
    120 
    121   print_percent_encoded(out, "abcdef-1234/.,");
    122   fclose(out);
    123 
    124   EXPECT_STREQ("abcdef-1234/.,", buf);
    125 
    126   free(buf);
    127 }
    128 
    129 UTEST(print_percent_encoded, SimpleEncoding) {
    130   char* buf = NULL;
    131   size_t size = 0;
    132   FILE* out = open_memstream(&buf, &size);
    133   ASSERT_NE(NULL, out);
    134 
    135   print_percent_encoded(out, "hello world");
    136   fclose(out);
    137 
    138   EXPECT_STREQ("hello%20world", buf);
    139 
    140   free(buf);
    141 }
    142 
    143 UTEST(print_percent_encoded, ReservedChars) {
    144   char* buf = NULL;
    145   size_t size = 0;
    146   FILE* out = open_memstream(&buf, &size);
    147   ASSERT_NE(NULL, out);
    148 
    149   print_percent_encoded(out, " \"%[]:?@");
    150   fclose(out);
    151 
    152   EXPECT_STREQ("%20%22%25%5B%5D%3A%3F%40", buf);
    153 
    154   free(buf);
    155 }
    156 
    157 UTEST(print_percent_encoded, EmptyString) {
    158   char* buf = NULL;
    159   size_t size = 0;
    160   FILE* out = open_memstream(&buf, &size);
    161   ASSERT_NE(NULL, out);
    162 
    163   print_percent_encoded(out, "");
    164   fclose(out);
    165 
    166   EXPECT_STREQ("", buf);
    167 
    168   free(buf);
    169 }
    170 
    171 UTEST(print_xml_encoded_len, FullEncoding) {
    172   char* buf = NULL;
    173   size_t size = 0;
    174   FILE* out = open_memstream(&buf, &size);
    175   ASSERT_NE(NULL, out);
    176 
    177   const char* test_str = "<tag attr='value'> & \"text\"";
    178   print_xml_encoded_len(out, test_str, -1, true);
    179   fclose(out);
    180 
    181   EXPECT_STREQ("&lt;tag attr=&#39;value&#39;&gt; &amp; &quot;text&quot;", buf);
    182 
    183   free(buf);
    184 }
    185 
    186 UTEST(print_xml_encoded_len, PartialEncoding) {
    187   char* buf = NULL;
    188   size_t size = 0;
    189   FILE* out = open_memstream(&buf, &size);
    190   ASSERT_NE(NULL, out);
    191 
    192   const char* test_str = "<tag>hello</tag>";
    193   print_xml_encoded_len(out, test_str, 5, true);
    194   fclose(out);
    195 
    196   EXPECT_STREQ("&lt;tag&gt;", buf);
    197 
    198   free(buf);
    199 }
    200 
    201 UTEST(print_xml_encoded_len, WithCrlf) {
    202   char* buf = NULL;
    203   size_t size = 0;
    204   FILE* out = open_memstream(&buf, &size);
    205   ASSERT_NE(NULL, out);
    206 
    207   const char* test_str = "line1\r\nline2";
    208   print_xml_encoded_len(out, test_str, -1, true);
    209   fclose(out);
    210 
    211   EXPECT_STREQ("line1\r\nline2", buf);
    212 
    213   free(buf);
    214 }
    215 
    216 UTEST(print_xml_encoded_len, WithoutCrlf) {
    217   char* buf = NULL;
    218   size_t size = 0;
    219   FILE* out = open_memstream(&buf, &size);
    220   ASSERT_NE(NULL, out);
    221 
    222   const char* test_str = "line1\r\nline2";
    223   print_xml_encoded_len(out, test_str, -1, false);
    224   fclose(out);
    225 
    226   EXPECT_STREQ("line1line2", buf);
    227 
    228   free(buf);
    229 }
    230 
    231 UTEST(print_xml_encoded_len, EmptyString) {
    232   char* buf = NULL;
    233   size_t size = 0;
    234   FILE* out = open_memstream(&buf, &size);
    235   ASSERT_NE(NULL, out);
    236 
    237   print_xml_encoded_len(out, "", -1, true);
    238   fclose(out);
    239 
    240   EXPECT_STREQ("", buf);
    241 
    242   free(buf);
    243 }
    244 
    245 UTEST(print_xml_encoded_len, ZeroLength) {
    246   char* buf = NULL;
    247   size_t size = 0;
    248   FILE* out = open_memstream(&buf, &size);
    249   ASSERT_NE(NULL, out);
    250 
    251   print_xml_encoded_len(out, "some text", 0, true);
    252   fclose(out);
    253 
    254   EXPECT_STREQ("", buf);
    255 
    256   free(buf);
    257 }
    258 
    259 UTEST(print_xml_encoded_len, ControlCharacters) {
    260   char* buf = NULL;
    261   size_t size = 0;
    262   FILE* out = open_memstream(&buf, &size);
    263   ASSERT_NE(NULL, out);
    264 
    265   /* Tab (\t), LF (\n), CR (\r) should be preserved.
    266    * Other control characters like \x01 (SOH) should be filtered. */
    267   const char* test_str =
    268       "a\t\n\r\x01"
    269       "b";
    270   print_xml_encoded_len(out, test_str, -1, true);
    271   fclose(out);
    272 
    273   EXPECT_STREQ("a\t\n\rb", buf);
    274 
    275   free(buf);
    276 }
    277 
    278 UTEST(print_xml_encoded_len, MultiByteUtf8) {
    279   char* buf = NULL;
    280   size_t size = 0;
    281   FILE* out = open_memstream(&buf, &size);
    282   ASSERT_NE(NULL, out);
    283 
    284   /* UTF-8 'é' is 0xC3 0xA9. These should be preserved as-is. */
    285   const char* test_str = "caf\xC3\xA9";
    286   print_xml_encoded_len(out, test_str, -1, true);
    287   fclose(out);
    288 
    289   EXPECT_STREQ("caf\xC3\xA9", buf);
    290 
    291   free(buf);
    292 }
    293 
    294 UTEST(print_xml_encoded_len, EmbeddedNull) {
    295   char* buf = NULL;
    296   size_t size = 0;
    297   FILE* out = open_memstream(&buf, &size);
    298   ASSERT_NE(NULL, out);
    299 
    300   /* The function should stop at \0 even if str_len is larger. */
    301   const char* test_str = "abc\0def";
    302   print_xml_encoded_len(out, test_str, 10, true);
    303   fclose(out);
    304 
    305   EXPECT_STREQ("abc", buf);
    306 
    307   free(buf);
    308 }
    309 
    310 UTEST(print_gopher_text_len, BasicWithLf) {
    311   char* buf = NULL;
    312   size_t size = 0;
    313   FILE* out = open_memstream(&buf, &size);
    314   ASSERT_NE(NULL, out);
    315 
    316   print_gopher_text_len(out, "hello\nworld", -1, true);
    317   fclose(out);
    318 
    319   EXPECT_STREQ("hello\nworld", buf);
    320 
    321   free(buf);
    322 }
    323 
    324 UTEST(print_gopher_text_len, BasicNoLf) {
    325   char* buf = NULL;
    326   size_t size = 0;
    327   FILE* out = open_memstream(&buf, &size);
    328   ASSERT_NE(NULL, out);
    329 
    330   print_gopher_text_len(out, "hello\nworld\r", -1, false);
    331   fclose(out);
    332 
    333   EXPECT_STREQ("helloworld", buf);
    334 
    335   free(buf);
    336 }
    337 
    338 UTEST(print_gopher_text_len, EscapesWithLf) {
    339   char* buf = NULL;
    340   size_t size = 0;
    341   FILE* out = open_memstream(&buf, &size);
    342   ASSERT_NE(NULL, out);
    343 
    344   print_gopher_text_len(out, "[hello]\n[world]", -1, true);
    345   fclose(out);
    346 
    347   EXPECT_STREQ("[|hello]\n[|world]", buf);
    348 
    349   free(buf);
    350 }
    351 
    352 UTEST(print_gopher_text_len, DoesNotEscapeIfBracketNotImmediatelyAfterLf) {
    353   char* buf = NULL;
    354   size_t size = 0;
    355   FILE* out = open_memstream(&buf, &size);
    356   ASSERT_NE(NULL, out);
    357 
    358   print_gopher_text_len(out, "[hello]\n\t[world]", -1, true);
    359   fclose(out);
    360 
    361   EXPECT_STREQ("[|hello]\n        [world]", buf);
    362 
    363   free(buf);
    364 }
    365 
    366 UTEST(print_gopher_text_len, NoEscapesWithoutLf) {
    367   char* buf = NULL;
    368   size_t size = 0;
    369   FILE* out = open_memstream(&buf, &size);
    370   ASSERT_NE(NULL, out);
    371 
    372   print_gopher_text_len(out, "[hello]\n\t[world]", -1, false);
    373   fclose(out);
    374 
    375   EXPECT_STREQ("[hello]        [world]", buf);
    376 
    377   free(buf);
    378 }
    379 
    380 UTEST(print_gopher_text_len, PartialLen) {
    381   char* buf = NULL;
    382   size_t size = 0;
    383   FILE* out = open_memstream(&buf, &size);
    384   ASSERT_NE(NULL, out);
    385 
    386   print_gopher_text_len(out, "[hello]\n\t[world]", 8, true);
    387   fclose(out);
    388 
    389   EXPECT_STREQ("[|hello]\n", buf);
    390 
    391   free(buf);
    392 }
    393 
    394 UTEST(print_gopher_text_len, EmptyString) {
    395   char* buf = NULL;
    396   size_t size = 0;
    397   FILE* out = open_memstream(&buf, &size);
    398   ASSERT_NE(NULL, out);
    399 
    400   print_gopher_text_len(out, "", -1, true);
    401   fclose(out);
    402 
    403   EXPECT_STREQ("", buf);
    404 
    405   free(buf);
    406 }
    407 
    408 UTEST(print_gopher_link, SpecialChars) {
    409   char* buf = NULL;
    410   size_t size = 0;
    411   FILE* out = open_memstream(&buf, &size);
    412   ASSERT_NE(NULL, out);
    413 
    414   print_gopher_link(out, "|\t\r\n");
    415   fclose(out);
    416 
    417   EXPECT_STREQ("\\|        ", buf);
    418 
    419   free(buf);
    420 }
    421 
    422 UTEST(print_gopher_link, MixedContent) {
    423   char* buf = NULL;
    424   size_t size = 0;
    425   FILE* out = open_memstream(&buf, &size);
    426   ASSERT_NE(NULL, out);
    427 
    428   print_gopher_link(out, "hello|world\t");
    429   fclose(out);
    430 
    431   EXPECT_STREQ("hello\\|world        ", buf);
    432 
    433   free(buf);
    434 }
    435 
    436 UTEST(print_gopher_link, EmptyString) {
    437   char* buf = NULL;
    438   size_t size = 0;
    439   FILE* out = open_memstream(&buf, &size);
    440   ASSERT_NE(NULL, out);
    441 
    442   print_gopher_link(out, "");
    443   fclose(out);
    444 
    445   EXPECT_STREQ("", buf);
    446 
    447   free(buf);
    448 }
    449 
    450 UTEST(print_gopher_link_padded, BasicPadding) {
    451   char* buf = NULL;
    452   size_t size = 0;
    453   FILE* out = open_memstream(&buf, &size);
    454   ASSERT_NE(NULL, out);
    455 
    456   print_gopher_link_padded(out, "hello", 10, ' ');
    457   fclose(out);
    458 
    459   EXPECT_STREQ("hello     ", buf);
    460 
    461   free(buf);
    462 }
    463 
    464 UTEST(print_gopher_link_padded, NoPadding) {
    465   char* buf = NULL;
    466   size_t size = 0;
    467   FILE* out = open_memstream(&buf, &size);
    468   ASSERT_NE(NULL, out);
    469 
    470   print_gopher_link_padded(out, "hello", 5, ' ');
    471   fclose(out);
    472 
    473   EXPECT_STREQ("hello", buf);
    474 
    475   free(buf);
    476 }
    477 
    478 UTEST(print_gopher_link_padded, Truncation) {
    479   char* buf = NULL;
    480   size_t size = 0;
    481   FILE* out = open_memstream(&buf, &size);
    482   ASSERT_NE(NULL, out);
    483 
    484   print_gopher_link_padded(out, "hello world", 10, ' ');
    485   fclose(out);
    486 
    487   EXPECT_STREQ("hello wor…", buf);
    488 
    489   free(buf);
    490 }
    491 
    492 UTEST(print_gopher_link_padded, SpecialChars) {
    493   char* buf = NULL;
    494   size_t size = 0;
    495   FILE* out = open_memstream(&buf, &size);
    496   ASSERT_NE(NULL, out);
    497 
    498   print_gopher_link_padded(out, "a|\t\r\nb", 20, '.');
    499   fclose(out);
    500 
    501   EXPECT_STREQ("a\\|        b.........", buf);
    502 
    503   free(buf);
    504 }
    505 
    506 UTEST(print_gopher_link_padded, MultiByte) {
    507   char* buf = NULL;
    508   size_t size = 0;
    509   FILE* out = open_memstream(&buf, &size);
    510   ASSERT_NE(NULL, out);
    511 
    512   print_gopher_link_padded(out, "こんにちは", 20, ' ');
    513   fclose(out);
    514 
    515   EXPECT_STREQ("こんにちは          ", buf);
    516 
    517   free(buf);
    518 }
    519 
    520 UTEST(print_gopher_link_padded, ZeroWidth) {
    521   char* buf = NULL;
    522   size_t size = 0;
    523   FILE* out = open_memstream(&buf, &size);
    524   ASSERT_NE(NULL, out);
    525 
    526   print_gopher_link_padded(out, "hello", 0, ' ');
    527   fclose(out);
    528 
    529   EXPECT_STREQ("", buf);
    530 
    531   free(buf);
    532 }
    533 
    534 UTEST(print_gopher_link_padded, NoPadChar) {
    535   char* buf = NULL;
    536   size_t size = 0;
    537   FILE* out = open_memstream(&buf, &size);
    538   ASSERT_NE(NULL, out);
    539 
    540   print_gopher_link_padded(out, "hello", 10, '\0');
    541   fclose(out);
    542 
    543   EXPECT_STREQ("hello", buf);
    544 
    545   free(buf);
    546 }
    547 
    548 UTEST(print_gopher_link_padded, ComplexEmoji) {
    549   char* buf = NULL;
    550   size_t size = 0;
    551   FILE* out = open_memstream(&buf, &size);
    552   ASSERT_NE(NULL, out);
    553 
    554   /* UTF-8 encoding of Unicode extended grapheme cluster for woman health worker
    555      with medium-dark skin tone. This emoji is a Unicode emoji ZWJ sequence
    556      composed of 5 code points. */
    557   const char* emoji =     // 👩🏾‍⚕️
    558       "\xF0\x9F\x91\xA9"  // U+1F469: Woman 👩
    559       "\xF0\x9F\x8F\xBE"  // U+1F3FE: Emoji modifier Fitzpatrick type 5 🏾
    560       "\xE2\x80\x8D"      // U+200D: Zero-width joiner
    561       "\xE2\x9A\x95"      // U+2695: Staff of Aesculapius ⚕
    562       "\xEF\xB8\x8F";     // U+FE0F: Variation selector 16 (colour emoji)
    563   print_gopher_link_padded(out, emoji, 10, ' ');
    564   fclose(out);
    565 
    566   /* Expect 1 emoji, 8 spaces. */
    567   EXPECT_STREQ("👩🏾‍⚕️        ", buf);
    568 
    569   free(buf);
    570 }
    571 
    572 UTEST(print_gopher_link_padded, MultiColumnTruncation) {
    573   {
    574     char* buf = NULL;
    575     size_t size = 0;
    576     FILE* out = open_memstream(&buf, &size);
    577     ASSERT_NE(NULL, out);
    578 
    579     /* "あいう" (6 columns). Width 4. Should be "あ…" + 1 space. */
    580     print_gopher_link_padded(out, "あいう", 4, ' ');
    581     fclose(out);
    582     EXPECT_STREQ("あ… ", buf);
    583     free(buf);
    584   }
    585 
    586   {
    587     char* buf = NULL;
    588     size_t size = 0;
    589     FILE* out = open_memstream(&buf, &size);
    590     ASSERT_NE(NULL, out);
    591 
    592     /* "あいう" (6 columns). Width 5. Should be "あい…" (5 columns). */
    593     print_gopher_link_padded(out, "あいう", 5, ' ');
    594     fclose(out);
    595     EXPECT_STREQ("あい…", buf);
    596     free(buf);
    597   }
    598 }
    599 
    600 UTEST(print_utf8_padded, Basic) {
    601   char* buf = NULL;
    602   size_t size = 0;
    603   FILE* out = open_memstream(&buf, &size);
    604   ASSERT_NE(NULL, out);
    605 
    606   print_utf8_padded(out, "hello", 10, ' ');
    607   fclose(out);
    608 
    609   EXPECT_STREQ("hello     ", buf);
    610 
    611   free(buf);
    612 }
    613 
    614 UTEST(print_utf8_padded, MultiByte) {
    615   char* buf = NULL;
    616   size_t size = 0;
    617   FILE* out = open_memstream(&buf, &size);
    618   ASSERT_NE(NULL, out);
    619 
    620   /* "こんにちは" is 10 columns. */
    621   print_utf8_padded(out, "こんにちは", 15, ' ');
    622   fclose(out);
    623 
    624   EXPECT_STREQ("こんにちは     ", buf);
    625 
    626   free(buf);
    627 }
    628 
    629 UTEST(print_utf8_padded, Truncation) {
    630   char* buf = NULL;
    631   size_t size = 0;
    632   FILE* out = open_memstream(&buf, &size);
    633   ASSERT_NE(NULL, out);
    634 
    635   /* "hello world" is 11 columns. Width 10. */
    636   print_utf8_padded(out, "hello world", 10, ' ');
    637   fclose(out);
    638 
    639   EXPECT_STREQ("hello wor…", buf);
    640 
    641   free(buf);
    642 }
    643 
    644 UTEST(print_utf8_padded, MultiColumnTruncation) {
    645   {
    646     char* buf = NULL;
    647     size_t size = 0;
    648     FILE* out = open_memstream(&buf, &size);
    649     ASSERT_NE(NULL, out);
    650 
    651     /* "あいう" (6 columns). Width 4. Should be "あ…" + 1 space. */
    652     print_utf8_padded(out, "あいう", 4, ' ');
    653     fclose(out);
    654     EXPECT_STREQ("あ… ", buf);
    655     free(buf);
    656   }
    657 
    658   {
    659     char* buf = NULL;
    660     size_t size = 0;
    661     FILE* out = open_memstream(&buf, &size);
    662     ASSERT_NE(NULL, out);
    663 
    664     /* "あいう" (6 columns). Width 5. Should be "あい…" (5 columns). */
    665     print_utf8_padded(out, "あいう", 5, ' ');
    666     fclose(out);
    667     EXPECT_STREQ("あい…", buf);
    668     free(buf);
    669   }
    670 }
    671 
    672 UTEST(print_utf8_padded, ComplexEmoji) {
    673   char* buf = NULL;
    674   size_t size = 0;
    675   FILE* out = open_memstream(&buf, &size);
    676   ASSERT_NE(NULL, out);
    677 
    678   /* UTF-8 encoding of Unicode extended grapheme cluster for woman health worker
    679      with medium-dark skin tone. This emoji is a Unicode emoji ZWJ sequence
    680      composed of 5 code points. */
    681   const char* emoji =     // 👩🏾‍⚕️
    682       "\xF0\x9F\x91\xA9"  // U+1F469: Woman 👩
    683       "\xF0\x9F\x8F\xBE"  // U+1F3FE: Emoji modifier Fitzpatrick type 5 🏾
    684       "\xE2\x80\x8D"      // U+200D: Zero-width joiner
    685       "\xE2\x9A\x95"      // U+2695: Staff of Aesculapius ⚕
    686       "\xEF\xB8\x8F";     // U+FE0F: Variation selector 16 (colour emoji)
    687   print_utf8_padded(out, emoji, 10, ' ');
    688   fclose(out);
    689 
    690   EXPECT_STREQ("👩🏾‍⚕️        ", buf);
    691 
    692   free(buf);
    693 }
    694 
    695 UTEST(print_utf8_padded, NoPadChar) {
    696   char* buf = NULL;
    697   size_t size = 0;
    698   FILE* out = open_memstream(&buf, &size);
    699   ASSERT_NE(NULL, out);
    700 
    701   print_utf8_padded(out, "hello", 10, '\0');
    702   fclose(out);
    703 
    704   EXPECT_STREQ("hello", buf);
    705 
    706   free(buf);
    707 }
    708 
    709 UTEST(print_utf8_padded, ZeroWidth) {
    710   char* buf = NULL;
    711   size_t size = 0;
    712   FILE* out = open_memstream(&buf, &size);
    713   ASSERT_NE(NULL, out);
    714 
    715   print_utf8_padded(out, "hello", 0, ' ');
    716   fclose(out);
    717 
    718   EXPECT_STREQ("", buf);
    719 
    720   free(buf);
    721 }