From dd0e227216e247d2040cdd40bf7397702880cdc4 Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Mon, 9 Oct 2017 23:05:00 +0200 Subject: Kconfiglib 2 backup WIP --- tests/Kchoice | 26 +++++++- tests/Kdefconfig_existent | 1 + tests/Keval | 1 + tests/Klocation | 79 ++++++----------------- tests/Klocation_included | 43 +++---------- tests/Kmisc | 2 +- tests/Kmodifiable | 50 -------------- tests/Kprompt | 77 ---------------------- tests/Krelation | 2 + tests/Krepr | 61 ++++++++++++++++++ tests/Kstr | 76 ++++++++++++++++++++++ tests/Ktext | 145 ----------------------------------------- tests/Kvisibility | 161 ++++++++++++++++++++++++++++------------------ 13 files changed, 290 insertions(+), 434 deletions(-) delete mode 100644 tests/Kmodifiable delete mode 100644 tests/Kprompt create mode 100644 tests/Krepr create mode 100644 tests/Kstr delete mode 100644 tests/Ktext (limited to 'tests') diff --git a/tests/Kchoice b/tests/Kchoice index e80e222..f635ccc 100644 --- a/tests/Kchoice +++ b/tests/Kchoice @@ -141,17 +141,39 @@ choice WEIRD_SYMS # Only WS1 is part of the choice config WS1 + bool "WS1" + config WS2 + bool "WS2" depends on WS1 + config WS3 + bool depends on WS2 + config WS4 + bool depends on WS1 -# 'if' has the same effect, so only WS5 is part of the choice config WS5 -if WS5 + bool "WS5" if WS1 + +# 'if' has the same effect, so only WS6 is part of the choice config WS6 + bool "WS6" + +if WS6 + +config WS7 + bool + +config WS8 + bool "WS8" + endif +# Should also be part of the choice +config WS9 + bool "WS9" + endchoice diff --git a/tests/Kdefconfig_existent b/tests/Kdefconfig_existent index 895c218..8dde443 100644 --- a/tests/Kdefconfig_existent +++ b/tests/Kdefconfig_existent @@ -2,6 +2,7 @@ # Should produce "Kconfiglib/tests/defconfig_2" config FOO + string option env="BAR" config A diff --git a/tests/Keval b/tests/Keval index 64bd4d8..4f63247 100644 --- a/tests/Keval +++ b/tests/Keval @@ -1,6 +1,7 @@ # Enabled/disabled in the test config MODULES bool "modules" + option modules config N def_tristate n diff --git a/tests/Klocation b/tests/Klocation index 404e5ae..498a372 100644 --- a/tests/Klocation +++ b/tests/Klocation @@ -1,73 +1,30 @@ -# Include some line continuations to make sure they don't mess up line numbers +if UNDEFINED +endif -# Defined and referenced in multiple locations -config A - bool +config SINGLE_DEF + +config MULTI_DEF # Throw in some line continuations too to make sure it doesn't mess up the line # numbers -menu "menu 1" - depends on A - visible if A && \ - NOT_DEFINED - -# Also defined in Klocation_included -choice B - bool "b" if A - -config C - bool "c" - -config D - bool "d" - -\ - -endchoice +if y && \ + y +if y && \ + y && \ + y -config A - def_bool NOT_DEFINED +config MULTI_DEF -comment "comment 1" +endif +endif -config E - bool "E" if A - depends on A - -endmenu - -config \ - FOO +config EXPANDED_FROM_ENV string - option \ - env\ - =\ - "FOO" - -\ -\ + option env="EXPANDED_FROM_ENV" -config BAR +config _INCLUDED string - default \ - "_included" + default "_included" # Expands to "tests/Klocation_included" -source \ -"$FOO/Klocation$BAR" - -\ -\ -\ - -config I - int - range A 0 - range 0 A - range 0 1 if A - default J if A < 0 - default K if 0 < A - default L if 0 <= A - default M if 0 > A - default N if 0 >= A - default N if y && 0 < A +source "$EXPANDED_FROM_ENV/Klocation$_INCLUDED" diff --git a/tests/Klocation_included b/tests/Klocation_included index 674116a..fb1afaa 100644 --- a/tests/Klocation_included +++ b/tests/Klocation_included @@ -1,42 +1,15 @@ -menuconfig A - bool "A" -menuconfig A - bool "A" -menu "menu 2" -config M - def_bool !(n || (n || A = n)) - default !A if y - default y if !A -config S - bool - select A if NOT_DEFINED = y - select E if A - imply A - imply E if A -endmenu -choice - bool "C" -config N - bool "N" -config O - bool "O" -endchoice -choice B - bool "B" -config B1 - tristate "B1" -config B2 - tristate "B2" +config MULTI_DEF +choice CHOICE endchoice -if !(NOT_DEFINED != A) -comment "comment 2" -endif +config MENU_HOOK -menu "visible if menu" - visible if A - visible if NOT_DEFINED +menu "menu" endmenu + +config COMMENT_HOOK + +comment "comment" diff --git a/tests/Kmisc b/tests/Kmisc index d2e55b2..c3a21f8 100644 --- a/tests/Kmisc +++ b/tests/Kmisc @@ -1,6 +1,6 @@ # For testing various minor APIs -# is_optional() +# optional choices choice NOT_OPTIONAL bool "not optional" diff --git a/tests/Kmodifiable b/tests/Kmodifiable deleted file mode 100644 index 1f9dcc9..0000000 --- a/tests/Kmodifiable +++ /dev/null @@ -1,50 +0,0 @@ -config MODULES - def_bool y - -config VISIBLE - tristate "bool visible" - -config NOT_VISIBLE - tristate - -config Y_SELECTOR - def_tristate y - select SELECTED_TO_Y - -config SELECTED_TO_Y - tristate "selected to y" - -config M_SELECTOR - def_tristate m - select TRISTATE_SELECTED_TO_M - select M_VISIBLE_TRISTATE_SELECTED_TO_M - select BOOL_SELECTED_TO_M - -config TRISTATE_SELECTED_TO_M - tristate "tristate selected to m" - -config M_VISIBLE_TRISTATE_SELECTED_TO_M - tristate "m-visible tristate selected to m" - depends on m - -# The "m" will get promoted to a "y", so this should still not be modifiable -config BOOL_SELECTED_TO_M - bool "bool selected to m" - -config VISIBLE_STRING - string "visible string" - -config VISIBLE_INT - int "visible int" - -config VISIBLE_HEX - hex "visible hex" - -config NOT_VISIBLE_STRING - string - -config NOT_VISIBLE_INT - int "not visible int" if n - -config NOT_VISIBLE_HEX - hex diff --git a/tests/Kprompt b/tests/Kprompt deleted file mode 100644 index a36a0fd..0000000 --- a/tests/Kprompt +++ /dev/null @@ -1,77 +0,0 @@ -config NO_PROMPT - tristate - -config SINGLE_PROMPT_1 - bool "single prompt 1" - -config SINGLE_PROMPT_2 - bool - prompt "single prompt 2" if n - -config MULTI_PROMPT - bool "ignored prompt" - prompt "prompt 1" -config MULTI_PROMPT - bool "prompt 2" -config MULTI_PROMPT - bool -config MULTI_PROMPT - bool - prompt "prompt 3" -config MULTI_PROMPT - bool - prompt "ignored prompt" - prompt "ignored prompt 2" if y - prompt "prompt 4" if y - -choice NO_PROMPT_CHOICE - tristate -config A - bool -config B - bool -endchoice - -choice SINGLE_PROMPT_1_CHOICE - bool "single prompt 1 choice" -config C - bool -config D - bool -endchoice - -choice SINGLE_PROMPT_2_CHOICE - bool "ignored prompt" - prompt "single prompt 2 choice" -config E - bool -config F - bool -endchoice - -choice MULTI_PROMPT_CHOICE - bool "prompt 1 choice" -config G - bool -config H - bool -endchoice - -choice MULTI_PROMPT_CHOICE - bool - prompt "prompt 2 choice" -config I - bool -config J - bool -endchoice - -choice MULTI_PROMPT_CHOICE - bool - prompt "ignored prompt" - prompt "prompt 3 choice" -config K - bool -config L - bool -endchoice diff --git a/tests/Krelation b/tests/Krelation index 057b585..420152f 100644 --- a/tests/Krelation +++ b/tests/Krelation @@ -1,5 +1,6 @@ config A bool + depends on UNDEFINED choice bool "C" @@ -18,6 +19,7 @@ menu "m2" config F bool choice + tristate "foo" config G bool "g" config H diff --git a/tests/Krepr b/tests/Krepr new file mode 100644 index 0000000..d886fe3 --- /dev/null +++ b/tests/Krepr @@ -0,0 +1,61 @@ +config MODULES + bool + option modules + default y + +if UNDEFINED +endif + +config BASIC + bool + default y + help + +config VISIBLE + bool "visible" + +config DIR_DEP_N + depends on n + +config OPTIONS + option allnoconfig_y + option defconfig_list + option env="ENV" + +config MULTI_DEF +config MULTI_DEF + +menuconfig MENUCONFIG + +choice CHOICE + tristate "choice" + +config CHOICE_1 + tristate "choice sym" + +config CHOICE_2 + tristate "choice sym" + +endchoice + +config CHOICE_HOOK + +choice + tristate "choice" if n + optional +endchoice + +config NO_VISIBLE_IF_HOOK + +menu "no visible if" +endmenu + +config VISIBLE_IF_HOOK + +menu "visible if" + visible if m +endmenu + +config COMMENT_HOOK + +comment "comment" diff --git a/tests/Kstr b/tests/Kstr new file mode 100644 index 0000000..8d74017 --- /dev/null +++ b/tests/Kstr @@ -0,0 +1,76 @@ +if UNDEFINED +endif + +config NO_TYPE + +config BASIC_NO_PROMPT + bool + help + blah blah + + blah blah blah + + blah + +config BASIC_PROMPT + bool "basic" + +config ADVANCED + tristate "prompt" if DEP + default DEFAULT_1 + default DEFAULT_2 if DEP + select SELECTED_1 + select SELECTED_2 if DEP + imply IMPLIED_1 + imply IMPLIED_2 if DEP + help + first help text + +config ADVANCED + prompt "prompt 2" + +menuconfig ADVANCED + prompt "prompt 3" + depends on DEP2 + +config ADVANCED + help + second help text + +config STRING + string + default "foo" + default "bar" if DEP + default STRING2 + default STRING3 if DEP + +config INT + int + range 1 2 + range FOO BAR + range BAZ QAZ if DEP + +config MODULES + option modules + +config OPTIONS + option allnoconfig_y + option defconfig_list + option env="ENV" + +choice CHOICE + tristate "foo" + default CHOICE_1 + default CHOICE_2 if dep + +config CHOICE_1 + tristate "choice 1" + +config CHOICE_2 + tristate "choice 2" + +endchoice + +choice + tristate "no name" +endchoice diff --git a/tests/Ktext b/tests/Ktext deleted file mode 100644 index 3440c3c..0000000 --- a/tests/Ktext +++ /dev/null @@ -1,145 +0,0 @@ -config BASIC - bool - -if !BASIC && !BASIC - -config ADVANCED - tristate "advanced prompt 1" if y || (BASIC && BASIC) - select SELECTED_1 if BASIC && DUMMY - select SELECTED_2 if !(DUMMY || BASIC) - imply IMPLIED_1 if BASIC || DUMMY - imply IMPLIED_2 if !(DUMMY && BASIC) - default y if BASIC && !BASIC - default n if BASIC = DUMMY && X < Y && X <= Y && X > Y && X >= Y - -config ADVANCED - tristate "advanced prompt 2" - -config STRING - string - default "foo" - default "bar" if BAR - default STRING2 if BAZ - -config STRING2 - string - default "baz" - -endif - -config SELECTED_1 -config SELECTED_2 -config SELECTING_1 - select ADVANCED if BASIC -config SELECTING_2 - select ADVANCED if !BASIC -config IMPLYING_1 - imply ADVANCED if DUMMY -config IMPLYING_2 - imply ADVANCED if !DUMMY - -config INT - int - default 7 - -config HAS_RANGES - int "ranged" - range 1 2 if !DUMMY - range INT INT if DUMMY - range 123 456 - -choice - bool "choice" - -config CHOICE_ITEM_1 - bool "A" -config CHOICE_ITEM_2 - bool "B" -config CHOICE_ITEM_3 - bool "C" - -endchoice - -menu "simple menu" -endmenu - -if !DUMMY -menu "advanced menu" - depends on !BASIC - visible if !DUMMY -endmenu -endif - -comment "simple comment" - -if !DUMMY - comment "advanced comment" - depends on !BASIC -endif - -config NO_HELP - bool - -choice NO_HELP_CHOICE -config FOO -endchoice - -config EMPTY_HELP - bool - help -config DUMMY - -choice EMPTY_HELP_CHOICE - bool - help -config DUMMY2 -endchoice - -config S - bool - help - help for - S -choice C - bool - help - help for - C -config A - bool "A" - -config B - bool "B" - -endchoice - -comment "a comment" - -menu "a menu" -endmenu - -config HELP_TERMINATED_BY_COMMENT - bool - help - a - b - c -# - -config TRICKY_HELP - bool - help - - - a - b - c - - d - e - f - - - g - h - i diff --git a/tests/Kvisibility b/tests/Kvisibility index 715d098..91def0a 100644 --- a/tests/Kvisibility +++ b/tests/Kvisibility @@ -1,5 +1,6 @@ config MODULES bool "MODULES" + option modules # # Symbol visibility @@ -12,186 +13,204 @@ config NO_PROMPT config MOD def_tristate m -config BOOL_n +config BOOL_N bool "bool n" if n -# Rewritten to m && MODULES -config BOOL_m +config BOOL_M + # Rewritten to m && MODULES bool "bool m" if m -# Not rewritten config BOOL_MOD bool "bool MOD" + # Not rewritten depends on MOD -# Rewritten to m && MODULES -config BOOL_y +config BOOL_Y bool "bool y" + # Rewritten to m && MODULES depends on y || m -config TRISTATE_n +config TRISTATE_N tristate "tristate n" if n -# Rewritten to m && MODULES -config TRISTATE_m +config TRISTATE_M + # Rewritten to m && MODULES tristate "tristate m" if m -# Not rewritten config TRISTATE_MOD tristate "tristate MOD" + # Not rewritten depends on MOD -# Rewritten to m && MODULES -config TRISTATE_y +config TRISTATE_Y bool "tristate y" + # Rewritten to m && MODULES depends on y || m # Symbols nested in 'if' if n -config BOOL_if_n + +config BOOL_IF_N bool "bool if n" -config TRISTATE_if_n + +config TRISTATE_IF_N tristate "tristate if n" + endif if m -config BOOL_if_m + +config BOOL_IF_M bool "bool if m" -config TRISTATE_if_m + +config TRISTATE_IF_M tristate "tristate if n" + endif if y -config BOOL_if_y + +config BOOL_IF_Y bool "bool if y" -config TRISTATE_if_y + +config TRISTATE_IF_Y tristate "tristate if y" + endif # Symbols nested in 'menu' menu "menu 1" depends on n -config BOOL_menu_n + +config BOOL_MENU_N bool "bool menu n" -config TRISTATE_menu_n + +config TRISTATE_MENU_N tristate "tristate menu n" + endmenu menu "menu 2" depends on m -config BOOL_menu_m + +config BOOL_MENU_M bool "bool menu m" -config TRISTATE_menu_m + +config TRISTATE_MENU_M tristate "tristate menu n" + endmenu menu "menu 3" depends on y -config BOOL_menu_y + +config BOOL_MENU_Y bool "bool menu y" -config TRISTATE_menu_y + +config TRISTATE_MENU_Y tristate "tristate menu y" + endmenu # Symbols nested in choices choice C1 tristate "choice n" if n -config BOOL_choice_n + +config BOOL_CHOICE_N bool "bool choice n" -config TRISTATE_choice_n + +config TRISTATE_CHOICE_N tristate "tristate choice n" + endchoice choice C2 tristate "choice m" if m -config BOOL_choice_m + +config BOOL_CHOICE_M bool "bool choice m" -config TRISTATE_choice_m + +config TRISTATE_CHOICE_M tristate "tristate choice n" + endchoice choice C3 tristate "choice y" if y -config BOOL_choice_y + +config BOOL_CHOICE_Y bool "bool choice y" -config TRISTATE_choice_y + +config TRISTATE_CHOICE_Y tristate "tristate choice y" + endchoice # # Choice visibility # -choice BOOL_CHOICE_n +choice BOOL_CHOICE_N bool "bool choice n" if n -config A - bool "A" -config B - bool "B" endchoice -choice BOOL_CHOICE_m +choice BOOL_CHOICE_M bool "bool choice m" if m -config C - bool "C" -config D - bool "D" endchoice -choice BOOL_CHOICE_y +choice BOOL_CHOICE_Y bool "bool choice y" if y -config E - bool "E" -config F - bool "F" endchoice -choice TRISTATE_CHOICE_n +choice TRISTATE_CHOICE_N tristate "tristate choice n" if n -config G - tristate "G" -config H - tristate "H" endchoice -choice TRISTATE_CHOICE_m +choice TRISTATE_CHOICE_M tristate "tristate choice m" if m -config I - tristate "I" -config J - tristate "J" endchoice -choice TRISTATE_CHOICE_y +choice TRISTATE_CHOICE_Y tristate "tristate choice y" if y + config K tristate "K" + config L tristate "L" + endchoice if m -choice TRISTATE_CHOICE_IF_m_and_y +choice TRISTATE_CHOICE_IF_M_AND_Y tristate "tristate choice if m and y" if y + config M bool "M" + config N bool "N" + endchoice endif menu "choice-containing menu" depends on n && y -choice TRISTATE_CHOICE_MENU_n_and_y + +choice TRISTATE_CHOICE_MENU_N_AND_Y tristate "tristate choice if n and y" + config O tristate "O" + config P tristate "P" + endchoice + endmenu # @@ -245,19 +264,25 @@ comment "comment y" if n comment "comment if n" endif + if m comment "comment if m" endif + if y comment "comment if y" endif if "y" -menu "comment-containing menu" + +menu "menu with comment" depends on m + comment "double-nested m comment" depends on y + endmenu + endif # Used to verify that string/int/hex symbols with m visibility accept a user @@ -280,28 +305,38 @@ endif menu "n-visible menu" visible if n -config VISIBLE_IF_n + +config VISIBLE_IF_N tristate "visible if n" + endmenu menu "m-visible menu" visible if m -config VISIBLE_IF_m + +config VISIBLE_IF_M tristate "visible if m" + endmenu menu "y-visible menu" visible if y -config VISIBLE_IF_y + +config VISIBLE_IF_Y tristate "visible if m" + endmenu menu "m-visible menu 2" visible if y || n visible if m && y visible if y + if y -config VISIBLE_IF_m_2 + +config VISIBLE_IF_M_2 tristate "visible if m 2" + endif + endmenu -- cgit v1.2.3 From 7bbaf7e7cf131d83931bfda2d2e8e5d6ef1b235f Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Sat, 28 Oct 2017 05:46:25 +0200 Subject: Add uncommitted test files --- kconfiglib.py | 2 ++ tests/Khelp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ tests/Klocation | 2 ++ tests/Krepr | 2 +- tests/Kstr | 1 + tests/Kwtf | 8 ++++++++ 6 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 tests/Khelp create mode 100644 tests/Kwtf (limited to 'tests') diff --git a/kconfiglib.py b/kconfiglib.py index 3262b43..1bf61a6 100644 --- a/kconfiglib.py +++ b/kconfiglib.py @@ -893,6 +893,8 @@ class Config(object): self._file = self._open(filename) except IOError as e: # Extend the error message a bit in this case + # TODO: broken for top-level Kconfig (because + # self._filename/_linenr isn't set) raise IOError( "{}:{}: {} Also note that e.g. $FOO in a 'source' " "statement does not refer to the environment " diff --git a/tests/Khelp b/tests/Khelp new file mode 100644 index 0000000..fdc81ed --- /dev/null +++ b/tests/Khelp @@ -0,0 +1,46 @@ +config TWO_HELP_STRINGS + help + first help string + + + + +config TWO_HELP_STRINGS + help + second help string + +config NO_BLANK_AFTER_HELP + help + help for + NO_BLANK_AFTER_HELP +choice CHOICE_HELP + help + help for + CHOICE_HELP +endchoice + +config HELP_TERMINATED_BY_COMMENT + bool + help + a + b + c +# + +config TRICKY_HELP + bool + help + + + a + b + c + + d + e + f + + + g + h + i diff --git a/tests/Klocation b/tests/Klocation index 498a372..737a221 100644 --- a/tests/Klocation +++ b/tests/Klocation @@ -28,3 +28,5 @@ config _INCLUDED # Expands to "tests/Klocation_included" source "$EXPANDED_FROM_ENV/Klocation$_INCLUDED" + +config MULTI_DEF diff --git a/tests/Krepr b/tests/Krepr index d886fe3..5a5b8b8 100644 --- a/tests/Krepr +++ b/tests/Krepr @@ -41,7 +41,7 @@ endchoice config CHOICE_HOOK choice - tristate "choice" if n + tristate "optional choice" if n optional endchoice diff --git a/tests/Kstr b/tests/Kstr index 8d74017..e591792 100644 --- a/tests/Kstr +++ b/tests/Kstr @@ -51,6 +51,7 @@ config INT range BAZ QAZ if DEP config MODULES + bool "MODULES" option modules config OPTIONS diff --git a/tests/Kwtf b/tests/Kwtf new file mode 100644 index 0000000..c71e328 --- /dev/null +++ b/tests/Kwtf @@ -0,0 +1,8 @@ +config A + bool + select n + select m + select y + imply n + imply m + imply y -- cgit v1.2.3 From 6bce225d38433c9b14ff94ff0fb66d1ac87ff4e3 Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Wed, 1 Nov 2017 23:53:38 +0100 Subject: Do not invalidate everything when loading .configs In replace mode, only unset symbols that didn't get set. Get rid of _set_value_no_invalidate() and just do a normal set_value() with invalidation. It's speedy with the new invalidation algorithm, and simpler. Not a big performance boost (but a small one), but means that invalidation must be even more rock solid for the test suite to pass (no global invalidations to hide behind), which is nice. Also make y assignments to choice symbol update just the choice user value. Gives nicer behavior when the choice mode is changed. --- kconfiglib.py | 187 +++++++++++++++++++++++++++++++++++----------------------- tests/Kmisc | 4 +- 2 files changed, 115 insertions(+), 76 deletions(-) (limited to 'tests') diff --git a/kconfiglib.py b/kconfiglib.py index 6fe9f88..d5143cf 100644 --- a/kconfiglib.py +++ b/kconfiglib.py @@ -420,6 +420,7 @@ class Kconfig(object): """ __slots__ = ( "_choices", + "_loading_config", "_print_undef_assign", "_print_warnings", "_set_re_match", @@ -583,6 +584,8 @@ class Kconfig(object): # Build Symbol._dependents for all symbols self._build_dep() + self._loading_config = False + @property def mainmenu_text(self): """ @@ -624,12 +627,30 @@ class Kconfig(object): True if all existing user values should be cleared before loading the .config. """ + # Are we currently loading a .config file? This disables a warning. + self._loading_config = True + + # This stub only exists to make sure _loading_config gets unset + try: + self._load_config(filename, replace) + finally: + self._loading_config = False + + def _load_config(self, filename, replace): with self._open(filename) as f: if replace: - # Invalidates all symbols as a side effect - self.unset_values() - else: - self._invalidate_all() + # If we're replacing the configuration, keep track of which + # symbols and choices got set so that we can unset the rest + # later. This avoids invalidating everything and is a tiny bit + # faster in the test suite. The main benefit though is that + # invalidation must be rock solid for it to work, making it a + # good test. + + for sym in self.defined_syms: + sym._was_set = False + + for choice in self._choices: + choice._was_set = False # Small optimizations set_re_match = self._set_re_match @@ -715,7 +736,7 @@ class Kconfig(object): # Done parsing the assignment. Set the value. - if sym.user_value is not None: + if sym._was_set: # Use strings for tristate values in the warning if sym.orig_type in (BOOL, TRISTATE): display_val = TRI_TO_STR[val] @@ -729,7 +750,19 @@ class Kconfig(object): .format(name, display_user_val, display_val), filename, linenr) - sym._set_value_no_invalidate(val, True) + sym.set_value(val) + + if replace: + # If we're replacing the configuration, unset the symbols that + # didn't get set + + for sym in self.defined_syms: + if not sym._was_set: + sym.unset_value() + + for choice in self._choices: + if not choice._was_set: + choice.unset_value() def write_config(self, filename, header="# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib)\n"): @@ -791,16 +824,11 @@ class Kconfig(object): # set_value() already rejects undefined symbols, and they don't need to # be invalidated (because their value never changes), so we can just # iterate over defined symbols - for sym in self.defined_syms: - # We're iterating over all (defined) symbols, so no need for - # symbols to invalidate their dependent symbols - sym.user_value = None - sym._invalidate() + sym.unset_value() for choice in self._choices: - choice.user_value = choice.user_selection = None - choice._invalidate() + choice.unset_value() def enable_warnings(self): """ @@ -2187,6 +2215,7 @@ class Symbol(object): "_cached_tri_val", "_cached_vis", "_dependents", + "_was_set", "_write_to_conf", "choice", "defaults", @@ -2482,21 +2511,69 @@ class Symbol(object): BOOL) are ignored and won't be stored in Symbol.user_str/tri_value. Kconfiglib will print a warning by default for invalid assignments. """ - self._set_value_no_invalidate(value, False) + if value == self.user_value: + # We know the value must be valid if it was successfully set + # previously + self._was_set = True + return - if self is self.kconfig.modules: - # Changing MODULES has wide-ranging effects - self.kconfig._invalidate_all() + # Check if the value is valid for our type + if not ((self.orig_type == BOOL and value in (0, 2) ) or + (self.orig_type == TRISTATE and value in (0, 1, 2) ) or + (self.orig_type == STRING and isinstance(value, str)) or + (self.orig_type == INT and isinstance(value, str) + and _is_base_n(value, 10) ) or + (self.orig_type == HEX and isinstance(value, str) + and _is_base_n(value, 16))): + + warning = "the value '{}' is invalid for {}, which has type {}" \ + .format(value, self.name, TYPE_TO_STR[self.orig_type]) + + if self.orig_type in (BOOL, TRISTATE) and \ + value in ("n", "m", "y"): + warning += ' (pass 0, 1, 2 for n, m, y, respectively)' + + self.kconfig._warn(warning) + + return + + if not self.nodes: + self.kconfig._warn_undef_assign( + "{} is constant or undefined. '{}' assignment ignored." + .format(self.name, value)) + return + + # Assignments to promptless symbols are expected when loading a .config + if not self.kconfig._loading_config: + for node in self.nodes: + if node.prompt is not None: + break + else: + self.kconfig._warn("{} has no prompt. '{}' assignment ignored." + .format(self.name, value)) + return + + if self.choice is not None and value == 2: + # Remember this as a choice selection only. Makes switching back + # and forth between choice modes work as expected, and makes the + # check for whether the user value is the same as before above + # safe. + self.choice.user_selection = self + self.choice._rec_invalidate() + self.choice._was_set = True else: + self.user_value = value self._rec_invalidate() + self._was_set = True def unset_value(self): """ Resets the user value of the symbol, as if the symbol had never gotten a user value via Kconfig.load_config() or Symbol.set_value(). """ - self.user_value = None - self._rec_invalidate() + if self.user_value is not None: + self.user_value = None + self._rec_invalidate() def __repr__(self): """ @@ -2618,6 +2695,8 @@ class Symbol(object): self.env_var = None self.is_allnoconfig_y = False + self._was_set = False + # Should the symbol get an entry in .config? Calculated along with the # value. self._write_to_conf = False @@ -2665,55 +2744,6 @@ class Symbol(object): return (1,) - def _set_value_no_invalidate(self, value, suppress_prompt_warning): - """ - Like set_value(), but does not invalidate any symbols. - - suppress_prompt_warning: - The warning about assigning a value to a promptless symbol gets - spammy for Linux defconfigs, so turn it off when loading .configs. - It's still helpful when manually invoking set_value(). - """ - # Check if the value is valid for our type - if not ((self.orig_type == BOOL and value in (0, 2) ) or - (self.orig_type == TRISTATE and value in (0, 1, 2) ) or - (self.orig_type == STRING and isinstance(value, str)) or - (self.orig_type == INT and isinstance(value, str) - and _is_base_n(value, 10) ) or - (self.orig_type == HEX and isinstance(value, str) - and _is_base_n(value, 16))): - - warning = "the value '{}' is invalid for {}, which has type {}" \ - .format(value, self.name, TYPE_TO_STR[self.orig_type]) - - if self.orig_type in (BOOL, TRISTATE) and \ - value in ("n", "m", "y"): - warning += ' (pass 0, 1, 2 for n, m, y, respectively)' - - self.kconfig._warn(warning) - - return - - if not self.nodes: - self.kconfig._warn_undef_assign( - 'assigning the value "{}" to the undefined symbol {} will ' - "have no effect".format(value, self.name)) - - if not suppress_prompt_warning: - for node in self.nodes: - if node.prompt is not None: - break - else: - self.kconfig._warn('assigning the value "{}" to the ' - "promptless symbol {} will have no effect" - .format(value, self.name)) - - self.user_value = value - - if self.choice is not None and value == 2: - self.choice.user_selection = self - self.choice._rec_invalidate() - def _invalidate(self): """ Marks the symbol as needing to be recalculated. @@ -2725,10 +2755,10 @@ class Symbol(object): """ Invalidates the symbol and all items that (possibly) depend on it. """ - # 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: + if self is self.kconfig.modules: + # Invalidating MODULES has wide-ranging effects + self.kconfig._invalidate_all() + else: self._invalidate() for item in self._dependents: @@ -2892,6 +2922,7 @@ class Choice(object): "_cached_selection", "_cached_vis", "_dependents", + "_was_set", "defaults", "is_constant", "is_optional", @@ -3015,6 +3046,12 @@ class Choice(object): attribute (is_optional) can never be in n mode, but 0 is still accepted (and ignored) since it's not a malformed value. """ + if value == self.user_value: + # We know the value must be valid if it was successfully set + # previously + self._was_set = True + return + if not ((self.orig_type == BOOL and value in (0, 2) ) or (self.orig_type == TRISTATE and value in (0, 1, 2))): self.kconfig._warn("the value '{}' is invalid for the choice, " @@ -3024,14 +3061,16 @@ class Choice(object): self.user_value = value self._rec_invalidate() + self._was_set = True def unset_value(self): """ Resets the user value (mode) and user selection of the Choice, as if the user had never touched the mode or any of the choice symbols. """ - self.user_value = self.user_selection = None - self._rec_invalidate() + if self.user_value is not None or self.user_selection is not None: + self.user_value = self.user_selection = None + self._rec_invalidate() def __repr__(self): """ diff --git a/tests/Kmisc b/tests/Kmisc index c3a21f8..cea3ca9 100644 --- a/tests/Kmisc +++ b/tests/Kmisc @@ -39,13 +39,13 @@ config BOOL bool "bool" if NOT_DEFINED_1 config TRISTATE - tristate # Visibility should not affect user value + tristate "A" config STRING string "string" config INT - int # Visibility should not affect user value + int "INT" config HEX hex "hex" -- cgit v1.2.3 From 57e5a8eb6d6ff0a393116d5471f720cc1af33f88 Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Thu, 2 Nov 2017 09:41:36 +0100 Subject: Always save user values if they're valid Can just skip the invalidation for promptless symbols. Makes things less magic and more intuitive while still being fast. Means no docs need to be rewritten too. Now the warning gets printed for unset_value() as well. --- kconfiglib.py | 76 +++++++++++++++++++++++++++++++++-------------------------- tests/Kmisc | 4 ++-- testsuite.py | 4 ++-- 3 files changed, 47 insertions(+), 37 deletions(-) (limited to 'tests') diff --git a/kconfiglib.py b/kconfiglib.py index 32a4041..8bb8957 100644 --- a/kconfiglib.py +++ b/kconfiglib.py @@ -420,11 +420,11 @@ class Kconfig(object): """ __slots__ = ( "_choices", - "_loading_config", "_print_undef_assign", "_print_warnings", "_set_re_match", "_unset_re_match", + "_warn_no_prompt", "config_prefix", "const_syms", "defconfig_list", @@ -584,7 +584,7 @@ class Kconfig(object): # Build Symbol._dependents for all symbols self._build_dep() - self._loading_config = False + self._warn_no_prompt = False @property def mainmenu_text(self): @@ -627,14 +627,15 @@ class Kconfig(object): True if all existing user values should be cleared before loading the .config. """ - # Are we currently loading a .config file? This disables a warning. - self._loading_config = True + # Disable the warning about assigning to symbols without prompts. This + # is normal and expected within a .config file. + self._warn_no_prompt = False - # This stub only exists to make sure _loading_config gets unset + # This stub only exists to make sure _warn_no_prompt gets reenabled try: self._load_config(filename, replace) finally: - self._loading_config = False + self._warn_no_prompt = True def _load_config(self, filename, replace): with self._open(filename) as f: @@ -821,14 +822,18 @@ class Kconfig(object): Resets the user values of all symbols, as if Kconfig.load_config() or Symbol.set_value() had never been called. """ - # set_value() already rejects undefined symbols, and they don't need to - # be invalidated (because their value never changes), so we can just - # iterate over defined symbols - for sym in self.defined_syms: - sym.unset_value() + self._warn_no_prompt = False + try: + # set_value() already rejects undefined symbols, and they don't + # need to be invalidated (because their value never changes), so we + # can just iterate over defined symbols + for sym in self.defined_syms: + sym.unset_value() - for choice in self._choices: - choice.unset_value() + for choice in self._choices: + choice.unset_value() + finally: + self._warn_no_prompt = True def enable_warnings(self): """ @@ -2537,35 +2542,20 @@ class Symbol(object): return - if not self.nodes: - self.kconfig._warn_undef_assign( - "{} is constant or undefined. '{}' assignment ignored." - .format(self.name, value)) - return - - for node in self.nodes: - if node.prompt is not None: - break - else: - # Assignments to promptless symbols are expected when loading a - # .config - if not self.kconfig._loading_config: - self.kconfig._warn("{} has no prompt. '{}' assignment ignored." - .format(self.name, value)) - return - if self.choice is not None and value == 2: # Remember this as a choice selection only. Makes switching back # and forth between choice modes work as expected, and makes the # check for whether the user value is the same as before above # safe. self.choice.user_selection = self - self.choice._rec_invalidate() self.choice._was_set = True + if self._is_user_assignable(): + self.choice._rec_invalidate() else: self.user_value = value - self._rec_invalidate() self._was_set = True + if self._is_user_assignable(): + self._rec_invalidate() def unset_value(self): """ @@ -2574,7 +2564,8 @@ class Symbol(object): """ if self.user_value is not None: self.user_value = None - self._rec_invalidate() + if self._is_user_assignable(): + self._rec_invalidate() def __repr__(self): """ @@ -2745,6 +2736,25 @@ class Symbol(object): return (1,) + def _is_user_assignable(self): + """ + Returns True if the symbol has a prompt, meaning a user value might + have an effect on it. Used as an optimization to skip invalidation when + promptless symbols are assigned to (given a user value). + + Prints a warning if the symbol has no prompt. In some contexts (e.g. + when loading a .config files) assignments to promptless symbols are + normal and expected, so the warning can be disabled. + """ + for node in self.nodes: + if node.prompt is not None: + return True + + if self.kconfig._warn_no_prompt: + self.kconfig._warn(self.name + " has no prompt, meaning user " + "values have no effect on it") + return False + def _invalidate(self): """ Marks the symbol as needing to be recalculated. diff --git a/tests/Kmisc b/tests/Kmisc index cea3ca9..c3a21f8 100644 --- a/tests/Kmisc +++ b/tests/Kmisc @@ -39,13 +39,13 @@ config BOOL bool "bool" if NOT_DEFINED_1 config TRISTATE - tristate "A" + tristate # Visibility should not affect user value config STRING string "string" config INT - int "INT" + int # Visibility should not affect user value config HEX hex "hex" diff --git a/testsuite.py b/testsuite.py index 4cfc245..586899a 100644 --- a/testsuite.py +++ b/testsuite.py @@ -1933,11 +1933,11 @@ def test_sanity(conf, arch): conf.disable_warnings() sym.set_value(2) sym.set_value("foo") + sym.unset_value() conf.enable_warnings() sym.str_value sym.tri_value sym.type - sym.unset_value() sym.user_value sym.visibility @@ -1971,11 +1971,11 @@ def test_sanity(conf, arch): conf.disable_warnings() sym.set_value(2) sym.set_value("foo") + sym.unset_value() conf.enable_warnings() sym.str_value sym.tri_value sym.type - sym.unset_value() sym.visibility # Cheat with internals -- cgit v1.2.3 From e388f85764dcc6ab87b256e4088b4be918e02c1f Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Thu, 2 Nov 2017 19:46:11 +0100 Subject: Get rid of separate is_optional test The choice semantics tests already verify the behavior of optional choices. Just print an optional choice instead to get some coverage for querying it. Do minor cleanup elsewhere. --- tests/Kstr | 1 + testsuite.py | 30 +++++++----------------------- 2 files changed, 8 insertions(+), 23 deletions(-) (limited to 'tests') diff --git a/tests/Kstr b/tests/Kstr index e591792..d792f08 100644 --- a/tests/Kstr +++ b/tests/Kstr @@ -74,4 +74,5 @@ endchoice choice tristate "no name" + optional endchoice diff --git a/testsuite.py b/testsuite.py index 4721349..b5c00ff 100644 --- a/testsuite.py +++ b/testsuite.py @@ -584,6 +584,7 @@ choice CHOICE choice tristate prompt "no name" + optional """) @@ -1052,7 +1053,6 @@ g verify_value("INACTIVE_RANGE", "2") verify_value("ACTIVE_RANGE", "1") - # TODO: test symbol references in some other way? # TODO: test selects in some other way? # TODO: test implies in some other way? @@ -1096,9 +1096,6 @@ g verify(c.defconfig_filename == "Kconfiglib/tests/sub/defconfig_in_sub", "defconfig_filename gave wrong file with $srctree set") - # - # mainmenu_text - # print("Testing mainmenu_text...") @@ -1112,29 +1109,18 @@ g verify(c.mainmenu_text == "---bar baz---", "Wrong mainmenu text") - # - # Misc. minor APIs - # - - os.environ["ENV_VAR"] = "foo" - # Contains reference to undefined environment variable, so disable warnings - c = Kconfig("Kconfiglib/tests/Kmisc", warn=False) - - print("Testing is_optional...") - - verify(not get_choices(c)[0].is_optional, - "First choice should not be optional") - verify(get_choices(c)[1].is_optional, - "Second choice should be optional") print("Testing user_value...") + # References undefined env. var. Disable warnings. + c = Kconfig("Kconfiglib/tests/Kmisc", warn=False) + # Avoid warnings from assigning invalid user values and assigning user # values to symbols without prompts c.disable_warnings() - syms = [c.syms[name] for name in \ - ("BOOL", "TRISTATE", "STRING", "INT", "HEX")] + syms = [c.syms[name] for name in + "BOOL", "TRISTATE", "STRING", "INT", "HEX"] for sym in syms: verify(sym.user_value is None, @@ -1183,6 +1169,7 @@ g verify(not c.syms[name].nodes, "{} should not be defined".format(name)) + print("Testing Symbol.choice...") for name in "A", "B", "C", "D": @@ -1211,9 +1198,6 @@ g ur.env_var == "", "UNAME_RELEASE has wrong fields") - # - # .config reading and writing - # print("Testing .config reading and writing...") -- cgit v1.2.3 From 72e7786599386ab2492ef06f1c2b72447addba45 Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Thu, 2 Nov 2017 20:01:24 +0100 Subject: Clean up relation test Think those variables got used in other places before... Fetch the choices by name. Also dedotdotdot all messages for consistency. --- tests/Krelation | 4 ++-- testsuite.py | 50 +++++++++++++++++++++----------------------------- 2 files changed, 23 insertions(+), 31 deletions(-) (limited to 'tests') diff --git a/tests/Krelation b/tests/Krelation index 420152f..940eff8 100644 --- a/tests/Krelation +++ b/tests/Krelation @@ -2,7 +2,7 @@ config A bool depends on UNDEFINED -choice +choice CHOICE_1 bool "C" config B bool "B" @@ -18,7 +18,7 @@ config E menu "m2" config F bool -choice +choice CHOICE_2 tristate "foo" config G bool "g" diff --git a/testsuite.py b/testsuite.py index b5c00ff..156a640 100644 --- a/testsuite.py +++ b/testsuite.py @@ -904,41 +904,33 @@ g assign_and_verify("HEX_m", "0x123") - print("Testing object relations...") + print("Testing object relations") c = Kconfig("Kconfiglib/tests/Krelation") - A, B, C, D, E, F, G, H, I = \ - c.syms["A"], c.syms["B"], c.syms["C"], c.syms["D"], c.syms["E"], \ - c.syms["F"], c.syms["G"], c.syms["H"], c.syms["I"] - choice_1, choice_2 = get_choices(c) - - verify(A.nodes[0].parent is c.top_node, + verify(c.syms["A"].nodes[0].parent is c.top_node, "A's parent should be the top node") - verify(B.nodes[0].parent.item is choice_1, + verify(c.syms["B"].nodes[0].parent.item is c.named_choices["CHOICE_1"], "B's parent should be the first choice") - verify(C.nodes[0].parent.item is B, + verify(c.syms["C"].nodes[0].parent.item is c.syms["B"], "C's parent should be B (due to auto menus)") - verify(E.nodes[0].parent.item == MENU, + verify(c.syms["E"].nodes[0].parent.item == MENU, "E's parent should be a menu") - verify(E.nodes[0].parent.parent is c.top_node, + verify(c.syms["E"].nodes[0].parent.parent is c.top_node, "E's grandparent should be the top node") - verify(G.nodes[0].parent.item is choice_2, + verify(c.syms["G"].nodes[0].parent.item is c.named_choices["CHOICE_2"], "G's parent should be the second choice") - verify(G.nodes[0].parent.parent.item == MENU, + verify(c.syms["G"].nodes[0].parent.parent.item == MENU, "G's grandparent should be a menu") - # - # hex/int ranges - # - print("Testing hex/int ranges...") + print("Testing hex/int ranges") c = Kconfig("Kconfiglib/tests/Krange") @@ -1060,7 +1052,7 @@ g # defconfig_filename # - print("Testing defconfig_filename...") + print("Testing defconfig_filename") c = Kconfig("Kconfiglib/tests/empty") verify(c.defconfig_filename is None, @@ -1097,7 +1089,7 @@ g "defconfig_filename gave wrong file with $srctree set") - print("Testing mainmenu_text...") + print("Testing mainmenu_text") c = Kconfig("Kconfiglib/tests/empty") verify(c.mainmenu_text == "Linux Kernel Configuration", @@ -1110,7 +1102,7 @@ g "Wrong mainmenu text") - print("Testing user_value...") + print("Testing user_value") # References undefined env. var. Disable warnings. c = Kconfig("Kconfiglib/tests/Kmisc", warn=False) @@ -1157,7 +1149,7 @@ g "{} should not have a user value after being reset". format(s.name)) - print("Testing defined vs undefined symbols...") + print("Testing defined vs undefined symbols") for name in "A", "B", "C", "D", "BOOL", "TRISTATE", "STRING", "INT", "HEX": verify(c.syms[name].nodes, @@ -1170,7 +1162,7 @@ g "{} should not be defined".format(name)) - print("Testing Symbol.choice...") + print("Testing Symbol.choice") for name in "A", "B", "C", "D": verify(c.syms[name].choice is not None, @@ -1182,14 +1174,14 @@ g verify(c.syms[name].choice is None, "{} should not be a choice symbol".format(name)) - print("Testing is_allnoconfig_y...") + print("Testing is_allnoconfig_y") verify(not c.syms["NOT_ALLNOCONFIG_Y"].is_allnoconfig_y, "NOT_ALLNOCONFIG_Y should not be allnoconfig_y") verify(c.syms["ALLNOCONFIG_Y"].is_allnoconfig_y, "ALLNOCONFIG_Y should be allnoconfig_y") - print("Testing UNAME_RELEASE...") + print("Testing UNAME_RELEASE") verify_value("UNAME_RELEASE", platform.uname()[2]) ur = c.syms["UNAME_RELEASE"] @@ -1199,7 +1191,7 @@ g "UNAME_RELEASE has wrong fields") - print("Testing .config reading and writing...") + print("Testing .config reading and writing") config_test_file = "Kconfiglib/tests/config_test" @@ -1269,7 +1261,7 @@ g verify_value("IGNOREME", "y") - print("Testing Kconfig separation...") + print("Testing Kconfig separation") c1 = Kconfig("Kconfiglib/tests/Kmisc", warn=False) c2 = Kconfig("Kconfiglib/tests/Kmisc", warn=False) @@ -1292,7 +1284,7 @@ g "Config instance state separation or .config is broken") - print("Testing imply semantics...") + print("Testing imply semantics") c = Kconfig("Kconfiglib/tests/Kimply") @@ -1387,7 +1379,7 @@ g assign_and_verify("IMPLIED_BOOL", 2) - print("Testing choice semantics...") + print("Testing choice semantics") c = Kconfig("Kconfiglib/tests/Kchoice") @@ -1559,7 +1551,7 @@ g verify_is_normal_choice_symbol("WS9") - print("Testing compatibility with weird selects/implies...") + print("Testing compatibility with weird selects/implies") # Check that Kconfiglib doesn't crash for stuff like 'select n' (seen in # U-Boot). These probably originate from misunderstandings of how Kconfig -- cgit v1.2.3 From 852eae7d41abed9051f72d0ba72bfb854cfb6fcb Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Thu, 2 Nov 2017 20:36:41 +0100 Subject: Clean up .kconfig tests Kinda silly to test if they're separate since a long time, but can do that easily too with some reorganization. --- tests/Kmisc | 3 +++ testsuite.py | 33 ++++++++++++--------------------- 2 files changed, 15 insertions(+), 21 deletions(-) (limited to 'tests') diff --git a/tests/Kmisc b/tests/Kmisc index c3a21f8..44fdfdc 100644 --- a/tests/Kmisc +++ b/tests/Kmisc @@ -51,7 +51,10 @@ config HEX hex "hex" depends on NOT_DEFINED_2 +config COMMENT_HOOK comment "comment" + +config MENU_HOOK menu "menu" depends on NOT_DEFINED_3 || NOT_DEFINED_2 depends on !NOT_DEFINED_4 diff --git a/testsuite.py b/testsuite.py index 156a640..3afa66a 100644 --- a/testsuite.py +++ b/testsuite.py @@ -1261,27 +1261,18 @@ g verify_value("IGNOREME", "y") - print("Testing Kconfig separation") - - c1 = Kconfig("Kconfiglib/tests/Kmisc", warn=False) - c2 = Kconfig("Kconfiglib/tests/Kmisc", warn=False) - - c1_undef, c1_bool, c1_choice, c1_menu, c1_comment = c1.syms["BOOL"], \ - c1.syms["NOT_DEFINED_1"], get_choices(c1)[0], get_menus(c1)[0], \ - get_comments(c1)[0] - c2_undef, c2_bool, c2_choice, c2_menu, c2_comment = c2.syms["BOOL"], \ - c2.syms["NOT_DEFINED_1"], get_choices(c2)[0], get_menus(c2)[0], \ - get_comments(c2)[0] - - verify((c1_undef is not c2_undef) and (c1_bool is not c2_bool) and - (c1_choice is not c2_choice) and (c1_menu is not c2_menu) and - (c1_comment is not c2_comment) and - (c1_undef.kconfig is c1) and (c2_undef.kconfig is c2) and - (c1_bool.kconfig is c1) and (c2_bool.kconfig is c2) and - (c1_choice.kconfig is c1) and (c2_choice.kconfig is c2) and - (c1_menu.kconfig is c1) and (c2_menu.kconfig is c2) and - (c1_comment.kconfig is c1) and (c2_comment.kconfig is c2), - "Config instance state separation or .config is broken") + print("Testing Kconfig fetching and separation") + + for c in Kconfig("Kconfiglib/tests/Kmisc", warn=False), \ + Kconfig("Kconfiglib/tests/Kmisc", warn=False): + for item in c.syms["BOOL"], \ + c.syms["BOOL"].nodes[0], \ + c.named_choices["OPTIONAL"], \ + c.named_choices["OPTIONAL"].nodes[0], \ + c.syms["MENU_HOOK"].nodes[0].next, \ + c.syms["COMMENT_HOOK"].nodes[0].next: + verify(item.kconfig is c, + ".kconfig not properly set for " + repr(item)) print("Testing imply semantics") -- cgit v1.2.3 From d4634ba8f0d6d53872b0a744fee9111d55334550 Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Thu, 2 Nov 2017 23:32:26 +0100 Subject: Clean up choice semantics tests Can finally get rid of get_choices() and get_items() now. Piggyback some more Kwtf tests, and remove some outdated comments. There's already plenty of select/imply testing. --- tests/Kwtf | 10 +++++ testsuite.py | 124 +++++++++++++++++++++++++---------------------------------- 2 files changed, 63 insertions(+), 71 deletions(-) (limited to 'tests') diff --git a/tests/Kwtf b/tests/Kwtf index c71e328..85ae57e 100644 --- a/tests/Kwtf +++ b/tests/Kwtf @@ -3,6 +3,16 @@ config A select n select m select y + select UNAME_RELEASE + select "n" + select "m" + select "y" + select "UNAME_RELEASE" imply n imply m imply y + imply UNAME_RELEASE + imply "n" + imply "m" + imply "y" + imply "UNAME_RELEASE" diff --git a/testsuite.py b/testsuite.py index 87914e7..cfaebfc 100644 --- a/testsuite.py +++ b/testsuite.py @@ -104,34 +104,14 @@ def run_tests(): run_selftests() run_compatibility_tests() -def get_items(config, type_): - items = [] - def rec(node): - if node is not None: - if isinstance(node.item, type_): - items.append(node.item) - rec(node.list) - rec(node.next) - rec(config.top_node) - return items - -def get_choices(config): - choices = get_items(config, Choice) - unique_choices = [] - for choice in choices: - if choice not in unique_choices: - unique_choices.append(choice) - return unique_choices - -STR_TO_TRI = {"n": 0, "m": 1, "y": 2} -TRI_TO_STR = {0: "n", 1: "m", 2: "y"} - def run_selftests(): # # Common helper functions. These all expect 'c' to hold the current # configuration. # + TRI_TO_STR = {0: "n", 1: "m", 2: "y"} + def verify_value(sym_name, val): """ Verifies that a symbol has a particular value. @@ -436,7 +416,7 @@ def run_selftests(): pass else: fail('expected eval_string("{}") to throw KconfigSyntaxError, ' \ - 'didn\'t'.format(expr)) + "didn't".format(expr)) # The C implementation's parser can be pretty lax about syntax. Kconfiglib # sometimes needs to emulate that. Verify that some bad stuff throws @@ -954,6 +934,7 @@ g that assigning values outside this range reverts the value back to 'default' (None if it should revert back to "").""" is_hex = (c.syms[sym_name].type == HEX) + for i in range(low, high + 1): assign_and_verify_user_value(sym_name, str(i), str(i)) if is_hex: @@ -1016,9 +997,6 @@ g verify_value("INACTIVE_RANGE", "2") verify_value("ACTIVE_RANGE", "1") - # TODO: test selects in some other way? - # TODO: test implies in some other way? - # # defconfig_filename # @@ -1345,20 +1323,13 @@ g c = Kconfig("Kconfiglib/tests/Kchoice") - choice_bool, choice_bool_opt, choice_tristate, choice_tristate_opt, \ - choice_bool_m, choice_tristate_m, choice_defaults, \ - choice_defaults_not_visible, choice_no_type_bool, \ - choice_no_type_tristate, choice_missing_member_type_1, \ - choice_missing_member_type_2, choice_weird_syms = get_choices(c) - - for choice in choice_bool, choice_bool_opt, choice_bool_m, choice_defaults: - verify(choice.type == BOOL, - "choice {} should have type bool".format(choice.name)) + for name in "BOOL", "BOOL_OPT", "BOOL_M", "DEFAULTS": + verify(c.named_choices[name].orig_type == BOOL, + "choice {} should have type bool".format(name)) - for choice in choice_tristate, choice_tristate_opt, choice_tristate_m: - verify(choice.orig_type == TRISTATE, - "choice {} should have type tristate" - .format(choice.name)) + for name in "TRISTATE", "TRISTATE_OPT", "TRISTATE_M": + verify(c.named_choices[name].orig_type == TRISTATE, + "choice {} should have type tristate".format(name)) def select_and_verify(sym): choice = sym.nodes[0].parent.item @@ -1385,7 +1356,9 @@ g verify(sibling.tri_value == 0, sibling.name + " should be n when not selected") - def select_and_verify_all(choice): + def select_and_verify_all(choice_name): + choice = c.named_choices[choice_name] + # Select in forward order for sym in choice.syms: select_and_verify(sym) @@ -1394,7 +1367,9 @@ g for sym in reversed(choice.syms): select_and_verify(sym) - def verify_mode(choice, no_modules_mode, modules_mode): + def verify_mode(choice_name, no_modules_mode, modules_mode): + choice = c.named_choices[choice_name] + c.modules.set_value(0) verify(choice.tri_value == no_modules_mode, 'Wrong mode for choice {} with no modules. Expected {}, got {}.' @@ -1405,26 +1380,31 @@ g 'Wrong mode for choice {} with modules. Expected {}, got {}.' .format(choice.name, modules_mode, choice.tri_value)) - verify_mode(choice_bool, 2, 2) - verify_mode(choice_bool_opt, 0, 0) - verify_mode(choice_tristate, 2, 1) - verify_mode(choice_tristate_opt, 0, 0) - verify_mode(choice_bool_m, 0, 2) - verify_mode(choice_tristate_m, 0, 1) + verify_mode("BOOL", 2, 2) + verify_mode("BOOL_OPT", 0, 0) + verify_mode("TRISTATE", 2, 1) + verify_mode("TRISTATE_OPT", 0, 0) + verify_mode("BOOL_M", 0, 2) + verify_mode("TRISTATE_M", 0, 1) # Test defaults + choice = c.named_choices["DEFAULTS"] + c.syms["TRISTATE_SYM"].set_value(0) - verify(choice_defaults.selection is c.syms["OPT_4"], + verify(choice.selection is c.syms["OPT_4"], "Wrong choice default with TRISTATE_SYM = n") + c.syms["TRISTATE_SYM"].set_value(2) - verify(choice_defaults.selection is c.syms["OPT_2"], + verify(choice.selection is c.syms["OPT_2"], "Wrong choice default with TRISTATE_SYM = y") + c.syms["OPT_1"].set_value(2) - verify(choice_defaults.selection is c.syms["OPT_1"], + verify(choice.selection is c.syms["OPT_1"], "User selection should override defaults") - verify(choice_defaults_not_visible.selection is c.syms["OPT_8"], + verify(c.named_choices["DEFAULTS_NOT_VISIBLE"].selection + is c.syms["OPT_8"], "Non-visible choice symbols should cause the next default to be " "considered") @@ -1432,34 +1412,34 @@ g c.modules.set_value(2) - select_and_verify_all(choice_bool) - select_and_verify_all(choice_bool_opt) - select_and_verify_all(choice_tristate) - select_and_verify_all(choice_tristate_opt) + select_and_verify_all("BOOL") + select_and_verify_all("BOOL_OPT") + select_and_verify_all("TRISTATE") + select_and_verify_all("TRISTATE_OPT") # For BOOL_M, the mode should have been promoted - select_and_verify_all(choice_bool_m) + select_and_verify_all("BOOL_M") # Test m mode selection - choice_tristate.set_value(1) + c.named_choices["TRISTATE"].set_value(1) assign_and_verify_value("T_1", 1, 1) assign_and_verify_value("T_2", 1, 1) c.syms["T_1"].set_value(0) # Check that this is remembered later # Switching to y mode should cause T_1 to become selected - choice_tristate.set_value(2) + c.named_choices["TRISTATE"].set_value(2) verify_value("T_1", 2) verify_value("T_2", 0) # Switching back to m mode should restore the old values - choice_tristate.set_value(1) + c.named_choices["TRISTATE"].set_value(1) verify_value("T_1", 0) verify_value("T_2", 1) assign_and_verify_value("TM_1", 1, 1) assign_and_verify_value("TM_1", 2, 1) # Ignored - verify(choice_tristate_m.tri_value == 1, + verify(c.named_choices["TRISTATE"].tri_value == 1, "m-visible choice got invalid mode") assign_and_verify_value("TM_1", 0, 0) @@ -1468,37 +1448,39 @@ g # Verify that choices with no explicitly specified type get the type of the # first contained symbol with a type - verify(choice_no_type_bool.orig_type == BOOL, + verify(c.named_choices["NO_TYPE_BOOL"].orig_type == BOOL, "Expected first choice without explicit type to have type bool") - verify(choice_no_type_tristate.orig_type == TRISTATE, + + verify(c.named_choices["NO_TYPE_TRISTATE"].orig_type == TRISTATE, "Expected second choice without explicit type to have type " "tristate") # Verify that symbols without a type in the choice get the type of the # choice - verify((c.syms["MMT_1"].orig_type, c.syms["MMT_2"].orig_type, - c.syms["MMT_3"].orig_type) == (BOOL, BOOL, TRISTATE), - "Wrong types for first choice with missing member types") + for name in "MMT_1", "MMT_2", "MMT_4", "MMT_5": + verify(c.syms[name].orig_type == BOOL, + "Expected {} to get type bool".format(name)) - verify((c.syms["MMT_4"].orig_type, c.syms["MMT_5"].orig_type) == - (BOOL, BOOL), - "Wrong types for second choice with missing member types") + verify(c.syms["MMT_3"].orig_type == TRISTATE, + "Expected MMT_3 to have type tristate") # Verify that symbols in choices that depend on the preceding symbol aren't # considered choice symbols + weird_choice = c.named_choices["WEIRD_SYMS"] + def verify_is_normal_choice_symbol(name): sym = c.syms[name] verify(sym.choice is not None and - sym in choice_weird_syms.syms and - sym.nodes[0].parent.item is choice_weird_syms, + sym in weird_choice.syms and + sym.nodes[0].parent.item is weird_choice, "{} should be a normal choice symbol".format(sym.name)) def verify_is_weird_choice_symbol(name): sym = c.syms[name] verify(sym.choice is None and - sym not in choice_weird_syms.syms, + sym not in weird_choice.syms, "{} should be a weird (non-)choice symbol" .format(sym.name)) -- cgit v1.2.3 From b59b618a0ce85632742ff92a5be2bab690a75e42 Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Fri, 3 Nov 2017 03:17:58 +0100 Subject: Add initial selftests for .assignable Comprehensive selftests are important here, because the allno/yesconfig.py scripts only check the upper and lower bound, and allnoconfig disables modules. Found a bug for non-selected m-visible tristates, where n didn't show up in sym.assignable. Everything matches menuconfig after fixing that. Still need to test symbols in choices with different modes, imply, and .assignable for choices. --- kconfiglib.py | 4 ++- tests/Kassignable | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ testsuite.py | 66 +++++++++++++++++++++++++++++++++- 3 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 tests/Kassignable (limited to 'tests') diff --git a/kconfiglib.py b/kconfiglib.py index 8bb8957..612fc58 100644 --- a/kconfiglib.py +++ b/kconfiglib.py @@ -2726,8 +2726,10 @@ class Symbol(object): # vis == 1 + # Must be a tristate here, because bool m visibility gets promoted to y + if not rev_dep_val: - return (1,) if expr_value(self.weak_rev_dep) != 2 else (2,) + return (0, 1) if expr_value(self.weak_rev_dep) != 2 else (0, 2) if rev_dep_val == 2: return (2,) diff --git a/tests/Kassignable b/tests/Kassignable new file mode 100644 index 0000000..97cb322 --- /dev/null +++ b/tests/Kassignable @@ -0,0 +1,105 @@ +config MODULES + bool "modules" + option modules + + +# Things that should never be .assignable + +if UNDEFINED && "const" +endif + +config NO_PROMPT + +config STRING + string "string" + +config INT + int "int" + +config HEX + hex "hex" + + +# Non-selected symbols + +config Y_VIS_BOOL + bool "y-vis bool" + +config M_VIS_BOOL + bool "m-vis bool" if m + +config N_VIS_BOOL + bool "n-vis bool" if n + +config Y_VIS_TRI + tristate "y-vis tri" + +config M_VIS_TRI + tristate "m-vis tri" if m + +config N_VIS_TRI + tristate "n-vis tri" if n + + +# Symbols selected to y + +config Y_SELECTOR + def_tristate y + + select Y_SEL_Y_VIS_BOOL + select Y_SEL_M_VIS_BOOL + select Y_SEL_N_VIS_BOOL + + select Y_SEL_Y_VIS_TRI + select Y_SEL_M_VIS_TRI + select Y_SEL_N_VIS_TRI + +config Y_SEL_Y_VIS_BOOL + bool "y-sel y-vis bool" + +config Y_SEL_M_VIS_BOOL + bool "y-sel m-vis bool" if m + +config Y_SEL_N_VIS_BOOL + bool "y-sel n-vis bool" if n + +config Y_SEL_Y_VIS_TRI + tristate "y-sel y-vis tri" + +config Y_SEL_M_VIS_TRI + bool "y-sel m-vis tri" if m + +config Y_SEL_N_VIS_TRI + bool "y-sel n-vis tri" if n + + +# Symbols selected to m + +config M_SELECTOR + def_tristate m + + select M_SEL_Y_VIS_BOOL + select M_SEL_M_VIS_BOOL + select M_SEL_N_VIS_BOOL + + select M_SEL_Y_VIS_TRI + select M_SEL_M_VIS_TRI + select M_SEL_N_VIS_TRI + +config M_SEL_Y_VIS_BOOL + bool "m-sel y-vis bool" + +config M_SEL_M_VIS_BOOL + bool "m-sel m-vis bool" if m + +config M_SEL_N_VIS_BOOL + bool "m-sel n-vis bool" if n + +config M_SEL_Y_VIS_TRI + tristate "m-sel y-vis tri" + +config M_SEL_M_VIS_TRI + tristate "m-sel m-vis tri" if m + +config M_SEL_N_VIS_TRI + tristate "m-sel n-vis tri" if n diff --git a/testsuite.py b/testsuite.py index e750cbf..11d3ef6 100644 --- a/testsuite.py +++ b/testsuite.py @@ -415,7 +415,7 @@ def run_selftests(): except KconfigSyntaxError: pass else: - fail('expected eval_string("{}") to throw KconfigSyntaxError, ' \ + fail('expected eval_string("{}") to throw KconfigSyntaxError, ' "didn't".format(expr)) # The C implementation's parser can be pretty lax about syntax. Kconfiglib @@ -855,6 +855,70 @@ g assign_and_verify("HEX_m", "0x123") + print("Testing .assignable") + + c = Kconfig("Kconfiglib/tests/Kassignable") + + def verify_assignable_imp(item, assignable): + verify(item.assignable == assignable, + "Incorrect assignable values for {}. " + "Should be {}, was {}." + .format(item.name, assignable, item.assignable)) + + # Verify that the values can actually be assigned too + for val in item.assignable: + item.set_value(val) + verify(item.tri_value == val, + "Unable to set {} to {}, even though " + "it was in .assignable" + .format(item.name, val)) + + def verify_assignable(sym_name, assignable): + verify_assignable_imp(c.syms[sym_name], assignable) + + def verify_const_unassignable(sym_name): + verify_assignable_imp(c.const_syms[sym_name], ()) + + # Test with modules enabled first + c.modules.set_value(2) + + # Things that shouldn't be .assignable + verify_const_unassignable("n") + verify_const_unassignable("m") + verify_const_unassignable("y") + verify_const_unassignable("const") + verify_const_unassignable("UNAME_RELEASE") + verify_assignable("UNDEFINED", ()) + verify_assignable("NO_PROMPT", ()) + verify_assignable("STRING", ()) + verify_assignable("INT", ()) + verify_assignable("HEX", ()) + + # Non-selected symbols + verify_assignable("Y_VIS_BOOL", (0, 2)) + verify_assignable("M_VIS_BOOL", (0, 2)) # Visibility promoted + verify_assignable("N_VIS_BOOL", ( )) + verify_assignable("Y_VIS_TRI", (0, 1, 2)) + verify_assignable("M_VIS_TRI", (0, 1 )) + verify_assignable("N_VIS_TRI", ( )) + + # Symbols selected to y + verify_assignable("Y_SEL_Y_VIS_BOOL", (2,)) + verify_assignable("Y_SEL_M_VIS_BOOL", (2,)) # Visibility promoted + verify_assignable("Y_SEL_N_VIS_BOOL", ( )) + verify_assignable("Y_SEL_Y_VIS_TRI", (2,)) + verify_assignable("Y_SEL_M_VIS_TRI", (2,)) + verify_assignable("Y_SEL_N_VIS_TRI", ( )) + + # Symbols selected to m + verify_assignable("M_SEL_Y_VIS_BOOL", ( 2,)) # Value promoted + verify_assignable("M_SEL_M_VIS_BOOL", ( 2,)) # Visibility/value promoted + verify_assignable("M_SEL_N_VIS_BOOL", ( )) + verify_assignable("M_SEL_Y_VIS_TRI", (1, 2 )) + verify_assignable("M_SEL_M_VIS_TRI", (1 ,)) + verify_assignable("M_SEL_N_VIS_TRI", ( )) + + print("Testing object relations") c = Kconfig("Kconfiglib/tests/Krelation") -- cgit v1.2.3 From b74cd303f763fbdc1307830b6333354d65733ef8 Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Fri, 3 Nov 2017 05:19:54 +0100 Subject: Test .assignable for imply, find C menuconfig bug A tristate implied to y can't be set to m. Other than that, imply doesn't affect assignable values. Fix some copy-paste type errors too. In the C menuconfig, a tristate with m visibility implied to y gets stuck if you change it with space. Look into that later. Test case: config MODULES def_bool y option modules config Y_IMPLIER def_tristate y imply Y_IMP_M_VIS_TRI config Y_IMP_M_VIS_TRI tristate "y-imp m-vis tri" if m --- tests/Kassignable | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- testsuite.py | 16 +++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/Kassignable b/tests/Kassignable index 97cb322..e600a39 100644 --- a/tests/Kassignable +++ b/tests/Kassignable @@ -67,10 +67,10 @@ config Y_SEL_Y_VIS_TRI tristate "y-sel y-vis tri" config Y_SEL_M_VIS_TRI - bool "y-sel m-vis tri" if m + tristate "y-sel m-vis tri" if m config Y_SEL_N_VIS_TRI - bool "y-sel n-vis tri" if n + tristate "y-sel n-vis tri" if n # Symbols selected to m @@ -103,3 +103,67 @@ config M_SEL_M_VIS_TRI config M_SEL_N_VIS_TRI tristate "m-sel n-vis tri" if n + + +# Symbols implied to y + +config Y_IMPLIER + def_tristate y + + imply Y_IMP_Y_VIS_BOOL + imply Y_IMP_M_VIS_BOOL + imply Y_IMP_N_VIS_BOOL + + imply Y_IMP_Y_VIS_TRI + imply Y_IMP_M_VIS_TRI + imply Y_IMP_N_VIS_TRI + +config Y_IMP_Y_VIS_BOOL + bool "y-imp y-vis bool" + +config Y_IMP_M_VIS_BOOL + bool "y-imp m-vis bool" if m + +config Y_IMP_N_VIS_BOOL + bool "y-imp n-vis bool" if n + +config Y_IMP_Y_VIS_TRI + tristate "y-imp y-vis tri" + +config Y_IMP_M_VIS_TRI + tristate "y-imp m-vis tri" if m + +config Y_IMP_N_VIS_TRI + tristate "y-imp n-vis tri" if n + + +# Symbols implied to m (never affects assignable values) + +config M_IMPLIER + def_tristate m + + imply M_IMP_Y_VIS_BOOL + imply M_IMP_M_VIS_BOOL + imply M_IMP_N_VIS_BOOL + + imply M_IMP_Y_VIS_TRI + imply M_IMP_M_VIS_TRI + imply M_IMP_N_VIS_TRI + +config M_IMP_Y_VIS_BOOL + bool "m-imp y-vis bool" + +config M_IMP_M_VIS_BOOL + bool "m-imp m-vis bool" if m + +config M_IMP_N_VIS_BOOL + bool "m-imp n-vis bool" if n + +config M_IMP_Y_VIS_TRI + tristate "m-imp y-vis tri" + +config M_IMP_M_VIS_TRI + tristate "m-imp m-vis tri" if m + +config M_IMP_N_VIS_TRI + tristate "m-imp n-vis tri" if n diff --git a/testsuite.py b/testsuite.py index 11d3ef6..17c7f9e 100644 --- a/testsuite.py +++ b/testsuite.py @@ -918,6 +918,22 @@ g verify_assignable("M_SEL_M_VIS_TRI", (1 ,)) verify_assignable("M_SEL_N_VIS_TRI", ( )) + # Symbols implied to y + verify_assignable("Y_IMP_Y_VIS_BOOL", (0, 2)) + verify_assignable("Y_IMP_M_VIS_BOOL", (0, 2)) # Visibility promoted + verify_assignable("Y_IMP_N_VIS_BOOL", ( )) + verify_assignable("Y_IMP_Y_VIS_TRI", (0, 2)) # m removed by imply + verify_assignable("Y_IMP_M_VIS_TRI", (0, 2)) # m promoted to y by imply + verify_assignable("Y_IMP_N_VIS_TRI", ( )) + + # Symbols implied to m (never affects assignable values) + verify_assignable("M_IMP_Y_VIS_BOOL", (0, 2)) + verify_assignable("M_IMP_M_VIS_BOOL", (0, 2)) # Visibility promoted + verify_assignable("M_IMP_N_VIS_BOOL", ( )) + verify_assignable("M_IMP_Y_VIS_TRI", (0, 1, 2)) # m removed by imply + verify_assignable("M_IMP_M_VIS_TRI", (0, 1 )) # m promoted to y by imply + verify_assignable("M_IMP_N_VIS_TRI", ( )) + print("Testing object relations") -- cgit v1.2.3 From d1ea825a1d9d8bfc9496926b6a800ad58581b09a Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Fri, 3 Nov 2017 06:13:23 +0100 Subject: Add .assignable selftests for choice symbols --- tests/Kassignable | 34 ++++++++++++++++++++++++++++++++++ testsuite.py | 44 ++++++++++++++++++++++++++++++++------------ 2 files changed, 66 insertions(+), 12 deletions(-) (limited to 'tests') diff --git a/tests/Kassignable b/tests/Kassignable index e600a39..fe88abe 100644 --- a/tests/Kassignable +++ b/tests/Kassignable @@ -167,3 +167,37 @@ config M_IMP_M_VIS_TRI config M_IMP_N_VIS_TRI tristate "m-imp n-vis tri" if n + + +# Symbols in y-mode choice + +choice Y_CHOICE + bool "y-mode choice" + +config Y_CHOICE_BOOL + bool "y-mode choice bool" + +config Y_CHOICE_TRISTATE + tristate "y-mode choice tristate" + +config Y_CHOICE_N_VIS_TRISTATE + tristate "y-mode choice tristate invisible" if n + +endchoice + + +# Symbols in m/y-mode choice + +choice MY_CHOICE + tristate "m/y-mode choice" + +config MY_CHOICE_BOOL + bool "m/y-mode choice bool" + +config MY_CHOICE_TRISTATE + tristate "m/y-mode choice tristate" + +config MY_CHOICE_N_VIS_TRISTATE + tristate "m/y-mode choice tristate invisible" if n + +endchoice diff --git a/testsuite.py b/testsuite.py index bd62c91..dd0fe7c 100644 --- a/testsuite.py +++ b/testsuite.py @@ -859,25 +859,28 @@ g c = Kconfig("Kconfiglib/tests/Kassignable") - def verify_assignable_imp(item, assignable): + def verify_assignable_imp(item, assignable, test_assign): verify(item.assignable == assignable, "Incorrect assignable values for {}. " "Should be {}, was {}." .format(item.name, assignable, item.assignable)) - # Verify that the values can actually be assigned too - for val in item.assignable: - item.set_value(val) - verify(item.tri_value == val, - "Unable to set {} to {}, even though " - "it was in .assignable" - .format(item.name, val)) + # Verify that the values can actually be assigned too, except for + # choices in y mode, where setting the user value to n doesn't change + # the value + if test_assign: + for val in item.assignable: + item.set_value(val) + verify(item.tri_value == val, + "Unable to set {} to {}, even though " + "it was in .assignable" + .format(item.name, val)) - def verify_assignable(sym_name, assignable): - verify_assignable_imp(c.syms[sym_name], assignable) + def verify_assignable(sym_name, assignable, test_assign=True): + verify_assignable_imp(c.syms[sym_name], assignable, test_assign) def verify_const_unassignable(sym_name): - verify_assignable_imp(c.const_syms[sym_name], ()) + verify_assignable_imp(c.const_syms[sym_name], (), False) # Test with modules enabled first c.modules.set_value(2) @@ -915,7 +918,7 @@ g verify_assignable("M_SEL_M_VIS_BOOL", ( 2,)) # Visibility/value promoted verify_assignable("M_SEL_N_VIS_BOOL", ( )) verify_assignable("M_SEL_Y_VIS_TRI", (1, 2 )) - verify_assignable("M_SEL_M_VIS_TRI", (1 ,)) + verify_assignable("M_SEL_M_VIS_TRI", (1, )) verify_assignable("M_SEL_N_VIS_TRI", ( )) # Symbols implied to y @@ -934,6 +937,23 @@ g verify_assignable("M_IMP_M_VIS_TRI", (0, 1 )) verify_assignable("M_IMP_N_VIS_TRI", ( )) + # Symbols in y-mode choice + verify_assignable("Y_CHOICE_BOOL", (0, 2), test_assign=False) + verify_assignable("Y_CHOICE_TRISTATE", (0, 2), test_assign=False) + verify_assignable("Y_CHOICE_N_VIS_TRISTATE", ( )) + + # Symbols in m/y-mode choice, starting out in m mode + verify_assignable("MY_CHOICE_BOOL", ( )) + verify_assignable("MY_CHOICE_TRISTATE", (0, 1)) + verify_assignable("MY_CHOICE_N_VIS_TRISTATE", ( )) + + c.named_choices["MY_CHOICE"].set_value(2) + + # Symbols in m/y-mode choice, now in y mode + verify_assignable("MY_CHOICE_BOOL", (0, 2), test_assign=False) + verify_assignable("MY_CHOICE_TRISTATE", (0, 2), test_assign=False) + verify_assignable("MY_CHOICE_N_VIS_TRISTATE", ( )) + print("Testing object relations") -- cgit v1.2.3 From de2e7f766f247d4e8701dcca9fc921f1d0230463 Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Fri, 3 Nov 2017 06:40:40 +0100 Subject: Test Choice.assignable, fix for optional choices Could never return 0 as a valid assignable value previously. --- kconfiglib.py | 2 +- tests/Kassignable | 26 ++++++++++++++++++++++++++ testsuite.py | 17 ++++++++++++++--- 3 files changed, 41 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/kconfiglib.py b/kconfiglib.py index 612fc58..ae86b2a 100644 --- a/kconfiglib.py +++ b/kconfiglib.py @@ -3190,7 +3190,7 @@ class Choice(object): if vis == 2: if not self.is_optional: return (2,) if self.type == BOOL else (1, 2) - return (2,) + return (0, 2) if self.type == BOOL else (0, 1, 2) # vis == 1 diff --git a/tests/Kassignable b/tests/Kassignable index fe88abe..f134a74 100644 --- a/tests/Kassignable +++ b/tests/Kassignable @@ -201,3 +201,29 @@ config MY_CHOICE_N_VIS_TRISTATE tristate "m/y-mode choice tristate invisible" if n endchoice + + +# Choices with some other possible modes + +choice NMY_CHOICE + tristate "n/m/y-mode choice" + optional +endchoice + +choice NY_CHOICE + bool "n/y-mode choice" + optional +endchoice + +choice NM_CHOICE + tristate "n/m-mode choice" if m + optional +endchoice + +choice M_CHOICE + tristate "m-mode choice" if m +endchoice + +choice N_CHOICE + tristate "n-mode choice" if n +endchoice diff --git a/testsuite.py b/testsuite.py index dd0fe7c..3abcbb0 100644 --- a/testsuite.py +++ b/testsuite.py @@ -879,12 +879,12 @@ g def verify_assignable(sym_name, assignable, test_assign=True): verify_assignable_imp(c.syms[sym_name], assignable, test_assign) - def verify_const_unassignable(sym_name): - verify_assignable_imp(c.const_syms[sym_name], (), False) - # Test with modules enabled first c.modules.set_value(2) + def verify_const_unassignable(sym_name): + verify_assignable_imp(c.const_syms[sym_name], (), False) + # Things that shouldn't be .assignable verify_const_unassignable("n") verify_const_unassignable("m") @@ -954,6 +954,17 @@ g verify_assignable("MY_CHOICE_TRISTATE", (0, 2), test_assign=False) verify_assignable("MY_CHOICE_N_VIS_TRISTATE", ( )) + def verify_choice_assignable(choice_name, assignable): + verify_assignable_imp(c.named_choices[choice_name], assignable, True) + + verify_choice_assignable("Y_CHOICE", ( 2,)) + verify_choice_assignable("MY_CHOICE", ( 1, 2 )) + verify_choice_assignable("NMY_CHOICE", (0, 1, 2 )) + verify_choice_assignable("NY_CHOICE", (0, 2 )) + verify_choice_assignable("NM_CHOICE", (0, 1 )) + verify_choice_assignable("M_CHOICE", ( 1, )) + verify_choice_assignable("N_CHOICE", ( )) + print("Testing object relations") -- cgit v1.2.3 From bac2790485ad61cf8f06de4017ff8c88f652eca8 Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Wed, 8 Nov 2017 11:11:26 +0100 Subject: Add a release test script Confirms that all the examples that aren't tested in the test suite at least run. Easy to miss brokenness there. Output can be inspected manually (it'll vary depending on the kernel version). Fix defconfig_oldconfig.py, which hadn't been properly updated for the new API. --- examples/defconfig_oldconfig.py | 20 ++++++++-------- examples/print_sym_info.py | 2 +- tests/reltest | 52 +++++++++++++++++++++++++++++++++++++++++ testsuite.py | 1 + 4 files changed, 64 insertions(+), 11 deletions(-) create mode 100755 tests/reltest (limited to 'tests') diff --git a/examples/defconfig_oldconfig.py b/examples/defconfig_oldconfig.py index 8e72c8a..84aa134 100644 --- a/examples/defconfig_oldconfig.py +++ b/examples/defconfig_oldconfig.py @@ -15,23 +15,23 @@ import kconfiglib import sys -conf = kconfiglib.Kconfig(sys.argv[1]) +kconf = kconfiglib.Kconfig(sys.argv[1]) # Mirrors defconfig -conf.load_config("arch/x86/configs/x86_64_defconfig") -conf.write_config(".config") +kconf.load_config("arch/x86/configs/x86_64_defconfig") +kconf.write_config(".config") # Mirrors the first oldconfig -conf.load_config(".config") -conf.syms["ETHERNET"].set_value(0) -conf.write_config(".config") +kconf.load_config(".config") +kconf.syms["ETHERNET"].set_value(0) +kconf.write_config(".config") # Mirrors the second oldconfig -conf.load_config(".config") -conf.syms["ETHERNET"].set_value(2) -for s in conf: +kconf.load_config(".config") +kconf.syms["ETHERNET"].set_value(2) +for s in kconf.defined_syms: if s.user_value is None and 0 in s.assignable: s.set_value(0) # Write the final configuration -conf.write_config(".config") +kconf.write_config(".config") diff --git a/examples/print_sym_info.py b/examples/print_sym_info.py index 120bc07..3ee3c97 100644 --- a/examples/print_sym_info.py +++ b/examples/print_sym_info.py @@ -4,7 +4,7 @@ # # $ make [ARCH=] scriptconfig SCRIPT=Kconfiglib/examples/print_sym_info.py SCRIPT_ARG= # -# Example output for SCRIPT_ARG=modules: +# Example output for SCRIPT_ARG=MODULES: # # menuconfig MODULES # bool diff --git a/tests/reltest b/tests/reltest new file mode 100755 index 0000000..8a3d581 --- /dev/null +++ b/tests/reltest @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +# Runs the test suite and all examples scripts with Python 2 and Python 3, +# bailing immediately if anything fails. For the examples that aren't tested in +# the test suite, we just confirm that they at least run. +# +# Should be run from the kernel root with $ Kconfiglib/tests/reltest + +test_script() { + echo -e "\n================= $1 with $py =================\n" + if (( $# == 1)); then + make scriptconfig PYTHONCMD=$py SCRIPT=$1 + else + make scriptconfig PYTHONCMD=$py SCRIPT=$1 SCRIPT_ARG="$2" + fi + + if (($?)); then + echo "$1 failed to run with $py" + exit 1 + fi +} + +for py in python2 python3; do + echo -e "\n================= Test suite with $py =================\n" + + if ! $py Kconfiglib/testsuite.py speedy; then + echo "test suite failed for $py" + exit 1 + fi + + # Check that the example scripts that aren't tested by the test suite run + # at least + + test_script Kconfiglib/examples/defconfig_oldconfig.py + test_script Kconfiglib/examples/defconfig.py + test_script Kconfiglib/examples/eval_expr.py MODULES + test_script Kconfiglib/examples/find_symbol.py X86 + test_script Kconfiglib/examples/help_grep.py general + test_script Kconfiglib/examples/print_sym_info.py MODULES + test_script Kconfiglib/examples/print_tree.py + + $py Kconfiglib/examples/menuconfig.py Kconfiglib/examples/Kmenuconfig < Date: Wed, 8 Nov 2017 11:18:21 +0100 Subject: Spacing nit --- tests/reltest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/reltest b/tests/reltest index 8a3d581..dea0137 100755 --- a/tests/reltest +++ b/tests/reltest @@ -8,7 +8,7 @@ test_script() { echo -e "\n================= $1 with $py =================\n" - if (( $# == 1)); then + if (($# == 1)); then make scriptconfig PYTHONCMD=$py SCRIPT=$1 else make scriptconfig PYTHONCMD=$py SCRIPT=$1 SCRIPT_ARG="$2" -- cgit v1.2.3