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"""Tests for flagsaver."""
15
16from absl import flags
17from absl.testing import absltest
18from absl.testing import flagsaver
19from absl.testing import parameterized
20
21flags.DEFINE_string('flagsaver_test_flag0', 'unchanged0', 'flag to test with')
22flags.DEFINE_string('flagsaver_test_flag1', 'unchanged1', 'flag to test with')
23
24flags.DEFINE_string('flagsaver_test_validated_flag', None, 'flag to test with')
25flags.register_validator('flagsaver_test_validated_flag', lambda x: not x)
26
27flags.DEFINE_string('flagsaver_test_validated_flag1', None, 'flag to test with')
28flags.DEFINE_string('flagsaver_test_validated_flag2', None, 'flag to test with')
29
30INT_FLAG = flags.DEFINE_integer(
31    'flagsaver_test_int_flag', default=1, help='help')
32STR_FLAG = flags.DEFINE_string(
33    'flagsaver_test_str_flag', default='str default', help='help')
34
35MULTI_INT_FLAG = flags.DEFINE_multi_integer('flagsaver_test_multi_int_flag',
36                                            None, 'flag to test with')
37
38
39@flags.multi_flags_validator(
40    ('flagsaver_test_validated_flag1', 'flagsaver_test_validated_flag2'))
41def validate_test_flags(flag_dict):
42  return (flag_dict['flagsaver_test_validated_flag1'] ==
43          flag_dict['flagsaver_test_validated_flag2'])
44
45
46FLAGS = flags.FLAGS
47
48
49@flags.validator('flagsaver_test_flag0')
50def check_no_upper_case(value):
51  return value == value.lower()
52
53
54class _TestError(Exception):
55  """Exception class for use in these tests."""
56
57
58class CommonUsageTest(absltest.TestCase):
59  """These test cases cover the most common usages of flagsaver."""
60
61  def test_as_parsed_context_manager(self):
62    # Precondition check, we expect all the flags to start as their default.
63    self.assertEqual('str default', STR_FLAG.value)
64    self.assertFalse(STR_FLAG.present)
65    self.assertEqual(1, INT_FLAG.value)
66    self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
67    self.assertEqual('unchanged1', FLAGS.flagsaver_test_flag1)
68
69    # Flagsaver will also save the state of flags that have been modified.
70    FLAGS.flagsaver_test_flag1 = 'outside flagsaver'
71
72    # Save all existing flag state, and set some flags as if they were parsed on
73    # the command line. Because of this, the new values must be provided as str,
74    # even if the flag type is something other than string.
75    with flagsaver.as_parsed(
76        (STR_FLAG, 'new string value'),  # Override using flagholder object.
77        (INT_FLAG, '123'),  # Override an int flag (NOTE: must specify as str).
78        flagsaver_test_flag0='new value',  # Override using flag name.
79    ):
80      # All the flags have their overridden values.
81      self.assertEqual('new string value', STR_FLAG.value)
82      self.assertTrue(STR_FLAG.present)
83      self.assertEqual(123, INT_FLAG.value)
84      self.assertEqual('new value', FLAGS.flagsaver_test_flag0)
85      # Even if we change other flags, they will reset on context exit.
86      FLAGS.flagsaver_test_flag1 = 'new value 1'
87
88    # The flags have all reset to their pre-flagsaver values.
89    self.assertEqual('str default', STR_FLAG.value)
90    self.assertFalse(STR_FLAG.present)
91    self.assertEqual(1, INT_FLAG.value)
92    self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
93    self.assertEqual('outside flagsaver', FLAGS.flagsaver_test_flag1)
94
95  def test_as_parsed_decorator(self):
96    # flagsaver.as_parsed can also be used as a decorator.
97    @flagsaver.as_parsed((INT_FLAG, '123'))
98    def do_something_with_flags():
99      self.assertEqual(123, INT_FLAG.value)
100      self.assertTrue(INT_FLAG.present)
101
102    do_something_with_flags()
103    self.assertEqual(1, INT_FLAG.value)
104    self.assertFalse(INT_FLAG.present)
105
106  def test_flagsaver_flagsaver(self):
107    # If you don't want the flags to go through parsing, you can instead use
108    # flagsaver.flagsaver(). With this method, you provide the native python
109    # value you'd like the flags to take on. Otherwise it functions similar to
110    # flagsaver.as_parsed().
111    @flagsaver.flagsaver((INT_FLAG, 345))
112    def do_something_with_flags():
113      self.assertEqual(345, INT_FLAG.value)
114      # Note that because this flag was never parsed, it will not register as
115      # .present unless you manually set that attribute.
116      self.assertFalse(INT_FLAG.present)
117      # If you do chose to modify things about the flag (such as .present) those
118      # changes will still be cleaned up when flagsaver.flagsaver() exits.
119      INT_FLAG.present = True
120
121    self.assertEqual(1, INT_FLAG.value)
122    # flagsaver.flagsaver() restored INT_FLAG.present to the state it was in
123    # before entering the context.
124    self.assertFalse(INT_FLAG.present)
125
126
127class SaveFlagValuesTest(absltest.TestCase):
128  """Test flagsaver.save_flag_values() and flagsaver.restore_flag_values().
129
130  In this test, we insure that *all* properties of flags get restored. In other
131  tests we only try changing the flag value.
132  """
133
134  def test_assign_value(self):
135    # First save the flag values.
136    saved_flag_values = flagsaver.save_flag_values()
137
138    # Now mutate the flag's value field and check that it changed.
139    FLAGS.flagsaver_test_flag0 = 'new value'
140    self.assertEqual('new value', FLAGS.flagsaver_test_flag0)
141
142    # Now restore the flag to its original value.
143    flagsaver.restore_flag_values(saved_flag_values)
144    self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
145
146  def test_set_default(self):
147    # First save the flag.
148    saved_flag_values = flagsaver.save_flag_values()
149
150    # Now mutate the flag's default field and check that it changed.
151    FLAGS.set_default('flagsaver_test_flag0', 'new_default')
152    self.assertEqual('new_default', FLAGS['flagsaver_test_flag0'].default)
153
154    # Now restore the flag's default field.
155    flagsaver.restore_flag_values(saved_flag_values)
156    self.assertEqual('unchanged0', FLAGS['flagsaver_test_flag0'].default)
157
158  def test_parse(self):
159    # First save the flag.
160    saved_flag_values = flagsaver.save_flag_values()
161
162    # Sanity check (would fail if called with --flagsaver_test_flag0).
163    self.assertEqual(0, FLAGS['flagsaver_test_flag0'].present)
164    # Now populate the flag and check that it changed.
165    FLAGS['flagsaver_test_flag0'].parse('new value')
166    self.assertEqual('new value', FLAGS['flagsaver_test_flag0'].value)
167    self.assertEqual(1, FLAGS['flagsaver_test_flag0'].present)
168
169    # Now restore the flag to its original value.
170    flagsaver.restore_flag_values(saved_flag_values)
171    self.assertEqual('unchanged0', FLAGS['flagsaver_test_flag0'].value)
172    self.assertEqual(0, FLAGS['flagsaver_test_flag0'].present)
173
174  def test_assign_validators(self):
175    # First save the flag.
176    saved_flag_values = flagsaver.save_flag_values()
177
178    # Sanity check that a validator already exists.
179    self.assertLen(FLAGS['flagsaver_test_flag0'].validators, 1)
180    original_validators = list(FLAGS['flagsaver_test_flag0'].validators)
181
182    def no_space(value):
183      return ' ' not in value
184
185    # Add a new validator.
186    flags.register_validator('flagsaver_test_flag0', no_space)
187    self.assertLen(FLAGS['flagsaver_test_flag0'].validators, 2)
188
189    # Now restore the flag to its original value.
190    flagsaver.restore_flag_values(saved_flag_values)
191    self.assertEqual(
192        original_validators, FLAGS['flagsaver_test_flag0'].validators
193    )
194
195
196@parameterized.named_parameters(
197    dict(
198        testcase_name='flagsaver.flagsaver',
199        flagsaver_method=flagsaver.flagsaver,
200    ),
201    dict(
202        testcase_name='flagsaver.as_parsed',
203        flagsaver_method=flagsaver.as_parsed,
204    ),
205)
206class NoOverridesTest(parameterized.TestCase):
207  """Test flagsaver.flagsaver and flagsaver.as_parsed without overrides."""
208
209  def test_context_manager_with_call(self, flagsaver_method):
210    with flagsaver_method():
211      FLAGS.flagsaver_test_flag0 = 'new value'
212    self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
213
214  def test_context_manager_with_exception(self, flagsaver_method):
215    with self.assertRaises(_TestError):
216      with flagsaver_method():
217        FLAGS.flagsaver_test_flag0 = 'new value'
218        # Simulate a failed test.
219        raise _TestError('something happened')
220    self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
221
222  def test_decorator_without_call(self, flagsaver_method):
223    @flagsaver_method
224    def mutate_flags():
225      FLAGS.flagsaver_test_flag0 = 'new value'
226
227    mutate_flags()
228    self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
229
230  def test_decorator_with_call(self, flagsaver_method):
231    @flagsaver_method()
232    def mutate_flags():
233      FLAGS.flagsaver_test_flag0 = 'new value'
234
235    mutate_flags()
236    self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
237
238  def test_decorator_with_exception(self, flagsaver_method):
239    @flagsaver_method()
240    def raise_exception():
241      FLAGS.flagsaver_test_flag0 = 'new value'
242      # Simulate a failed test.
243      raise _TestError('something happened')
244
245    self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
246    self.assertRaises(_TestError, raise_exception)
247    self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
248
249
250@parameterized.named_parameters(
251    dict(
252        testcase_name='flagsaver.flagsaver',
253        flagsaver_method=flagsaver.flagsaver,
254    ),
255    dict(
256        testcase_name='flagsaver.as_parsed',
257        flagsaver_method=flagsaver.as_parsed,
258    ),
259)
260class TestStringFlagOverrides(parameterized.TestCase):
261  """Test flagsaver.flagsaver and flagsaver.as_parsed with string overrides.
262
263  Note that these tests can be parameterized because both .flagsaver and
264  .as_parsed expect a str input when overriding a string flag. For non-string
265  flags these two flagsaver methods have separate tests elsewhere in this file.
266
267  Each test is one class of overrides, executed twice. Once as a context
268  manager, and once as a decorator on a mutate_flags() method.
269  """
270
271  def test_keyword_overrides(self, flagsaver_method):
272    # Context manager:
273    with flagsaver_method(flagsaver_test_flag0='new value'):
274      self.assertEqual('new value', FLAGS.flagsaver_test_flag0)
275    self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
276
277    # Decorator:
278    @flagsaver_method(flagsaver_test_flag0='new value')
279    def mutate_flags():
280      self.assertEqual('new value', FLAGS.flagsaver_test_flag0)
281
282    mutate_flags()
283    self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
284
285  def test_flagholder_overrides(self, flagsaver_method):
286    with flagsaver_method((STR_FLAG, 'new value')):
287      self.assertEqual('new value', STR_FLAG.value)
288    self.assertEqual('str default', STR_FLAG.value)
289
290    @flagsaver_method((STR_FLAG, 'new value'))
291    def mutate_flags():
292      self.assertEqual('new value', STR_FLAG.value)
293
294    mutate_flags()
295    self.assertEqual('str default', STR_FLAG.value)
296
297  def test_keyword_and_flagholder_overrides(self, flagsaver_method):
298    with flagsaver_method(
299        (STR_FLAG, 'another value'), flagsaver_test_flag0='new value'
300    ):
301      self.assertEqual('another value', STR_FLAG.value)
302      self.assertEqual('new value', FLAGS.flagsaver_test_flag0)
303    self.assertEqual('str default', STR_FLAG.value)
304    self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
305
306    @flagsaver_method(
307        (STR_FLAG, 'another value'), flagsaver_test_flag0='new value'
308    )
309    def mutate_flags():
310      self.assertEqual('another value', STR_FLAG.value)
311      self.assertEqual('new value', FLAGS.flagsaver_test_flag0)
312
313    mutate_flags()
314    self.assertEqual('str default', STR_FLAG.value)
315    self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
316
317  def test_cross_validated_overrides_set_together(self, flagsaver_method):
318    # When the flags are set in the same flagsaver call their validators will
319    # be triggered only once the setting is done.
320    with flagsaver_method(
321        flagsaver_test_validated_flag1='new_value',
322        flagsaver_test_validated_flag2='new_value',
323    ):
324      self.assertEqual('new_value', FLAGS.flagsaver_test_validated_flag1)
325      self.assertEqual('new_value', FLAGS.flagsaver_test_validated_flag2)
326    self.assertIsNone(FLAGS.flagsaver_test_validated_flag1)
327    self.assertIsNone(FLAGS.flagsaver_test_validated_flag2)
328
329    @flagsaver_method(
330        flagsaver_test_validated_flag1='new_value',
331        flagsaver_test_validated_flag2='new_value',
332    )
333    def mutate_flags():
334      self.assertEqual('new_value', FLAGS.flagsaver_test_validated_flag1)
335      self.assertEqual('new_value', FLAGS.flagsaver_test_validated_flag2)
336
337    mutate_flags()
338    self.assertIsNone(FLAGS.flagsaver_test_validated_flag1)
339    self.assertIsNone(FLAGS.flagsaver_test_validated_flag2)
340
341  def test_cross_validated_overrides_set_badly(self, flagsaver_method):
342    # Different values should violate the validator.
343    with self.assertRaisesRegex(
344        flags.IllegalFlagValueError, 'Flag validation failed'
345    ):
346      with flagsaver_method(
347          flagsaver_test_validated_flag1='new_value',
348          flagsaver_test_validated_flag2='other_value',
349      ):
350        pass
351    self.assertIsNone(FLAGS.flagsaver_test_validated_flag1)
352    self.assertIsNone(FLAGS.flagsaver_test_validated_flag2)
353
354    @flagsaver_method(
355        flagsaver_test_validated_flag1='new_value',
356        flagsaver_test_validated_flag2='other_value',
357    )
358    def mutate_flags():
359      pass
360
361    self.assertRaisesRegex(
362        flags.IllegalFlagValueError, 'Flag validation failed', mutate_flags
363    )
364    self.assertIsNone(FLAGS.flagsaver_test_validated_flag1)
365    self.assertIsNone(FLAGS.flagsaver_test_validated_flag2)
366
367  def test_cross_validated_overrides_set_separately(self, flagsaver_method):
368    # Setting just one flag will trip the validator as well.
369    with self.assertRaisesRegex(
370        flags.IllegalFlagValueError, 'Flag validation failed'
371    ):
372      with flagsaver_method(flagsaver_test_validated_flag1='new_value'):
373        pass
374    self.assertIsNone(FLAGS.flagsaver_test_validated_flag1)
375    self.assertIsNone(FLAGS.flagsaver_test_validated_flag2)
376
377    @flagsaver_method(flagsaver_test_validated_flag1='new_value')
378    def mutate_flags():
379      pass
380
381    self.assertRaisesRegex(
382        flags.IllegalFlagValueError, 'Flag validation failed', mutate_flags
383    )
384    self.assertIsNone(FLAGS.flagsaver_test_validated_flag1)
385    self.assertIsNone(FLAGS.flagsaver_test_validated_flag2)
386
387  def test_validation_exception(self, flagsaver_method):
388    with self.assertRaises(flags.IllegalFlagValueError):
389      with flagsaver_method(
390          flagsaver_test_flag0='new value',
391          flagsaver_test_validated_flag='new value',
392      ):
393        pass
394    self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
395    self.assertIsNone(FLAGS.flagsaver_test_validated_flag)
396
397    @flagsaver_method(
398        flagsaver_test_flag0='new value',
399        flagsaver_test_validated_flag='new value',
400    )
401    def mutate_flags():
402      pass
403
404    self.assertRaises(flags.IllegalFlagValueError, mutate_flags)
405    self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
406    self.assertIsNone(FLAGS.flagsaver_test_validated_flag)
407
408  def test_unknown_flag_raises_exception(self, flagsaver_method):
409    self.assertNotIn('this_flag_does_not_exist', FLAGS)
410
411    # Flagsaver raises an error when trying to override a non-existent flag.
412    with self.assertRaises(flags.UnrecognizedFlagError):
413      with flagsaver_method(
414          flagsaver_test_flag0='new value', this_flag_does_not_exist='new value'
415      ):
416        pass
417    self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
418
419    @flagsaver_method(
420        flagsaver_test_flag0='new value', this_flag_does_not_exist='new value'
421    )
422    def mutate_flags():
423      pass
424
425    self.assertRaises(flags.UnrecognizedFlagError, mutate_flags)
426    self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
427
428    # Make sure flagsaver didn't create the flag at any point.
429    self.assertNotIn('this_flag_does_not_exist', FLAGS)
430
431
432class AsParsedTest(absltest.TestCase):
433
434  def test_parse_context_manager_sets_present_and_using_default(self):
435    self.assertFalse(INT_FLAG.present)
436    self.assertFalse(STR_FLAG.present)
437    # Note that .using_default_value isn't available on the FlagHolder directly.
438    self.assertTrue(FLAGS[INT_FLAG.name].using_default_value)
439    self.assertTrue(FLAGS[STR_FLAG.name].using_default_value)
440
441    with flagsaver.as_parsed((INT_FLAG, '123'),
442                             flagsaver_test_str_flag='new value'):
443      self.assertTrue(INT_FLAG.present)
444      self.assertTrue(STR_FLAG.present)
445      self.assertFalse(FLAGS[INT_FLAG.name].using_default_value)
446      self.assertFalse(FLAGS[STR_FLAG.name].using_default_value)
447
448    self.assertFalse(INT_FLAG.present)
449    self.assertFalse(STR_FLAG.present)
450    self.assertTrue(FLAGS[INT_FLAG.name].using_default_value)
451    self.assertTrue(FLAGS[STR_FLAG.name].using_default_value)
452
453  def test_parse_decorator_sets_present_and_using_default(self):
454    self.assertFalse(INT_FLAG.present)
455    self.assertFalse(STR_FLAG.present)
456    # Note that .using_default_value isn't available on the FlagHolder directly.
457    self.assertTrue(FLAGS[INT_FLAG.name].using_default_value)
458    self.assertTrue(FLAGS[STR_FLAG.name].using_default_value)
459
460    @flagsaver.as_parsed((INT_FLAG, '123'), flagsaver_test_str_flag='new value')
461    def some_func():
462      self.assertTrue(INT_FLAG.present)
463      self.assertTrue(STR_FLAG.present)
464      self.assertFalse(FLAGS[INT_FLAG.name].using_default_value)
465      self.assertFalse(FLAGS[STR_FLAG.name].using_default_value)
466
467    some_func()
468    self.assertFalse(INT_FLAG.present)
469    self.assertFalse(STR_FLAG.present)
470    self.assertTrue(FLAGS[INT_FLAG.name].using_default_value)
471    self.assertTrue(FLAGS[STR_FLAG.name].using_default_value)
472
473  def test_parse_decorator_with_multi_int_flag(self):
474    self.assertFalse(MULTI_INT_FLAG.present)
475    self.assertIsNone(MULTI_INT_FLAG.value)
476
477    @flagsaver.as_parsed((MULTI_INT_FLAG, ['123', '456']))
478    def assert_flags_updated():
479      self.assertTrue(MULTI_INT_FLAG.present)
480      self.assertCountEqual([123, 456], MULTI_INT_FLAG.value)
481
482    assert_flags_updated()
483    self.assertFalse(MULTI_INT_FLAG.present)
484    self.assertIsNone(MULTI_INT_FLAG.value)
485
486  def test_parse_raises_type_error(self):
487    with self.assertRaisesRegex(
488        TypeError,
489        r'flagsaver\.as_parsed\(\) cannot parse flagsaver_test_int_flag\. '
490        r'Expected a single string or sequence of strings but .*int.* was '
491        r'provided\.'):
492      manager = flagsaver.as_parsed(flagsaver_test_int_flag=123)  # pytype: disable=wrong-arg-types
493      del manager
494
495
496class SetUpTearDownTest(absltest.TestCase):
497  """Example using a single flagsaver in setUp."""
498
499  def setUp(self):
500    super().setUp()
501    self.saved_flag_values = flagsaver.save_flag_values()
502
503  def tearDown(self):
504    super().tearDown()
505    flagsaver.restore_flag_values(self.saved_flag_values)
506
507  def test_mutate1(self):
508    # Even though other test cases change the flag, it should be
509    # restored to 'unchanged0' if the flagsaver is working.
510    self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
511    FLAGS.flagsaver_test_flag0 = 'changed0'
512
513  def test_mutate2(self):
514    # Even though other test cases change the flag, it should be
515    # restored to 'unchanged0' if the flagsaver is working.
516    self.assertEqual('unchanged0', FLAGS.flagsaver_test_flag0)
517    FLAGS.flagsaver_test_flag0 = 'changed0'
518
519
520@parameterized.named_parameters(
521    dict(
522        testcase_name='flagsaver.flagsaver',
523        flagsaver_method=flagsaver.flagsaver,
524    ),
525    dict(
526        testcase_name='flagsaver.as_parsed',
527        flagsaver_method=flagsaver.as_parsed,
528    ),
529)
530class BadUsageTest(parameterized.TestCase):
531  """Tests that improper usage (such as decorating a class) raise errors."""
532
533  def test_flag_saver_on_class(self, flagsaver_method):
534    with self.assertRaises(TypeError):
535
536      # WRONG. Don't do this.
537      # Consider the correct usage example in FlagSaverSetUpTearDownUsageTest.
538      @flagsaver_method
539      class FooTest(absltest.TestCase):
540
541        def test_tautology(self):
542          pass
543
544      del FooTest
545
546  def test_flag_saver_call_on_class(self, flagsaver_method):
547    with self.assertRaises(TypeError):
548
549      # WRONG. Don't do this.
550      # Consider the correct usage example in FlagSaverSetUpTearDownUsageTest.
551      @flagsaver_method()
552      class FooTest(absltest.TestCase):
553
554        def test_tautology(self):
555          pass
556
557      del FooTest
558
559  def test_flag_saver_with_overrides_on_class(self, flagsaver_method):
560    with self.assertRaises(TypeError):
561
562      # WRONG. Don't do this.
563      # Consider the correct usage example in FlagSaverSetUpTearDownUsageTest.
564      @flagsaver_method(foo='bar')
565      class FooTest(absltest.TestCase):
566
567        def test_tautology(self):
568          pass
569
570      del FooTest
571
572  def test_multiple_positional_parameters(self, flagsaver_method):
573    with self.assertRaises(ValueError):
574      func_a = lambda: None
575      func_b = lambda: None
576      flagsaver_method(func_a, func_b)
577
578  def test_both_positional_and_keyword_parameters(self, flagsaver_method):
579    with self.assertRaises(ValueError):
580      func_a = lambda: None
581      flagsaver_method(func_a, flagsaver_test_flag0='new value')
582
583  def test_duplicate_holder_parameters(self, flagsaver_method):
584    with self.assertRaises(ValueError):
585      flagsaver_method((INT_FLAG, 45), (INT_FLAG, 45))
586
587  def test_duplicate_holder_and_kw_parameter(self, flagsaver_method):
588    with self.assertRaises(ValueError):
589      flagsaver_method((INT_FLAG, 45), **{INT_FLAG.name: 45})
590
591  def test_both_positional_and_holder_parameters(self, flagsaver_method):
592    with self.assertRaises(ValueError):
593      func_a = lambda: None
594      flagsaver_method(func_a, (INT_FLAG, 45))
595
596  def test_holder_parameters_wrong_shape(self, flagsaver_method):
597    with self.assertRaises(ValueError):
598      flagsaver_method(INT_FLAG)
599
600  def test_holder_parameters_tuple_too_long(self, flagsaver_method):
601    with self.assertRaises(ValueError):
602      # Even if it is a bool flag, it should be a tuple
603      flagsaver_method((INT_FLAG, 4, 5))
604
605  def test_holder_parameters_tuple_wrong_type(self, flagsaver_method):
606    with self.assertRaises(ValueError):
607      # Even if it is a bool flag, it should be a tuple
608      flagsaver_method((4, INT_FLAG))
609
610  def test_both_wrong_positional_parameters(self, flagsaver_method):
611    with self.assertRaises(ValueError):
612      func_a = lambda: None
613      flagsaver_method(func_a, STR_FLAG, '45')
614
615  def test_context_manager_no_call(self, flagsaver_method):
616    # The exact exception that's raised appears to be system specific.
617    with self.assertRaises((AttributeError, TypeError)):
618      # Wrong. You must call the flagsaver method before using it as a CM.
619      with flagsaver_method:
620        # We don't expect to get here. A type error should happen when
621        # attempting to enter the context manager.
622        pass
623
624
625if __name__ == '__main__':
626  absltest.main()
627