12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203 |
- # Copyright (c) 2011-2019, Ulf Magnusson
- # SPDX-License-Identifier: ISC
- # This is the Kconfiglib test suite. It runs selftests on Kconfigs provided by
- # us and tests compatibility with the C Kconfig implementation by comparing the
- # output of Kconfiglib with the output of the scripts/kconfig/*conf utilities
- # for different targets and defconfigs. It should be run from the top-level
- # kernel directory with
- #
- # $ python Kconfiglib/testsuite.py
- #
- # Some additional options can be turned on by passing them as arguments. They
- # default to off.
- #
- # - obsessive:
- # By default, only valid arch/defconfig pairs are tested. In obsessive mode,
- # every arch will be tested with every defconfig. Increases the testing time
- # by an order of magnitude. Occasionally finds (usually obscure) bugs, and I
- # make sure everything passes with it.
- #
- # - obsessive-min-config:
- # Like obsessive, for the minimal configuation (defconfig) tests.
- #
- # - log:
- # Log timestamped defconfig test failures to the file test_defconfig_fails.
- # Handy in obsessive mode.
- #
- # For example, this commands runs the test suite in obsessive mode with logging
- # enabled:
- #
- # $ python(3) Kconfiglib/testsuite.py obsessive log
- #
- # pypy works too, and runs most tests much faster than CPython.
- #
- # All tests should pass. Report regressions to ulfalizer a.t Google's email
- # service.
- import difflib
- import errno
- import os
- import re
- import shutil
- import subprocess
- import sys
- import tempfile
- import textwrap
- from kconfiglib import Kconfig, Symbol, Choice, COMMENT, MENU, MenuNode, \
- BOOL, TRISTATE, HEX, \
- TRI_TO_STR, \
- escape, unescape, \
- expr_str, expr_items, split_expr, \
- _ordered_unique, \
- OR, AND, \
- KconfigError
- def shell(cmd):
- with open(os.devnull, "w") as devnull:
- subprocess.call(cmd, shell=True, stdout=devnull, stderr=devnull)
- all_passed = True
- def fail(msg=None):
- global all_passed
- all_passed = False
- if msg is not None:
- print("fail: " + msg)
- def verify(cond, msg):
- if not cond:
- fail(msg)
- def verify_equal(x, y):
- if x != y:
- fail("'{}' does not equal '{}'".format(x, y))
- # Prevent accidental loading of configuration files by removing
- # KCONFIG_ALLCONFIG from the environment
- os.environ.pop("KCONFIG_ALLCONFIG", None)
- obsessive = False
- obsessive_min_config = False
- log = False
- def run_tests():
- global obsessive, log
- for s in sys.argv[1:]:
- if s == "obsessive":
- obsessive = True
- print("Obsessive mode enabled")
- elif s == "obsessive-min-config":
- obsessive_min_config = True
- print("Obsessive minimal config mode enabled")
- elif s == "log":
- log = True
- print("Log mode enabled")
- else:
- print("Unrecognized option '{}'".format(s))
- return
- run_selftests()
- run_compatibility_tests()
- def run_selftests():
- #
- # Common helper functions. These all expect 'c' to hold the current
- # configuration.
- #
- def verify_value(sym_name, val):
- # Verifies that a symbol has a particular value.
- if isinstance(val, int):
- val = TRI_TO_STR[val]
- sym = c.syms[sym_name]
- verify(sym.str_value == val,
- 'expected {} to have the value "{}", had the value "{}"'
- .format(sym_name, val, sym.str_value))
- def assign_and_verify_value(sym_name, val, new_val):
- # Assigns 'val' to a symbol and verifies that its value becomes
- # 'new_val'. Assumes (and tests) that 'val' is valid for the
- # symbol type.
- if isinstance(new_val, int):
- new_val = TRI_TO_STR[new_val]
- sym = c.syms[sym_name]
- old_val = sym.str_value
- verify(sym.set_value(val),
- "assigning '{}' to {} unexpectedly failed"
- .format(val, sym_name))
- verify(sym.str_value == new_val,
- "expected {} to have the value '{}' after being assigned the "
- "value '{}'. Instead, the value is '{}'. The old value was "
- "'{}'."
- .format(sym_name, new_val, val, sym.str_value, old_val))
- def assign_and_verify(sym_name, user_val):
- # Like assign_and_verify_value(), with the expected value being the
- # value just set.
- assign_and_verify_value(sym_name, user_val, user_val)
- def assign_and_verify_user_value(sym_name, val, user_val, valid):
- # Assigns a user value to the symbol and verifies the new user value.
- # If valid is True, the user value is valid for the type, otherwise
- # not. This is used to test the set_value() return value.
- sym = c.syms[sym_name]
- sym_old_user_val = sym.user_value
- verify(sym.set_value(val) == valid,
- "expected the user value '{}' to be {} for {}, was not"
- .format(val, "valid" if valid else "invalid", sym_name))
- verify(sym.user_value == user_val,
- "the assigned user value '{}' wasn't reflected in user_value "
- "on the symbol {}. Instead, the new user_value was '{}'. The "
- "old user value was '{}'."
- .format(user_val, sym_name, sym.user_value, sym_old_user_val))
- #
- # Selftests
- #
- print("Testing string literal lexing")
- # Dummy empty configuration just to get a Kconfig object
- c = Kconfig("Kconfiglib/tests/empty")
- def verify_string_lex(s, expected):
- # Verifies that a constant symbol with the name 'res' is produced from
- # lexing 's'
- res = c._tokenize("if " + s)[1].name
- verify(res == expected,
- "expected <{}> to produced the constant symbol <{}>, "
- 'produced <{}>'.format(s[1:-1], expected, res))
- verify_string_lex(r""" "" """, "")
- verify_string_lex(r""" '' """, "")
- verify_string_lex(r""" "a" """, "a")
- verify_string_lex(r""" 'a' """, "a")
- verify_string_lex(r""" "ab" """, "ab")
- verify_string_lex(r""" 'ab' """, "ab")
- verify_string_lex(r""" "abc" """, "abc")
- verify_string_lex(r""" 'abc' """, "abc")
- verify_string_lex(r""" "'" """, "'")
- verify_string_lex(r""" '"' """, '"')
- verify_string_lex(r""" "\"" """, '"')
- verify_string_lex(r""" '\'' """, "'")
- verify_string_lex(r""" "\"\"" """, '""')
- verify_string_lex(r""" '\'\'' """, "''")
- verify_string_lex(r""" "\'" """, "'")
- verify_string_lex(r""" '\"' """, '"')
- verify_string_lex(r""" "\\" """, "\\")
- verify_string_lex(r""" '\\' """, "\\")
- verify_string_lex(r""" "\a\\'\b\c\"'d" """, 'a\\\'bc"\'d')
- verify_string_lex(r""" '\a\\"\b\c\'"d' """, "a\\\"bc'\"d")
- def verify_string_bad(s):
- # Verifies that tokenizing 's' throws a KconfigError. Strips the first
- # and last characters from 's' so we can use readable raw strings as
- # input.
- try:
- c.eval_string(s)
- except KconfigError:
- pass
- else:
- fail("expected tokenization of {} to fail, didn't".format(s[1:-1]))
- verify_string_bad(r""" " """)
- verify_string_bad(r""" ' """)
- verify_string_bad(r""" "' """)
- verify_string_bad(r""" '" """)
- verify_string_bad(r""" "\" """)
- verify_string_bad(r""" '\' """)
- verify_string_bad(r""" "foo """)
- verify_string_bad(r""" 'foo """)
- print("Testing escape() and unescape()")
- def verify_escape_unescape(s, sesc):
- # Verify that 's' escapes to 'sesc' and that 'sesc' unescapes to 's'
- verify_equal(escape(s), sesc)
- verify_equal(unescape(sesc), s)
- verify_escape_unescape(r'' , r'' )
- verify_escape_unescape(r'foo' , r'foo' )
- verify_escape_unescape(r'"' , r'\"' )
- verify_escape_unescape(r'""' , r'\"\"' )
- verify_escape_unescape('\\' , r'\\' )
- verify_escape_unescape(r'\\' , r'\\\\' )
- verify_escape_unescape(r'\"' , r'\\\"' )
- verify_escape_unescape(r'"ab\cd"ef"', r'\"ab\\cd\"ef\"')
- # Backslashes before any character should be unescaped, not just before "
- # and \
- verify_equal(unescape(r"\afoo\b\c\\d\\\e\\\\f"), r"afoobc\d\e\\f")
- print("Testing _ordered_unique()")
- verify_equal(_ordered_unique([]), [])
- verify_equal(_ordered_unique([1]), [1])
- verify_equal(_ordered_unique([1, 2]), [1, 2])
- verify_equal(_ordered_unique([1, 1]), [1])
- verify_equal(_ordered_unique([1, 1, 2]), [1, 2])
- verify_equal(_ordered_unique([1, 2, 1]), [1, 2])
- verify_equal(_ordered_unique([1, 2, 2]), [1, 2])
- verify_equal(_ordered_unique([1, 2, 3, 2, 1, 2, 3, 4, 3, 2, 1, 0]),
- [1, 2, 3, 4, 0])
- print("Testing expression evaluation")
- c = Kconfig("Kconfiglib/tests/Keval", warn=False)
- def verify_eval(expr, val):
- res = c.eval_string(expr)
- verify(res == val,
- "'{}' evaluated to {}, expected {}".format(expr, res, val))
- # No modules
- verify_eval("n", 0)
- verify_eval("m", 0)
- verify_eval("y", 2)
- verify_eval("'n'", 0)
- verify_eval("'m'", 0)
- verify_eval("'y'", 2)
- verify_eval("M", 2)
- # Modules
- c.modules.set_value(2)
- verify_eval("n", 0)
- verify_eval("m", 1)
- verify_eval("y", 2)
- verify_eval("'n'", 0)
- verify_eval("'m'", 1)
- verify_eval("'y'", 2)
- verify_eval("M", 1)
- verify_eval("(Y || N) && (m && y)", 1)
- # Non-bool/non-tristate symbols are always n in a tristate sense
- verify_eval("Y_STRING", 0)
- verify_eval("Y_STRING || m", 1)
- # As are all constants besides y and m
- verify_eval('"foo"', 0)
- verify_eval('"foo" || "bar"', 0)
- verify_eval('"foo" || m', 1)
- # Test equality for symbols
- verify_eval("N = N", 2)
- verify_eval("N = n", 2)
- verify_eval("N = 'n'", 2)
- verify_eval("N != N", 0)
- verify_eval("N != n", 0)
- verify_eval("N != 'n'", 0)
- verify_eval("M = M", 2)
- verify_eval("M = m", 2)
- verify_eval("M = 'm'", 2)
- verify_eval("M != M", 0)
- verify_eval("M != m", 0)
- verify_eval("M != 'm'", 0)
- verify_eval("Y = Y", 2)
- verify_eval("Y = y", 2)
- verify_eval("Y = 'y'", 2)
- verify_eval("Y != Y", 0)
- verify_eval("Y != y", 0)
- verify_eval("Y != 'y'", 0)
- verify_eval("N != M", 2)
- verify_eval("N != Y", 2)
- verify_eval("M != Y", 2)
- verify_eval("Y_STRING = y", 2)
- verify_eval("Y_STRING = 'y'", 2)
- verify_eval('FOO_BAR_STRING = "foo bar"', 2)
- verify_eval('FOO_BAR_STRING != "foo bar baz"', 2)
- verify_eval('INT_37 = 37', 2)
- verify_eval("INT_37 = '37'", 2)
- verify_eval('HEX_0X37 = 0x37', 2)
- verify_eval("HEX_0X37 = '0x37'", 2)
- # These should also hold after 31847b67 (kconfig: allow use of relations
- # other than (in)equality)
- verify_eval("HEX_0X37 = '0x037'", 2)
- verify_eval("HEX_0X37 = '0x0037'", 2)
- # Constant symbol comparisons
- verify_eval('"foo" != "bar"', 2)
- verify_eval('"foo" = "bar"', 0)
- verify_eval('"foo" = "foo"', 2)
- # Undefined symbols get their name as their value
- c.warn = False
- verify_eval("'not_defined' = not_defined", 2)
- verify_eval("not_defined_2 = not_defined_2", 2)
- verify_eval("not_defined_1 != not_defined_2", 2)
- # Test less than/greater than
- # Basic evaluation
- verify_eval("INT_37 < 38", 2)
- verify_eval("38 < INT_37", 0)
- verify_eval("INT_37 < '38'", 2)
- verify_eval("'38' < INT_37", 0)
- verify_eval("INT_37 < 138", 2)
- verify_eval("138 < INT_37", 0)
- verify_eval("INT_37 < '138'", 2)
- verify_eval("'138' < INT_37", 0)
- verify_eval("INT_37 < -138", 0)
- verify_eval("-138 < INT_37", 2)
- verify_eval("INT_37 < '-138'", 0)
- verify_eval("'-138' < INT_37", 2)
- verify_eval("INT_37 < 37", 0)
- verify_eval("37 < INT_37", 0)
- verify_eval("INT_37 < 36", 0)
- verify_eval("36 < INT_37", 2)
- # Different formats in comparison
- verify_eval("INT_37 < 0x26", 2) # 38
- verify_eval("INT_37 < 0x25", 0) # 37
- verify_eval("INT_37 < 0x24", 0) # 36
- verify_eval("HEX_0X37 < 56", 2) # 0x38
- verify_eval("HEX_0X37 < 55", 0) # 0x37
- verify_eval("HEX_0X37 < 54", 0) # 0x36
- # Other int comparisons
- verify_eval("INT_37 <= 38", 2)
- verify_eval("INT_37 <= 37", 2)
- verify_eval("INT_37 <= 36", 0)
- verify_eval("INT_37 > 38", 0)
- verify_eval("INT_37 > 37", 0)
- verify_eval("INT_37 > 36", 2)
- verify_eval("INT_37 >= 38", 0)
- verify_eval("INT_37 >= 37", 2)
- verify_eval("INT_37 >= 36", 2)
- # Other hex comparisons
- verify_eval("HEX_0X37 <= 0x38", 2)
- verify_eval("HEX_0X37 <= 0x37", 2)
- verify_eval("HEX_0X37 <= 0x36", 0)
- verify_eval("HEX_0X37 > 0x38", 0)
- verify_eval("HEX_0X37 > 0x37", 0)
- verify_eval("HEX_0X37 > 0x36", 2)
- verify_eval("HEX_0X37 >= 0x38", 0)
- verify_eval("HEX_0X37 >= 0x37", 2)
- verify_eval("HEX_0X37 >= 0x36", 2)
- # A hex holding a value without a "0x" prefix should still be treated as
- # hexadecimal
- verify_eval("HEX_37 < 0x38", 2)
- verify_eval("HEX_37 < 0x37", 0)
- verify_eval("HEX_37 < 0x36", 0)
- # Symbol comparisons
- verify_eval("INT_37 < HEX_0X37", 2)
- verify_eval("INT_37 > HEX_0X37", 0)
- verify_eval("HEX_0X37 < INT_37 ", 0)
- verify_eval("HEX_0X37 > INT_37 ", 2)
- verify_eval("INT_37 < INT_37 ", 0)
- verify_eval("INT_37 <= INT_37 ", 2)
- verify_eval("INT_37 > INT_37 ", 0)
- verify_eval("INT_37 <= INT_37 ", 2)
- # Tristate value comparisons
- verify_eval("n < n", 0)
- verify_eval("n < m", 2)
- verify_eval("n < y", 2)
- verify_eval("n < N", 0)
- verify_eval("n < M", 2)
- verify_eval("n < Y", 2)
- verify_eval("0 > n", 0)
- verify_eval("1 > n", 2)
- verify_eval("2 > n", 2)
- verify_eval("m < n", 0)
- verify_eval("m < m", 0)
- verify_eval("m < y", 2)
- # Strings compare lexicographically
- verify_eval("'aa' < 'ab'", 2)
- verify_eval("'aa' > 'ab'", 0)
- verify_eval("'ab' < 'aa'", 0)
- verify_eval("'ab' > 'aa'", 2)
- # Comparisons where one of the operands doesn't parse as a number also give
- # a lexicographic comparison
- verify_eval("INT_37 < '37a' ", 2)
- verify_eval("'37a' > INT_37", 2)
- verify_eval("INT_37 <= '37a' ", 2)
- verify_eval("'37a' >= INT_37", 2)
- verify_eval("INT_37 >= '37a' ", 0)
- verify_eval("INT_37 > '37a' ", 0)
- verify_eval("'37a' < INT_37", 0)
- verify_eval("'37a' <= INT_37", 0)
- def verify_eval_bad(expr):
- try:
- c.eval_string(expr)
- except KconfigError:
- pass
- else:
- fail('expected eval_string("{}") to throw KconfigError, '
- "didn't".format(expr))
- # Verify that some bad stuff throws KconfigError's
- verify_eval_bad("")
- verify_eval_bad("&")
- verify_eval_bad("|")
- verify_eval_bad("!")
- verify_eval_bad("(")
- verify_eval_bad(")")
- verify_eval_bad("=")
- verify_eval_bad("(X")
- verify_eval_bad("X)")
- verify_eval_bad("X X")
- verify_eval_bad("!X X")
- verify_eval_bad("X !X")
- verify_eval_bad("(X) X")
- verify_eval_bad("X &&")
- verify_eval_bad("&& X")
- verify_eval_bad("X && && X")
- verify_eval_bad("X && !&&")
- verify_eval_bad("X ||")
- verify_eval_bad("|| X")
- print("Testing Symbol.__str__()/custom_str() and def_{int,hex,string}")
- def verify_str(item, s):
- verify_equal(str(item), s[1:-1])
- def verify_custom_str(item, s):
- verify_equal(item.custom_str(lambda sc: "[{}]".format(sc.name)),
- s[1:-1])
- c = Kconfig("Kconfiglib/tests/Kstr", warn=False)
- c.modules.set_value(2)
- verify_str(c.syms["UNDEFINED"], """
- """)
- verify_str(c.syms["BASIC_NO_PROMPT"], """
- config BASIC_NO_PROMPT
- bool
- help
- blah blah
-
- blah blah blah
-
- blah
- """)
- verify_str(c.syms["BASIC_PROMPT"], """
- config BASIC_PROMPT
- bool "basic"
- """)
- verify_str(c.syms["ADVANCED"], """
- 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
- tristate "prompt 2"
- menuconfig ADVANCED
- tristate "prompt 3"
- config ADVANCED
- tristate
- depends on (A || !B || (C && D) || !(E && F) || G = H || (I && !J && (K || L) && !(M || N) && O = P)) && DEP4 && DEP3
- help
- second help text
- config ADVANCED
- tristate "prompt 4" if VIS
- depends on DEP4 && DEP3
- """)
- verify_custom_str(c.syms["ADVANCED"], """
- 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
- tristate "prompt 2"
- menuconfig ADVANCED
- tristate "prompt 3"
- config ADVANCED
- tristate
- depends on ([A] || ![B] || ([C] && [D]) || !([E] && [F]) || [G] = [H] || ([I] && ![J] && ([K] || [L]) && !([M] || [N]) && [O] = [P])) && [DEP4] && [DEP3]
- help
- second help text
- config ADVANCED
- tristate "prompt 4" if [VIS]
- depends on [DEP4] && [DEP3]
- """)
- verify_str(c.syms["ONLY_DIRECT_DEPS"], """
- config ONLY_DIRECT_DEPS
- int
- depends on DEP1 && DEP2
- """)
- verify_str(c.syms["STRING"], """
- config STRING
- string
- default "foo"
- default "bar" if DEP
- default STRING2
- default STRING3 if DEP
- """)
- verify_str(c.syms["INT"], """
- config INT
- int
- range 1 2
- range FOO BAR
- range BAZ QAZ if DEP
- default 7 if DEP
- """)
- verify_str(c.syms["HEX"], """
- config HEX
- hex
- range 0x100 0x200
- range FOO BAR
- range BAZ QAZ if DEP
- default 0x123
- """)
- verify_str(c.modules, """
- config MODULES
- bool "MODULES"
- option modules
- """)
- verify_str(c.syms["OPTIONS"], """
- config OPTIONS
- option allnoconfig_y
- option defconfig_list
- option env="ENV"
- """)
- verify_str(c.syms["CORRECT_PROP_LOCS_BOOL"], """
- config CORRECT_PROP_LOCS_BOOL
- bool "prompt 1"
- default DEFAULT_1
- default DEFAULT_2
- select SELECT_1
- select SELECT_2
- imply IMPLY_1
- imply IMPLY_2
- depends on LOC_1
- help
- help 1
- menuconfig CORRECT_PROP_LOCS_BOOL
- bool "prompt 2"
- default DEFAULT_3
- default DEFAULT_4
- select SELECT_3
- select SELECT_4
- imply IMPLY_3
- imply IMPLY_4
- depends on LOC_2
- help
- help 2
- config CORRECT_PROP_LOCS_BOOL
- bool "prompt 3"
- default DEFAULT_5
- default DEFAULT_6
- select SELECT_5
- select SELECT_6
- imply IMPLY_5
- imply IMPLY_6
- depends on LOC_3
- help
- help 2
- """)
- verify_str(c.syms["CORRECT_PROP_LOCS_INT"], """
- config CORRECT_PROP_LOCS_INT
- int
- range 1 2
- range 3 4
- depends on LOC_1
- config CORRECT_PROP_LOCS_INT
- int
- range 5 6
- range 7 8
- depends on LOC_2
- """)
- verify_str(c.syms["PROMPT_ONLY"], """
- config PROMPT_ONLY
- prompt "prompt only"
- """)
- verify_custom_str(c.syms["CORRECT_PROP_LOCS_INT"], """
- config CORRECT_PROP_LOCS_INT
- int
- range [1] [2]
- range [3] [4]
- depends on [LOC_1]
- config CORRECT_PROP_LOCS_INT
- int
- range [5] [6]
- range [7] [8]
- depends on [LOC_2]
- """)
- print("Testing Choice.__str__()/custom_str()")
- verify_str(c.named_choices["CHOICE"], """
- choice CHOICE
- tristate "foo"
- default CHOICE_1
- default CHOICE_2 if dep
- """)
- verify_str(c.named_choices["CHOICE"].nodes[0].next.item, """
- choice
- tristate "no name"
- optional
- """)
- verify_str(c.named_choices["CORRECT_PROP_LOCS_CHOICE"], """
- choice CORRECT_PROP_LOCS_CHOICE
- bool
- default CHOICE_3
- depends on LOC_1
- choice CORRECT_PROP_LOCS_CHOICE
- bool
- default CHOICE_4
- depends on LOC_2
- choice CORRECT_PROP_LOCS_CHOICE
- bool
- default CHOICE_5
- depends on LOC_3
- """)
- verify_custom_str(c.named_choices["CORRECT_PROP_LOCS_CHOICE"], """
- choice CORRECT_PROP_LOCS_CHOICE
- bool
- default [CHOICE_3]
- depends on [LOC_1]
- choice CORRECT_PROP_LOCS_CHOICE
- bool
- default [CHOICE_4]
- depends on [LOC_2]
- choice CORRECT_PROP_LOCS_CHOICE
- bool
- default [CHOICE_5]
- depends on [LOC_3]
- """)
- print("Testing MenuNode.__str__()/custom_str() for menus and comments")
- verify_str(c.syms["SIMPLE_MENU_HOOK"].nodes[0].next, """
- menu "simple menu"
- """)
- verify_str(c.syms["ADVANCED_MENU_HOOK"].nodes[0].next, """
- menu "advanced menu"
- depends on A
- visible if B && (C || D)
- """)
- verify_custom_str(c.syms["ADVANCED_MENU_HOOK"].nodes[0].next, """
- menu "advanced menu"
- depends on [A]
- visible if [B] && ([C] || [D])
- """)
- verify_str(c.syms["SIMPLE_COMMENT_HOOK"].nodes[0].next, """
- comment "simple comment"
- """)
- verify_str(c.syms["ADVANCED_COMMENT_HOOK"].nodes[0].next, """
- comment "advanced comment"
- depends on A && B
- """)
- verify_custom_str(c.syms["ADVANCED_COMMENT_HOOK"].nodes[0].next, """
- comment "advanced comment"
- depends on [A] && [B]
- """)
- print("Testing {MenuNode,Symbol,Choice}.orig_*")
- # Just test some corner cases here re. MenuNode.orig_*. They are already
- # indirectly tested above. Use MenuNode.__str__() as a proxy.
- verify_str(c.syms["DEP_REM_CORNER_CASES"], """
- config DEP_REM_CORNER_CASES
- bool
- default A
- depends on n
- config DEP_REM_CORNER_CASES
- bool
- default B if n
- config DEP_REM_CORNER_CASES
- bool
- default C
- depends on m && MODULES
- config DEP_REM_CORNER_CASES
- bool
- default D if A
- config DEP_REM_CORNER_CASES
- bool
- default E if !E1
- default F if F1 = F2
- default G if G1 || H1
- depends on !H
- config DEP_REM_CORNER_CASES
- bool
- default H
- depends on "foo" = "bar"
- config DEP_REM_CORNER_CASES
- bool "prompt" if FOO || BAR
- depends on BAZ && QAZ
- """)
- # Test {Symbol,Choice}.orig_*
- def verify_deps(elms, dep_index, expected):
- verify_equal(" ".join(expr_str(elm[dep_index]) for elm in elms),
- expected)
- verify_deps(c.syms["BOOL_SYM_ORIG"].orig_defaults, 1, "DEP y y")
- verify_deps(c.syms["BOOL_SYM_ORIG"].orig_selects, 1, "y DEP y")
- verify_deps(c.syms["BOOL_SYM_ORIG"].orig_implies, 1, "y y DEP")
- verify_deps(c.syms["INT_SYM_ORIG"].orig_ranges, 2, "DEP y DEP")
- verify_deps(c.named_choices["CHOICE_ORIG"].orig_defaults, 1, "y DEP DEP")
- print("Testing Symbol.__repr__()")
- def verify_repr(item, s):
- verify_equal(repr(item) + "\n", s[1:])
- c = Kconfig("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>
- """)
- verify_repr(c.syms["BASIC"], """
- <symbol BASIC, bool, value y, visibility n, direct deps y, Kconfiglib/tests/Krepr:9>
- """)
- verify_repr(c.syms["VISIBLE"], """
- <symbol VISIBLE, bool, "visible", value n, visibility y, direct deps y, Kconfiglib/tests/Krepr:14>
- """)
- c.syms["VISIBLE"].set_value(2)
- c.syms["STRING"].set_value("foo")
- 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["STRING"], """
- <symbol STRING, string, "visible", value "foo", user value "foo", visibility y, direct deps y, Kconfiglib/tests/Krepr:17>
- """)
- verify_repr(c.syms["DIR_DEP_N"], """
- <symbol DIR_DEP_N, unknown, value "DIR_DEP_N", visibility n, direct deps n, Kconfiglib/tests/Krepr:20>
- """)
- verify_repr(c.syms["OPTIONS"], """
- <symbol OPTIONS, unknown, value "OPTIONS", visibility n, allnoconfig_y, is the defconfig_list symbol, from environment variable ENV, direct deps y, Kconfiglib/tests/Krepr:23>
- """)
- verify_repr(c.syms["MULTI_DEF"], """
- <symbol MULTI_DEF, unknown, value "MULTI_DEF", visibility n, direct deps y, Kconfiglib/tests/Krepr:28, Kconfiglib/tests/Krepr:29>
- """)
- verify_repr(c.syms["CHOICE_1"], """
- <symbol CHOICE_1, tristate, "choice sym", value n, visibility m, choice symbol, direct deps m, Kconfiglib/tests/Krepr:36>
- """)
- verify_repr(c.modules, """
- <symbol MODULES, bool, value y, visibility n, is the modules symbol, direct deps y, Kconfiglib/tests/Krepr:1>
- """)
- print("Testing Choice.__repr__()")
- verify_repr(c.named_choices["CHOICE"], """
- <choice CHOICE, tristate, "choice", mode m, visibility y, Kconfiglib/tests/Krepr:33>
- """)
- c.named_choices["CHOICE"].set_value(2)
- verify_repr(c.named_choices["CHOICE"], """
- <choice CHOICE, tristate, "choice", mode y, user mode y, CHOICE_1 selected, visibility y, Kconfiglib/tests/Krepr:33>
- """)
- c.syms["CHOICE_2"].set_value(2)
- verify_repr(c.named_choices["CHOICE"], """
- <choice CHOICE, tristate, "choice", mode y, user mode y, CHOICE_2 selected, CHOICE_2 selected by user, visibility y, Kconfiglib/tests/Krepr:33>
- """)
- c.named_choices["CHOICE"].set_value(1)
- verify_repr(c.named_choices["CHOICE"], """
- <choice CHOICE, tristate, "choice", mode m, user mode m, CHOICE_2 selected by user (overridden), visibility y, Kconfiglib/tests/Krepr:33>
- """)
- verify_repr(c.syms["CHOICE_HOOK"].nodes[0].next.item, """
- <choice, tristate, "optional choice", mode n, visibility n, optional, Kconfiglib/tests/Krepr:46>
- """)
- print("Testing MenuNode.__repr__()")
- verify_repr(c.syms["BASIC"].nodes[0], """
- <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, deps n, has next, Kconfiglib/tests/Krepr:20>
- """)
- verify_repr(c.syms["MULTI_DEF"].nodes[0], """
- <menu node for symbol MULTI_DEF, deps y, has next, Kconfiglib/tests/Krepr:28>
- """)
- verify_repr(c.syms["MULTI_DEF"].nodes[1], """
- <menu node for symbol MULTI_DEF, deps y, has next, Kconfiglib/tests/Krepr:29>
- """)
- verify_repr(c.syms["MENUCONFIG"].nodes[0], """
- <menu node for symbol MENUCONFIG, is menuconfig, deps y, has next, Kconfiglib/tests/Krepr:31>
- """)
- verify_repr(c.named_choices["CHOICE"].nodes[0], """
- <menu node for choice CHOICE, prompt "choice" (visibility y), deps y, has child, has next, Kconfiglib/tests/Krepr:33>
- """)
- verify_repr(c.syms["CHOICE_HOOK"].nodes[0].next, """
- <menu node for choice, prompt "optional choice" (visibility n), deps y, has next, Kconfiglib/tests/Krepr:46>
- """)
- verify_repr(c.syms["NO_VISIBLE_IF_HOOK"].nodes[0].next, """
- <menu node for menu, prompt "no visible if" (visibility y), deps y, 'visible if' deps y, has next, Kconfiglib/tests/Krepr:53>
- """)
- verify_repr(c.syms["VISIBLE_IF_HOOK"].nodes[0].next, """
- <menu node for menu, prompt "visible if" (visibility y), deps y, 'visible if' deps m, has next, Kconfiglib/tests/Krepr:58>
- """)
- verify_repr(c.syms["COMMENT_HOOK"].nodes[0].next, """
- <menu node for comment, prompt "comment" (visibility y), deps y, Kconfiglib/tests/Krepr:64>
- """)
- print("Testing Kconfig.__repr__()")
- verify_repr(c, """
- <configuration with 15 symbols, main menu prompt "Main menu", srctree is current directory, config symbol prefix "CONFIG_", warnings disabled, printing of warnings to stderr enabled, undef. symbol assignment warnings disabled, overriding symbol assignment warnings enabled, redundant symbol assignment warnings enabled>
- """)
- os.environ["srctree"] = "Kconfiglib"
- os.environ["CONFIG_"] = "CONFIG_ value"
- c = Kconfig("tests/Krepr", warn=False)
- c.warn = True
- c.warn_to_stderr = False
- c.warn_assign_override = False
- c.warn_assign_redun = False
- c.warn_assign_undef = True
- verify_repr(c, """
- <configuration with 15 symbols, main menu prompt "Main menu", srctree "Kconfiglib", config symbol prefix "CONFIG_ value", warnings enabled, printing of warnings to stderr disabled, undef. symbol assignment warnings enabled, overriding symbol assignment warnings disabled, redundant symbol assignment warnings disabled>
- """)
- os.environ.pop("srctree", None)
- os.environ.pop("CONFIG_", None)
- print("Testing tricky help strings")
- c = Kconfig("Kconfiglib/tests/Khelp")
- def verify_help(node, s):
- verify_equal(node.help, s[1:-1])
- verify_help(c.syms["TWO_HELP_STRINGS"].nodes[0], """
- first help string
- """)
- verify_help(c.syms["TWO_HELP_STRINGS"].nodes[1], """
- second help string
- """)
- verify_help(c.syms["NO_BLANK_AFTER_HELP"].nodes[0], """
- help for
- NO_BLANK_AFTER_HELP
- """)
- verify_help(c.named_choices["CHOICE_HELP"].nodes[0], """
- help for
- CHOICE_HELP
- """)
- verify_help(c.syms["HELP_TERMINATED_BY_COMMENT"].nodes[0], """
- a
- b
- c
- """)
- verify_help(c.syms["TRICKY_HELP"].nodes[0], """
- a
- b
- c
- d
- e
- f
- g
- h
- i
- """)
- print("Testing locations, source/rsource/gsource/grsource, and "
- "Kconfig.kconfig_filenames")
- def verify_locations(nodes, *expected_locs):
- verify(len(nodes) == len(expected_locs),
- "Wrong number of locations for " + repr(nodes))
- for node, expected_loc in zip(nodes, expected_locs):
- node_loc = "{}:{}".format(node.filename, node.linenr)
- verify(node_loc == expected_loc,
- "expected {} to have the location {}, had the location {}"
- .format(repr(node), expected_loc, node_loc))
- # Expanded in the 'source' statement in Klocation
- os.environ["TESTS_DIR_FROM_ENV"] = "tests"
- os.environ["SUB_DIR_FROM_ENV"] = "sub"
- os.environ["_SOURCED"] = "_sourced"
- os.environ["_RSOURCED"] = "_rsourced"
- os.environ["_GSOURCED"] = "_gsourced"
- os.environ["_GRSOURCED"] = "_grsourced"
- # Test twice, with $srctree as a relative and an absolute path,
- # respectively
- for srctree in "Kconfiglib", os.path.abspath("Kconfiglib"):
- os.environ["srctree"] = srctree
- # Has symbol with empty help text, so disable warnings
- c = Kconfig("tests/Klocation", warn=False)
- verify_locations(c.syms["UNDEFINED"].nodes)
- verify_equal(c.syms["UNDEFINED"].name_and_loc, "UNDEFINED (undefined)")
- verify_locations(c.syms["ONE_DEF"].nodes, "tests/Klocation:4")
- verify_equal(c.syms["ONE_DEF"].name_and_loc,
- "ONE_DEF (defined at tests/Klocation:4)")
- verify_locations(c.syms["TWO_DEF"].nodes,
- "tests/Klocation:7",
- "tests/Klocation:10")
- verify_equal(c.syms["TWO_DEF"].name_and_loc,
- "TWO_DEF (defined at tests/Klocation:7, tests/Klocation:10)")
- verify_locations(c.syms["MANY_DEF"].nodes,
- "tests/Klocation:13",
- "tests/Klocation:43",
- "tests/Klocation:45",
- "tests/Klocation_sourced:3",
- "tests/sub/Klocation_rsourced:2",
- "tests/sub/Klocation_gsourced1:1",
- "tests/sub/Klocation_gsourced2:1",
- "tests/sub/Klocation_gsourced1:1",
- "tests/sub/Klocation_gsourced2:1",
- "tests/sub/Klocation_grsourced1:1",
- "tests/sub/Klocation_grsourced2:1",
- "tests/sub/Klocation_grsourced1:1",
- "tests/sub/Klocation_grsourced2:1",
- "tests/Klocation:78")
- verify_locations(c.named_choices["CHOICE_ONE_DEF"].nodes,
- "tests/Klocation_sourced:5")
- verify_equal(c.named_choices["CHOICE_ONE_DEF"].name_and_loc,
- "<choice CHOICE_ONE_DEF> (defined at tests/Klocation_sourced:5)")
- verify_locations(c.named_choices["CHOICE_TWO_DEF"].nodes,
- "tests/Klocation_sourced:9",
- "tests/Klocation_sourced:13")
- verify_equal(c.named_choices["CHOICE_TWO_DEF"].name_and_loc,
- "<choice CHOICE_TWO_DEF> (defined at tests/Klocation_sourced:9, tests/Klocation_sourced:13)")
- verify_locations([c.syms["MENU_HOOK"].nodes[0].next],
- "tests/Klocation_sourced:20")
- verify_locations([c.syms["COMMENT_HOOK"].nodes[0].next],
- "tests/Klocation_sourced:26")
- # Test Kconfig.kconfig_filenames
- verify_equal(c.kconfig_filenames, [
- "tests/Klocation",
- "tests/Klocation_sourced",
- "tests/sub/Klocation_rsourced",
- "tests/sub/Klocation_gsourced1",
- "tests/sub/Klocation_gsourced2",
- "tests/sub/Klocation_gsourced1",
- "tests/sub/Klocation_gsourced2",
- "tests/sub/Klocation_grsourced1",
- "tests/sub/Klocation_grsourced2",
- "tests/sub/Klocation_grsourced1",
- "tests/sub/Klocation_grsourced2"
- ])
- # Test recursive 'source' detection
- try:
- Kconfig("tests/Krecursive1")
- except KconfigError as e:
- verify_equal(str(e), """
- tests/Krecursive2:1: recursive 'source' of 'tests/Krecursive1' detected. Check that environment variables are set correctly.
- Include path:
- tests/Krecursive1:1
- tests/Krecursive2:1
- """[:-1])
- except:
- fail("recursive 'source' raised wrong exception")
- else:
- fail("recursive 'source' did not raise exception")
- # Verify that source and rsource throw exceptions for missing files
- # TODO: Make an exception test helper
- try:
- Kconfig("tests/Kmissingsource")
- except KconfigError as e:
- if "not found" not in str(e):
- fail("'source' with missing file raised wrong KconfigError")
- except:
- fail("'source' with missing file raised wrong exception")
- else:
- fail("'source' with missing file did not raise exception")
- try:
- Kconfig("tests/Kmissingrsource")
- except KconfigError as e:
- if "not found" not in str(e):
- fail("'rsource' with missing file raised wrong KconfigError")
- except:
- fail("'rsource' with missing file raised wrong exception")
- else:
- fail("'rsource' with missing file did not raise exception")
- # Test a tricky case involving symlinks. $srctree is tests/symlink, which
- # points to tests/sub/sub, meaning tests/symlink/.. != tests/. Previously,
- # using 'rsource' from a file sourced with an absolute path triggered an
- # unsafe relpath() with tests/symlink/.. in it, crashing.
- os.environ["srctree"] = "Kconfiglib/tests/symlink"
- os.environ["KCONFIG_SYMLINK_2"] = os.path.abspath(
- "Kconfiglib/tests/sub/Kconfig_symlink_2")
- if not os.path.isabs(
- Kconfig("Kconfig_symlink_1").syms["FOUNDME"].nodes[0].filename):
- fail("Symlink + rsource issues")
- print("Testing Kconfig.node_iter()")
- # Reuse tests/Klocation. The node_iter(unique_syms=True) case already gets
- # plenty of testing from write_config() as well.
- os.environ["srctree"] = "Kconfiglib"
- c = Kconfig("tests/Klocation", warn=False)
- verify_equal(
- [node.item.name for node in c.node_iter()
- if isinstance(node.item, Symbol)],
- ["ONE_DEF", "TWO_DEF", "TWO_DEF", "MANY_DEF", "HELP_1", "HELP_2",
- "HELP_3", "MANY_DEF", "MANY_DEF", "MANY_DEF", "MENU_HOOK",
- "COMMENT_HOOK"] + 10*["MANY_DEF"])
- verify_equal(
- [node.item.name for node in c.node_iter(True)
- if isinstance(node.item, Symbol)],
- ["ONE_DEF", "TWO_DEF", "MANY_DEF", "HELP_1", "HELP_2", "HELP_3",
- "MENU_HOOK", "COMMENT_HOOK"])
- verify_equal(
- [node.prompt[0] for node in c.node_iter()
- if not isinstance(node.item, Symbol)],
- ["one-def choice", "two-def choice 1", "two-def choice 2",
- "menu", "comment"])
- verify_equal(
- [node.prompt[0] for node in c.node_iter(True)
- if not isinstance(node.item, Symbol)],
- ["one-def choice", "two-def choice 1", "two-def choice 2",
- "menu", "comment"])
- print("Testing MenuNode.include_path")
- os.environ["srctree"] = "Kconfiglib/tests"
- c = Kconfig("Kinclude_path")
- def verify_node_path(node, *expected):
- if node.include_path != expected:
- fail("Wrong include path for node {!r}. Got {}, expected {}."
- .format(node, node.include_path, expected))
- def verify_sym_path(sym_name, node_i, *expected):
- verify_node_path(c.syms[sym_name].nodes[node_i], *expected)
- verify_sym_path("TOP", 0)
- verify_sym_path("TOP", 1)
- verify_sym_path("TOP", 2)
- verify_sym_path("ONE_DOWN", 0, ("Kinclude_path", 4))
- verify_sym_path("ONE_DOWN", 1, ("Kinclude_path", 4))
- verify_sym_path("ONE_DOWN", 2, ("Kinclude_path", 4))
- verify_sym_path("ONE_DOWN", 3, ("Kinclude_path", 9))
- verify_sym_path("ONE_DOWN", 4, ("Kinclude_path", 9))
- verify_sym_path("ONE_DOWN", 5, ("Kinclude_path", 9))
- verify_sym_path("TWO_DOWN", 0,
- ("Kinclude_path", 4), ("Kinclude_path_sourced_1", 4))
- verify_sym_path("TWO_DOWN", 1,
- ("Kinclude_path", 4), ("Kinclude_path_sourced_1", 9))
- verify_sym_path("TWO_DOWN", 2,
- ("Kinclude_path", 9), ("Kinclude_path_sourced_1", 4))
- verify_sym_path("TWO_DOWN", 3,
- ("Kinclude_path", 9), ("Kinclude_path_sourced_1", 9))
- verify_node_path(c.top_node)
- verify_node_path(c.menus[0], ("Kinclude_path", 4), ("Kinclude_path_sourced_1", 4))
- verify_node_path(c.comments[0], ("Kinclude_path", 4), ("Kinclude_path_sourced_1", 4))
- verify_node_path(c.choices[0].nodes[0], ("Kinclude_path", 4), ("Kinclude_path_sourced_1", 4))
- os.environ.pop("srctree", None)
- print("Testing Kconfig.choices/menus/comments")
- c = Kconfig("Kconfiglib/tests/Kitemlists")
- def verify_prompts(items, *expected_prompts):
- verify(len(items) == len(expected_prompts),
- "Wrong number of prompts for {}".format(items))
- for item, expected_prompt in zip(items, expected_prompts):
- if not isinstance(item, MenuNode):
- item = item.nodes[0]
- verify(item.prompt[0] == expected_prompt,
- "Wrong prompt for {}, expected '{}'"
- .format(repr(item), expected_prompt))
- verify_prompts(c.choices, "choice 1", "choice 2", "choice 3", "choice 2")
- verify_prompts(c.menus, "menu 1", "menu 2", "menu 3", "menu 4", "menu 5")
- verify_prompts(c.comments, "comment 1", "comment 2", "comment 3")
- print("Testing Symbol/Choice.direct_dep")
- c = Kconfig("Kconfiglib/tests/Kdirdep")
- verify_equal(expr_str(c.syms["NO_DEP_SYM"].direct_dep), 'y')
- verify_equal(expr_str(c.syms["DEP_SYM"].direct_dep), "A || (B && C) || !D")
- verify_equal(expr_str(c.named_choices["NO_DEP_CHOICE"].direct_dep), 'y')
- verify_equal(expr_str(c.named_choices["DEP_CHOICE"].direct_dep),
- "A || B || C")
- print("Testing expr_items()")
- c = Kconfig("Kconfiglib/tests/Kexpr_items")
- def verify_expr_items(expr, *sym_names):
- verify_equal(tuple(sorted(item.name for item in expr_items(expr))),
- sym_names)
- verify_expr_items(
- c.syms["TEST"].defaults[0][0],
- "A", "B", "C", "D", "E", "F", "G", "H"
- )
- verify_expr_items(
- c.syms["TEST_CHOICE"].nodes[0].prompt[1],
- "A", "CHOICE"
- )
- print("Testing MenuNode/Symbol/Choice.referenced")
- c = Kconfig("Kconfiglib/tests/Kreferenced", warn=False)
- def verify_deps(item, *dep_names):
- verify_equal(tuple(sorted(item.name for item in item.referenced)),
- dep_names)
- verify_deps(c.top_node, "y")
- verify_deps(c.syms["NO_REFS"].nodes[0], "y")
- verify_deps(c.syms["JUST_DEPENDS_ON_REFS"].nodes[0], "A", "B")
- verify_deps(c.syms["LOTS_OF_REFS"].nodes[0],
- *(chr(n) for n in range(ord("A"), ord("Z") + 1)))
- verify_deps(c.syms["INT_REFS"].nodes[0],
- "A", "B", "C", "D", "E", "F", "G", "H", "y")
- verify_deps(c.syms["CHOICE_REF"].nodes[0], "CHOICE")
- verify_deps(c.menus[0], "A", "B", "C", "D")
- verify_deps(c.comments[0], "A", "B")
- verify_deps(c.syms["MULTI_DEF_SYM"], "A", "B", "C", "y")
- verify_deps(c.named_choices["MULTI_DEF_CHOICE"], "A", "B", "C")
- print("Testing split_expr()")
- c = Kconfig("Kconfiglib/tests/empty")
- c.warn = False
- def verify_split(to_split, op, operand_strs):
- # The same hackage as in Kconfig.eval_string()
- c._tokens = c._tokenize("if " + to_split)[1:]
- c._tokens_i = 0
- operands = split_expr(c._parse_expr(False), op)
- verify(len(operands) == len(operand_strs),
- "Wrong number of operands when {} was split by {}"
- .format(to_split, "OR" if op == OR else "AND"))
- for operand, operand_str in zip(operands, operand_strs):
- verify_equal(expr_str(operand), operand_str)
- verify_split("A", OR, ("A", ))
- verify_split("!A", OR, ("!A", ))
- verify_split("A = B", OR, ("A = B", ))
- verify_split("A && B", OR, ("A && B", ))
- verify_split("A || B", OR, ("A", "B" ))
- verify_split("(A || B) || C", OR, ("A", "B", "C" ))
- verify_split("A || (B || C)", OR, ("A", "B", "C" ))
- verify_split("A || !(B || C)", OR, ("A", "!(B || C)" ))
- verify_split("A || (B && (C || D))", OR, ("A", "B && (C || D)"))
- verify_split("(A && (B || C)) || D", OR, ("A && (B || C)", "D"))
- verify_split("A", AND, ("A", ))
- verify_split("!A", AND, ("!A", ))
- verify_split("A = B", AND, ("A = B", ))
- verify_split("A || B", AND, ("A || B", ))
- verify_split("A && B", AND, ("A", "B" ))
- verify_split("(A && B) && C", AND, ("A", "B", "C" ))
- verify_split("A && (B && C)", AND, ("A", "B", "C" ))
- verify_split("A && !(B && C)", AND, ("A", "!(B && C)" ))
- verify_split("A && (B || (C && D))", AND, ("A", "B || (C && D)"))
- verify_split("(A || (B && C)) && D", AND, ("A || (B && C)", "D"))
- print("Testing visibility")
- c = Kconfig("Kconfiglib/tests/Kvisibility")
- def verify_visibility(item, no_module_vis, module_vis):
- c.modules.set_value(0)
- verify(item.visibility == no_module_vis,
- "expected {} to have visibility {} without modules, had "
- "visibility {}".
- format(repr(item), no_module_vis, item.visibility))
- c.modules.set_value(2)
- verify(item.visibility == module_vis,
- "expected {} to have visibility {} with modules, had "
- "visibility {}".
- format(repr(item), module_vis, item.visibility))
- # Symbol visibility
- verify_visibility(c.syms["NO_PROMPT"], 0, 0)
- verify_visibility(c.syms["BOOL_N"], 0, 0)
- verify_visibility(c.syms["BOOL_M"], 0, 2)
- verify_visibility(c.syms["BOOL_MOD"], 2, 2)
- verify_visibility(c.syms["BOOL_Y"], 2, 2)
- verify_visibility(c.syms["TRISTATE_M"], 0, 1)
- verify_visibility(c.syms["TRISTATE_MOD"], 2, 1)
- verify_visibility(c.syms["TRISTATE_Y"], 2, 2)
- verify_visibility(c.syms["BOOL_IF_N"], 0, 0)
- verify_visibility(c.syms["BOOL_IF_M"], 0, 2)
- verify_visibility(c.syms["BOOL_IF_Y"], 2, 2)
- verify_visibility(c.syms["BOOL_MENU_N"], 0, 0)
- verify_visibility(c.syms["BOOL_MENU_M"], 0, 2)
- verify_visibility(c.syms["BOOL_MENU_Y"], 2, 2)
- verify_visibility(c.syms["BOOL_CHOICE_N"], 0, 0)
- # Non-tristate symbols in tristate choices are only visible if the choice
- # is in y mode
- # The choice can't be brought to y mode because of the 'if m'
- verify_visibility(c.syms["BOOL_CHOICE_M"], 0, 0)
- c.syms["BOOL_CHOICE_M"].choice.set_value(2)
- verify_visibility(c.syms["BOOL_CHOICE_M"], 0, 0)
- # The choice gets y mode only when running without modules, because it
- # defaults to m mode
- verify_visibility(c.syms["BOOL_CHOICE_Y"], 2, 0)
- c.syms["BOOL_CHOICE_Y"].choice.set_value(2)
- # When set to y mode, the choice symbol becomes visible both with and
- # without modules
- verify_visibility(c.syms["BOOL_CHOICE_Y"], 2, 2)
- verify_visibility(c.syms["TRISTATE_IF_N"], 0, 0)
- verify_visibility(c.syms["TRISTATE_IF_M"], 0, 1)
- verify_visibility(c.syms["TRISTATE_IF_Y"], 2, 2)
- verify_visibility(c.syms["TRISTATE_MENU_N"], 0, 0)
- verify_visibility(c.syms["TRISTATE_MENU_M"], 0, 1)
- verify_visibility(c.syms["TRISTATE_MENU_Y"], 2, 2)
- verify_visibility(c.syms["TRISTATE_CHOICE_N"], 0, 0)
- verify_visibility(c.syms["TRISTATE_CHOICE_M"], 0, 1)
- verify_visibility(c.syms["TRISTATE_CHOICE_Y"], 2, 2)
- verify_visibility(c.named_choices["BOOL_CHOICE_N"], 0, 0)
- verify_visibility(c.named_choices["BOOL_CHOICE_M"], 0, 2)
- verify_visibility(c.named_choices["BOOL_CHOICE_Y"], 2, 2)
- verify_visibility(c.named_choices["TRISTATE_CHOICE_N"], 0, 0)
- verify_visibility(c.named_choices["TRISTATE_CHOICE_M"], 0, 1)
- verify_visibility(c.named_choices["TRISTATE_CHOICE_Y"], 2, 2)
- verify_visibility(c.named_choices["TRISTATE_CHOICE_IF_M_AND_Y"], 0, 1)
- verify_visibility(c.named_choices["TRISTATE_CHOICE_MENU_N_AND_Y"], 0, 0)
- # Verify that 'visible if' visibility gets propagated to prompts
- verify_visibility(c.syms["VISIBLE_IF_N"], 0, 0)
- verify_visibility(c.syms["VISIBLE_IF_M"], 0, 1)
- verify_visibility(c.syms["VISIBLE_IF_Y"], 2, 2)
- verify_visibility(c.syms["VISIBLE_IF_M_2"], 0, 1)
- # Verify that string/int/hex symbols with m visibility accept a user value
- assign_and_verify("STRING_m", "foo bar")
- assign_and_verify("INT_m", "123")
- assign_and_verify("HEX_m", "0x123")
- print("Testing .assignable")
- c = Kconfig("Kconfiglib/tests/Kassignable")
- def verify_assignable_imp(item, assignable_no_modules, assignable_modules):
- # Verifies the assignable values for 'item', with and without modules.
- for modules_val, assignable in (0, assignable_no_modules), \
- (2, assignable_modules):
- c.modules.set_value(modules_val)
- module_msg = "without modules" if modules_val == 0 else \
- "with modules"
- verify(item.assignable == assignable,
- "Incorrect assignable values for {} {}. Should be {}, "
- "was {}."
- .format(item.name, module_msg, 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, module_msg))
- def verify_assignable(sym_name, assignable_no_modules, assignable_modules):
- verify_assignable_imp(c.syms[sym_name],
- assignable_no_modules,
- assignable_modules)
- def verify_const_unassignable(sym_name):
- verify_assignable_imp(c.const_syms[sym_name], (), ())
- # Things that shouldn't be .assignable
- verify_const_unassignable("n")
- verify_const_unassignable("m")
- verify_const_unassignable("y")
- verify_const_unassignable("const")
- 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), (0, 2))
- verify_assignable("M_VIS_BOOL", ( ), (0, 2)) # Vis. promoted
- verify_assignable("N_VIS_BOOL", ( ), ( ))
- verify_assignable("Y_VIS_TRI", (0, 2), (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,), (2,))
- verify_assignable("Y_SEL_M_VIS_BOOL", ( ), (2,)) # Vis. promoted
- verify_assignable("Y_SEL_N_VIS_BOOL", ( ), ( ))
- verify_assignable("Y_SEL_Y_VIS_TRI", (2,), (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,), ( 2,)) # Value promoted
- verify_assignable("M_SEL_M_VIS_BOOL", ( ), ( 2,)) # Vis./value promoted
- verify_assignable("M_SEL_N_VIS_BOOL", ( ), ( ))
- verify_assignable("M_SEL_Y_VIS_TRI", (2,), (1, 2 ))
- 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), (0, 2))
- verify_assignable("Y_IMP_M_VIS_BOOL", ( ), (0, 2)) # Vis. promoted
- verify_assignable("Y_IMP_N_VIS_BOOL", ( ), ( ))
- verify_assignable("Y_IMP_Y_VIS_TRI", (0, 2), (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), (0, 2))
- verify_assignable("M_IMP_M_VIS_BOOL", ( ), (0, 2)) # Vis. promoted
- verify_assignable("M_IMP_N_VIS_BOOL", ( ), ( ))
- verify_assignable("M_IMP_Y_VIS_TRI", (0, 2), (0, 1, 2))
- 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", (2,), (2,))
- verify_assignable("Y_CHOICE_TRISTATE", (2,), (2,))
- verify_assignable("Y_CHOICE_N_VIS_TRISTATE", ( ), ( ))
- # Symbols in m/y-mode choice, starting out in m mode, or y mode when
- # running without modules
- verify_assignable("MY_CHOICE_BOOL", (2,), ( ))
- verify_assignable("MY_CHOICE_TRISTATE", (2,), (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", (2,), (2,))
- verify_assignable("MY_CHOICE_TRISTATE", (2,), (2,))
- verify_assignable("MY_CHOICE_N_VIS_TRISTATE", ( ), ( ))
- def verify_choice_assignable(choice_name, assignable_no_modules,
- assignable_modules):
- verify_assignable_imp(c.named_choices[choice_name],
- assignable_no_modules,
- assignable_modules)
- # Choices with various possible modes
- verify_choice_assignable("Y_CHOICE", (2, ), ( 2,))
- verify_choice_assignable("MY_CHOICE", (2, ), ( 1, 2 ))
- verify_choice_assignable("NMY_CHOICE", (0, 2), (0, 1, 2 ))
- verify_choice_assignable("NY_CHOICE", (0, 2), (0, 2 ))
- verify_choice_assignable("NM_CHOICE", ( ), (0, 1 ))
- verify_choice_assignable("M_CHOICE", ( ), ( 1, ))
- verify_choice_assignable("N_CHOICE", ( ), ( ))
- print("Testing object relations")
- c = Kconfig("Kconfiglib/tests/Krelation")
- verify(c.syms["A"].nodes[0].parent is c.top_node,
- "A's parent should be the top node")
- verify(c.syms["B"].nodes[0].parent.item is c.named_choices["CHOICE_1"],
- "B's parent should be the first choice")
- verify(c.syms["C"].nodes[0].parent.item is c.syms["B"],
- "C's parent should be B (due to auto menus)")
- verify(c.syms["E"].nodes[0].parent.item == MENU,
- "E's parent should be a menu")
- verify(c.syms["E"].nodes[0].parent.parent is c.top_node,
- "E's grandparent should be the top node")
- verify(c.syms["G"].nodes[0].parent.item is c.named_choices["CHOICE_2"],
- "G's parent should be the second choice")
- verify(c.syms["G"].nodes[0].parent.parent.item == MENU,
- "G's grandparent should be a menu")
- print("Testing hex/int ranges")
- c = Kconfig("Kconfiglib/tests/Krange", warn=False)
- for sym_name in "HEX_NO_RANGE", "INT_NO_RANGE", "HEX_40", "INT_40":
- sym = c.syms[sym_name]
- verify(not sym.ranges,
- "{} should not have ranges".format(sym_name))
- for sym_name in "HEX_ALL_RANGES_DISABLED", "INT_ALL_RANGES_DISABLED", \
- "HEX_RANGE_10_20_LOW_DEFAULT", \
- "INT_RANGE_10_20_LOW_DEFAULT":
- sym = c.syms[sym_name]
- verify(sym.ranges, "{} should have ranges".format(sym_name))
- # hex/int symbols without defaults should get no default value
- verify_value("HEX_NO_RANGE", "")
- verify_value("INT_NO_RANGE", "")
- # And neither if all ranges are disabled
- verify_value("HEX_ALL_RANGES_DISABLED", "")
- verify_value("INT_ALL_RANGES_DISABLED", "")
- # Make sure they are assignable though, and test that the form of the user
- # value is reflected in the value for hex symbols
- assign_and_verify("HEX_NO_RANGE", "0x123")
- assign_and_verify("HEX_NO_RANGE", "123")
- assign_and_verify("INT_NO_RANGE", "123")
- # Defaults outside of the valid range should be clamped
- verify_value("HEX_RANGE_10_20_LOW_DEFAULT", "0x10")
- verify_value("HEX_RANGE_10_20_HIGH_DEFAULT", "0x20")
- verify_value("INT_RANGE_10_20_LOW_DEFAULT", "10")
- verify_value("INT_RANGE_10_20_HIGH_DEFAULT", "20")
- # Defaults inside the valid range should be preserved. For hex symbols,
- # they should additionally use the same form as in the assignment.
- verify_value("HEX_RANGE_10_20_OK_DEFAULT", "0x15")
- verify_value("HEX_RANGE_10_20_OK_DEFAULT_ALTERNATE", "15")
- verify_value("INT_RANGE_10_20_OK_DEFAULT", "15")
- # hex/int symbols with no defaults but valid ranges should default to the
- # lower end of the range if it's > 0
- verify_value("HEX_RANGE_10_20", "0x10")
- verify_value("HEX_RANGE_0_10", "")
- verify_value("INT_RANGE_10_20", "10")
- verify_value("INT_RANGE_0_10", "")
- verify_value("INT_RANGE_NEG_10_10", "")
- # User values and dependent ranges
- # Avoid warnings for assigning values outside the active range
- c.warn = False
- def verify_range(sym_name, low, high, default):
- # Verifies that all values in the range 'low'-'high' can be assigned,
- # and that assigning values outside the 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), True)
- if is_hex:
- # The form of the user value should be preserved for hex
- # symbols
- assign_and_verify_user_value(sym_name, hex(i), hex(i), True)
- # Verify that assigning a user value just outside the range causes
- # defaults to be used
- if default is None:
- default_str = ""
- else:
- default_str = hex(default) if is_hex else str(default)
- if is_hex:
- too_low_str = hex(low - 1)
- too_high_str = hex(high + 1)
- else:
- too_low_str = str(low - 1)
- too_high_str = str(high + 1)
- assign_and_verify_value(sym_name, too_low_str, default_str)
- assign_and_verify_value(sym_name, too_high_str, default_str)
- verify_range("HEX_RANGE_10_20_LOW_DEFAULT", 0x10, 0x20, 0x10)
- verify_range("HEX_RANGE_10_20_HIGH_DEFAULT", 0x10, 0x20, 0x20)
- verify_range("HEX_RANGE_10_20_OK_DEFAULT", 0x10, 0x20, 0x15)
- verify_range("INT_RANGE_10_20_LOW_DEFAULT", 10, 20, 10)
- verify_range("INT_RANGE_10_20_HIGH_DEFAULT", 10, 20, 20)
- verify_range("INT_RANGE_10_20_OK_DEFAULT", 10, 20, 15)
- verify_range("HEX_RANGE_10_20", 0x10, 0x20, 0x10)
- verify_range("INT_RANGE_10_20", 10, 20, 10)
- verify_range("INT_RANGE_0_10", 0, 10, None)
- verify_range("INT_RANGE_NEG_10_10", -10, 10, None)
- # Dependent ranges
- verify_value("HEX_40", "40")
- verify_value("INT_40", "40")
- c.syms["HEX_RANGE_10_20"].unset_value()
- c.syms["INT_RANGE_10_20"].unset_value()
- verify_value("HEX_RANGE_10_40_DEPENDENT", "0x10")
- verify_value("INT_RANGE_10_40_DEPENDENT", "10")
- c.syms["HEX_RANGE_10_20"].set_value("15")
- c.syms["INT_RANGE_10_20"].set_value("15")
- verify_value("HEX_RANGE_10_40_DEPENDENT", "0x15")
- verify_value("INT_RANGE_10_40_DEPENDENT", "15")
- c.unset_values()
- verify_range("HEX_RANGE_10_40_DEPENDENT", 0x10, 0x40, 0x10)
- verify_range("INT_RANGE_10_40_DEPENDENT", 10, 40, 10)
- # Ranges and symbols defined in multiple locations
- verify_value("INACTIVE_RANGE", "2")
- verify_value("ACTIVE_RANGE", "1")
- print("Testing defconfig_filename")
- c = Kconfig("Kconfiglib/tests/empty")
- verify(c.defconfig_filename is None,
- "defconfig_filename should be None with no defconfig_list symbol")
- c = Kconfig("Kconfiglib/tests/Kdefconfig_nonexistent")
- verify(c.defconfig_filename is None,
- "defconfig_filename should be None when none of the files in the "
- "defconfig_list symbol exist")
- # Referenced in Kdefconfig_existent(_but_n)
- os.environ["FOO"] = "defconfig_2"
- c = Kconfig("Kconfiglib/tests/Kdefconfig_existent_but_n")
- verify(c.defconfig_filename is None,
- "defconfig_filename should be None when the condition is n for all "
- "the defaults")
- c = Kconfig("Kconfiglib/tests/Kdefconfig_existent")
- verify(c.defconfig_filename == "Kconfiglib/tests/defconfig_2",
- "defconfig_filename should return the existing file "
- "Kconfiglib/tests/defconfig_2")
- # Should also look relative to $srctree if the specified defconfig is a
- # relative path and can't be opened
- c = Kconfig("Kconfiglib/tests/Kdefconfig_srctree")
- verify(c.defconfig_filename == "Kconfiglib/tests/defconfig_2",
- "defconfig_filename gave wrong file with $srctree unset")
- os.environ["srctree"] = "Kconfiglib/tests"
- c = Kconfig("Kdefconfig_srctree")
- verify(c.defconfig_filename == "Kconfiglib/tests/sub/defconfig_in_sub",
- "defconfig_filename gave wrong file with $srctree set")
- os.environ.pop("srctree", None)
- print("Testing mainmenu_text")
- c = Kconfig("Kconfiglib/tests/empty")
- verify(c.mainmenu_text == "Main menu",
- "An empty Kconfig should get a default main menu prompt")
- # Expanded in the mainmenu text
- os.environ["FOO"] = "bar baz"
- c = Kconfig("Kconfiglib/tests/Kmainmenu")
- verify(c.mainmenu_text == "---bar baz---",
- "Wrong mainmenu text")
- 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.warn = False
- syms = [c.syms[name] for name in
- ("BOOL", "TRISTATE", "STRING", "INT", "HEX")]
- for sym in syms:
- verify(sym.user_value is None,
- "{} should not have a user value to begin with")
- # Assign valid values for the types
- assign_and_verify_user_value("BOOL", 0, 0, True)
- assign_and_verify_user_value("BOOL", 2, 2, True)
- assign_and_verify_user_value("TRISTATE", 0, 0, True)
- assign_and_verify_user_value("TRISTATE", 1, 1, True)
- assign_and_verify_user_value("TRISTATE", 2, 2, True)
- assign_and_verify_user_value("STRING", "foo bar", "foo bar", True)
- assign_and_verify_user_value("INT", "123", "123", True)
- assign_and_verify_user_value("HEX", "0x123", "0x123", True)
- # Assign invalid values for the types. They should retain their old user
- # value.
- assign_and_verify_user_value("BOOL", 1, 2, False)
- assign_and_verify_user_value("BOOL", "foo", 2, False)
- assign_and_verify_user_value("BOOL", "1", 2, False)
- assign_and_verify_user_value("TRISTATE", "foo", 2, False)
- assign_and_verify_user_value("TRISTATE", "1", 2, False)
- assign_and_verify_user_value("STRING", 0, "foo bar", False)
- assign_and_verify_user_value("INT", "foo", "123", False)
- assign_and_verify_user_value("INT", 0, "123", False)
- assign_and_verify_user_value("HEX", "foo", "0x123", False)
- assign_and_verify_user_value("HEX", 0, "0x123", False)
- assign_and_verify_user_value("HEX", "-0x1", "0x123", False)
- for s in syms:
- s.unset_value()
- verify(s.user_value is None,
- "{} should not have a user value after being reset".
- format(s.name))
- print("Testing is_menuconfig")
- c = Kconfig("Kconfiglib/tests/Kmenuconfig")
- for not_menuconfig in c.syms["NOT_MENUCONFIG_1"].nodes[0], \
- c.syms["NOT_MENUCONFIG_2"].nodes[0], \
- c.syms["MENUCONFIG_MULTI_DEF"].nodes[0], \
- c.syms["COMMENT_HOOK"].nodes[0].next:
- verify(not not_menuconfig.is_menuconfig,
- "'{}' should have is_menuconfig False".format(not_menuconfig))
- for menuconfig in c.top_node, \
- c.syms["MENUCONFIG_1"].nodes[0], \
- c.syms["MENUCONFIG_MULTI_DEF"].nodes[1], \
- c.syms["MENU_HOOK"].nodes[0].next, \
- c.syms["CHOICE_HOOK"].nodes[0].next:
- verify(menuconfig.is_menuconfig,
- "'{}' should have is_menuconfig True".format(menuconfig))
- print("Testing 'option env' semantics")
- os.environ["ENV_VAR"] = "ENV_VAR value"
- # References undefined env. var., so disable warnings
- c = Kconfig("Kconfiglib/tests/Kmisc", warn=False)
- # Verify that 'option env' is treated like a default
- verify_value("FROM_ENV", "ENV_VAR value")
- verify_value("FROM_ENV_MISSING", "missing")
- verify_value("FROM_ENV_WEIRD", "weird")
- print("Testing defined vs undefined symbols")
- for name in "A", "B", "C", "D", "BOOL", "TRISTATE", "STRING", "INT", "HEX":
- verify(c.syms[name].nodes,
- "{} should be defined".format(name))
- for name in "NOT_DEFINED_1", "NOT_DEFINED_2", "NOT_DEFINED_3", \
- "NOT_DEFINED_4":
- sym = c.syms[name]
- verify(not c.syms[name].nodes,
- "{} should not be defined".format(name))
- print("Testing Symbol.choice")
- for name in "A", "B", "C", "D":
- verify(c.syms[name].choice is not None,
- "{} should be a choice symbol".format(name))
- for name in "Q1", "Q2", "Q3", "BOOL", "TRISTATE", "STRING", "INT", "HEX", \
- "FROM_ENV", "FROM_ENV_MISSING", "NOT_DEFINED_1", \
- "NOT_DEFINED_2", "NOT_DEFINED_3", "NOT_DEFINED_4":
- verify(c.syms[name].choice is None,
- "{} should not be a choice symbol".format(name))
- 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 .config reading and writing")
- config_test_file = "Kconfiglib/tests/config_test"
- def verify_file_contents(fname, contents):
- with open(fname, "r") as f:
- file_contents = f.read()
- verify(file_contents == contents,
- "{} contains '{}'. Expected '{}'."
- .format(fname, file_contents, contents))
- # Writing/reading strings with characters that need to be escaped
- c = Kconfig("Kconfiglib/tests/Kescape")
- # Test the default value
- c.write_config(config_test_file + "_from_def")
- verify_file_contents(config_test_file + "_from_def",
- r'''CONFIG_STRING="\"\\"''' "\n")
- # Write our own value
- c.syms["STRING"].set_value(r'''\"a'\\''')
- c.write_config(config_test_file + "_from_user")
- verify_file_contents(config_test_file + "_from_user",
- r'''CONFIG_STRING="\\\"a'\\\\"''' "\n")
- # Read back the two configs and verify the respective values
- c.load_config(config_test_file + "_from_def")
- verify_value("STRING", '"\\')
- c.load_config(config_test_file + "_from_user")
- verify_value("STRING", r'''\"a'\\''')
- # Appending values from a .config
- c = Kconfig("Kconfiglib/tests/Kappend")
- # Values before assigning
- verify_value("BOOL", "n")
- verify_value("STRING", "")
- # Assign BOOL
- c.load_config("Kconfiglib/tests/config_set_bool", replace=False)
- verify_value("BOOL", "y")
- verify_value("STRING", "")
- # Assign STRING
- c.load_config("Kconfiglib/tests/config_set_string", replace=False)
- verify_value("BOOL", "y")
- verify_value("STRING", "foo bar")
- # Reset BOOL
- c.load_config("Kconfiglib/tests/config_set_string")
- verify_value("BOOL", "n")
- verify_value("STRING", "foo bar")
- # Loading a completely empty .config should reset values
- c.load_config("Kconfiglib/tests/empty")
- verify_value("STRING", "")
- # An indented assignment in a .config should be ignored
- c.load_config("Kconfiglib/tests/config_indented")
- verify_value("IGNOREME", "y")
- # Symbol order in headers and minimal configuration files should match
- # definition order, like in .config files
- c = Kconfig("Kconfiglib/tests/Korder")
- c.write_autoconf(config_test_file)
- verify_file_contents(config_test_file, """
- #define CONFIG_O 0
- #define CONFIG_R 1
- #define CONFIG_D 2
- #define CONFIG_E 3
- #define CONFIG_R2 4
- #define CONFIG_I 5
- #define CONFIG_N 6
- #define CONFIG_G 7
- """[1:])
- # Differs from defaults
- c.syms["O"].set_value("-1")
- c.syms["R"].set_value("-1")
- c.syms["E"].set_value("-1")
- c.syms["R2"].set_value("-1")
- c.syms["N"].set_value("-1")
- c.syms["G"].set_value("-1")
- c.write_min_config(config_test_file)
- verify_file_contents(config_test_file, """
- CONFIG_O=-1
- CONFIG_R=-1
- CONFIG_E=-1
- CONFIG_R2=-1
- CONFIG_N=-1
- CONFIG_G=-1
- """[1:])
- # Test header strings in configuration files and headers
- os.environ["KCONFIG_CONFIG_HEADER"] = "config header from env.\n"
- os.environ["KCONFIG_AUTOHEADER_HEADER"] = "header header from env.\n"
- c = Kconfig("Kconfiglib/tests/Kheader")
- c.write_config(config_test_file, header="config header from param\n")
- verify_file_contents(config_test_file, """\
- config header from param
- CONFIG_FOO=y
- """)
- c.write_min_config(config_test_file, header="min. config header from param\n")
- verify_file_contents(config_test_file, """\
- min. config header from param
- """)
- c.write_config(config_test_file)
- verify_file_contents(config_test_file, """\
- config header from env.
- CONFIG_FOO=y
- """)
- c.write_min_config(config_test_file)
- verify_file_contents(config_test_file, """\
- config header from env.
- """)
- c.write_autoconf(config_test_file, header="header header from param\n")
- verify_file_contents(config_test_file, """\
- header header from param
- #define CONFIG_FOO 1
- """)
- c.write_autoconf(config_test_file)
- verify_file_contents(config_test_file, """\
- header header from env.
- #define CONFIG_FOO 1
- """)
- del os.environ["KCONFIG_CONFIG_HEADER"]
- del os.environ["KCONFIG_AUTOHEADER_HEADER"]
- 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")
- c = Kconfig("Kconfiglib/tests/Kimply")
- verify_value("IMPLY_DIRECT_DEPS", "y")
- verify_value("UNMET_DIRECT_1", "n")
- verify_value("UNMET_DIRECT_2", "n")
- verify_value("UNMET_DIRECT_3", "n")
- verify_value("MET_DIRECT_1", "y")
- verify_value("MET_DIRECT_2", "y")
- verify_value("MET_DIRECT_3", "y")
- verify_value("MET_DIRECT_4", "y")
- verify_value("IMPLY_COND", "y")
- verify_value("IMPLIED_N_COND", "n")
- verify_value("IMPLIED_M_COND", "m")
- verify_value("IMPLIED_Y_COND", "y")
- verify_value("IMPLY_N_1", "n")
- verify_value("IMPLY_N_2", "n")
- verify_value("IMPLIED_FROM_N_1", "n")
- verify_value("IMPLIED_FROM_N_2", "n")
- verify_value("IMPLY_M", "m")
- verify_value("IMPLIED_M", "m")
- verify_value("IMPLIED_M_BOOL", "y")
- verify_value("IMPLY_M_TO_Y", "y")
- verify_value("IMPLIED_M_TO_Y", "y")
- # Test user value semantics
- # Verify that IMPLIED_TRISTATE is invalidated if the direct
- # dependencies change
- assign_and_verify("IMPLY", 2)
- assign_and_verify("DIRECT_DEP", 2)
- verify_value("IMPLIED_TRISTATE", 2)
- assign_and_verify("DIRECT_DEP", 0)
- verify_value("IMPLIED_TRISTATE", 0)
- # Set back for later tests
- assign_and_verify("DIRECT_DEP", 2)
- # Verify that IMPLIED_TRISTATE can be set to anything when IMPLY has value
- # n, and that it gets the value n by default (for non-imply-related
- # reasons)
- assign_and_verify("IMPLY", 0)
- assign_and_verify("IMPLIED_TRISTATE", 0)
- assign_and_verify("IMPLIED_TRISTATE", 1)
- assign_and_verify("IMPLIED_TRISTATE", 2)
- c.syms["IMPLIED_TRISTATE"].unset_value()
- verify_value("IMPLIED_TRISTATE", "n")
- # Same as above for m. Anything still goes, but m by default now.
- assign_and_verify("IMPLY", 1)
- assign_and_verify("IMPLIED_TRISTATE", 0)
- assign_and_verify("IMPLIED_TRISTATE", 1)
- assign_and_verify("IMPLIED_TRISTATE", 2)
- c.syms["IMPLIED_TRISTATE"].unset_value()
- verify_value("IMPLIED_TRISTATE", 1)
- # Same as above for y. Only n and y should be accepted. m gets promoted to
- # y. Default should be y.
- assign_and_verify("IMPLY", 2)
- assign_and_verify("IMPLIED_TRISTATE", 0)
- assign_and_verify_value("IMPLIED_TRISTATE", 1, 2)
- assign_and_verify("IMPLIED_TRISTATE", 2)
- c.syms["IMPLIED_TRISTATE"].unset_value()
- verify_value("IMPLIED_TRISTATE", 2)
- # Being implied to either m or y should give a bool the value y
- c.syms["IMPLY"].unset_value()
- verify_value("IMPLIED_BOOL", 0)
- assign_and_verify("IMPLY", 0)
- verify_value("IMPLIED_BOOL", 0)
- assign_and_verify("IMPLY", 1)
- verify_value("IMPLIED_BOOL", 2)
- assign_and_verify("IMPLY", 2)
- verify_value("IMPLIED_BOOL", 2)
- # A bool implied to m or y can take the values n and y
- c.syms["IMPLY"].set_value(1)
- assign_and_verify("IMPLIED_BOOL", 0)
- assign_and_verify("IMPLIED_BOOL", 2)
- c.syms["IMPLY"].set_value(2)
- assign_and_verify("IMPLIED_BOOL", 0)
- assign_and_verify("IMPLIED_BOOL", 2)
- print("Testing choice semantics")
- # Would warn for choice value symbols defined without a type, even
- # though the type is automatically derived. This is probably more
- # helpful than ignoring those cases, as this feature isn't used
- # deliberately anywhere from what I've seen.
- c = Kconfig("Kconfiglib/tests/Kchoice", warn=False)
- 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 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
- choice.set_value(2)
- sym.set_value(2)
- verify(sym.choice.selection is sym,
- sym.name + " should be the selected symbol")
- verify(choice.user_selection is sym,
- sym.name + " should be the user selection of the choice")
- verify(sym.tri_value == 2,
- sym.name + " should have value y when selected")
- verify(sym.user_value == 2,
- sym.name + " should have user value y when selected")
- for sibling in choice.syms:
- if sibling is not sym:
- verify(sibling.tri_value == 0,
- sibling.name + " should be n when not selected")
- 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)
- # Select in reverse order
- for sym in reversed(choice.syms):
- select_and_verify(sym)
- 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 {}.'
- .format(choice.name, no_modules_mode, choice.tri_value))
- c.modules.set_value(2)
- verify(choice.tri_value == modules_mode,
- 'Wrong mode for choice {} with modules. Expected {}, got {}.'
- .format(choice.name, modules_mode, choice.tri_value))
- 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.selection is c.syms["OPT_4"],
- "Wrong choice default with TRISTATE_SYM = n")
- c.syms["TRISTATE_SYM"].set_value(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.selection is c.syms["OPT_1"],
- "User selection should override defaults")
- 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")
- # Test y mode selection
- c.modules.set_value(2)
- 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("BOOL_M")
- # Test m mode selection
- c.named_choices["TRISTATE"].set_value(1)
- verify(c.named_choices["TRISTATE"].tri_value == 1,
- "TRISTATE choice should have mode m after explicit mode assignment")
- assign_and_verify_value("T_1", 0, 0)
- assign_and_verify_value("T_2", 0, 0)
- assign_and_verify_value("T_1", 1, 1)
- assign_and_verify_value("T_2", 1, 1)
- assign_and_verify_value("T_1", 2, 1)
- assign_and_verify_value("T_2", 2, 1)
- # Switching to y mode should cause T_2 to become selected
- c.named_choices["TRISTATE"].set_value(2)
- verify_value("T_1", 0)
- verify_value("T_2", 2)
- # Verify that choices with no explicitly specified type get the type of the
- # first contained symbol with a type
- verify(c.named_choices["NO_TYPE_BOOL"].orig_type == BOOL,
- "Expected first choice without explicit type to have type bool")
- 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
- 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_3"].orig_type == TRISTATE,
- "Expected MMT_3 to have type tristate")
- # Verify that the default selection can change depending on the
- # visibility of the choice symbols
- default_with_dep_choice = c.named_choices["DEFAULT_WITH_DEP"]
- verify(default_with_dep_choice.selection is c.syms["B"],
- "Wrong choice default with unsatisfied deps on default")
- c.syms["DEP"].set_value("y")
- verify(default_with_dep_choice.selection is c.syms["A"],
- "Wrong choice default with satisfied deps on default")
- c.syms["DEP"].set_value("n")
- verify(default_with_dep_choice.selection is c.syms["B"],
- "Wrong choice default with unsatisfied deps on default (round two)")
- # 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 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 weird_choice.syms,
- "{} should be a weird (non-)choice symbol"
- .format(sym.name))
- verify_is_normal_choice_symbol("WS1")
- verify_is_weird_choice_symbol("WS2")
- verify_is_weird_choice_symbol("WS3")
- verify_is_weird_choice_symbol("WS4")
- verify_is_weird_choice_symbol("WS5")
- verify_is_normal_choice_symbol("WS6")
- verify_is_weird_choice_symbol("WS7")
- verify_is_weird_choice_symbol("WS8")
- verify_is_normal_choice_symbol("WS9")
- print("Testing 'if' node removal")
- c = Kconfig("Kconfiglib/tests/Kifremoval", warn=False)
- nodes = tuple(c.node_iter())
- verify_equal(nodes[0].item.name, "A")
- verify_equal(nodes[1].item.name, "B")
- verify_equal(nodes[2].item.name, "C")
- verify_equal(nodes[3].item.name, "D")
- verify_equal(nodes[4].prompt[0], "E")
- verify_equal(nodes[5].prompt[0], "F")
- verify_equal(nodes[6].prompt[0], "G")
- verify_equal(nodes[7].item.name, "H")
- verify_equal(nodes[8].item.name, "I")
- verify_equal(nodes[9].item.name, "J")
- verify(len(nodes) == 10,
- "Wrong number of nodes after 'if' removal")
- print("Testing multi.def. property copying")
- c = Kconfig("Kconfiglib/tests/Kdepcopy", warn=False)
- def verify_props(desc, props, prop_names):
- actual = [prop[0].name for prop in props]
- expected = prop_names.split()
- verify(actual == expected,
- "Wrong {} properties, expected '{}', got '{}'"
- .format(desc, expected, actual))
- verify_props("default", c.syms["MULTIDEF"].defaults,
- "A B C D E F G H I J K L M N O P Q R")
- verify_props("select", c.syms["MULTIDEF"].selects,
- "AA BB CC DD EE FF GG HH II JJ")
- verify_props("imply", c.syms["MULTIDEF"].selects,
- "AA BB CC DD EE FF GG HH II JJ")
- verify_props("select", c.syms["MULTIDEF_CHOICE"].selects,
- "A B C")
- verify_props("range", c.syms["MULTIDEF_RANGE"].ranges,
- "A B C D E F")
- verify_props("default", c.choices[1].defaults,
- "A B C D E")
- print("Testing dependency loop detection")
- # These are all expected to raise dependency loop errors
- for i in range(11):
- filename = "Kconfiglib/tests/Kdeploop" + str(i)
- try:
- Kconfig(filename)
- except KconfigError as e:
- if "Dependency loop" not in str(e):
- fail("dependency loop in {} raised wrong KconfigError"
- .format(filename))
- except:
- fail("dependency loop in {} raised wrong exception"
- .format(filename))
- else:
- fail("dependency loop in {} not detected".format(filename))
- # Check the most complicated message completely
- try:
- Kconfig("Kconfiglib/tests/Kdeploop10")
- except KconfigError as e:
- verify_equal(str(e), """
- Dependency loop
- ===============
- A (defined at Kconfiglib/tests/Kdeploop10:1), with definition...
- config A
- bool
- depends on B
- ...depends on B (defined at Kconfiglib/tests/Kdeploop10:5), with definition...
- config B
- bool
- depends on C = 7
- ...depends on C (defined at Kconfiglib/tests/Kdeploop10:9), with definition...
- config C
- int
- range D 8
- ...depends on D (defined at Kconfiglib/tests/Kdeploop10:13), with definition...
- config D
- int
- default 3 if E
- default 8
- ...depends on E (defined at Kconfiglib/tests/Kdeploop10:18), with definition...
- config E
- bool
- (select-related dependencies: F && G)
- ...depends on G (defined at Kconfiglib/tests/Kdeploop10:25), with definition...
- config G
- bool
- depends on H
- ...depends on the choice symbol H (defined at Kconfiglib/tests/Kdeploop10:32), with definition...
- config H
- bool "H"
- depends on I && <choice>
- ...depends on the choice symbol I (defined at Kconfiglib/tests/Kdeploop10:41), with definition...
- config I
- bool "I"
- depends on <choice>
- ...depends on <choice> (defined at Kconfiglib/tests/Kdeploop10:38), with definition...
- choice
- bool "choice" if J
- ...depends on J (defined at Kconfiglib/tests/Kdeploop10:46), with definition...
- config J
- bool
- depends on A
- ...depends again on A (defined at Kconfiglib/tests/Kdeploop10:1)
- """[:-1])
- except:
- fail("Loop detection message check raised wrong exception")
- else:
- fail("Loop detection message check did not raise exception")
- print("Testing preprocessor")
- os.environ["ENV_1"] = "env_1"
- os.environ["ENV_2"] = "env_2"
- os.environ["ENV_3"] = "env_3"
- os.environ["ENV_4"] = "env_4"
- os.environ["ENV_5"] = "n"
- os.environ["ENV_6"] = "Kconfiglib/tests/empty"
- os.environ["ENV_7"] = "env_7"
- # We verify warnings manually
- c = Kconfig("Kconfiglib/tests/Kpreprocess", warn_to_stderr=False)
- def verify_variable(name, unexp_value, exp_value, recursive, *args):
- var = c.variables[name]
- verify(var.value == unexp_value,
- "expected variable '{}' to have the unexpanded value '{}', had "
- "the value '{}'".format(name, unexp_value, var.value))
- if not args:
- verify(var.expanded_value == exp_value,
- "expected expanded_value for {} to be '{}', was '{}'"
- .format(name, exp_value, var.expanded_value))
- verify(var.expanded_value_w_args(*args) == exp_value,
- "expected expanded_value_w_args() for '{}' to be '{}', was '{}'"
- .format(name, exp_value, var.expanded_value_w_args(*args)))
- verify(var.is_recursive == recursive,
- "{} was {}, shouldn't be"
- .format(name, "recursive" if var.is_recursive else "simple"))
- verify_variable("simple-recursive", "foo", "foo", True)
- verify_variable("simple-immediate", "bar", "bar", False)
- verify_variable("simple-recursive-2", "baz", "baz", True)
- verify_variable("whitespaced", "foo", "foo", True)
- verify_variable("preserve-recursive", "foo bar", "foo bar", True)
- verify_variable("preserve-immediate", "foo bar", "foo bar", False)
- verify_variable("recursive",
- "$(foo) $(bar) $($(b-char)a$(z-char)) $(indir)",
- "abc def ghi jkl mno",
- True)
- verify_variable("immediate", "foofoo", "foofoo", False)
- verify_variable("messy-fn-res",
- "$($(fn-indir)-unused-arg, a b (,) , c d )",
- 'surround-rev-quote " c d " " a b (,) " surround-rev-quote ',
- True)
- verify_variable("special-chars-fn-res",
- "$(fn,$(comma)$(dollar)$(left-paren)foo$(right-paren))",
- '",$(foo)"',
- True)
- verify_variable("quote", '"$(1)" "$(2)"', '"" ""', True)
- verify_variable("quote", '"$(1)" "$(2)"', '"one" ""', True,
- "one")
- verify_variable("quote", '"$(1)" "$(2)"', '"one" "two"', True,
- "one", "two")
- verify_variable("quote", '"$(1)" "$(2)"', '"one" "two"', True,
- "one", "two", "three")
- verify_str(c.syms["PRINT_ME"], r"""
- config PRINT_ME
- string "env_1" if (FOO && BAR) || !BAZ || !QAZ
- default "\"foo\"" if "foo \"bar\" baz" = ""
- """)
- verify_str(c.syms["PRINT_ME_TOO"], r"""
- config PRINT_ME_TOO
- bool "foo"
- default FOOBARBAZQAZ if QAZ && QAZFOO && xxx
- """)
- def verify_repr(name, s):
- verify_equal(repr(c.variables[name]), s)
- verify_repr(
- "simple-immediate",
- "<variable simple-immediate, immediate, value 'bar'>")
- verify_repr(
- "messy-fn-res",
- "<variable messy-fn-res, recursive, value '$($(fn-indir)-unused-arg, a b (,) , c d )'>")
- def verify_recursive(name):
- try:
- c.variables[name].expanded_value
- except KconfigError:
- pass
- else:
- fail("Expected '{}' expansion to flag recursive expansion, didn't"
- .format(name))
- verify_recursive("rec-1")
- # Indirectly verifies that it's not recursive
- verify_variable("safe-fn-rec-res",
- "$(safe-fn-rec,safe-fn-rec-2)",
- "foo",
- True)
- verify_recursive("unsafe-fn-rec")
- verify_variable("foo-bar-baz", "$(rhs)", "value", True)
- verify_variable("space-var-res", "$(foo bar)", "value", True)
- verify_variable("shell-res",
- "$(shell,false && echo foo bar || echo baz qaz)",
- "baz qaz",
- True)
- verify_variable("shell-stderr-res", "", "", False)
- verify_variable("parens-res",
- "pre-$(shell,echo '(a,$(b-char),(c,d),e)')-post",
- "pre-(a,b,(c,d),e)-post",
- True)
- verify_variable("location-res",
- "Kconfiglib/tests/Kpreprocess:129",
- "Kconfiglib/tests/Kpreprocess:129",
- False)
- verify_variable("warning-res", "", "", False)
- verify_variable("error-n-res", "", "", False)
- try:
- c.variables["error-y-res"].expanded_value
- except KconfigError:
- pass
- else:
- fail("expanding error-y-res didn't raise an exception")
- # Check Kconfig.env_vars
- verify_equal(c.env_vars,
- set(("ENV_1", "ENV_2", "ENV_3", "ENV_4", "ENV_5", "ENV_6")))
- # Check that the expected warnings were generated
- verify_equal(c.warnings, [
- "Kconfiglib/tests/Kpreprocess:122: warning: 'echo message on stderr >&2' wrote to stderr: message on stderr",
- "Kconfiglib/tests/Kpreprocess:134: warning: a warning"
- ])
- print("Testing user-defined preprocessor functions")
- # Make Kconfiglib/tests/kconfigfunctions.py importable
- sys.path.insert(0, "Kconfiglib/tests")
- c = Kconfig("Kconfiglib/tests/Kuserfunctions")
- verify_variable("add-zero", "$(add)", "0", True)
- verify_variable("add-one", "$(add,1)", "1", True)
- verify_variable("add-three", "$(add,1,-1,2,1)", "3", True)
- verify_variable("one-one", "$(one,foo bar)", "onefoo barfoo bar", True)
- verify_variable("one-or-more-one", "$(one-or-more,foo)", "foo + ", True)
- verify_variable("one-or-more-three", "$(one-or-more,foo,bar,baz)",
- "foo + bar,baz", True)
- verify_variable("location-1", "Kconfiglib/tests/Kuserfunctions:13",
- "Kconfiglib/tests/Kuserfunctions:13", False)
- verify_variable("location-2", "Kconfiglib/tests/Kuserfunctions:14",
- "Kconfiglib/tests/Kuserfunctions:14", False)
- def verify_bad_argno(name):
- try:
- c.variables[name].expanded_value
- except KconfigError:
- pass
- else:
- fail("Expected '{}' expansion to flag wrong number of arguments, "
- "didn't".format(name))
- verify_bad_argno("one-zero")
- verify_bad_argno("one-two")
- verify_bad_argno("one-or-more-zero")
- sys.path.pop(0)
- # This test can fail on older Python 3.x versions, because they don't
- # preserve dict insertion order during iteration. The output is still
- # correct, just different.
- if not (3, 0) <= sys.version_info <= (3, 5):
- print("Testing KCONFIG_WARN_UNDEF")
- os.environ["KCONFIG_WARN_UNDEF"] = "y"
- c = Kconfig("Kconfiglib/tests/Kundef", warn_to_stderr=False)
- verify_equal("\n".join(c.warnings), """
- warning: the int symbol INT (defined at Kconfiglib/tests/Kundef:8) has a non-int range [UNDEF_2 (undefined), 8 (undefined)]
- warning: undefined symbol UNDEF_1:
- - Referenced at Kconfiglib/tests/Kundef:4:
- config BOOL
- bool "foo" if DEF || !UNDEF_1
- default UNDEF_2
- - Referenced at Kconfiglib/tests/Kundef:19:
- menu "menu"
- depends on UNDEF_1
- visible if UNDEF_3
- warning: undefined symbol UNDEF_2:
- - Referenced at Kconfiglib/tests/Kundef:4:
- config BOOL
- bool "foo" if DEF || !UNDEF_1
- default UNDEF_2
- - Referenced at Kconfiglib/tests/Kundef:8:
- config INT
- int
- range UNDEF_2 8
- range 5 15
- default 10
- warning: undefined symbol UNDEF_3:
- - Referenced at Kconfiglib/tests/Kundef:19:
- menu "menu"
- depends on UNDEF_1
- visible if UNDEF_3
- """[1:-1])
- os.environ.pop("KCONFIG_WARN_UNDEF")
- print("\nAll selftests passed\n" if all_passed else
- "\nSome selftests failed\n")
- def run_compatibility_tests():
- # Runs tests on configurations from the kernel. Tests compability with the
- # C implementation by comparing outputs.
- # Referenced inside the kernel Kconfig files.
- #
- # The str() makes the type of the value 'str' on both Python 2 and Python 3,
- # which is nice for some later dictionary key sanity checks.
- os.environ["KERNELVERSION"] = str(
- subprocess.check_output("make kernelversion", shell=True)
- .decode("utf-8").rstrip()
- )
- os.environ["CC_VERSION_TEXT"] = str(
- subprocess.check_output("gcc --version | head -n1", shell=True)
- .decode("utf-8").rstrip()
- )
- os.environ["srctree"] = "."
- os.environ["CC"] = "gcc"
- os.environ["LD"] = "ld"
- if not os.path.exists("scripts/kconfig/conf"):
- print("\nscripts/kconfig/conf does not exist -- running "
- "'make allnoconfig' to build it...")
- shell("make allnoconfig")
- print("Running compatibility tests...\n")
- test_fns = (test_defconfig,
- # Fails for a few defconfigs due to a bug in the C tools. Will
- # be enabled once patches get in.
- #test_min_config,
- test_alldefconfig,
- test_allnoconfig,
- test_allnoconfig_walk,
- test_allmodconfig,
- test_allyesconfig,
- test_sanity)
- for test_fn in test_fns:
- # The test description is taken from the docstring of the corresponding
- # function
- print(textwrap.dedent(test_fn.__doc__))
- for arch, srcarch in all_arch_srcarch():
- # Referenced inside the Kconfig files
- os.environ["ARCH"] = arch
- os.environ["SRCARCH"] = srcarch
- rm_configs()
- test_fn(arch, srcarch)
- if all_passed:
- print("All selftests and compatibility tests passed")
- else:
- sys.exit("Some tests failed")
- def all_arch_srcarch():
- for srcarch in os.listdir("arch"):
- # arc and h8300 are currently broken with the C tools on linux-next as
- # well. Perhaps they require cross-compilers to be installed.
- #
- # User-mode Linux has an unorthodox Kconfig setup that would require a
- # different testing setup. Skip it too.
- if srcarch in ("arc", "h8300", "um"):
- continue
- if os.path.exists(os.path.join("arch", srcarch, "Kconfig")):
- yield (srcarch, srcarch)
- # Some arches define additional ARCH settings with ARCH != SRCARCH
- # (search for "Additional ARCH settings for" in the top-level Makefile)
- yield ("i386", "x86")
- yield ("x86_64", "x86")
- yield ("sparc32", "sparc")
- yield ("sparc64", "sparc")
- yield ("sh64", "sh")
- def test_allnoconfig(arch, srcarch):
- """
- Verify that allnoconfig.py generates the same .config as
- 'make allnoconfig', for each architecture. Runs the script via
- 'make scriptconfig'.
- """
- shell("make scriptconfig SCRIPT=Kconfiglib/allnoconfig.py "
- "PYTHONCMD='{}'".format(sys.executable))
- shell("mv .config ._config")
- shell("scripts/kconfig/conf --allnoconfig Kconfig")
- compare_configs(arch)
- def test_allnoconfig_walk(arch, srcarch):
- """
- Verify that examples/allnoconfig_walk.py generates the same .config as
- 'make allnoconfig', for each architecture. Runs the script via
- 'make scriptconfig'.
- """
- shell("make scriptconfig SCRIPT=Kconfiglib/examples/allnoconfig_walk.py "
- "PYTHONCMD='{}'".format(sys.executable))
- shell("mv .config ._config")
- shell("scripts/kconfig/conf --allnoconfig Kconfig")
- compare_configs(arch)
- def test_allmodconfig(arch, srcarch):
- """
- Verify that allmodconfig.py generates the same .config as
- 'make allmodconfig', for each architecture. Runs the script via
- 'make scriptconfig'.
- """
- shell("make scriptconfig SCRIPT=Kconfiglib/allmodconfig.py "
- "PYTHONCMD='{}'".format(sys.executable))
- shell("mv .config ._config")
- shell("scripts/kconfig/conf --allmodconfig Kconfig")
- compare_configs(arch)
- def test_allyesconfig(arch, srcarch):
- """
- Verify that allyesconfig.py generates the same .config as
- 'make allyesconfig', for each architecture. Runs the script via
- 'make scriptconfig'.
- """
- shell("make scriptconfig SCRIPT=Kconfiglib/allyesconfig.py "
- "PYTHONCMD='{}'".format(sys.executable))
- shell("mv .config ._config")
- shell("scripts/kconfig/conf --allyesconfig Kconfig")
- compare_configs(arch)
- def test_sanity(arch, srcarch):
- """
- 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))
- kconf = Kconfig()
- for sym in kconf.defined_syms:
- verify(sym._visited == 2,
- "{} has broken dependency loop detection (_visited = {})"
- .format(sym.name, sym._visited))
- kconf.modules
- kconf.defconfig_list
- kconf.defconfig_filename
- # Legacy warning functions
- kconf.enable_redun_warnings()
- kconf.disable_redun_warnings()
- kconf.enable_undef_warnings()
- kconf.disable_undef_warnings()
- kconf.enable_warnings()
- kconf.disable_warnings()
- kconf.enable_stderr_warnings()
- kconf.disable_stderr_warnings()
- kconf.mainmenu_text
- kconf.unset_values()
- kconf.write_autoconf("/dev/null")
- # No tempfile.TemporaryDirectory in Python 2
- tmpdir = tempfile.mkdtemp()
- kconf.sync_deps(os.path.join(tmpdir, "deps")) # Create
- kconf.sync_deps(os.path.join(tmpdir, "deps")) # Update
- shutil.rmtree(tmpdir)
- # Python 2/3 compatible
- for key, sym in kconf.syms.items():
- verify(isinstance(key, str), "weird key '{}' in syms dict".format(key))
- verify(not sym.is_constant, sym.name + " in 'syms' and constant")
- verify(sym not in kconf.const_syms,
- sym.name + " in both 'syms' and 'const_syms'")
- for dep in sym._dependents:
- verify(not dep.is_constant,
- "the constant symbol {} depends on {}"
- .format(dep.name, sym.name))
- sym.__repr__()
- sym.__str__()
- sym.assignable
- kconf.disable_warnings()
- sym.set_value(2)
- sym.set_value("foo")
- sym.unset_value()
- kconf.enable_warnings() # Legacy warning function
- sym.str_value
- sym.tri_value
- sym.type
- sym.user_value
- sym.visibility
- for sym in kconf.defined_syms:
- verify(sym.nodes, sym.name + " is defined but lacks menu nodes")
- verify(not (sym.orig_type not in (BOOL, TRISTATE) and sym.choice),
- sym.name + " is a choice symbol but not bool/tristate")
- for key, sym in kconf.const_syms.items():
- verify(isinstance(key, str),
- "weird key '{}' in const_syms dict".format(key))
- verify(sym.is_constant,
- '"{}" is in const_syms but not marked constant'
- .format(sym.name))
- verify(not sym.nodes,
- '"{}" is constant but has menu nodes'.format(sym.name))
- verify(not sym._dependents,
- '"{}" is constant but is a dependency of some symbol'
- .format(sym.name))
- verify(not sym.choice,
- '"{}" is constant and a choice symbol'.format(sym.name))
- sym.__repr__()
- sym.__str__()
- sym.assignable
- kconf.disable_warnings()
- sym.set_value(2)
- sym.set_value("foo")
- sym.unset_value()
- kconf.enable_warnings() # Legacy warning function
- sym.str_value
- sym.tri_value
- sym.type
- sym.visibility
- for choice in kconf.choices:
- for sym in choice.syms:
- verify(sym.choice is choice,
- "{0} is in choice.syms but 'sym.choice' is not the choice"
- .format(sym.name))
- verify(sym.type in (BOOL, TRISTATE),
- "{} is a choice symbol but is not a bool/tristate"
- .format(sym.name))
- choice.__str__()
- choice.__repr__()
- choice.str_value
- choice.tri_value
- choice.user_value
- choice.assignable
- choice.selection
- choice.type
- choice.visibility
- # Menu nodes
- node = kconf.top_node
- while 1:
- # Everything else should be well exercised elsewhere
- node.__repr__()
- node.__str__()
- verify(isinstance(node.item, (Symbol, Choice)) or \
- node.item in (MENU, COMMENT),
- "'{}' appeared as a menu item".format(node.item))
- 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(arch, srcarch):
- """
- Verify that alldefconfig.py generates the same .config as
- 'make alldefconfig', for each architecture. Runs the script via
- 'make scriptconfig'.
- """
- shell("make scriptconfig SCRIPT=Kconfiglib/alldefconfig.py "
- "PYTHONCMD='{}'".format(sys.executable))
- shell("mv .config ._config")
- shell("scripts/kconfig/conf --alldefconfig Kconfig")
- compare_configs(arch)
- def test_defconfig(arch, srcarch):
- """
- Verify that Kconfiglib generates the same .config as scripts/kconfig/conf,
- for each architecture/defconfig pair. In obsessive mode, this test includes
- nonsensical groupings of arches with defconfigs from other arches (every
- arch/defconfig combination) and takes an order of magnitude longer time to
- run.
- With logging enabled, this test appends any failures to a file
- test_defconfig_fails in the root.
- """
- kconf = Kconfig()
- if obsessive:
- defconfigs = []
- # Collect all defconfigs. This could be done once instead, but it's
- # a speedy operation comparatively.
- for srcarch_ in os.listdir("arch"):
- defconfigs.extend(defconfig_files(srcarch_))
- else:
- defconfigs = defconfig_files(srcarch)
- # Test architecture for each defconfig
- for defconfig in defconfigs:
- rm_configs()
- kconf.load_config(defconfig)
- kconf.write_config("._config")
- shell("scripts/kconfig/conf --defconfig='{}' Kconfig".
- format(defconfig))
- arch_defconfig_str = " {:14}with {:60} ".format(arch, defconfig)
- if equal_configs():
- print(arch_defconfig_str + "OK")
- else:
- print(arch_defconfig_str + "FAIL")
- fail()
- if log:
- with open("test_defconfig_fails", "a") as fail_log:
- fail_log.write("{} with {} did not match\n"
- .format(arch, defconfig))
- def test_min_config(arch, srcarch):
- """
- Verify that Kconfiglib generates the same .config as 'make savedefconfig'
- for each architecture/defconfig pair.
- """
- kconf = Kconfig()
- if obsessive_min_config:
- defconfigs = []
- for srcarch_ in os.listdir("arch"):
- defconfigs.extend(defconfig_files(srcarch_))
- else:
- defconfigs = defconfig_files(srcarch)
- for defconfig in defconfigs:
- rm_configs()
- kconf.load_config(defconfig)
- kconf.write_min_config("._config")
- shell("cp {} .config".format(defconfig))
- shell("scripts/kconfig/conf --savedefconfig=.config Kconfig")
- arch_defconfig_str = " {:14}with {:60} ".format(arch, defconfig)
- if equal_configs():
- print(arch_defconfig_str + "OK")
- else:
- print(arch_defconfig_str + "FAIL")
- #
- # Helper functions
- #
- def defconfig_files(srcarch):
- # Yields a list of defconfig file filenames for a particular srcarch
- # subdirectory (arch/<srcarch>/)
- srcarch_dir = os.path.join("arch", srcarch)
- # Some arches have a defconfig in the root of their arch/<arch>/ directory
- root_defconfig = os.path.join(srcarch_dir, "defconfig")
- if os.path.exists(root_defconfig):
- yield root_defconfig
- # Assume all files in the arch/<arch>/configs/ directory (if it exists) are
- # configurations
- defconfigs_dir = os.path.join(srcarch_dir, "configs")
- if not os.path.isdir(defconfigs_dir):
- return
- for dirpath, _, filenames in os.walk(defconfigs_dir):
- for filename in filenames:
- yield os.path.join(dirpath, filename)
- def rm_configs():
- # Delete any old ".config" (generated by the C implementation) and
- # "._config" (generated by us), if present.
- def rm_if_exists(f):
- if os.path.exists(f):
- os.remove(f)
- rm_if_exists(".config")
- rm_if_exists("._config")
- def compare_configs(arch):
- if equal_configs():
- print("{:14}OK".format(arch))
- else:
- print("{:14}FAIL".format(arch))
- fail()
- def equal_configs():
- with open(".config") as f:
- their = f.readlines()
- # Strip the header generated by 'conf'
- i = 0
- for line in their:
- if not line.startswith("#") or \
- re.match(r"# CONFIG_(\w+) is not set", line):
- break
- i += 1
- their = their[i:]
- try:
- f = open("._config")
- except EnvironmentError as e:
- if e.errno != errno.ENOENT:
- raise
- print("._config not found. Did you forget to apply the Makefile patch?")
- return False
- else:
- with f:
- our = f.readlines()
- if their == our:
- return True
- # Print a unified diff to help debugging
- print("Mismatched .config's! Unified diff:")
- sys.stdout.writelines(difflib.unified_diff(their, our, fromfile="their",
- tofile="our"))
- return False
- if __name__ == "__main__":
- run_tests()
|