#!/usr/bin/env python # Copyright 2014 Google Inc. All Rights Reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following disclaimer # in the documentation and/or other materials provided with the # distribution. # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Unittest for helpers module.""" import sys import unittest from gflags import _helpers from gflags.flags_modules_for_testing import module_bar from gflags.flags_modules_for_testing import module_foo class FlagSuggestionTest(unittest.TestCase): def setUp(self): self.longopts = [ 'fsplit-ivs-in-unroller=', 'fsplit-wide-types=', 'fstack-protector=', 'fstack-protector-all=', 'fstrict-aliasing=', 'fstrict-overflow=', 'fthread-jumps=', 'ftracer', 'ftree-bit-ccp', 'ftree-builtin-call-dce', 'ftree-ccp', 'ftree-ch'] def testDamerauLevenshteinId(self): self.assertEqual(0, _helpers._DamerauLevenshtein('asdf', 'asdf')) def testDamerauLevenshteinEmpty(self): self.assertEqual(5, _helpers._DamerauLevenshtein('', 'kites')) self.assertEqual(6, _helpers._DamerauLevenshtein('kitten', '')) def testDamerauLevenshteinCommutative(self): self.assertEqual(2, _helpers._DamerauLevenshtein('kitten', 'kites')) self.assertEqual(2, _helpers._DamerauLevenshtein('kites', 'kitten')) def testDamerauLevenshteinTransposition(self): self.assertEqual(1, _helpers._DamerauLevenshtein('kitten', 'ktiten')) def testMispelledSuggestions(self): suggestions = _helpers.GetFlagSuggestions('fstack_protector_all', self.longopts) self.assertEqual(['fstack-protector-all'], suggestions) def testAmbiguousPrefixSuggestion(self): suggestions = _helpers.GetFlagSuggestions('fstack', self.longopts) self.assertEqual(['fstack-protector', 'fstack-protector-all'], suggestions) def testMisspelledAmbiguousPrefixSuggestion(self): suggestions = _helpers.GetFlagSuggestions('stack', self.longopts) self.assertEqual(['fstack-protector', 'fstack-protector-all'], suggestions) def testCrazySuggestion(self): suggestions = _helpers.GetFlagSuggestions('asdfasdgasdfa', self.longopts) self.assertEqual([], suggestions) class GetCallingModuleTest(unittest.TestCase): """Test whether we correctly determine the module which defines the flag.""" def testGetCallingModule(self): self.assertEqual('setup.py', sys.argv[0]) self.assertEqual( 'gflags.flags_modules_for_testing.module_foo', 'gflags.flags_modules_for_testing.module_foo') self.assertEqual( module_bar.GetModuleName(), 'gflags.flags_modules_for_testing.module_bar') # We execute the following exec statements for their side-effect # (i.e., not raising an error). They emphasize the case that not # all code resides in one of the imported modules: Python is a # really dynamic language, where we can dynamically construct some # code and execute it. code = ('from gflags import _helpers\n' 'module_name = _helpers.GetCallingModule()') exec(code) # pylint: disable=exec-used # Next two exec statements executes code with a global environment # that is different from the global environment of any imported # module. exec(code, {}) # pylint: disable=exec-used # vars(self) returns a dictionary corresponding to the symbol # table of the self object. dict(...) makes a distinct copy of # this dictionary, such that any new symbol definition by the # exec-ed code (e.g., import flags, module_name = ...) does not # affect the symbol table of self. exec(code, dict(vars(self))) # pylint: disable=exec-used # Next test is actually more involved: it checks not only that # GetCallingModule does not crash inside exec code, it also checks # that it returns the expected value: the code executed via exec # code is treated as being executed by the current module. We # check it twice: first time by executing exec from the main # module, second time by executing it from module_bar. global_dict = {} exec(code, global_dict) # pylint: disable=exec-used self.assertEqual(global_dict['module_name'], 'gflags._helpers_test') global_dict = {} module_bar.ExecuteCode(code, global_dict) self.assertEqual( global_dict['module_name'], 'gflags.flags_modules_for_testing.module_bar') def testGetCallingModuleWithIteritemsError(self): # This test checks that GetCallingModule is using # sys.modules.items(), instead of .iteritems(). orig_sys_modules = sys.modules # Mock sys.modules: simulates error produced by importing a module # in paralel with our iteration over sys.modules.iteritems(). class SysModulesMock(dict): def __init__(self, original_content): dict.__init__(self, original_content) def iteritems(self): # Any dictionary method is fine, but not .iteritems(). raise RuntimeError('dictionary changed size during iteration') sys.modules = SysModulesMock(orig_sys_modules) try: # _GetCallingModule should still work as expected: self.assertEqual('setup.py', sys.argv[0]) self.assertEqual( 'gflags.flags_modules_for_testing.module_foo', 'gflags.flags_modules_for_testing.module_foo') finally: sys.modules = orig_sys_modules class IsRunningTestTest(unittest.TestCase): def testUnderTest(self): self.assertTrue(_helpers.IsRunningTest()) def main(): unittest.main() if __name__ == '__main__': main()