blob: 077dcd62c0e227b55d15f9b0c082c72378562d7a [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{
Francis Laniel91ec8702023-12-22 22:02:24 +010017 ut_assertok(run_command("echo $dollar_foo", 0));
18 ut_assert_nextline_empty();
19 ut_assert_console_end();
20
21 ut_assertok(run_command("echo ${dollar_foo}", 0));
22 ut_assert_nextline_empty();
23 ut_assert_console_end();
24
25 ut_assertok(run_command("dollar_foo=bar", 0));
26
27 ut_assertok(run_command("echo $dollar_foo", 0));
28 ut_assert_nextline("bar");
29 ut_assert_console_end();
30
31 ut_assertok(run_command("echo ${dollar_foo}", 0));
32 ut_assert_nextline("bar");
33 ut_assert_console_end();
34
35 ut_assertok(run_command("dollar_foo=\\$bar", 0));
36
37 ut_assertok(run_command("echo $dollar_foo", 0));
38 ut_assert_nextline("$bar");
39 ut_assert_console_end();
40
41 ut_assertok(run_command("dollar_foo='$bar'", 0));
42
43 ut_assertok(run_command("echo $dollar_foo", 0));
44 ut_assert_nextline("$bar");
45 ut_assert_console_end();
46
47 ut_asserteq(1, run_command("dollar_foo=bar quux", 0));
48 /* Next line contains error message */
49 ut_assert_skipline();
50 ut_assert_console_end();
51
52 ut_asserteq(1, run_command("dollar_foo='bar quux", 0));
53 /* Next line contains error message */
54 ut_assert_skipline();
Ion Agorriadd847ea2024-09-03 19:09:42 +020055 ut_assert_console_end();
Francis Laniel91ec8702023-12-22 22:02:24 +010056
57 ut_asserteq(1, run_command("dollar_foo=bar quux\"", 0));
Ion Agorriadd847ea2024-09-03 19:09:42 +020058 /* Next line contains error message */
Francis Laniel91ec8702023-12-22 22:02:24 +010059 ut_assert_skipline();
Ion Agorriadd847ea2024-09-03 19:09:42 +020060 /*
61 * Old parser prints the error message on two lines:
62 * Unknown command 'quux
63 * ' - try 'help'
64 * While the new only prints it on one:
65 * syntax error: unterminated \"
66 */
67 if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
68 ut_assert_skipline();
Tom Rinida3ae1f2024-01-18 11:38:25 -050069 }
Ion Agorriadd847ea2024-09-03 19:09:42 +020070 ut_assert_console_end();
Francis Laniel91ec8702023-12-22 22:02:24 +010071
72 ut_assertok(run_command("dollar_foo='bar \"quux'", 0));
73
74 ut_assertok(run_command("echo $dollar_foo", 0));
75 /*
76 * This one is buggy.
77 * ut_assert_nextline("bar \"quux");
78 * ut_assert_console_end();
79 *
80 * So, let's reset output:
81 */
82 console_record_reset_enable();
83
Francis Laniel0c0495c2023-12-22 22:02:37 +010084 if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
85 /*
86 * Old parser returns an error because it waits for closing
87 * '\'', but this behavior is wrong as the '\'' is surrounded by
88 * '"', so no need to wait for a closing one.
89 */
90 ut_assertok(run_command("dollar_foo=\"bar 'quux\"", 0));
91
92 ut_assertok(run_command("echo $dollar_foo", 0));
93 ut_assert_nextline("bar 'quux");
94 ut_assert_console_end();
95 } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
96 ut_asserteq(1, run_command("dollar_foo=\"bar 'quux\"", 0));
97 /* Next line contains error message */
98 ut_assert_skipline();
99 ut_assert_console_end();
100 }
Francis Laniel91ec8702023-12-22 22:02:24 +0100101
102 ut_assertok(run_command("dollar_foo='bar quux'", 0));
103 ut_assertok(run_command("echo $dollar_foo", 0));
104 ut_assert_nextline("bar quux");
105 ut_assert_console_end();
106
Francis Laniel0c0495c2023-12-22 22:02:37 +0100107 if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
108 /* Reset local variable. */
109 ut_assertok(run_command("dollar_foo=", 0));
110 } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
111 puts("Beware: this test set local variable dollar_foo and it cannot be unset!");
112 }
Francis Laniel91ec8702023-12-22 22:02:24 +0100113
114 return 0;
115}
Simon Glassf8dc3792024-08-22 07:58:00 -0600116HUSH_TEST(hush_test_simple_dollar, UTF_CONSOLE);
Francis Laniel91ec8702023-12-22 22:02:24 +0100117
118static int hush_test_env_dollar(struct unit_test_state *uts)
119{
120 env_set("env_foo", "bar");
Francis Laniel91ec8702023-12-22 22:02:24 +0100121
122 ut_assertok(run_command("echo $env_foo", 0));
123 ut_assert_nextline("bar");
124 ut_assert_console_end();
125
126 ut_assertok(run_command("echo ${env_foo}", 0));
127 ut_assert_nextline("bar");
128 ut_assert_console_end();
129
130 /* Environment variables have priority over local variable */
131 ut_assertok(run_command("env_foo=quux", 0));
132 ut_assertok(run_command("echo ${env_foo}", 0));
133 ut_assert_nextline("bar");
134 ut_assert_console_end();
135
136 /* Clean up setting the variable */
137 env_set("env_foo", NULL);
138
Francis Laniel0c0495c2023-12-22 22:02:37 +0100139 if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
140 /* Reset local variable. */
141 ut_assertok(run_command("env_foo=", 0));
142 } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
143 puts("Beware: this test set local variable env_foo and it cannot be unset!");
144 }
Francis Laniel91ec8702023-12-22 22:02:24 +0100145
146 return 0;
147}
Simon Glassf8dc3792024-08-22 07:58:00 -0600148HUSH_TEST(hush_test_env_dollar, UTF_CONSOLE);
Francis Laniel91ec8702023-12-22 22:02:24 +0100149
150static int hush_test_command_dollar(struct unit_test_state *uts)
151{
Francis Laniel91ec8702023-12-22 22:02:24 +0100152 ut_assertok(run_command("dollar_bar=\"echo bar\"", 0));
153
154 ut_assertok(run_command("$dollar_bar", 0));
155 ut_assert_nextline("bar");
156 ut_assert_console_end();
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=\"echo\nbar\"", 0));
163
164 ut_assertok(run_command("$dollar_bar", 0));
165 ut_assert_nextline("bar");
166 ut_assert_console_end();
167
168 ut_assertok(run_command("dollar_bar='echo bar\n'", 0));
169
170 ut_assertok(run_command("$dollar_bar", 0));
171 ut_assert_nextline("bar");
172 ut_assert_console_end();
173
174 ut_assertok(run_command("dollar_bar='echo bar\\n'", 0));
175
176 ut_assertok(run_command("$dollar_bar", 0));
Francis Laniel0c0495c2023-12-22 22:02:37 +0100177
178 if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
179 /*
180 * This difference seems to come from a bug solved in Busybox
181 * hush.
182 * Behavior of hush 2021 is coherent with bash and other shells.
183 */
184 ut_assert_nextline("bar\\n");
185 } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
186 ut_assert_nextline("barn");
187 }
188
Francis Laniel91ec8702023-12-22 22:02:24 +0100189 ut_assert_console_end();
190
191 ut_assertok(run_command("dollar_bar='echo $bar'", 0));
192
193 ut_assertok(run_command("$dollar_bar", 0));
194 ut_assert_nextline("$bar");
195 ut_assert_console_end();
196
197 ut_assertok(run_command("dollar_quux=quux", 0));
198 ut_assertok(run_command("dollar_bar=\"echo $dollar_quux\"", 0));
199
200 ut_assertok(run_command("$dollar_bar", 0));
201 ut_assert_nextline("quux");
202 ut_assert_console_end();
203
Francis Laniel0c0495c2023-12-22 22:02:37 +0100204 if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
205 /* Reset local variables. */
206 ut_assertok(run_command("dollar_bar=", 0));
207 ut_assertok(run_command("dollar_quux=", 0));
208 } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
209 puts("Beware: this test sets local variable dollar_bar and dollar_quux and they cannot be unset!");
210 }
Francis Laniel91ec8702023-12-22 22:02:24 +0100211
212 return 0;
213}
Simon Glassf8dc3792024-08-22 07:58:00 -0600214HUSH_TEST(hush_test_command_dollar, UTF_CONSOLE);