Automatic date update in version.in
[binutils-gdb.git] / libiberty / testsuite / test-expandargv.c
blob1e9cb0a0d5a8ea53227373104564fd4fe14014dd
1 /* expandargv test program,
2 Copyright (C) 2006-2024 Free Software Foundation, Inc.
3 Written by Carlos O'Donell <carlos@codesourcery.com>
5 This file is part of the libiberty library, which is part of GCC.
7 This file is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 In addition to the permissions in the GNU General Public License, the
13 Free Software Foundation gives you unlimited permission to link the
14 compiled version of this file into combinations with other programs,
15 and to distribute those combinations without any restriction coming
16 from the use of this file. (The General Public License restrictions
17 do apply in other respects; for example, they cover modification of
18 the file, and distribution when not linked into a combined
19 executable.)
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 #include "libiberty.h"
35 #include <stdio.h>
36 #include <errno.h>
37 #ifdef HAVE_STDLIB_H
38 #include <stdlib.h>
39 #endif
40 #ifdef HAVE_STRING_H
41 #include <string.h>
42 #endif
43 #ifdef HAVE_UNISTD_H
44 #include <unistd.h>
45 #endif
47 #ifndef EXIT_SUCCESS
48 #define EXIT_SUCCESS 0
49 #endif
51 #ifndef EXIT_FAILURE
52 #define EXIT_FAILURE 1
53 #endif
55 static void fatal_error (int, const char *, int) ATTRIBUTE_NORETURN;
56 void writeout_test (int, const char *);
57 void run_replaces (char *);
58 void hook_char_replace (char *, size_t, char, char);
59 int run_tests (const char **);
60 void erase_test (int);
62 /* Test input data, argv before, and argv after:
64 The \n is an important part of test_data since expandargv
65 may have to work in environments where \n is translated
66 as \r\n. Thus \n is included in the test data for the file.
68 We use \b to indicate that the test data is the null character.
69 This is because we use \0 normally to represent the end of the
70 file data, so we need something else for this. */
72 #define FILENAME_PATTERN "test-expandargv-%d.lst"
73 #define ARGV0 "test-expandargv"
75 const char *test_data[] = {
76 /* Test 0 - Check for expansion with \r\n */
77 "a\r\nb", /* Test 0 data */
78 ARGV0,
79 "@test-expandargv-0.lst",
80 0, /* End of argv[] before expansion */
81 ARGV0,
82 "a",
83 "b",
84 0, /* End of argv[] after expansion */
86 /* Test 1 - Check for expansion with \n */
87 "a\nb", /* Test 1 data */
88 ARGV0,
89 "@test-expandargv-1.lst",
91 ARGV0,
92 "a",
93 "b",
96 /* Test 2 - Check for expansion with \0 */
97 "a\bb", /* Test 2 data */
98 ARGV0,
99 "@test-expandargv-2.lst",
101 ARGV0,
102 "a",
105 /* Test 3 - Check for expansion with only \0 */
106 "\b", /* Test 3 data */
107 ARGV0,
108 "@test-expandargv-3.lst",
110 ARGV0,
113 /* Test 4 - Check for options beginning with an empty line. */
114 "\na\nb", /* Test 4 data */
115 ARGV0,
116 "@test-expandargv-4.lst",
118 ARGV0,
119 "a",
120 "b",
123 /* Test 5 - Check for options containing an empty argument. */
124 "a\n''\nb", /* Test 5 data */
125 ARGV0,
126 "@test-expandargv-5.lst",
128 ARGV0,
129 "a",
131 "b",
134 /* Test 6 - Check for options containing a quoted newline. */
135 "a\n'a\n\nb'\nb", /* Test 6 data */
136 ARGV0,
137 "@test-expandargv-6.lst",
139 ARGV0,
140 "a",
141 "a\n\nb",
142 "b",
145 0 /* Test done marker, don't remove. */
148 /* Print a fatal error and exit. LINE is the line number where we
149 detected the error, ERRMSG is the error message to print, and ERR
150 is 0 or an errno value to print. */
152 static void
153 fatal_error (int line, const char *errmsg, int err)
155 fprintf (stderr, "test-expandargv:%d: %s", line, errmsg);
156 if (errno != 0)
157 fprintf (stderr, ": %s", xstrerror (err));
158 fprintf (stderr, "\n");
159 exit (EXIT_FAILURE);
162 /* hook_char_replace:
163 Replace 'replacethis' with 'withthis' */
165 void
166 hook_char_replace (char *string, size_t len, char replacethis, char withthis)
168 int i = 0;
169 for (i = 0; i < len; i++)
170 if (string[i] == replacethis)
171 string[i] = withthis;
174 /* run_replaces:
175 Hook here all the character for character replaces.
176 Be warned that expanding the string or contracting the string
177 should be handled with care. */
179 void
180 run_replaces (char * string)
182 /* Store original string size */
183 size_t len = strlen (string);
184 hook_char_replace (string, len, '\b', '\0');
187 /* write_test:
188 Write test datafile */
190 void
191 writeout_test (int test, const char * test_data)
193 char filename[256];
194 FILE *fd;
195 size_t len, sys_fwrite;
196 char * parse;
198 /* Unique filename per test */
199 sprintf (filename, FILENAME_PATTERN, test);
200 fd = fopen (filename, "w");
201 if (fd == NULL)
202 fatal_error (__LINE__, "Failed to create test file.", errno);
204 /* Generate RW copy of data for replaces */
205 len = strlen (test_data);
206 parse = malloc (sizeof (char) * (len + 1));
207 if (parse == NULL)
208 fatal_error (__LINE__, "Failed to malloc parse.", errno);
210 memcpy (parse, test_data, sizeof (char) * (len + 1));
211 /* Run all possible replaces */
212 run_replaces (parse);
214 sys_fwrite = fwrite (parse, sizeof (char), len, fd);
215 if (sys_fwrite != len)
216 fatal_error (__LINE__, "Failed to write to test file.", errno);
218 free (parse);
219 fclose (fd);
222 /* erase_test:
223 Erase the test file */
225 void
226 erase_test (int test)
228 char filename[256];
229 sprintf (filename, FILENAME_PATTERN, test);
230 if (unlink (filename) != 0)
231 fatal_error (__LINE__, "Failed to erase test file.", errno);
235 /* run_tests:
236 Run expandargv
237 Compare argv before and after.
238 Return number of fails */
241 run_tests (const char **test_data)
243 int argc_after, argc_before;
244 char ** argv_before, ** argv_after;
245 int i, j, k, fails, failed;
247 i = j = fails = 0;
248 /* Loop over all the tests */
249 while (test_data[j])
251 /* Write test data */
252 writeout_test (i, test_data[j++]);
253 /* Copy argv before */
254 argv_before = dupargv ((char **) &test_data[j]);
256 /* Count argc before/after */
257 argc_before = 0;
258 argc_after = 0;
259 while (test_data[j + argc_before])
260 argc_before++;
261 j += argc_before + 1; /* Skip null */
262 while (test_data[j + argc_after])
263 argc_after++;
265 /* Copy argv after */
266 argv_after = dupargv ((char **) &test_data[j]);
268 /* Run all possible replaces */
269 for (k = 0; k < argc_before; k++)
270 run_replaces (argv_before[k]);
271 for (k = 0; k < argc_after; k++)
272 run_replaces (argv_after[k]);
274 /* Run test: Expand arguments */
275 expandargv (&argc_before, &argv_before);
277 failed = 0;
278 /* Compare size first */
279 if (argc_before != argc_after)
281 printf ("FAIL: test-expandargv-%d. Number of arguments don't match.\n", i);
282 failed++;
284 /* Compare each of the argv's ... */
285 else
286 for (k = 0; k < argc_after; k++)
287 if (strcmp (argv_before[k], argv_after[k]) != 0)
289 printf ("FAIL: test-expandargv-%d. Arguments don't match.\n", i);
290 failed++;
293 if (!failed)
294 printf ("PASS: test-expandargv-%d.\n", i);
295 else
296 fails++;
298 freeargv (argv_before);
299 freeargv (argv_after);
300 /* Advance to next test */
301 j += argc_after + 1;
302 /* Erase test file */
303 erase_test (i);
304 i++;
306 return fails;
309 /* main:
310 Run tests.
311 Check result and exit with appropriate code. */
313 int
314 main(int argc, char **argv)
316 int fails;
317 /* Repeat for all the tests:
318 - Parse data array and write into file.
319 - Run replace hooks before writing to file.
320 - Parse data array and build argv before/after.
321 - Run replace hooks on argv before/after
322 - Run expandargv.
323 - Compare output of expandargv argv to after argv.
324 - If they compare the same then test passes
325 else the test fails.
326 - Erase test file. */
328 fails = run_tests (test_data);
329 if (!fails)
330 exit (EXIT_SUCCESS);
331 else
332 exit (EXIT_FAILURE);