3
# Copyright (c) 2007, Google Inc.
6
# Redistribution and use in source and binary forms, with or without
7
# modification, are permitted provided that the following conditions are
10
# * Redistributions of source code must retain the above copyright
11
# notice, this list of conditions and the following disclaimer.
12
# * Redistributions in binary form must reproduce the above
13
# copyright notice, this list of conditions and the following disclaimer
14
# in the documentation and/or other materials provided with the
16
# * Neither the name of Google Inc. nor the names of its
17
# contributors may be used to endorse or promote products derived from
18
# this software without specific prior written permission.
20
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
"Unittest for gflags.py module"
34
__pychecker__ = "no-local" # for unittest
42
# We use the name 'flags' internally in this test, for historical reasons.
43
# Don't do this yourself! :-) Just do 'import gflags; FLAGS=gflags.FLAGS; etc'
44
import gflags as flags
47
# For historic reasons, we use the name module_foo instead of
48
# test_module_foo, and module_bar instead of test_module_bar.
49
import test_module_foo as module_foo
50
import test_module_bar as module_bar
51
import test_module_baz as module_baz
53
def MultiLineEqual(expected_help, help):
54
"""Returns True if expected_help == help. Otherwise returns False
55
and logs the difference in a human-readable way.
57
if help == expected_help:
60
print "Error: FLAGS.MainModuleHelp() didn't return the expected result."
65
help_lines = help.split('\n')
66
expected_help_lines = expected_help.split('\n')
68
num_help_lines = len(help_lines)
69
num_expected_help_lines = len(expected_help_lines)
71
if num_help_lines != num_expected_help_lines:
72
print "Number of help lines = %d, expected %d" % (
73
num_help_lines, num_expected_help_lines)
75
num_to_match = min(num_help_lines, num_expected_help_lines)
77
for i in range(num_to_match):
78
if help_lines[i] != expected_help_lines[i]:
79
print "One discrepancy: Got:"
82
print expected_help_lines[i]
85
# If we got here, found no discrepancy, print first new line.
86
if num_help_lines > num_expected_help_lines:
87
print "New help line:"
88
print help_lines[num_expected_help_lines]
89
elif num_expected_help_lines > num_help_lines:
90
print "Missing expected help line:"
91
print expected_help_lines[num_help_lines]
93
print "Bug in this test -- discrepancy detected but not found."
98
class FlagsUnitTest(unittest.TestCase):
102
# make sure we are using the old, stupid way of parsing flags.
103
FLAGS.UseGnuGetOpt(False)
105
def assertListEqual(self, list1, list2):
106
"""Asserts that, when sorted, list1 and list2 are identical."""
107
sorted_list1 = list1[:]
108
sorted_list2 = list2[:]
111
self.assertEqual(sorted_list1, sorted_list2)
113
def assertMultiLineEqual(self, expected, actual):
114
self.assert_(MultiLineEqual(expected, actual))
117
def test_flags(self):
119
##############################################
120
# Test normal usage with no (expected) errors.
123
number_test_framework_flags = len(FLAGS.RegisteredFlags())
124
repeatHelp = "how many times to repeat (0-5)"
125
flags.DEFINE_integer("repeat", 4, repeatHelp,
126
lower_bound=0, short_name='r')
127
flags.DEFINE_string("name", "Bob", "namehelp")
128
flags.DEFINE_boolean("debug", 0, "debughelp")
129
flags.DEFINE_boolean("q", 1, "quiet mode")
130
flags.DEFINE_boolean("quack", 0, "superstring of 'q'")
131
flags.DEFINE_boolean("noexec", 1, "boolean flag with no as prefix")
132
flags.DEFINE_integer("x", 3, "how eXtreme to be")
133
flags.DEFINE_integer("l", 0x7fffffff00000000L, "how long to be")
134
flags.DEFINE_list('letters', 'a,b,c', "a list of letters")
135
flags.DEFINE_list('numbers', [1, 2, 3], "a list of numbers")
136
flags.DEFINE_enum("kwery", None, ['who', 'what', 'why', 'where', 'when'],
139
# Specify number of flags defined above. The short_name defined
140
# for 'repeat' counts as an extra flag.
141
number_defined_flags = 11 + 1
142
self.assertEqual(len(FLAGS.RegisteredFlags()),
143
number_defined_flags + number_test_framework_flags)
145
assert FLAGS.repeat == 4, "integer default values not set:" + FLAGS.repeat
146
assert FLAGS.name == 'Bob', "default values not set:" + FLAGS.name
147
assert FLAGS.debug == 0, "boolean default values not set:" + FLAGS.debug
148
assert FLAGS.q == 1, "boolean default values not set:" + FLAGS.q
149
assert FLAGS.x == 3, "integer default values not set:" + FLAGS.x
150
assert FLAGS.l == 0x7fffffff00000000L, ("integer default values not set:"
152
assert FLAGS.letters == ['a', 'b', 'c'], ("list default values not set:"
154
assert FLAGS.numbers == [1, 2, 3], ("list default values not set:"
156
assert FLAGS.kwery is None, ("enum default None value not set:"
159
flag_values = FLAGS.FlagValuesDict()
160
assert flag_values['repeat'] == 4
161
assert flag_values['name'] == 'Bob'
162
assert flag_values['debug'] == 0
163
assert flag_values['r'] == 4 # short for of repeat
164
assert flag_values['q'] == 1
165
assert flag_values['quack'] == 0
166
assert flag_values['x'] == 3
167
assert flag_values['l'] == 0x7fffffff00000000L
168
assert flag_values['letters'] == ['a', 'b', 'c']
169
assert flag_values['numbers'] == [1, 2, 3]
170
assert flag_values['kwery'] is None
172
# Verify string form of defaults
173
assert FLAGS['repeat'].default_as_str == "'4'"
174
assert FLAGS['name'].default_as_str == "'Bob'"
175
assert FLAGS['debug'].default_as_str == "'false'"
176
assert FLAGS['q'].default_as_str == "'true'"
177
assert FLAGS['quack'].default_as_str == "'false'"
178
assert FLAGS['noexec'].default_as_str == "'true'"
179
assert FLAGS['x'].default_as_str == "'3'"
180
assert FLAGS['l'].default_as_str == "'9223372032559808512'"
181
assert FLAGS['letters'].default_as_str == "'a,b,c'"
182
assert FLAGS['numbers'].default_as_str == "'1,2,3'"
184
# Verify that the iterator for flags yields all the keys
187
reg_flags = FLAGS.RegisteredFlags()
189
self.assertEqual(keys, reg_flags)
192
# .. empty command line
193
argv = ('./program',)
195
assert len(argv) == 1, "wrong number of arguments pulled"
196
assert argv[0]=='./program', "program name not preserved"
198
# .. non-empty command line
199
argv = ('./program', '--debug', '--name=Bob', '-q', '--x=8')
201
assert len(argv) == 1, "wrong number of arguments pulled"
202
assert argv[0]=='./program', "program name not preserved"
203
assert FLAGS['debug'].present == 1
204
FLAGS['debug'].present = 0 # Reset
205
assert FLAGS['name'].present == 1
206
FLAGS['name'].present = 0 # Reset
207
assert FLAGS['q'].present == 1
208
FLAGS['q'].present = 0 # Reset
209
assert FLAGS['x'].present == 1
210
FLAGS['x'].present = 0 # Reset
213
self.assertEqual(len(FLAGS.RegisteredFlags()),
214
number_defined_flags + number_test_framework_flags)
215
assert 'name' in FLAGS.RegisteredFlags()
216
assert 'debug' in FLAGS.RegisteredFlags()
217
assert 'repeat' in FLAGS.RegisteredFlags()
218
assert 'r' in FLAGS.RegisteredFlags()
219
assert 'q' in FLAGS.RegisteredFlags()
220
assert 'quack' in FLAGS.RegisteredFlags()
221
assert 'x' in FLAGS.RegisteredFlags()
222
assert 'l' in FLAGS.RegisteredFlags()
223
assert 'letters' in FLAGS.RegisteredFlags()
224
assert 'numbers' in FLAGS.RegisteredFlags()
227
assert FLAGS.has_key('name')
228
assert not FLAGS.has_key('name2')
229
assert 'name' in FLAGS
230
assert 'name2' not in FLAGS
232
# try deleting a flag
234
self.assertEqual(len(FLAGS.RegisteredFlags()),
235
number_defined_flags - 1 + number_test_framework_flags)
236
assert not 'r' in FLAGS.RegisteredFlags()
238
# .. command line with extra stuff
239
argv = ('./program', '--debug', '--name=Bob', 'extra')
241
assert len(argv) == 2, "wrong number of arguments pulled"
242
assert argv[0]=='./program', "program name not preserved"
243
assert argv[1]=='extra', "extra argument not preserved"
244
assert FLAGS['debug'].present == 1
245
FLAGS['debug'].present = 0 # Reset
246
assert FLAGS['name'].present == 1
247
FLAGS['name'].present = 0 # Reset
250
argv = ('./program', '--debug')
252
assert len(argv) == 1, "wrong number of arguments pulled"
253
assert argv[0] == './program', "program name not preserved"
254
assert FLAGS['debug'].present == 1
255
assert FLAGS['debug'].value
257
assert FLAGS['debug'].present == 0
258
assert not FLAGS['debug'].value
260
# Test that reset restores default value when default value is None.
261
argv = ('./program', '--kwery=who')
263
assert len(argv) == 1, "wrong number of arguments pulled"
264
assert argv[0] == './program', "program name not preserved"
265
assert FLAGS['kwery'].present == 1
266
assert FLAGS['kwery'].value == 'who'
268
assert FLAGS['kwery'].present == 0
269
assert FLAGS['kwery'].value == None
271
# Test integer argument passing
272
argv = ('./program', '--x', '0x12345')
274
self.assertEquals(FLAGS.x, 0x12345)
275
self.assertEquals(type(FLAGS.x), int)
277
argv = ('./program', '--x', '0x1234567890ABCDEF1234567890ABCDEF')
279
self.assertEquals(FLAGS.x, 0x1234567890ABCDEF1234567890ABCDEF)
280
self.assertEquals(type(FLAGS.x), long)
282
# Treat 0-prefixed parameters as base-10, not base-8
283
argv = ('./program', '--x', '012345')
285
self.assertEquals(FLAGS.x, 12345)
286
self.assertEquals(type(FLAGS.x), int)
288
argv = ('./program', '--x', '0123459')
290
self.assertEquals(FLAGS.x, 123459)
291
self.assertEquals(type(FLAGS.x), int)
293
argv = ('./program', '--x', '0x123efg')
296
raise AssertionError("failed to detect invalid hex argument")
297
except flags.IllegalFlagValue:
300
argv = ('./program', '--x', '0X123efg')
303
raise AssertionError("failed to detect invalid hex argument")
304
except flags.IllegalFlagValue:
307
# Test boolean argument parsing
308
flags.DEFINE_boolean("test0", None, "test boolean parsing")
309
argv = ('./program', '--notest0')
311
assert FLAGS.test0 == 0
313
flags.DEFINE_boolean("test1", None, "test boolean parsing")
314
argv = ('./program', '--test1')
316
assert FLAGS.test1 == 1
319
argv = ('./program', '--test0=false')
321
assert FLAGS.test0 == 0
324
argv = ('./program', '--test1=true')
326
assert FLAGS.test1 == 1
329
argv = ('./program', '--test0=0')
331
assert FLAGS.test0 == 0
334
argv = ('./program', '--test1=1')
336
assert FLAGS.test1 == 1
338
# Test booleans that already have 'no' as a prefix
340
argv = ('./program', '--nonoexec', '--name', 'Bob')
342
assert FLAGS.noexec == 0
345
argv = ('./program', '--name', 'Bob', '--noexec')
347
assert FLAGS.noexec == 1
349
# Test unassigned booleans
350
flags.DEFINE_boolean("testnone", None, "test boolean parsing")
351
argv = ('./program',)
353
assert FLAGS.testnone == None
355
# Test get with default
356
flags.DEFINE_boolean("testget1", None, "test parsing with defaults")
357
flags.DEFINE_boolean("testget2", None, "test parsing with defaults")
358
flags.DEFINE_boolean("testget3", None, "test parsing with defaults")
359
flags.DEFINE_integer("testget4", None, "test parsing with defaults")
360
argv = ('./program','--testget1','--notestget2')
362
assert FLAGS.get('testget1', 'foo') == 1
363
assert FLAGS.get('testget2', 'foo') == 0
364
assert FLAGS.get('testget3', 'foo') == 'foo'
365
assert FLAGS.get('testget4', 'foo') == 'foo'
368
lists = [['hello','moo','boo','1'],
371
flags.DEFINE_list('testlist', '', 'test lists parsing')
372
flags.DEFINE_spaceseplist('testspacelist', '', 'tests space lists parsing')
374
for name, sep in (('testlist', ','), ('testspacelist', ' '),
375
('testspacelist', '\n')):
377
argv = ('./program', '--%s=%s' % (name, sep.join(lst)))
379
self.assertEquals(getattr(FLAGS, name), lst)
382
flagsHelp = str(FLAGS)
383
assert flagsHelp.find("repeat") != -1, "cannot find flag in help"
384
assert flagsHelp.find(repeatHelp) != -1, "cannot find help string in help"
386
# Test flag specified twice
387
argv = ('./program', '--repeat=4', '--repeat=2', '--debug', '--nodebug')
389
self.assertEqual(FLAGS.get('repeat', None), 2)
390
self.assertEqual(FLAGS.get('debug', None), 0)
392
# Test MultiFlag with single default value
393
flags.DEFINE_multistring('s_str', 'sing1',
394
'string option that can occur multiple times',
396
self.assertEqual(FLAGS.get('s_str', None), [ 'sing1', ])
398
# Test MultiFlag with list of default values
399
multi_string_defs = [ 'def1', 'def2', ]
400
flags.DEFINE_multistring('m_str', multi_string_defs,
401
'string option that can occur multiple times',
403
self.assertEqual(FLAGS.get('m_str', None), multi_string_defs)
405
# Test flag specified multiple times with a MultiFlag
406
argv = ('./program', '--m_str=str1', '-m', 'str2')
408
self.assertEqual(FLAGS.get('m_str', None), [ 'str1', 'str2', ])
410
# Test single-letter flags; should support both single and double dash
411
argv = ('./program', '-q', '-x8')
413
self.assertEqual(FLAGS.get('q', None), 1)
414
self.assertEqual(FLAGS.get('x', None), 8)
416
argv = ('./program', '--q', '--x', '9', '--noqu')
418
self.assertEqual(FLAGS.get('q', None), 1)
419
self.assertEqual(FLAGS.get('x', None), 9)
420
# --noqu should match '--noquack since it's a unique prefix
421
self.assertEqual(FLAGS.get('quack', None), 0)
423
argv = ('./program', '--noq', '--x=10', '--qu')
425
self.assertEqual(FLAGS.get('q', None), 0)
426
self.assertEqual(FLAGS.get('x', None), 10)
427
self.assertEqual(FLAGS.get('quack', None), 1)
429
####################################
430
# Test flag serialization code:
432
oldtestlist = FLAGS.testlist
433
oldtestspacelist = FLAGS.testspacelist
436
FLAGS['test0'].Serialize(),
437
FLAGS['test1'].Serialize(),
438
FLAGS['testnone'].Serialize(),
439
FLAGS['s_str'].Serialize())
441
self.assertEqual(FLAGS['test0'].Serialize(), '--notest0')
442
self.assertEqual(FLAGS['test1'].Serialize(), '--test1')
443
self.assertEqual(FLAGS['testnone'].Serialize(), '')
444
self.assertEqual(FLAGS['s_str'].Serialize(), '--s_str=sing1')
446
testlist1 = ['aa', 'bb']
447
testspacelist1 = ['aa', 'bb', 'cc']
448
FLAGS.testlist = list(testlist1)
449
FLAGS.testspacelist = list(testspacelist1)
451
FLAGS['testlist'].Serialize(),
452
FLAGS['testspacelist'].Serialize())
454
self.assertEqual(FLAGS.testlist, testlist1)
455
self.assertEqual(FLAGS.testspacelist, testspacelist1)
457
testlist1 = ['aa some spaces', 'bb']
458
testspacelist1 = ['aa', 'bb,some,commas,', 'cc']
459
FLAGS.testlist = list(testlist1)
460
FLAGS.testspacelist = list(testspacelist1)
462
FLAGS['testlist'].Serialize(),
463
FLAGS['testspacelist'].Serialize())
465
self.assertEqual(FLAGS.testlist, testlist1)
466
self.assertEqual(FLAGS.testspacelist, testspacelist1)
468
FLAGS.testlist = oldtestlist
469
FLAGS.testspacelist = oldtestspacelist
471
####################################
475
flagnames = FLAGS.RegisteredFlags()
478
nonbool_flags = ['--%s %s' % (name, FLAGS.get(name, None))
479
for name in flagnames
480
if not isinstance(FLAGS[name], flags.BooleanFlag)]
482
truebool_flags = ['--%s' % (name)
483
for name in flagnames
484
if isinstance(FLAGS[name], flags.BooleanFlag) and
485
FLAGS.get(name, None)]
486
falsebool_flags = ['--no%s' % (name)
487
for name in flagnames
488
if isinstance(FLAGS[name], flags.BooleanFlag) and
489
not FLAGS.get(name, None)]
490
return ' '.join(nonbool_flags + truebool_flags + falsebool_flags)
492
argv = ('./program', '--repeat=3', '--name=giants', '--nodebug')
495
self.assertEqual(FLAGS.get('repeat', None), 3)
496
self.assertEqual(FLAGS.get('name', None), 'giants')
497
self.assertEqual(FLAGS.get('debug', None), 0)
498
self.assertEqual(ArgsString(),
500
"--l 9223372032559808512 "
501
"--letters ['a', 'b', 'c'] "
502
"--m ['str1', 'str2'] --m_str ['str1', 'str2'] "
504
"--numbers [1, 2, 3] "
506
"--s ['sing1'] --s_str ['sing1'] "
507
"--testget4 None --testlist [] "
508
"--testspacelist [] --x 10 "
511
"--testget1 --tmod_baz_x --no? --nodebug --nohelp --nohelpshort --nohelpxml "
512
"--noq --notest0 --notestget2 "
513
"--notestget3 --notestnone")
515
argv = ('./program', '--debug', '--m_str=upd1', '-s', 'upd2')
517
self.assertEqual(FLAGS.get('repeat', None), 3)
518
self.assertEqual(FLAGS.get('name', None), 'giants')
519
self.assertEqual(FLAGS.get('debug', None), 1)
521
# items appended to existing non-default value lists for --m/--m_str
522
# new value overwrites default value (not appended to it) for --s/--s_str
523
self.assertEqual(ArgsString(),
525
"--l 9223372032559808512 "
526
"--letters ['a', 'b', 'c'] "
527
"--m ['str1', 'str2', 'upd1'] "
528
"--m_str ['str1', 'str2', 'upd1'] "
530
"--numbers [1, 2, 3] "
532
"--s ['upd2'] --s_str ['upd2'] "
533
"--testget4 None --testlist [] "
534
"--testspacelist [] --x 10 "
535
"--debug --noexec --quack "
537
"--testget1 --tmod_baz_x --no? --nohelp --nohelpshort --nohelpxml "
538
"--noq --notest0 --notestget2 "
539
"--notestget3 --notestnone")
542
####################################
543
# Test all kind of error conditions.
545
# Duplicate flag detection
547
flags.DEFINE_boolean("run", 0, "runhelp", short_name='q')
548
raise AssertionError("duplicate flag detection failed")
549
except flags.DuplicateFlag, e:
552
# Duplicate short flag detection
554
flags.DEFINE_boolean("zoom1", 0, "runhelp z1", short_name='z')
555
flags.DEFINE_boolean("zoom2", 0, "runhelp z2", short_name='z')
556
raise AssertionError("duplicate short flag detection failed")
557
except flags.DuplicateFlag, e:
558
self.assertTrue("The flag 'z' is defined twice. " in e.args[0])
559
self.assertTrue("First from" in e.args[0])
560
self.assertTrue(", Second from" in e.args[0])
562
# Duplicate mixed flag detection
564
flags.DEFINE_boolean("short1", 0, "runhelp s1", short_name='s')
565
flags.DEFINE_boolean("s", 0, "runhelp s2")
566
raise AssertionError("duplicate mixed flag detection failed")
567
except flags.DuplicateFlag, e:
568
self.assertTrue("The flag 's' is defined twice. " in e.args[0])
569
self.assertTrue("First from" in e.args[0])
570
self.assertTrue(", Second from" in e.args[0])
572
# Make sure allow_override works
574
flags.DEFINE_boolean("dup1", 0, "runhelp d11", short_name='u',
576
flag = FLAGS.FlagDict()['dup1']
577
self.assertEqual(flag.default, 0)
579
flags.DEFINE_boolean("dup1", 1, "runhelp d12", short_name='u',
581
flag = FLAGS.FlagDict()['dup1']
582
self.assertEqual(flag.default, 1)
583
except flags.DuplicateFlag, e:
584
raise AssertionError("allow_override did not permit a flag duplication")
586
# Make sure allow_override works
588
flags.DEFINE_boolean("dup2", 0, "runhelp d21", short_name='u',
590
flag = FLAGS.FlagDict()['dup2']
591
self.assertEqual(flag.default, 0)
593
flags.DEFINE_boolean("dup2", 1, "runhelp d22", short_name='u',
595
flag = FLAGS.FlagDict()['dup2']
596
self.assertEqual(flag.default, 1)
597
except flags.DuplicateFlag, e:
598
raise AssertionError("allow_override did not permit a flag duplication")
600
# Make sure allow_override doesn't work with None default
602
flags.DEFINE_boolean("dup3", 0, "runhelp d31", short_name='u',
604
flag = FLAGS.FlagDict()['dup3']
605
self.assertEqual(flag.default, 0)
607
flags.DEFINE_boolean("dup3", None, "runhelp d32", short_name='u',
609
raise AssertionError('Cannot override a flag with a default of None')
610
except flags.DuplicateFlag, e:
613
# Make sure that when we override, the help string gets updated correctly
614
flags.DEFINE_boolean("dup3", 0, "runhelp d31", short_name='u',
616
flags.DEFINE_boolean("dup3", 1, "runhelp d32", short_name='u',
618
self.assert_(str(FLAGS).find('runhelp d31') == -1)
619
self.assert_(str(FLAGS).find('runhelp d32') != -1)
621
# Make sure AppendFlagValues works
622
new_flags = flags.FlagValues()
623
flags.DEFINE_boolean("new1", 0, "runhelp n1", flag_values=new_flags)
624
flags.DEFINE_boolean("new2", 0, "runhelp n2", flag_values=new_flags)
625
self.assertEqual(len(new_flags.FlagDict()), 2)
626
old_len = len(FLAGS.FlagDict())
627
FLAGS.AppendFlagValues(new_flags)
628
self.assertEqual(len(FLAGS.FlagDict())-old_len, 2)
629
self.assertEqual("new1" in FLAGS.FlagDict(), True)
630
self.assertEqual("new2" in FLAGS.FlagDict(), True)
632
# Make sure AppendFlagValues works with flags with shortnames.
633
new_flags = flags.FlagValues()
634
flags.DEFINE_boolean("new3", 0, "runhelp n3", flag_values=new_flags)
635
flags.DEFINE_boolean("new4", 0, "runhelp n4", flag_values=new_flags,
637
self.assertEqual(len(new_flags.FlagDict()), 3)
638
old_len = len(FLAGS.FlagDict())
639
FLAGS.AppendFlagValues(new_flags)
640
self.assertEqual(len(FLAGS.FlagDict())-old_len, 3)
641
self.assertTrue("new3" in FLAGS.FlagDict())
642
self.assertTrue("new4" in FLAGS.FlagDict())
643
self.assertTrue("n4" in FLAGS.FlagDict())
644
self.assertEqual(FLAGS.FlagDict()['n4'], FLAGS.FlagDict()['new4'])
646
# Make sure AppendFlagValues fails on duplicates
647
flags.DEFINE_boolean("dup4", 0, "runhelp d41")
648
new_flags = flags.FlagValues()
649
flags.DEFINE_boolean("dup4", 0, "runhelp d42", flag_values=new_flags)
651
FLAGS.AppendFlagValues(new_flags)
652
raise AssertionError("ignore_copy was not set but caused no exception")
653
except flags.DuplicateFlag, e:
656
# Integer out of bounds
658
argv = ('./program', '--repeat=-4')
660
raise AssertionError('integer bounds exception not raised:'
662
except flags.IllegalFlagValue:
667
argv = ('./program', '--repeat=2.5')
669
raise AssertionError("malformed integer value exception not raised")
670
except flags.IllegalFlagValue:
673
# Missing required arugment
675
argv = ('./program', '--name')
677
raise AssertionError("Flag argument required exception not raised")
678
except flags.FlagsError:
681
# Non-boolean arguments for boolean
683
argv = ('./program', '--debug=goofup')
685
raise AssertionError("Illegal flag value exception not raised")
686
except flags.IllegalFlagValue:
690
argv = ('./program', '--debug=42')
692
raise AssertionError("Illegal flag value exception not raised")
693
except flags.IllegalFlagValue:
697
# Non-numeric argument for integer flag --repeat
699
argv = ('./program', '--repeat', 'Bob', 'extra')
701
raise AssertionError("Illegal flag value exception not raised")
702
except flags.IllegalFlagValue:
705
################################################
706
# Code to test the flagfile=<> loading behavior
707
################################################
708
def _SetupTestFiles(self):
709
""" Creates and sets up some dummy flagfile files with bogus flags"""
711
# Figure out where to create temporary files
712
tmp_path = '/tmp/flags_unittest'
713
if os.path.exists(tmp_path):
714
shutil.rmtree(tmp_path)
715
os.makedirs(tmp_path)
718
tmp_flag_file_1 = open((tmp_path + '/UnitTestFile1.tst'), 'w')
719
tmp_flag_file_2 = open((tmp_path + '/UnitTestFile2.tst'), 'w')
720
tmp_flag_file_3 = open((tmp_path + '/UnitTestFile3.tst'), 'w')
721
except IOError, e_msg:
723
print 'FAIL\n File Creation problem in Unit Test'
726
# put some dummy flags in our test files
727
tmp_flag_file_1.write('#A Fake Comment\n')
728
tmp_flag_file_1.write('--UnitTestMessage1=tempFile1!\n')
729
tmp_flag_file_1.write('\n')
730
tmp_flag_file_1.write('--UnitTestNumber=54321\n')
731
tmp_flag_file_1.write('--noUnitTestBoolFlag\n')
732
file_list = [tmp_flag_file_1.name]
733
# this one includes test file 1
734
tmp_flag_file_2.write('//A Different Fake Comment\n')
735
tmp_flag_file_2.write('--flagfile=%s\n' % tmp_flag_file_1.name)
736
tmp_flag_file_2.write('--UnitTestMessage2=setFromTempFile2\n')
737
tmp_flag_file_2.write('\t\t\n')
738
tmp_flag_file_2.write('--UnitTestNumber=6789a\n')
739
file_list.append(tmp_flag_file_2.name)
740
# this file points to itself
741
tmp_flag_file_3.write('--flagfile=%s\n' % tmp_flag_file_3.name)
742
tmp_flag_file_3.write('--UnitTestMessage1=setFromTempFile3\n')
743
tmp_flag_file_3.write('#YAFC\n')
744
tmp_flag_file_3.write('--UnitTestBoolFlag\n')
745
file_list.append(tmp_flag_file_3.name)
747
tmp_flag_file_1.close()
748
tmp_flag_file_2.close()
749
tmp_flag_file_3.close()
751
return file_list # these are just the file names
754
def _RemoveTestFiles(self, tmp_file_list):
755
"""Closes the files we just created. tempfile deletes them for us """
756
for file_name in tmp_file_list:
759
except OSError, e_msg:
760
print '%s\n, Problem deleting test file' % e_msg
761
#end RemoveTestFiles def
763
def __DeclareSomeFlags(self):
764
flags.DEFINE_string('UnitTestMessage1', 'Foo!', 'You Add Here.')
765
flags.DEFINE_string('UnitTestMessage2', 'Bar!', 'Hello, Sailor!')
766
flags.DEFINE_boolean('UnitTestBoolFlag', 0, 'Some Boolean thing')
767
flags.DEFINE_integer('UnitTestNumber', 12345, 'Some integer',
769
flags.DEFINE_list('UnitTestList', "1,2,3", 'Some list')
771
def _UndeclareSomeFlags(self):
772
FLAGS.__delattr__('UnitTestMessage1')
773
FLAGS.__delattr__('UnitTestMessage2')
774
FLAGS.__delattr__('UnitTestBoolFlag')
775
FLAGS.__delattr__('UnitTestNumber')
776
FLAGS.__delattr__('UnitTestList')
778
def _ReadFlagsFromFiles(self, argv, force_gnu):
779
return argv[:1] + FLAGS.ReadFlagsFromFiles(argv[1:], force_gnu=force_gnu)
781
#### Flagfile Unit Tests ####
782
def testMethod_flagfiles_1(self):
783
""" Test trivial case with no flagfile based options. """
784
self.__DeclareSomeFlags()
786
fake_cmd_line = 'fooScript --UnitTestBoolFlag'
787
fake_argv = fake_cmd_line.split(' ')
789
self.assertEqual( FLAGS.UnitTestBoolFlag, 1)
790
self.assertEqual( fake_argv, self._ReadFlagsFromFiles(fake_argv, False))
792
self._UndeclareSomeFlags()
795
def testMethod_flagfiles_2(self):
796
"""Tests parsing one file + arguments off simulated argv"""
797
self.__DeclareSomeFlags()
799
tmp_files = self._SetupTestFiles()
800
# specify our temp file on the fake cmd line
801
fake_cmd_line = 'fooScript --q --flagfile=%s' % tmp_files[0]
802
fake_argv = fake_cmd_line.split(' ')
804
# We should see the original cmd line with the file's contents spliced in.
805
# Note that these will be in REVERSE order from order encountered in file
806
# This is done so arguements we encounter sooner will have priority.
807
expected_results = ['fooScript',
808
'--UnitTestMessage1=tempFile1!',
809
'--UnitTestNumber=54321',
810
'--noUnitTestBoolFlag',
812
test_results = self._ReadFlagsFromFiles(fake_argv, False)
813
self.assertEqual(expected_results, test_results)
815
self._RemoveTestFiles(tmp_files)
816
self._UndeclareSomeFlags()
819
def testMethod_flagfiles_3(self):
820
"""Tests parsing nested files + arguments of simulated argv"""
821
self.__DeclareSomeFlags()
823
tmp_files = self._SetupTestFiles()
824
# specify our temp file on the fake cmd line
825
fake_cmd_line = ('fooScript --UnitTestNumber=77 --flagfile=%s'
827
fake_argv = fake_cmd_line.split(' ')
829
expected_results = ['fooScript',
830
'--UnitTestMessage1=tempFile1!',
831
'--UnitTestNumber=54321',
832
'--noUnitTestBoolFlag',
833
'--UnitTestMessage2=setFromTempFile2',
834
'--UnitTestNumber=6789a',
835
'--UnitTestNumber=77']
836
test_results = self._ReadFlagsFromFiles(fake_argv, False)
837
self.assertEqual(expected_results, test_results)
839
self._RemoveTestFiles(tmp_files)
840
self._UndeclareSomeFlags()
843
def testMethod_flagfiles_4(self):
844
"""Tests parsing self-referential files + arguments of simulated argv.
845
This test should print a warning to stderr of some sort.
847
self.__DeclareSomeFlags()
849
tmp_files = self._SetupTestFiles()
850
# specify our temp file on the fake cmd line
851
fake_cmd_line = ('fooScript --flagfile=%s --noUnitTestBoolFlag'
853
fake_argv = fake_cmd_line.split(' ')
854
expected_results = ['fooScript',
855
'--UnitTestMessage1=setFromTempFile3',
856
'--UnitTestBoolFlag',
857
'--noUnitTestBoolFlag' ]
859
test_results = self._ReadFlagsFromFiles(fake_argv, False)
860
self.assertEqual(expected_results, test_results)
862
self._RemoveTestFiles(tmp_files)
863
self._UndeclareSomeFlags()
865
def testMethod_flagfiles_5(self):
866
"""Test that --flagfile parsing respects the '--' end-of-options marker."""
867
self.__DeclareSomeFlags()
869
tmp_files = self._SetupTestFiles()
870
# specify our temp file on the fake cmd line
871
fake_cmd_line = 'fooScript --SomeFlag -- --flagfile=%s' % tmp_files[0]
872
fake_argv = fake_cmd_line.split(' ')
873
expected_results = ['fooScript',
876
'--flagfile=%s' % tmp_files[0]]
878
test_results = self._ReadFlagsFromFiles(fake_argv, False)
879
self.assertEqual(expected_results, test_results)
881
self._RemoveTestFiles(tmp_files)
882
self._UndeclareSomeFlags()
884
def testMethod_flagfiles_6(self):
885
"""Test that --flagfile parsing stops at non-options (non-GNU behavior)."""
886
self.__DeclareSomeFlags()
888
tmp_files = self._SetupTestFiles()
889
# specify our temp file on the fake cmd line
890
fake_cmd_line = ('fooScript --SomeFlag some_arg --flagfile=%s'
892
fake_argv = fake_cmd_line.split(' ')
893
expected_results = ['fooScript',
896
'--flagfile=%s' % tmp_files[0]]
898
test_results = self._ReadFlagsFromFiles(fake_argv, False)
899
self.assertEqual(expected_results, test_results)
901
self._RemoveTestFiles(tmp_files)
902
self._UndeclareSomeFlags()
904
def testMethod_flagfiles_7(self):
905
"""Test that --flagfile parsing skips over a non-option (GNU behavior)."""
906
self.__DeclareSomeFlags()
909
tmp_files = self._SetupTestFiles()
910
# specify our temp file on the fake cmd line
911
fake_cmd_line = ('fooScript --SomeFlag some_arg --flagfile=%s'
913
fake_argv = fake_cmd_line.split(' ')
914
expected_results = ['fooScript',
915
'--UnitTestMessage1=tempFile1!',
916
'--UnitTestNumber=54321',
917
'--noUnitTestBoolFlag',
921
test_results = self._ReadFlagsFromFiles(fake_argv, False)
922
self.assertEqual(expected_results, test_results)
924
self._RemoveTestFiles(tmp_files)
925
self._UndeclareSomeFlags()
927
def testMethod_flagfiles_8(self):
928
"""Test that --flagfile parsing respects force_gnu=True."""
929
self.__DeclareSomeFlags()
931
tmp_files = self._SetupTestFiles()
932
# specify our temp file on the fake cmd line
933
fake_cmd_line = ('fooScript --SomeFlag some_arg --flagfile=%s'
935
fake_argv = fake_cmd_line.split(' ')
936
expected_results = ['fooScript',
937
'--UnitTestMessage1=tempFile1!',
938
'--UnitTestNumber=54321',
939
'--noUnitTestBoolFlag',
943
test_results = self._ReadFlagsFromFiles(fake_argv, True)
944
self.assertEqual(expected_results, test_results)
946
self._RemoveTestFiles(tmp_files)
947
self._UndeclareSomeFlags()
949
def test_flagfiles_user_path_expansion(self):
950
"""Test that user directory referenced paths (ie. ~/foo) are correctly
951
expanded. This test depends on whatever account's running the unit test
952
to have read/write access to their own home directory, otherwise it'll
955
self.__DeclareSomeFlags()
956
fake_flagfile_item_style_1 = '--flagfile=~/foo.file'
957
fake_flagfile_item_style_2 = '-flagfile=~/foo.file'
959
expected_results = os.path.expanduser('~/foo.file')
961
test_results = FLAGS.ExtractFilename(fake_flagfile_item_style_1)
962
self.assertEqual(expected_results, test_results)
964
test_results = FLAGS.ExtractFilename(fake_flagfile_item_style_2)
965
self.assertEqual(expected_results, test_results)
967
self._UndeclareSomeFlags()
971
def test_no_touchy_non_flags(self):
973
Test that the flags parser does not mutilate arguments which are
974
not supposed to be flags
976
self.__DeclareSomeFlags()
977
fake_argv = ['fooScript', '--UnitTestBoolFlag',
978
'command', '--command_arg1', '--UnitTestBoom', '--UnitTestB']
979
argv = FLAGS(fake_argv)
980
self.assertEqual(argv, fake_argv[:1] + fake_argv[2:])
981
self._UndeclareSomeFlags()
983
def test_parse_flags_after_args_if_using_gnu_getopt(self):
985
Test that flags given after arguments are parsed if using gnu_getopt.
987
self.__DeclareSomeFlags()
989
fake_argv = ['fooScript', '--UnitTestBoolFlag',
990
'command', '--UnitTestB']
991
argv = FLAGS(fake_argv)
992
self.assertEqual(argv, ['fooScript', 'command'])
993
self._UndeclareSomeFlags()
995
def test_SetDefault(self):
997
Test changing flag defaults.
999
self.__DeclareSomeFlags()
1000
# Test that SetDefault changes both the default and the value,
1001
# and that the value is changed when one is given as an option.
1002
FLAGS['UnitTestMessage1'].SetDefault('New value')
1003
self.assertEqual(FLAGS.UnitTestMessage1, 'New value')
1004
self.assertEqual(FLAGS['UnitTestMessage1'].default_as_str,"'New value'")
1005
FLAGS([ 'dummyscript', '--UnitTestMessage1=Newer value' ])
1006
self.assertEqual(FLAGS.UnitTestMessage1, 'Newer value')
1008
# Test that setting the default to None works correctly.
1009
FLAGS['UnitTestNumber'].SetDefault(None)
1010
self.assertEqual(FLAGS.UnitTestNumber, None)
1011
self.assertEqual(FLAGS['UnitTestNumber'].default_as_str, None)
1012
FLAGS([ 'dummyscript', '--UnitTestNumber=56' ])
1013
self.assertEqual(FLAGS.UnitTestNumber, 56)
1015
# Test that setting the default to zero works correctly.
1016
FLAGS['UnitTestNumber'].SetDefault(0)
1017
self.assertEqual(FLAGS.UnitTestNumber, 0)
1018
self.assertEqual(FLAGS['UnitTestNumber'].default_as_str, "'0'")
1019
FLAGS([ 'dummyscript', '--UnitTestNumber=56' ])
1020
self.assertEqual(FLAGS.UnitTestNumber, 56)
1022
# Test that setting the default to "" works correctly.
1023
FLAGS['UnitTestMessage1'].SetDefault("")
1024
self.assertEqual(FLAGS.UnitTestMessage1, "")
1025
self.assertEqual(FLAGS['UnitTestMessage1'].default_as_str, "''")
1026
FLAGS([ 'dummyscript', '--UnitTestMessage1=fifty-six' ])
1027
self.assertEqual(FLAGS.UnitTestMessage1, "fifty-six")
1029
# Test that setting the default to false works correctly.
1030
FLAGS['UnitTestBoolFlag'].SetDefault(False)
1031
self.assertEqual(FLAGS.UnitTestBoolFlag, False)
1032
self.assertEqual(FLAGS['UnitTestBoolFlag'].default_as_str, "'false'")
1033
FLAGS([ 'dummyscript', '--UnitTestBoolFlag=true' ])
1034
self.assertEqual(FLAGS.UnitTestBoolFlag, True)
1036
# Test that setting a list default works correctly.
1037
FLAGS['UnitTestList'].SetDefault('4,5,6')
1038
self.assertEqual(FLAGS.UnitTestList, ['4', '5', '6'])
1039
self.assertEqual(FLAGS['UnitTestList'].default_as_str, "'4,5,6'")
1040
FLAGS([ 'dummyscript', '--UnitTestList=7,8,9' ])
1041
self.assertEqual(FLAGS.UnitTestList, ['7', '8', '9'])
1043
# Test that setting invalid defaults raises exceptions
1044
self.assertRaises(flags.IllegalFlagValue,
1045
FLAGS['UnitTestNumber'].SetDefault, 'oops')
1046
self.assertRaises(flags.IllegalFlagValue,
1047
FLAGS['UnitTestNumber'].SetDefault, -1)
1048
self.assertRaises(flags.IllegalFlagValue,
1049
FLAGS['UnitTestBoolFlag'].SetDefault, 'oops')
1051
self._UndeclareSomeFlags()
1053
def testMethod_ShortestUniquePrefixes(self):
1055
Test FlagValues.ShortestUniquePrefixes
1057
flags.DEFINE_string('a', '', '')
1058
flags.DEFINE_string('abc', '', '')
1059
flags.DEFINE_string('common_a_string', '', '')
1060
flags.DEFINE_boolean('common_b_boolean', 0, '')
1061
flags.DEFINE_boolean('common_c_boolean', 0, '')
1062
flags.DEFINE_boolean('common', 0, '')
1063
flags.DEFINE_integer('commonly', 0, '')
1064
flags.DEFINE_boolean('zz', 0, '')
1065
flags.DEFINE_integer('nozz', 0, '')
1067
shorter_flags = FLAGS.ShortestUniquePrefixes(FLAGS.FlagDict())
1069
expected_results = {'nocommon_b_boolean': 'nocommon_b',
1070
'common_c_boolean': 'common_c',
1071
'common_b_boolean': 'common_b',
1076
'common_a_string': 'common_a',
1077
'commonly': 'commonl',
1078
'nocommon_c_boolean': 'nocommon_c',
1079
'nocommon': 'nocommon',
1082
for name, shorter in expected_results.iteritems():
1083
self.assertEquals(shorter_flags[name], shorter)
1085
FLAGS.__delattr__('a')
1086
FLAGS.__delattr__('abc')
1087
FLAGS.__delattr__('common_a_string')
1088
FLAGS.__delattr__('common_b_boolean')
1089
FLAGS.__delattr__('common_c_boolean')
1090
FLAGS.__delattr__('common')
1091
FLAGS.__delattr__('commonly')
1092
FLAGS.__delattr__('zz')
1093
FLAGS.__delattr__('nozz')
1095
def test_twodasharg_first(self):
1096
flags.DEFINE_string("twodash_name", "Bob", "namehelp")
1097
flags.DEFINE_string("twodash_blame", "Rob", "blamehelp")
1098
argv = ('./program',
1100
'--twodash_name=Harry')
1102
self.assertEqual('Bob', FLAGS.twodash_name)
1103
self.assertEqual(argv[1], '--twodash_name=Harry')
1105
def test_twodasharg_middle(self):
1106
flags.DEFINE_string("twodash2_name", "Bob", "namehelp")
1107
flags.DEFINE_string("twodash2_blame", "Rob", "blamehelp")
1108
argv = ('./program',
1109
'--twodash2_blame=Larry',
1111
'--twodash2_name=Harry')
1113
self.assertEqual('Bob', FLAGS.twodash2_name)
1114
self.assertEqual('Larry', FLAGS.twodash2_blame)
1115
self.assertEqual(argv[1], '--twodash2_name=Harry')
1117
def test_onedasharg_first(self):
1118
flags.DEFINE_string("onedash_name", "Bob", "namehelp")
1119
flags.DEFINE_string("onedash_blame", "Rob", "blamehelp")
1120
argv = ('./program',
1122
'--onedash_name=Harry')
1124
self.assertEqual(argv[1], '-')
1125
# TODO(csilvers): we should still parse --onedash_name=Harry as a
1126
# flag, but currently we don't (we stop flag processing as soon as
1127
# we see the first non-flag).
1128
# - This requires gnu_getopt from Python 2.3+ see FLAGS.UseGnuGetOpt()
1130
def test_unrecognized_flags(self):
1131
# Unknown flag --nosuchflag
1133
argv = ('./program', '--nosuchflag', '--name=Bob', 'extra')
1135
raise AssertionError("Unknown flag exception not raised")
1136
except flags.UnrecognizedFlag, e:
1137
assert e.flagname == 'nosuchflag'
1139
# Unknown flag -w (short option)
1141
argv = ('./program', '-w', '--name=Bob', 'extra')
1143
raise AssertionError("Unknown flag exception not raised")
1144
except flags.UnrecognizedFlag, e:
1145
assert e.flagname == 'w'
1147
# Unknown flag --nosuchflagwithparam=foo
1149
argv = ('./program', '--nosuchflagwithparam=foo', '--name=Bob', 'extra')
1151
raise AssertionError("Unknown flag exception not raised")
1152
except flags.UnrecognizedFlag, e:
1153
assert e.flagname == 'nosuchflagwithparam'
1155
# Allow unknown flag --nosuchflag if specified with undefok
1156
argv = ('./program', '--nosuchflag', '--name=Bob',
1157
'--undefok=nosuchflag', 'extra')
1159
assert len(argv) == 2, "wrong number of arguments pulled"
1160
assert argv[0]=='./program', "program name not preserved"
1161
assert argv[1]=='extra', "extra argument not preserved"
1163
# Allow unknown flag --noboolflag if undefok=boolflag is specified
1164
argv = ('./program', '--noboolflag', '--name=Bob',
1165
'--undefok=boolflag', 'extra')
1167
assert len(argv) == 2, "wrong number of arguments pulled"
1168
assert argv[0]=='./program', "program name not preserved"
1169
assert argv[1]=='extra', "extra argument not preserved"
1171
# But not if the flagname is misspelled:
1173
argv = ('./program', '--nosuchflag', '--name=Bob',
1174
'--undefok=nosuchfla', 'extra')
1176
raise AssertionError("Unknown flag exception not raised")
1177
except flags.UnrecognizedFlag, e:
1178
assert e.flagname == 'nosuchflag'
1181
argv = ('./program', '--nosuchflag', '--name=Bob',
1182
'--undefok=nosuchflagg', 'extra')
1184
raise AssertionError("Unknown flag exception not raised")
1185
except flags.UnrecognizedFlag:
1186
assert e.flagname == 'nosuchflag'
1188
# Allow unknown short flag -w if specified with undefok
1189
argv = ('./program', '-w', '--name=Bob', '--undefok=w', 'extra')
1191
assert len(argv) == 2, "wrong number of arguments pulled"
1192
assert argv[0]=='./program', "program name not preserved"
1193
assert argv[1]=='extra', "extra argument not preserved"
1195
# Allow unknown flag --nosuchflagwithparam=foo if specified
1197
argv = ('./program', '--nosuchflagwithparam=foo', '--name=Bob',
1198
'--undefok=nosuchflagwithparam', 'extra')
1200
assert len(argv) == 2, "wrong number of arguments pulled"
1201
assert argv[0]=='./program', "program name not preserved"
1202
assert argv[1]=='extra', "extra argument not preserved"
1204
# Even if undefok specifies multiple flags
1205
argv = ('./program', '--nosuchflag', '-w', '--nosuchflagwithparam=foo',
1207
'--undefok=nosuchflag,w,nosuchflagwithparam',
1210
assert len(argv) == 2, "wrong number of arguments pulled"
1211
assert argv[0]=='./program', "program name not preserved"
1212
assert argv[1]=='extra', "extra argument not preserved"
1214
# However, not if undefok doesn't specify the flag
1216
argv = ('./program', '--nosuchflag', '--name=Bob',
1217
'--undefok=another_such', 'extra')
1219
raise AssertionError("Unknown flag exception not raised")
1220
except flags.UnrecognizedFlag, e:
1221
assert e.flagname == 'nosuchflag'
1223
# Make sure --undefok doesn't mask other option errors.
1225
# Provide an option requiring a parameter but not giving it one.
1226
argv = ('./program', '--undefok=name', '--name')
1228
raise AssertionError("Missing option parameter exception not raised")
1229
except flags.UnrecognizedFlag:
1230
raise AssertionError("Wrong kind of error exception raised")
1231
except flags.FlagsError:
1234
# Test --undefok <list>
1235
argv = ('./program', '--nosuchflag', '-w', '--nosuchflagwithparam=foo',
1238
'nosuchflag,w,nosuchflagwithparam',
1241
assert len(argv) == 2, "wrong number of arguments pulled"
1242
assert argv[0]=='./program', "program name not preserved"
1243
assert argv[1]=='extra', "extra argument not preserved"
1245
def test_nonglobal_flags(self):
1246
"""Test use of non-global FlagValues"""
1247
nonglobal_flags = flags.FlagValues()
1248
flags.DEFINE_string("nonglobal_flag", "Bob", "flaghelp", nonglobal_flags)
1249
argv = ('./program',
1250
'--nonglobal_flag=Mary',
1252
argv = nonglobal_flags(argv)
1253
assert len(argv) == 2, "wrong number of arguments pulled"
1254
assert argv[0]=='./program', "program name not preserved"
1255
assert argv[1]=='extra', "extra argument not preserved"
1256
assert nonglobal_flags['nonglobal_flag'].value == 'Mary'
1258
def test_unrecognized_nonglobal_flags(self):
1259
"""Test unrecognized non-global flags"""
1260
nonglobal_flags = flags.FlagValues()
1261
argv = ('./program',
1264
argv = nonglobal_flags(argv)
1265
raise AssertionError("Unknown flag exception not raised")
1266
except flags.UnrecognizedFlag, e:
1267
assert e.flagname == 'nosuchflag'
1270
argv = ('./program',
1272
'--undefok=nosuchflag')
1274
argv = nonglobal_flags(argv)
1275
assert len(argv) == 1, "wrong number of arguments pulled"
1276
assert argv[0]=='./program', "program name not preserved"
1278
def test_module_help(self):
1279
"""Test ModuleHelp()."""
1280
helpstr = FLAGS.ModuleHelp(module_baz)
1282
expected_help = "\n" + module_baz.__name__ + ":" + """
1283
--[no]tmod_baz_x: Boolean flag.
1284
(default: 'true')"""
1286
self.assertMultiLineEqual(expected_help, helpstr)
1288
def test_main_module_help(self):
1289
"""Test MainModuleHelp()."""
1290
helpstr = FLAGS.MainModuleHelp()
1292
# When this test is invoked on behalf of flags_unittest_2_2,
1293
# the main module has not defined any flags. Since there's
1294
# no easy way to run this script in our test environment
1295
# directly from python2.2, don't bother to test the output
1296
# of MainModuleHelp() in that scenario.
1297
if sys.version.startswith('2.2.'):
1300
expected_help = "\n" + sys.argv[0] + ':' + """
1301
--[no]debug: debughelp
1303
-u,--[no]dup1: runhelp d12
1305
-u,--[no]dup2: runhelp d22
1307
-u,--[no]dup3: runhelp d32
1309
--[no]dup4: runhelp d41
1311
-?,--[no]help: show this help
1312
--[no]helpshort: show usage only for this module
1313
--[no]helpxml: like --help, but generates XML output
1314
--kwery: <who|what|why|where|when>: ?
1316
(default: '9223372032559808512')
1318
--letters: a list of letters
1320
(a comma separated list)
1321
-m,--m_str: string option that can occur multiple times;
1322
repeat this option to specify a list of values
1323
(default: "['def1', 'def2']")
1326
--[no]noexec: boolean flag with no as prefix
1328
--numbers: a list of numbers
1330
(a comma separated list)
1333
--[no]quack: superstring of 'q'
1335
-r,--repeat: how many times to repeat (0-5)
1337
(a non-negative integer)
1338
-s,--s_str: string option that can occur multiple times;
1339
repeat this option to specify a list of values
1340
(default: "['sing1']")
1341
--[no]test0: test boolean parsing
1342
--[no]test1: test boolean parsing
1343
--[no]testget1: test parsing with defaults
1344
--[no]testget2: test parsing with defaults
1345
--[no]testget3: test parsing with defaults
1346
--testget4: test parsing with defaults
1348
--testlist: test lists parsing
1350
(a comma separated list)
1351
--[no]testnone: test boolean parsing
1352
--testspacelist: tests space lists parsing
1354
(a whitespace separated list)
1355
--x: how eXtreme to be
1358
-z,--[no]zoom1: runhelp z1
1359
(default: 'false')"""
1361
if not MultiLineEqual(expected_help, helpstr):
1364
def test_create_flag_errors(self):
1365
# Since the exception classes are exposed, nothing stops users
1366
# from creating their own instances. This test makes sure that
1367
# people modifying the flags module understand that the external
1368
# mechanisms for creating the exceptions should continue to work.
1369
e = flags.FlagsError()
1370
e = flags.FlagsError("message")
1371
e = flags.DuplicateFlag()
1372
e = flags.DuplicateFlag("message")
1373
e = flags.IllegalFlagValue()
1374
e = flags.IllegalFlagValue("message")
1375
e = flags.UnrecognizedFlag()
1376
e = flags.UnrecognizedFlag("message")
1378
def testFlagValuesDelAttr(self):
1379
"""Checks that del FLAGS.flag_id works."""
1380
default_value = 'default value for testFlagValuesDelAttr'
1381
# 1. Declare and delete a flag with no short name.
1382
flags.DEFINE_string('delattr_foo', default_value, 'A simple flag.')
1383
self.assertEquals(FLAGS.delattr_foo, default_value)
1384
flag_obj = FLAGS['delattr_foo']
1385
# We also check that _FlagIsRegistered works as expected :)
1386
self.assertTrue(FLAGS._FlagIsRegistered(flag_obj))
1387
del FLAGS.delattr_foo
1388
self.assertFalse('delattr_foo' in FLAGS.FlagDict())
1389
self.assertFalse(FLAGS._FlagIsRegistered(flag_obj))
1390
# If the previous del FLAGS.delattr_foo did not work properly, the
1391
# next definition will trigger a redefinition error.
1392
flags.DEFINE_integer('delattr_foo', 3, 'A simple flag.')
1393
del FLAGS.delattr_foo
1395
self.assertFalse('delattr_foo' in FLAGS.RegisteredFlags())
1397
# 2. Declare and delete a flag with a short name.
1398
flags.DEFINE_string('delattr_bar', default_value, 'flag with short name',
1400
flag_obj = FLAGS['delattr_bar']
1401
self.assertTrue(FLAGS._FlagIsRegistered(flag_obj))
1403
self.assertTrue(FLAGS._FlagIsRegistered(flag_obj))
1404
del FLAGS.delattr_bar
1405
self.assertFalse(FLAGS._FlagIsRegistered(flag_obj))
1407
# 3. Just like 2, but del FLAGS.name last
1408
flags.DEFINE_string('delattr_bar', default_value, 'flag with short name',
1410
flag_obj = FLAGS['delattr_bar']
1411
self.assertTrue(FLAGS._FlagIsRegistered(flag_obj))
1412
del FLAGS.delattr_bar
1413
self.assertTrue(FLAGS._FlagIsRegistered(flag_obj))
1415
self.assertFalse(FLAGS._FlagIsRegistered(flag_obj))
1417
self.assertFalse('delattr_bar' in FLAGS.RegisteredFlags())
1418
self.assertFalse('x5' in FLAGS.RegisteredFlags())
1420
def _GetNamesOfDefinedFlags(self, module, flag_values=FLAGS):
1421
"""Returns the list of names of flags defined by a module.
1423
Auxiliary for the testKeyFlags* methods.
1426
module: A module object or a string module name.
1427
flag_values: A FlagValues object.
1432
return [f.name for f in flag_values._GetFlagsDefinedByModule(module)]
1434
def _GetNamesOfKeyFlags(self, module, flag_values=FLAGS):
1435
"""Returns the list of names of key flags for a module.
1437
Auxiliary for the testKeyFlags* methods.
1440
module: A module object or a string module name.
1441
flag_values: A FlagValues object.
1446
return [f.name for f in flag_values._GetKeyFlagsForModule(module)]
1448
def testKeyFlags(self):
1449
# Before starting any testing, make sure no flags are already
1450
# defined for module_foo and module_bar.
1451
self.assertListEqual(self._GetNamesOfKeyFlags(module_foo), [])
1452
self.assertListEqual(self._GetNamesOfKeyFlags(module_bar), [])
1453
self.assertListEqual(self._GetNamesOfDefinedFlags(module_foo), [])
1454
self.assertListEqual(self._GetNamesOfDefinedFlags(module_bar), [])
1457
# Defines a few flags in module_foo and module_bar.
1458
module_foo.DefineFlags()
1460
# Part 1. Check that all flags defined by module_foo are key for
1461
# that module, and similarly for module_bar.
1462
for module in [module_foo, module_bar]:
1463
self.assertListEqual(FLAGS._GetFlagsDefinedByModule(module),
1464
FLAGS._GetKeyFlagsForModule(module))
1465
# Also check that each module defined the expected flags.
1466
self.assertListEqual(self._GetNamesOfDefinedFlags(module),
1467
module.NamesOfDefinedFlags())
1469
# Part 2. Check that flags.DECLARE_key_flag works fine.
1470
# Declare that some flags from module_bar are key for
1472
module_foo.DeclareKeyFlags()
1474
# Check that module_foo has the expected list of defined flags.
1475
self.assertListEqual(self._GetNamesOfDefinedFlags(module_foo),
1476
module_foo.NamesOfDefinedFlags())
1478
# Check that module_foo has the expected list of key flags.
1479
self.assertListEqual(self._GetNamesOfKeyFlags(module_foo),
1480
module_foo.NamesOfDeclaredKeyFlags())
1482
# Part 3. Check that flags.ADOPT_module_key_flags works fine.
1483
# Trigger a call to flags.ADOPT_module_key_flags(module_bar)
1484
# inside module_foo. This should declare a few more key
1485
# flags in module_foo.
1486
module_foo.DeclareExtraKeyFlags()
1488
# Check that module_foo has the expected list of key flags.
1489
self.assertListEqual(self._GetNamesOfKeyFlags(module_foo),
1490
module_foo.NamesOfDeclaredKeyFlags() +
1491
module_foo.NamesOfDeclaredExtraKeyFlags())
1493
module_foo.RemoveFlags()
1495
def testKeyFlagsWithNonDefaultFlagValuesObject(self):
1496
# Check that key flags work even when we use a FlagValues object
1497
# that is not the default flags.FLAGS object. Otherwise, this
1498
# test is similar to testKeyFlags, but it uses only module_bar.
1499
# The other test module (module_foo) uses only the default values
1500
# for the flag_values keyword arguments. This way, testKeyFlags
1501
# and this method test both the default FlagValues, the explicitly
1502
# specified one, and a mixed usage of the two.
1504
# A brand-new FlagValues object, to use instead of flags.FLAGS.
1505
fv = flags.FlagValues()
1507
# Before starting any testing, make sure no flags are already
1508
# defined for module_foo and module_bar.
1509
self.assertListEqual(
1510
self._GetNamesOfKeyFlags(module_bar, flag_values=fv),
1512
self.assertListEqual(
1513
self._GetNamesOfDefinedFlags(module_bar, flag_values=fv),
1516
module_bar.DefineFlags(flag_values=fv)
1518
# Check that all flags defined by module_bar are key for that
1519
# module, and that module_bar defined the expected flags.
1520
self.assertListEqual(fv._GetFlagsDefinedByModule(module_bar),
1521
fv._GetKeyFlagsForModule(module_bar))
1522
self.assertListEqual(
1523
self._GetNamesOfDefinedFlags(module_bar, flag_values=fv),
1524
module_bar.NamesOfDefinedFlags())
1526
# Pick two flags from module_bar, declare them as key for the
1527
# current (i.e., main) module (via flags.DECLARE_key_flag), and
1528
# check that we get the expected effect. The important thing is
1529
# that we always use flags_values=fv (instead of the default
1531
main_module = flags._GetMainModule()
1532
names_of_flags_defined_by_bar = module_bar.NamesOfDefinedFlags()
1533
flag_name_0 = names_of_flags_defined_by_bar[0]
1534
flag_name_2 = names_of_flags_defined_by_bar[2]
1536
flags.DECLARE_key_flag(flag_name_0, flag_values=fv)
1537
self.assertListEqual(
1538
self._GetNamesOfKeyFlags(main_module, flag_values=fv),
1541
flags.DECLARE_key_flag(flag_name_2, flag_values=fv)
1542
self.assertListEqual(
1543
self._GetNamesOfKeyFlags(main_module, flag_values=fv),
1544
[flag_name_0, flag_name_2])
1546
flags.ADOPT_module_key_flags(module_bar, flag_values=fv)
1547
key_flags = self._GetNamesOfKeyFlags(main_module, flag_values=fv)
1548
# Order is irrelevant; hence, we sort both lists before comparison.
1550
names_of_flags_defined_by_bar.sort()
1551
self.assertListEqual(key_flags, names_of_flags_defined_by_bar)
1553
def testMainModuleHelpWithKeyFlags(self):
1554
# Similar to test_main_module_help, but this time we make sure to
1555
# declare some key flags.
1558
" -?,--[no]help: show this help\n"
1559
" --[no]helpshort: show usage only for this module\n"
1560
" --[no]helpxml: like --help, but generates XML output"
1563
expected_help = "\n%s:\n%s" % (sys.argv[0], help_flag_help)
1565
# Safety check that the main module does not declare any flags
1566
# at the beginning of this test.
1567
self.assertMultiLineEqual(expected_help, FLAGS.MainModuleHelp())
1569
# Define one flag in this main module and some flags in modules
1570
# a and b. Also declare one flag from module a and one flag
1571
# from module b as key flags for the main module.
1572
flags.DEFINE_integer('main_module_int_fg', 1,
1573
'Integer flag in the main module.')
1575
main_module_int_fg_help = (
1576
" --main_module_int_fg: Integer flag in the main module.\n"
1580
expected_help += "\n" + main_module_int_fg_help
1581
self.assertMultiLineEqual(expected_help, FLAGS.MainModuleHelp())
1583
# The following call should be a no-op: any flag declared by a
1584
# module is automatically key for that module.
1585
flags.DECLARE_key_flag('main_module_int_fg')
1586
self.assertMultiLineEqual(expected_help, FLAGS.MainModuleHelp())
1588
# The definition of a few flags in an imported module should not
1589
# change the main module help.
1590
module_foo.DefineFlags()
1591
self.assertMultiLineEqual(expected_help, FLAGS.MainModuleHelp())
1593
flags.DECLARE_key_flag('tmod_foo_bool')
1594
tmod_foo_bool_help = (
1595
" --[no]tmod_foo_bool: Boolean flag from module foo.\n"
1596
" (default: 'true')")
1597
expected_help += "\n" + tmod_foo_bool_help
1598
self.assertMultiLineEqual(expected_help, FLAGS.MainModuleHelp())
1600
flags.DECLARE_key_flag('tmod_bar_z')
1602
" --[no]tmod_bar_z: Another boolean flag from module bar.\n"
1603
" (default: 'false')")
1604
# Unfortunately, there is some flag sorting inside
1605
# MainModuleHelp, so we can't keep incrementally extending
1606
# the expected_help string ...
1607
expected_help = ("\n%s:\n%s\n%s\n%s\n%s" %
1610
main_module_int_fg_help,
1612
tmod_foo_bool_help))
1613
self.assertMultiLineEqual(FLAGS.MainModuleHelp(), expected_help)
1616
# At the end, delete all the flag information we created.
1617
FLAGS.__delattr__('main_module_int_fg')
1618
module_foo.RemoveFlags()
1620
def test_ADOPT_module_key_flags(self):
1621
# Check that ADOPT_module_key_flags raises an exception when
1622
# called with a module name (as opposed to a module object).
1623
self.assertRaises(flags.FlagsError,
1624
flags.ADOPT_module_key_flags,
1625
'google3.pyglib.app')
1627
def test_GetCallingModule(self):
1628
self.assertEqual(flags._GetCallingModule(), sys.argv[0])
1630
module_foo.GetModuleName(),
1633
module_bar.GetModuleName(),
1636
# We execute the following exec statements for their side-effect
1637
# (i.e., not raising an error). They emphasize the case that not
1638
# all code resides in one of the imported modules: Python is a
1639
# really dynamic language, where we can dynamically construct some
1640
# code and execute it.
1641
code = ("import gflags\n"
1642
"module_name = gflags._GetCallingModule()")
1645
# Next two exec statements executes code with a global environment
1646
# that is different from the global environment of any imported
1649
# vars(self) returns a dictionary corresponding to the symbol
1650
# table of the self object. dict(...) makes a distinct copy of
1651
# this dictionary, such that any new symbol definition by the
1652
# exec-ed code (e.g., import flags, module_name = ...) does not
1653
# affect the symbol table of self.
1654
exec code in dict(vars(self))
1656
# Next test is actually more involved: it checks not only that
1657
# _GetCallingModule does not crash inside exec code, it also checks
1658
# that it returns the expected value: the code executed via exec
1659
# code is treated as being executed by the current module. We
1660
# check it twice: first time by executing exec from the main
1661
# module, second time by executing it from module_bar.
1663
exec code in global_dict
1664
self.assertEqual(global_dict['module_name'],
1668
module_bar.ExecuteCode(code, global_dict)
1670
global_dict['module_name'],
1678
if __name__ == '__main__':