1169695Skan/* expandargv test program, 2169695Skan Copyright (C) 2006 Free Software Foundation, Inc. 3169695Skan Written by Carlos O'Donell <carlos@codesourcery.com> 4169695Skan 5169695Skan This file is part of the libiberty library, which is part of GCC. 6169695Skan 7169695Skan This file is free software; you can redistribute it and/or modify 8169695Skan it under the terms of the GNU General Public License as published by 9169695Skan the Free Software Foundation; either version 2 of the License, or 10169695Skan (at your option) any later version. 11169695Skan 12169695Skan In addition to the permissions in the GNU General Public License, the 13169695Skan Free Software Foundation gives you unlimited permission to link the 14169695Skan compiled version of this file into combinations with other programs, 15169695Skan and to distribute those combinations without any restriction coming 16169695Skan from the use of this file. (The General Public License restrictions 17169695Skan do apply in other respects; for example, they cover modification of 18169695Skan the file, and distribution when not linked into a combined 19169695Skan executable.) 20169695Skan 21169695Skan This program is distributed in the hope that it will be useful, 22169695Skan but WITHOUT ANY WARRANTY; without even the implied warranty of 23169695Skan MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24169695Skan GNU General Public License for more details. 25169695Skan 26169695Skan You should have received a copy of the GNU General Public License 27169695Skan along with this program; if not, write to the Free Software 28169695Skan Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. 29169695Skan*/ 30169695Skan 31169695Skan#ifdef HAVE_CONFIG_H 32169695Skan#include "config.h" 33169695Skan#endif 34169695Skan#include "libiberty.h" 35169695Skan#include <stdio.h> 36169695Skan#include <errno.h> 37169695Skan#ifdef HAVE_STDLIB_H 38169695Skan#include <stdlib.h> 39169695Skan#endif 40169695Skan#ifdef HAVE_STRING_H 41169695Skan#include <string.h> 42169695Skan#endif 43169695Skan 44169695Skan#ifndef EXIT_SUCCESS 45169695Skan#define EXIT_SUCCESS 0 46169695Skan#endif 47169695Skan 48169695Skan#ifndef EXIT_FAILURE 49169695Skan#define EXIT_FAILURE 1 50169695Skan#endif 51169695Skan 52169695Skanstatic void fatal_error (int, const char *, int) ATTRIBUTE_NORETURN; 53169695Skanvoid writeout_test (int, const char *); 54169695Skanvoid run_replaces (char *); 55169695Skanvoid hook_char_replace (char *, size_t, char, char); 56169695Skanint run_tests (const char **); 57169695Skanvoid erase_test (int); 58169695Skan 59169695Skan/* Test input data, argv before, and argv after: 60169695Skan 61169695Skan The \n is an important part of test_data since expandargv 62169695Skan may have to work in environments where \n is translated 63169695Skan as \r\n. Thus \n is included in the test data for the file. 64169695Skan 65169695Skan We use \b to indicate that the test data is the null character. 66169695Skan This is because we use \0 normally to represent the end of the 67169695Skan file data, so we need something else for this. */ 68169695Skan 69169695Skan#define FILENAME_PATTERN "test-expandargv-%d.lst" 70169695Skan#define ARGV0 "test-expandargv" 71169695Skan 72169695Skanconst char *test_data[] = { 73169695Skan /* Test 0 - Check for expansion with \r\n */ 74169695Skan "a\r\nb", /* Test 0 data */ 75169695Skan ARGV0, 76169695Skan "@test-expandargv-0.lst", 77169695Skan 0, /* End of argv[] before expansion */ 78169695Skan ARGV0, 79169695Skan "a", 80169695Skan "b", 81169695Skan 0, /* End of argv[] after expansion */ 82169695Skan 83169695Skan /* Test 1 - Check for expansion with \n */ 84169695Skan "a\nb", /* Test 1 data */ 85169695Skan ARGV0, 86169695Skan "@test-expandargv-1.lst", 87169695Skan 0, 88169695Skan ARGV0, 89169695Skan "a", 90169695Skan "b", 91169695Skan 0, 92169695Skan 93169695Skan /* Test 2 - Check for expansion with \0 */ 94169695Skan "a\bb", /* Test 2 data */ 95169695Skan ARGV0, 96169695Skan "@test-expandargv-2.lst", 97169695Skan 0, 98169695Skan ARGV0, 99169695Skan "a", 100169695Skan 0, 101169695Skan 102169695Skan /* Test 3 - Check for expansion with only \0 */ 103169695Skan "\b", /* Test 3 data */ 104169695Skan ARGV0, 105169695Skan "@test-expandargv-3.lst", 106169695Skan 0, 107169695Skan ARGV0, 108169695Skan 0, 109169695Skan 110169695Skan 0 /* Test done marker, don't remove. */ 111169695Skan}; 112169695Skan 113169695Skan/* Print a fatal error and exit. LINE is the line number where we 114169695Skan detected the error, ERRMSG is the error message to print, and ERR 115169695Skan is 0 or an errno value to print. */ 116169695Skan 117169695Skanstatic void 118169695Skanfatal_error (int line, const char *errmsg, int err) 119169695Skan{ 120169695Skan fprintf (stderr, "test-expandargv:%d: %s", line, errmsg); 121169695Skan if (errno != 0) 122169695Skan fprintf (stderr, ": %s", xstrerror (err)); 123169695Skan fprintf (stderr, "\n"); 124169695Skan exit (EXIT_FAILURE); 125169695Skan} 126169695Skan 127169695Skan/* hook_char_replace: 128169695Skan Replace 'replacethis' with 'withthis' */ 129169695Skan 130169695Skanvoid 131169695Skanhook_char_replace (char *string, size_t len, char replacethis, char withthis) 132169695Skan{ 133169695Skan int i = 0; 134169695Skan for (i = 0; i < len; i++) 135169695Skan if (string[i] == replacethis) 136169695Skan string[i] = withthis; 137169695Skan} 138169695Skan 139169695Skan/* run_replaces: 140169695Skan Hook here all the character for character replaces. 141169695Skan Be warned that expanding the string or contracting the string 142169695Skan should be handled with care. */ 143169695Skan 144169695Skanvoid 145169695Skanrun_replaces (char * string) 146169695Skan{ 147169695Skan /* Store original string size */ 148169695Skan size_t len = strlen (string); 149169695Skan hook_char_replace (string, len, '\b', '\0'); 150169695Skan} 151169695Skan 152169695Skan/* write_test: 153169695Skan Write test datafile */ 154169695Skan 155169695Skanvoid 156169695Skanwriteout_test (int test, const char * test_data) 157169695Skan{ 158169695Skan char filename[256]; 159169695Skan FILE *fd; 160169695Skan size_t len; 161169695Skan char * parse; 162169695Skan 163169695Skan /* Unique filename per test */ 164169695Skan sprintf (filename, FILENAME_PATTERN, test); 165169695Skan fd = fopen (filename, "w"); 166169695Skan if (fd == NULL) 167169695Skan fatal_error (__LINE__, "Failed to create test file.", errno); 168169695Skan 169169695Skan /* Generate RW copy of data for replaces */ 170169695Skan len = strlen (test_data); 171169695Skan parse = malloc (sizeof (char) * (len + 1)); 172169695Skan if (parse == NULL) 173169695Skan fatal_error (__LINE__, "Failed to malloc parse.", errno); 174169695Skan 175169695Skan memcpy (parse, test_data, sizeof (char) * len); 176169695Skan /* Run all possible replaces */ 177169695Skan run_replaces (parse); 178169695Skan 179169695Skan fwrite (parse, len, sizeof (char), fd); 180169695Skan free (parse); 181169695Skan fclose (fd); 182169695Skan} 183169695Skan 184169695Skan/* erase_test: 185169695Skan Erase the test file */ 186169695Skan 187169695Skanvoid 188169695Skanerase_test (int test) 189169695Skan{ 190169695Skan char filename[256]; 191169695Skan sprintf (filename, FILENAME_PATTERN, test); 192169695Skan if (unlink (filename) != 0) 193169695Skan fatal_error (__LINE__, "Failed to erase test file.", errno); 194169695Skan} 195169695Skan 196169695Skan 197169695Skan/* run_tests: 198169695Skan Run expandargv 199169695Skan Compare argv before and after. 200169695Skan Return number of fails */ 201169695Skan 202169695Skanint 203169695Skanrun_tests (const char **test_data) 204169695Skan{ 205169695Skan int argc_after, argc_before; 206169695Skan char ** argv_before, ** argv_after; 207169695Skan int i, j, k, fails, failed; 208169695Skan 209169695Skan i = j = fails = 0; 210169695Skan /* Loop over all the tests */ 211169695Skan while (test_data[j]) 212169695Skan { 213169695Skan /* Write test data */ 214169695Skan writeout_test (i, test_data[j++]); 215169695Skan /* Copy argv before */ 216169695Skan argv_before = dupargv ((char **) &test_data[j]); 217169695Skan 218169695Skan /* Count argc before/after */ 219169695Skan argc_before = 0; 220169695Skan argc_after = 0; 221169695Skan while (test_data[j + argc_before]) 222169695Skan argc_before++; 223169695Skan j += argc_before + 1; /* Skip null */ 224169695Skan while (test_data[j + argc_after]) 225169695Skan argc_after++; 226169695Skan 227169695Skan /* Copy argv after */ 228169695Skan argv_after = dupargv ((char **) &test_data[j]); 229169695Skan 230169695Skan /* Run all possible replaces */ 231169695Skan for (k = 0; k < argc_before; k++) 232169695Skan run_replaces (argv_before[k]); 233169695Skan for (k = 0; k < argc_after; k++) 234169695Skan run_replaces (argv_after[k]); 235169695Skan 236169695Skan /* Run test: Expand arguments */ 237169695Skan expandargv (&argc_before, &argv_before); 238169695Skan 239169695Skan failed = 0; 240169695Skan /* Compare size first */ 241169695Skan if (argc_before != argc_after) 242169695Skan { 243169695Skan printf ("FAIL: test-expandargv-%d. Number of arguments don't match.\n", i); 244169695Skan failed++; 245169695Skan } 246169695Skan /* Compare each of the argv's ... */ 247169695Skan else 248169695Skan for (k = 0; k < argc_after; k++) 249169695Skan if (strncmp (argv_before[k], argv_after[k], strlen(argv_after[k])) != 0) 250169695Skan { 251169695Skan printf ("FAIL: test-expandargv-%d. Arguments don't match.\n", i); 252169695Skan failed++; 253169695Skan } 254169695Skan 255169695Skan if (!failed) 256169695Skan printf ("PASS: test-expandargv-%d.\n", i); 257169695Skan else 258169695Skan fails++; 259169695Skan 260169695Skan freeargv (argv_before); 261169695Skan freeargv (argv_after); 262169695Skan /* Advance to next test */ 263169695Skan j += argc_after + 1; 264169695Skan /* Erase test file */ 265169695Skan erase_test (i); 266169695Skan i++; 267169695Skan } 268169695Skan return fails; 269169695Skan} 270169695Skan 271169695Skan/* main: 272169695Skan Run tests. 273169695Skan Check result and exit with appropriate code. */ 274169695Skan 275169695Skanint 276169695Skanmain(int argc, char **argv) 277169695Skan{ 278169695Skan int fails; 279169695Skan /* Repeat for all the tests: 280169695Skan - Parse data array and write into file. 281169695Skan - Run replace hooks before writing to file. 282169695Skan - Parse data array and build argv before/after. 283169695Skan - Run replace hooks on argv before/after 284169695Skan - Run expandargv. 285169695Skan - Compare output of expandargv argv to after argv. 286169695Skan - If they compare the same then test passes 287169695Skan else the test fails. 288169695Skan - Erase test file. */ 289169695Skan 290169695Skan fails = run_tests (test_data); 291169695Skan if (!fails) 292169695Skan exit (EXIT_SUCCESS); 293169695Skan else 294169695Skan exit (EXIT_FAILURE); 295169695Skan} 296169695Skan 297