1 # SPDX-License-Identifier: GPL-2.0
2 # Copyright (c) 2015 Stephen Warren
3 # Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
5 # Test operation of shell commands relating to environment variables.
10 # FIXME: This might be useful for other tests;
11 # perhaps refactor it into ConsoleBase or some other state object?
12 class StateTestEnv(object):
13 """Container that represents the state of all U-Boot environment variables.
14 This enables quick determination of existant/non-existant variable
18 def __init__(self, u_boot_console):
19 """Initialize a new StateTestEnv object.
22 u_boot_console: A U-Boot console.
28 self.u_boot_console = u_boot_console
30 self.set_var = self.get_non_existent_var()
33 """Read all current environment variables from U-Boot.
42 if self.u_boot_console.config.buildconfig.get(
43 'config_version_variable', 'n') == 'y':
44 with self.u_boot_console.disable_check('main_signon'):
45 response = self.u_boot_console.run_command('printenv')
47 response = self.u_boot_console.run_command('printenv')
49 for l in response.splitlines():
52 (var, value) = l.split('=', 1)
55 def get_existent_var(self):
56 """Return the name of an environment variable that exists.
62 The name of an environment variable.
68 def get_non_existent_var(self):
69 """Return the name of an environment variable that does not exist.
75 The name of an environment variable.
80 var = 'test_env_' + str(n)
81 if var not in self.env:
86 @pytest.fixture(scope='function')
87 def state_test_env(u_boot_console):
88 """pytest fixture to provide a StateTestEnv object to tests."""
92 ste = StateTestEnv(u_boot_console)
95 def unset_var(state_test_env, var):
96 """Unset an environment variable.
98 This both executes a U-Boot shell command and updates a StateTestEnv
102 state_test_env: The StateTestEnv object to update.
103 var: The variable name to unset.
109 state_test_env.u_boot_console.run_command('setenv %s' % var)
110 if var in state_test_env.env:
111 del state_test_env.env[var]
113 def set_var(state_test_env, var, value):
114 """Set an environment variable.
116 This both executes a U-Boot shell command and updates a StateTestEnv
120 state_test_env: The StateTestEnv object to update.
121 var: The variable name to set.
122 value: The value to set the variable to.
128 bc = state_test_env.u_boot_console.config.buildconfig
129 if bc.get('config_hush_parser', None):
134 pytest.skip('Space in variable value on non-Hush shell')
136 state_test_env.u_boot_console.run_command(
137 'setenv %s %s%s%s' % (var, quote, value, quote))
138 state_test_env.env[var] = value
140 def validate_empty(state_test_env, var):
141 """Validate that a variable is not set, using U-Boot shell commands.
144 var: The variable name to test.
150 response = state_test_env.u_boot_console.run_command('echo $%s' % var)
151 assert response == ''
153 def validate_set(state_test_env, var, value):
154 """Validate that a variable is set, using U-Boot shell commands.
157 var: The variable name to test.
158 value: The value the variable is expected to have.
164 # echo does not preserve leading, internal, or trailing whitespace in the
165 # value. printenv does, and hence allows more complete testing.
166 response = state_test_env.u_boot_console.run_command('printenv %s' % var)
167 assert response == ('%s=%s' % (var, value))
169 def test_env_echo_exists(state_test_env):
170 """Test echoing a variable that exists."""
172 var = state_test_env.get_existent_var()
173 value = state_test_env.env[var]
174 validate_set(state_test_env, var, value)
176 @pytest.mark.buildconfigspec('cmd_echo')
177 def test_env_echo_non_existent(state_test_env):
178 """Test echoing a variable that doesn't exist."""
180 var = state_test_env.set_var
181 validate_empty(state_test_env, var)
183 def test_env_printenv_non_existent(state_test_env):
184 """Test printenv error message for non-existant variables."""
186 var = state_test_env.set_var
187 c = state_test_env.u_boot_console
188 with c.disable_check('error_notification'):
189 response = c.run_command('printenv %s' % var)
190 assert(response == '## Error: "%s" not defined' % var)
192 @pytest.mark.buildconfigspec('cmd_echo')
193 def test_env_unset_non_existent(state_test_env):
194 """Test unsetting a nonexistent variable."""
196 var = state_test_env.get_non_existent_var()
197 unset_var(state_test_env, var)
198 validate_empty(state_test_env, var)
200 def test_env_set_non_existent(state_test_env):
201 """Test set a non-existant variable."""
203 var = state_test_env.set_var
205 set_var(state_test_env, var, value)
206 validate_set(state_test_env, var, value)
208 def test_env_set_existing(state_test_env):
209 """Test setting an existant variable."""
211 var = state_test_env.set_var
213 set_var(state_test_env, var, value)
214 validate_set(state_test_env, var, value)
216 @pytest.mark.buildconfigspec('cmd_echo')
217 def test_env_unset_existing(state_test_env):
218 """Test unsetting a variable."""
220 var = state_test_env.set_var
221 unset_var(state_test_env, var)
222 validate_empty(state_test_env, var)
224 def test_env_expansion_spaces(state_test_env):
225 """Test expanding a variable that contains a space in its value."""
230 var_space = state_test_env.get_non_existent_var()
231 set_var(state_test_env, var_space, ' ')
233 var_test = state_test_env.get_non_existent_var()
234 value = ' 1${%(var_space)s}${%(var_space)s} 2 ' % locals()
235 set_var(state_test_env, var_test, value)
237 validate_set(state_test_env, var_test, value)
240 unset_var(state_test_env, var_space)
242 unset_var(state_test_env, var_test)
244 @pytest.mark.buildconfigspec('cmd_importenv')
245 def test_env_import_checksum_no_size(state_test_env):
246 """Test that omitted ('-') size parameter with checksum validation fails the
249 c = state_test_env.u_boot_console
250 ram_base = u_boot_utils.find_ram_base(state_test_env.u_boot_console)
251 addr = '%08x' % ram_base
253 with c.disable_check('error_notification'):
254 response = c.run_command('env import -c %s -' % addr)
255 assert(response == '## Error: external checksum format must pass size')
257 @pytest.mark.buildconfigspec('cmd_importenv')
258 def test_env_import_whitelist_checksum_no_size(state_test_env):
259 """Test that omitted ('-') size parameter with checksum validation fails the
260 env import function when variables are passed as parameters.
262 c = state_test_env.u_boot_console
263 ram_base = u_boot_utils.find_ram_base(state_test_env.u_boot_console)
264 addr = '%08x' % ram_base
266 with c.disable_check('error_notification'):
267 response = c.run_command('env import -c %s - foo1 foo2 foo4' % addr)
268 assert(response == '## Error: external checksum format must pass size')
270 @pytest.mark.buildconfigspec('cmd_exportenv')
271 @pytest.mark.buildconfigspec('cmd_importenv')
272 def test_env_import_whitelist(state_test_env):
273 """Test importing only a handful of env variables from an environment."""
274 c = state_test_env.u_boot_console
275 ram_base = u_boot_utils.find_ram_base(state_test_env.u_boot_console)
276 addr = '%08x' % ram_base
278 set_var(state_test_env, 'foo1', 'bar1')
279 set_var(state_test_env, 'foo2', 'bar2')
280 set_var(state_test_env, 'foo3', 'bar3')
282 c.run_command('env export %s' % addr)
284 unset_var(state_test_env, 'foo1')
285 set_var(state_test_env, 'foo2', 'test2')
286 set_var(state_test_env, 'foo4', 'bar4')
288 # no foo1 in current env, foo2 overridden, foo3 should be of the value
289 # before exporting and foo4 should be of the value before importing.
290 c.run_command('env import %s - foo1 foo2 foo4' % addr)
292 validate_set(state_test_env, 'foo1', 'bar1')
293 validate_set(state_test_env, 'foo2', 'bar2')
294 validate_set(state_test_env, 'foo3', 'bar3')
295 validate_set(state_test_env, 'foo4', 'bar4')
297 # Cleanup test environment
298 unset_var(state_test_env, 'foo1')
299 unset_var(state_test_env, 'foo2')
300 unset_var(state_test_env, 'foo3')
301 unset_var(state_test_env, 'foo4')
303 @pytest.mark.buildconfigspec('cmd_exportenv')
304 @pytest.mark.buildconfigspec('cmd_importenv')
305 def test_env_import_whitelist_delete(state_test_env):
307 """Test importing only a handful of env variables from an environment, with.
308 deletion if a var A that is passed to env import is not in the
309 environment to be imported.
311 c = state_test_env.u_boot_console
312 ram_base = u_boot_utils.find_ram_base(state_test_env.u_boot_console)
313 addr = '%08x' % ram_base
315 set_var(state_test_env, 'foo1', 'bar1')
316 set_var(state_test_env, 'foo2', 'bar2')
317 set_var(state_test_env, 'foo3', 'bar3')
319 c.run_command('env export %s' % addr)
321 unset_var(state_test_env, 'foo1')
322 set_var(state_test_env, 'foo2', 'test2')
323 set_var(state_test_env, 'foo4', 'bar4')
325 # no foo1 in current env, foo2 overridden, foo3 should be of the value
326 # before exporting and foo4 should be empty.
327 c.run_command('env import -d %s - foo1 foo2 foo4' % addr)
329 validate_set(state_test_env, 'foo1', 'bar1')
330 validate_set(state_test_env, 'foo2', 'bar2')
331 validate_set(state_test_env, 'foo3', 'bar3')
332 validate_empty(state_test_env, 'foo4')
334 # Cleanup test environment
335 unset_var(state_test_env, 'foo1')
336 unset_var(state_test_env, 'foo2')
337 unset_var(state_test_env, 'foo3')
338 unset_var(state_test_env, 'foo4')
340 @pytest.mark.buildconfigspec('cmd_nvedit_info')
341 def test_env_info(state_test_env):
343 """Test 'env info' command with all possible options.
345 c = state_test_env.u_boot_console
347 response = c.run_command('env info')
349 for l in response.split('\n'):
350 if 'env_valid = ' in l:
351 assert '= invalid' in l or '= valid' in l or '= redundant' in l
353 elif 'env_ready =' in l or 'env_use_default =' in l:
354 assert '= true' in l or '= false' in l
360 response = c.run_command('env info -p -d')
361 assert 'Default environment is used' in response or "Environment was loaded from persistent storage" in response
362 assert 'Environment can be persisted' in response or "Environment cannot be persisted" in response
364 response = c.run_command('env info -p -d -q')
365 assert response == ""
367 response = c.run_command('env info -p -q')
368 assert response == ""
370 response = c.run_command('env info -d -q')
371 assert response == ""
373 @pytest.mark.boardspec('sandbox')
374 @pytest.mark.buildconfigspec('cmd_nvedit_info')
375 @pytest.mark.buildconfigspec('cmd_echo')
376 def test_env_info_sandbox(state_test_env):
378 """Test 'env info' command result with several options on sandbox
379 with a known ENV configuration: ready & default & persistent
381 c = state_test_env.u_boot_console
383 response = c.run_command('env info')
384 assert 'env_ready = true' in response
385 assert 'env_use_default = true' in response
387 response = c.run_command('env info -p -d')
388 assert 'Default environment is used' in response
389 assert 'Environment cannot be persisted' in response
391 response = c.run_command('env info -d -q')
392 response = c.run_command('echo $?')
393 assert response == "0"
395 response = c.run_command('env info -p -q')
396 response = c.run_command('echo $?')
397 assert response == "1"
399 response = c.run_command('env info -d -p -q')
400 response = c.run_command('echo $?')
401 assert response == "1"