Fix last ChangeLog entry.
[gnulib.git] / tests / test-vasnwprintf-big.c
blobab59f6de3a57a329976b9c5a611c0e4dcbeed52c
1 /* Test of [v]asnwprintf() with big results.
2 Copyright (C) 2024-2025 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>, 2024. */
19 #include <config.h>
21 #include "vasnwprintf.h"
23 #include "physmem.h"
25 /* Get INT_MAX. */
26 #include <limits.h>
28 /* Get PTRDIFF_MAX. */
29 #include <stdint.h>
31 #include <errno.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <wchar.h>
36 #if HAVE_SETRLIMIT
37 # include <sys/types.h>
38 # include <sys/time.h>
39 # include <sys/resource.h>
40 #endif
42 #include "macros.h"
44 int
45 main ()
47 #if PTRDIFF_MAX == INT_MAX
48 fputs ("Skipping test: ptrdiff_t is not 64-bits wide\n", stderr);
49 return 77;
50 #else
51 bool skipped = false;
52 /* Disable core files that would be huge. */
53 # if HAVE_SETRLIMIT && defined RLIMIT_CORE
54 struct rlimit rl;
55 rl.rlim_cur = rl.rlim_max = 0;
56 setrlimit (RLIMIT_CORE, &rl);
57 # endif
58 /* The test below needs about 40 GiB of memory:
59 $ time /usr/bin/time -f "Max RSS: %M KiB" ./test-vasnwprintf-big
60 Max RSS: 41944784 KiB
61 real 5m8,508s
62 user 4m38,035s
63 sys 0m30,456s
64 5 GiB for the inputs in the %s tests,
65 or 20 GiB for the inputs in the %ls tests,
66 and up to 20 GiB for temporary output buffers. */
67 double needed = 40.0 * 1024 * 1024 * 1024;
68 double avail = physmem_claimable (1.0);
69 printf ("memory needed = %g MiB, available = %g MiB\n",
70 needed / 1024 / 1024, avail / 1024 / 1024);
71 if (avail >= needed)
73 /* Note: The malloc() calls can fail, due to ulimit of RLIMIT_DATA.
74 For example, on OpenBSD 7.5, the soft limit is 1.0 GiB or 1.5 GiB,
75 and you need "ulimit -d 42991616". */
77 /* Verify that asnwprintf() can return a string of size > 4 GiB. */
79 size_t n1 = 3 * (INT_MAX / 4) + 10;
80 size_t n2 = 3 * (INT_MAX / 4) + 20;
81 char *s1;
82 char *s2;
84 s1 = (char *) malloc (n1 + 1);
85 if (s1 != NULL)
87 memset (s1, 'a', n1);
88 s1[n1] = '\0';
90 s2 = (char *) malloc (n2 + 1);
91 if (s2 != NULL)
93 memset (s2, 'b', n2);
94 s1[n1] = '\0';
96 size_t len;
97 wchar_t *s = asnwprintf (NULL, &len, L"x%sy%sz", s1, s2);
98 if (s == NULL)
100 ASSERT (errno == ENOMEM);
101 skipped = true;
103 else
105 ASSERT (wcslen (s) == len);
106 ASSERT (len == n1 + n2 + 3);
107 size_t i;
108 for (i = 0; i <= len; i++)
109 s[i] = (i == 0 ? 'x' :
110 i <= n1 ? 'a' :
111 i == n1 + 1 ? 'y' :
112 i <= n1 + n2 + 1 ? 'b' :
113 i == n1 + n2 + 2 ? 'z' :
114 '\0');
115 free (s);
117 free (s2);
119 free (s1);
123 /* Verify that asnwprintf() can take a string of size > 2 GiB, < 4 GiB
124 as argument. */
126 size_t n1 = 3 * (size_t) (INT_MAX / 2) + 10;
127 char *s1;
129 s1 = (char *) malloc (n1 + 1);
130 if (s1 != NULL)
132 memset (s1, 'a', n1);
133 s1[n1] = '\0';
135 size_t len;
136 wchar_t *s = asnwprintf (NULL, &len, L"x%sy", s1);
137 if (s == NULL)
139 ASSERT (errno == ENOMEM);
140 skipped = true;
142 else
144 ASSERT (wcslen (s) == len);
145 ASSERT (len == n1 + 2);
146 size_t i;
147 for (i = 0; i <= len; i++)
148 s[i] = (i == 0 ? 'x' :
149 i <= n1 ? 'a' :
150 i == n1 + 1 ? 'y' :
151 '\0');
152 free (s);
154 free (s1);
158 /* Verify that asnwprintf() can take a string of size > 4 GiB
159 as argument. */
161 size_t n1 = 5 * (size_t) (INT_MAX / 2) + 10;
162 if (n1 > (size_t) INT_MAX)
164 char *s1;
166 s1 = (char *) malloc (n1 + 1);
167 if (s1 != NULL)
169 memset (s1, 'a', n1);
170 s1[n1] = '\0';
172 size_t len;
173 wchar_t *s = asnwprintf (NULL, &len, L"x%sy", s1);
174 if (s == NULL)
176 ASSERT (errno == ENOMEM);
177 skipped = true;
179 else
181 ASSERT (wcslen (s) == len);
182 ASSERT (len == n1 + 2);
183 size_t i;
184 for (i = 0; i <= len; i++)
185 s[i] = (i == 0 ? 'x' :
186 i <= n1 ? 'a' :
187 i == n1 + 1 ? 'y' :
188 '\0');
189 free (s);
191 free (s1);
196 /* Verify that asnwprintf() can take a wide string with an element count
197 > 2^31, < 2^32 as argument. */
199 size_t n1 = 3 * (size_t) (INT_MAX / 2) + 10;
200 wchar_t *s1;
202 s1 = (wchar_t *) malloc ((n1 + 1) * sizeof (wchar_t));
203 if (s1 != NULL)
205 wmemset (s1, L'a', n1);
206 s1[n1] = L'\0';
208 size_t len;
209 wchar_t *s = asnwprintf (NULL, &len, L"x%lsy", s1);
210 if (s == NULL)
212 ASSERT (errno == ENOMEM);
213 skipped = true;
215 else
217 ASSERT (wcslen (s) == len);
218 ASSERT (len == n1 + 2);
219 size_t i;
220 for (i = 0; i <= len; i++)
221 s[i] = (i == 0 ? 'x' :
222 i <= n1 ? 'a' :
223 i == n1 + 1 ? 'y' :
224 '\0');
225 free (s);
227 free (s1);
231 /* Verify that asnwprintf() can take a wide string with an element count
232 > 2^32 as argument. */
234 size_t n1 = 5 * (size_t) (INT_MAX / 2) + 10;
235 if (n1 > (size_t) INT_MAX)
237 wchar_t *s1;
239 s1 = (wchar_t *) malloc ((n1 + 1) * sizeof (wchar_t));
240 if (s1 != NULL)
242 wmemset (s1, L'a', n1);
243 s1[n1] = L'\0';
245 size_t len;
246 wchar_t *s = asnwprintf (NULL, &len, L"x%lsy", s1);
247 if (s == NULL)
249 ASSERT (errno == ENOMEM);
250 skipped = true;
252 else
254 ASSERT (wcslen (s) == len);
255 ASSERT (len == n1 + 2);
256 size_t i;
257 for (i = 0; i <= len; i++)
258 s[i] = (i == 0 ? 'x' :
259 i <= n1 ? 'a' :
260 i == n1 + 1 ? 'y' :
261 '\0');
262 free (s);
264 free (s1);
269 else
270 skipped = true;
272 if (test_exit_status != EXIT_SUCCESS)
273 return test_exit_status;
274 if (skipped)
276 fputs ("Skipping test: not enough memory available\n", stderr);
277 return 77;
279 return 0;
280 #endif