(root)/
diffutils-3.10/
gnulib-tests/
test-nl_langinfo-mt.c
       1  /* Multithread-safety test for nl_langinfo().
       2     Copyright (C) 2019-2023 Free Software Foundation, Inc.
       3  
       4     This program is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU General Public License as published by
       6     the Free Software Foundation, either version 3 of the License, or
       7     (at your option) any later version.
       8  
       9     This program is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU General Public License for more details.
      13  
      14     You should have received a copy of the GNU General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  /* Written by Bruno Haible <bruno@clisp.org>, 2019.  */
      18  
      19  #include <config.h>
      20  
      21  /* Work around GCC bug 44511.  */
      22  #if 4 < __GNUC__ + (3 <= __GNUC_MINOR__)
      23  # pragma GCC diagnostic ignored "-Wreturn-type"
      24  #endif
      25  
      26  #if USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS
      27  
      28  /* Specification.  */
      29  #include <langinfo.h>
      30  
      31  #include <locale.h>
      32  #include <stdio.h>
      33  #include <stdlib.h>
      34  #include <string.h>
      35  #include <time.h>
      36  
      37  #include "glthread/thread.h"
      38  
      39  
      40  /* Some common locale names.  */
      41  
      42  #if defined _WIN32 && !defined __CYGWIN__
      43  # define ENGLISH "English_United States"
      44  # define FRENCH  "French_France"
      45  # define GERMAN  "German_Germany"
      46  # define ENCODING ".1252"
      47  #else
      48  # define ENGLISH "en_US"
      49  # define FRENCH  "fr_FR"
      50  # define GERMAN  "de_DE"
      51  # if defined __sgi
      52  #  define ENCODING ".ISO8859-15"
      53  # elif defined __hpux
      54  #  define ENCODING ".utf8"
      55  # else
      56  #  define ENCODING ".UTF-8"
      57  # endif
      58  #endif
      59  
      60  static const char LOCALE1[] = ENGLISH ENCODING;
      61  static const char LOCALE2[] = FRENCH ENCODING;
      62  static const char LOCALE3[] = GERMAN ENCODING;
      63  
      64  static char *expected1;
      65  
      66  static void *
      67  thread1_func (void *arg)
      68  {
      69    for (;;)
      70      {
      71        const char *value = nl_langinfo (CODESET);
      72        if (strcmp (expected1, value) != 0)
      73          {
      74            fprintf (stderr, "thread1 disturbed by threadN!\n"); fflush (stderr);
      75            abort ();
      76          }
      77      }
      78  
      79    /*NOTREACHED*/
      80  }
      81  
      82  static char *expected2;
      83  
      84  static void *
      85  thread2_func (void *arg)
      86  {
      87    for (;;)
      88      {
      89        const char *value = nl_langinfo (PM_STR);
      90        if (strcmp (expected2, value) != 0)
      91          {
      92            fprintf (stderr, "thread2 disturbed by threadN!\n"); fflush (stderr);
      93            abort ();
      94          }
      95      }
      96  
      97    /*NOTREACHED*/
      98  }
      99  
     100  static char *expected3;
     101  
     102  static void *
     103  thread3_func (void *arg)
     104  {
     105    for (;;)
     106      {
     107        const char *value = nl_langinfo (DAY_2);
     108        if (strcmp (expected3, value) != 0)
     109          {
     110            fprintf (stderr, "thread3 disturbed by threadN!\n"); fflush (stderr);
     111            abort ();
     112          }
     113      }
     114  
     115    /*NOTREACHED*/
     116  }
     117  
     118  static char *expected4;
     119  
     120  static void *
     121  thread4_func (void *arg)
     122  {
     123    for (;;)
     124      {
     125        const char *value = nl_langinfo (ALTMON_2);
     126        if (strcmp (expected4, value) != 0)
     127          {
     128            fprintf (stderr, "thread4 disturbed by threadN!\n"); fflush (stderr);
     129            abort ();
     130          }
     131      }
     132  
     133    /*NOTREACHED*/
     134  }
     135  
     136  static char *expected5;
     137  
     138  static void *
     139  thread5_func (void *arg)
     140  {
     141    for (;;)
     142      {
     143        const char *value = nl_langinfo (CRNCYSTR);
     144        if (strcmp (expected5, value) != 0)
     145          {
     146            fprintf (stderr, "thread5 disturbed by threadN!\n"); fflush (stderr);
     147            abort ();
     148          }
     149      }
     150  
     151    /*NOTREACHED*/
     152  }
     153  
     154  static char *expected6;
     155  
     156  static void *
     157  thread6_func (void *arg)
     158  {
     159    for (;;)
     160      {
     161        const char *value = nl_langinfo (RADIXCHAR);
     162        if (strcmp (expected6, value) != 0)
     163          {
     164            fprintf (stderr, "thread6 disturbed by threadN!\n"); fflush (stderr);
     165            abort ();
     166          }
     167      }
     168  
     169    /*NOTREACHED*/
     170  }
     171  
     172  static void *
     173  threadN_func (void *arg)
     174  {
     175    for (;;)
     176      {
     177        nl_langinfo (CODESET);   /* LC_CTYPE */    /* locale charmap */
     178        nl_langinfo (AM_STR);    /* LC_TIME */     /* locale -k am_pm */
     179        nl_langinfo (PM_STR);    /* LC_TIME */     /* locale -k am_pm */
     180        nl_langinfo (DAY_2);     /* LC_TIME */     /* locale -k day */
     181        nl_langinfo (DAY_5);     /* LC_TIME */     /* locale -k day */
     182        nl_langinfo (ALTMON_2);  /* LC_TIME */     /* locale -k alt_mon */
     183        nl_langinfo (ALTMON_9);  /* LC_TIME */     /* locale -k alt_mon */
     184        nl_langinfo (CRNCYSTR);  /* LC_MONETARY */ /* locale -k currency_symbol */
     185        nl_langinfo (RADIXCHAR); /* LC_NUMERIC */  /* locale -k decimal_point */
     186        nl_langinfo (THOUSEP);   /* LC_NUMERIC */  /* locale -k thousands_sep */
     187      }
     188  
     189    /*NOTREACHED*/
     190  }
     191  
     192  int
     193  main (int argc, char *argv[])
     194  {
     195    if (setlocale (LC_ALL, LOCALE1) == NULL)
     196      {
     197        fprintf (stderr, "Skipping test: LOCALE1 not recognized\n");
     198        return 77;
     199      }
     200    if (setlocale (LC_MONETARY, LOCALE2) == NULL)
     201      {
     202        fprintf (stderr, "Skipping test: LOCALE2 not recognized\n");
     203        return 77;
     204      }
     205    if (setlocale (LC_NUMERIC, LOCALE3) == NULL)
     206      {
     207        fprintf (stderr, "Skipping test: LOCALE3 not recognized\n");
     208        return 77;
     209      }
     210  
     211    expected1 = strdup (nl_langinfo (CODESET));
     212    expected2 = strdup (nl_langinfo (PM_STR));
     213    expected3 = strdup (nl_langinfo (DAY_2));
     214    expected4 = strdup (nl_langinfo (ALTMON_2));
     215    expected5 = strdup (nl_langinfo (CRNCYSTR));
     216    expected6 = strdup (nl_langinfo (RADIXCHAR));
     217  
     218    /* Create the checker threads.  */
     219    gl_thread_create (thread1_func, NULL);
     220    gl_thread_create (thread2_func, NULL);
     221    gl_thread_create (thread3_func, NULL);
     222    gl_thread_create (thread4_func, NULL);
     223    gl_thread_create (thread5_func, NULL);
     224    gl_thread_create (thread6_func, NULL);
     225    /* Create the disturber thread.  */
     226    gl_thread_create (threadN_func, NULL);
     227  
     228    /* Let them run for 2 seconds.  */
     229    {
     230      struct timespec duration;
     231      duration.tv_sec = (argc > 1 ? atoi (argv[1]) : 2);
     232      duration.tv_nsec = 0;
     233  
     234      nanosleep (&duration, NULL);
     235    }
     236  
     237    return 0;
     238  }
     239  
     240  #else
     241  
     242  /* No multithreading available.  */
     243  
     244  #include <stdio.h>
     245  
     246  int
     247  main ()
     248  {
     249    fputs ("Skipping test: multithreading not enabled\n", stderr);
     250    return 77;
     251  }
     252  
     253  #endif