• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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