1 | /* GLIB - Library of useful routines for C programming |
2 | * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald |
3 | * |
4 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Lesser General Public |
6 | * License as published by the Free Software Foundation; either |
7 | * version 2.1 of the License, or (at your option) any later version. |
8 | * |
9 | * This 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 | * Lesser General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Lesser General Public |
15 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
16 | */ |
17 | |
18 | /* |
19 | * Modified by the GLib Team and others 1997-2000. See the AUTHORS |
20 | * file for a list of people on the GLib Team. See the ChangeLog |
21 | * files for a list of changes. These files are distributed with |
22 | * GLib at ftp://ftp.gtk.org/pub/gtk/. |
23 | */ |
24 | |
25 | #undef G_DISABLE_ASSERT |
26 | #undef G_LOG_DOMAIN |
27 | |
28 | #include <glib.h> |
29 | #include <stdio.h> |
30 | #include <string.h> |
31 | #include <stdlib.h> |
32 | |
33 | |
34 | typedef struct _CmdlineTest CmdlineTest; |
35 | |
36 | struct _CmdlineTest |
37 | { |
38 | const gchar *cmdline; |
39 | gint argc; |
40 | const gchar *argv[10]; |
41 | gint error_code; |
42 | }; |
43 | |
44 | static CmdlineTest cmdline_tests[] = |
45 | { |
46 | { "foo bar" , 2, { "foo" , "bar" , NULL }, -1 }, |
47 | { "foo 'bar'" , 2, { "foo" , "bar" , NULL }, -1 }, |
48 | { "foo \"bar\"" , 2, { "foo" , "bar" , NULL }, -1 }, |
49 | { "foo '' 'bar'" , 3, { "foo" , "" , "bar" , NULL }, -1 }, |
50 | { "foo \"bar\"'baz'blah'foo'\\''blah'\"boo\"" , 2, { "foo" , "barbazblahfoo'blahboo" , NULL }, -1 }, |
51 | { "foo \t \tblah\tfoo\t\tbar baz" , 5, { "foo" , "blah" , "foo" , "bar" , "baz" , NULL }, -1 }, |
52 | { "foo ' spaces more spaces lots of spaces in this ' \t" , 2, { "foo" , " spaces more spaces lots of spaces in this " , NULL }, -1 }, |
53 | { "foo \\\nbar" , 2, { "foo" , "bar" , NULL }, -1 }, |
54 | { "foo '' ''" , 3, { "foo" , "" , "" , NULL }, -1 }, |
55 | { "foo \\\" la la la" , 5, { "foo" , "\"" , "la" , "la" , "la" , NULL }, -1 }, |
56 | { "foo \\ foo woo woo\\ " , 4, { "foo" , " foo" , "woo" , "woo " , NULL }, -1 }, |
57 | { "foo \"yada yada \\$\\\"\"" , 2, { "foo" , "yada yada $\"" , NULL }, -1 }, |
58 | { "foo \"c:\\\\\"" , 2, { "foo" , "c:\\" , NULL }, -1 }, |
59 | { "foo # bla bla bla\n bar" , 2, { "foo" , "bar" , NULL }, -1 }, |
60 | { "foo a#b" , 2, { "foo" , "a#b" , NULL }, -1 }, |
61 | { "#foo" , 0, { NULL }, G_SHELL_ERROR_EMPTY_STRING }, |
62 | { "foo bar \\" , 0, { NULL }, G_SHELL_ERROR_BAD_QUOTING }, |
63 | { "foo 'bar baz" , 0, { NULL }, G_SHELL_ERROR_BAD_QUOTING }, |
64 | { "foo '\"bar\" baz" , 0, { NULL }, G_SHELL_ERROR_BAD_QUOTING }, |
65 | { "" , 0, { NULL }, G_SHELL_ERROR_EMPTY_STRING }, |
66 | { " " , 0, { NULL }, G_SHELL_ERROR_EMPTY_STRING }, |
67 | { "# foo bar" , 0, { NULL }, G_SHELL_ERROR_EMPTY_STRING }, |
68 | {"foo '/bar/summer'\\''09 tours.pdf'" , 2, {"foo" , "/bar/summer'09 tours.pdf" , NULL}, -1} |
69 | }; |
70 | |
71 | static void |
72 | do_cmdline_test (gconstpointer d) |
73 | { |
74 | const CmdlineTest *test = d; |
75 | gint argc; |
76 | gchar **argv; |
77 | GError *err; |
78 | gboolean res; |
79 | |
80 | err = NULL; |
81 | g_printerr (format: "test cmdline: %s\n" , test->cmdline); |
82 | res = g_shell_parse_argv (command_line: test->cmdline, argcp: &argc, argvp: &argv, error: &err); |
83 | if (test->error_code == -1) |
84 | { |
85 | g_assert (res); |
86 | g_assert_cmpint (argc, ==, test->argc); |
87 | g_assert (g_strv_equal ((const gchar * const *) argv, (const gchar * const *) test->argv)); |
88 | g_assert_no_error (err); |
89 | } |
90 | else |
91 | { |
92 | g_assert (!res); |
93 | g_assert_error (err, G_SHELL_ERROR, test->error_code); |
94 | } |
95 | |
96 | if (err) |
97 | g_error_free (error: err); |
98 | if (res) |
99 | g_strfreev (str_array: argv); |
100 | } |
101 | |
102 | typedef struct _QuoteTest QuoteTest; |
103 | |
104 | struct _QuoteTest |
105 | { |
106 | const gchar *in; |
107 | const gchar *out; |
108 | }; |
109 | |
110 | static QuoteTest quote_tests[] = |
111 | { |
112 | { "" , "''" }, |
113 | { "a" , "'a'" }, |
114 | { "(" , "'('" }, |
115 | { "'" , "''\\'''" }, |
116 | { "'a" , "''\\''a'" }, |
117 | { "a'" , "'a'\\'''" }, |
118 | { "a'a" , "'a'\\''a'" } |
119 | }; |
120 | |
121 | static void |
122 | do_quote_test (gconstpointer d) |
123 | { |
124 | const QuoteTest *test = d; |
125 | gchar *out; |
126 | |
127 | out = g_shell_quote (unquoted_string: test->in); |
128 | g_assert_cmpstr (out, ==, test->out); |
129 | g_free (mem: out); |
130 | } |
131 | |
132 | typedef struct _UnquoteTest UnquoteTest; |
133 | |
134 | struct _UnquoteTest |
135 | { |
136 | const gchar *in; |
137 | const gchar *out; |
138 | gint error_code; |
139 | }; |
140 | |
141 | static UnquoteTest unquote_tests[] = |
142 | { |
143 | { "" , "" , -1 }, |
144 | { "a" , "a" , -1 }, |
145 | { "'a'" , "a" , -1 }, |
146 | { "'('" , "(" , -1 }, |
147 | { "''\\'''" , "'" , -1 }, |
148 | { "''\\''a'" , "'a" , -1 }, |
149 | { "'a'\\'''" , "a'" , -1 }, |
150 | { "'a'\\''a'" , "a'a" , -1 }, |
151 | { "\\\\" , "\\" , -1 }, |
152 | { "\\\n" , "" , -1 }, |
153 | { "'\\''" , NULL, G_SHELL_ERROR_BAD_QUOTING }, |
154 | { "\"\\\"\"" , "\"" , -1 }, |
155 | { "\"" , NULL, G_SHELL_ERROR_BAD_QUOTING }, |
156 | { "'" , NULL, G_SHELL_ERROR_BAD_QUOTING }, |
157 | { "\x22\\\\\"" , "\\" , -1 }, |
158 | { "\x22\\`\"" , "`" , -1 }, |
159 | { "\x22\\$\"" , "$" , -1 }, |
160 | { "\x22\\\n\"" , "\n" , -1 }, |
161 | { "\"\\'\"" , "\\'" , -1 }, |
162 | { "\x22\\\r\"" , "\\\r" , -1 }, |
163 | { "\x22\\n\"" , "\\n" , -1 } |
164 | }; |
165 | |
166 | static void |
167 | do_unquote_test (gconstpointer d) |
168 | { |
169 | const UnquoteTest *test = d; |
170 | gchar *out; |
171 | GError *error; |
172 | |
173 | error = NULL; |
174 | out = g_shell_unquote (quoted_string: test->in, error: &error); |
175 | g_assert_cmpstr (out, ==, test->out); |
176 | if (test->error_code == -1) |
177 | g_assert_no_error (error); |
178 | else |
179 | g_assert_error (error, G_SHELL_ERROR, test->error_code); |
180 | |
181 | g_free (mem: out); |
182 | if (error) |
183 | g_error_free (error); |
184 | } |
185 | |
186 | int |
187 | main (int argc, char *argv[]) |
188 | { |
189 | gsize i; |
190 | gchar *path; |
191 | |
192 | g_test_init (argc: &argc, argv: &argv, NULL); |
193 | |
194 | for (i = 0; i < G_N_ELEMENTS (cmdline_tests); i++) |
195 | { |
196 | path = g_strdup_printf (format: "/shell/cmdline/%" G_GSIZE_FORMAT, i); |
197 | g_test_add_data_func (testpath: path, test_data: &cmdline_tests[i], test_func: do_cmdline_test); |
198 | g_free (mem: path); |
199 | } |
200 | |
201 | for (i = 0; i < G_N_ELEMENTS (quote_tests); i++) |
202 | { |
203 | path = g_strdup_printf (format: "/shell/quote/%" G_GSIZE_FORMAT, i); |
204 | g_test_add_data_func (testpath: path, test_data: "e_tests[i], test_func: do_quote_test); |
205 | g_free (mem: path); |
206 | } |
207 | |
208 | for (i = 0; i < G_N_ELEMENTS (unquote_tests); i++) |
209 | { |
210 | path = g_strdup_printf (format: "/shell/unquote/%" G_GSIZE_FORMAT, i); |
211 | g_test_add_data_func (testpath: path, test_data: &unquote_tests[i], test_func: do_unquote_test); |
212 | g_free (mem: path); |
213 | } |
214 | |
215 | return g_test_run (); |
216 | } |
217 | |