1# Copyright 2017 The Abseil Authors. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://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, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14"""Additional tests for flag argument parsers. 15 16Most of the argument parsers are covered in the flags_test.py. 17""" 18 19import enum 20 21from absl.flags import _argument_parser 22from absl.testing import absltest 23from absl.testing import parameterized 24 25 26class ArgumentParserTest(absltest.TestCase): 27 28 def test_instance_cache(self): 29 parser1 = _argument_parser.FloatParser() 30 parser2 = _argument_parser.FloatParser() 31 self.assertIs(parser1, parser2) 32 33 def test_parse_wrong_type(self): 34 parser = _argument_parser.ArgumentParser() 35 with self.assertRaises(TypeError): 36 parser.parse(0) 37 38 if bytes is not str: 39 # In PY3, it does not accept bytes. 40 with self.assertRaises(TypeError): 41 parser.parse(b'') 42 43 44class BooleanParserTest(absltest.TestCase): 45 46 def setUp(self): 47 super().setUp() 48 self.parser = _argument_parser.BooleanParser() 49 50 def test_parse_bytes(self): 51 with self.assertRaises(TypeError): 52 self.parser.parse(b'true') 53 54 def test_parse_str(self): 55 self.assertTrue(self.parser.parse('true')) 56 57 def test_parse_unicode(self): 58 self.assertTrue(self.parser.parse(u'true')) 59 60 def test_parse_wrong_type(self): 61 with self.assertRaises(TypeError): 62 self.parser.parse(1.234) 63 64 def test_parse_str_false(self): 65 self.assertFalse(self.parser.parse('false')) 66 67 def test_parse_integer(self): 68 self.assertTrue(self.parser.parse(1)) 69 70 def test_parse_invalid_integer(self): 71 with self.assertRaises(ValueError): 72 self.parser.parse(-1) 73 74 def test_parse_invalid_str(self): 75 with self.assertRaises(ValueError): 76 self.parser.parse('nottrue') 77 78 79class FloatParserTest(absltest.TestCase): 80 81 def setUp(self): 82 self.parser = _argument_parser.FloatParser() 83 84 def test_parse_string(self): 85 self.assertEqual(1.5, self.parser.parse('1.5')) 86 87 def test_parse_wrong_type(self): 88 with self.assertRaises(TypeError): 89 self.parser.parse(False) 90 91 92class IntegerParserTest(absltest.TestCase): 93 94 def setUp(self): 95 self.parser = _argument_parser.IntegerParser() 96 97 def test_parse_string(self): 98 self.assertEqual(1, self.parser.parse('1')) 99 100 def test_parse_wrong_type(self): 101 with self.assertRaises(TypeError): 102 self.parser.parse(1e2) 103 with self.assertRaises(TypeError): 104 self.parser.parse(False) 105 106 107class EnumParserTest(absltest.TestCase): 108 109 def test_empty_values(self): 110 with self.assertRaises(ValueError): 111 _argument_parser.EnumParser([]) 112 113 def test_parse(self): 114 parser = _argument_parser.EnumParser(['apple', 'banana']) 115 self.assertEqual('apple', parser.parse('apple')) 116 117 def test_parse_not_found(self): 118 parser = _argument_parser.EnumParser(['apple', 'banana']) 119 with self.assertRaises(ValueError): 120 parser.parse('orange') 121 122 123class Fruit(enum.Enum): 124 APPLE = 1 125 BANANA = 2 126 127 128class EmptyEnum(enum.Enum): 129 pass 130 131 132class MixedCaseEnum(enum.Enum): 133 APPLE = 1 134 BANANA = 2 135 apple = 3 136 137 138class EnumClassParserTest(parameterized.TestCase): 139 140 def test_requires_enum(self): 141 with self.assertRaises(TypeError): 142 _argument_parser.EnumClassParser(['apple', 'banana']) 143 144 def test_requires_non_empty_enum_class(self): 145 with self.assertRaises(ValueError): 146 _argument_parser.EnumClassParser(EmptyEnum) 147 148 def test_case_sensitive_rejects_duplicates(self): 149 unused_normal_parser = _argument_parser.EnumClassParser(MixedCaseEnum) 150 with self.assertRaisesRegex(ValueError, 'Duplicate.+apple'): 151 _argument_parser.EnumClassParser(MixedCaseEnum, case_sensitive=False) 152 153 def test_parse_string(self): 154 parser = _argument_parser.EnumClassParser(Fruit) 155 self.assertEqual(Fruit.APPLE, parser.parse('APPLE')) 156 157 def test_parse_string_case_sensitive(self): 158 parser = _argument_parser.EnumClassParser(Fruit) 159 with self.assertRaises(ValueError): 160 parser.parse('apple') 161 162 @parameterized.parameters('APPLE', 'apple', 'Apple') 163 def test_parse_string_case_insensitive(self, value): 164 parser = _argument_parser.EnumClassParser(Fruit, case_sensitive=False) 165 self.assertIs(Fruit.APPLE, parser.parse(value)) 166 167 def test_parse_literal(self): 168 parser = _argument_parser.EnumClassParser(Fruit) 169 self.assertEqual(Fruit.APPLE, parser.parse(Fruit.APPLE)) 170 171 def test_parse_not_found(self): 172 parser = _argument_parser.EnumClassParser(Fruit) 173 with self.assertRaises(ValueError): 174 parser.parse('ORANGE') 175 176 @parameterized.parameters((Fruit.BANANA, False, 'BANANA'), 177 (Fruit.BANANA, True, 'banana')) 178 def test_serialize_parse(self, value, lowercase, expected): 179 serializer = _argument_parser.EnumClassSerializer(lowercase=lowercase) 180 parser = _argument_parser.EnumClassParser( 181 Fruit, case_sensitive=not lowercase) 182 serialized = serializer.serialize(value) 183 self.assertEqual(serialized, expected) 184 self.assertEqual(value, parser.parse(expected)) 185 186 187class SerializerTest(parameterized.TestCase): 188 189 def test_csv_serializer(self): 190 serializer = _argument_parser.CsvListSerializer('+') 191 self.assertEqual(serializer.serialize(['foo', 'bar']), 'foo+bar') 192 193 @parameterized.parameters([ 194 dict(lowercase=False, expected='APPLE+BANANA'), 195 dict(lowercase=True, expected='apple+banana'), 196 ]) 197 def test_enum_class_list_serializer(self, lowercase, expected): 198 values = [Fruit.APPLE, Fruit.BANANA] 199 serializer = _argument_parser.EnumClassListSerializer( 200 list_sep='+', lowercase=lowercase) 201 serialized = serializer.serialize(values) 202 self.assertEqual(expected, serialized) 203 204 205class HelperFunctionsTest(absltest.TestCase): 206 207 def test_is_integer_type(self): 208 self.assertTrue(_argument_parser._is_integer_type(1)) 209 # Note that isinstance(False, int) == True. 210 self.assertFalse(_argument_parser._is_integer_type(False)) 211 212 213if __name__ == '__main__': 214 absltest.main() 215