blob: cfcb1bd3e1dbd7938098367566f455829bd27879 [file] [log] [blame]
Francis Laniel91ec8702023-12-22 22:02:24 +01001// SPDX-License-Identifier: GPL-2.0
2/*
3 * (C) Copyright 2021
4 * Francis Laniel, Amarula Solutions, francis.laniel@amarulasolutions.com
5 */
6
Francis Laniel91ec8702023-12-22 22:02:24 +01007#include <command.h>
8#include <env_attr.h>
9#include <test/hush.h>
10#include <test/ut.h>
Francis Laniel0c0495c2023-12-22 22:02:37 +010011#include <asm/global_data.h>
12
13DECLARE_GLOBAL_DATA_PTR;
Francis Laniel91ec8702023-12-22 22:02:24 +010014
15static int hush_test_simple_dollar(struct unit_test_state *uts)
16{
17 console_record_reset_enable();
18 ut_assertok(run_command("echo $dollar_foo", 0));
19 ut_assert_nextline_empty();
20 ut_assert_console_end();
21
22 ut_assertok(run_command("echo ${dollar_foo}", 0));
23 ut_assert_nextline_empty();
24 ut_assert_console_end();
25
26 ut_assertok(run_command("dollar_foo=bar", 0));
27
28 ut_assertok(run_command("echo $dollar_foo", 0));
29 ut_assert_nextline("bar");
30 ut_assert_console_end();
31
32 ut_assertok(run_command("echo ${dollar_foo}", 0));
33 ut_assert_nextline("bar");
34 ut_assert_console_end();
35
36 ut_assertok(run_command("dollar_foo=\\$bar", 0));
37
38 ut_assertok(run_command("echo $dollar_foo", 0));
39 ut_assert_nextline("$bar");
40 ut_assert_console_end();
41
42 ut_assertok(run_command("dollar_foo='$bar'", 0));
43
44 ut_assertok(run_command("echo $dollar_foo", 0));
45 ut_assert_nextline("$bar");
46 ut_assert_console_end();
47
48 ut_asserteq(1, run_command("dollar_foo=bar quux", 0));
49 /* Next line contains error message */
50 ut_assert_skipline();
51 ut_assert_console_end();
52
53 ut_asserteq(1, run_command("dollar_foo='bar quux", 0));
54 /* Next line contains error message */
55 ut_assert_skipline();
Ion Agorriadd847ea2024-09-03 19:09:42 +020056 ut_assert_console_end();
Francis Laniel91ec8702023-12-22 22:02:24 +010057
58 ut_asserteq(1, run_command("dollar_foo=bar quux\"", 0));
Ion Agorriadd847ea2024-09-03 19:09:42 +020059 /* Next line contains error message */
Francis Laniel91ec8702023-12-22 22:02:24 +010060 ut_assert_skipline();
Ion Agorriadd847ea2024-09-03 19:09:42 +020061 /*
62 * Old parser prints the error message on two lines:
63 * Unknown command 'quux
64 * ' - try 'help'
65 * While the new only prints it on one:
66 * syntax error: unterminated \"
67 */
68 if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
69 ut_assert_skipline();
Tom Rinida3ae1f2024-01-18 11:38:25 -050070 }
Ion Agorriadd847ea2024-09-03 19:09:42 +020071 ut_assert_console_end();
Francis Laniel91ec8702023-12-22 22:02:24 +010072
73 ut_assertok(run_command("dollar_foo='bar \"quux'", 0));
74
75 ut_assertok(run_command("echo $dollar_foo", 0));
76 /*
77 * This one is buggy.
78 * ut_assert_nextline("bar \"quux");
79 * ut_assert_console_end();
80 *
81 * So, let's reset output:
82 */
83 console_record_reset_enable();
84
Francis Laniel0c0495c2023-12-22 22:02:37 +010085 if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
86 /*
87 * Old parser returns an error because it waits for closing
88 * '\'', but this behavior is wrong as the '\'' is surrounded by
89 * '"', so no need to wait for a closing one.
90 */
91 ut_assertok(run_command("dollar_foo=\"bar 'quux\"", 0));
92
93 ut_assertok(run_command("echo $dollar_foo", 0));
94 ut_assert_nextline("bar 'quux");
95 ut_assert_console_end();
96 } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
97 ut_asserteq(1, run_command("dollar_foo=\"bar 'quux\"", 0));
98 /* Next line contains error message */
99 ut_assert_skipline();
100 ut_assert_console_end();
101 }
Francis Laniel91ec8702023-12-22 22:02:24 +0100102
103 ut_assertok(run_command("dollar_foo='bar quux'", 0));
104 ut_assertok(run_command("echo $dollar_foo", 0));
105 ut_assert_nextline("bar quux");
106 ut_assert_console_end();
107
Francis Laniel0c0495c2023-12-22 22:02:37 +0100108 if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
109 /* Reset local variable. */
110 ut_assertok(run_command("dollar_foo=", 0));
111 } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
112 puts("Beware: this test set local variable dollar_foo and it cannot be unset!");
113 }
Francis Laniel91ec8702023-12-22 22:02:24 +0100114
115 return 0;
116}
117HUSH_TEST(hush_test_simple_dollar, 0);
118
119static int hush_test_env_dollar(struct unit_test_state *uts)
120{
121 env_set("env_foo", "bar");
122 console_record_reset_enable();
123
124 ut_assertok(run_command("echo $env_foo", 0));
125 ut_assert_nextline("bar");
126 ut_assert_console_end();
127
128 ut_assertok(run_command("echo ${env_foo}", 0));
129 ut_assert_nextline("bar");
130 ut_assert_console_end();
131
132 /* Environment variables have priority over local variable */
133 ut_assertok(run_command("env_foo=quux", 0));
134 ut_assertok(run_command("echo ${env_foo}", 0));
135 ut_assert_nextline("bar");
136 ut_assert_console_end();
137
138 /* Clean up setting the variable */
139 env_set("env_foo", NULL);
140
Francis Laniel0c0495c2023-12-22 22:02:37 +0100141 if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
142 /* Reset local variable. */
143 ut_assertok(run_command("env_foo=", 0));
144 } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
145 puts("Beware: this test set local variable env_foo and it cannot be unset!");
146 }
Francis Laniel91ec8702023-12-22 22:02:24 +0100147
148 return 0;
149}
150HUSH_TEST(hush_test_env_dollar, 0);
151
152static int hush_test_command_dollar(struct unit_test_state *uts)
153{
154 console_record_reset_enable();
155
156 ut_assertok(run_command("dollar_bar=\"echo bar\"", 0));
157
158 ut_assertok(run_command("$dollar_bar", 0));
159 ut_assert_nextline("bar");
160 ut_assert_console_end();
161
162 ut_assertok(run_command("${dollar_bar}", 0));
163 ut_assert_nextline("bar");
164 ut_assert_console_end();
165
166 ut_assertok(run_command("dollar_bar=\"echo\nbar\"", 0));
167
168 ut_assertok(run_command("$dollar_bar", 0));
169 ut_assert_nextline("bar");
170 ut_assert_console_end();
171
172 ut_assertok(run_command("dollar_bar='echo bar\n'", 0));
173
174 ut_assertok(run_command("$dollar_bar", 0));
175 ut_assert_nextline("bar");
176 ut_assert_console_end();
177
178 ut_assertok(run_command("dollar_bar='echo bar\\n'", 0));
179
180 ut_assertok(run_command("$dollar_bar", 0));
Francis Laniel0c0495c2023-12-22 22:02:37 +0100181
182 if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
183 /*
184 * This difference seems to come from a bug solved in Busybox
185 * hush.
186 * Behavior of hush 2021 is coherent with bash and other shells.
187 */
188 ut_assert_nextline("bar\\n");
189 } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
190 ut_assert_nextline("barn");
191 }
192
Francis Laniel91ec8702023-12-22 22:02:24 +0100193 ut_assert_console_end();
194
195 ut_assertok(run_command("dollar_bar='echo $bar'", 0));
196
197 ut_assertok(run_command("$dollar_bar", 0));
198 ut_assert_nextline("$bar");
199 ut_assert_console_end();
200
201 ut_assertok(run_command("dollar_quux=quux", 0));
202 ut_assertok(run_command("dollar_bar=\"echo $dollar_quux\"", 0));
203
204 ut_assertok(run_command("$dollar_bar", 0));
205 ut_assert_nextline("quux");
206 ut_assert_console_end();
207
Francis Laniel0c0495c2023-12-22 22:02:37 +0100208 if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
209 /* Reset local variables. */
210 ut_assertok(run_command("dollar_bar=", 0));
211 ut_assertok(run_command("dollar_quux=", 0));
212 } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
213 puts("Beware: this test sets local variable dollar_bar and dollar_quux and they cannot be unset!");
214 }
Francis Laniel91ec8702023-12-22 22:02:24 +0100215
216 return 0;
217}
218HUSH_TEST(hush_test_command_dollar, 0);