diff options
| author | Ulf Magnusson <ulfalizer@gmail.com> | 2017-10-28 05:18:37 +0200 |
|---|---|---|
| committer | Ulf Magnusson <ulfalizer@gmail.com> | 2017-10-28 05:18:37 +0200 |
| commit | 840d65fe069297fb1d088b85e3164465ace4d467 (patch) | |
| tree | 3490754deac2dc813c1344bf086fe6191ae3f405 | |
| parent | 481bfd60d0b283f30b906d2edf8228aeb82e8492 (diff) | |
Test suite work, cleanup, const sym invalidation fix
| -rw-r--r-- | kconfiglib.py | 203 | ||||
| -rw-r--r-- | testsuite.py | 186 |
2 files changed, 250 insertions, 139 deletions
diff --git a/kconfiglib.py b/kconfiglib.py index 25bb380..3262b43 100644 --- a/kconfiglib.py +++ b/kconfiglib.py @@ -360,13 +360,13 @@ class Config(object): # Predefined symbol. DEFCONFIG_LIST uses this. uname_sym = self._lookup_const_sym("UNAME_RELEASE") uname_sym._type = STRING - uname_sym.defaults.append( - (self._lookup_const_sym(platform.uname()[2]), - self.y)) # env_var doubles as the SYMBOL_AUTO flag from the C implementation, so # just set it to something. The naming breaks a bit here, but it's # pretty obscure. uname_sym.env_var = "<uname release>" + uname_sym.defaults.append( + (self._lookup_const_sym(platform.uname()[2]), + self.y)) self.syms["UNAME_RELEASE"] = uname_sym self.top_node = MenuNode() @@ -418,8 +418,8 @@ class Config(object): if self.defconfig_list is None: return None - for filename, cond_expr in self.defconfig_list.defaults: - if eval_expr(cond_expr): + for filename, cond in self.defconfig_list.defaults: + if expr_value(cond): filename = self._expand_sym_refs(filename.str_value) try: with self._open(filename) as f: @@ -559,7 +559,7 @@ class Config(object): self._line = s del self._tokens[0] - return eval_expr(self._parse_expr(True)) + return expr_value(self._parse_expr(True)) def unset_values(self): """ @@ -921,7 +921,6 @@ class Config(object): self._reuse_line = False while self._line.endswith("\\\n"): - # TODO: Can hang if the file ends with a backslash self._line = self._line[:-2] + self._file.readline() self._linenr += 1 @@ -1346,39 +1345,39 @@ class Config(object): node.prompt = None # Add the new defaults, with dependencies propagated - for val_expr, cond_expr in defaults: + for val_expr, cond in defaults: node.item.defaults.append( - (val_expr, self._make_and(cond_expr, node.dep))) + (val_expr, self._make_and(cond, node.dep))) # Add the new ranges, with dependencies propagated - for low, high, cond_expr in ranges: + for low, high, cond in ranges: node.item.ranges.append( - (low, high, self._make_and(cond_expr, node.dep))) + (low, high, self._make_and(cond, node.dep))) # Handle selects - for target, cond_expr in selects: + for target, cond in selects: # Only stored for convenience. Not used during evaluation. node.item.selects.append( - (target, self._make_and(cond_expr, node.dep))) + (target, self._make_and(cond, node.dep))) # Modify the dependencies of the selected symbol target.rev_dep = \ self._make_or(target.rev_dep, self._make_and(node.item, - self._make_and(cond_expr, + self._make_and(cond, node.dep))) # Handle implies - for target, cond_expr in implies: + for target, cond in implies: # Only stored for convenience. Not used during evaluation. node.item.implies.append( - (target, self._make_and(cond_expr, node.dep))) + (target, self._make_and(cond, node.dep))) # Modify the dependencies of the implied symbol target.weak_rev_dep = \ self._make_or(target.weak_rev_dep, self._make_and(node.item, - self._make_and(cond_expr, + self._make_and(cond, node.dep))) def _parse_expr(self, transform_m): @@ -1559,8 +1558,8 @@ class Config(object): add_fn(config_string) sym._already_written = True - elif eval_expr(node.dep) and \ - ((node.item == MENU and eval_expr(node.visibility)) or + elif expr_value(node.dep) and \ + ((node.item == MENU and expr_value(node.visibility)) or node.item == COMMENT): add_fn("\n#\n# {}\n#\n".format(node.prompt[0])) @@ -1994,8 +1993,8 @@ class Symbol(object): base = _TYPE_TO_BASE[self._type] # Check if a range is in effect - for low_expr, high_expr, cond_expr in self.ranges: - if eval_expr(cond_expr): + for low_expr, high_expr, cond in self.ranges: + if expr_value(cond): has_active_range = True low = int(low_expr.str_value, base) if \ @@ -2020,8 +2019,8 @@ class Symbol(object): else: # No user value or invalid user value. Look at defaults. - for val_expr, cond_expr in self.defaults: - if eval_expr(cond_expr): + for val_expr, cond in self.defaults: + if expr_value(cond): self._write_to_conf = True # Similarly to above, well-formed defaults are @@ -2059,8 +2058,8 @@ class Symbol(object): if vis and self.user_str_value is not None: val = self.user_str_value else: - for val_expr, cond_expr in self.defaults: - if eval_expr(cond_expr): + for val_expr, cond in self.defaults: + if expr_value(cond): self._write_to_conf = True val = val_expr.str_value break @@ -2096,22 +2095,22 @@ class Symbol(object): # (implies) for default, cond in self.defaults: - cond_val = eval_expr(cond) + cond_val = expr_value(cond) if cond_val: - val = min(cond_val, eval_expr(default)) + val = min(cond_val, expr_value(default)) self._write_to_conf = True break # Weak reverse dependencies are only considered if our # direct dependencies are met - if eval_expr(self.direct_dep): - weak_rev_dep_val = eval_expr(self.weak_rev_dep) + if expr_value(self.direct_dep): + weak_rev_dep_val = expr_value(self.weak_rev_dep) if weak_rev_dep_val: val = max(weak_rev_dep_val, val) self._write_to_conf = True # Reverse (select-related) dependencies take precedence - rev_dep_val = eval_expr(self.rev_dep) + rev_dep_val = expr_value(self.rev_dep) if rev_dep_val: val = max(rev_dep_val, val) self._write_to_conf = True @@ -2139,7 +2138,7 @@ class Symbol(object): # 1) If our type is boolean # 2) If our weak_rev_dep (from IMPLY) is y if val == 1 and \ - (self.type == BOOL or eval_expr(self.weak_rev_dep) == 2): + (self.type == BOOL or expr_value(self.weak_rev_dep) == 2): val = 2 self._cached_tri_val = val @@ -2259,38 +2258,51 @@ class Symbol(object): Prints some information about the symbol (including its name, value, visibility, and location(s)) when it is evaluated. """ - fields = [ - "symbol " + self.name, - _TYPENAME[self.type], - 'value "{}"'.format(self.str_value), - "visibility " + TRI_TO_STR[self.visibility], - ] + fields = [] - if self.user_str_value is not None: - fields.append('user value "{}"'.format(self.user_str_value)) + fields.append("symbol " + self.name) + fields.append(_TYPENAME[self.type]) - if self.choice is not None: - fields.append("choice symbol") + for node in self.nodes: + if node.prompt is not None: + fields.append('"{}"'.format(node.prompt[0])) - if self.is_allnoconfig_y: - fields.append("allnoconfig_y") + fields.append('value "{}"'.format(self.str_value)) - if self is self.config.defconfig_list: - fields.append("is the defconfig_list symbol") + if not self.is_constant: + # These aren't helpful to show for constant symbols - if self.env_var is not None: - fields.append("from environment variable " + self.env_var) + if self.user_str_value is not None: + fields.append('user value "{}"'.format(self.user_str_value)) - if self is self.config.modules: - fields.append("is the modules symbol") + fields.append("visibility " + TRI_TO_STR[self.visibility]) - fields.append("direct deps " + TRI_TO_STR[eval_expr(self.direct_dep)]) + if self.choice is not None: + fields.append("choice symbol") + + if self.is_allnoconfig_y: + fields.append("allnoconfig_y") + + if self is self.config.defconfig_list: + fields.append("is the defconfig_list symbol") + + if self.env_var is not None: + fields.append("from environment variable " + self.env_var) + + if self is self.config.modules: + fields.append("is the modules symbol") + + fields.append("direct deps " + + TRI_TO_STR[expr_value(self.direct_dep)]) if self.nodes: for node in self.nodes: fields.append("{}:{}".format(node.filename, node.linenr)) else: - fields.append("undefined") + if self.is_constant: + fields.append("constant") + else: + fields.append("undefined") return "<{}>".format(", ".join(fields)) @@ -2358,11 +2370,11 @@ class Symbol(object): if not vis: return "" - rev_dep_val = eval_expr(self.rev_dep) + rev_dep_val = expr_value(self.rev_dep) if vis == 2: if not rev_dep_val: - if self.type == BOOL or eval_expr(self.weak_rev_dep) == 2: + if self.type == BOOL or expr_value(self.weak_rev_dep) == 2: return "ny" return "nmy" @@ -2371,14 +2383,14 @@ class Symbol(object): # rev_dep_val == 1 - if self.type == BOOL or eval_expr(self.weak_rev_dep) == 2: + if self.type == BOOL or expr_value(self.weak_rev_dep) == 2: return "y" return "my" # vis == 1 if not rev_dep_val: - return "m" if eval_expr(self.weak_rev_dep) != 2 else "y" + return "m" if expr_value(self.weak_rev_dep) != 2 else "y" if rev_dep_val == 2: return "y" @@ -2451,10 +2463,14 @@ class Symbol(object): Invalidates the symbol and all symbols and choices that (possibly indirectly) depend on it """ - self._invalidate() + # Constant symbols must never be invalidated, because they lose their + # value. They never appear as dependencies, but can still be manually + # assigned a user value (and that's OK, though pointless). + if not self.is_constant: + self._invalidate() - for item in self._get_dependent(): - item._invalidate() + for item in self._get_dependent(): + item._invalidate() def _get_dependent(self): """ @@ -2708,8 +2724,8 @@ class Choice(object): """ See the class documentation. """ - for sym, cond_expr in self.defaults: - if eval_expr(cond_expr) and sym.visibility: + for sym, cond in self.defaults: + if expr_value(cond) and sym.visibility: return sym # Otherwise, pick the first visible symbol, if any @@ -2761,19 +2777,38 @@ class Choice(object): """ TODO """ - fields = [ - "choice" if self.name is None else "choice " + self.name, - _TYPENAME[self.type], - "mode " + self.str_value, - "visibility " + TRI_TO_STR[self.visibility], - ] + fields = [] - if self.is_optional: - fields.append("optional") + fields.append("choice" if self.name is None else \ + "choice " + self.name) + fields.append(_TYPENAME[self.type]) + + for node in self.nodes: + if node.prompt is not None: + fields.append('"{}"'.format(node.prompt[0])) + + fields.append("mode " + self.str_value) + + if self.user_str_value is not None: + fields.append('user mode {}'.format(self.user_str_value)) if self.selection is not None: fields.append("{} selected".format(self.selection.name)) + if self.user_selection is not None: + user_sel_str = "{} selected by user" \ + .format(self.user_selection.name) + + if self.selection is not self.user_selection: + user_sel_str += " (overriden)" + + fields.append(user_sel_str) + + fields.append("visibility " + TRI_TO_STR[self.visibility]) + + if self.is_optional: + fields.append("optional") + for node in self.nodes: fields.append("{}:{}".format(node.filename, node.linenr)) @@ -2932,46 +2967,42 @@ class MenuNode(object): ) def __repr__(self): + """ + TODO + """ fields = [] if isinstance(self.item, Symbol): fields.append("menu node for symbol " + self.item.name) - elif isinstance(self.item, Choice): s = "menu node for choice" if self.item.name is not None: s += " " + self.item.name fields.append(s) - elif self.item == MENU: fields.append("menu node for menu") - elif self.item == COMMENT: fields.append("menu node for comment") - elif self.item is None: fields.append("menu node for if (should not appear in the final " " tree)") - else: raise InternalError("unable to determine type in " "MenuNode.__repr__()") - fields.append("{}:{}".format(self.filename, self.linenr)) - if self.prompt is not None: fields.append('prompt "{}" (visibility {})' .format(self.prompt[0], - TRI_TO_STR[eval_expr(self.prompt[1])])) + TRI_TO_STR[expr_value(self.prompt[1])])) if isinstance(self.item, Symbol) and self.is_menuconfig: fields.append("is menuconfig") - fields.append("deps " + TRI_TO_STR[eval_expr(self.dep)]) + fields.append("deps " + TRI_TO_STR[expr_value(self.dep)]) if self.item == MENU: fields.append("'visible if' deps " + \ - TRI_TO_STR[eval_expr(self.visibility)]) + TRI_TO_STR[expr_value(self.visibility)]) if isinstance(self.item, (Symbol, Choice)) and self.help is not None: fields.append("has help") @@ -2982,6 +3013,8 @@ class MenuNode(object): if self.next is not None: fields.append("has next") + fields.append("{}:{}".format(self.filename, self.linenr)) + return "<{}>".format(", ".join(fields)) class KconfigSyntaxError(Exception): @@ -3000,7 +3033,7 @@ class InternalError(Exception): # Public functions # -def eval_expr(expr): +def expr_value(expr): """ TODO """ @@ -3008,18 +3041,18 @@ def eval_expr(expr): return expr.tri_value if expr[0] == AND: - v1 = eval_expr(expr[1]) + v1 = expr_value(expr[1]) # Short-circuit the n case as an optimization (~5% faster # allnoconfig.py and allyesconfig.py, as of writing) - return 0 if not v1 else min(v1, eval_expr(expr[2])) + return 0 if not v1 else min(v1, expr_value(expr[2])) if expr[0] == OR: - v1 = eval_expr(expr[1]) + v1 = expr_value(expr[1]) # Short-circuit the y case as an optimization - return 2 if v1 == 2 else max(v1, eval_expr(expr[2])) + return 2 if v1 == 2 else max(v1, expr_value(expr[2])) if expr[0] == NOT: - return 2 - eval_expr(expr[1]) + return 2 - expr_value(expr[1]) if expr[0] in _RELATIONS: # Implements <, <=, >, >= comparisons as well. These were added to @@ -3096,7 +3129,7 @@ def _get_visibility(sc): for node in sc.nodes: if node.prompt: - vis = max(vis, eval_expr(node.prompt[1])) + vis = max(vis, expr_value(node.prompt[1])) if isinstance(sc, Symbol) and sc.choice is not None: if sc.choice._type == TRISTATE and sc._type != TRISTATE and \ diff --git a/testsuite.py b/testsuite.py index 711a0fb..4af7c19 100644 --- a/testsuite.py +++ b/testsuite.py @@ -56,7 +56,7 @@ def fail(msg=None): global all_passed all_passed = False if msg is not None: - print("Fail: " + msg) + print("fail: " + msg) def verify(cond, msg): if not cond: @@ -587,6 +587,18 @@ choice c = kconfiglib.Config("Kconfiglib/tests/Krepr", warn=False) + verify_repr(c.n, """ +<symbol n, tristate, value "n", constant> +""") + + verify_repr(c.m, """ +<symbol m, tristate, value "m", constant> +""") + + verify_repr(c.y, """ +<symbol y, tristate, value "y", constant> +""") + verify_repr(c.syms["UNDEFINED"], """ <symbol UNDEFINED, unknown, value "UNDEFINED", visibility n, direct deps n, undefined> """) @@ -596,7 +608,13 @@ choice """) verify_repr(c.syms["VISIBLE"], """ -<symbol VISIBLE, bool, value "n", visibility y, direct deps y, Kconfiglib/tests/Krepr:14> +<symbol VISIBLE, bool, "visible", value "n", visibility y, direct deps y, Kconfiglib/tests/Krepr:14> +""") + + c.syms["VISIBLE"].set_value("y") + + verify_repr(c.syms["VISIBLE"], """ +<symbol VISIBLE, bool, "visible", value "y", user value "y", visibility y, direct deps y, Kconfiglib/tests/Krepr:14> """) verify_repr(c.syms["DIR_DEP_N"], """ @@ -612,7 +630,7 @@ choice """) verify_repr(c.syms["CHOICE_1"], """ -<symbol CHOICE_1, tristate, value "n", visibility y, choice symbol, direct deps y, Kconfiglib/tests/Krepr:33> +<symbol CHOICE_1, tristate, "choice sym", value "n", visibility y, choice symbol, direct deps y, Kconfiglib/tests/Krepr:33> """) verify_repr(c.modules, """ @@ -623,66 +641,72 @@ choice print("Testing Choice.__repr__()") verify_repr(c.named_choices["CHOICE"], """ -<choice CHOICE, tristate, mode m, visibility y, Kconfiglib/tests/Krepr:30> +<choice CHOICE, tristate, "choice", mode m, visibility y, Kconfiglib/tests/Krepr:30> """) c.named_choices["CHOICE"].set_value("y") verify_repr(c.named_choices["CHOICE"], """ -<choice CHOICE, tristate, mode y, visibility y, CHOICE_1 selected, Kconfiglib/tests/Krepr:30> +<choice CHOICE, tristate, "choice", mode y, user mode y, CHOICE_1 selected, visibility y, Kconfiglib/tests/Krepr:30> """) c.syms["CHOICE_2"].set_value("y") verify_repr(c.named_choices["CHOICE"], """ -<choice CHOICE, tristate, mode y, visibility y, CHOICE_2 selected, Kconfiglib/tests/Krepr:30> +<choice CHOICE, tristate, "choice", mode y, user mode y, CHOICE_2 selected, CHOICE_2 selected by user, visibility y, Kconfiglib/tests/Krepr:30> +""") + + c.syms["CHOICE_1"].set_value("m") + + verify_repr(c.named_choices["CHOICE"], """ +<choice CHOICE, tristate, "choice", mode m, user mode m, CHOICE_2 selected by user (overriden), visibility y, Kconfiglib/tests/Krepr:30> """) verify_repr(c.syms["CHOICE_HOOK"].nodes[0].next.item, """ -<choice, tristate, mode n, visibility n, optional, Kconfiglib/tests/Krepr:43> +<choice, tristate, "optional choice", mode n, visibility n, optional, Kconfiglib/tests/Krepr:43> """) print("Testing MenuNode.__repr__()") verify_repr(c.syms["BASIC"].nodes[0], """ -<menu node for symbol BASIC, Kconfiglib/tests/Krepr:9, deps y, has help, has next> +<menu node for symbol BASIC, deps y, has help, has next, Kconfiglib/tests/Krepr:9> """) verify_repr(c.syms["DIR_DEP_N"].nodes[0], """ -<menu node for symbol DIR_DEP_N, Kconfiglib/tests/Krepr:17, deps n, has next> +<menu node for symbol DIR_DEP_N, deps n, has next, Kconfiglib/tests/Krepr:17> """) verify_repr(c.syms["MULTI_DEF"].nodes[0], """ -<menu node for symbol MULTI_DEF, Kconfiglib/tests/Krepr:25, deps y, has next> +<menu node for symbol MULTI_DEF, deps y, has next, Kconfiglib/tests/Krepr:25> """) verify_repr(c.syms["MULTI_DEF"].nodes[1], """ -<menu node for symbol MULTI_DEF, Kconfiglib/tests/Krepr:26, deps y, has next> +<menu node for symbol MULTI_DEF, deps y, has next, Kconfiglib/tests/Krepr:26> """) verify_repr(c.syms["MENUCONFIG"].nodes[0], """ -<menu node for symbol MENUCONFIG, Kconfiglib/tests/Krepr:28, is menuconfig, deps y, has next> +<menu node for symbol MENUCONFIG, is menuconfig, deps y, has next, Kconfiglib/tests/Krepr:28> """) verify_repr(c.named_choices["CHOICE"].nodes[0], """ -<menu node for choice CHOICE, Kconfiglib/tests/Krepr:30, prompt "choice" (visibility y), deps y, has child, has next> +<menu node for choice CHOICE, prompt "choice" (visibility y), deps y, has child, has next, Kconfiglib/tests/Krepr:30> """) verify_repr(c.syms["CHOICE_HOOK"].nodes[0].next, """ -<menu node for choice, Kconfiglib/tests/Krepr:43, prompt "choice" (visibility n), deps y, has next> +<menu node for choice, prompt "optional choice" (visibility n), deps y, has next, Kconfiglib/tests/Krepr:43> """) verify_repr(c.syms["NO_VISIBLE_IF_HOOK"].nodes[0].next, """ -<menu node for menu, Kconfiglib/tests/Krepr:50, prompt "no visible if" (visibility y), deps y, 'visible if' deps y, has next> +<menu node for menu, prompt "no visible if" (visibility y), deps y, 'visible if' deps y, has next, Kconfiglib/tests/Krepr:50> """) verify_repr(c.syms["VISIBLE_IF_HOOK"].nodes[0].next, """ -<menu node for menu, Kconfiglib/tests/Krepr:55, prompt "visible if" (visibility y), deps y, 'visible if' deps m, has next> +<menu node for menu, prompt "visible if" (visibility y), deps y, 'visible if' deps m, has next, Kconfiglib/tests/Krepr:55> """) verify_repr(c.syms["COMMENT_HOOK"].nodes[0].next, """ -<menu node for comment, Kconfiglib/tests/Krepr:61, prompt "comment" (visibility y), deps y> +<menu node for comment, prompt "comment" (visibility y), deps y, Kconfiglib/tests/Krepr:61> """) @@ -869,14 +893,14 @@ g def verify_menu_visibility(menu, no_module_vis, module_vis): c.modules.set_value("n") - menu_vis = kconfiglib.eval_expr(menu.node.dep) + menu_vis = kconfiglib.expr_value(menu.node.dep) verify(menu_vis == no_module_vis, "menu \"{}\" should have visibility '{}' without modules, " "has visibility '{}'" .format(menu.title, no_module_vis, menu_vis)) c.modules.set_value("y") - menu_vis = kconfiglib.eval_expr(menu.node.dep) + menu_vis = kconfiglib.expr_value(menu.node.dep) verify(menu_vis == module_vis, "menu \"{}\" should have visibility '{}' with modules, " "has visibility '{}'". @@ -939,14 +963,14 @@ g def verify_comment_visibility(comment, no_module_vis, module_vis): c.modules.set_value("n") # TODO: uninternalize - comment_vis = kconfiglib.eval_expr(comment.node.dep) + comment_vis = kconfiglib.expr_value(comment.node.dep) verify(comment_vis == no_module_vis, "comment \"{}\" should have visibility '{}' without " "modules, has visibility '{}'". format(comment.text, no_module_vis, comment_vis)) c.modules.set_value("y") - comment_vis = kconfiglib.eval_expr(comment.node.dep) + comment_vis = kconfiglib.expr_value(comment.node.dep) verify(comment_vis == module_vis, "comment \"{}\" should have visibility '{}' with " "modules, has visibility '{}'". @@ -1731,11 +1755,11 @@ def run_compatibility_tests(): # (generated by the C implementation) should be compared to ._config # (generated by us) after each invocation. all_arch_tests = [(test_load, False), - (test_config_absent, True), - (test_call_all, False), + (test_alldefconfig, True), + (test_sanity, False), (test_all_no, True), - (test_all_yes, True), (test_all_no_simpler, True), + (test_all_yes, True), # Needs to report success/failure for each arch/defconfig # combo, hence False. (test_defconfig, False)] @@ -1857,49 +1881,78 @@ def test_all_yes(conf, arch): else: shell("make allyesconfig") -def test_call_all(conf, arch): +def test_sanity(conf, arch): """ - Call all public methods on all symbols, choices, and TODO menu nodes for - all architectures to make sure we never crash or hang. (Nearly all public - methods: some are hard to test like this, but are exercised by other - tests.) + Do sanity checks on each configuration and call all public methods on all + symbols, choices, and menu nodes for all architectures to make sure we + never crash or hang. """ print("For {}...".format(arch)) + conf.modules + conf.defconfig_list conf.defconfig_filename - conf.mainmenu_text conf.enable_undef_warnings() conf.disable_undef_warnings() - conf.disable_warnings() conf.enable_warnings() + conf.disable_warnings() + conf.mainmenu_text conf.unset_values() # Python 2/3 compatible - for _, s in conf.syms.items(): - s.__str__() - s.__repr__() - s.assignable - s.type - s.str_value - s.tri_value - s.visibility - s.unset_value() + for _, sym in conf.syms.items(): + if sym.name != "UNAME_RELEASE": + verify(not sym.is_constant, sym.name + " in 'syms' and constant") + + verify(sym not in conf.const_syms, + sym.name + " in both 'syms' and 'const_syms'") + + for dep in sym._direct_dependents: + verify(not dep.is_constant, + "the constant symbol {} depends on {}" + .format(dep.name, sym.name)) + + sym.__repr__() + sym.__str__() + sym.assignable + conf.disable_warnings() + sym.set_value("y") + conf.enable_warnings() + sym.str_value + sym.tri_value + sym.type + sym.unset_value() + sym.user_str_value + sym.user_tri_value + sym.visibility + + for sym in conf.defined_syms: + verify(sym.nodes, sym.name + " is defined but lacks menu nodes") + + for _, sym in conf.const_syms.items(): + verify(sym.is_constant, + '"{}" is in const_syms but not marked constant' + .format(sym.name)) - # TODO: verify that constant symbols do not: - # 1) have a non-empty dep - # 2) have nodes + verify(not sym.nodes, + '"{}" is constant but has menu nodes' + .format(sym.name)) - # TODO: Look for weird stuff in the dictionaries + verify(not sym._direct_dependents, + '"{}" is constant but is a dependency of some symbol' + .format(sym.name)) - # TODO: infinite recursion action - #for _, s in conf.const_syms.items(): - # s.__str__() - # s.__repr__() - # s.assignable - # s.type - # s.value - # s.visibility - # s.unset_value() + sym.__repr__() + sym.__str__() + sym.assignable + conf.disable_warnings() + sym.set_value("y") + conf.enable_warnings() + sym.str_value + sym.tri_value + sym.type + sym.unset_value() + sym.visibility # Cheat with internals for c in conf._choices: @@ -1907,13 +1960,38 @@ def test_call_all(conf, arch): c.__repr__() c.str_value c.tri_value + c.user_str_value + c.user_tri_value c.assignable c.selection c.default_selection c.type c.visibility -def test_config_absent(conf, arch): + # Menu nodes + + node = conf.top_node + + while 1: + # Everything else should be well exercised elsewhere + node.__repr__() + + if node.list is not None: + node = node.list + + elif node.next is not None: + node = node.next + + else: + while node.parent is not None: + node = node.parent + if node.next is not None: + node = node.next + break + else: + break + +def test_alldefconfig(conf, arch): """ Verify that Kconfiglib generates the same .config as 'make alldefconfig', for each architecture |
