1# Copyright 2020 The Pigweed Authors 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); you may not 4# use this file except in compliance with the License. You may obtain a copy of 5# the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12# License for the specific language governing permissions and limitations under 13# the License. 14"""Tests for pw_cli.envparse.""" 15 16import math 17import unittest 18 19from pw_cli import envparse 20 21# pylint: disable=no-member 22 23 24class ErrorError(Exception): 25 pass 26 27 28def error(value: str): 29 raise ErrorError('error!') 30 31 32class TestEnvironmentParser(unittest.TestCase): 33 """Tests for envparse.EnvironmentParser.""" 34 35 def setUp(self): 36 self.raw_env = { 37 'PATH': '/bin:/usr/bin:/usr/local/bin', 38 'FOO': '2020', 39 'ReVeRsE': 'pigweed', 40 } 41 42 self.parser = envparse.EnvironmentParser(error_on_unrecognized=True) 43 self.parser.add_var('PATH') 44 self.parser.add_var('FOO', type=int) 45 self.parser.add_var('BAR', type=bool) 46 self.parser.add_var('BAZ', type=float, default=math.pi) 47 self.parser.add_var('ReVeRsE', type=lambda s: s[::-1]) 48 self.parser.add_var('INT', type=int) 49 self.parser.add_var('ERROR', type=error) 50 51 def test_string_value(self): 52 env = self.parser.parse_env(env=self.raw_env) 53 self.assertEqual(env.PATH, self.raw_env['PATH']) 54 55 def test_int_value(self): 56 env = self.parser.parse_env(env=self.raw_env) 57 self.assertEqual(env.FOO, 2020) 58 59 def test_custom_value(self): 60 env = self.parser.parse_env(env=self.raw_env) 61 self.assertEqual(env.ReVeRsE, 'deewgip') 62 63 def test_empty_value(self): 64 env = self.parser.parse_env(env=self.raw_env) 65 self.assertEqual(env.BAR, None) 66 67 def test_default_value(self): 68 env = self.parser.parse_env(env=self.raw_env) 69 self.assertEqual(env.BAZ, math.pi) 70 71 def test_unknown_key(self): 72 env = self.parser.parse_env(env=self.raw_env) 73 with self.assertRaises(AttributeError): 74 env.BBBBB # pylint: disable=pointless-statement 75 76 def test_bad_value(self): 77 raw_env = {**self.raw_env, 'INT': 'not an int'} 78 with self.assertRaises(envparse.EnvironmentValueError) as ctx: 79 self.parser.parse_env(env=raw_env) 80 81 self.assertEqual(ctx.exception.variable, 'INT') 82 self.assertIsInstance(ctx.exception.__cause__, ValueError) 83 84 def test_custom_exception(self): 85 raw_env = {**self.raw_env, 'ERROR': 'error'} 86 with self.assertRaises(envparse.EnvironmentValueError) as ctx: 87 self.parser.parse_env(env=raw_env) 88 89 self.assertEqual(ctx.exception.variable, 'ERROR') 90 self.assertIsInstance(ctx.exception.__cause__, ErrorError) 91 92 93class TestEnvironmentParserWithPrefix(unittest.TestCase): 94 """Tests for envparse.EnvironmentParser using a prefix.""" 95 96 def setUp(self): 97 self.raw_env = { 98 'PW_FOO': '001', 99 'PW_BAR': '010', 100 'PW_BAZ': '100', 101 'IGNORED': '011', 102 } 103 104 def test_parse_unrecognized_variable(self): 105 parser = envparse.EnvironmentParser( 106 prefix='PW_', error_on_unrecognized=True 107 ) 108 parser.add_var('PW_FOO') 109 parser.add_var('PW_BAR') 110 111 with self.assertRaises(ValueError): 112 parser.parse_env(env=self.raw_env) 113 114 def test_parse_unrecognized_but_allowed_suffix(self): 115 parser = envparse.EnvironmentParser( 116 prefix='PW_', error_on_unrecognized=True 117 ) 118 parser.add_allowed_suffix('_ALLOWED_SUFFIX') 119 120 env = parser.parse_env(env={'PW_FOO_ALLOWED_SUFFIX': '001'}) 121 self.assertEqual(env.PW_FOO_ALLOWED_SUFFIX, '001') 122 123 def test_parse_allowed_suffix_but_not_suffix(self): 124 parser = envparse.EnvironmentParser( 125 prefix='PW_', error_on_unrecognized=True 126 ) 127 parser.add_allowed_suffix('_ALLOWED_SUFFIX') 128 129 with self.assertRaises(ValueError): 130 parser.parse_env(env={'PW_FOO_ALLOWED_SUFFIX_FOO': '001'}) 131 132 def test_parse_ignore_unrecognized(self): 133 parser = envparse.EnvironmentParser( 134 prefix='PW_', error_on_unrecognized=False 135 ) 136 parser.add_var('PW_FOO') 137 parser.add_var('PW_BAR') 138 139 env = parser.parse_env(env=self.raw_env) 140 self.assertEqual(env.PW_FOO, self.raw_env['PW_FOO']) 141 self.assertEqual(env.PW_BAR, self.raw_env['PW_BAR']) 142 143 def test_add_var_without_prefix(self): 144 parser = envparse.EnvironmentParser( 145 prefix='PW_', error_on_unrecognized=True 146 ) 147 with self.assertRaises(ValueError): 148 parser.add_var('FOO') 149 150 151class TestStrictBool(unittest.TestCase): 152 """Tests for envparse.strict_bool.""" 153 154 def setUp(self): 155 self.good_bools = ['true', '1', 'TRUE', 'tRuE'] 156 self.bad_bools = [ 157 '', 158 'false', 159 '0', 160 'foo', 161 '2', 162 '999', 163 'ok', 164 'yes', 165 'no', 166 ] 167 168 def test_good_bools(self): 169 self.assertTrue( 170 all(envparse.strict_bool(val) for val in self.good_bools) 171 ) 172 173 def test_bad_bools(self): 174 self.assertFalse( 175 any(envparse.strict_bool(val) for val in self.bad_bools) 176 ) 177 178 179if __name__ == '__main__': 180 unittest.main() 181