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
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.
34 #include "libiberty.h"
48 #define EXIT_SUCCESS 0
52 #define EXIT_FAILURE 1
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 */
79 "@test-expandargv-0.lst",
80 0, /* End of argv[] before expansion */
84 0, /* End of argv[] after expansion */
86 /* Test 1 - Check for expansion with \n */
87 "a\nb", /* Test 1 data */
89 "@test-expandargv-1.lst",
96 /* Test 2 - Check for expansion with \0 */
97 "a\bb", /* Test 2 data */
99 "@test-expandargv-2.lst",
105 /* Test 3 - Check for expansion with only \0 */
106 "\b", /* Test 3 data */
108 "@test-expandargv-3.lst",
113 /* Test 4 - Check for options beginning with an empty line. */
114 "\na\nb", /* Test 4 data */
116 "@test-expandargv-4.lst",
123 /* Test 5 - Check for options containing an empty argument. */
124 "a\n''\nb", /* Test 5 data */
126 "@test-expandargv-5.lst",
134 /* Test 6 - Check for options containing a quoted newline. */
135 "a\n'a\n\nb'\nb", /* Test 6 data */
137 "@test-expandargv-6.lst",
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. */
153 fatal_error (int line
, const char *errmsg
, int err
)
155 fprintf (stderr
, "test-expandargv:%d: %s", line
, errmsg
);
157 fprintf (stderr
, ": %s", xstrerror (err
));
158 fprintf (stderr
, "\n");
162 /* hook_char_replace:
163 Replace 'replacethis' with 'withthis' */
166 hook_char_replace (char *string
, size_t len
, char replacethis
, char withthis
)
169 for (i
= 0; i
< len
; i
++)
170 if (string
[i
] == replacethis
)
171 string
[i
] = withthis
;
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. */
180 run_replaces (char * string
)
182 /* Store original string size */
183 size_t len
= strlen (string
);
184 hook_char_replace (string
, len
, '\b', '\0');
188 Write test datafile */
191 writeout_test (int test
, const char * test_data
)
195 size_t len
, sys_fwrite
;
198 /* Unique filename per test */
199 sprintf (filename
, FILENAME_PATTERN
, test
);
200 fd
= fopen (filename
, "w");
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));
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
);
223 Erase the test file */
226 erase_test (int test
)
229 sprintf (filename
, FILENAME_PATTERN
, test
);
230 if (unlink (filename
) != 0)
231 fatal_error (__LINE__
, "Failed to erase test file.", errno
);
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
;
248 /* Loop over all the tests */
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 */
259 while (test_data
[j
+ argc_before
])
261 j
+= argc_before
+ 1; /* Skip null */
262 while (test_data
[j
+ 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
);
278 /* Compare size first */
279 if (argc_before
!= argc_after
)
281 printf ("FAIL: test-expandargv-%d. Number of arguments don't match.\n", i
);
284 /* Compare each of the argv's ... */
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
);
294 printf ("PASS: test-expandargv-%d.\n", i
);
298 freeargv (argv_before
);
299 freeargv (argv_after
);
300 /* Advance to next test */
302 /* Erase test file */
311 Check result and exit with appropriate code. */
314 main(int argc
, char **argv
)
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
323 - Compare output of expandargv argv to after argv.
324 - If they compare the same then test passes
326 - Erase test file. */
328 fails
= run_tests (test_data
);