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 19import pw_cli.envparse as 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 def setUp(self): 35 self.raw_env = { 36 'PATH': '/bin:/usr/bin:/usr/local/bin', 37 'FOO': '2020', 38 'ReVeRsE': 'pigweed', 39 } 40 41 self.parser = envparse.EnvironmentParser() 42 self.parser.add_var('PATH') 43 self.parser.add_var('FOO', type=int) 44 self.parser.add_var('BAR', type=bool) 45 self.parser.add_var('BAZ', type=float, default=math.pi) 46 self.parser.add_var('ReVeRsE', type=lambda s: s[::-1]) 47 self.parser.add_var('INT', type=int) 48 self.parser.add_var('ERROR', type=error) 49 50 def test_string_value(self): 51 env = self.parser.parse_env(env=self.raw_env) 52 self.assertEqual(env.PATH, self.raw_env['PATH']) 53 54 def test_int_value(self): 55 env = self.parser.parse_env(env=self.raw_env) 56 self.assertEqual(env.FOO, 2020) 57 58 def test_custom_value(self): 59 env = self.parser.parse_env(env=self.raw_env) 60 self.assertEqual(env.ReVeRsE, 'deewgip') 61 62 def test_empty_value(self): 63 env = self.parser.parse_env(env=self.raw_env) 64 self.assertEqual(env.BAR, None) 65 66 def test_default_value(self): 67 env = self.parser.parse_env(env=self.raw_env) 68 self.assertEqual(env.BAZ, math.pi) 69 70 def test_unknown_key(self): 71 env = self.parser.parse_env(env=self.raw_env) 72 with self.assertRaises(AttributeError): 73 env.BBBBB # pylint: disable=pointless-statement 74 75 def test_bad_value(self): 76 raw_env = {**self.raw_env, 'INT': 'not an int'} 77 with self.assertRaises(envparse.EnvironmentValueError) as ctx: 78 self.parser.parse_env(env=raw_env) 79 80 self.assertEqual(ctx.exception.variable, 'INT') 81 self.assertIsInstance(ctx.exception.__cause__, ValueError) 82 83 def test_custom_exception(self): 84 raw_env = {**self.raw_env, 'ERROR': 'error'} 85 with self.assertRaises(envparse.EnvironmentValueError) as ctx: 86 self.parser.parse_env(env=raw_env) 87 88 self.assertEqual(ctx.exception.variable, 'ERROR') 89 self.assertIsInstance(ctx.exception.__cause__, ErrorError) 90 91 92class TestEnvironmentParserWithPrefix(unittest.TestCase): 93 """Tests for envparse.EnvironmentParser using a prefix.""" 94 def setUp(self): 95 self.raw_env = { 96 'PW_FOO': '001', 97 'PW_BAR': '010', 98 'PW_BAZ': '100', 99 'IGNORED': '011', 100 } 101 102 def test_parse_unrecognized_variable(self): 103 parser = envparse.EnvironmentParser(prefix='PW_') 104 parser.add_var('PW_FOO') 105 parser.add_var('PW_BAR') 106 107 with self.assertRaises(ValueError): 108 parser.parse_env(env=self.raw_env) 109 110 def test_parse_unrecognized_but_allowed_suffix(self): 111 parser = envparse.EnvironmentParser(prefix='PW_') 112 parser.add_allowed_suffix('_ALLOWED_SUFFIX') 113 114 env = parser.parse_env(env={'PW_FOO_ALLOWED_SUFFIX': '001'}) 115 self.assertEqual(env.PW_FOO_ALLOWED_SUFFIX, '001') 116 117 def test_parse_allowed_suffix_but_not_suffix(self): 118 parser = envparse.EnvironmentParser(prefix='PW_') 119 parser.add_allowed_suffix('_ALLOWED_SUFFIX') 120 121 with self.assertRaises(ValueError): 122 parser.parse_env(env={'PW_FOO_ALLOWED_SUFFIX_FOO': '001'}) 123 124 def test_parse_ignore_unrecognized(self): 125 parser = envparse.EnvironmentParser(prefix='PW_', 126 error_on_unrecognized=False) 127 parser.add_var('PW_FOO') 128 parser.add_var('PW_BAR') 129 130 env = parser.parse_env(env=self.raw_env) 131 self.assertEqual(env.PW_FOO, self.raw_env['PW_FOO']) 132 self.assertEqual(env.PW_BAR, self.raw_env['PW_BAR']) 133 134 def test_add_var_without_prefix(self): 135 parser = envparse.EnvironmentParser(prefix='PW_') 136 with self.assertRaises(ValueError): 137 parser.add_var('FOO') 138 139 140class TestStrictBool(unittest.TestCase): 141 """Tests for envparse.strict_bool.""" 142 def setUp(self): 143 self.good_bools = ['true', '1', 'TRUE', 'tRuE'] 144 self.bad_bools = [ 145 '', 'false', '0', 'foo', '2', '999', 'ok', 'yes', 'no' 146 ] 147 148 def test_good_bools(self): 149 self.assertTrue( 150 all(envparse.strict_bool(val) for val in self.good_bools)) 151 152 def test_bad_bools(self): 153 self.assertFalse( 154 any(envparse.strict_bool(val) for val in self.bad_bools)) 155 156 157if __name__ == '__main__': 158 unittest.main() 159