1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
# Copyright 2017 The Abseil Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Unittests for helpers module."""
import sys
from absl.flags import _helpers
from absl.flags.tests import module_bar
from absl.flags.tests import module_foo
from absl.testing import absltest
class FlagSuggestionTest(absltest.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 test_damerau_levenshtein_id(self):
self.assertEqual(0, _helpers._damerau_levenshtein('asdf', 'asdf'))
def test_damerau_levenshtein_empty(self):
self.assertEqual(5, _helpers._damerau_levenshtein('', 'kites'))
self.assertEqual(6, _helpers._damerau_levenshtein('kitten', ''))
def test_damerau_levenshtein_commutative(self):
self.assertEqual(2, _helpers._damerau_levenshtein('kitten', 'kites'))
self.assertEqual(2, _helpers._damerau_levenshtein('kites', 'kitten'))
def test_damerau_levenshtein_transposition(self):
self.assertEqual(1, _helpers._damerau_levenshtein('kitten', 'ktiten'))
def test_mispelled_suggestions(self):
suggestions = _helpers.get_flag_suggestions('fstack_protector_all',
self.longopts)
self.assertEqual(['fstack-protector-all'], suggestions)
def test_ambiguous_prefix_suggestion(self):
suggestions = _helpers.get_flag_suggestions('fstack', self.longopts)
self.assertEqual(['fstack-protector', 'fstack-protector-all'], suggestions)
def test_misspelled_ambiguous_prefix_suggestion(self):
suggestions = _helpers.get_flag_suggestions('stack', self.longopts)
self.assertEqual(['fstack-protector', 'fstack-protector-all'], suggestions)
def test_crazy_suggestion(self):
suggestions = _helpers.get_flag_suggestions('asdfasdgasdfa', self.longopts)
self.assertEqual([], suggestions)
def test_suggestions_are_sorted(self):
sorted_flags = sorted(['aab', 'aac', 'aad'])
misspelt_flag = 'aaa'
suggestions = _helpers.get_flag_suggestions(
misspelt_flag, list(reversed(sorted_flags))
)
self.assertEqual(sorted_flags, suggestions)
class GetCallingModuleTest(absltest.TestCase):
"""Test whether we correctly determine the module which defines the flag."""
def test_get_calling_module(self):
self.assertEqual(_helpers.get_calling_module(), sys.argv[0])
self.assertEqual(module_foo.get_module_name(),
'absl.flags.tests.module_foo')
self.assertEqual(module_bar.get_module_name(),
'absl.flags.tests.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 absl.flags import _helpers\n'
'module_name = _helpers.get_calling_module()')
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
# get_calling_module 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'],
sys.argv[0])
global_dict = {}
module_bar.execute_code(code, global_dict)
self.assertEqual(global_dict['module_name'],
'absl.flags.tests.module_bar')
def test_get_calling_module_with_iteritems_error(self):
# This test checks that get_calling_module is using
# sys.modules.items(), instead of .iteritems().
orig_sys_modules = sys.modules
# Mock sys.modules: simulates error produced by importing a module
# in parallel 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:
# _get_calling_module should still work as expected:
self.assertEqual(_helpers.get_calling_module(), sys.argv[0])
self.assertEqual(module_foo.get_module_name(),
'absl.flags.tests.module_foo')
finally:
sys.modules = orig_sys_modules
if __name__ == '__main__':
absltest.main()
|