unistr/u{8,16,32}-uctomb: Avoid possible trouble with huge strings.
[gnulib.git] / tests / test-setlocale_null-mt-one.c
blobfd6083a58d15c7731814cdd7bcb1fd4143601ab5
1 /* Multithread-safety test for setlocale_null_r (LC_xxx, ...).
2 Copyright (C) 2019-2020 Free Software Foundation, Inc.
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.
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.
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/>. */
17 /* Written by Bruno Haible <bruno@clisp.org>, 2019. */
19 #include <config.h>
21 #if USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS
23 /* Specification. */
24 #include <locale.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <time.h>
31 #include "glthread/thread.h"
33 /* We want to use the system's setlocale() function here, not the gnulib
34 override. */
35 #undef setlocale
38 /* Some common locale names. */
40 #if defined _WIN32 && !defined __CYGWIN__
41 # define ENGLISH "English_United States"
42 # define GERMAN "German_Germany"
43 # define FRENCH "French_France"
44 # define ENCODING ".1252"
45 #else
46 # define ENGLISH "en_US"
47 # define GERMAN "de_DE"
48 # define FRENCH "fr_FR"
49 # if defined __sgi
50 # define ENCODING ".ISO8859-15"
51 # elif defined __hpux
52 # define ENCODING ".utf8"
53 # else
54 # define ENCODING ".UTF-8"
55 # endif
56 #endif
58 static const char LOCALE1[] = ENGLISH ENCODING;
59 static const char LOCALE2[] = GERMAN ENCODING;
60 static const char LOCALE3[] = FRENCH ENCODING;
62 static char *expected;
64 static void *
65 thread1_func (void *arg)
67 for (;;)
69 char buf[SETLOCALE_NULL_MAX];
71 if (setlocale_null_r (LC_NUMERIC, buf, sizeof (buf)))
72 abort ();
73 if (strcmp (expected, buf) != 0)
75 fprintf (stderr, "thread1 disturbed by thread2!\n"); fflush (stderr);
76 abort ();
80 /*NOTREACHED*/
81 return NULL;
84 static void *
85 thread2_func (void *arg)
87 for (;;)
89 char buf[SETLOCALE_NULL_MAX];
91 setlocale_null_r (LC_NUMERIC, buf, sizeof (buf));
92 setlocale_null_r (LC_TIME, buf, sizeof (buf));
95 /*NOTREACHED*/
96 return NULL;
99 int
100 main (int argc, char *argv[])
102 if (setlocale (LC_ALL, LOCALE1) == NULL)
104 fprintf (stderr, "Skipping test: LOCALE1 not recognized\n");
105 return 77;
107 if (setlocale (LC_NUMERIC, LOCALE2) == NULL)
109 fprintf (stderr, "Skipping test: LOCALE2 not recognized\n");
110 return 77;
112 if (setlocale (LC_TIME, LOCALE3) == NULL)
114 fprintf (stderr, "Skipping test: LOCALE3 not recognized\n");
115 return 77;
118 expected = strdup (setlocale (LC_NUMERIC, NULL));
120 /* Create the two threads. */
121 gl_thread_create (thread1_func, NULL);
122 gl_thread_create (thread2_func, NULL);
124 /* Let them run for 2 seconds. */
126 struct timespec duration;
127 duration.tv_sec = 2;
128 duration.tv_nsec = 0;
130 nanosleep (&duration, NULL);
133 return 0;
136 #else
138 /* No multithreading available. */
140 #include <stdio.h>
143 main ()
145 fputs ("Skipping test: multithreading not enabled\n", stderr);
146 return 77;
149 #endif
151 /* Without locking, the results of this test would be:
152 glibc OK
153 musl libc OK
154 macOS OK
155 FreeBSD OK
156 NetBSD OK
157 OpenBSD crash < 1 sec
158 AIX crash < 2 sec
159 HP-UX OK
160 IRIX OK
161 Solaris 10 OK
162 Solaris 11.0 OK
163 Solaris 11.4 OK
164 Solaris OpenIndiana OK
165 Haiku OK
166 Cygwin OK
167 mingw OK
168 MSVC OK (assuming compiler option /MD !)