(root)/
glibc-2.38/
time/
tst-strftime3.c
       1  /* Data-driven tests for strftime/strptime.
       2     Copyright (C) 2019-2023 Free Software Foundation, Inc.  This file is
       3     part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <stdio.h>
      20  #include <stdlib.h>
      21  #include <string.h>
      22  #include <time.h>
      23  #include <locale.h>
      24  #include <wchar.h>
      25  
      26  #include <support/check.h>
      27  #include <array_length.h>
      28  #include <libc-diag.h>
      29  
      30  /* These exist for the convenience of writing the test data, because
      31     zero-based vs one-based.  */
      32  typedef enum
      33    {
      34      Sun, Mon, Tue, Wed, Thu, Fri, Sat
      35    } WeekDay;
      36  
      37  typedef enum
      38    {
      39      Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
      40    } Month;
      41  
      42  typedef struct
      43  {
      44    /* A descriptive name of the test.  */
      45    const char *name;
      46  
      47    /* The specific date and time to be tested.  */
      48    int y, m, d;
      49    WeekDay w;
      50    int hh, mm, ss;
      51  
      52    /* The locale under which the conversion is done.  */
      53    const char *locale;
      54  
      55    /* Format passed to strftime.  */
      56    const char *format;
      57  
      58    /* Expected data, NUL terminated.  */
      59    const char *printed;
      60  
      61  } Data;
      62  
      63  /* Notes:
      64  
      65     Years are full 4-digit years, the code compensates.  Likewise,
      66     use month and weekday enums (above) which are zero-based.
      67  
      68     The encoded strings are multibyte strings in the C locale which
      69     reflect the same binary data as the expected strings.  When you run
      70     the test, the strings are printed as-is to stdout, so if your
      71     terminal is set for the correct encoding, they'll be printed
      72     "correctly".  Put the Unicode codes and UTF-8 samples in the
      73     comments.
      74  
      75     For convenience, mis-matched strings are printed in
      76     paste-compatible format, raw text format, and Unicode format.  Use
      77     "" between a hex escape sequence (like \xe8) and a following hex
      78     digit which should be considered as a printable character.
      79  
      80     To verify text, save the correct text in a file, and use "od -tx1
      81     -tc file" to see the raw hex values.  */
      82  
      83  const Data data[] = {
      84  
      85    { "Baseline test",
      86      2019, Mar, 27, Wed, 14,  3, 22, "en_US.ISO-8859-1", "%Y-%m-%d %T",
      87      "2019-03-27 14:03:22" },
      88  
      89  
      90    { "Japanese era change, BCE/CE, before transition",
      91      0, Dec, 31, Sun, 12, 00, 00, "ja_JP.UTF-8", "%EY",
      92      /* <U7D00><U5143><U524D>01<U5E74> 紀元前01年 */
      93      "\xe7\xb4\x80\xe5\x85\x83\xe5\x89\x8d""01\xe5\xb9\xb4" },
      94    { "Japanese era change, BCE/CE, after transition",
      95      1, Jan,  1, Mon, 12, 00, 00, "ja_JP.UTF-8", "%EY",
      96      /* <U897F><U66A6>01<U5E74> 西暦01年 */
      97      "\xe8\xa5\xbf\xe6\x9a\xa6""01\xe5\xb9\xb4" },
      98  
      99    { "Japanese era change, BCE/CE, before transition",
     100      0, Dec, 31, Sun, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     101      /* <U7D00><U5143><U524D>01<U5E74> 紀元前01年 */
     102      "\xb5\xaa\xb8\xb5\xc1\xb0""01\xc7\xaf" },
     103    { "Japanese era change, BCE/CE, after transition",
     104      1, Jan,  1, Mon, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     105      /* <U897F><U66A6>01<U5E74> 西暦01年 */
     106      "\xc0\xbe\xce\xf1""01\xc7\xaf" },
     107  
     108  
     109    { "Japanese era change, 1873, before transition",
     110      1872, Dec, 31, Tue, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     111      /* <U897F><U66A6>1872<U5E74> 西暦1872年 */
     112      "\xe8\xa5\xbf\xe6\x9a\xa6""1872\xe5\xb9\xb4" },
     113    { "Japanese era change, 1873, after transition",
     114      1873, Jan,  1, Wed, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     115      /* <U660E><U6CBB>06<U5E74> 明治06年 */
     116      "\xe6\x98\x8e\xe6\xb2\xbb""06\xe5\xb9\xb4" },
     117  
     118  
     119    { "Japanese era change, 1873, before transition",
     120      1872, Dec, 31, Tue, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     121      /* <U897F><U66A6>1872<U5E74> 西暦1872年 */
     122      "\xc0\xbe\xce\xf1""1872\xc7\xaf" },
     123    { "Japanese era change, 1873, after transition",
     124      1873, Jan,  1, Wed, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     125      /* <U660E><U6CBB>06<U5E74> 明治06年 */
     126      "\xcc\xc0\xbc\xa3""06\xc7\xaf" },
     127  
     128  
     129    { "Japanese era change, 1912, before transition year",
     130      1911, Dec, 31, Sun, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     131      /* <U660E><U6CBB>44<U5E74> 明治44年 */
     132      "\xe6\x98\x8e\xe6\xb2\xbb""44\xe5\xb9\xb4" },
     133    { "Japanese era change, 1912, start of transition year",
     134      1912, Jan,  1, Mon, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     135      /* <U660E><U6CBB>45<U5E74> 明治45年 */
     136      "\xe6\x98\x8e\xe6\xb2\xbb""45\xe5\xb9\xb4" },
     137  
     138    { "Japanese era change, 1912, before transition",
     139      1912, Jul, 29, Mon, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     140      /* <U660E><U6CBB>45<U5E74> 明治45年 */
     141      "\xe6\x98\x8e\xe6\xb2\xbb""45\xe5\xb9\xb4" },
     142    { "Japanese era change, 1912, after transition",
     143      1912, Jul, 30, Tue, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     144      /* <U5927><U6B63><U5143><U5E74> 大正元年 */
     145      "\xe5\xa4\xa7\xe6\xad\xa3\xe5\x85\x83\xe5\xb9\xb4" },
     146  
     147    { "Japanese era change, 1912, before end of transition year",
     148      1912, Dec, 31, Tue, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     149      /* <U5927><U6B63><U5143><U5E74> 大正元年 */
     150      "\xe5\xa4\xa7\xe6\xad\xa3\xe5\x85\x83\xe5\xb9\xb4" },
     151    { "Japanese era change, 1912, after transition year",
     152      1913, Jan,  1, Wed, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     153      /* <U5927><U6B63>02<U5E74> 大正02年 */
     154      "\xe5\xa4\xa7\xe6\xad\xa3""02\xe5\xb9\xb4" },
     155  
     156  
     157    { "Japanese era change, 1912, before transition year",
     158      1911, Dec, 31, Sun, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     159      /* <U660E><U6CBB>44<U5E74> 明治44年 */
     160      "\xcc\xc0\xbc\xa3""44\xc7\xaf" },
     161    { "Japanese era change, 1912, start of transition year",
     162      1912, Jan,  1, Mon, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     163      /* <U660E><U6CBB>45<U5E74> 明治45年 */
     164      "\xcc\xc0\xbc\xa3""45\xc7\xaf" },
     165  
     166    { "Japanese era change, 1912, before transition",
     167      1912, Jul, 29, Mon, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     168      /* <U660E><U6CBB>45<U5E74> 明治45年 */
     169      "\xcc\xc0\xbc\xa3""45\xc7\xaf" },
     170    { "Japanese era change, 1912, after transition",
     171      1912, Jul, 30, Tue, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     172      /* <U5927><U6B63><U5143><U5E74> 大正元年 */
     173      "\xc2\xe7\xc0\xb5\xb8\xb5\xc7\xaf" },
     174  
     175    { "Japanese era change, 1912, before end of transition year",
     176      1912, Dec, 31, Tue, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     177      /* <U5927><U6B63><U5143><U5E74> 大正元年 */
     178      "\xc2\xe7\xc0\xb5\xb8\xb5\xc7\xaf" },
     179    { "Japanese era change, 1912, after transition year",
     180      1913, Jan,  1, Wed, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     181      /* <U5927><U6B63>02<U5E74> 大正02年 */
     182      "\xc2\xe7\xc0\xb5""02\xc7\xaf" },
     183  
     184  
     185    { "Japanese era change, 1926, before transition year",
     186      1925, Dec, 31, Thu, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     187      /* <U5927><U6B63>14<U5E74> 大正14年 */
     188      "\xe5\xa4\xa7\xe6\xad\xa3""14\xe5\xb9\xb4" },
     189    { "Japanese era change, 1926, start of transition year",
     190      1926, Jan,  1, Fri, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     191      /* <U5927><U6B63>15<U5E74> 大正15年 */
     192      "\xe5\xa4\xa7\xe6\xad\xa3""15\xe5\xb9\xb4" },
     193  
     194    { "Japanese era change, 1926, before transition",
     195      1926, Dec, 24, Fri, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     196      /* <U5927><U6B63>15<U5E74> 大正15年 */
     197      "\xe5\xa4\xa7\xe6\xad\xa3""15\xe5\xb9\xb4" },
     198    { "Japanese era change, 1926, after transition",
     199      1926, Dec, 25, Sat, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     200      /* <U662D><U548C><U5143><U5E74> 昭和元年 */
     201      "\xe6\x98\xad\xe5\x92\x8c\xe5\x85\x83\xe5\xb9\xb4" },
     202  
     203    { "Japanese era change, 1926, before end of transition year",
     204      1926, Dec, 31, Fri, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     205      /* <U662D><U548C><U5143><U5E74> 昭和元年 */
     206      "\xe6\x98\xad\xe5\x92\x8c\xe5\x85\x83\xe5\xb9\xb4" },
     207    { "Japanese era change, 1926, after transition year",
     208      1927, Jan,  1, Sat, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     209      /*  <U662D><U548C>02<U5E74> 昭和02年 */
     210      "\xe6\x98\xad\xe5\x92\x8c""02\xe5\xb9\xb4" },
     211  
     212  
     213    { "Japanese era change, 1926, before transition year",
     214      1925, Dec, 31, Thu, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     215      /* <U5927><U6B63>14<U5E74> 大正14年 */
     216      "\xc2\xe7\xc0\xb5""14\xc7\xaf" },
     217    { "Japanese era change, 1926, start of transition year",
     218      1926, Jan,  1, Fri, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     219      /* <U5927><U6B63>15<U5E74> 大正15年 */
     220      "\xc2\xe7\xc0\xb5""15\xc7\xaf" },
     221  
     222    { "Japanese era change, 1926, before transition",
     223      1926, Dec, 24, Fri, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     224      /* <U5927><U6B63>15<U5E74> 大正15年 */
     225      "\xc2\xe7\xc0\xb5""15\xc7\xaf" },
     226    { "Japanese era change, 1926, after transition",
     227      1926, Dec, 25, Sat, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     228      /* <U662D><U548C><U5143><U5E74> 昭和元年 */
     229      "\xbe\xbc\xcf\xc2\xb8\xb5\xc7\xaf" },
     230  
     231    { "Japanese era change, 1926, before end of transition year",
     232      1926, Dec, 31, Fri, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     233      /* <U662D><U548C><U5143><U5E74> 昭和元年 */
     234      "\xbe\xbc\xcf\xc2\xb8\xb5\xc7\xaf" },
     235    { "Japanese era change, 1926, after transition year",
     236      1927, Jan,  1, Sat, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     237      /*  <U662D><U548C>02<U5E74> 昭和02年 */
     238      "\xbe\xbc\xcf\xc2""02\xc7\xaf" },
     239  
     240  
     241    { "Japanese era change, 1989, before transition year",
     242      1988, Dec, 31, Sat, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     243      /* <U662D><U548C>63<U5E74> 昭和63年 */
     244      "\xe6\x98\xad\xe5\x92\x8c""63\xe5\xb9\xb4" },
     245    { "Japanese era change, 1989, start of transition year",
     246      1989, Jan,  1, Sun, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     247      /* <U662D><U548C>64<U5E74> 昭和64年 */
     248      "\xe6\x98\xad\xe5\x92\x8c""64\xe5\xb9\xb4" },
     249  
     250    { "Japanese era change, 1989, before transition",
     251      1989, Jan,  7, Sat, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     252      /* <U662D><U548C>64<U5E74> 昭和64年 */
     253      "\xe6\x98\xad\xe5\x92\x8c""64\xe5\xb9\xb4" },
     254    { "Japanese era change, 1989, after transition",
     255      1989, Jan,  8, Sun, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     256      /* <U5E73><U6210><U5143><U5E74> 平成元年 */
     257      "\xe5\xb9\xb3\xe6\x88\x90\xe5\x85\x83\xe5\xb9\xb4" },
     258  
     259    { "Japanese era change, 1989, end of transition year",
     260      1989, Dec, 31, Sun, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     261      /* <U5E73><U6210><U5143><U5E74> 平成元年 */
     262      "\xe5\xb9\xb3\xe6\x88\x90\xe5\x85\x83\xe5\xb9\xb4" },
     263    { "Japanese era change, 1989, after transition year",
     264      1990, Jan,  1, Mon, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     265      /* <U5E73><U6210>02<U5E74> 平成02年 */
     266      "\xe5\xb9\xb3\xe6\x88\x90""02\xe5\xb9\xb4" },
     267  
     268  
     269    { "Japanese era change, 1989, before transition year",
     270      1988, Dec, 31, Sat, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     271      /* <U662D><U548C>63<U5E74> 昭和63年 */
     272      "\xbe\xbc\xcf\xc2""63\xc7\xaf" },
     273    { "Japanese era change, 1989, start of transition year",
     274      1989, Jan,  1, Sun, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     275      /* <U662D><U548C>64<U5E74> 昭和64年 */
     276      "\xbe\xbc\xcf\xc2""64\xc7\xaf" },
     277  
     278    { "Japanese era change, 1989, before transition",
     279      1989, Jan,  7, Sat, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     280      /* <U662D><U548C>64<U5E74> 昭和64年 */
     281      "\xbe\xbc\xcf\xc2""64\xc7\xaf" },
     282    { "Japanese era change, 1989, after transition",
     283      1989, Jan,  8, Sun, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     284      /* <U5E73><U6210><U5143><U5E74> 平成元年 */
     285      "\xca\xbf\xc0\xae\xb8\xb5\xc7\xaf" },
     286  
     287    { "Japanese era change, 1989, end of transition year",
     288      1989, Dec, 31, Sun, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     289      /* <U5E73><U6210><U5143><U5E74> 平成元年 */
     290      "\xca\xbf\xc0\xae\xb8\xb5\xc7\xaf" },
     291    { "Japanese era change, 1989, after transition year",
     292      1990, Jan,  1, Mon, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     293      /* <U5E73><U6210>02<U5E74> 平成02年 */
     294      "\xca\xbf\xc0\xae""02\xc7\xaf" },
     295  
     296  
     297    { "Japanese era change, 2019, before transition year",
     298      2018, Dec, 31, Mon, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     299      /* <U5E73><U6210>30<U5E74> 昭和30年 */
     300      "\xe5\xb9\xb3\xe6\x88\x90""30\xe5\xb9\xb4" },
     301    { "Japanese era change, 2019, start of transition year",
     302      2019, Jan,  1, Tue, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     303      /* <U5E73><U6210>30<U5E74> 昭和31年 */
     304      "\xe5\xb9\xb3\xe6\x88\x90""31\xe5\xb9\xb4" },
     305  
     306    { "Japanese era change, 2019, before transition",
     307      2019, Apr, 30, Tue, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     308      /* <U5E73><U6210>30<U5E74> 昭和31年 */
     309      "\xe5\xb9\xb3\xe6\x88\x90""31\xe5\xb9\xb4" },
     310    { "Japanese era change, 2019, after transition",
     311      2019, May,  1, Wed, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     312      /* <U4EE4><U548C><U5143><U5E74> 令和元年 */
     313      "\xe4\xbb\xa4\xe5\x92\x8c\xe5\x85\x83\xe5\xb9\xb4" },
     314  
     315    { "Japanese era change, 2019, end of transition year",
     316      2019, Dec, 31, Tue, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     317      /* <U4EE4><U548C><U5143><U5E74> 令和元年 */
     318      "\xe4\xbb\xa4\xe5\x92\x8c\xe5\x85\x83\xe5\xb9\xb4" },
     319    { "Japanese era change, 2019, after transition year",
     320      2020, Jan,  1, Wed, 12, 00, 00, "ja_JP.UTF-8", "%EY",
     321      /* <U4EE4><U548C>02<U5E74> 令和02年 */
     322      "\xe4\xbb\xa4\xe5\x92\x8c""02\xe5\xb9\xb4" },
     323  
     324  
     325    { "Japanese era change, 2019, before transition year",
     326      2018, Dec, 31, Mon, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     327      /* <U5E73><U6210>30<U5E74> 昭和30年 */
     328      "\xca\xbf\xc0\xae""30\xc7\xaf" },
     329    { "Japanese era change, 2019, start of transition year",
     330      2019, Jan,  1, Tue, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     331      /* <U5E73><U6210>30<U5E74> 昭和31年 */
     332      "\xca\xbf\xc0\xae""31\xc7\xaf" },
     333  
     334    { "Japanese era change, 2019, before transition",
     335      2019, Apr, 30, Tue, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     336      /* <U5E73><U6210>30<U5E74> 昭和31年 */
     337      "\xca\xbf\xc0\xae""31\xc7\xaf" },
     338    { "Japanese era change, 2019, after transition",
     339      2019, May,  1, Wed, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     340      /* <U4EE4><U548C><U5143><U5E74> 令和元年 */
     341      "\xce\xe1\xcf\xc2\xb8\xb5\xc7\xaf" },
     342  
     343    { "Japanese era change, 2019, end of transition year",
     344      2019, Dec, 31, Tue, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     345      /* <U4EE4><U548C><U5143><U5E74> 令和元年 */
     346      "\xce\xe1\xcf\xc2\xb8\xb5\xc7\xaf" },
     347    { "Japanese era change, 2019, after transition year",
     348      2020, Jan,  1, Wed, 12, 00, 00, "ja_JP.EUC-JP", "%EY",
     349      /* <U4EE4><U548C>02<U5E74> 令和02年 */
     350      "\xce\xe1\xcf\xc2""02\xc7\xaf" },
     351  };
     352  
     353  #define NDATA array_length(data)
     354  
     355  /* Size of buffer passed to strftime.  */
     356  #define STRBUFLEN 1000
     357  /* Size of buffer passed to tm_to_printed.  */
     358  #define TMBUFLEN 50
     359  
     360  /* Helper function to compare strings and print out mismatches in a
     361     format suitable for maintaining this test.  TEST_COMPARE_STRINGS
     362     prints out a less suitable format.  */
     363  
     364  static void
     365  print_string_hex (const char *header, const char *str)
     366  {
     367    int tictoc = 0;
     368    const char *s = str;
     369    wchar_t w[STRBUFLEN];
     370    size_t i, wlen;
     371  
     372    printf ("%s : ", header);
     373  
     374    if (str == NULL)
     375      {
     376        printf ("<NULL>\n");
     377        return;
     378      }
     379  
     380    while (*s)
     381      {
     382        /* isgraph equivalent, but independent of current locale.  */
     383        if (' ' <= *s && *s <= '~')
     384  	putchar (*s);
     385        else
     386  	{
     387  	  if (tictoc)
     388  	    printf ("\033[36m");
     389  	  else
     390  	    printf ("\033[31m");
     391  	  tictoc = ! tictoc;
     392  
     393  	  printf ("\\x%02x\033[0m", (unsigned char) *s);
     394  	}
     395  
     396        ++ s;
     397      }
     398    printf (" - %s\n", str);
     399  
     400    s = str;
     401    wlen = mbsrtowcs (w, &s, strlen (s), NULL);
     402    printf ("%*s", (int) strlen (header) + 3, " ");
     403    for (i = 0; i < wlen && i < strlen (str); i ++)
     404      {
     405        if (' ' <= w[i] && w[i] <= '~')
     406  	putchar (w[i]);
     407        else
     408  	printf ("<U%04X>", (int) w[i]);
     409      }
     410    printf ("\n");
     411  }
     412  
     413  static void
     414  compare_strings (const char *got, const char *expected,
     415  		 const char *filename, int lineno)
     416  {
     417    if (got && expected && strcmp (got, expected) == 0)
     418      return;
     419    support_record_failure ();
     420    printf ("%s:%d: error: strftime output incorrect\n", filename, lineno);
     421    print_string_hex ("Got", got);
     422    print_string_hex ("Exp", expected);
     423  }
     424  #define COMPARE_STRINGS(g,e) compare_strings (g, e, __FILE__, __LINE__)
     425  
     426  const char *weekday_name[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri",
     427  			       "Sat" };
     428  
     429  /* Helper function to create a printable version of struct tm.  */
     430  static void
     431  tm_to_printed (struct tm *tm, char *buffer)
     432  {
     433    const char *wn;
     434    char temp[50];
     435  
     436    if (0 <= tm->tm_wday && tm->tm_wday <= 6)
     437      wn = weekday_name[tm->tm_wday];
     438    else
     439      {
     440        wn = temp;
     441        sprintf (temp, "%d", tm->tm_wday);
     442      }
     443  
     444    DIAG_PUSH_NEEDS_COMMENT;
     445  #if __GNUC_PREREQ (9, 0)
     446    /* GCC 9 warns that strncmp may truncate its output, but that's why
     447       we're using it.  When it needs to truncate, it got corrupted
     448       data, and we only care that the string is different than valid
     449       data, which won't truncate.  */
     450    DIAG_IGNORE_NEEDS_COMMENT (9, "-Wformat-truncation=");
     451  #endif
     452    snprintf (buffer, TMBUFLEN, "%04d/%02d/%02d %02d:%02d:%02d %s",
     453  	    tm->tm_year + 1900,
     454  	    tm->tm_mon + 1,
     455  	    tm->tm_mday,
     456  	    tm->tm_hour,
     457  	    tm->tm_min,
     458  	    tm->tm_sec,
     459  	    wn);
     460    DIAG_POP_NEEDS_COMMENT;
     461  }
     462  
     463  static int
     464  do_test (void)
     465  {
     466    int i;
     467    char buffer[STRBUFLEN];
     468    char expected_time[TMBUFLEN];
     469    char got_time[TMBUFLEN];
     470  
     471    for (i = 0; i < NDATA; i ++)
     472      {
     473        const Data *d = &(data[i]);
     474        struct tm tm;
     475        struct tm tm2;
     476        size_t rv;
     477        char *rvp;
     478  
     479        /* Print this just to help debug failures.  */
     480        printf ("%s:\n\t%s %s %s\n", d->name, d->locale, d->format, d->printed);
     481  
     482        tm.tm_year = d->y - 1900;
     483        tm.tm_mon = d->m;
     484        tm.tm_mday = d->d;
     485        tm.tm_wday = d->w;
     486        tm.tm_hour = d->hh;
     487        tm.tm_min = d->mm;
     488        tm.tm_sec = d->ss;
     489        tm.tm_isdst = -1;
     490  
     491        /* LC_ALL may interfere with the snprintf in tm_to_printed.  */
     492        if (setlocale (LC_TIME, d->locale) == NULL)
     493  	{
     494  	  /* See the LOCALES list in the Makefile.  */
     495  	  printf ("locale %s does not exist!\n", d->locale);
     496  	  exit (EXIT_FAILURE);
     497  	}
     498        /* This is just for printing wide characters if there's an error.  */
     499        setlocale (LC_CTYPE, d->locale);
     500  
     501        rv = strftime (buffer, sizeof (buffer), d->format, &tm);
     502  
     503        TEST_COMPARE (rv, strlen (d->printed));
     504        COMPARE_STRINGS (buffer, d->printed);
     505  
     506        /* Copy the original time, so that any fields not affected by
     507  	 the call to strptime will match.  */
     508        tm2 = tm;
     509  
     510        rvp = strptime (d->printed, d->format, &tm2);
     511  
     512        TEST_COMPARE_STRING (rvp, "");
     513  
     514        tm_to_printed (&tm, expected_time);
     515        tm_to_printed (&tm2, got_time);
     516        TEST_COMPARE_STRING (got_time, expected_time);
     517      }
     518  
     519    return 0;
     520  }
     521  
     522  #include <support/test-driver.c>