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 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(error_on_unrecognized=True) 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 error_on_unrecognized=True) 105 parser.add_var('PW_FOO') 106 parser.add_var('PW_BAR') 107 108 with self.assertRaises(ValueError): 109 parser.parse_env(env=self.raw_env) 110 111 def test_parse_unrecognized_but_allowed_suffix(self): 112 parser = envparse.EnvironmentParser(prefix='PW_', 113 error_on_unrecognized=True) 114 parser.add_allowed_suffix('_ALLOWED_SUFFIX') 115 116 env = parser.parse_env(env={'PW_FOO_ALLOWED_SUFFIX': '001'}) 117 self.assertEqual(env.PW_FOO_ALLOWED_SUFFIX, '001') 118 119 def test_parse_allowed_suffix_but_not_suffix(self): 120 parser = envparse.EnvironmentParser(prefix='PW_', 121 error_on_unrecognized=True) 122 parser.add_allowed_suffix('_ALLOWED_SUFFIX') 123 124 with self.assertRaises(ValueError): 125 parser.parse_env(env={'PW_FOO_ALLOWED_SUFFIX_FOO': '001'}) 126 127 def test_parse_ignore_unrecognized(self): 128 parser = envparse.EnvironmentParser(prefix='PW_', 129 error_on_unrecognized=False) 130 parser.add_var('PW_FOO') 131 parser.add_var('PW_BAR') 132 133 env = parser.parse_env(env=self.raw_env) 134 self.assertEqual(env.PW_FOO, self.raw_env['PW_FOO']) 135 self.assertEqual(env.PW_BAR, self.raw_env['PW_BAR']) 136 137 def test_add_var_without_prefix(self): 138 parser = envparse.EnvironmentParser(prefix='PW_', 139 error_on_unrecognized=True) 140 with self.assertRaises(ValueError): 141 parser.add_var('FOO') 142 143 144class TestStrictBool(unittest.TestCase): 145 """Tests for envparse.strict_bool.""" 146 def setUp(self): 147 self.good_bools = ['true', '1', 'TRUE', 'tRuE'] 148 self.bad_bools = [ 149 '', 'false', '0', 'foo', '2', '999', 'ok', 'yes', 'no' 150 ] 151 152 def test_good_bools(self): 153 self.assertTrue( 154 all(envparse.strict_bool(val) for val in self.good_bools)) 155 156 def test_bad_bools(self): 157 self.assertFalse( 158 any(envparse.strict_bool(val) for val in self.bad_bools)) 159 160 161if __name__ == '__main__': 162 unittest.main() 163