luaunit.lua 114 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207
  1. --[[
  2. luaunit.lua
  3. Description: A unit testing framework
  4. Homepage: https://github.com/bluebird75/luaunit
  5. Development by Philippe Fremy <[email protected]>
  6. Based on initial work of Ryu, Gwang (http://www.gpgstudy.com/gpgiki/LuaUnit)
  7. License: BSD License, see LICENSE.txt
  8. ]]--
  9. require("math")
  10. local M={}
  11. -- private exported functions (for testing)
  12. M.private = {}
  13. M.VERSION='3.4-dev'
  14. M._VERSION=M.VERSION -- For LuaUnit v2 compatibility
  15. -- a version which distinguish between regular Lua and LuaJit
  16. M._LUAVERSION = (jit and jit.version) or _VERSION
  17. --[[ Some people like assertEquals( actual, expected ) and some people prefer
  18. assertEquals( expected, actual ).
  19. ]]--
  20. M.ORDER_ACTUAL_EXPECTED = true
  21. M.PRINT_TABLE_REF_IN_ERROR_MSG = false
  22. M.LINE_LENGTH = 80
  23. M.TABLE_DIFF_ANALYSIS_THRESHOLD = 10 -- display deep analysis for more than 10 items
  24. M.LIST_DIFF_ANALYSIS_THRESHOLD = 10 -- display deep analysis for more than 10 items
  25. --[[ EPS is meant to help with Lua's floating point math in simple corner
  26. cases like almostEquals(1.1-0.1, 1), which may not work as-is (e.g. on numbers
  27. with rational binary representation) if the user doesn't provide some explicit
  28. error margin.
  29. The default margin used by almostEquals() in such cases is EPS; and since
  30. Lua may be compiled with different numeric precisions (single vs. double), we
  31. try to select a useful default for it dynamically. Note: If the initial value
  32. is not acceptable, it can be changed by the user to better suit specific needs.
  33. See also: https://en.wikipedia.org/wiki/Machine_epsilon
  34. ]]
  35. M.EPS = 2^-52 -- = machine epsilon for "double", ~2.22E-16
  36. if math.abs(1.1 - 1 - 0.1) > M.EPS then
  37. -- rounding error is above EPS, assume single precision
  38. M.EPS = 2^-23 -- = machine epsilon for "float", ~1.19E-07
  39. end
  40. -- set this to false to debug luaunit
  41. local STRIP_LUAUNIT_FROM_STACKTRACE = true
  42. M.VERBOSITY_DEFAULT = 10
  43. M.VERBOSITY_LOW = 1
  44. M.VERBOSITY_QUIET = 0
  45. M.VERBOSITY_VERBOSE = 20
  46. M.DEFAULT_DEEP_ANALYSIS = nil
  47. M.FORCE_DEEP_ANALYSIS = true
  48. M.DISABLE_DEEP_ANALYSIS = false
  49. -- set EXPORT_ASSERT_TO_GLOBALS to have all asserts visible as global values
  50. -- EXPORT_ASSERT_TO_GLOBALS = true
  51. -- we need to keep a copy of the script args before it is overriden
  52. local cmdline_argv = rawget(_G, "arg")
  53. M.FAILURE_PREFIX = 'LuaUnit test FAILURE: ' -- prefix string for failed tests
  54. M.SUCCESS_PREFIX = 'LuaUnit test SUCCESS: ' -- prefix string for successful tests finished early
  55. M.SKIP_PREFIX = 'LuaUnit test SKIP: ' -- prefix string for skipped tests
  56. M.USAGE=[[Usage: lua <your_test_suite.lua> [options] [testname1 [testname2] ... ]
  57. Options:
  58. -h, --help: Print this help
  59. --version: Print version information
  60. -v, --verbose: Increase verbosity
  61. -q, --quiet: Set verbosity to minimum
  62. -e, --error: Stop on first error
  63. -f, --failure: Stop on first failure or error
  64. -s, --shuffle: Shuffle tests before running them
  65. -o, --output OUTPUT: Set output type to OUTPUT
  66. Possible values: text, tap, junit, nil
  67. -n, --name NAME: For junit only, mandatory name of xml file
  68. -r, --repeat NUM: Execute all tests NUM times, e.g. to trig the JIT
  69. -p, --pattern PATTERN: Execute all test names matching the Lua PATTERN
  70. May be repeated to include several patterns
  71. Make sure you escape magic chars like +? with %
  72. -x, --exclude PATTERN: Exclude all test names matching the Lua PATTERN
  73. May be repeated to exclude several patterns
  74. Make sure you escape magic chars like +? with %
  75. testname1, testname2, ... : tests to run in the form of testFunction,
  76. TestClass or TestClass.testMethod
  77. ]]
  78. local is_equal -- defined here to allow calling from mismatchFormattingPureList
  79. ----------------------------------------------------------------
  80. --
  81. -- general utility functions
  82. --
  83. ----------------------------------------------------------------
  84. local function pcall_or_abort(func, ...)
  85. -- unpack is a global function for Lua 5.1, otherwise use table.unpack
  86. local unpack = rawget(_G, "unpack") or table.unpack
  87. local result = {pcall(func, ...)}
  88. if not result[1] then
  89. -- an error occurred
  90. print(result[2]) -- error message
  91. print()
  92. print(M.USAGE)
  93. os.exit(-1)
  94. end
  95. return unpack(result, 2)
  96. end
  97. local crossTypeOrdering = {
  98. number = 1, boolean = 2, string = 3, table = 4, other = 5
  99. }
  100. local crossTypeComparison = {
  101. number = function(a, b) return a < b end,
  102. string = function(a, b) return a < b end,
  103. other = function(a, b) return tostring(a) < tostring(b) end,
  104. }
  105. local function crossTypeSort(a, b)
  106. local type_a, type_b = type(a), type(b)
  107. if type_a == type_b then
  108. local func = crossTypeComparison[type_a] or crossTypeComparison.other
  109. return func(a, b)
  110. end
  111. type_a = crossTypeOrdering[type_a] or crossTypeOrdering.other
  112. type_b = crossTypeOrdering[type_b] or crossTypeOrdering.other
  113. return type_a < type_b
  114. end
  115. local function __genSortedIndex( t )
  116. -- Returns a sequence consisting of t's keys, sorted.
  117. local sortedIndex = {}
  118. for key,_ in pairs(t) do
  119. table.insert(sortedIndex, key)
  120. end
  121. table.sort(sortedIndex, crossTypeSort)
  122. return sortedIndex
  123. end
  124. M.private.__genSortedIndex = __genSortedIndex
  125. local function sortedNext(state, control)
  126. -- Equivalent of the next() function of table iteration, but returns the
  127. -- keys in sorted order (see __genSortedIndex and crossTypeSort).
  128. -- The state is a temporary variable during iteration and contains the
  129. -- sorted key table (state.sortedIdx). It also stores the last index (into
  130. -- the keys) used by the iteration, to find the next one quickly.
  131. local key
  132. --print("sortedNext: control = "..tostring(control) )
  133. if control == nil then
  134. -- start of iteration
  135. state.count = #state.sortedIdx
  136. state.lastIdx = 1
  137. key = state.sortedIdx[1]
  138. return key, state.t[key]
  139. end
  140. -- normally, we expect the control variable to match the last key used
  141. if control ~= state.sortedIdx[state.lastIdx] then
  142. -- strange, we have to find the next value by ourselves
  143. -- the key table is sorted in crossTypeSort() order! -> use bisection
  144. local lower, upper = 1, state.count
  145. repeat
  146. state.lastIdx = math.modf((lower + upper) / 2)
  147. key = state.sortedIdx[state.lastIdx]
  148. if key == control then
  149. break -- key found (and thus prev index)
  150. end
  151. if crossTypeSort(key, control) then
  152. -- key < control, continue search "right" (towards upper bound)
  153. lower = state.lastIdx + 1
  154. else
  155. -- key > control, continue search "left" (towards lower bound)
  156. upper = state.lastIdx - 1
  157. end
  158. until lower > upper
  159. if lower > upper then -- only true if the key wasn't found, ...
  160. state.lastIdx = state.count -- ... so ensure no match in code below
  161. end
  162. end
  163. -- proceed by retrieving the next value (or nil) from the sorted keys
  164. state.lastIdx = state.lastIdx + 1
  165. key = state.sortedIdx[state.lastIdx]
  166. if key then
  167. return key, state.t[key]
  168. end
  169. -- getting here means returning `nil`, which will end the iteration
  170. end
  171. local function sortedPairs(tbl)
  172. -- Equivalent of the pairs() function on tables. Allows to iterate in
  173. -- sorted order. As required by "generic for" loops, this will return the
  174. -- iterator (function), an "invariant state", and the initial control value.
  175. -- (see http://www.lua.org/pil/7.2.html)
  176. return sortedNext, {t = tbl, sortedIdx = __genSortedIndex(tbl)}, nil
  177. end
  178. M.private.sortedPairs = sortedPairs
  179. -- seed the random with a strongly varying seed
  180. math.randomseed(os.clock()*1E11)
  181. local function randomizeTable( t )
  182. -- randomize the item orders of the table t
  183. for i = #t, 2, -1 do
  184. local j = math.random(i)
  185. if i ~= j then
  186. t[i], t[j] = t[j], t[i]
  187. end
  188. end
  189. end
  190. M.private.randomizeTable = randomizeTable
  191. local function strsplit(delimiter, text)
  192. -- Split text into a list consisting of the strings in text, separated
  193. -- by strings matching delimiter (which may _NOT_ be a pattern).
  194. -- Example: strsplit(", ", "Anna, Bob, Charlie, Dolores")
  195. if delimiter == "" or delimiter == nil then -- this would result in endless loops
  196. error("delimiter is nil or empty string!")
  197. end
  198. if text == nil then
  199. return nil
  200. end
  201. local list, pos, first, last = {}, 1
  202. while true do
  203. first, last = text:find(delimiter, pos, true)
  204. if first then -- found?
  205. table.insert(list, text:sub(pos, first - 1))
  206. pos = last + 1
  207. else
  208. table.insert(list, text:sub(pos))
  209. break
  210. end
  211. end
  212. return list
  213. end
  214. M.private.strsplit = strsplit
  215. local function hasNewLine( s )
  216. -- return true if s has a newline
  217. return (string.find(s, '\n', 1, true) ~= nil)
  218. end
  219. M.private.hasNewLine = hasNewLine
  220. local function prefixString( prefix, s )
  221. -- Prefix all the lines of s with prefix
  222. return prefix .. string.gsub(s, '\n', '\n' .. prefix)
  223. end
  224. M.private.prefixString = prefixString
  225. local function strMatch(s, pattern, start, final )
  226. -- return true if s matches completely the pattern from index start to index end
  227. -- return false in every other cases
  228. -- if start is nil, matches from the beginning of the string
  229. -- if final is nil, matches to the end of the string
  230. start = start or 1
  231. final = final or string.len(s)
  232. local foundStart, foundEnd = string.find(s, pattern, start, false)
  233. return foundStart == start and foundEnd == final
  234. end
  235. M.private.strMatch = strMatch
  236. local function patternFilter(patterns, expr)
  237. -- Run `expr` through the inclusion and exclusion rules defined in patterns
  238. -- and return true if expr shall be included, false for excluded.
  239. -- Inclusion pattern are defined as normal patterns, exclusions
  240. -- patterns start with `!` and are followed by a normal pattern
  241. -- result: nil = UNKNOWN (not matched yet), true = ACCEPT, false = REJECT
  242. -- default: true if no explicit "include" is found, set to false otherwise
  243. local default, result = true, nil
  244. if patterns ~= nil then
  245. for _, pattern in ipairs(patterns) do
  246. local exclude = pattern:sub(1,1) == '!'
  247. if exclude then
  248. pattern = pattern:sub(2)
  249. else
  250. -- at least one include pattern specified, a match is required
  251. default = false
  252. end
  253. -- print('pattern: ',pattern)
  254. -- print('exclude: ',exclude)
  255. -- print('default: ',default)
  256. if string.find(expr, pattern) then
  257. -- set result to false when excluding, true otherwise
  258. result = not exclude
  259. end
  260. end
  261. end
  262. if result ~= nil then
  263. return result
  264. end
  265. return default
  266. end
  267. M.private.patternFilter = patternFilter
  268. local function xmlEscape( s )
  269. -- Return s escaped for XML attributes
  270. -- escapes table:
  271. -- " &quot;
  272. -- ' &apos;
  273. -- < &lt;
  274. -- > &gt;
  275. -- & &amp;
  276. return string.gsub( s, '.', {
  277. ['&'] = "&amp;",
  278. ['"'] = "&quot;",
  279. ["'"] = "&apos;",
  280. ['<'] = "&lt;",
  281. ['>'] = "&gt;",
  282. } )
  283. end
  284. M.private.xmlEscape = xmlEscape
  285. local function xmlCDataEscape( s )
  286. -- Return s escaped for CData section, escapes: "]]>"
  287. return string.gsub( s, ']]>', ']]&gt;' )
  288. end
  289. M.private.xmlCDataEscape = xmlCDataEscape
  290. local function stripLuaunitTrace( stackTrace )
  291. --[[
  292. -- Example of a traceback:
  293. <<stack traceback:
  294. example_with_luaunit.lua:130: in function 'test2_withFailure'
  295. ./luaunit.lua:1449: in function <./luaunit.lua:1449>
  296. [C]: in function 'xpcall'
  297. ./luaunit.lua:1449: in function 'protectedCall'
  298. ./luaunit.lua:1508: in function 'execOneFunction'
  299. ./luaunit.lua:1596: in function 'runSuiteByInstances'
  300. ./luaunit.lua:1660: in function 'runSuiteByNames'
  301. ./luaunit.lua:1736: in function 'runSuite'
  302. example_with_luaunit.lua:140: in main chunk
  303. [C]: in ?>>
  304. Other example:
  305. <<stack traceback:
  306. ./luaunit.lua:545: in function 'assertEquals'
  307. example_with_luaunit.lua:58: in function 'TestToto.test7'
  308. ./luaunit.lua:1517: in function <./luaunit.lua:1517>
  309. [C]: in function 'xpcall'
  310. ./luaunit.lua:1517: in function 'protectedCall'
  311. ./luaunit.lua:1578: in function 'execOneFunction'
  312. ./luaunit.lua:1677: in function 'runSuiteByInstances'
  313. ./luaunit.lua:1730: in function 'runSuiteByNames'
  314. ./luaunit.lua:1806: in function 'runSuite'
  315. example_with_luaunit.lua:140: in main chunk
  316. [C]: in ?>>
  317. <<stack traceback:
  318. luaunit2/example_with_luaunit.lua:124: in function 'test1_withFailure'
  319. luaunit2/luaunit.lua:1532: in function <luaunit2/luaunit.lua:1532>
  320. [C]: in function 'xpcall'
  321. luaunit2/luaunit.lua:1532: in function 'protectedCall'
  322. luaunit2/luaunit.lua:1591: in function 'execOneFunction'
  323. luaunit2/luaunit.lua:1679: in function 'runSuiteByInstances'
  324. luaunit2/luaunit.lua:1743: in function 'runSuiteByNames'
  325. luaunit2/luaunit.lua:1819: in function 'runSuite'
  326. luaunit2/example_with_luaunit.lua:140: in main chunk
  327. [C]: in ?>>
  328. -- first line is "stack traceback": KEEP
  329. -- next line may be luaunit line: REMOVE
  330. -- next lines are call in the program under testOk: REMOVE
  331. -- next lines are calls from luaunit to call the program under test: KEEP
  332. -- Strategy:
  333. -- keep first line
  334. -- remove lines that are part of luaunit
  335. -- kepp lines until we hit a luaunit line
  336. ]]
  337. local function isLuaunitInternalLine( s )
  338. -- return true if line of stack trace comes from inside luaunit
  339. return s:find('[/\\]luaunit%.lua:%d+: ') ~= nil
  340. end
  341. -- print( '<<'..stackTrace..'>>' )
  342. local t = strsplit( '\n', stackTrace )
  343. -- print( prettystr(t) )
  344. local idx = 2
  345. -- remove lines that are still part of luaunit
  346. while t[idx] and isLuaunitInternalLine( t[idx] ) do
  347. -- print('Removing : '..t[idx] )
  348. table.remove(t, idx)
  349. end
  350. -- keep lines until we hit luaunit again
  351. while t[idx] and (not isLuaunitInternalLine(t[idx])) do
  352. -- print('Keeping : '..t[idx] )
  353. idx = idx + 1
  354. end
  355. -- remove remaining luaunit lines
  356. while t[idx] do
  357. -- print('Removing : '..t[idx] )
  358. table.remove(t, idx)
  359. end
  360. -- print( prettystr(t) )
  361. return table.concat( t, '\n')
  362. end
  363. M.private.stripLuaunitTrace = stripLuaunitTrace
  364. local function prettystr_sub(v, indentLevel, printTableRefs, cycleDetectTable )
  365. local type_v = type(v)
  366. if "string" == type_v then
  367. -- use clever delimiters according to content:
  368. -- enclose with single quotes if string contains ", but no '
  369. if v:find('"', 1, true) and not v:find("'", 1, true) then
  370. return "'" .. v .. "'"
  371. end
  372. -- use double quotes otherwise, escape embedded "
  373. return '"' .. v:gsub('"', '\\"') .. '"'
  374. elseif "table" == type_v then
  375. --if v.__class__ then
  376. -- return string.gsub( tostring(v), 'table', v.__class__ )
  377. --end
  378. return M.private._table_tostring(v, indentLevel, printTableRefs, cycleDetectTable)
  379. elseif "number" == type_v then
  380. -- eliminate differences in formatting between various Lua versions
  381. if v ~= v then
  382. return "#NaN" -- "not a number"
  383. end
  384. if v == math.huge then
  385. return "#Inf" -- "infinite"
  386. end
  387. if v == -math.huge then
  388. return "-#Inf"
  389. end
  390. if _VERSION == "Lua 5.3" then
  391. local i = math.tointeger(v)
  392. if i then
  393. return tostring(i)
  394. end
  395. end
  396. end
  397. return tostring(v)
  398. end
  399. local function prettystr( v )
  400. --[[ Pretty string conversion, to display the full content of a variable of any type.
  401. * string are enclosed with " by default, or with ' if string contains a "
  402. * tables are expanded to show their full content, with indentation in case of nested tables
  403. ]]--
  404. local cycleDetectTable = {}
  405. local s = prettystr_sub(v, 1, M.PRINT_TABLE_REF_IN_ERROR_MSG, cycleDetectTable)
  406. if cycleDetectTable.detected and not M.PRINT_TABLE_REF_IN_ERROR_MSG then
  407. -- some table contain recursive references,
  408. -- so we must recompute the value by including all table references
  409. -- else the result looks like crap
  410. cycleDetectTable = {}
  411. s = prettystr_sub(v, 1, true, cycleDetectTable)
  412. end
  413. return s
  414. end
  415. M.prettystr = prettystr
  416. function M.adjust_err_msg_with_iter( err_msg, iter_msg )
  417. --[[ Adjust the error message err_msg: trim the FAILURE_PREFIX or SUCCESS_PREFIX information if needed,
  418. add the iteration message if any and return the result.
  419. err_msg: string, error message captured with pcall
  420. iter_msg: a string describing the current iteration ("iteration N") or nil
  421. if there is no iteration in this test.
  422. Returns: (new_err_msg, test_status)
  423. new_err_msg: string, adjusted error message, or nil in case of success
  424. test_status: M.NodeStatus.FAIL, SUCCESS or ERROR according to the information
  425. contained in the error message.
  426. ]]
  427. if iter_msg then
  428. iter_msg = iter_msg..', '
  429. else
  430. iter_msg = ''
  431. end
  432. local RE_FILE_LINE = '.*:%d+: '
  433. -- error message is not necessarily a string,
  434. -- so convert the value to string with prettystr()
  435. if type( err_msg ) ~= 'string' then
  436. err_msg = prettystr( err_msg )
  437. end
  438. if (err_msg:find( M.SUCCESS_PREFIX ) == 1) or err_msg:match( '('..RE_FILE_LINE..')' .. M.SUCCESS_PREFIX .. ".*" ) then
  439. -- test finished early with success()
  440. return nil, M.NodeStatus.SUCCESS
  441. end
  442. if (err_msg:find( M.SKIP_PREFIX ) == 1) or (err_msg:match( '('..RE_FILE_LINE..')' .. M.SKIP_PREFIX .. ".*" ) ~= nil) then
  443. -- substitute prefix by iteration message
  444. err_msg = err_msg:gsub('.*'..M.SKIP_PREFIX, iter_msg, 1)
  445. -- print("failure detected")
  446. return err_msg, M.NodeStatus.SKIP
  447. end
  448. if (err_msg:find( M.FAILURE_PREFIX ) == 1) or (err_msg:match( '('..RE_FILE_LINE..')' .. M.FAILURE_PREFIX .. ".*" ) ~= nil) then
  449. -- substitute prefix by iteration message
  450. err_msg = err_msg:gsub(M.FAILURE_PREFIX, iter_msg, 1)
  451. -- print("failure detected")
  452. return err_msg, M.NodeStatus.FAIL
  453. end
  454. -- print("error detected")
  455. -- regular error, not a failure
  456. if iter_msg then
  457. local match
  458. -- "./test\\test_luaunit.lua:2241: some error msg
  459. match = err_msg:match( '(.*:%d+: ).*' )
  460. if match then
  461. err_msg = err_msg:gsub( match, match .. iter_msg )
  462. else
  463. -- no file:line: infromation, just add the iteration info at the beginning of the line
  464. err_msg = iter_msg .. err_msg
  465. end
  466. end
  467. return err_msg, M.NodeStatus.ERROR
  468. end
  469. local function tryMismatchFormatting( table_a, table_b, doDeepAnalysis )
  470. --[[
  471. Prepares a nice error message when comparing tables, performing a deeper
  472. analysis.
  473. Arguments:
  474. * table_a, table_b: tables to be compared
  475. * doDeepAnalysis:
  476. M.DEFAULT_DEEP_ANALYSIS: (the default if not specified) perform deep analysis only for big lists and big dictionnaries
  477. M.FORCE_DEEP_ANALYSIS : always perform deep analysis
  478. M.DISABLE_DEEP_ANALYSIS: never perform deep analysis
  479. Returns: {success, result}
  480. * success: false if deep analysis could not be performed
  481. in this case, just use standard assertion message
  482. * result: if success is true, a multi-line string with deep analysis of the two lists
  483. ]]
  484. -- check if table_a & table_b are suitable for deep analysis
  485. if type(table_a) ~= 'table' or type(table_b) ~= 'table' then
  486. return false
  487. end
  488. if doDeepAnalysis == M.DISABLE_DEEP_ANALYSIS then
  489. return false
  490. end
  491. local len_a, len_b, isPureList = #table_a, #table_b, true
  492. for k1, v1 in pairs(table_a) do
  493. if type(k1) ~= 'number' or k1 > len_a then
  494. -- this table a mapping
  495. isPureList = false
  496. break
  497. end
  498. end
  499. if isPureList then
  500. for k2, v2 in pairs(table_b) do
  501. if type(k2) ~= 'number' or k2 > len_b then
  502. -- this table a mapping
  503. isPureList = false
  504. break
  505. end
  506. end
  507. end
  508. if isPureList and math.min(len_a, len_b) < M.LIST_DIFF_ANALYSIS_THRESHOLD then
  509. if not (doDeepAnalysis == M.FORCE_DEEP_ANALYSIS) then
  510. return false
  511. end
  512. end
  513. if isPureList then
  514. return M.private.mismatchFormattingPureList( table_a, table_b )
  515. else
  516. -- only work on mapping for the moment
  517. -- return M.private.mismatchFormattingMapping( table_a, table_b, doDeepAnalysis )
  518. return false
  519. end
  520. end
  521. M.private.tryMismatchFormatting = tryMismatchFormatting
  522. local function getTaTbDescr()
  523. if not M.ORDER_ACTUAL_EXPECTED then
  524. return 'expected', 'actual'
  525. end
  526. return 'actual', 'expected'
  527. end
  528. local function extendWithStrFmt( res, ... )
  529. table.insert( res, string.format( ... ) )
  530. end
  531. local function mismatchFormattingMapping( table_a, table_b, doDeepAnalysis )
  532. --[[
  533. Prepares a nice error message when comparing tables which are not pure lists, performing a deeper
  534. analysis.
  535. Returns: {success, result}
  536. * success: false if deep analysis could not be performed
  537. in this case, just use standard assertion message
  538. * result: if success is true, a multi-line string with deep analysis of the two lists
  539. ]]
  540. -- disable for the moment
  541. --[[
  542. local result = {}
  543. local descrTa, descrTb = getTaTbDescr()
  544. local keysCommon = {}
  545. local keysOnlyTa = {}
  546. local keysOnlyTb = {}
  547. local keysDiffTaTb = {}
  548. local k, v
  549. for k,v in pairs( table_a ) do
  550. if is_equal( v, table_b[k] ) then
  551. table.insert( keysCommon, k )
  552. else
  553. if table_b[k] == nil then
  554. table.insert( keysOnlyTa, k )
  555. else
  556. table.insert( keysDiffTaTb, k )
  557. end
  558. end
  559. end
  560. for k,v in pairs( table_b ) do
  561. if not is_equal( v, table_a[k] ) and table_a[k] == nil then
  562. table.insert( keysOnlyTb, k )
  563. end
  564. end
  565. local len_a = #keysCommon + #keysDiffTaTb + #keysOnlyTa
  566. local len_b = #keysCommon + #keysDiffTaTb + #keysOnlyTb
  567. local limited_display = (len_a < 5 or len_b < 5)
  568. if math.min(len_a, len_b) < M.TABLE_DIFF_ANALYSIS_THRESHOLD then
  569. return false
  570. end
  571. if not limited_display then
  572. if len_a == len_b then
  573. extendWithStrFmt( result, 'Table A (%s) and B (%s) both have %d items', descrTa, descrTb, len_a )
  574. else
  575. extendWithStrFmt( result, 'Table A (%s) has %d items and table B (%s) has %d items', descrTa, len_a, descrTb, len_b )
  576. end
  577. if #keysCommon == 0 and #keysDiffTaTb == 0 then
  578. table.insert( result, 'Table A and B have no keys in common, they are totally different')
  579. else
  580. local s_other = 'other '
  581. if #keysCommon then
  582. extendWithStrFmt( result, 'Table A and B have %d identical items', #keysCommon )
  583. else
  584. table.insert( result, 'Table A and B have no identical items' )
  585. s_other = ''
  586. end
  587. if #keysDiffTaTb ~= 0 then
  588. result[#result] = string.format( '%s and %d items differing present in both tables', result[#result], #keysDiffTaTb)
  589. else
  590. result[#result] = string.format( '%s and no %sitems differing present in both tables', result[#result], s_other, #keysDiffTaTb)
  591. end
  592. end
  593. extendWithStrFmt( result, 'Table A has %d keys not present in table B and table B has %d keys not present in table A', #keysOnlyTa, #keysOnlyTb )
  594. end
  595. local function keytostring(k)
  596. if "string" == type(k) and k:match("^[_%a][_%w]*$") then
  597. return k
  598. end
  599. return prettystr(k)
  600. end
  601. if #keysDiffTaTb ~= 0 then
  602. table.insert( result, 'Items differing in A and B:')
  603. for k,v in sortedPairs( keysDiffTaTb ) do
  604. extendWithStrFmt( result, ' - A[%s]: %s', keytostring(v), prettystr(table_a[v]) )
  605. extendWithStrFmt( result, ' + B[%s]: %s', keytostring(v), prettystr(table_b[v]) )
  606. end
  607. end
  608. if #keysOnlyTa ~= 0 then
  609. table.insert( result, 'Items only in table A:' )
  610. for k,v in sortedPairs( keysOnlyTa ) do
  611. extendWithStrFmt( result, ' - A[%s]: %s', keytostring(v), prettystr(table_a[v]) )
  612. end
  613. end
  614. if #keysOnlyTb ~= 0 then
  615. table.insert( result, 'Items only in table B:' )
  616. for k,v in sortedPairs( keysOnlyTb ) do
  617. extendWithStrFmt( result, ' + B[%s]: %s', keytostring(v), prettystr(table_b[v]) )
  618. end
  619. end
  620. if #keysCommon ~= 0 then
  621. table.insert( result, 'Items common to A and B:')
  622. for k,v in sortedPairs( keysCommon ) do
  623. extendWithStrFmt( result, ' = A and B [%s]: %s', keytostring(v), prettystr(table_a[v]) )
  624. end
  625. end
  626. return true, table.concat( result, '\n')
  627. ]]
  628. end
  629. M.private.mismatchFormattingMapping = mismatchFormattingMapping
  630. local function mismatchFormattingPureList( table_a, table_b )
  631. --[[
  632. Prepares a nice error message when comparing tables which are lists, performing a deeper
  633. analysis.
  634. Returns: {success, result}
  635. * success: false if deep analysis could not be performed
  636. in this case, just use standard assertion message
  637. * result: if success is true, a multi-line string with deep analysis of the two lists
  638. ]]
  639. local result, descrTa, descrTb = {}, getTaTbDescr()
  640. local len_a, len_b, refa, refb = #table_a, #table_b, '', ''
  641. if M.PRINT_TABLE_REF_IN_ERROR_MSG then
  642. refa, refb = string.format( '<%s> ', M.private.table_ref(table_a)), string.format('<%s> ', M.private.table_ref(table_b) )
  643. end
  644. local longest, shortest = math.max(len_a, len_b), math.min(len_a, len_b)
  645. local deltalv = longest - shortest
  646. local commonUntil = shortest
  647. for i = 1, shortest do
  648. if not is_equal(table_a[i], table_b[i]) then
  649. commonUntil = i - 1
  650. break
  651. end
  652. end
  653. local commonBackTo = shortest - 1
  654. for i = 0, shortest - 1 do
  655. if not is_equal(table_a[len_a-i], table_b[len_b-i]) then
  656. commonBackTo = i - 1
  657. break
  658. end
  659. end
  660. table.insert( result, 'List difference analysis:' )
  661. if len_a == len_b then
  662. -- TODO: handle expected/actual naming
  663. extendWithStrFmt( result, '* lists %sA (%s) and %sB (%s) have the same size', refa, descrTa, refb, descrTb )
  664. else
  665. extendWithStrFmt( result, '* list sizes differ: list %sA (%s) has %d items, list %sB (%s) has %d items', refa, descrTa, len_a, refb, descrTb, len_b )
  666. end
  667. extendWithStrFmt( result, '* lists A and B start differing at index %d', commonUntil+1 )
  668. if commonBackTo >= 0 then
  669. if deltalv > 0 then
  670. extendWithStrFmt( result, '* lists A and B are equal again from index %d for A, %d for B', len_a-commonBackTo, len_b-commonBackTo )
  671. else
  672. extendWithStrFmt( result, '* lists A and B are equal again from index %d', len_a-commonBackTo )
  673. end
  674. end
  675. local function insertABValue(ai, bi)
  676. bi = bi or ai
  677. if is_equal( table_a[ai], table_b[bi]) then
  678. return extendWithStrFmt( result, ' = A[%d], B[%d]: %s', ai, bi, prettystr(table_a[ai]) )
  679. else
  680. extendWithStrFmt( result, ' - A[%d]: %s', ai, prettystr(table_a[ai]))
  681. extendWithStrFmt( result, ' + B[%d]: %s', bi, prettystr(table_b[bi]))
  682. end
  683. end
  684. -- common parts to list A & B, at the beginning
  685. if commonUntil > 0 then
  686. table.insert( result, '* Common parts:' )
  687. for i = 1, commonUntil do
  688. insertABValue( i )
  689. end
  690. end
  691. -- diffing parts to list A & B
  692. if commonUntil < shortest - commonBackTo - 1 then
  693. table.insert( result, '* Differing parts:' )
  694. for i = commonUntil + 1, shortest - commonBackTo - 1 do
  695. insertABValue( i )
  696. end
  697. end
  698. -- display indexes of one list, with no match on other list
  699. if shortest - commonBackTo <= longest - commonBackTo - 1 then
  700. table.insert( result, '* Present only in one list:' )
  701. for i = shortest - commonBackTo, longest - commonBackTo - 1 do
  702. if len_a > len_b then
  703. extendWithStrFmt( result, ' - A[%d]: %s', i, prettystr(table_a[i]) )
  704. -- table.insert( result, '+ (no matching B index)')
  705. else
  706. -- table.insert( result, '- no matching A index')
  707. extendWithStrFmt( result, ' + B[%d]: %s', i, prettystr(table_b[i]) )
  708. end
  709. end
  710. end
  711. -- common parts to list A & B, at the end
  712. if commonBackTo >= 0 then
  713. table.insert( result, '* Common parts at the end of the lists' )
  714. for i = longest - commonBackTo, longest do
  715. if len_a > len_b then
  716. insertABValue( i, i-deltalv )
  717. else
  718. insertABValue( i-deltalv, i )
  719. end
  720. end
  721. end
  722. return true, table.concat( result, '\n')
  723. end
  724. M.private.mismatchFormattingPureList = mismatchFormattingPureList
  725. local function prettystrPairs(value1, value2, suffix_a, suffix_b)
  726. --[[
  727. This function helps with the recurring task of constructing the "expected
  728. vs. actual" error messages. It takes two arbitrary values and formats
  729. corresponding strings with prettystr().
  730. To keep the (possibly complex) output more readable in case the resulting
  731. strings contain line breaks, they get automatically prefixed with additional
  732. newlines. Both suffixes are optional (default to empty strings), and get
  733. appended to the "value1" string. "suffix_a" is used if line breaks were
  734. encountered, "suffix_b" otherwise.
  735. Returns the two formatted strings (including padding/newlines).
  736. ]]
  737. local str1, str2 = prettystr(value1), prettystr(value2)
  738. if hasNewLine(str1) or hasNewLine(str2) then
  739. -- line break(s) detected, add padding
  740. return "\n" .. str1 .. (suffix_a or ""), "\n" .. str2
  741. end
  742. return str1 .. (suffix_b or ""), str2
  743. end
  744. M.private.prettystrPairs = prettystrPairs
  745. local UNKNOWN_REF = 'table 00-unknown ref'
  746. local ref_generator = { value=1, [UNKNOWN_REF]=0 }
  747. local function table_ref( t )
  748. -- return the default tostring() for tables, with the table ID, even if the table has a metatable
  749. -- with the __tostring converter
  750. local ref = ''
  751. local mt = getmetatable( t )
  752. if mt == nil then
  753. ref = tostring(t)
  754. else
  755. local success, result
  756. success, result = pcall(setmetatable, t, nil)
  757. if not success then
  758. -- protected table, if __tostring is defined, we can
  759. -- not get the reference. And we can not know in advance.
  760. ref = tostring(t)
  761. if not ref:match( 'table: 0?x?[%x]+' ) then
  762. return UNKNOWN_REF
  763. end
  764. else
  765. ref = tostring(t)
  766. setmetatable( t, mt )
  767. end
  768. end
  769. -- strip the "table: " part
  770. ref = ref:sub(8)
  771. if ref ~= UNKNOWN_REF and ref_generator[ref] == nil then
  772. -- Create a new reference number
  773. ref_generator[ref] = ref_generator.value
  774. ref_generator.value = ref_generator.value+1
  775. end
  776. if M.PRINT_TABLE_REF_IN_ERROR_MSG then
  777. return string.format('table %02d-%s', ref_generator[ref], ref)
  778. else
  779. return string.format('table %02d', ref_generator[ref])
  780. end
  781. end
  782. M.private.table_ref = table_ref
  783. local TABLE_TOSTRING_SEP = ", "
  784. local TABLE_TOSTRING_SEP_LEN = string.len(TABLE_TOSTRING_SEP)
  785. local function _table_tostring( tbl, indentLevel, printTableRefs, cycleDetectTable )
  786. printTableRefs = printTableRefs or M.PRINT_TABLE_REF_IN_ERROR_MSG
  787. cycleDetectTable = cycleDetectTable or {}
  788. cycleDetectTable[tbl] = true
  789. local result, dispOnMultLines = {}, false
  790. -- like prettystr but do not enclose with "" if the string is just alphanumerical
  791. -- this is better for displaying table keys who are often simple strings
  792. local function keytostring(k)
  793. if "string" == type(k) and k:match("^[_%a][_%w]*$") then
  794. return k
  795. end
  796. return prettystr_sub(k, indentLevel+1, printTableRefs, cycleDetectTable)
  797. end
  798. local mt = getmetatable( tbl )
  799. if mt and mt.__tostring then
  800. -- if table has a __tostring() function in its metatable, use it to display the table
  801. -- else, compute a regular table
  802. result = tostring(tbl)
  803. if type(result) ~= 'string' then
  804. return string.format( '<invalid tostring() result: "%s" >', prettystr(result) )
  805. end
  806. result = strsplit( '\n', result )
  807. return M.private._table_tostring_format_multiline_string( result, indentLevel )
  808. else
  809. -- no metatable, compute the table representation
  810. local entry, count, seq_index = nil, 0, 1
  811. for k, v in sortedPairs( tbl ) do
  812. -- key part
  813. if k == seq_index then
  814. -- for the sequential part of tables, we'll skip the "<key>=" output
  815. entry = ''
  816. seq_index = seq_index + 1
  817. elseif cycleDetectTable[k] then
  818. -- recursion in the key detected
  819. cycleDetectTable.detected = true
  820. entry = "<"..table_ref(k)..">="
  821. else
  822. entry = keytostring(k) .. "="
  823. end
  824. -- value part
  825. if cycleDetectTable[v] then
  826. -- recursion in the value detected!
  827. cycleDetectTable.detected = true
  828. entry = entry .. "<"..table_ref(v)..">"
  829. else
  830. entry = entry ..
  831. prettystr_sub( v, indentLevel+1, printTableRefs, cycleDetectTable )
  832. end
  833. count = count + 1
  834. result[count] = entry
  835. end
  836. return M.private._table_tostring_format_result( tbl, result, indentLevel, printTableRefs )
  837. end
  838. end
  839. M.private._table_tostring = _table_tostring -- prettystr_sub() needs it
  840. local function _table_tostring_format_multiline_string( tbl_str, indentLevel )
  841. local indentString = '\n'..string.rep(" ", indentLevel - 1)
  842. return table.concat( tbl_str, indentString )
  843. end
  844. M.private._table_tostring_format_multiline_string = _table_tostring_format_multiline_string
  845. local function _table_tostring_format_result( tbl, result, indentLevel, printTableRefs )
  846. -- final function called in _table_to_string() to format the resulting list of
  847. -- string describing the table.
  848. local dispOnMultLines = false
  849. -- set dispOnMultLines to true if the maximum LINE_LENGTH would be exceeded with the values
  850. local totalLength = 0
  851. for k, v in ipairs( result ) do
  852. totalLength = totalLength + string.len( v )
  853. if totalLength >= M.LINE_LENGTH then
  854. dispOnMultLines = true
  855. break
  856. end
  857. end
  858. -- set dispOnMultLines to true if the max LINE_LENGTH would be exceeded
  859. -- with the values and the separators.
  860. if not dispOnMultLines then
  861. -- adjust with length of separator(s):
  862. -- two items need 1 sep, three items two seps, ... plus len of '{}'
  863. if #result > 0 then
  864. totalLength = totalLength + TABLE_TOSTRING_SEP_LEN * (#result - 1)
  865. end
  866. dispOnMultLines = (totalLength + 2 >= M.LINE_LENGTH)
  867. end
  868. -- now reformat the result table (currently holding element strings)
  869. if dispOnMultLines then
  870. local indentString = string.rep(" ", indentLevel - 1)
  871. result = {
  872. "{\n ",
  873. indentString,
  874. table.concat(result, ",\n " .. indentString),
  875. "\n",
  876. indentString,
  877. "}"
  878. }
  879. else
  880. result = {"{", table.concat(result, TABLE_TOSTRING_SEP), "}"}
  881. end
  882. if printTableRefs then
  883. table.insert(result, 1, "<"..table_ref(tbl).."> ") -- prepend table ref
  884. end
  885. return table.concat(result)
  886. end
  887. M.private._table_tostring_format_result = _table_tostring_format_result -- prettystr_sub() needs it
  888. local function table_findkeyof(t, element)
  889. -- Return the key k of the given element in table t, so that t[k] == element
  890. -- (or `nil` if element is not present within t). Note that we use our
  891. -- 'general' is_equal comparison for matching, so this function should
  892. -- handle table-type elements gracefully and consistently.
  893. if type(t) == "table" then
  894. for k, v in pairs(t) do
  895. if is_equal(v, element) then
  896. return k
  897. end
  898. end
  899. end
  900. return nil
  901. end
  902. local function _is_table_items_equals(actual, expected )
  903. local type_a, type_e = type(actual), type(expected)
  904. if type_a ~= type_e then
  905. return false
  906. elseif (type_a == 'table') --[[and (type_e == 'table')]] then
  907. for k, v in pairs(actual) do
  908. if table_findkeyof(expected, v) == nil then
  909. return false -- v not contained in expected
  910. end
  911. end
  912. for k, v in pairs(expected) do
  913. if table_findkeyof(actual, v) == nil then
  914. return false -- v not contained in actual
  915. end
  916. end
  917. return true
  918. elseif actual ~= expected then
  919. return false
  920. end
  921. return true
  922. end
  923. --[[
  924. This is a specialized metatable to help with the bookkeeping of recursions
  925. in _is_table_equals(). It provides an __index table that implements utility
  926. functions for easier management of the table. The "cached" method queries
  927. the state of a specific (actual,expected) pair; and the "store" method sets
  928. this state to the given value. The state of pairs not "seen" / visited is
  929. assumed to be `nil`.
  930. ]]
  931. local _recursion_cache_MT = {
  932. __index = {
  933. -- Return the cached value for an (actual,expected) pair (or `nil`)
  934. cached = function(t, actual, expected)
  935. local subtable = t[actual] or {}
  936. return subtable[expected]
  937. end,
  938. -- Store cached value for a specific (actual,expected) pair.
  939. -- Returns the value, so it's easy to use for a "tailcall" (return ...).
  940. store = function(t, actual, expected, value, asymmetric)
  941. local subtable = t[actual]
  942. if not subtable then
  943. subtable = {}
  944. t[actual] = subtable
  945. end
  946. subtable[expected] = value
  947. -- Unless explicitly marked "asymmetric": Consider the recursion
  948. -- on (expected,actual) to be equivalent to (actual,expected) by
  949. -- default, and thus cache the value for both.
  950. if not asymmetric then
  951. t:store(expected, actual, value, true)
  952. end
  953. return value
  954. end
  955. }
  956. }
  957. local function _is_table_equals(actual, expected, cycleDetectTable)
  958. local type_a, type_e = type(actual), type(expected)
  959. if type_a ~= type_e then
  960. return false -- different types won't match
  961. end
  962. if type_a ~= 'table' then
  963. -- other typtes compare directly
  964. return actual == expected
  965. end
  966. -- print('_is_table_equals( \n '..prettystr(actual)..'\n , '..prettystr(expected)..'\n , '..prettystr(recursions)..' \n )')
  967. cycleDetectTable = cycleDetectTable or { actual={}, expected={} }
  968. if cycleDetectTable.actual[ actual ] then
  969. -- oh, we hit a cycle in actual
  970. if cycleDetectTable.expected[ expected ] then
  971. -- uh, we hit a cycle at the same time in expected
  972. -- so the two tables have similar structure
  973. return true
  974. end
  975. -- cycle was hit only in actual, the structure differs from expected
  976. return false
  977. end
  978. if cycleDetectTable.expected[ expected ] then
  979. -- no cycle in actual, but cycle in expected
  980. -- the structure differ
  981. return false
  982. end
  983. -- at this point, no table cycle detected, we are
  984. -- seeing this table for the first time
  985. -- mark the cycle detection
  986. cycleDetectTable.actual[ actual ] = true
  987. cycleDetectTable.expected[ expected ] = true
  988. local actualKeysMatched = {}
  989. for k, v in pairs(actual) do
  990. actualKeysMatched[k] = true -- Keep track of matched keys
  991. if not _is_table_equals(v, expected[k], cycleDetectTable) then
  992. -- table differs on this key
  993. -- clear the cycle detection before returning
  994. cycleDetectTable.actual[ actual ] = nil
  995. cycleDetectTable.expected[ expected ] = nil
  996. return false
  997. end
  998. end
  999. for k, v in pairs(expected) do
  1000. if not actualKeysMatched[k] then
  1001. -- Found a key that we did not see in "actual" -> mismatch
  1002. -- clear the cycle detection before returning
  1003. cycleDetectTable.actual[ actual ] = nil
  1004. cycleDetectTable.expected[ expected ] = nil
  1005. return false
  1006. end
  1007. -- Otherwise actual[k] was already matched against v = expected[k].
  1008. end
  1009. -- all key match, we have a match !
  1010. cycleDetectTable.actual[ actual ] = nil
  1011. cycleDetectTable.expected[ expected ] = nil
  1012. return true
  1013. end
  1014. M.private._is_table_equals = _is_table_equals
  1015. is_equal = _is_table_equals
  1016. local function failure(main_msg, extra_msg_or_nil, level)
  1017. -- raise an error indicating a test failure
  1018. -- for error() compatibility we adjust "level" here (by +1), to report the
  1019. -- calling context
  1020. local msg
  1021. if type(extra_msg_or_nil) == 'string' and extra_msg_or_nil:len() > 0 then
  1022. msg = extra_msg_or_nil .. '\n' .. main_msg
  1023. else
  1024. msg = main_msg
  1025. end
  1026. error(M.FAILURE_PREFIX .. msg, (level or 1) + 1)
  1027. end
  1028. local function fail_fmt(level, extra_msg_or_nil, ...)
  1029. -- failure with printf-style formatted message and given error level
  1030. failure(string.format(...), extra_msg_or_nil, (level or 1) + 1)
  1031. end
  1032. M.private.fail_fmt = fail_fmt
  1033. local function error_fmt(level, ...)
  1034. -- printf-style error()
  1035. error(string.format(...), (level or 1) + 1)
  1036. end
  1037. ----------------------------------------------------------------
  1038. --
  1039. -- assertions
  1040. --
  1041. ----------------------------------------------------------------
  1042. local function errorMsgEquality(actual, expected, doDeepAnalysis)
  1043. if not M.ORDER_ACTUAL_EXPECTED then
  1044. expected, actual = actual, expected
  1045. end
  1046. if type(expected) == 'string' or type(expected) == 'table' then
  1047. local strExpected, strActual = prettystrPairs(expected, actual)
  1048. local result = string.format("expected: %s\nactual: %s", strExpected, strActual)
  1049. -- extend with mismatch analysis if possible:
  1050. local success, mismatchResult
  1051. success, mismatchResult = tryMismatchFormatting( actual, expected, doDeepAnalysis )
  1052. if success then
  1053. result = table.concat( { result, mismatchResult }, '\n' )
  1054. end
  1055. return result
  1056. end
  1057. return string.format("expected: %s, actual: %s",
  1058. prettystr(expected), prettystr(actual))
  1059. end
  1060. function M.assertError(f, ...)
  1061. -- assert that calling f with the arguments will raise an error
  1062. -- example: assertError( f, 1, 2 ) => f(1,2) should generate an error
  1063. if pcall( f, ... ) then
  1064. failure( "Expected an error when calling function but no error generated", nil, 2 )
  1065. end
  1066. end
  1067. function M.fail( msg )
  1068. -- stops a test due to a failure
  1069. failure( msg, nil, 2 )
  1070. end
  1071. function M.failIf( cond, msg )
  1072. -- Fails a test with "msg" if condition is true
  1073. if cond then
  1074. failure( msg, nil, 2 )
  1075. end
  1076. end
  1077. function M.skip(msg)
  1078. -- skip a running test
  1079. error(M.SKIP_PREFIX .. msg, 2)
  1080. end
  1081. function M.skipIf( cond, msg )
  1082. -- skip a running test if condition is met
  1083. if cond then
  1084. error(M.SKIP_PREFIX .. msg, 2)
  1085. end
  1086. end
  1087. function M.runOnlyIf( cond, msg )
  1088. -- continue a running test if condition is met, else skip it
  1089. if not cond then
  1090. error(M.SKIP_PREFIX .. prettystr(msg), 2)
  1091. end
  1092. end
  1093. function M.success()
  1094. -- stops a test with a success
  1095. error(M.SUCCESS_PREFIX, 2)
  1096. end
  1097. function M.successIf( cond )
  1098. -- stops a test with a success if condition is met
  1099. if cond then
  1100. error(M.SUCCESS_PREFIX, 2)
  1101. end
  1102. end
  1103. ------------------------------------------------------------------
  1104. -- Equality assertions
  1105. ------------------------------------------------------------------
  1106. function M.assertEquals(actual, expected, extra_msg_or_nil, doDeepAnalysis)
  1107. if type(actual) == 'table' and type(expected) == 'table' then
  1108. if not _is_table_equals(actual, expected) then
  1109. failure( errorMsgEquality(actual, expected, doDeepAnalysis), extra_msg_or_nil, 2 )
  1110. end
  1111. elseif type(actual) ~= type(expected) then
  1112. failure( errorMsgEquality(actual, expected), extra_msg_or_nil, 2 )
  1113. elseif actual ~= expected then
  1114. failure( errorMsgEquality(actual, expected), extra_msg_or_nil, 2 )
  1115. end
  1116. end
  1117. function M.almostEquals( actual, expected, margin )
  1118. if type(actual) ~= 'number' or type(expected) ~= 'number' or type(margin) ~= 'number' then
  1119. error_fmt(3, 'almostEquals: must supply only number arguments.\nArguments supplied: %s, %s, %s',
  1120. prettystr(actual), prettystr(expected), prettystr(margin))
  1121. end
  1122. if margin < 0 then
  1123. error('almostEquals: margin must not be negative, current value is ' .. margin, 3)
  1124. end
  1125. return math.abs(expected - actual) <= margin
  1126. end
  1127. function M.assertAlmostEquals( actual, expected, margin, extra_msg_or_nil )
  1128. -- check that two floats are close by margin
  1129. margin = margin or M.EPS
  1130. if not M.almostEquals(actual, expected, margin) then
  1131. if not M.ORDER_ACTUAL_EXPECTED then
  1132. expected, actual = actual, expected
  1133. end
  1134. local delta = math.abs(actual - expected)
  1135. fail_fmt(2, extra_msg_or_nil, 'Values are not almost equal\n' ..
  1136. 'Actual: %s, expected: %s, delta %s above margin of %s',
  1137. actual, expected, delta, margin)
  1138. end
  1139. end
  1140. function M.assertNotEquals(actual, expected, extra_msg_or_nil)
  1141. if type(actual) ~= type(expected) then
  1142. return
  1143. end
  1144. if type(actual) == 'table' and type(expected) == 'table' then
  1145. if not _is_table_equals(actual, expected) then
  1146. return
  1147. end
  1148. elseif actual ~= expected then
  1149. return
  1150. end
  1151. fail_fmt(2, extra_msg_or_nil, 'Received the not expected value: %s', prettystr(actual))
  1152. end
  1153. function M.assertNotAlmostEquals( actual, expected, margin, extra_msg_or_nil )
  1154. -- check that two floats are not close by margin
  1155. margin = margin or M.EPS
  1156. if M.almostEquals(actual, expected, margin) then
  1157. if not M.ORDER_ACTUAL_EXPECTED then
  1158. expected, actual = actual, expected
  1159. end
  1160. local delta = math.abs(actual - expected)
  1161. fail_fmt(2, extra_msg_or_nil, 'Values are almost equal\nActual: %s, expected: %s' ..
  1162. ', delta %s below margin of %s',
  1163. actual, expected, delta, margin)
  1164. end
  1165. end
  1166. function M.assertItemsEquals(actual, expected, extra_msg_or_nil)
  1167. -- checks that the items of table expected
  1168. -- are contained in table actual. Warning, this function
  1169. -- is at least O(n^2)
  1170. if not _is_table_items_equals(actual, expected ) then
  1171. expected, actual = prettystrPairs(expected, actual)
  1172. fail_fmt(2, extra_msg_or_nil, 'Content of the tables are not identical:\nExpected: %s\nActual: %s',
  1173. expected, actual)
  1174. end
  1175. end
  1176. ------------------------------------------------------------------
  1177. -- String assertion
  1178. ------------------------------------------------------------------
  1179. function M.assertStrContains( str, sub, isPattern, extra_msg_or_nil )
  1180. -- this relies on lua string.find function
  1181. -- a string always contains the empty string
  1182. -- assert( type(str) == 'string', 'Argument 1 of assertStrContains() should be a string.' ) )
  1183. -- assert( type(sub) == 'string', 'Argument 2 of assertStrContains() should be a string.' ) )
  1184. if not string.find(str, sub, 1, not isPattern) then
  1185. sub, str = prettystrPairs(sub, str, '\n')
  1186. fail_fmt(2, extra_msg_or_nil, 'Could not find %s %s in string %s',
  1187. isPattern and 'pattern' or 'substring', sub, str)
  1188. end
  1189. end
  1190. function M.assertStrIContains( str, sub, extra_msg_or_nil )
  1191. -- this relies on lua string.find function
  1192. -- a string always contains the empty string
  1193. if not string.find(str:lower(), sub:lower(), 1, true) then
  1194. sub, str = prettystrPairs(sub, str, '\n')
  1195. fail_fmt(2, extra_msg_or_nil, 'Could not find (case insensitively) substring %s in string %s',
  1196. sub, str)
  1197. end
  1198. end
  1199. function M.assertNotStrContains( str, sub, isPattern, extra_msg_or_nil )
  1200. -- this relies on lua string.find function
  1201. -- a string always contains the empty string
  1202. if string.find(str, sub, 1, not isPattern) then
  1203. sub, str = prettystrPairs(sub, str, '\n')
  1204. fail_fmt(2, extra_msg_or_nil, 'Found the not expected %s %s in string %s',
  1205. isPattern and 'pattern' or 'substring', sub, str)
  1206. end
  1207. end
  1208. function M.assertNotStrIContains( str, sub, extra_msg_or_nil )
  1209. -- this relies on lua string.find function
  1210. -- a string always contains the empty string
  1211. if string.find(str:lower(), sub:lower(), 1, true) then
  1212. sub, str = prettystrPairs(sub, str, '\n')
  1213. fail_fmt(2, extra_msg_or_nil, 'Found (case insensitively) the not expected substring %s in string %s',
  1214. sub, str)
  1215. end
  1216. end
  1217. function M.assertStrMatches( str, pattern, start, final, extra_msg_or_nil )
  1218. -- Verify a full match for the string
  1219. if not strMatch( str, pattern, start, final ) then
  1220. pattern, str = prettystrPairs(pattern, str, '\n')
  1221. fail_fmt(2, extra_msg_or_nil, 'Could not match pattern %s with string %s',
  1222. pattern, str)
  1223. end
  1224. end
  1225. local function _assertErrorMsgEquals( stripFileAndLine, expectedMsg, func, ... )
  1226. local no_error, error_msg = pcall( func, ... )
  1227. if no_error then
  1228. failure( 'No error generated when calling function but expected error: '..M.prettystr(expectedMsg), nil, 3 )
  1229. end
  1230. if type(expectedMsg) == "string" and type(error_msg) ~= "string" then
  1231. -- table are converted to string automatically
  1232. error_msg = tostring(error_msg)
  1233. end
  1234. local differ = false
  1235. if stripFileAndLine then
  1236. if error_msg:gsub("^.+:%d+: ", "") ~= expectedMsg then
  1237. differ = true
  1238. end
  1239. else
  1240. if error_msg ~= expectedMsg then
  1241. local tr = type(error_msg)
  1242. local te = type(expectedMsg)
  1243. if te == 'table' then
  1244. if tr ~= 'table' then
  1245. differ = true
  1246. else
  1247. local ok = pcall(M.assertItemsEquals, error_msg, expectedMsg)
  1248. if not ok then
  1249. differ = true
  1250. end
  1251. end
  1252. else
  1253. differ = true
  1254. end
  1255. end
  1256. end
  1257. if differ then
  1258. error_msg, expectedMsg = prettystrPairs(error_msg, expectedMsg)
  1259. fail_fmt(3, nil, 'Error message expected: %s\nError message received: %s\n',
  1260. expectedMsg, error_msg)
  1261. end
  1262. end
  1263. function M.assertErrorMsgEquals( expectedMsg, func, ... )
  1264. -- assert that calling f with the arguments will raise an error
  1265. -- example: assertError( f, 1, 2 ) => f(1,2) should generate an error
  1266. _assertErrorMsgEquals(false, expectedMsg, func, ...)
  1267. end
  1268. function M.assertErrorMsgContentEquals(expectedMsg, func, ...)
  1269. _assertErrorMsgEquals(true, expectedMsg, func, ...)
  1270. end
  1271. function M.assertErrorMsgContains( partialMsg, func, ... )
  1272. -- assert that calling f with the arguments will raise an error
  1273. -- example: assertError( f, 1, 2 ) => f(1,2) should generate an error
  1274. local no_error, error_msg = pcall( func, ... )
  1275. if no_error then
  1276. failure( 'No error generated when calling function but expected error containing: '..prettystr(partialMsg), nil, 2 )
  1277. end
  1278. if type(error_msg) ~= "string" then
  1279. error_msg = tostring(error_msg)
  1280. end
  1281. if not string.find( error_msg, partialMsg, nil, true ) then
  1282. error_msg, partialMsg = prettystrPairs(error_msg, partialMsg)
  1283. fail_fmt(2, nil, 'Error message does not contain: %s\nError message received: %s\n',
  1284. partialMsg, error_msg)
  1285. end
  1286. end
  1287. function M.assertErrorMsgMatches( expectedMsg, func, ... )
  1288. -- assert that calling f with the arguments will raise an error
  1289. -- example: assertError( f, 1, 2 ) => f(1,2) should generate an error
  1290. local no_error, error_msg = pcall( func, ... )
  1291. if no_error then
  1292. failure( 'No error generated when calling function but expected error matching: "'..expectedMsg..'"', nil, 2 )
  1293. end
  1294. if type(error_msg) ~= "string" then
  1295. error_msg = tostring(error_msg)
  1296. end
  1297. if not strMatch( error_msg, expectedMsg ) then
  1298. expectedMsg, error_msg = prettystrPairs(expectedMsg, error_msg)
  1299. fail_fmt(2, nil, 'Error message does not match pattern: %s\nError message received: %s\n',
  1300. expectedMsg, error_msg)
  1301. end
  1302. end
  1303. ------------------------------------------------------------------
  1304. -- Type assertions
  1305. ------------------------------------------------------------------
  1306. function M.assertEvalToTrue(value, extra_msg_or_nil)
  1307. if not value then
  1308. failure("expected: a value evaluating to true, actual: " ..prettystr(value), extra_msg_or_nil, 2)
  1309. end
  1310. end
  1311. function M.assertEvalToFalse(value, extra_msg_or_nil)
  1312. if value then
  1313. failure("expected: false or nil, actual: " ..prettystr(value), extra_msg_or_nil, 2)
  1314. end
  1315. end
  1316. function M.assertIsTrue(value, extra_msg_or_nil)
  1317. if value ~= true then
  1318. failure("expected: true, actual: " ..prettystr(value), extra_msg_or_nil, 2)
  1319. end
  1320. end
  1321. function M.assertNotIsTrue(value, extra_msg_or_nil)
  1322. if value == true then
  1323. failure("expected: not true, actual: " ..prettystr(value), extra_msg_or_nil, 2)
  1324. end
  1325. end
  1326. function M.assertIsFalse(value, extra_msg_or_nil)
  1327. if value ~= false then
  1328. failure("expected: false, actual: " ..prettystr(value), extra_msg_or_nil, 2)
  1329. end
  1330. end
  1331. function M.assertNotIsFalse(value, extra_msg_or_nil)
  1332. if value == false then
  1333. failure("expected: not false, actual: " ..prettystr(value), extra_msg_or_nil, 2)
  1334. end
  1335. end
  1336. function M.assertIsNil(value, extra_msg_or_nil)
  1337. if value ~= nil then
  1338. failure("expected: nil, actual: " ..prettystr(value), extra_msg_or_nil, 2)
  1339. end
  1340. end
  1341. function M.assertNotIsNil(value, extra_msg_or_nil)
  1342. if value == nil then
  1343. failure("expected: not nil, actual: nil", extra_msg_or_nil, 2)
  1344. end
  1345. end
  1346. --[[
  1347. Add type assertion functions to the module table M. Each of these functions
  1348. takes a single parameter "value", and checks that its Lua type matches the
  1349. expected string (derived from the function name):
  1350. M.assertIsXxx(value) -> ensure that type(value) conforms to "xxx"
  1351. ]]
  1352. for _, funcName in ipairs(
  1353. {'assertIsNumber', 'assertIsString', 'assertIsTable', 'assertIsBoolean',
  1354. 'assertIsFunction', 'assertIsUserdata', 'assertIsThread'}
  1355. ) do
  1356. local typeExpected = funcName:match("^assertIs([A-Z]%a*)$")
  1357. -- Lua type() always returns lowercase, also make sure the match() succeeded
  1358. typeExpected = typeExpected and typeExpected:lower()
  1359. or error("bad function name '"..funcName.."' for type assertion")
  1360. M[funcName] = function(value, extra_msg_or_nil)
  1361. if type(value) ~= typeExpected then
  1362. if type(value) == 'nil' then
  1363. fail_fmt(2, extra_msg_or_nil, 'expected: a %s value, actual: nil',
  1364. typeExpected, type(value), prettystrPairs(value))
  1365. else
  1366. fail_fmt(2, extra_msg_or_nil, 'expected: a %s value, actual: type %s, value %s',
  1367. typeExpected, type(value), prettystrPairs(value))
  1368. end
  1369. end
  1370. end
  1371. end
  1372. --[[
  1373. Add shortcuts for verifying type of a variable, without failure (luaunit v2 compatibility)
  1374. M.isXxx(value) -> returns true if type(value) conforms to "xxx"
  1375. ]]
  1376. for _, typeExpected in ipairs(
  1377. {'Number', 'String', 'Table', 'Boolean',
  1378. 'Function', 'Userdata', 'Thread', 'Nil' }
  1379. ) do
  1380. local typeExpectedLower = typeExpected:lower()
  1381. local isType = function(value)
  1382. return (type(value) == typeExpectedLower)
  1383. end
  1384. M['is'..typeExpected] = isType
  1385. M['is_'..typeExpectedLower] = isType
  1386. end
  1387. --[[
  1388. Add non-type assertion functions to the module table M. Each of these functions
  1389. takes a single parameter "value", and checks that its Lua type differs from the
  1390. expected string (derived from the function name):
  1391. M.assertNotIsXxx(value) -> ensure that type(value) is not "xxx"
  1392. ]]
  1393. for _, funcName in ipairs(
  1394. {'assertNotIsNumber', 'assertNotIsString', 'assertNotIsTable', 'assertNotIsBoolean',
  1395. 'assertNotIsFunction', 'assertNotIsUserdata', 'assertNotIsThread'}
  1396. ) do
  1397. local typeUnexpected = funcName:match("^assertNotIs([A-Z]%a*)$")
  1398. -- Lua type() always returns lowercase, also make sure the match() succeeded
  1399. typeUnexpected = typeUnexpected and typeUnexpected:lower()
  1400. or error("bad function name '"..funcName.."' for type assertion")
  1401. M[funcName] = function(value, extra_msg_or_nil)
  1402. if type(value) == typeUnexpected then
  1403. fail_fmt(2, extra_msg_or_nil, 'expected: not a %s type, actual: value %s',
  1404. typeUnexpected, prettystrPairs(value))
  1405. end
  1406. end
  1407. end
  1408. function M.assertIs(actual, expected, extra_msg_or_nil)
  1409. if actual ~= expected then
  1410. if not M.ORDER_ACTUAL_EXPECTED then
  1411. actual, expected = expected, actual
  1412. end
  1413. local old_print_table_ref_in_error_msg = M.PRINT_TABLE_REF_IN_ERROR_MSG
  1414. M.PRINT_TABLE_REF_IN_ERROR_MSG = true
  1415. expected, actual = prettystrPairs(expected, actual, '\n', '')
  1416. M.PRINT_TABLE_REF_IN_ERROR_MSG = old_print_table_ref_in_error_msg
  1417. fail_fmt(2, extra_msg_or_nil, 'expected and actual object should not be different\nExpected: %s\nReceived: %s',
  1418. expected, actual)
  1419. end
  1420. end
  1421. function M.assertNotIs(actual, expected, extra_msg_or_nil)
  1422. if actual == expected then
  1423. local old_print_table_ref_in_error_msg = M.PRINT_TABLE_REF_IN_ERROR_MSG
  1424. M.PRINT_TABLE_REF_IN_ERROR_MSG = true
  1425. local s_expected
  1426. if not M.ORDER_ACTUAL_EXPECTED then
  1427. s_expected = prettystrPairs(actual)
  1428. else
  1429. s_expected = prettystrPairs(expected)
  1430. end
  1431. M.PRINT_TABLE_REF_IN_ERROR_MSG = old_print_table_ref_in_error_msg
  1432. fail_fmt(2, extra_msg_or_nil, 'expected and actual object should be different: %s', s_expected )
  1433. end
  1434. end
  1435. ------------------------------------------------------------------
  1436. -- Scientific assertions
  1437. ------------------------------------------------------------------
  1438. function M.assertIsNaN(value, extra_msg_or_nil)
  1439. if type(value) ~= "number" or value == value then
  1440. failure("expected: NaN, actual: " ..prettystr(value), extra_msg_or_nil, 2)
  1441. end
  1442. end
  1443. function M.assertNotIsNaN(value, extra_msg_or_nil)
  1444. if type(value) == "number" and value ~= value then
  1445. failure("expected: not NaN, actual: NaN", extra_msg_or_nil, 2)
  1446. end
  1447. end
  1448. function M.assertIsInf(value, extra_msg_or_nil)
  1449. if type(value) ~= "number" or math.abs(value) ~= math.huge then
  1450. failure("expected: #Inf, actual: " ..prettystr(value), extra_msg_or_nil, 2)
  1451. end
  1452. end
  1453. function M.assertIsPlusInf(value, extra_msg_or_nil)
  1454. if type(value) ~= "number" or value ~= math.huge then
  1455. failure("expected: #Inf, actual: " ..prettystr(value), extra_msg_or_nil, 2)
  1456. end
  1457. end
  1458. function M.assertIsMinusInf(value, extra_msg_or_nil)
  1459. if type(value) ~= "number" or value ~= -math.huge then
  1460. failure("expected: -#Inf, actual: " ..prettystr(value), extra_msg_or_nil, 2)
  1461. end
  1462. end
  1463. function M.assertNotIsPlusInf(value, extra_msg_or_nil)
  1464. if type(value) == "number" and value == math.huge then
  1465. failure("expected: not #Inf, actual: #Inf", extra_msg_or_nil, 2)
  1466. end
  1467. end
  1468. function M.assertNotIsMinusInf(value, extra_msg_or_nil)
  1469. if type(value) == "number" and value == -math.huge then
  1470. failure("expected: not -#Inf, actual: -#Inf", extra_msg_or_nil, 2)
  1471. end
  1472. end
  1473. function M.assertNotIsInf(value, extra_msg_or_nil)
  1474. if type(value) == "number" and math.abs(value) == math.huge then
  1475. failure("expected: not infinity, actual: " .. prettystr(value), extra_msg_or_nil, 2)
  1476. end
  1477. end
  1478. function M.assertIsPlusZero(value, extra_msg_or_nil)
  1479. if type(value) ~= 'number' or value ~= 0 then
  1480. failure("expected: +0.0, actual: " ..prettystr(value), extra_msg_or_nil, 2)
  1481. else if (1/value == -math.huge) then
  1482. -- more precise error diagnosis
  1483. failure("expected: +0.0, actual: -0.0", extra_msg_or_nil, 2)
  1484. else if (1/value ~= math.huge) then
  1485. -- strange, case should have already been covered
  1486. failure("expected: +0.0, actual: " ..prettystr(value), extra_msg_or_nil, 2)
  1487. end
  1488. end
  1489. end
  1490. end
  1491. function M.assertIsMinusZero(value, extra_msg_or_nil)
  1492. if type(value) ~= 'number' or value ~= 0 then
  1493. failure("expected: -0.0, actual: " ..prettystr(value), extra_msg_or_nil, 2)
  1494. else if (1/value == math.huge) then
  1495. -- more precise error diagnosis
  1496. failure("expected: -0.0, actual: +0.0", extra_msg_or_nil, 2)
  1497. else if (1/value ~= -math.huge) then
  1498. -- strange, case should have already been covered
  1499. failure("expected: -0.0, actual: " ..prettystr(value), extra_msg_or_nil, 2)
  1500. end
  1501. end
  1502. end
  1503. end
  1504. function M.assertNotIsPlusZero(value, extra_msg_or_nil)
  1505. if type(value) == 'number' and (1/value == math.huge) then
  1506. failure("expected: not +0.0, actual: +0.0", extra_msg_or_nil, 2)
  1507. end
  1508. end
  1509. function M.assertNotIsMinusZero(value, extra_msg_or_nil)
  1510. if type(value) == 'number' and (1/value == -math.huge) then
  1511. failure("expected: not -0.0, actual: -0.0", extra_msg_or_nil, 2)
  1512. end
  1513. end
  1514. function M.assertTableContains(t, expected)
  1515. -- checks that table t contains the expected element
  1516. if table_findkeyof(t, expected) == nil then
  1517. t, expected = prettystrPairs(t, expected)
  1518. fail_fmt(2, 'Table %s does NOT contain the expected element %s',
  1519. t, expected)
  1520. end
  1521. end
  1522. function M.assertNotTableContains(t, expected)
  1523. -- checks that table t doesn't contain the expected element
  1524. local k = table_findkeyof(t, expected)
  1525. if k ~= nil then
  1526. t, expected = prettystrPairs(t, expected)
  1527. fail_fmt(2, 'Table %s DOES contain the unwanted element %s (at key %s)',
  1528. t, expected, prettystr(k))
  1529. end
  1530. end
  1531. ----------------------------------------------------------------
  1532. -- Compatibility layer
  1533. ----------------------------------------------------------------
  1534. -- for compatibility with LuaUnit v2.x
  1535. function M.wrapFunctions()
  1536. -- In LuaUnit version <= 2.1 , this function was necessary to include
  1537. -- a test function inside the global test suite. Nowadays, the functions
  1538. -- are simply run directly as part of the test discovery process.
  1539. -- so just do nothing !
  1540. io.stderr:write[[Use of WrapFunctions() is no longer needed.
  1541. Just prefix your test function names with "test" or "Test" and they
  1542. will be picked up and run by LuaUnit.
  1543. ]]
  1544. end
  1545. local list_of_funcs = {
  1546. -- { official function name , alias }
  1547. -- general assertions
  1548. { 'assertEquals' , 'assert_equals' },
  1549. { 'assertItemsEquals' , 'assert_items_equals' },
  1550. { 'assertNotEquals' , 'assert_not_equals' },
  1551. { 'assertAlmostEquals' , 'assert_almost_equals' },
  1552. { 'assertNotAlmostEquals' , 'assert_not_almost_equals' },
  1553. { 'assertEvalToTrue' , 'assert_eval_to_true' },
  1554. { 'assertEvalToFalse' , 'assert_eval_to_false' },
  1555. { 'assertStrContains' , 'assert_str_contains' },
  1556. { 'assertStrIContains' , 'assert_str_icontains' },
  1557. { 'assertNotStrContains' , 'assert_not_str_contains' },
  1558. { 'assertNotStrIContains' , 'assert_not_str_icontains' },
  1559. { 'assertStrMatches' , 'assert_str_matches' },
  1560. { 'assertError' , 'assert_error' },
  1561. { 'assertErrorMsgEquals' , 'assert_error_msg_equals' },
  1562. { 'assertErrorMsgContains' , 'assert_error_msg_contains' },
  1563. { 'assertErrorMsgMatches' , 'assert_error_msg_matches' },
  1564. { 'assertErrorMsgContentEquals', 'assert_error_msg_content_equals' },
  1565. { 'assertIs' , 'assert_is' },
  1566. { 'assertNotIs' , 'assert_not_is' },
  1567. { 'assertTableContains' , 'assert_table_contains' },
  1568. { 'assertNotTableContains' , 'assert_not_table_contains' },
  1569. { 'wrapFunctions' , 'WrapFunctions' },
  1570. { 'wrapFunctions' , 'wrap_functions' },
  1571. -- type assertions: assertIsXXX -> assert_is_xxx
  1572. { 'assertIsNumber' , 'assert_is_number' },
  1573. { 'assertIsString' , 'assert_is_string' },
  1574. { 'assertIsTable' , 'assert_is_table' },
  1575. { 'assertIsBoolean' , 'assert_is_boolean' },
  1576. { 'assertIsNil' , 'assert_is_nil' },
  1577. { 'assertIsTrue' , 'assert_is_true' },
  1578. { 'assertIsFalse' , 'assert_is_false' },
  1579. { 'assertIsNaN' , 'assert_is_nan' },
  1580. { 'assertIsInf' , 'assert_is_inf' },
  1581. { 'assertIsPlusInf' , 'assert_is_plus_inf' },
  1582. { 'assertIsMinusInf' , 'assert_is_minus_inf' },
  1583. { 'assertIsPlusZero' , 'assert_is_plus_zero' },
  1584. { 'assertIsMinusZero' , 'assert_is_minus_zero' },
  1585. { 'assertIsFunction' , 'assert_is_function' },
  1586. { 'assertIsThread' , 'assert_is_thread' },
  1587. { 'assertIsUserdata' , 'assert_is_userdata' },
  1588. -- type assertions: assertIsXXX -> assertXxx
  1589. { 'assertIsNumber' , 'assertNumber' },
  1590. { 'assertIsString' , 'assertString' },
  1591. { 'assertIsTable' , 'assertTable' },
  1592. { 'assertIsBoolean' , 'assertBoolean' },
  1593. { 'assertIsNil' , 'assertNil' },
  1594. { 'assertIsTrue' , 'assertTrue' },
  1595. { 'assertIsFalse' , 'assertFalse' },
  1596. { 'assertIsNaN' , 'assertNaN' },
  1597. { 'assertIsInf' , 'assertInf' },
  1598. { 'assertIsPlusInf' , 'assertPlusInf' },
  1599. { 'assertIsMinusInf' , 'assertMinusInf' },
  1600. { 'assertIsPlusZero' , 'assertPlusZero' },
  1601. { 'assertIsMinusZero' , 'assertMinusZero'},
  1602. { 'assertIsFunction' , 'assertFunction' },
  1603. { 'assertIsThread' , 'assertThread' },
  1604. { 'assertIsUserdata' , 'assertUserdata' },
  1605. -- type assertions: assertIsXXX -> assert_xxx (luaunit v2 compat)
  1606. { 'assertIsNumber' , 'assert_number' },
  1607. { 'assertIsString' , 'assert_string' },
  1608. { 'assertIsTable' , 'assert_table' },
  1609. { 'assertIsBoolean' , 'assert_boolean' },
  1610. { 'assertIsNil' , 'assert_nil' },
  1611. { 'assertIsTrue' , 'assert_true' },
  1612. { 'assertIsFalse' , 'assert_false' },
  1613. { 'assertIsNaN' , 'assert_nan' },
  1614. { 'assertIsInf' , 'assert_inf' },
  1615. { 'assertIsPlusInf' , 'assert_plus_inf' },
  1616. { 'assertIsMinusInf' , 'assert_minus_inf' },
  1617. { 'assertIsPlusZero' , 'assert_plus_zero' },
  1618. { 'assertIsMinusZero' , 'assert_minus_zero' },
  1619. { 'assertIsFunction' , 'assert_function' },
  1620. { 'assertIsThread' , 'assert_thread' },
  1621. { 'assertIsUserdata' , 'assert_userdata' },
  1622. -- type assertions: assertNotIsXXX -> assert_not_is_xxx
  1623. { 'assertNotIsNumber' , 'assert_not_is_number' },
  1624. { 'assertNotIsString' , 'assert_not_is_string' },
  1625. { 'assertNotIsTable' , 'assert_not_is_table' },
  1626. { 'assertNotIsBoolean' , 'assert_not_is_boolean' },
  1627. { 'assertNotIsNil' , 'assert_not_is_nil' },
  1628. { 'assertNotIsTrue' , 'assert_not_is_true' },
  1629. { 'assertNotIsFalse' , 'assert_not_is_false' },
  1630. { 'assertNotIsNaN' , 'assert_not_is_nan' },
  1631. { 'assertNotIsInf' , 'assert_not_is_inf' },
  1632. { 'assertNotIsPlusInf' , 'assert_not_plus_inf' },
  1633. { 'assertNotIsMinusInf' , 'assert_not_minus_inf' },
  1634. { 'assertNotIsPlusZero' , 'assert_not_plus_zero' },
  1635. { 'assertNotIsMinusZero' , 'assert_not_minus_zero' },
  1636. { 'assertNotIsFunction' , 'assert_not_is_function' },
  1637. { 'assertNotIsThread' , 'assert_not_is_thread' },
  1638. { 'assertNotIsUserdata' , 'assert_not_is_userdata' },
  1639. -- type assertions: assertNotIsXXX -> assertNotXxx (luaunit v2 compat)
  1640. { 'assertNotIsNumber' , 'assertNotNumber' },
  1641. { 'assertNotIsString' , 'assertNotString' },
  1642. { 'assertNotIsTable' , 'assertNotTable' },
  1643. { 'assertNotIsBoolean' , 'assertNotBoolean' },
  1644. { 'assertNotIsNil' , 'assertNotNil' },
  1645. { 'assertNotIsTrue' , 'assertNotTrue' },
  1646. { 'assertNotIsFalse' , 'assertNotFalse' },
  1647. { 'assertNotIsNaN' , 'assertNotNaN' },
  1648. { 'assertNotIsInf' , 'assertNotInf' },
  1649. { 'assertNotIsPlusInf' , 'assertNotPlusInf' },
  1650. { 'assertNotIsMinusInf' , 'assertNotMinusInf' },
  1651. { 'assertNotIsPlusZero' , 'assertNotPlusZero' },
  1652. { 'assertNotIsMinusZero' , 'assertNotMinusZero' },
  1653. { 'assertNotIsFunction' , 'assertNotFunction' },
  1654. { 'assertNotIsThread' , 'assertNotThread' },
  1655. { 'assertNotIsUserdata' , 'assertNotUserdata' },
  1656. -- type assertions: assertNotIsXXX -> assert_not_xxx
  1657. { 'assertNotIsNumber' , 'assert_not_number' },
  1658. { 'assertNotIsString' , 'assert_not_string' },
  1659. { 'assertNotIsTable' , 'assert_not_table' },
  1660. { 'assertNotIsBoolean' , 'assert_not_boolean' },
  1661. { 'assertNotIsNil' , 'assert_not_nil' },
  1662. { 'assertNotIsTrue' , 'assert_not_true' },
  1663. { 'assertNotIsFalse' , 'assert_not_false' },
  1664. { 'assertNotIsNaN' , 'assert_not_nan' },
  1665. { 'assertNotIsInf' , 'assert_not_inf' },
  1666. { 'assertNotIsPlusInf' , 'assert_not_plus_inf' },
  1667. { 'assertNotIsMinusInf' , 'assert_not_minus_inf' },
  1668. { 'assertNotIsPlusZero' , 'assert_not_plus_zero' },
  1669. { 'assertNotIsMinusZero' , 'assert_not_minus_zero' },
  1670. { 'assertNotIsFunction' , 'assert_not_function' },
  1671. { 'assertNotIsThread' , 'assert_not_thread' },
  1672. { 'assertNotIsUserdata' , 'assert_not_userdata' },
  1673. -- all assertions with Coroutine duplicate Thread assertions
  1674. { 'assertIsThread' , 'assertIsCoroutine' },
  1675. { 'assertIsThread' , 'assertCoroutine' },
  1676. { 'assertIsThread' , 'assert_is_coroutine' },
  1677. { 'assertIsThread' , 'assert_coroutine' },
  1678. { 'assertNotIsThread' , 'assertNotIsCoroutine' },
  1679. { 'assertNotIsThread' , 'assertNotCoroutine' },
  1680. { 'assertNotIsThread' , 'assert_not_is_coroutine' },
  1681. { 'assertNotIsThread' , 'assert_not_coroutine' },
  1682. }
  1683. -- Create all aliases in M
  1684. for _,v in ipairs( list_of_funcs ) do
  1685. local funcname, alias = v[1], v[2]
  1686. M[alias] = M[funcname]
  1687. if EXPORT_ASSERT_TO_GLOBALS then
  1688. _G[funcname] = M[funcname]
  1689. _G[alias] = M[funcname]
  1690. end
  1691. end
  1692. ----------------------------------------------------------------
  1693. --
  1694. -- Outputters
  1695. --
  1696. ----------------------------------------------------------------
  1697. -- A common "base" class for outputters
  1698. -- For concepts involved (class inheritance) see http://www.lua.org/pil/16.2.html
  1699. local genericOutput = { __class__ = 'genericOutput' } -- class
  1700. local genericOutput_MT = { __index = genericOutput } -- metatable
  1701. M.genericOutput = genericOutput -- publish, so that custom classes may derive from it
  1702. function genericOutput.new(runner, default_verbosity)
  1703. -- runner is the "parent" object controlling the output, usually a LuaUnit instance
  1704. local t = { runner = runner }
  1705. if runner then
  1706. t.result = runner.result
  1707. t.verbosity = runner.verbosity or default_verbosity
  1708. t.fname = runner.fname
  1709. else
  1710. t.verbosity = default_verbosity
  1711. end
  1712. return setmetatable( t, genericOutput_MT)
  1713. end
  1714. -- abstract ("empty") methods
  1715. function genericOutput:startSuite()
  1716. -- Called once, when the suite is started
  1717. end
  1718. function genericOutput:startClass(className)
  1719. -- Called each time a new test class is started
  1720. end
  1721. function genericOutput:startTest(testName)
  1722. -- called each time a new test is started, right before the setUp()
  1723. -- the current test status node is already created and available in: self.result.currentNode
  1724. end
  1725. function genericOutput:updateStatus(node)
  1726. -- called with status failed or error as soon as the error/failure is encountered
  1727. -- this method is NOT called for a successful test because a test is marked as successful by default
  1728. -- and does not need to be updated
  1729. end
  1730. function genericOutput:endTest(node)
  1731. -- called when the test is finished, after the tearDown() method
  1732. end
  1733. function genericOutput:endClass()
  1734. -- called when executing the class is finished, before moving on to the next class of at the end of the test execution
  1735. end
  1736. function genericOutput:endSuite()
  1737. -- called at the end of the test suite execution
  1738. end
  1739. ----------------------------------------------------------------
  1740. -- class TapOutput
  1741. ----------------------------------------------------------------
  1742. local TapOutput = genericOutput.new() -- derived class
  1743. local TapOutput_MT = { __index = TapOutput } -- metatable
  1744. TapOutput.__class__ = 'TapOutput'
  1745. -- For a good reference for TAP format, check: http://testanything.org/tap-specification.html
  1746. function TapOutput.new(runner)
  1747. local t = genericOutput.new(runner, M.VERBOSITY_LOW)
  1748. return setmetatable( t, TapOutput_MT)
  1749. end
  1750. function TapOutput:startSuite()
  1751. print("1.."..self.result.selectedCount)
  1752. print('# Started on '..self.result.startDate)
  1753. end
  1754. function TapOutput:startClass(className)
  1755. if className ~= '[TestFunctions]' then
  1756. print('# Starting class: '..className)
  1757. end
  1758. end
  1759. function TapOutput:updateStatus( node )
  1760. if node:isSkipped() then
  1761. io.stdout:write("ok ", self.result.currentTestNumber, "\t# SKIP ", node.msg, "\n" )
  1762. return
  1763. end
  1764. io.stdout:write("not ok ", self.result.currentTestNumber, "\t", node.testName, "\n")
  1765. if self.verbosity > M.VERBOSITY_LOW then
  1766. print( prefixString( '# ', node.msg ) )
  1767. end
  1768. if (node:isFailure() or node:isError()) and self.verbosity > M.VERBOSITY_DEFAULT then
  1769. print( prefixString( '# ', node.stackTrace ) )
  1770. end
  1771. end
  1772. function TapOutput:endTest( node )
  1773. if node:isSuccess() then
  1774. io.stdout:write("ok ", self.result.currentTestNumber, "\t", node.testName, "\n")
  1775. end
  1776. end
  1777. function TapOutput:endSuite()
  1778. print( '# '..M.LuaUnit.statusLine( self.result ) )
  1779. return self.result.notSuccessCount
  1780. end
  1781. -- class TapOutput end
  1782. ----------------------------------------------------------------
  1783. -- class JUnitOutput
  1784. ----------------------------------------------------------------
  1785. -- See directory junitxml for more information about the junit format
  1786. local JUnitOutput = genericOutput.new() -- derived class
  1787. local JUnitOutput_MT = { __index = JUnitOutput } -- metatable
  1788. JUnitOutput.__class__ = 'JUnitOutput'
  1789. function JUnitOutput.new(runner)
  1790. local t = genericOutput.new(runner, M.VERBOSITY_LOW)
  1791. t.testList = {}
  1792. return setmetatable( t, JUnitOutput_MT )
  1793. end
  1794. function JUnitOutput:startSuite()
  1795. -- open xml file early to deal with errors
  1796. if self.fname == nil then
  1797. error('With Junit, an output filename must be supplied with --name!')
  1798. end
  1799. if string.sub(self.fname,-4) ~= '.xml' then
  1800. self.fname = self.fname..'.xml'
  1801. end
  1802. self.fd = io.open(self.fname, "w")
  1803. if self.fd == nil then
  1804. error("Could not open file for writing: "..self.fname)
  1805. end
  1806. print('# XML output to '..self.fname)
  1807. print('# Started on '..self.result.startDate)
  1808. end
  1809. function JUnitOutput:startClass(className)
  1810. if className ~= '[TestFunctions]' then
  1811. print('# Starting class: '..className)
  1812. end
  1813. end
  1814. function JUnitOutput:startTest(testName)
  1815. print('# Starting test: '..testName)
  1816. end
  1817. function JUnitOutput:updateStatus( node )
  1818. if node:isFailure() then
  1819. print( '# Failure: ' .. prefixString( '# ', node.msg ):sub(4, nil) )
  1820. -- print('# ' .. node.stackTrace)
  1821. elseif node:isError() then
  1822. print( '# Error: ' .. prefixString( '# ' , node.msg ):sub(4, nil) )
  1823. -- print('# ' .. node.stackTrace)
  1824. end
  1825. end
  1826. function JUnitOutput:endSuite()
  1827. print( '# '..M.LuaUnit.statusLine(self.result))
  1828. -- XML file writing
  1829. self.fd:write('<?xml version="1.0" encoding="UTF-8" ?>\n')
  1830. self.fd:write('<testsuites>\n')
  1831. self.fd:write(string.format(
  1832. ' <testsuite name="LuaUnit" id="00001" package="" hostname="localhost" tests="%d" timestamp="%s" time="%0.3f" errors="%d" failures="%d" skipped="%d">\n',
  1833. self.result.runCount, self.result.startIsodate, self.result.duration, self.result.errorCount, self.result.failureCount, self.result.skippedCount ))
  1834. self.fd:write(" <properties>\n")
  1835. self.fd:write(string.format(' <property name="Lua Version" value="%s"/>\n', _VERSION ) )
  1836. self.fd:write(string.format(' <property name="LuaUnit Version" value="%s"/>\n', M.VERSION) )
  1837. -- XXX please include system name and version if possible
  1838. self.fd:write(" </properties>\n")
  1839. for i,node in ipairs(self.result.allTests) do
  1840. self.fd:write(string.format(' <testcase classname="%s" name="%s" time="%0.3f">\n',
  1841. node.className, node.testName, node.duration ) )
  1842. if node:isNotSuccess() then
  1843. self.fd:write(node:statusXML())
  1844. end
  1845. self.fd:write(' </testcase>\n')
  1846. end
  1847. -- Next two lines are needed to validate junit ANT xsd, but really not useful in general:
  1848. self.fd:write(' <system-out/>\n')
  1849. self.fd:write(' <system-err/>\n')
  1850. self.fd:write(' </testsuite>\n')
  1851. self.fd:write('</testsuites>\n')
  1852. self.fd:close()
  1853. return self.result.notSuccessCount
  1854. end
  1855. -- class TapOutput end
  1856. ----------------------------------------------------------------
  1857. -- class TextOutput
  1858. ----------------------------------------------------------------
  1859. --[[ Example of other unit-tests suite text output
  1860. -- Python Non verbose:
  1861. For each test: . or F or E
  1862. If some failed tests:
  1863. ==============
  1864. ERROR / FAILURE: TestName (testfile.testclass)
  1865. ---------
  1866. Stack trace
  1867. then --------------
  1868. then "Ran x tests in 0.000s"
  1869. then OK or FAILED (failures=1, error=1)
  1870. -- Python Verbose:
  1871. testname (filename.classname) ... ok
  1872. testname (filename.classname) ... FAIL
  1873. testname (filename.classname) ... ERROR
  1874. then --------------
  1875. then "Ran x tests in 0.000s"
  1876. then OK or FAILED (failures=1, error=1)
  1877. -- Ruby:
  1878. Started
  1879. .
  1880. Finished in 0.002695 seconds.
  1881. 1 tests, 2 assertions, 0 failures, 0 errors
  1882. -- Ruby:
  1883. >> ruby tc_simple_number2.rb
  1884. Loaded suite tc_simple_number2
  1885. Started
  1886. F..
  1887. Finished in 0.038617 seconds.
  1888. 1) Failure:
  1889. test_failure(TestSimpleNumber) [tc_simple_number2.rb:16]:
  1890. Adding doesn't work.
  1891. <3> expected but was
  1892. <4>.
  1893. 3 tests, 4 assertions, 1 failures, 0 errors
  1894. -- Java Junit
  1895. .......F.
  1896. Time: 0,003
  1897. There was 1 failure:
  1898. 1) testCapacity(junit.samples.VectorTest)junit.framework.AssertionFailedError
  1899. at junit.samples.VectorTest.testCapacity(VectorTest.java:87)
  1900. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  1901. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  1902. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  1903. FAILURES!!!
  1904. Tests run: 8, Failures: 1, Errors: 0
  1905. -- Maven
  1906. # mvn test
  1907. -------------------------------------------------------
  1908. T E S T S
  1909. -------------------------------------------------------
  1910. Running math.AdditionTest
  1911. Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, Time elapsed:
  1912. 0.03 sec <<< FAILURE!
  1913. Results :
  1914. Failed tests:
  1915. testLireSymbole(math.AdditionTest)
  1916. Tests run: 2, Failures: 1, Errors: 0, Skipped: 0
  1917. -- LuaUnit
  1918. ---- non verbose
  1919. * display . or F or E when running tests
  1920. ---- verbose
  1921. * display test name + ok/fail
  1922. ----
  1923. * blank line
  1924. * number) ERROR or FAILURE: TestName
  1925. Stack trace
  1926. * blank line
  1927. * number) ERROR or FAILURE: TestName
  1928. Stack trace
  1929. then --------------
  1930. then "Ran x tests in 0.000s (%d not selected, %d skipped)"
  1931. then OK or FAILED (failures=1, error=1)
  1932. ]]
  1933. local TextOutput = genericOutput.new() -- derived class
  1934. local TextOutput_MT = { __index = TextOutput } -- metatable
  1935. TextOutput.__class__ = 'TextOutput'
  1936. function TextOutput.new(runner)
  1937. local t = genericOutput.new(runner, M.VERBOSITY_DEFAULT)
  1938. t.errorList = {}
  1939. return setmetatable( t, TextOutput_MT )
  1940. end
  1941. function TextOutput:startSuite()
  1942. if self.verbosity > M.VERBOSITY_DEFAULT then
  1943. print( 'Started on '.. self.result.startDate )
  1944. end
  1945. end
  1946. function TextOutput:startTest(testName)
  1947. if self.verbosity > M.VERBOSITY_DEFAULT then
  1948. io.stdout:write( " ", self.result.currentNode.testName, " ... " )
  1949. end
  1950. end
  1951. function TextOutput:endTest( node )
  1952. if node:isSuccess() then
  1953. if self.verbosity > M.VERBOSITY_DEFAULT then
  1954. io.stdout:write("Ok\n")
  1955. else
  1956. io.stdout:write(".")
  1957. io.stdout:flush()
  1958. end
  1959. else
  1960. if self.verbosity > M.VERBOSITY_DEFAULT then
  1961. print( node.status )
  1962. print( node.msg )
  1963. --[[
  1964. -- find out when to do this:
  1965. if self.verbosity > M.VERBOSITY_DEFAULT then
  1966. print( node.stackTrace )
  1967. end
  1968. ]]
  1969. else
  1970. -- write only the first character of status E, F or S
  1971. io.stdout:write(string.sub(node.status, 1, 1))
  1972. io.stdout:flush()
  1973. end
  1974. end
  1975. end
  1976. function TextOutput:displayOneFailedTest( index, fail )
  1977. print(index..") "..fail.testName )
  1978. print( fail.msg )
  1979. print( fail.stackTrace )
  1980. print()
  1981. end
  1982. function TextOutput:displayErroredTests()
  1983. if #self.result.errorTests ~= 0 then
  1984. print("Tests with errors:")
  1985. print("------------------")
  1986. for i, v in ipairs(self.result.errorTests) do
  1987. self:displayOneFailedTest(i, v)
  1988. end
  1989. end
  1990. end
  1991. function TextOutput:displayFailedTests()
  1992. if #self.result.failedTests ~= 0 then
  1993. print("Failed tests:")
  1994. print("-------------")
  1995. for i, v in ipairs(self.result.failedTests) do
  1996. self:displayOneFailedTest(i, v)
  1997. end
  1998. end
  1999. end
  2000. function TextOutput:endSuite()
  2001. if self.verbosity > M.VERBOSITY_DEFAULT then
  2002. print("=========================================================")
  2003. else
  2004. print()
  2005. end
  2006. self:displayErroredTests()
  2007. self:displayFailedTests()
  2008. print( M.LuaUnit.statusLine( self.result ) )
  2009. if self.result.notSuccessCount == 0 then
  2010. print('OK')
  2011. end
  2012. end
  2013. -- class TextOutput end
  2014. ----------------------------------------------------------------
  2015. -- class NilOutput
  2016. ----------------------------------------------------------------
  2017. local function nopCallable()
  2018. --print(42)
  2019. return nopCallable
  2020. end
  2021. local NilOutput = { __class__ = 'NilOuptut' } -- class
  2022. local NilOutput_MT = { __index = nopCallable } -- metatable
  2023. function NilOutput.new(runner)
  2024. return setmetatable( { __class__ = 'NilOutput' }, NilOutput_MT )
  2025. end
  2026. ----------------------------------------------------------------
  2027. --
  2028. -- class LuaUnit
  2029. --
  2030. ----------------------------------------------------------------
  2031. M.LuaUnit = {
  2032. outputType = TextOutput,
  2033. verbosity = M.VERBOSITY_DEFAULT,
  2034. __class__ = 'LuaUnit'
  2035. }
  2036. local LuaUnit_MT = { __index = M.LuaUnit }
  2037. if EXPORT_ASSERT_TO_GLOBALS then
  2038. LuaUnit = M.LuaUnit
  2039. end
  2040. function M.LuaUnit.new()
  2041. return setmetatable( {}, LuaUnit_MT )
  2042. end
  2043. -----------------[[ Utility methods ]]---------------------
  2044. function M.LuaUnit.asFunction(aObject)
  2045. -- return "aObject" if it is a function, and nil otherwise
  2046. if 'function' == type(aObject) then
  2047. return aObject
  2048. end
  2049. end
  2050. function M.LuaUnit.splitClassMethod(someName)
  2051. --[[
  2052. Return a pair of className, methodName strings for a name in the form
  2053. "class.method". If no class part (or separator) is found, will return
  2054. nil, someName instead (the latter being unchanged).
  2055. This convention thus also replaces the older isClassMethod() test:
  2056. You just have to check for a non-nil className (return) value.
  2057. ]]
  2058. local separator = string.find(someName, '.', 1, true)
  2059. if separator then
  2060. return someName:sub(1, separator - 1), someName:sub(separator + 1)
  2061. end
  2062. return nil, someName
  2063. end
  2064. function M.LuaUnit.isMethodTestName( s )
  2065. -- return true is the name matches the name of a test method
  2066. -- default rule is that is starts with 'Test' or with 'test'
  2067. return string.sub(s, 1, 4):lower() == 'test'
  2068. end
  2069. function M.LuaUnit.isTestName( s )
  2070. -- return true is the name matches the name of a test
  2071. -- default rule is that is starts with 'Test' or with 'test'
  2072. return string.sub(s, 1, 4):lower() == 'test'
  2073. end
  2074. function M.LuaUnit.collectTests()
  2075. -- return a list of all test names in the global namespace
  2076. -- that match LuaUnit.isTestName
  2077. local testNames = {}
  2078. for k, _ in pairs(_G) do
  2079. if type(k) == "string" and M.LuaUnit.isTestName( k ) then
  2080. table.insert( testNames , k )
  2081. end
  2082. end
  2083. table.sort( testNames )
  2084. return testNames
  2085. end
  2086. function M.LuaUnit.parseCmdLine( cmdLine )
  2087. -- parse the command line
  2088. -- Supported command line parameters:
  2089. -- --verbose, -v: increase verbosity
  2090. -- --quiet, -q: silence output
  2091. -- --error, -e: treat errors as fatal (quit program)
  2092. -- --output, -o, + name: select output type
  2093. -- --pattern, -p, + pattern: run test matching pattern, may be repeated
  2094. -- --exclude, -x, + pattern: run test not matching pattern, may be repeated
  2095. -- --shuffle, -s, : shuffle tests before reunning them
  2096. -- --name, -n, + fname: name of output file for junit, default to stdout
  2097. -- --repeat, -r, + num: number of times to execute each test
  2098. -- [testnames, ...]: run selected test names
  2099. --
  2100. -- Returns a table with the following fields:
  2101. -- verbosity: nil, M.VERBOSITY_DEFAULT, M.VERBOSITY_QUIET, M.VERBOSITY_VERBOSE
  2102. -- output: nil, 'tap', 'junit', 'text', 'nil'
  2103. -- testNames: nil or a list of test names to run
  2104. -- exeRepeat: num or 1
  2105. -- pattern: nil or a list of patterns
  2106. -- exclude: nil or a list of patterns
  2107. local result, state = {}, nil
  2108. local SET_OUTPUT = 1
  2109. local SET_PATTERN = 2
  2110. local SET_EXCLUDE = 3
  2111. local SET_FNAME = 4
  2112. local SET_REPEAT = 5
  2113. if cmdLine == nil then
  2114. return result
  2115. end
  2116. local function parseOption( option )
  2117. if option == '--help' or option == '-h' then
  2118. result['help'] = true
  2119. return
  2120. elseif option == '--version' then
  2121. result['version'] = true
  2122. return
  2123. elseif option == '--verbose' or option == '-v' then
  2124. result['verbosity'] = M.VERBOSITY_VERBOSE
  2125. return
  2126. elseif option == '--quiet' or option == '-q' then
  2127. result['verbosity'] = M.VERBOSITY_QUIET
  2128. return
  2129. elseif option == '--error' or option == '-e' then
  2130. result['quitOnError'] = true
  2131. return
  2132. elseif option == '--failure' or option == '-f' then
  2133. result['quitOnFailure'] = true
  2134. return
  2135. elseif option == '--shuffle' or option == '-s' then
  2136. result['shuffle'] = true
  2137. return
  2138. elseif option == '--output' or option == '-o' then
  2139. state = SET_OUTPUT
  2140. return state
  2141. elseif option == '--name' or option == '-n' then
  2142. state = SET_FNAME
  2143. return state
  2144. elseif option == '--repeat' or option == '-r' then
  2145. state = SET_REPEAT
  2146. return state
  2147. elseif option == '--pattern' or option == '-p' then
  2148. state = SET_PATTERN
  2149. return state
  2150. elseif option == '--exclude' or option == '-x' then
  2151. state = SET_EXCLUDE
  2152. return state
  2153. end
  2154. error('Unknown option: '..option,3)
  2155. end
  2156. local function setArg( cmdArg, state )
  2157. if state == SET_OUTPUT then
  2158. result['output'] = cmdArg
  2159. return
  2160. elseif state == SET_FNAME then
  2161. result['fname'] = cmdArg
  2162. return
  2163. elseif state == SET_REPEAT then
  2164. result['exeRepeat'] = tonumber(cmdArg)
  2165. or error('Malformed -r argument: '..cmdArg)
  2166. return
  2167. elseif state == SET_PATTERN then
  2168. if result['pattern'] then
  2169. table.insert( result['pattern'], cmdArg )
  2170. else
  2171. result['pattern'] = { cmdArg }
  2172. end
  2173. return
  2174. elseif state == SET_EXCLUDE then
  2175. local notArg = '!'..cmdArg
  2176. if result['pattern'] then
  2177. table.insert( result['pattern'], notArg )
  2178. else
  2179. result['pattern'] = { notArg }
  2180. end
  2181. return
  2182. end
  2183. error('Unknown parse state: '.. state)
  2184. end
  2185. for i, cmdArg in ipairs(cmdLine) do
  2186. if state ~= nil then
  2187. setArg( cmdArg, state, result )
  2188. state = nil
  2189. else
  2190. if cmdArg:sub(1,1) == '-' then
  2191. state = parseOption( cmdArg )
  2192. else
  2193. if result['testNames'] then
  2194. table.insert( result['testNames'], cmdArg )
  2195. else
  2196. result['testNames'] = { cmdArg }
  2197. end
  2198. end
  2199. end
  2200. end
  2201. if result['help'] then
  2202. M.LuaUnit.help()
  2203. end
  2204. if result['version'] then
  2205. M.LuaUnit.version()
  2206. end
  2207. if state ~= nil then
  2208. error('Missing argument after '..cmdLine[ #cmdLine ],2 )
  2209. end
  2210. return result
  2211. end
  2212. function M.LuaUnit.help()
  2213. print(M.USAGE)
  2214. os.exit(0)
  2215. end
  2216. function M.LuaUnit.version()
  2217. print('LuaUnit v'..M.VERSION..' by Philippe Fremy <[email protected]>')
  2218. os.exit(0)
  2219. end
  2220. ----------------------------------------------------------------
  2221. -- class NodeStatus
  2222. ----------------------------------------------------------------
  2223. local NodeStatus = { __class__ = 'NodeStatus' } -- class
  2224. local NodeStatus_MT = { __index = NodeStatus } -- metatable
  2225. M.NodeStatus = NodeStatus
  2226. -- values of status
  2227. NodeStatus.SUCCESS = 'SUCCESS'
  2228. NodeStatus.SKIP = 'SKIP'
  2229. NodeStatus.FAIL = 'FAIL'
  2230. NodeStatus.ERROR = 'ERROR'
  2231. function NodeStatus.new( number, testName, className )
  2232. -- default constructor, test are PASS by default
  2233. local t = { number = number, testName = testName, className = className }
  2234. setmetatable( t, NodeStatus_MT )
  2235. t:success()
  2236. return t
  2237. end
  2238. function NodeStatus:success()
  2239. self.status = self.SUCCESS
  2240. -- useless because lua does this for us, but it helps me remembering the relevant field names
  2241. self.msg = nil
  2242. self.stackTrace = nil
  2243. end
  2244. function NodeStatus:skip(msg)
  2245. self.status = self.SKIP
  2246. self.msg = msg
  2247. self.stackTrace = nil
  2248. end
  2249. function NodeStatus:fail(msg, stackTrace)
  2250. self.status = self.FAIL
  2251. self.msg = msg
  2252. self.stackTrace = stackTrace
  2253. end
  2254. function NodeStatus:error(msg, stackTrace)
  2255. self.status = self.ERROR
  2256. self.msg = msg
  2257. self.stackTrace = stackTrace
  2258. end
  2259. function NodeStatus:isSuccess()
  2260. return self.status == NodeStatus.SUCCESS
  2261. end
  2262. function NodeStatus:isNotSuccess()
  2263. -- Return true if node is either failure or error or skip
  2264. return (self.status == NodeStatus.FAIL or self.status == NodeStatus.ERROR or self.status == NodeStatus.SKIP)
  2265. end
  2266. function NodeStatus:isSkipped()
  2267. return self.status == NodeStatus.SKIP
  2268. end
  2269. function NodeStatus:isFailure()
  2270. return self.status == NodeStatus.FAIL
  2271. end
  2272. function NodeStatus:isError()
  2273. return self.status == NodeStatus.ERROR
  2274. end
  2275. function NodeStatus:statusXML()
  2276. if self:isError() then
  2277. return table.concat(
  2278. {' <error type="', xmlEscape(self.msg), '">\n',
  2279. ' <![CDATA[', xmlCDataEscape(self.stackTrace),
  2280. ']]></error>\n'})
  2281. elseif self:isFailure() then
  2282. return table.concat(
  2283. {' <failure type="', xmlEscape(self.msg), '">\n',
  2284. ' <![CDATA[', xmlCDataEscape(self.stackTrace),
  2285. ']]></failure>\n'})
  2286. elseif self:isSkipped() then
  2287. return table.concat({' <skipped>', xmlEscape(self.msg),'</skipped>\n' } )
  2288. end
  2289. return ' <passed/>\n' -- (not XSD-compliant! normally shouldn't get here)
  2290. end
  2291. --------------[[ Output methods ]]-------------------------
  2292. local function conditional_plural(number, singular)
  2293. -- returns a grammatically well-formed string "%d <singular/plural>"
  2294. local suffix = ''
  2295. if number ~= 1 then -- use plural
  2296. suffix = (singular:sub(-2) == 'ss') and 'es' or 's'
  2297. end
  2298. return string.format('%d %s%s', number, singular, suffix)
  2299. end
  2300. function M.LuaUnit.statusLine(result)
  2301. -- return status line string according to results
  2302. local s = {
  2303. string.format('Ran %d tests in %0.3f seconds',
  2304. result.runCount, result.duration),
  2305. conditional_plural(result.successCount, 'success'),
  2306. }
  2307. if result.notSuccessCount > 0 then
  2308. if result.failureCount > 0 then
  2309. table.insert(s, conditional_plural(result.failureCount, 'failure'))
  2310. end
  2311. if result.errorCount > 0 then
  2312. table.insert(s, conditional_plural(result.errorCount, 'error'))
  2313. end
  2314. else
  2315. table.insert(s, '0 failures')
  2316. end
  2317. if result.skippedCount > 0 then
  2318. table.insert(s, string.format("%d skipped", result.skippedCount))
  2319. end
  2320. if result.nonSelectedCount > 0 then
  2321. table.insert(s, string.format("%d non-selected", result.nonSelectedCount))
  2322. end
  2323. return table.concat(s, ', ')
  2324. end
  2325. function M.LuaUnit:startSuite(selectedCount, nonSelectedCount)
  2326. self.result = {
  2327. selectedCount = selectedCount,
  2328. nonSelectedCount = nonSelectedCount,
  2329. successCount = 0,
  2330. runCount = 0,
  2331. currentTestNumber = 0,
  2332. currentClassName = "",
  2333. currentNode = nil,
  2334. suiteStarted = true,
  2335. startTime = os.clock(),
  2336. startDate = os.date(os.getenv('LUAUNIT_DATEFMT')),
  2337. startIsodate = os.date('%Y-%m-%dT%H:%M:%S'),
  2338. patternIncludeFilter = self.patternIncludeFilter,
  2339. -- list of test node status
  2340. allTests = {},
  2341. failedTests = {},
  2342. errorTests = {},
  2343. skippedTests = {},
  2344. failureCount = 0,
  2345. errorCount = 0,
  2346. notSuccessCount = 0,
  2347. skippedCount = 0,
  2348. }
  2349. self.outputType = self.outputType or TextOutput
  2350. self.output = self.outputType.new(self)
  2351. self.output:startSuite()
  2352. end
  2353. function M.LuaUnit:startClass( className )
  2354. self.result.currentClassName = className
  2355. self.output:startClass( className )
  2356. end
  2357. function M.LuaUnit:startTest( testName )
  2358. self.result.currentTestNumber = self.result.currentTestNumber + 1
  2359. self.result.runCount = self.result.runCount + 1
  2360. self.result.currentNode = NodeStatus.new(
  2361. self.result.currentTestNumber,
  2362. testName,
  2363. self.result.currentClassName
  2364. )
  2365. self.result.currentNode.startTime = os.clock()
  2366. table.insert( self.result.allTests, self.result.currentNode )
  2367. self.output:startTest( testName )
  2368. end
  2369. function M.LuaUnit:updateStatus( err )
  2370. -- "err" is expected to be a table / result from protectedCall()
  2371. if err.status == NodeStatus.SUCCESS then
  2372. return
  2373. end
  2374. local node = self.result.currentNode
  2375. --[[ As a first approach, we will report only one error or one failure for one test.
  2376. However, we can have the case where the test is in failure, and the teardown is in error.
  2377. In such case, it's a good idea to report both a failure and an error in the test suite. This is
  2378. what Python unittest does for example. However, it mixes up counts so need to be handled carefully: for
  2379. example, there could be more (failures + errors) count that tests. What happens to the current node ?
  2380. We will do this more intelligent version later.
  2381. ]]
  2382. -- if the node is already in failure/error, just don't report the new error (see above)
  2383. if node.status ~= NodeStatus.SUCCESS then
  2384. return
  2385. end
  2386. if err.status == NodeStatus.FAIL then
  2387. node:fail( err.msg, err.trace )
  2388. table.insert( self.result.failedTests, node )
  2389. elseif err.status == NodeStatus.ERROR then
  2390. node:error( err.msg, err.trace )
  2391. table.insert( self.result.errorTests, node )
  2392. elseif err.status == NodeStatus.SKIP then
  2393. node:skip( err.msg )
  2394. table.insert( self.result.skippedTests, node )
  2395. else
  2396. error('No such status: ' .. prettystr(err.status))
  2397. end
  2398. self.output:updateStatus( node )
  2399. end
  2400. function M.LuaUnit:endTest()
  2401. local node = self.result.currentNode
  2402. -- print( 'endTest() '..prettystr(node))
  2403. -- print( 'endTest() '..prettystr(node:isNotSuccess()))
  2404. node.duration = os.clock() - node.startTime
  2405. node.startTime = nil
  2406. self.output:endTest( node )
  2407. if node:isSuccess() then
  2408. self.result.successCount = self.result.successCount + 1
  2409. elseif node:isError() then
  2410. if self.quitOnError or self.quitOnFailure then
  2411. -- Runtime error - abort test execution as requested by
  2412. -- "--error" option. This is done by setting a special
  2413. -- flag that gets handled in runSuiteByInstances().
  2414. print("\nERROR during LuaUnit test execution:\n" .. node.msg)
  2415. self.result.aborted = true
  2416. end
  2417. elseif node:isFailure() then
  2418. if self.quitOnFailure then
  2419. -- Failure - abort test execution as requested by
  2420. -- "--failure" option. This is done by setting a special
  2421. -- flag that gets handled in runSuiteByInstances().
  2422. print("\nFailure during LuaUnit test execution:\n" .. node.msg)
  2423. self.result.aborted = true
  2424. end
  2425. elseif node:isSkipped() then
  2426. self.result.runCount = self.result.runCount - 1
  2427. else
  2428. error('No such node status: ' .. prettystr(node.status))
  2429. end
  2430. self.result.currentNode = nil
  2431. end
  2432. function M.LuaUnit:endClass()
  2433. self.output:endClass()
  2434. end
  2435. function M.LuaUnit:endSuite()
  2436. if self.result.suiteStarted == false then
  2437. error('LuaUnit:endSuite() -- suite was already ended' )
  2438. end
  2439. self.result.duration = os.clock()-self.result.startTime
  2440. self.result.suiteStarted = false
  2441. -- Expose test counts for outputter's endSuite(). This could be managed
  2442. -- internally instead by using the length of the lists of failed tests
  2443. -- but unit tests rely on these fields being present.
  2444. self.result.failureCount = #self.result.failedTests
  2445. self.result.errorCount = #self.result.errorTests
  2446. self.result.notSuccessCount = self.result.failureCount + self.result.errorCount
  2447. self.result.skippedCount = #self.result.skippedTests
  2448. self.output:endSuite()
  2449. end
  2450. function M.LuaUnit:setOutputType(outputType, fname)
  2451. -- Configures LuaUnit runner output
  2452. -- outputType is one of: NIL, TAP, JUNIT, TEXT
  2453. -- when outputType is junit, the additional argument fname is used to set the name of junit output file
  2454. -- for other formats, fname is ignored
  2455. if outputType:upper() == "NIL" then
  2456. self.outputType = NilOutput
  2457. return
  2458. end
  2459. if outputType:upper() == "TAP" then
  2460. self.outputType = TapOutput
  2461. return
  2462. end
  2463. if outputType:upper() == "JUNIT" then
  2464. self.outputType = JUnitOutput
  2465. if fname then
  2466. self.fname = fname
  2467. end
  2468. return
  2469. end
  2470. if outputType:upper() == "TEXT" then
  2471. self.outputType = TextOutput
  2472. return
  2473. end
  2474. error( 'No such format: '..outputType,2)
  2475. end
  2476. --------------[[ Runner ]]-----------------
  2477. function M.LuaUnit:protectedCall(classInstance, methodInstance, prettyFuncName)
  2478. -- if classInstance is nil, this is just a function call
  2479. -- else, it's method of a class being called.
  2480. local function err_handler(e)
  2481. -- transform error into a table, adding the traceback information
  2482. return {
  2483. status = NodeStatus.ERROR,
  2484. msg = e,
  2485. trace = string.sub(debug.traceback("", 3), 2)
  2486. }
  2487. end
  2488. local ok, err
  2489. if classInstance then
  2490. -- stupid Lua < 5.2 does not allow xpcall with arguments so let's use a workaround
  2491. ok, err = xpcall( function () methodInstance(classInstance) end, err_handler )
  2492. else
  2493. ok, err = xpcall( function () methodInstance() end, err_handler )
  2494. end
  2495. if ok then
  2496. return {status = NodeStatus.SUCCESS}
  2497. end
  2498. local iter_msg
  2499. iter_msg = self.exeRepeat and 'iteration '..self.currentCount
  2500. err.msg, err.status = M.adjust_err_msg_with_iter( err.msg, iter_msg )
  2501. if err.status == NodeStatus.SUCCESS or err.status == NodeStatus.SKIP then
  2502. err.trace = nil
  2503. return err
  2504. end
  2505. -- reformat / improve the stack trace
  2506. if prettyFuncName then -- we do have the real method name
  2507. err.trace = err.trace:gsub("in (%a+) 'methodInstance'", "in %1 '"..prettyFuncName.."'")
  2508. end
  2509. if STRIP_LUAUNIT_FROM_STACKTRACE then
  2510. err.trace = stripLuaunitTrace(err.trace)
  2511. end
  2512. return err -- return the error "object" (table)
  2513. end
  2514. function M.LuaUnit:execOneFunction(className, methodName, classInstance, methodInstance)
  2515. -- When executing a test function, className and classInstance must be nil
  2516. -- When executing a class method, all parameters must be set
  2517. if type(methodInstance) ~= 'function' then
  2518. error( tostring(methodName)..' must be a function, not '..type(methodInstance))
  2519. end
  2520. local prettyFuncName
  2521. if className == nil then
  2522. className = '[TestFunctions]'
  2523. prettyFuncName = methodName
  2524. else
  2525. prettyFuncName = className..'.'..methodName
  2526. end
  2527. if self.lastClassName ~= className then
  2528. if self.lastClassName ~= nil then
  2529. self:endClass()
  2530. end
  2531. self:startClass( className )
  2532. self.lastClassName = className
  2533. end
  2534. self:startTest(prettyFuncName)
  2535. local node = self.result.currentNode
  2536. for iter_n = 1, self.exeRepeat or 1 do
  2537. if node:isNotSuccess() then
  2538. break
  2539. end
  2540. self.currentCount = iter_n
  2541. -- run setUp first (if any)
  2542. if classInstance then
  2543. local func = self.asFunction( classInstance.setUp ) or
  2544. self.asFunction( classInstance.Setup ) or
  2545. self.asFunction( classInstance.setup ) or
  2546. self.asFunction( classInstance.SetUp )
  2547. if func then
  2548. self:updateStatus(self:protectedCall(classInstance, func, className..'.setUp'))
  2549. end
  2550. end
  2551. -- run testMethod()
  2552. if node:isSuccess() then
  2553. self:updateStatus(self:protectedCall(classInstance, methodInstance, prettyFuncName))
  2554. end
  2555. -- lastly, run tearDown (if any)
  2556. if classInstance then
  2557. local func = self.asFunction( classInstance.tearDown ) or
  2558. self.asFunction( classInstance.TearDown ) or
  2559. self.asFunction( classInstance.teardown ) or
  2560. self.asFunction( classInstance.Teardown )
  2561. if func then
  2562. self:updateStatus(self:protectedCall(classInstance, func, className..'.tearDown'))
  2563. end
  2564. end
  2565. end
  2566. self:endTest()
  2567. end
  2568. function M.LuaUnit.expandOneClass( result, className, classInstance )
  2569. --[[
  2570. Input: a list of { name, instance }, a class name, a class instance
  2571. Ouptut: modify result to add all test method instance in the form:
  2572. { className.methodName, classInstance }
  2573. ]]
  2574. for methodName, methodInstance in sortedPairs(classInstance) do
  2575. if M.LuaUnit.asFunction(methodInstance) and M.LuaUnit.isMethodTestName( methodName ) then
  2576. table.insert( result, { className..'.'..methodName, classInstance } )
  2577. end
  2578. end
  2579. end
  2580. function M.LuaUnit.expandClasses( listOfNameAndInst )
  2581. --[[
  2582. -- expand all classes (provided as {className, classInstance}) to a list of {className.methodName, classInstance}
  2583. -- functions and methods remain untouched
  2584. Input: a list of { name, instance }
  2585. Output:
  2586. * { function name, function instance } : do nothing
  2587. * { class.method name, class instance }: do nothing
  2588. * { class name, class instance } : add all method names in the form of (className.methodName, classInstance)
  2589. ]]
  2590. local result = {}
  2591. for i,v in ipairs( listOfNameAndInst ) do
  2592. local name, instance = v[1], v[2]
  2593. if M.LuaUnit.asFunction(instance) then
  2594. table.insert( result, { name, instance } )
  2595. else
  2596. if type(instance) ~= 'table' then
  2597. error( 'Instance must be a table or a function, not a '..type(instance)..' with value '..prettystr(instance))
  2598. end
  2599. local className, methodName = M.LuaUnit.splitClassMethod( name )
  2600. if className then
  2601. local methodInstance = instance[methodName]
  2602. if methodInstance == nil then
  2603. error( "Could not find method in class "..tostring(className).." for method "..tostring(methodName) )
  2604. end
  2605. table.insert( result, { name, instance } )
  2606. else
  2607. M.LuaUnit.expandOneClass( result, name, instance )
  2608. end
  2609. end
  2610. end
  2611. return result
  2612. end
  2613. function M.LuaUnit.applyPatternFilter( patternIncFilter, listOfNameAndInst )
  2614. local included, excluded = {}, {}
  2615. for i, v in ipairs( listOfNameAndInst ) do
  2616. -- local name, instance = v[1], v[2]
  2617. if patternFilter( patternIncFilter, v[1] ) then
  2618. table.insert( included, v )
  2619. else
  2620. table.insert( excluded, v )
  2621. end
  2622. end
  2623. return included, excluded
  2624. end
  2625. function M.LuaUnit:runSuiteByInstances( listOfNameAndInst )
  2626. --[[ Run an explicit list of tests. Each item of the list must be one of:
  2627. * { function name, function instance }
  2628. * { class name, class instance }
  2629. * { class.method name, class instance }
  2630. ]]
  2631. local expandedList = self.expandClasses( listOfNameAndInst )
  2632. if self.shuffle then
  2633. randomizeTable( expandedList )
  2634. end
  2635. local filteredList, filteredOutList = self.applyPatternFilter(
  2636. self.patternIncludeFilter, expandedList )
  2637. self:startSuite( #filteredList, #filteredOutList )
  2638. for i,v in ipairs( filteredList ) do
  2639. local name, instance = v[1], v[2]
  2640. if M.LuaUnit.asFunction(instance) then
  2641. self:execOneFunction( nil, name, nil, instance )
  2642. else
  2643. -- expandClasses() should have already taken care of sanitizing the input
  2644. assert( type(instance) == 'table' )
  2645. local className, methodName = M.LuaUnit.splitClassMethod( name )
  2646. assert( className ~= nil )
  2647. local methodInstance = instance[methodName]
  2648. assert(methodInstance ~= nil)
  2649. self:execOneFunction( className, methodName, instance, methodInstance )
  2650. end
  2651. if self.result.aborted then
  2652. break -- "--error" or "--failure" option triggered
  2653. end
  2654. end
  2655. if self.lastClassName ~= nil then
  2656. self:endClass()
  2657. end
  2658. self:endSuite()
  2659. if self.result.aborted then
  2660. print("LuaUnit ABORTED (as requested by --error or --failure option)")
  2661. os.exit(-2)
  2662. end
  2663. end
  2664. function M.LuaUnit:runSuiteByNames( listOfName )
  2665. --[[ Run LuaUnit with a list of generic names, coming either from command-line or from global
  2666. namespace analysis. Convert the list into a list of (name, valid instances (table or function))
  2667. and calls runSuiteByInstances.
  2668. ]]
  2669. local instanceName, instance
  2670. local listOfNameAndInst = {}
  2671. for i,name in ipairs( listOfName ) do
  2672. local className, methodName = M.LuaUnit.splitClassMethod( name )
  2673. if className then
  2674. instanceName = className
  2675. instance = _G[instanceName]
  2676. if instance == nil then
  2677. error( "No such name in global space: "..instanceName )
  2678. end
  2679. if type(instance) ~= 'table' then
  2680. error( 'Instance of '..instanceName..' must be a table, not '..type(instance))
  2681. end
  2682. local methodInstance = instance[methodName]
  2683. if methodInstance == nil then
  2684. error( "Could not find method in class "..tostring(className).." for method "..tostring(methodName) )
  2685. end
  2686. else
  2687. -- for functions and classes
  2688. instanceName = name
  2689. instance = _G[instanceName]
  2690. end
  2691. if instance == nil then
  2692. error( "No such name in global space: "..instanceName )
  2693. end
  2694. if (type(instance) ~= 'table' and type(instance) ~= 'function') then
  2695. error( 'Name must match a function or a table: '..instanceName )
  2696. end
  2697. table.insert( listOfNameAndInst, { name, instance } )
  2698. end
  2699. self:runSuiteByInstances( listOfNameAndInst )
  2700. end
  2701. function M.LuaUnit.run(...)
  2702. -- Run some specific test classes.
  2703. -- If no arguments are passed, run the class names specified on the
  2704. -- command line. If no class name is specified on the command line
  2705. -- run all classes whose name starts with 'Test'
  2706. --
  2707. -- If arguments are passed, they must be strings of the class names
  2708. -- that you want to run or generic command line arguments (-o, -p, -v, ...)
  2709. local runner = M.LuaUnit.new()
  2710. return runner:runSuite(...)
  2711. end
  2712. function M.LuaUnit:runSuite( ... )
  2713. local args = {...}
  2714. if type(args[1]) == 'table' and args[1].__class__ == 'LuaUnit' then
  2715. -- run was called with the syntax M.LuaUnit:runSuite()
  2716. -- we support both M.LuaUnit.run() and M.LuaUnit:run()
  2717. -- strip out the first argument
  2718. table.remove(args,1)
  2719. end
  2720. if #args == 0 then
  2721. args = cmdline_argv
  2722. end
  2723. local options = pcall_or_abort( M.LuaUnit.parseCmdLine, args )
  2724. -- We expect these option fields to be either `nil` or contain
  2725. -- valid values, so it's safe to always copy them directly.
  2726. self.verbosity = options.verbosity
  2727. self.quitOnError = options.quitOnError
  2728. self.quitOnFailure = options.quitOnFailure
  2729. self.exeRepeat = options.exeRepeat
  2730. self.patternIncludeFilter = options.pattern
  2731. self.shuffle = options.shuffle
  2732. if options.output then
  2733. if options.output:lower() == 'junit' and options.fname == nil then
  2734. print('With junit output, a filename must be supplied with -n or --name')
  2735. os.exit(-1)
  2736. end
  2737. pcall_or_abort(self.setOutputType, self, options.output, options.fname)
  2738. end
  2739. self:runSuiteByNames( options.testNames or M.LuaUnit.collectTests() )
  2740. return self.result.notSuccessCount
  2741. end
  2742. -- class LuaUnit
  2743. -- For compatbility with LuaUnit v2
  2744. M.run = M.LuaUnit.run
  2745. M.Run = M.LuaUnit.run
  2746. function M:setVerbosity( verbosity )
  2747. M.LuaUnit.verbosity = verbosity
  2748. end
  2749. M.set_verbosity = M.setVerbosity
  2750. M.SetVerbosity = M.setVerbosity
  2751. return M