More tests.
[kopensolaris-gnu/glibc.git] / posix / wordexp-test.c
1 /* Copyright (C) 1997, 1998 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8
9    The GNU C Library 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 GNU
12    Library General Public License for more details.
13
14    You should have received a copy of the GNU Library General Public
15    License along with the GNU C Library; see the file COPYING.LIB.  If not,
16    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17    Boston, MA 02111-1307, USA.  */
18
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <pwd.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <wordexp.h>
27
28 #define IFS ", \n\t"
29
30 struct test_case_struct
31 {
32   int retval;
33   const char *env;
34   const char *words;
35   int flags;
36   int wordc;
37   const char *wordv[10];
38 } test_case[] =
39   {
40     /* Simple field-splitting */
41     { 0, NULL, "one", 0, 1, { "one", } },
42     { 0, NULL, "one two", 0, 2, { "one", "two", } },
43     { 0, NULL, "one two three", 0, 3, { "one", "two", "three", } },
44     { 0, NULL, " \tfoo\t\tbar ", 0, 2, { "foo", "bar", } },
45     { 0, NULL, "  red  , white blue", 0, 3, { "red", "white", "blue", } },
46
47     /* Simple parameter expansion */
48     { 0, "foo", "${var}", 0, 1, { "foo", } },
49     { 0, "foo", "$var", 0, 1, { "foo", } },
50
51     /* Simple quote removal */
52     { 0, NULL, "\"quoted\"", 0, 1, { "quoted", } },
53     { 0, "foo", "\"$var\"\"$var\"", 0, 1, { "foofoo", } },
54     { 0, NULL, "'singly-quoted'", 0, 1, { "singly-quoted", } },
55
56     /* Simple command substitution */
57     { 0, NULL, "$(echo hello)", 0, 1, { "hello", } },
58     { 0, NULL, "$( (echo hello) )", 0, 1, { "hello", } },
59     { 0, NULL, "$((echo hello);(echo there))", 0, 2, { "hello", "there", } },
60     { 0, NULL, "`echo one two`", 0, 2, { "one", "two", } },
61
62     /* Simple arithmetic expansion */
63     { 0, NULL, "$((1 + 1))", 0, 1, { "2", } },
64     { 0, NULL, "$((2-3))", 0, 1, { "-1", } },
65     { 0, NULL, "$((-1))", 0, 1, { "-1", } },
66     { 0, NULL, "$[50+20]", 0, 1, { "70", } },
67
68     /* Advanced parameter expansion */
69     { 0, NULL, "${var:-bar}", 0, 1, { "bar", } },
70     { 0, NULL, "${var-bar}", 0, 1, { "bar", } },
71     { 0, "", "${var:-bar}", 0, 1, { "bar", } },
72     { 0, "foo", "${var:-bar}", 0, 1, { "foo", } },
73     { 0, "", "${var-bar}", 0, 0, { NULL, } },
74     { 0, NULL, "${var:=bar}", 0, 1, { "bar", } },
75     { 0, NULL, "${var=bar}", 0, 1, { "bar", } },
76     { 0, "", "${var:=bar}", 0, 1, { "bar", } },
77     { 0, "foo", "${var:=bar}", 0, 1, { "foo", } },
78     { 0, "", "${var=bar}", 0, 0, { NULL, } },
79     { 0, "foo", "${var:?bar}", 0, 1, { "foo", } },
80     { 0, NULL, "${var:+bar}", 0, 0, { NULL, } },
81     { 0, NULL, "${var+bar}", 0, 0, { NULL, } },
82     { 0, "", "${var:+bar}", 0, 0, { NULL, } },
83     { 0, "foo", "${var:+bar}", 0, 1, { "bar", } },
84     { 0, "", "${var+bar}", 0, 1, { "bar", } },
85     { 0, "12345", "${#var}", 0, 1, { "5", } },
86
87     { 0, "banana", "${var%na*}", 0, 1, { "bana", } },
88     { 0, "banana", "${var%%na*}", 0, 1, { "ba", } },
89     { 0, "borabora-island", "${var#*bora}", 0, 1, { "bora-island", } },
90     { 0, "borabora-island", "${var##*bora}", 0, 1, {"-island", } },
91
92     /* Pathname expansion */
93     { 0, NULL, "???", 0, 2, { "one", "two", } },
94     { 0, NULL, "[ot]??", 0, 2, { "one", "two", } },
95     { 0, NULL, "t*", 0, 2, { "three", "two", } },
96     { 0, NULL, "\"t\"*", 0, 2, { "three", "two", } },
97
98     /* Nested constructs */
99     { 0, "one two", "$var", 0, 2, { "one", "two", } },
100     { 0, "one two three", "$var", 0, 3, { "one", "two", "three", } },
101     { 0, " \tfoo\t\tbar ", "$var", 0, 2, { "foo", "bar", } },
102     { 0, "  red  , white blue", "$var", 0, 3, { "red", "white", "blue", } },
103     { 0, "  red  , white blue", "\"$var\"", 0, 1, { "  red  , white blue", } },
104     { 0, NULL, "\"$(echo hello there)\"", 0, 1, { "hello there", } },
105     { 0, NULL, "\"$(echo \"hello there\")\"", 0, 1, { "hello there", } },
106     { 0, NULL, "${var=one two} \"$var\"", 0, 3, { "one", "two", "one two", } },
107     { 0, "1", "$(( $(echo 3)+$var ))", 0, 1, { "4", } },
108     { 0, NULL, "\"$(echo \"*\")\"", 0, 1, { "*", } },
109
110     /* Other things that should succeed */
111     { 0, NULL, "\\*\"|&;<>\"\\(\\)\\{\\}", 0, 1, { "*|&;<>(){}", } },
112     { 0, "???", "$var", 0, 1, { "???", } },
113     { 0, NULL, "$var", 0, 0, { NULL, } },
114     { 0, NULL, "\"\\n\"", 0, 1, { "\\n", } },
115     { 0, NULL, "", 0, 0, { NULL, } },
116
117     /* Things that should fail */
118     { WRDE_BADCHAR, NULL, "new\nline", 0, 0, { NULL, } },
119     { WRDE_BADCHAR, NULL, "pipe|symbol", 0, 0, { NULL, } },
120     { WRDE_BADCHAR, NULL, "&ampersand", 0, 0, { NULL, } },
121     { WRDE_BADCHAR, NULL, "semi;colon", 0, 0, { NULL, } },
122     { WRDE_BADCHAR, NULL, "<greater", 0, 0, { NULL, } },
123     { WRDE_BADCHAR, NULL, "less>", 0, 0, { NULL, } },
124     { WRDE_BADCHAR, NULL, "(open-paren", 0, 0, { NULL, } },
125     { WRDE_BADCHAR, NULL, "close-paren)", 0, 0, { NULL, } },
126     { WRDE_BADCHAR, NULL, "{open-brace", 0, 0, { NULL, } },
127     { WRDE_BADCHAR, NULL, "close-brace}", 0, 0, { NULL, } },
128     { WRDE_CMDSUB, NULL, "$(ls)", WRDE_NOCMD, 0, { NULL, } },
129     { WRDE_BADVAL, NULL, "$var", WRDE_UNDEF, 0, { NULL, } },
130     { WRDE_SYNTAX, NULL, "$[50+20))", 0, 0, { NULL, } },
131     { WRDE_SYNTAX, NULL, "${%%noparam}", 0, 0, { NULL, } },
132     { WRDE_SYNTAX, NULL, "${missing-brace", 0, 0, { NULL, } },
133     { WRDE_SYNTAX, NULL, "$((2+))", 0, 0, { NULL, } },
134     { WRDE_SYNTAX, NULL, "`", 0, 0, { NULL, } },
135
136     { -1, NULL, NULL, 0, 0, { NULL, } },
137   };
138
139 static int testit (struct test_case_struct *tc);
140
141 void
142 command_line_test (const char *words)
143 {
144   wordexp_t we;
145   int i;
146   int retval = wordexp (words, &we, 0);
147   printf ("wordexp returned %d\n", retval);
148   for (i = 0; i < we.we_wordc; i++)
149     printf ("we_wordv[%d] = \"%s\"\n", i, we.we_wordv[i]);
150 }
151
152 int
153 main (int argc, char *argv[])
154 {
155   char tmpdir[32];
156   struct passwd *pw;
157   int test;
158   int fail = 0;
159   int fd;
160
161   if (argc > 1)
162     {
163       command_line_test (argv[1]);
164       return 0;
165     }
166
167   setenv ("IFS", IFS, 1);
168
169   /* Set up arena for pathname expansion */
170   tmpnam (tmpdir);
171   if (mkdir (tmpdir, S_IRWXU) ||
172       chdir (tmpdir) ||
173       (fd = creat ("one", S_IRWXU)) == -1 || close (fd) ||
174       (fd = creat ("two", S_IRWXU)) == -1 || close (fd) ||
175       (fd = creat ("three", S_IRWXU)) == -1 || close (fd))
176     return -1;
177
178   for (test = 0; test_case[test].retval != -1; test++)
179     if (testit (&test_case[test]))
180       ++fail;
181
182   pw = getpwnam ("root");
183   if (pw != NULL)
184     {
185       struct test_case_struct ts;
186
187       ts.retval = 0;
188       ts.env = NULL;
189       ts.words = "~root";
190       ts.flags = 0;
191       ts.wordc = 1;
192       ts.wordv[0] = pw->pw_dir;
193
194       if (testit (&ts))
195         ++fail;
196     }
197
198   return fail != 0;
199 }
200
201
202 static int
203 testit (struct test_case_struct *tc)
204 {
205   static int test;
206   int retval;
207   wordexp_t we;
208   int bzzzt = 0;
209   int i;
210
211   if (tc->env)
212     setenv ("var", tc->env, 1);
213   else
214     unsetenv ("var");
215
216   printf ("Test %d: ", ++test);
217   retval = wordexp (tc->words, &we, tc->flags);
218
219   if (retval != tc->retval || (retval != 0 && we.we_wordc != tc->wordc))
220     bzzzt = 1;
221   else
222     for (i = 0; i < we.we_wordc; ++i)
223       if (strcmp (tc->wordv[i], we.we_wordv[i]) != 0)
224         {
225           bzzzt = 1;
226           break;
227         }
228
229   if (bzzzt)
230     {
231       printf ("FAILED\n");
232       printf ("Test words: <%s>, need retval %d, wordc %d\n",
233               tc->words, tc->retval, tc->wordc);
234       printf ("Got retval %d, wordc %d: ", retval, we.we_wordc);
235       for (i = 0; i < we.we_wordc; ++i)
236         printf ("<%s> ", we.we_wordv[i]);
237       printf ("\n");
238     }
239   else
240     printf ("OK\n");
241
242   wordfree (&we);
243
244   return bzzzt;
245 }