1*4882a593Smuzhiyun# Copyright (c) 2015 Stephen Warren 2*4882a593Smuzhiyun# Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0 5*4882a593Smuzhiyun 6*4882a593Smuzhiyun# Test operation of shell commands relating to environment variables. 7*4882a593Smuzhiyun 8*4882a593Smuzhiyunimport pytest 9*4882a593Smuzhiyun 10*4882a593Smuzhiyun# FIXME: This might be useful for other tests; 11*4882a593Smuzhiyun# perhaps refactor it into ConsoleBase or some other state object? 12*4882a593Smuzhiyunclass StateTestEnv(object): 13*4882a593Smuzhiyun """Container that represents the state of all U-Boot environment variables. 14*4882a593Smuzhiyun This enables quick determination of existant/non-existant variable 15*4882a593Smuzhiyun names. 16*4882a593Smuzhiyun """ 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun def __init__(self, u_boot_console): 19*4882a593Smuzhiyun """Initialize a new StateTestEnv object. 20*4882a593Smuzhiyun 21*4882a593Smuzhiyun Args: 22*4882a593Smuzhiyun u_boot_console: A U-Boot console. 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun Returns: 25*4882a593Smuzhiyun Nothing. 26*4882a593Smuzhiyun """ 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun self.u_boot_console = u_boot_console 29*4882a593Smuzhiyun self.get_env() 30*4882a593Smuzhiyun self.set_var = self.get_non_existent_var() 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun def get_env(self): 33*4882a593Smuzhiyun """Read all current environment variables from U-Boot. 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun Args: 36*4882a593Smuzhiyun None. 37*4882a593Smuzhiyun 38*4882a593Smuzhiyun Returns: 39*4882a593Smuzhiyun Nothing. 40*4882a593Smuzhiyun """ 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun if self.u_boot_console.config.buildconfig.get( 43*4882a593Smuzhiyun 'config_version_variable', 'n') == 'y': 44*4882a593Smuzhiyun with self.u_boot_console.disable_check('main_signon'): 45*4882a593Smuzhiyun response = self.u_boot_console.run_command('printenv') 46*4882a593Smuzhiyun else: 47*4882a593Smuzhiyun response = self.u_boot_console.run_command('printenv') 48*4882a593Smuzhiyun self.env = {} 49*4882a593Smuzhiyun for l in response.splitlines(): 50*4882a593Smuzhiyun if not '=' in l: 51*4882a593Smuzhiyun continue 52*4882a593Smuzhiyun (var, value) = l.strip().split('=', 1) 53*4882a593Smuzhiyun self.env[var] = value 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun def get_existent_var(self): 56*4882a593Smuzhiyun """Return the name of an environment variable that exists. 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun Args: 59*4882a593Smuzhiyun None. 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun Returns: 62*4882a593Smuzhiyun The name of an environment variable. 63*4882a593Smuzhiyun """ 64*4882a593Smuzhiyun 65*4882a593Smuzhiyun for var in self.env: 66*4882a593Smuzhiyun return var 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun def get_non_existent_var(self): 69*4882a593Smuzhiyun """Return the name of an environment variable that does not exist. 70*4882a593Smuzhiyun 71*4882a593Smuzhiyun Args: 72*4882a593Smuzhiyun None. 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun Returns: 75*4882a593Smuzhiyun The name of an environment variable. 76*4882a593Smuzhiyun """ 77*4882a593Smuzhiyun 78*4882a593Smuzhiyun n = 0 79*4882a593Smuzhiyun while True: 80*4882a593Smuzhiyun var = 'test_env_' + str(n) 81*4882a593Smuzhiyun if var not in self.env: 82*4882a593Smuzhiyun return var 83*4882a593Smuzhiyun n += 1 84*4882a593Smuzhiyun 85*4882a593Smuzhiyunste = None 86*4882a593Smuzhiyun@pytest.fixture(scope='function') 87*4882a593Smuzhiyundef state_test_env(u_boot_console): 88*4882a593Smuzhiyun """pytest fixture to provide a StateTestEnv object to tests.""" 89*4882a593Smuzhiyun 90*4882a593Smuzhiyun global ste 91*4882a593Smuzhiyun if not ste: 92*4882a593Smuzhiyun ste = StateTestEnv(u_boot_console) 93*4882a593Smuzhiyun return ste 94*4882a593Smuzhiyun 95*4882a593Smuzhiyundef unset_var(state_test_env, var): 96*4882a593Smuzhiyun """Unset an environment variable. 97*4882a593Smuzhiyun 98*4882a593Smuzhiyun This both executes a U-Boot shell command and updates a StateTestEnv 99*4882a593Smuzhiyun object. 100*4882a593Smuzhiyun 101*4882a593Smuzhiyun Args: 102*4882a593Smuzhiyun state_test_env: The StateTestEnv object to update. 103*4882a593Smuzhiyun var: The variable name to unset. 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun Returns: 106*4882a593Smuzhiyun Nothing. 107*4882a593Smuzhiyun """ 108*4882a593Smuzhiyun 109*4882a593Smuzhiyun state_test_env.u_boot_console.run_command('setenv %s' % var) 110*4882a593Smuzhiyun if var in state_test_env.env: 111*4882a593Smuzhiyun del state_test_env.env[var] 112*4882a593Smuzhiyun 113*4882a593Smuzhiyundef set_var(state_test_env, var, value): 114*4882a593Smuzhiyun """Set an environment variable. 115*4882a593Smuzhiyun 116*4882a593Smuzhiyun This both executes a U-Boot shell command and updates a StateTestEnv 117*4882a593Smuzhiyun object. 118*4882a593Smuzhiyun 119*4882a593Smuzhiyun Args: 120*4882a593Smuzhiyun state_test_env: The StateTestEnv object to update. 121*4882a593Smuzhiyun var: The variable name to set. 122*4882a593Smuzhiyun value: The value to set the variable to. 123*4882a593Smuzhiyun 124*4882a593Smuzhiyun Returns: 125*4882a593Smuzhiyun Nothing. 126*4882a593Smuzhiyun """ 127*4882a593Smuzhiyun 128*4882a593Smuzhiyun bc = state_test_env.u_boot_console.config.buildconfig 129*4882a593Smuzhiyun if bc.get('config_hush_parser', None): 130*4882a593Smuzhiyun quote = '"' 131*4882a593Smuzhiyun else: 132*4882a593Smuzhiyun quote = '' 133*4882a593Smuzhiyun if ' ' in value: 134*4882a593Smuzhiyun pytest.skip('Space in variable value on non-Hush shell') 135*4882a593Smuzhiyun 136*4882a593Smuzhiyun state_test_env.u_boot_console.run_command( 137*4882a593Smuzhiyun 'setenv %s %s%s%s' % (var, quote, value, quote)) 138*4882a593Smuzhiyun state_test_env.env[var] = value 139*4882a593Smuzhiyun 140*4882a593Smuzhiyundef validate_empty(state_test_env, var): 141*4882a593Smuzhiyun """Validate that a variable is not set, using U-Boot shell commands. 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun Args: 144*4882a593Smuzhiyun var: The variable name to test. 145*4882a593Smuzhiyun 146*4882a593Smuzhiyun Returns: 147*4882a593Smuzhiyun Nothing. 148*4882a593Smuzhiyun """ 149*4882a593Smuzhiyun 150*4882a593Smuzhiyun response = state_test_env.u_boot_console.run_command('echo $%s' % var) 151*4882a593Smuzhiyun assert response == '' 152*4882a593Smuzhiyun 153*4882a593Smuzhiyundef validate_set(state_test_env, var, value): 154*4882a593Smuzhiyun """Validate that a variable is set, using U-Boot shell commands. 155*4882a593Smuzhiyun 156*4882a593Smuzhiyun Args: 157*4882a593Smuzhiyun var: The variable name to test. 158*4882a593Smuzhiyun value: The value the variable is expected to have. 159*4882a593Smuzhiyun 160*4882a593Smuzhiyun Returns: 161*4882a593Smuzhiyun Nothing. 162*4882a593Smuzhiyun """ 163*4882a593Smuzhiyun 164*4882a593Smuzhiyun # echo does not preserve leading, internal, or trailing whitespace in the 165*4882a593Smuzhiyun # value. printenv does, and hence allows more complete testing. 166*4882a593Smuzhiyun response = state_test_env.u_boot_console.run_command('printenv %s' % var) 167*4882a593Smuzhiyun assert response == ('%s=%s' % (var, value)) 168*4882a593Smuzhiyun 169*4882a593Smuzhiyundef test_env_echo_exists(state_test_env): 170*4882a593Smuzhiyun """Test echoing a variable that exists.""" 171*4882a593Smuzhiyun 172*4882a593Smuzhiyun var = state_test_env.get_existent_var() 173*4882a593Smuzhiyun value = state_test_env.env[var] 174*4882a593Smuzhiyun validate_set(state_test_env, var, value) 175*4882a593Smuzhiyun 176*4882a593Smuzhiyun@pytest.mark.buildconfigspec('cmd_echo') 177*4882a593Smuzhiyundef test_env_echo_non_existent(state_test_env): 178*4882a593Smuzhiyun """Test echoing a variable that doesn't exist.""" 179*4882a593Smuzhiyun 180*4882a593Smuzhiyun var = state_test_env.set_var 181*4882a593Smuzhiyun validate_empty(state_test_env, var) 182*4882a593Smuzhiyun 183*4882a593Smuzhiyundef test_env_printenv_non_existent(state_test_env): 184*4882a593Smuzhiyun """Test printenv error message for non-existant variables.""" 185*4882a593Smuzhiyun 186*4882a593Smuzhiyun var = state_test_env.set_var 187*4882a593Smuzhiyun c = state_test_env.u_boot_console 188*4882a593Smuzhiyun with c.disable_check('error_notification'): 189*4882a593Smuzhiyun response = c.run_command('printenv %s' % var) 190*4882a593Smuzhiyun assert(response == '## Error: "%s" not defined' % var) 191*4882a593Smuzhiyun 192*4882a593Smuzhiyun@pytest.mark.buildconfigspec('cmd_echo') 193*4882a593Smuzhiyundef test_env_unset_non_existent(state_test_env): 194*4882a593Smuzhiyun """Test unsetting a nonexistent variable.""" 195*4882a593Smuzhiyun 196*4882a593Smuzhiyun var = state_test_env.get_non_existent_var() 197*4882a593Smuzhiyun unset_var(state_test_env, var) 198*4882a593Smuzhiyun validate_empty(state_test_env, var) 199*4882a593Smuzhiyun 200*4882a593Smuzhiyundef test_env_set_non_existent(state_test_env): 201*4882a593Smuzhiyun """Test set a non-existant variable.""" 202*4882a593Smuzhiyun 203*4882a593Smuzhiyun var = state_test_env.set_var 204*4882a593Smuzhiyun value = 'foo' 205*4882a593Smuzhiyun set_var(state_test_env, var, value) 206*4882a593Smuzhiyun validate_set(state_test_env, var, value) 207*4882a593Smuzhiyun 208*4882a593Smuzhiyundef test_env_set_existing(state_test_env): 209*4882a593Smuzhiyun """Test setting an existant variable.""" 210*4882a593Smuzhiyun 211*4882a593Smuzhiyun var = state_test_env.set_var 212*4882a593Smuzhiyun value = 'bar' 213*4882a593Smuzhiyun set_var(state_test_env, var, value) 214*4882a593Smuzhiyun validate_set(state_test_env, var, value) 215*4882a593Smuzhiyun 216*4882a593Smuzhiyun@pytest.mark.buildconfigspec('cmd_echo') 217*4882a593Smuzhiyundef test_env_unset_existing(state_test_env): 218*4882a593Smuzhiyun """Test unsetting a variable.""" 219*4882a593Smuzhiyun 220*4882a593Smuzhiyun var = state_test_env.set_var 221*4882a593Smuzhiyun unset_var(state_test_env, var) 222*4882a593Smuzhiyun validate_empty(state_test_env, var) 223*4882a593Smuzhiyun 224*4882a593Smuzhiyundef test_env_expansion_spaces(state_test_env): 225*4882a593Smuzhiyun """Test expanding a variable that contains a space in its value.""" 226*4882a593Smuzhiyun 227*4882a593Smuzhiyun var_space = None 228*4882a593Smuzhiyun var_test = None 229*4882a593Smuzhiyun try: 230*4882a593Smuzhiyun var_space = state_test_env.get_non_existent_var() 231*4882a593Smuzhiyun set_var(state_test_env, var_space, ' ') 232*4882a593Smuzhiyun 233*4882a593Smuzhiyun var_test = state_test_env.get_non_existent_var() 234*4882a593Smuzhiyun value = ' 1${%(var_space)s}${%(var_space)s} 2 ' % locals() 235*4882a593Smuzhiyun set_var(state_test_env, var_test, value) 236*4882a593Smuzhiyun value = ' 1 2 ' 237*4882a593Smuzhiyun validate_set(state_test_env, var_test, value) 238*4882a593Smuzhiyun finally: 239*4882a593Smuzhiyun if var_space: 240*4882a593Smuzhiyun unset_var(state_test_env, var_space) 241*4882a593Smuzhiyun if var_test: 242*4882a593Smuzhiyun unset_var(state_test_env, var_test) 243