blob: f85cb031382e9881e36a87c0ae66b1cccb2922c4 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001# SPDX-License-Identifier: GPL-2.0
Stephen Warrend6310622016-01-15 11:15:26 -07002# Copyright (c) 2015 Stephen Warren
3# Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
Stephen Warrend6310622016-01-15 11:15:26 -07004
5# Test operation of shell commands relating to environment variables.
6
Patrick Delaunay57951c52020-07-28 11:51:24 +02007import os
8import os.path
9from subprocess import call, check_call, CalledProcessError
Simon Glass7327fe72021-10-21 21:08:46 -060010import tempfile
Patrick Delaunay57951c52020-07-28 11:51:24 +020011
Stephen Warrend6310622016-01-15 11:15:26 -070012import pytest
Quentin Schulze74def52018-07-09 19:16:30 +020013import u_boot_utils
Stephen Warrend6310622016-01-15 11:15:26 -070014
15# FIXME: This might be useful for other tests;
16# perhaps refactor it into ConsoleBase or some other state object?
17class StateTestEnv(object):
Stephen Warren75e731e2016-01-26 13:41:30 -070018 """Container that represents the state of all U-Boot environment variables.
Stephen Warrend6310622016-01-15 11:15:26 -070019 This enables quick determination of existant/non-existant variable
20 names.
Stephen Warren75e731e2016-01-26 13:41:30 -070021 """
Stephen Warrend6310622016-01-15 11:15:26 -070022
23 def __init__(self, u_boot_console):
Stephen Warren75e731e2016-01-26 13:41:30 -070024 """Initialize a new StateTestEnv object.
Stephen Warrend6310622016-01-15 11:15:26 -070025
26 Args:
27 u_boot_console: A U-Boot console.
28
29 Returns:
30 Nothing.
Stephen Warren75e731e2016-01-26 13:41:30 -070031 """
Stephen Warrend6310622016-01-15 11:15:26 -070032
33 self.u_boot_console = u_boot_console
34 self.get_env()
35 self.set_var = self.get_non_existent_var()
36
37 def get_env(self):
Stephen Warren75e731e2016-01-26 13:41:30 -070038 """Read all current environment variables from U-Boot.
Stephen Warrend6310622016-01-15 11:15:26 -070039
40 Args:
41 None.
42
43 Returns:
44 Nothing.
Stephen Warren75e731e2016-01-26 13:41:30 -070045 """
Stephen Warrend6310622016-01-15 11:15:26 -070046
Stephen Warren9c401e42016-06-16 12:59:34 -060047 if self.u_boot_console.config.buildconfig.get(
48 'config_version_variable', 'n') == 'y':
Heiko Schocher52e05e92016-06-07 08:31:15 +020049 with self.u_boot_console.disable_check('main_signon'):
50 response = self.u_boot_console.run_command('printenv')
51 else:
52 response = self.u_boot_console.run_command('printenv')
Stephen Warrend6310622016-01-15 11:15:26 -070053 self.env = {}
54 for l in response.splitlines():
55 if not '=' in l:
56 continue
Stephen Warren66b5b9e2019-12-18 11:37:21 -070057 (var, value) = l.split('=', 1)
Stephen Warrend6310622016-01-15 11:15:26 -070058 self.env[var] = value
59
60 def get_existent_var(self):
Stephen Warren75e731e2016-01-26 13:41:30 -070061 """Return the name of an environment variable that exists.
Stephen Warrend6310622016-01-15 11:15:26 -070062
63 Args:
64 None.
65
66 Returns:
67 The name of an environment variable.
Stephen Warren75e731e2016-01-26 13:41:30 -070068 """
Stephen Warrend6310622016-01-15 11:15:26 -070069
70 for var in self.env:
71 return var
72
73 def get_non_existent_var(self):
Stephen Warren75e731e2016-01-26 13:41:30 -070074 """Return the name of an environment variable that does not exist.
Stephen Warrend6310622016-01-15 11:15:26 -070075
76 Args:
77 None.
78
79 Returns:
80 The name of an environment variable.
Stephen Warren75e731e2016-01-26 13:41:30 -070081 """
Stephen Warrend6310622016-01-15 11:15:26 -070082
83 n = 0
84 while True:
85 var = 'test_env_' + str(n)
86 if var not in self.env:
87 return var
88 n += 1
89
Stephen Warrene1d24d02016-01-22 12:30:08 -070090ste = None
91@pytest.fixture(scope='function')
Stephen Warrend6310622016-01-15 11:15:26 -070092def state_test_env(u_boot_console):
Stephen Warren75e731e2016-01-26 13:41:30 -070093 """pytest fixture to provide a StateTestEnv object to tests."""
Stephen Warrend6310622016-01-15 11:15:26 -070094
Stephen Warrene1d24d02016-01-22 12:30:08 -070095 global ste
96 if not ste:
97 ste = StateTestEnv(u_boot_console)
98 return ste
Stephen Warrend6310622016-01-15 11:15:26 -070099
100def unset_var(state_test_env, var):
Stephen Warren75e731e2016-01-26 13:41:30 -0700101 """Unset an environment variable.
Stephen Warrend6310622016-01-15 11:15:26 -0700102
103 This both executes a U-Boot shell command and updates a StateTestEnv
104 object.
105
106 Args:
Stephen Warren2b467242016-01-28 10:18:03 -0700107 state_test_env: The StateTestEnv object to update.
Stephen Warrend6310622016-01-15 11:15:26 -0700108 var: The variable name to unset.
109
110 Returns:
111 Nothing.
Stephen Warren75e731e2016-01-26 13:41:30 -0700112 """
Stephen Warrend6310622016-01-15 11:15:26 -0700113
114 state_test_env.u_boot_console.run_command('setenv %s' % var)
115 if var in state_test_env.env:
116 del state_test_env.env[var]
117
118def set_var(state_test_env, var, value):
Stephen Warren75e731e2016-01-26 13:41:30 -0700119 """Set an environment variable.
Stephen Warrend6310622016-01-15 11:15:26 -0700120
121 This both executes a U-Boot shell command and updates a StateTestEnv
122 object.
123
124 Args:
Stephen Warren2b467242016-01-28 10:18:03 -0700125 state_test_env: The StateTestEnv object to update.
Stephen Warrend6310622016-01-15 11:15:26 -0700126 var: The variable name to set.
127 value: The value to set the variable to.
128
129 Returns:
130 Nothing.
Stephen Warren75e731e2016-01-26 13:41:30 -0700131 """
Stephen Warrend6310622016-01-15 11:15:26 -0700132
Stephen Warren16abcd92017-11-10 11:59:15 +0100133 bc = state_test_env.u_boot_console.config.buildconfig
134 if bc.get('config_hush_parser', None):
135 quote = '"'
136 else:
137 quote = ''
138 if ' ' in value:
139 pytest.skip('Space in variable value on non-Hush shell')
140
141 state_test_env.u_boot_console.run_command(
142 'setenv %s %s%s%s' % (var, quote, value, quote))
Stephen Warrend6310622016-01-15 11:15:26 -0700143 state_test_env.env[var] = value
144
145def validate_empty(state_test_env, var):
Stephen Warren75e731e2016-01-26 13:41:30 -0700146 """Validate that a variable is not set, using U-Boot shell commands.
Stephen Warrend6310622016-01-15 11:15:26 -0700147
148 Args:
149 var: The variable name to test.
150
151 Returns:
152 Nothing.
Stephen Warren75e731e2016-01-26 13:41:30 -0700153 """
Stephen Warrend6310622016-01-15 11:15:26 -0700154
Heinrich Schuchardtff3fbc62020-09-10 12:09:03 +0200155 response = state_test_env.u_boot_console.run_command('echo ${%s}' % var)
Stephen Warrend6310622016-01-15 11:15:26 -0700156 assert response == ''
157
158def validate_set(state_test_env, var, value):
Stephen Warren75e731e2016-01-26 13:41:30 -0700159 """Validate that a variable is set, using U-Boot shell commands.
Stephen Warrend6310622016-01-15 11:15:26 -0700160
161 Args:
162 var: The variable name to test.
163 value: The value the variable is expected to have.
164
165 Returns:
166 Nothing.
Stephen Warren75e731e2016-01-26 13:41:30 -0700167 """
Stephen Warrend6310622016-01-15 11:15:26 -0700168
169 # echo does not preserve leading, internal, or trailing whitespace in the
170 # value. printenv does, and hence allows more complete testing.
171 response = state_test_env.u_boot_console.run_command('printenv %s' % var)
172 assert response == ('%s=%s' % (var, value))
173
174def test_env_echo_exists(state_test_env):
Stephen Warren75e731e2016-01-26 13:41:30 -0700175 """Test echoing a variable that exists."""
Stephen Warrend6310622016-01-15 11:15:26 -0700176
177 var = state_test_env.get_existent_var()
178 value = state_test_env.env[var]
179 validate_set(state_test_env, var, value)
180
Michal Simeke710ab72017-05-15 14:29:02 +0200181@pytest.mark.buildconfigspec('cmd_echo')
Stephen Warrend6310622016-01-15 11:15:26 -0700182def test_env_echo_non_existent(state_test_env):
Stephen Warren75e731e2016-01-26 13:41:30 -0700183 """Test echoing a variable that doesn't exist."""
Stephen Warrend6310622016-01-15 11:15:26 -0700184
185 var = state_test_env.set_var
186 validate_empty(state_test_env, var)
187
188def test_env_printenv_non_existent(state_test_env):
Stephen Warren75e731e2016-01-26 13:41:30 -0700189 """Test printenv error message for non-existant variables."""
Stephen Warrend6310622016-01-15 11:15:26 -0700190
191 var = state_test_env.set_var
192 c = state_test_env.u_boot_console
193 with c.disable_check('error_notification'):
194 response = c.run_command('printenv %s' % var)
195 assert(response == '## Error: "%s" not defined' % var)
196
Michal Simeke710ab72017-05-15 14:29:02 +0200197@pytest.mark.buildconfigspec('cmd_echo')
Stephen Warrend6310622016-01-15 11:15:26 -0700198def test_env_unset_non_existent(state_test_env):
Stephen Warren75e731e2016-01-26 13:41:30 -0700199 """Test unsetting a nonexistent variable."""
Stephen Warrend6310622016-01-15 11:15:26 -0700200
201 var = state_test_env.get_non_existent_var()
202 unset_var(state_test_env, var)
203 validate_empty(state_test_env, var)
204
205def test_env_set_non_existent(state_test_env):
Stephen Warren75e731e2016-01-26 13:41:30 -0700206 """Test set a non-existant variable."""
Stephen Warrend6310622016-01-15 11:15:26 -0700207
208 var = state_test_env.set_var
209 value = 'foo'
210 set_var(state_test_env, var, value)
211 validate_set(state_test_env, var, value)
212
213def test_env_set_existing(state_test_env):
Stephen Warren75e731e2016-01-26 13:41:30 -0700214 """Test setting an existant variable."""
Stephen Warrend6310622016-01-15 11:15:26 -0700215
216 var = state_test_env.set_var
217 value = 'bar'
218 set_var(state_test_env, var, value)
219 validate_set(state_test_env, var, value)
220
Michal Simeke710ab72017-05-15 14:29:02 +0200221@pytest.mark.buildconfigspec('cmd_echo')
Stephen Warrend6310622016-01-15 11:15:26 -0700222def test_env_unset_existing(state_test_env):
Stephen Warren75e731e2016-01-26 13:41:30 -0700223 """Test unsetting a variable."""
Stephen Warrend6310622016-01-15 11:15:26 -0700224
225 var = state_test_env.set_var
226 unset_var(state_test_env, var)
227 validate_empty(state_test_env, var)
228
229def test_env_expansion_spaces(state_test_env):
Stephen Warren75e731e2016-01-26 13:41:30 -0700230 """Test expanding a variable that contains a space in its value."""
Stephen Warrend6310622016-01-15 11:15:26 -0700231
232 var_space = None
233 var_test = None
234 try:
235 var_space = state_test_env.get_non_existent_var()
236 set_var(state_test_env, var_space, ' ')
237
238 var_test = state_test_env.get_non_existent_var()
239 value = ' 1${%(var_space)s}${%(var_space)s} 2 ' % locals()
240 set_var(state_test_env, var_test, value)
241 value = ' 1 2 '
242 validate_set(state_test_env, var_test, value)
243 finally:
244 if var_space:
245 unset_var(state_test_env, var_space)
246 if var_test:
247 unset_var(state_test_env, var_test)
Quentin Schulze74def52018-07-09 19:16:30 +0200248
249@pytest.mark.buildconfigspec('cmd_importenv')
250def test_env_import_checksum_no_size(state_test_env):
251 """Test that omitted ('-') size parameter with checksum validation fails the
252 env import function.
253 """
254 c = state_test_env.u_boot_console
255 ram_base = u_boot_utils.find_ram_base(state_test_env.u_boot_console)
256 addr = '%08x' % ram_base
257
258 with c.disable_check('error_notification'):
259 response = c.run_command('env import -c %s -' % addr)
260 assert(response == '## Error: external checksum format must pass size')
261
262@pytest.mark.buildconfigspec('cmd_importenv')
263def test_env_import_whitelist_checksum_no_size(state_test_env):
264 """Test that omitted ('-') size parameter with checksum validation fails the
265 env import function when variables are passed as parameters.
266 """
267 c = state_test_env.u_boot_console
268 ram_base = u_boot_utils.find_ram_base(state_test_env.u_boot_console)
269 addr = '%08x' % ram_base
270
271 with c.disable_check('error_notification'):
272 response = c.run_command('env import -c %s - foo1 foo2 foo4' % addr)
273 assert(response == '## Error: external checksum format must pass size')
274
275@pytest.mark.buildconfigspec('cmd_exportenv')
276@pytest.mark.buildconfigspec('cmd_importenv')
277def test_env_import_whitelist(state_test_env):
278 """Test importing only a handful of env variables from an environment."""
279 c = state_test_env.u_boot_console
280 ram_base = u_boot_utils.find_ram_base(state_test_env.u_boot_console)
281 addr = '%08x' % ram_base
282
283 set_var(state_test_env, 'foo1', 'bar1')
284 set_var(state_test_env, 'foo2', 'bar2')
285 set_var(state_test_env, 'foo3', 'bar3')
286
287 c.run_command('env export %s' % addr)
288
289 unset_var(state_test_env, 'foo1')
290 set_var(state_test_env, 'foo2', 'test2')
291 set_var(state_test_env, 'foo4', 'bar4')
292
293 # no foo1 in current env, foo2 overridden, foo3 should be of the value
294 # before exporting and foo4 should be of the value before importing.
295 c.run_command('env import %s - foo1 foo2 foo4' % addr)
296
297 validate_set(state_test_env, 'foo1', 'bar1')
298 validate_set(state_test_env, 'foo2', 'bar2')
299 validate_set(state_test_env, 'foo3', 'bar3')
300 validate_set(state_test_env, 'foo4', 'bar4')
301
302 # Cleanup test environment
303 unset_var(state_test_env, 'foo1')
304 unset_var(state_test_env, 'foo2')
305 unset_var(state_test_env, 'foo3')
306 unset_var(state_test_env, 'foo4')
307
308@pytest.mark.buildconfigspec('cmd_exportenv')
309@pytest.mark.buildconfigspec('cmd_importenv')
310def test_env_import_whitelist_delete(state_test_env):
311
312 """Test importing only a handful of env variables from an environment, with.
313 deletion if a var A that is passed to env import is not in the
314 environment to be imported.
315 """
316 c = state_test_env.u_boot_console
317 ram_base = u_boot_utils.find_ram_base(state_test_env.u_boot_console)
318 addr = '%08x' % ram_base
319
320 set_var(state_test_env, 'foo1', 'bar1')
321 set_var(state_test_env, 'foo2', 'bar2')
322 set_var(state_test_env, 'foo3', 'bar3')
323
324 c.run_command('env export %s' % addr)
325
326 unset_var(state_test_env, 'foo1')
327 set_var(state_test_env, 'foo2', 'test2')
328 set_var(state_test_env, 'foo4', 'bar4')
329
330 # no foo1 in current env, foo2 overridden, foo3 should be of the value
331 # before exporting and foo4 should be empty.
332 c.run_command('env import -d %s - foo1 foo2 foo4' % addr)
333
334 validate_set(state_test_env, 'foo1', 'bar1')
335 validate_set(state_test_env, 'foo2', 'bar2')
336 validate_set(state_test_env, 'foo3', 'bar3')
337 validate_empty(state_test_env, 'foo4')
338
339 # Cleanup test environment
340 unset_var(state_test_env, 'foo1')
341 unset_var(state_test_env, 'foo2')
342 unset_var(state_test_env, 'foo3')
343 unset_var(state_test_env, 'foo4')
Patrick Delaunaydc4d1c52020-06-19 14:03:37 +0200344
345@pytest.mark.buildconfigspec('cmd_nvedit_info')
346def test_env_info(state_test_env):
347
348 """Test 'env info' command with all possible options.
349 """
350 c = state_test_env.u_boot_console
351
352 response = c.run_command('env info')
353 nb_line = 0
354 for l in response.split('\n'):
355 if 'env_valid = ' in l:
356 assert '= invalid' in l or '= valid' in l or '= redundant' in l
357 nb_line += 1
358 elif 'env_ready =' in l or 'env_use_default =' in l:
359 assert '= true' in l or '= false' in l
360 nb_line += 1
361 else:
362 assert true
363 assert nb_line == 3
364
365 response = c.run_command('env info -p -d')
366 assert 'Default environment is used' in response or "Environment was loaded from persistent storage" in response
367 assert 'Environment can be persisted' in response or "Environment cannot be persisted" in response
368
369 response = c.run_command('env info -p -d -q')
370 assert response == ""
371
372 response = c.run_command('env info -p -q')
373 assert response == ""
374
375 response = c.run_command('env info -d -q')
376 assert response == ""
377
378@pytest.mark.boardspec('sandbox')
379@pytest.mark.buildconfigspec('cmd_nvedit_info')
380@pytest.mark.buildconfigspec('cmd_echo')
381def test_env_info_sandbox(state_test_env):
Patrick Delaunaydc4d1c52020-06-19 14:03:37 +0200382 """Test 'env info' command result with several options on sandbox
383 with a known ENV configuration: ready & default & persistent
384 """
385 c = state_test_env.u_boot_console
386
387 response = c.run_command('env info')
388 assert 'env_ready = true' in response
389 assert 'env_use_default = true' in response
390
391 response = c.run_command('env info -p -d')
392 assert 'Default environment is used' in response
393 assert 'Environment cannot be persisted' in response
394
395 response = c.run_command('env info -d -q')
396 response = c.run_command('echo $?')
397 assert response == "0"
398
399 response = c.run_command('env info -p -q')
400 response = c.run_command('echo $?')
401 assert response == "1"
402
403 response = c.run_command('env info -d -p -q')
404 response = c.run_command('echo $?')
405 assert response == "1"
Patrick Delaunay57951c52020-07-28 11:51:24 +0200406
407def mk_env_ext4(state_test_env):
408
409 """Create a empty ext4 file system volume."""
410 c = state_test_env.u_boot_console
411 filename = 'env.ext4.img'
412 persistent = c.config.persistent_data_dir + '/' + filename
413 fs_img = c.config.result_dir + '/' + filename
414
415 if os.path.exists(persistent):
416 c.log.action('Disk image file ' + persistent + ' already exists')
417 else:
Andy Shevchenko9cdba9b2021-02-11 16:40:09 +0200418 # Some distributions do not add /sbin to the default PATH, where mkfs.ext4 lives
419 os.environ["PATH"] += os.pathsep + '/sbin'
Patrick Delaunay57951c52020-07-28 11:51:24 +0200420 try:
421 u_boot_utils.run_and_log(c, 'dd if=/dev/zero of=%s bs=1M count=16' % persistent)
Stephen Warrenf7d10932020-08-04 11:28:33 -0600422 u_boot_utils.run_and_log(c, 'mkfs.ext4 %s' % persistent)
423 sb_content = u_boot_utils.run_and_log(c, 'tune2fs -l %s' % persistent)
424 if 'metadata_csum' in sb_content:
425 u_boot_utils.run_and_log(c, 'tune2fs -O ^metadata_csum %s' % persistent)
Patrick Delaunay57951c52020-07-28 11:51:24 +0200426 except CalledProcessError:
427 call('rm -f %s' % persistent, shell=True)
428 raise
429
430 u_boot_utils.run_and_log(c, ['cp', '-f', persistent, fs_img])
431 return fs_img
432
433@pytest.mark.boardspec('sandbox')
434@pytest.mark.buildconfigspec('cmd_echo')
435@pytest.mark.buildconfigspec('cmd_nvedit_info')
436@pytest.mark.buildconfigspec('cmd_nvedit_load')
437@pytest.mark.buildconfigspec('cmd_nvedit_select')
438@pytest.mark.buildconfigspec('env_is_in_ext4')
439def test_env_ext4(state_test_env):
440
441 """Test ENV in EXT4 on sandbox."""
442 c = state_test_env.u_boot_console
443 fs_img = ''
444 try:
445 fs_img = mk_env_ext4(state_test_env)
446
447 c.run_command('host bind 0 %s' % fs_img)
448
449 response = c.run_command('ext4ls host 0:0')
450 assert 'uboot.env' not in response
451
452 # force env location: EXT4 (prio 1 in sandbox)
453 response = c.run_command('env select EXT4')
454 assert 'Select Environment on EXT4: OK' in response
455
456 response = c.run_command('env save')
457 assert 'Saving Environment to EXT4' in response
458
459 response = c.run_command('env load')
460 assert 'Loading Environment from EXT4... OK' in response
461
462 response = c.run_command('ext4ls host 0:0')
463 assert '8192 uboot.env' in response
464
465 response = c.run_command('env info')
466 assert 'env_valid = valid' in response
467 assert 'env_ready = true' in response
468 assert 'env_use_default = false' in response
469
470 response = c.run_command('env info -p -d')
471 assert 'Environment was loaded from persistent storage' in response
472 assert 'Environment can be persisted' in response
473
474 response = c.run_command('env info -d -q')
475 assert response == ""
476 response = c.run_command('echo $?')
477 assert response == "1"
478
479 response = c.run_command('env info -p -q')
480 assert response == ""
481 response = c.run_command('echo $?')
482 assert response == "0"
483
Patrick Delaunayfe6e1f12020-07-28 11:51:27 +0200484 response = c.run_command('env erase')
485 assert 'OK' in response
486
487 response = c.run_command('env load')
488 assert 'Loading Environment from EXT4... ' in response
489 assert 'bad CRC, using default environment' in response
490
491 response = c.run_command('env info')
492 assert 'env_valid = invalid' in response
493 assert 'env_ready = true' in response
494 assert 'env_use_default = true' in response
495
496 response = c.run_command('env info -p -d')
497 assert 'Default environment is used' in response
498 assert 'Environment can be persisted' in response
499
Patrick Delaunay57951c52020-07-28 11:51:24 +0200500 # restore env location: NOWHERE (prio 0 in sandbox)
501 response = c.run_command('env select nowhere')
502 assert 'Select Environment on nowhere: OK' in response
503
504 response = c.run_command('env load')
505 assert 'Loading Environment from nowhere... OK' in response
506
507 response = c.run_command('env info')
508 assert 'env_valid = invalid' in response
509 assert 'env_ready = true' in response
510 assert 'env_use_default = true' in response
511
512 response = c.run_command('env info -p -d')
513 assert 'Default environment is used' in response
514 assert 'Environment cannot be persisted' in response
515
516 finally:
517 if fs_img:
518 call('rm -f %s' % fs_img, shell=True)
Simon Glass7327fe72021-10-21 21:08:46 -0600519
520def test_env_text(u_boot_console):
521 """Test the script that converts the environment to a text file"""
522
523 def check_script(intext, expect_val):
524 """Check a test case
525
526 Args:
527 intext: Text to pass to the script
528 expect_val: Expected value of the CONFIG_EXTRA_ENV_TEXT string, or
529 None if we expect it not to be defined
530 """
531 with tempfile.TemporaryDirectory() as path:
532 fname = os.path.join(path, 'infile')
533 with open(fname, 'w') as inf:
534 print(intext, file=inf)
535 result = u_boot_utils.run_and_log(cons, ['awk', '-f', script, fname])
536 if expect_val is not None:
537 expect = '#define CONFIG_EXTRA_ENV_TEXT "%s"\n' % expect_val
538 assert result == expect
539 else:
540 assert result == ''
541
542 cons = u_boot_console
543 script = os.path.join(cons.config.source_dir, 'scripts', 'env2string.awk')
544
545 # simple script with a single var
546 check_script('fred=123', 'fred=123\\0')
547
548 # no vars
549 check_script('', None)
550
551 # two vars
552 check_script('''fred=123
553ernie=456''', 'fred=123\\0ernie=456\\0')
554
555 # blank lines
556 check_script('''fred=123
557
558
559ernie=456
560
561''', 'fred=123\\0ernie=456\\0')
562
563 # append
564 check_script('''fred=123
565ernie=456
566fred+= 456''', 'fred=123 456\\0ernie=456\\0')
567
568 # append from empty
569 check_script('''fred=
570ernie=456
571fred+= 456''', 'fred= 456\\0ernie=456\\0')
572
573 # variable with + in it
574 check_script('fred+ernie=123', 'fred+ernie=123\\0')
575
576 # ignores variables that are empty
577 check_script('''fred=
578fred+=
579ernie=456''', 'ernie=456\\0')
580
581 # single-character env name
582 check_script('''f=123
583e=456
584f+= 456''', 'e=456\\0f=123 456\\0')
585
586 # contains quotes
587 check_script('''fred="my var"
588ernie=another"''', 'fred=\\"my var\\"\\0ernie=another\\"\\0')
589
590 # variable name ending in +
591 check_script('''fred\\+=my var
592fred++= again''', 'fred+=my var again\\0')
593
594 # variable name containing +
595 check_script('''fred+jane=both
596fred+jane+=again
597ernie=456''', 'fred+jane=bothagain\\0ernie=456\\0')
598
599 # multi-line vars - new vars always start at column 1
600 check_script('''fred=first
601 second
602\tthird with tab
603
604 after blank
605 confusing=oops
606ernie=another"''', 'fred=first second third with tab after blank confusing=oops\\0ernie=another\\"\\0')
607
608 # real-world example
609 check_script('''ubifs_boot=
610 env exists bootubipart ||
611 env set bootubipart UBI;
612 env exists bootubivol ||
613 env set bootubivol boot;
614 if ubi part ${bootubipart} &&
615 ubifsmount ubi${devnum}:${bootubivol};
616 then
617 devtype=ubi;
618 run scan_dev_for_boot;
619 fi
620''',
621 'ubifs_boot=env exists bootubipart || env set bootubipart UBI; '
622 'env exists bootubivol || env set bootubivol boot; '
623 'if ubi part ${bootubipart} && ubifsmount ubi${devnum}:${bootubivol}; '
624 'then devtype=ubi; run scan_dev_for_boot; fi\\0')