pax_global_header00006660000000000000000000000064140177352320014516gustar00rootroot0000000000000052 comment=ddee11c5069c699f4fc6e6c0cea1f1c11dddc373 luaunit-LUAUNIT_V3_4/000077500000000000000000000000001401773523200144555ustar00rootroot00000000000000luaunit-LUAUNIT_V3_4/.appveyor/000077500000000000000000000000001401773523200164005ustar00rootroot00000000000000luaunit-LUAUNIT_V3_4/.appveyor/install-lua.cmd000077500000000000000000000077431401773523200213300ustar00rootroot00000000000000REM This is a batch file to help with setting up the desired Lua environment. REM It is intended to be run as "install" step from within AppVeyor. REM version numbers and file names for binaries from http://sf.net/p/luabinaries/ set VER_51=5.1.5 set VER_52=5.2.4 set VER_53=5.3.3 set VER_54=5.4.0 set ZIP_51=lua-%VER_51%_Win32_bin.zip set ZIP_52=lua-%VER_52%_Win32_bin.zip set ZIP_53=lua-%VER_53%_Win32_bin.zip set ZIP_54=lua-%VER_54%_Win32_bin.zip set ZIP_51_64=lua-%VER_51%_Win64_bin.zip set ZIP_52_64=lua-%VER_52%_Win64_bin.zip set ZIP_53_64=lua-%VER_53%_Win64_bin.zip set ZIP_54_64=lua-%VER_54%_Win64_bin.zip set ZIP_LUAJIT20=LuaJIT-2.0.5 set ZIP_LUAJIT21=LuaJIT-2.1.0-beta3 goto %LUAENV% goto error :lua51 set PRETTY_VERSION='Lua 5.1' set LUA_BIN_DIR=lua51 set LUA_EXE=lua51\lua5.1.exe set DL_URL=http://sourceforge.net/projects/luabinaries/files/%VER_51%/Tools%%20Executables/%ZIP_51%/download set DL_ZIP=%ZIP_51% goto download_and_intall_lua :lua51_64 set PRETTY_VERSION='Lua 5.1 - 64 bits' set LUA_BIN_DIR=lua51-64 set LUA_EXE=lua51-64\lua5.1.exe set DL_URL=http://sourceforge.net/projects/luabinaries/files/%VER_51%/Tools%%20Executables/%ZIP_51_64%/download set DL_ZIP=%ZIP_51_64% goto download_and_intall_lua :lua52 set PRETTY_VERSION='Lua 5.2' set LUA_BIN_DIR=lua52 set LUA_EXE=lua52\lua52.exe set DL_URL=http://sourceforge.net/projects/luabinaries/files/%VER_52%/Tools%%20Executables/%ZIP_52%/download set DL_ZIP=%ZIP_52% goto download_and_intall_lua :lua52_64 set PRETTY_VERSION='Lua 5.2 - 64 bits' set LUA_BIN_DIR=lua52-64 set LUA_EXE=lua52-64\lua52.exe set DL_URL=http://sourceforge.net/projects/luabinaries/files/%VER_52%/Tools%%20Executables/%ZIP_52_64%/download set DL_ZIP=%ZIP_52_64% goto download_and_intall_lua :lua53 set PRETTY_VERSION='Lua 5.3' set LUA_BIN_DIR=lua53 set LUA_EXE=lua53\lua53.exe set DL_URL=http://sourceforge.net/projects/luabinaries/files/%VER_53%/Tools%%20Executables/%ZIP_53%/download set DL_ZIP=%ZIP_53% goto download_and_intall_lua :lua53_64 set PRETTY_VERSION='Lua 5.3 - 64 bits' set LUA_BIN_DIR=lua53-64 set LUA_EXE=lua53-64\lua53.exe set DL_URL=http://sourceforge.net/projects/luabinaries/files/%VER_53%/Tools%%20Executables/%ZIP_53_64%/download set DL_ZIP=%ZIP_53_64% goto download_and_intall_lua :lua54 set PRETTY_VERSION='Lua 5.4' set LUA_BIN_DIR=lua54 set LUA_EXE=lua54\lua54.exe set DL_URL=http://sourceforge.net/projects/luabinaries/files/%VER_54%/Tools%%20Executables/%ZIP_54%/download set DL_ZIP=%ZIP_54% goto download_and_intall_lua :lua54_64 set PRETTY_VERSION='Lua 5.4 - 64 bits' set LUA_BIN_DIR=lua54-64 set LUA_EXE=lua54-64\lua54.exe set DL_URL=http://sourceforge.net/projects/luabinaries/files/%VER_54%/Tools%%20Executables/%ZIP_54_64%/download set DL_ZIP=%ZIP_54_64% goto download_and_intall_lua :luajit20 set PRETTY_VERSION='LuaJIT 2.0' set LUA_BIN_DIR=luajit20 set LUA_EXE=luajit20\luajit.exe set DL_ZIP=LuaJIT-2.0.5 set DL_URL=http://luajit.org/download/%DL_ZIP%.zip goto download_and_intall_luajit :luajit21 set PRETTY_VERSION='LuaJIT 2.1' set LUA_BIN_DIR=luajit21 set LUA_EXE=luajit21\luajit.exe set DL_ZIP=LuaJIT-2.1.0-beta3 set DL_URL=http://luajit.org/download/%DL_ZIP%.zip goto download_and_intall_luajit :download_and_intall_lua echo Setting up %PRETTY_VERSION% ... if NOT EXIST %LUA_EXE% ( @echo on echo Fetching %PRETTY_VERSION% from internet curl -fLsS -o %DL_ZIP% %DL_URL% unzip -d %LUA_BIN_DIR% %DL_ZIP% ) else ( echo Using cached version of %PRETTY_VERSION ) set LUA=%LUA_EXE% goto :eof :download_and_intall_luajit echo download and install luajit if NOT EXIST %LUA_EXE% ( REM We need to put the compiling logic into a separate script REM else we hit the limitation on the length of the path variable REM which somehow stops the script call %~dp0install-luajit.cmd ) else ( echo Using cached version of %PRETTY_VERSION% ) set LUA=%LUA_EXE% goto :eof :error echo Do not know how to install %LUAENV% luaunit-LUAUNIT_V3_4/.appveyor/install-luajit.cmd000077500000000000000000000013141401773523200220230ustar00rootroot00000000000000REM Do a minimalistic build of LuaJIT using the MinGW compiler set PATH=C:\MinGW\bin;%PATH% echo Downloading %PRETTY_VERSION% ... curl -fLsS -o %DL_ZIP%.zip %DL_URL% echo Unzipping %DL_ZIP% unzip -q %DL_ZIP% REM tweak Makefile for a static LuaJIT build (Windows defaults to "dynamic" otherwise) sed -i "s/BUILDMODE=.*mixed/BUILDMODE=static/" %DL_ZIP%\src\Makefile mingw32-make TARGET_SYS=Windows -C %DL_ZIP%\src echo Installing %PRETTY_VERSION% ... REM copy luajit.exe to project dir mkdir %APPVEYOR_BUILD_FOLDER%\%LUA_BIN_DIR% copy %DL_ZIP%\src\luajit.exe %APPVEYOR_BUILD_FOLDER%\%LUA_BIN_DIR%\ REM clean up (remove source folders and archive) rm -rf %DL_ZIP%/* rm -f %DL_ZIP%.zip luaunit-LUAUNIT_V3_4/.gitignore000066400000000000000000000014461401773523200164520ustar00rootroot00000000000000 # ignore temp files *.sw? *.bak *.pyc #ignore thumbnails created by windows Thumbs.db #Ignore files build by Visual Studio *.obj *.exe *.pdb *.user *.aps *.pch *.vspscc *_i.c *_p.c *.ncb *.suo *.tlb *.tlh *.cache *.ilk *.log [Bb]in [Dd]ebug*/ *.lib *.sbr obj/ [Rr]elease*/ _ReSharper*/ # LuaCov output (stats and report) luacov.*.out # LuaUnit ignores [Tt]est[Rr]esult* *.sublime-project *.lsln *.sublime-workspace doc/_build/ doc/html/ junit_stdout.txt output_junit.xml junit_stdout?.txt output_junit?.xml test/example*.txt test/example*.xml test/testWithXml*.xml test/testWithXml*.txt test/unitTests*.xml test/unitTests*.txt test/legacyExample.txt test/legacyExampleError.txt test/compat_luaunit_v2x.txt test/errFailPass*.txt test/errFailPass*.xml test/some_lists_comparisons.txt *.diff #Emacs *~ luaunit-LUAUNIT_V3_4/.luacheckrc000066400000000000000000000014401401773523200165610ustar00rootroot00000000000000--[[ Luacheck configuration (see http://luacheck.readthedocs.io/en/stable/config.html) Thanks to Peter Melnichenko for providing an example file for LuaUnit. ]] only = {"1"} -- limit checks to the use of global variables std = "max" self = false ignore = {"[Tt]est[%w_]+"} files = { ["luaunit.lua"] = { globals = {"EXPORT_ASSERT_TO_GLOBALS", "LuaUnit", "os"}, }, ["test/compat_luaunit_v2x.lua"] = { ignore = {"EXPORT_ASSERT_TO_GLOBALS", "assert[%w_]+", "v", "y"} }, ["test/legacy_example_with_luaunit.lua"] = { ignore = {"LuaUnit", "EXPORT_ASSERT_TO_GLOBALS", "assertEquals", "assertNotEquals", "assertTrue", "assertFalse"} }, ["test/test_luaunit.lua"] = { ignore = {"TestMock", "TestLuaUnit%a+", "MyTest%w+", "v", "y" } } } luaunit-LUAUNIT_V3_4/.travis.yml000066400000000000000000000020501401773523200165630ustar00rootroot00000000000000language: c sudo: false os: linux env: matrix: - LUA=lua5.1 LUANUMBER=double - LUA=lua5.1 LUANUMBER=float - LUA=lua5.2 LUANUMBER=double - LUA=lua5.2 LUANUMBER=float - LUA=lua5.3 LUANUMBER=double - LUA=lua5.3 LUANUMBER=float - LUA=lua5.4 LUANUMBER=double - LUA=luajit2.0 - LUA=luajit2.1 matrix: # test Mac OS X, but limit it to a single build include: - os: osx env: LUA=lua5.1 LUANUMBER=double allow_failures: - os: osx env: LUA=lua5.1 LUANUMBER=double before_install: - source .travis/setup_lua.sh - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install -y libxml2-utils; fi cache: directories: - $TRAVIS_BUILD_DIR/install script: - lua -v -lluacov run_unit_tests.lua --shuffle - lua run_functional_tests.lua --coverage - luacheck example_with_luaunit.lua luaunit.lua run_unit_tests.lua run_functional_tests.lua test/ after_success: - luacov-coveralls -v --include %./luaunit.lua notifications: email: on_success: change on_failure: always luaunit-LUAUNIT_V3_4/.travis/000077500000000000000000000000001401773523200160435ustar00rootroot00000000000000luaunit-LUAUNIT_V3_4/.travis/emulate_travis.sh000077500000000000000000000004121401773523200214230ustar00rootroot00000000000000echo == Travis emulation mode == rm -rf $HOME/.lua export LUA=lua5.4 # export LUA=luajit2.1 export LUANUMBER=double export TRAVIS_BUILD_DIR=`pwd` export TRAVIS_OS_NAME=linux # erase previous builds rm -rf $TRAVIS_BUILD_DIR/install bash ../.travis/setup_lua.sh luaunit-LUAUNIT_V3_4/.travis/setup_lua.sh000066400000000000000000000150621401773523200204040ustar00rootroot00000000000000#! /bin/bash # A script for setting up environment for travis-ci testing. # Sets up Lua and Luarocks. # LUA must be "lua5.1", "lua5.2" or "luajit". # luajit2.0 - master v2.0 # luajit2.1 - master v2.1 ### # This script will create the following symbolic links, to refer to the installed lua: # $HOME/.lua/lua # $HOME/.lua/luajit # $HOME/.lua/luac # $HOME/.lua/luarocks # # Building of the targeted lua version is done in: # $HOME/install/ # # Lua rocks in installed in # $HOME/install/luacoks set -eufox pipefail LUAROCKS_VERSION=3.4.0 LUAROCKS_URL=http://luarocks.org/releases/luarocks-3.4.0.tar.gz # Note: TRAVIS_BUILD_DIR=/home/travis/build/bluebird75/luaunit/ LUA_HOME_DIR=$TRAVIS_BUILD_DIR/install/$LUA LUAROCK_HOME_DIR=$TRAVIS_BUILD_DIR/install/luarocks # setup a wide path export PATH=$HOME/.lua:${LUAROCK_HOME_DIR}/bin:${PATH} case $LUA in "lua5.1") LUA_SOURCE_URL=http://www.lua.org/ftp/lua-5.1.5.tar.gz LUA_BUILD_DIR=lua-5.1.5 LUAJIT="no" LUAROCKS_CONFIGURE_ARGS=--with-lua="$LUA_HOME_DIR" LUAROCKS_CONFIGURE_ARGS2= ;; "lua5.2") LUA_SOURCE_URL=http://www.lua.org/ftp/lua-5.2.4.tar.gz LUA_BUILD_DIR=lua-5.2.4 LUAJIT="no" LUAROCKS_CONFIGURE_ARGS=--with-lua="$LUA_HOME_DIR" LUAROCKS_CONFIGURE_ARGS2= ;; "lua5.3") LUA_SOURCE_URL=http://www.lua.org/ftp/lua-5.3.3.tar.gz LUA_BUILD_DIR=lua-5.3.3 LUAJIT="no" LUAROCKS_CONFIGURE_ARGS=--with-lua="$LUA_HOME_DIR" LUAROCKS_CONFIGURE_ARGS2= ;; "lua5.4") LUA_SOURCE_URL=http://www.lua.org/ftp/lua-5.4.0.tar.gz LUA_BUILD_DIR=lua-5.4.0 LUAJIT="no" LUAROCKS_CONFIGURE_ARGS=--with-lua="$LUA_HOME_DIR" LUAROCKS_CONFIGURE_ARGS2= ;; "luajit2.0") LUA_SOURCE_URL=https://luajit.org/download/LuaJIT-2.0.5.tar.gz LUA_BUILD_DIR=LuaJIT-2.0.5 LUAJIT="yes" LUAROCKS_CONFIGURE_ARGS=--lua-suffix=jit LUAROCKS_CONFIGURE_ARGS2=--with-lua-include="$LUA_HOME_DIR/include/luajit-2.0" ;; "luajit2.1") LUA_SOURCE_URL=https://luajit.org/download/LuaJIT-2.1.0-beta3.tar.gz LUA_BUILD_DIR=LuaJIT-2.1.0-beta3 LUAJIT="yes" LUAROCKS_CONFIGURE_ARGS=--lua-suffix=jit LUAROCKS_CONFIGURE_ARGS2=--with-lua-include="$LUA_HOME_DIR/include/luajit-2.1" ;; esac # Set the variable PLATFORM to one of the following: # - linux # - macosx if [ -z "${PLATFORM:-}" ]; then PLATFORM=$TRAVIS_OS_NAME; fi if [ "$PLATFORM" == "osx" ]; then PLATFORM="macosx"; fi # Allow running not on travis if [ -z "$PLATFORM" ]; then if [ "$(uname)" == "Linux" ]; then PLATFORM="linux"; else PLATFORM="macosx"; fi; fi mkdir $HOME/.lua if [ -e $LUA_HOME_DIR ] then echo ">> Using cached version of $LUA_HOME_DIR and luarocks" echo "Content:" find $LUA_HOME_DIR -print find $LUAROCK_HOME_DIR -print # remove links to other version of lua and luarocks rm -f $HOME/.lua/lua rm -f $HOME/.lua/luajit rm -f $HOME/.lua/luac rm -f $HOME/.lua/luarocks # recreating the links if [ "$LUAJIT" == "yes" ]; then ln -s $LUA_HOME_DIR/bin/luajit $HOME/.lua/luajit ln -s $LUA_HOME_DIR/bin/luajit $HOME/.lua/lua else ln -s $LUA_HOME_DIR/bin/lua $HOME/.lua/lua ln -s $LUA_HOME_DIR/bin/luac $HOME/.lua/luac fi ln -s $LUAROCK_HOME_DIR/bin/luarocks $HOME/.lua/luarocks # installation is ok ? lua -v luarocks --version else # -e $LUA_HOME_DIR echo ">> Compiling lua into $LUA_HOME_DIR" mkdir -p "$LUA_HOME_DIR" echo ">> Downloading $LUA from $LUA_SOURCE_URL" curl $LUA_SOURCE_URL | tar xz cd $LUA_BUILD_DIR if [ "$LUAJIT" == "yes" ]; then if [ "$LUA" == "luajit2.1" ]; then # force the INSTALL_TNAME to be luajit perl -i -pe 's/INSTALL_TNAME=.+/INSTALL_TNAME= luajit/' Makefile fi echo ">> Compiling LuaJIT" make && make install PREFIX="$LUA_HOME_DIR" ln -s $LUA_HOME_DIR/bin/luajit $HOME/.lua/luajit ln -s $LUA_HOME_DIR/bin/luajit $HOME/.lua/lua else # $LUAJIT == "yes" # adjust numerical precision if requested with LUANUMBER=float if [ "$LUANUMBER" == "float" ]; then if [ "$LUA" == "lua5.3" -o "$LUA" == "lua5.4" ]; then # for Lua 5.3 we can simply adjust the default float type perl -i -pe "s/#define LUA_FLOAT_TYPE\tLUA_FLOAT_DOUBLE/#define LUA_FLOAT_TYPE\tLUA_FLOAT_FLOAT/" src/luaconf.h else # modify the basic LUA_NUMBER type perl -i -pe 's/#define LUA_NUMBER_DOUBLE/#define LUA_NUMBER_FLOAT/' src/luaconf.h perl -i -pe "s/LUA_NUMBER\tdouble/LUA_NUMBER\tfloat/" src/luaconf.h #perl -i -pe "s/LUAI_UACNUMBER\tdouble/LUAI_UACNUMBER\tfloat/" src/luaconf.h # adjust LUA_NUMBER_SCAN (input format) perl -i -pe 's/"%lf"/"%f"/' src/luaconf.h # adjust LUA_NUMBER_FMT (output format) perl -i -pe 's/"%\.14g"/"%\.7g"/' src/luaconf.h # adjust lua_str2number conversion perl -i -pe 's/strtod\(/strtof\(/' src/luaconf.h # this one is specific to the l_mathop(x) macro of Lua 5.2 perl -i -pe 's/\t\t\(x\)/\t\t\(x##f\)/' src/luaconf.h fi fi # Build Lua without backwards compatibility for testing perl -i -pe 's/-DLUA_COMPAT_(ALL|5_2)//' src/Makefile echo ">> Compiling $LUA" make $PLATFORM make INSTALL_TOP="$LUA_HOME_DIR" install ln -s $LUA_HOME_DIR/bin/lua $HOME/.lua/lua ln -s $LUA_HOME_DIR/bin/luac $HOME/.lua/luac fi # $LUAJIT == "yes" # cleanup LUA build dir rm -rf $LUA_BUILD_DIR # lua is OK ? echo ">> lua -v" lua -v echo ">> Downloading luarocks" curl --location $LUAROCKS_URL | tar xz cd luarocks-$LUAROCKS_VERSION echo ">> Compiling luarocks" ./configure $LUAROCKS_CONFIGURE_ARGS $LUAROCKS_CONFIGURE_ARGS2 --prefix="$LUAROCK_HOME_DIR"; make build && make install # cleanup luarocks rm -rf luarocks-$LUAROCKS_VERSION ln -s $LUAROCK_HOME_DIR/bin/luarocks $HOME/.lua/luarocks echo ">> luarocks --version" luarocks --version echo ">> luarocks install luacheck" luarocks install luacheck echo ">> luarocks install luacov" luarocks install luacov echo ">> luarocks install luacov-coversall" luarocks install luacov-coveralls fi # -e $LUA_HOME_DIR echo "Setting lua path to luarock user tree " eval $(luarocks path --bin) lua -l luacov -v cd $TRAVIS_BUILD_DIR # To make travis happy, we must no fail on unassigned variables so reset this option to its default value set +u luaunit-LUAUNIT_V3_4/LICENSE.txt000077500000000000000000000025371401773523200163120ustar00rootroot00000000000000This software is distributed under the BSD License. Copyright (c) 2005-2018, Philippe Fremy All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. luaunit-LUAUNIT_V3_4/README.md000066400000000000000000000325641401773523200157460ustar00rootroot00000000000000[![Build status](https://ci.appveyor.com/api/projects/status/us6uh4e5q597jj54?svg=true&passingText=Windows%20Build%20passing&failingText=Windows%20Build%20failed)](https://ci.appveyor.com/project/bluebird75/luaunit) [![Build Status](https://travis-ci.org/bluebird75/luaunit.svg?branch=master)](https://travis-ci.org/bluebird75/luaunit) [![Documentation Status](https://readthedocs.org/projects/luaunit/badge/?version=latest)](https://readthedocs.org/projects/luaunit/?badge=latest) [![Coverage Status](https://coveralls.io/repos/github/bluebird75/luaunit/badge.svg?branch=master)](https://coveralls.io/github/bluebird75/luaunit?branch=master) [![Downloads](https://img.shields.io/badge/downloads-235k-brightgreen.svg)](https://luarocks.org/modules/bluebird75/luaunit) [![License](http://img.shields.io/badge/License-BSD-green.svg)](LICENSE.txt) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/2756/badge)](https://bestpractices.coreinfrastructure.org/projects/2756) ## LuaUnit by Philippe Fremy LuaUnit is a popular unit-testing framework for Lua, with an interface typical of xUnit libraries (Python unittest, Junit, NUnit, ...). It supports several output formats (Text, TAP, JUnit, ...) to be used directly or work with Continuous Integration platforms (Jenkins, Hudson, ...). LuaUnit may be installed as a [rock](https://luarocks.org/modules/bluebird75/luaunit) or directly added to your project. For simplicity, LuaUnit is contained into a single-file and has no external dependency. Tutorial and reference documentation is available on [read-the-docs](http://luaunit.readthedocs.org/en/latest/) LuaUnit may also be used as an assertion library, to validate assertions inside a running program. In addition, it provides a pretty stringifier which converts any type into a nicely formatted string (including complex nested or recursive tables). ## More details LuaUnit provides a wide range of assertions and goes into great efforts to provide the most useful output. For example since version 3.3 , comparing lists will provide a detailed difference analysis: -- lua test code. Can you spot the difference ? function TestListCompare:test1() local A = { 121221, 122211, 121221, 122211, 121221, 122212, 121212, 122112, 122121, 121212, 122121 } local B = { 121221, 122211, 121221, 122211, 121221, 122212, 121212, 122112, 121221, 121212, 122121 } lu.assertEquals( A, B ) end $ lua test_some_lists_comparison.lua TestListCompare.test1 ... FAIL test/some_lists_comparisons.lua:22: expected: List difference analysis: * lists A (actual) and B (expected) have the same size * lists A and B start differing at index 9 * lists A and B are equal again from index 10 * Common parts: = A[1], B[1]: 121221 = A[2], B[2]: 122211 = A[3], B[3]: 121221 = A[4], B[4]: 122211 = A[5], B[5]: 121221 = A[6], B[6]: 122212 = A[7], B[7]: 121212 = A[8], B[8]: 122112 * Differing parts: - A[9]: 122121 + B[9]: 121221 * Common parts at the end of the lists = A[10], B[10]: 121212 = A[11], B[11]: 122121 The command-line options provide a flexible interface to select tests by name or patterns, control output format, set verbosity and more. See [the documentation](http://luaunit.readthedocs.io/en/latest/#command-line-options) . LuaUnit also provides some dedicated support to scientific computing. See [the documentation](http://luaunit.readthedocs.io/en/latest/#scientific-computing-and-luaunit) . LuaUnit is very well tested: code coverage is 99.5% . The test suite is run on every version of Lua (Lua 5.1 to 5.4, LuaJIT 2.0 and 2.1 beta) and on many OS (Windows Seven, Windows Server 2012, MacOs X and Ubuntu). You can check the continuous build results on [Travis-CI](https://travis-ci.org/bluebird75/luaunit) and [AppVeyor](https://ci.appveyor.com/project/bluebird75/luaunit). LuaUnit is maintained on GitHub: https://github.com/bluebird75/luaunit . We gladly accept feature requests and even better Pull Requests. For more information on LuaUnit development, please check: [Developing LuaUnit](http://luaunit.readthedocs.org/en/latest/#developing-luaunit) . LuaUnit is released under the BSD license. The main developer can be reached at *phil.fremy at free.fr* . If you have security issue to report requiring confidentiality, this is the address to use. ## LuaUnit successes Version 3.2 of LuaUnit has been downloaded more than 235 000 times on [LuaRocks](https://luarocks.org/modules/bluebird75/luaunit) LuaUnit is used in some very nice technological products. I like to mention: * [SchedMD/Slurm](https://www.schedmd.com/): Slurm is an open-source cluster resource management and job scheduling system that strives to be simple, scalable, portable, fault-tolerant, and interconnect agnostic. On the June 2017 Top 500 computer list, Slurm was performing workload management on six of the ten most powerful computers in the world including the number 1 system, Sunway TaihuLight with 10,649,600 computing cores. LuaUnit is used by Slurm to validate plugins written in Lua. Thanks Douglas Jacobsen to contribute back to LuaUnit. See the [GitHub repository of Slurm](https://github.com/SchedMD/slurm) . * [MAD by the CERN](http://mad.web.cern.ch/mad/): CERN is the European Organization for Nuclear Research, where physicists and engineers are probing the fundamental structure of the universe. MAD is one of the CERN project: MAD aims to be at the forefront of computational physics in the field of particle accelerator design and simulation. Its scripting language is de facto the standard to describe particle accelerators, simulate beam dynamics and optimize beam optics at CERN. Lua is the main language of MAD-ng, the new generatino of MAD. A fork of LuaUnit is used extensively for all MAD calculation and framework validation. Thanks Laurent Deniau for contributing back to LuaUnit. See the [GitHub repository of MAD](https://github.com/MethodicalAcceleratorDesign/MAD) . ## Contributors * [NiteHawk](https://github.com/n1tehawk) * [AbigailBuccaneer](https://github.com/AbigailBuccaneer) * [Juan Julián Merelo Guervós](https://github.com/JJ) * [Naoyuki Totani](https://github.com/ntotani) * [Jennal](https://github.com/Jennal) * [George Zhao](https://github.com/zhaozg) * kbuschelman * [Victor Seva](https://github.com/linuxmaniac) * [Urs Breu](https://github.com/ubreu) * Jim Anderson * [Douglas Jacobsen](https://github.com/dmjacobsen) * [Mayama Takeshi](https://github.com/MayamaTakeshi) ## Installation **LuaRocks** LuaUnit is available on [LuaRocks](https://luarocks.org/modules/bluebird75/luaunit). To install it, you need at least LuaRocks version 2.4.4 (due to old versions of wget being incompatible with GitHub https downloading) **GitHub** The simplest way to install LuaUnit is to fetch the GitHub version: git clone git@github.com:bluebird75/luaunit.git Then copy the file luaunit.lua into your project or the Lua libs directory. The version of the main branch on GitHub is always stable and can be used safely. ### History #### Version 3.4 - 02 March 2021 * support for Lua 5.4 * assertAlmostEquals() works also on tables and nested structures * choose test output style with environment variable LUAUNIT_OUTPUT * setOutputType() accepts the xml filename as second argument when using the format junit * improve printing of table information in case of cycles * add ability to skip tests with `skip()` and `skipIf()` * detect attempts to exit the test suite before it is finished running * add assertErrorMsgContentEquals() to validate exactly any error message * filter out some stack entries when printing assertions (useful when embedding LuaUnit inside another test layer) with `STRIP_EXTRA_ENTRIES_IN_STACK_TRACE` * add `assertTableContains()` and `assertNotTableContains()` to verify the presence of a given value within a table * remove option TABLE_EQUALS_KEYBYCONTENT, it did not make sense * bugfix: * assertIs()/assertNotIs() deals better with protected metatables * assertEquals() deals better with tables containing cycles of different structure * fix table length comparison for table returning inconsistent length #### Version 3.3 - 6. March 2018 * General * when comparing lists with assertEquals(), failure message provides an advanced comparison of the lists * assertErrorMsgEquals() can check for error raised as tables * tests may be finished early with fail(), failIf(), success() or successIf() * improve printing of recursive tables * improvements and fixes to JUnit and TAP output * stricter assertTrue() and assertFalse(): they only succeed with boolean values * add assertEvalToTrue() and assertEvalToFalse() with previous assertTrue()/assertFalse() behavior of coercing to boolean before asserting ** all assertion functions accept an optional extra message, to be printed along the failure * New command-line arguments: * can now shuffle tests with --shuffle or -s * possibility to repeat tests (for example to trigger a JIT), with --repeat NUM or -r NUM * more flexible test selection with inclusion (--pattern / -p) or exclusion (--exclude / -x) or combination of both * Scientific computing dedicated support (see documentation): * provide the machine epsilon in lu.EPS * new functions: assertNan(), assertInf(), assertPlusInf(), assertMinusInf(), assertPlusZero(), assertMinusZero() * in assertAlmostEquals( a, b, margin ), margin no longer provides a default value of 1E-11, the machine epsilon is used instead * Platform and continuous integration support: * validate LuaUnit on MacOs platform (thank to Travis CI) * validate LuaUnit with 32 bits numbers (floats) and 64 bits numbers (double) * add test coverage measurements thank to coveralls.io . Status: 99.76% of the code is verified. * use cache for AppVeyor and Travis builds * support for luarocks doc command * General doc improvements (detailed description of all output, more cross-linking between sections) #### Version 3.2 - 12. Jul 2016 * distinguish between failures (failed assertion) and errors * add command-line option to stop on first error or failure * support for new versions: Lua 5.3 and LuaJIT (2.0, 2.1 beta) * validation of all lua versions on Travis CI and AppVeyor * added compatibility layer with forked luaunit v2.x * added documentation about development process * improved support for table containing keys of type table * small bug fixes, several internal improvements #### Version 3.1 - 10 Mar. 2015 * luaunit no longer pollutes global namespace, unless defining EXPORT_ASSERT_TO_GLOBALS to true * fixes and validation of JUnit XML generation * strip luaunit internal information from stacktrace * general improvements of test results with duration and other details * improve printing for tables, with an option to always print table id * fix printing of recursive tables **Important note when upgrading to version 3.1** : assertions functions are no longer exported directly to the global namespace. See documentation for upgrade paths. #### Version 3.0 - 9. Oct 2014 Since some people have forked LuaUnit and release some 2.x version, I am jumping the version number to 3. - moved to Github - full documentation available in text, html and pdf at read-the-docs.org - new output format: JUnit - much better table assertions - new assertions for strings, with patterns and case insensitivity: assertStrContains, assertNotStrContains, assertNotStrIContains, assertStrIContains, assertStrMatches - new assertions for floats: assertAlmostEquals, assertNotAlmostEquals - type assertions: assertIsString, assertIsNumber, ... - error assertions: assertErrorMsgEquals, assertErrorMsgContains, assertErrorMsgMatches - improved error messages for several assertions - command-line options to select test, control output type and verbosity #### Version 2.0 Unofficial fork from version 1.3 by rjbcomupting - lua 5.2 module style, without global namespace pollution - setUp() may be named Setup() or setup() - tearDown() may be named Teardown() or teardown() - wrapFunction() may be called WrapFunctions() or wrap_functions() - run() may also be called Run() - table deep comparision (also available in 1.4) - control verbosity with setVerbosity() SetVerbosity() and set_verbosity() - More assertions: - is, is_, assert and assert_ (e.g. assert( LuaUnit.isString( getString() ) ) - assertNot and assert_not_ #### Version 1.5 - 8. Nov 2012 - compatibility with Lua 5.1 and 5.2 - better object model internally - a lot more of internal tests - several internal bug fixes - make it easy to customize the test output - running test functions no longer requires a wrapper - several level of verbosity #### Version 1.4 - 26. Jul 2012 - table deep comparison - switch from X11 to more popular BSD license - add TAP output format for integration into Jenkins - official repository now on GitHub #### Version 1.3 - 30. Oct 2007 - port to lua 5.1 - iterate over the test classes, methods and functions in the alphabetical order - change the default order of expected, actual in assertEquals (adjustable with USE_EXPECTED_ACTUAL_IN_ASSERT_EQUALS). #### Version 1.2 - 13. Jun 2005 - first public release #### Version 1.1 - move global variables to internal variables - assertion order is configurable between expected/actual or actual/expected - new assertion to check that a function call returns an error - display the calling stack when an error is spotted - two verbosity level, like in python unittest ![stats](https://stats.sylphide-consulting.com/piwik/piwik.php?idsite=37&rec=1) luaunit-LUAUNIT_V3_4/TODO.txt000066400000000000000000000175161401773523200157750ustar00rootroot00000000000000# make all instead of make platform, this would allow to remove platform.sh # also avoid setnv_lua.sh if possible # ensure luarocks package are installed inside insall location /home/travis/build/bluebird75/luaunit/install/luarocks/share/lua/5.1/luarocks" /home/travis/build/bluebird75/luaunit/install/luarocks/share/lua/5.1/luarocks" TODO Future: ============ - run a full modules with a function - build lua with ASAN, memory sanitizer and so on on travis before running it - ensure that assert string functions like assertStr, strcontains, etc reject incorrect type with a correct error message - pretty function formatting: https://github.com/luarocks/luarocks/blob/master/src/luarocks/core/util.lua - platform detection: - document prettystr - validate output with ignored tests (0 failures or some failures) - parametrize tests - coloured output - better error messages for string differences (diffing) - print local variables upon assertion error: + debug.get_local( ) will get the local variables in the current context + debug.get_upvalue( ) will get the upvalues in the current context - see inspect for better table printing: https://github.com/kikito/inspect.lua + print list part separate from the dict part in a table + print metatables in tables - see StackTracePlus for printing more stack information: https://github.com/ignacio/StackTracePlus - how does busted deal with nested tables ? functions ? - look at serpent to see how to improve nested table printing - function should be printed as - print table of test test_filterWithPattern and see how to improve readability - shuffle should shuffle separately classes and then class methods - add assertTableContains and assertTableNotContains to check the presence / absence of value in an array - look at serpent to see how to improve nested table printing - doc about usage of prettystr & assertion library - assertListContainsElements - assertListContainsElements - checkXXX for every assertXXX - review and enhance: TestLuaUnitExecution:test_withTableErrorInside Version 3.5 (future): ============ Planned: -------- - global setup / teardown - class setup / teardown - report test duration everywhere - add date and duration to tap output - XML: report system information - align the "OK" vertically for text output - better detection of screen size - move all file:line description to stack trace - better deal with one line formatting - table_contains(): + check with finding table or nested tables + add check for error messages - correctly compare tables with same content but different metatable Already done: ------------- - Version 3.4: ============ TODO: - assertAlmostNotEquals shall support tables - document the release process to luarocks and update dev manual - add test for the runner interface of luaunit - update examples - dev guide: explain doit.py - dev guide: explain CI Done - add a list of environment variables controlling LuaUnit - double-check documentation generation - move enabling global namespace pollution explanation to a later chapter - update doc about TABLE_EQUALS_KEYBYCONTENT - update doc about test skipping - update documentation about how to run list of test classes - update documentation about setOutputType() - assertAlmostEquals can check lists and more complex structures - can choose test output type through environment variables LUAUNIT_OUTPUT - setOutputType() also accepts the xml filename when using the format junit - simplify printing of table-info in cycles - allow to skip tests - fix a bug where assertIs/assertNotIs would not deal with protected metatables - fix a bug in dealing with table including cycles of different structure - remove option TABLE_EQUALS_KEYBYCONTENT, it did not make sense Version 3.3: ============ - make sure that example source code is included in documentation when packaging - add annex to documentation with full source code of example - add annex with BSD license - verify that assertError functions all work with tables, review implementation in detail - useRe -> usePattern - add success() to terminate test successfully - doc: explain that prettystr() is used in assertions - check rock installation of luaunit - add custom message support - build luarocks - update contributors - update download badge - doc about prettystr - add fail() to force test failure - use caching on travis-ci - assertAlmostEqual no longer includes a default margin, margin must always be explicitly specified. - verify that lu.EPS by calculation - fix include/exclude bug (see https://github.com/bluebird75/luaunit/pull/82 ) - doc about scientific computing dedicated functions - assertions for nan and inf and +/- zero - fixes for junit and tap output - doc improvements - better error messages for list assertions: + expected length of X, got Y + index differing in table 1 and 2 - more doc about assertTrue/False/... with a table - randomized testing - can run a tests numerous times (useful for triggering the JIT effect) - can include and exclude tests from the test list Done since 3.1: =============== x provide a luarock package. See: https://rocks.moonscript.org/modules/rjpcomputing/luaunit x make a difference between errors and failures x lua 5.3 x travis lua 5.3 x compatibility with LuaUnit v2.0 of rjbcomputing x provide a legacy wrapFunction() Done since 3.0: =============== x check documentation link glitch to TAP x doc: report how to handle global space pollution/restriction x doc: adapt all examples to new way of requireing luaunit x less global space pollution x doc: move description of table printing to an annex x validate well-formed XML with a DTD x validate test output (TAP, ...) with functional tests x test failures, verify that output is correct x improve testresult: contain the list of tests, with status of each test x strip luaunit stack more intelligently: exclude content of luaunit x mention mailing-list in README.md x mention version in documentation x mention mailing-list x mention the new global variable config for displaying table content x fix display of tables with recursive references x improve display of nested tables in error messages x improve display of multiline strings in error messages x Junit XML Ouptut: x test and fix xml escaping x validate xml with apache and jenkins schemas + xml format: - add proper xml formatting header - report number of failures within element - report duration - add properties describe the environment Done: ============ x add email to report vulnerabilities in private x add other types of output x assert with matching of the error message x finish user documentation x switch version 3.0 x add assertMatch for strings x document --name x improve junit xml output (one file, choice of filename) x display number of non selected tests x assertIs with all types x mention one file distribution x improve TAP output: pre-calculate test numbers, display test summary as comment x test error messages of assertStrMatches and all error functions x assertNil + assertNotNil x readthedocs integration x add travis-ci badges to README x filter by pattern x support --version x support --help x replace methodInstance with real test name in reports x better error messages for wrong command line option, or wrong output type x control verbosity and output type with command line x display time to run all tests x move all assertions together x better error display of assertIsXXX functions x add assertContains for strings x add assertIsNumber, assertIsXXX x table assertions x sequence asserts x compatibilty tests with several version of lua x add assertNotEquals Release TODO: ============= - all tests green in Travis and AppVeyor - doc is green in read-the-docs - documentation is updated with release content - doit.py runtests success - tag set on the code - upload release to GitHub - prepare luarocks and upload to luarocks - verify smooth installation of luarocks - annonce release on lua mailing-list luaunit-LUAUNIT_V3_4/appveyor.yml000066400000000000000000000021211401773523200170410ustar00rootroot00000000000000image: Visual Studio 2015 shallow_clone: true # create a build matrix to use various Lua and LuaJIT versions environment: matrix: - LUAENV: luajit20 - LUAENV: luajit21 - LUAENV: lua51 - LUAENV: lua51_64 - LUAENV: lua52 - LUAENV: lua52_64 - LUAENV: lua53 - LUAENV: lua53_64 - LUAENV: lua54 - LUAENV: lua54_64 # install required binaries via batch file (also sets %LUA% path) install: - cmd: .appveyor\install-lua.cmd cache: # each directory resulting from the previous download/build is cached - lua51 -> .appveyor\install-lua.cmd - lua51-64 -> .appveyor\install-lua.cmd - lua52 -> .appveyor\install-lua.cmd - lua52-64 -> .appveyor\install-lua.cmd - lua53 -> .appveyor\install-lua.cmd - lua53-64 -> .appveyor\install-lua.cmd - lua54 -> .appveyor\install-lua.cmd - lua54-64 -> .appveyor\install-lua.cmd - luajit20 -> .appveyor\install-lua.cmd - luajit21 -> .appveyor\install-lua.cmd build: off test_script: - cmd: >- %LUA% -v run_unit_tests.lua --shuffle %LUA% run_functional_tests.lua luaunit-LUAUNIT_V3_4/doc/000077500000000000000000000000001401773523200152225ustar00rootroot00000000000000luaunit-LUAUNIT_V3_4/doc/Makefile000066400000000000000000000151561401773523200166720ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # User-friendly check for sphinx-build ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) endif # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " xml to make Docutils-native XML files" @echo " pseudoxml to make pseudoxml-XML files for display purposes" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/LuaUnit.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/LuaUnit.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/LuaUnit" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/LuaUnit" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." latexpdfja: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through platex and dvipdfmx..." $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." xml: $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml @echo @echo "Build finished. The XML files are in $(BUILDDIR)/xml." pseudoxml: $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml @echo @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." luaunit-LUAUNIT_V3_4/doc/conf.py000066400000000000000000000177111401773523200165300ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # LuaUnit documentation build configuration file, created by # sphinx-quickstart on Thu Aug 21 21:45:55 2014. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys import os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'LuaUnit' copyright = u'2016, Philippe Fremy' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '3.3' # The full version, including alpha/beta/rc tags. release = '3.3' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all # documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. #keep_warnings = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = [] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. #html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'LuaUnitdoc' # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ ('index', 'LuaUnit.tex', u'LuaUnit Documentation', u'Philippe Fremy', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'luaunit', u'LuaUnit Documentation', [u'Philippe Fremy'], 1) ] # If true, show URL addresses after external links. #man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'LuaUnit', u'LuaUnit Documentation', u'Philippe Fremy', 'LuaUnit', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. #texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. #texinfo_no_detailmenu = False luaunit-LUAUNIT_V3_4/doc/index.rst000066400000000000000000002761251401773523200171000ustar00rootroot00000000000000.. LuaUnit documentation master file, created by sphinx-quickstart on Thu Aug 21 21:45:55 2014. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, Welcome to LuaUnit's documentation! ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, Introduction ************ LuaUnit is a popular unit-testing framework for Lua, with an interface typical of xUnit libraries (Python unittest, Junit, NUnit, ...). It supports several output formats (Text, TAP, JUnit, ...) to be used directly or work with Continuous Integration platforms (Jenkins, Hudson, ...). For simplicity, LuaUnit is contained into a single-file and has no external dependency. To start using it, just add the file *luaunit.lua* to your project. A `LuaRocks package`_ is also available. .. _LuaRocks package: https://luarocks.org/modules/bluebird75/luaunit Tutorial and reference documentation is available on `Read-the-docs`_ . .. _Read-the-docs: http://luaunit.readthedocs.org/en/latest/ LuaUnit also provides some dedicated support to scientific computing. See the section `Scientific computing and LuaUnit`_ LuaUnit may also be used as an assertion library. In that case, you will call the assertion functions, which generate errors when the assertion fails. The error includes a detailed analysis of the failed assertion, like when executing a test suite. LuaUnit provides another generic usage function: :func:`prettystr` which converts any value to a nicely formatted string. It supports in particular tables, nested table and even recursive tables. More details ************ LuaUnit provides a wide range of assertions and goes into great efforts to provide the most useful output. For example since version 3.3 , comparing lists will provide a detailed difference analysis: .. code-block:: -- lua test code. Can you spot the difference ? function TestListCompare:test1() local A = { 121221, 122211, 121221, 122211, 121221, 122212, 121212, 122112, 122121, 121212, 122121 } local B = { 121221, 122211, 121221, 122211, 121221, 122212, 121212, 122112, 121221, 121212, 122121 } lu.assertEquals( A, B ) end $ lua test_some_lists_comparison.lua TestListCompare.test1 ... FAIL test/some_lists_comparisons.lua:22: expected: List difference analysis: * lists A (actual) and B (expected) have the same size * lists A and B start differing at index 9 * lists A and B are equal again from index 10 * Common parts: = A[1], B[1]: 121221 = A[2], B[2]: 122211 = A[3], B[3]: 121221 = A[4], B[4]: 122211 = A[5], B[5]: 121221 = A[6], B[6]: 122212 = A[7], B[7]: 121212 = A[8], B[8]: 122112 * Differing parts: - A[9]: 122121 + B[9]: 121221 * Common parts at the end of the lists = A[10], B[10]: 121212 = A[11], B[11]: 122121 The command-line options provide a flexible interface to select tests by name or patterns, control output format, set verbosity and more. See `Using the command-line`_ . LuaUnit is very well tested: code coverage is 99.5% . The test suite is run on every version of Lua (Lua 5.1 to 5.3, LuaJIT 2.0 and 2.1 beta) and on many OS (Windows Seven, Windows Server 2012, MacOs X and Ubuntu). You can check the continuous build results on `Travis-CI`_ and `AppVeyor`_ . .. _Travis-CI: https://travis-ci.org/bluebird75/luaunit .. _AppVeyor: https://ci.appveyor.com/project/bluebird75/luaunit/history LuaUnit is maintained on GitHub: https://github.com/bluebird75/luaunit . We gladly accept feature requests and even better Pull Requests. LuaUnit is released under the BSD license. Installation ============ LuaUnit is packed into a single-file. To make start using it, just add the file to your project. Several installation methods are available. LuaRocks -------- LuaUnit is available as a `LuaRocks package`_ . .. _LuaRocks package: https://luarocks.org/modules/bluebird75/luaunit GitHub ------ The simplest way to install LuaUnit is to fetch the GitHub version: .. code-block:: bash git clone git@github.com:bluebird75/luaunit.git Then copy the file luaunit.lua into your project or the Lua libs directory. The version in development on GitHub is always stable and can be used safely. On Linux, you can also install it into your Lua directories .. code-block:: bash sudo python doit.py install If that fail, edit the function *install()* in the file *doit.py* to adjust the Lua version and installation directory. It uses, by default, Linux paths that depend on the version. Upgrade note ================ **Important note when upgrading from version below 3.1** : there is a break of backward compatibility in version 3.1, assertions functions are no longer exported directly to the global namespace. See :ref:`luaunit-global-asserts` on how to adjust or restore previous behavior. LuaUnit development =================== See `Developing luaunit`_ Version and Changelog ===================== This documentation describes the functionality of LuaUnit v3.2 . New in version 3.4 - 02 March 2021 ---------------------------------- * support for Lua 5.4 * :func:`assertAlmostEquals` works also on tables and nested structures * choose test output style with environment variable `LUAUNIT_OUTPUT` * :func:`runner:setOutputType()` accepts the xml filename as second argument when using the format *junit* * improve printing of table information in case of cycles * add ability to skip tests with :func:`skip` and :func:`skipIf` * detect attempts to exit the test suite before it is finished running * add :func:`assertErrorMsgContentEquals` to validate exactly any error message * filter out some stack entries when printing assertions (useful when embedding LuaUnit inside another test layer) with :ref:`strip_extra_entries_in_stack_trace` * add :func:`assertTableContains` and :func:`assertNotTableContains` to verify the presence of a given value within a table * remove option `TABLE_EQUALS_KEYBYCONTENT`, it did not make sense * bugfix: * :func:`assertIs`/:func:`assertNotIs` deals better with protected metatables * :func:`assertEquals` deals better with tables containing cycles of different structure * fix table length comparison for table returning inconsistent length New in version 3.3 - 6. Mar 2018 -------------------------------- * General * when comparing lists with :func:`assertEquals`, failure message provides an advanced comparison of the lists * :func:`assertErrorMsgEquals` can check for error raised as tables * tests may be finished early with :func:`fail`, :func:`failIf`, :func:`success` or :func:`successIf` * improve printing of recursive tables * improvements and fixes to JUnit and TAP output * stricter :func:`assertTrue` and :func:`assertFalse`: they only succeed with boolean values * add :func:`assertEvalToTrue` and :func:`assertEvalToFalse` with previous :func:`assertTrue`/:func:`assertFalse` behavior of coercing to boolean before asserting * all assertion functions accept an optional extra message, to be printed along the failure * New command-line arguments: * can now shuffle tests with ``--shuffle`` or ``-s`` * possibility to repeat tests (for example to trigger a JIT), with ``--repeat NUM`` or ``-r NUM`` * more flexible test selection with inclusion (``--pattern`` / ``-p``) or exclusion (``--exclude`` / ``-x``) or combination of both * Scientific computing dedicated support (see documentation): * provide the machine epsilon in EPS * new functions: :func:`assertNan`, :func:`assertInf`, :func:`assertPlusInf`, :func:`assertMinusInf`, :func:`assertPlusZero`, :func:`assertMinusZero` and their negative version * in :func:`assertAlmostEquals`, margin no longer provides a default value of 1E-11, the machine epsilon is used instead * Platform and continuous integration support: * validate LuaUnit on MacOs platform (thank to Travis CI) * validate LuaUnit with 32 bits numbers (floats) and 64 bits numbers (double) * add test coverage measurements thank to coveralls.io . Status: 99.76% of the code is verified. * use cache for AppVeyor and Travis builds * support for ``luarocks doc`` command * General doc improvements (detailed description of all output, more cross-linking between sections) New in version 3.2 - 12. Jul 2016 --------------------------------- * Add command-line option to stop on first error or failure. See `Other options`_ * Distinguish between failures (failed assertion) and errors * Support for new versions: Lua 5.3 and LuaJIT (2.0, 2.1 beta) * Validation of all lua versions on Travis CI and AppVeyor * Add compatibility layer with forked luaunit v2.x * Added documentation about development process. See `Developing luaUnit`_ * Improved support for table containing keys of type table. See :ref:`comparing-table-keys-table` * Small bug fixes, several internal improvements * Availability of a Luarock package. See `https://luarocks.org/modules/bluebird75/luaunit` . New in version 3.1 - 10. Mar 2015 --------------------------------- * luaunit no longer pollutes global namespace, unless defining EXPORT_ASSERT_TO_GLOBALS to true. See :ref:`luaunit-global-asserts` * fixes and validation of JUnit XML generation * strip luaunit internal information from stacktrace * general improvements of test results with duration and other details * improve printing for tables, with an option to always print table id. See :ref:`table-printing` * fix printing of recursive tables **Important note when upgrading to version 3.1** : assertions functions are no longer exported directly to the global namespace. See :ref:`luaunit-global-asserts` New in version 3.0 - 9. Oct 2014 -------------------------------- Because LuaUnit was forked and released as some 2.x version, version number is now jumping to 3.0 . * full documentation available in text, html and pdf at http://luaunit.read-the-docs.org * new output format: JUnit, compatible with Bamboo and other CI platforms. See `Output formats`_ * much better table assertions * new assertions for strings, with patterns and case insensitivity: assertStrContains, assertNotStrContains, assertNotStrIContains, assertStrIContains, assertStrMatches * new assertions for floats: assertAlmostEquals, assertNotAlmostEquals * type assertions: assertIsString, assertIsNumber, ... * error assertions: assertErrorMsgEquals, assertErrorMsgContains, assertErrorMsgMatches * improved error messages for several assertions * command-line options to select test, control output type and verbosity New in version 1.5 - 8. Nov 2012 -------------------------------- * compatibility with Lua 5.1 and 5.2 * better object model internally * a lot more of internal tests * several internal bug fixes * make it easy to customize the test output * running test functions no longer requires a wrapper * several level of verbosity New in version 1.4 - 26. Jul 2012 --------------------------------- * switch from X11 to more popular BSD license * add TAP output format for integration into Jenkins. See `Output formats`_ * official repository now on GitHub New in version 1.3 - 30. Oct 2007 --------------------------------- * port to lua 5.1 * iterate over the test classes, methods and functions in the alphabetical order * change the default order of expected, actual in assertEquals. See `Equality assertions`_ Version 1.2 - 13. Jun 2005 --------------------------------- * first public release Version 1.1 ------------ * move global variables to internal variables * assertion order is configurable between expected/actual or actual/expected. See `Equality assertions`_ * new assertion to check that a function call returns an error * display the calling stack when an error is spotted * two verbosity level, like in python unittest Getting started with LuaUnit **************************** This section will guide you through a step by step usage of *LuaUnit* . The full source code of the example below is available in the : `source_code_example`_ or in the file *my_test_suite.lua* in the doc directory. Setting up your test script =========================== To get started, create your file *my_test_suite.lua* . The script should import LuaUnit:: lu = require('luaunit') The last line executes your script with LuaUnit and exit with the proper error code:: os.exit( lu.LuaUnit.run() ) Now, run your file with:: lua my_test_suite.lua It prints something like:: Ran 0 tests in 0.000 seconds, 0 successes, 0 failures OK Now, your testing framework is in place, you can start writing tests. Writing tests ============= LuaUnit scans all variables that start with *test* or *Test*. If they are functions, or if they are tables that contain functions that start with *test* or *Test*, they are run as part of the test suite. So just write a function whose name starts with test. Inside test functions, use the assertions functions provided by LuaUnit, such as :func:`assertEquals`. Let's see that in practice. Suppose you want to test the following add function:: function add(v1,v2) -- add positive numbers -- return 0 if any of the numbers are 0 -- error if any of the two numbers are negative if v1 < 0 or v2 < 0 then error('Can only add positive or null numbers, received '..v1..' and '..v2) end if v1 == 0 or v2 == 0 then return 0 end return v1+v2 end You write the following tests:: function testAddPositive() lu.assertEquals(add(1,1),2) end function testAddZero() lu.assertEquals(add(1,0),0) lu.assertEquals(add(0,5),0) lu.assertEquals(add(0,0),0) end :func:`assertEquals` is the most commonly used assertion function. It verifies that both argument are equals, in the order actual value, expected value. Rerun your test script (``-v`` is to activate a more verbose output):: $ lua my_test_suite.lua -v It now prints:: Started on 02/19/17 22:15:53 TestAdd.testAddPositive ... Ok TestAdd.testAddZero ... Ok ========================================================= Ran 2 tests in 0.003 seconds, 2 successes, 0 failures OK You always have: * the date at which the test suite was started * the group to which the function belongs (usually, the name of the function table, and ** for all direct test functions) * the name of the function being executed * a report at the end, with number of executed test, number of non selected tests if any, number of failures, number of errors (if any) and duration. The difference between failures and errors are: * luaunit assertion functions generate failures * any unexpected error during execution generates an error * failures or errors during setup() or teardown() always generate errors If we continue with our example, we also want to test that when the function receives negative numbers, it generates an error. Use :func:`assertError` or even better, :func:`assertErrorMsgContains` to also validate the content of the error message. There are other types or error checking functions, see `Error assertions`_ . Here we use :func:`assertErrorMsgContains` . First argument is the expected message, then the function to call and the optional arguments:: function testAddError() lu.assertErrorMsgContains('Can only add positive or null numbers, received 2 and -3', add, 2, -3) end Now, suppose we also have the following function to test:: function adder(v) -- return a function that adds v to its argument using add function closure( x ) return x+v end return closure end We want to test the type of the value returned by adder and its behavior. LuaUnit provides assertion for type testing (see `Type assertions`_ ). In this case, we use :func:`assertIsFunction`:: function testAdder() f = adder(3) lu.assertIsFunction( f ) lu.assertEquals( f(2), 5 ) end Grouping tests, setup/teardown functionality ===================================================== When the number of tests starts to grow, you usually organise them into separate groups. You can do that with LuaUnit by putting them inside a table (whose name must start with *Test* or *test* ). For example, assume we have a second function to test:: function div(v1,v2) -- divide positive numbers -- return 0 if any of the numbers are 0 -- error if any of the two numbers are negative if v1 < 0 or v2 < 0 then error('Can only divide positive or null numbers, received '..v1..' and '..v2) end if v1 == 0 or v2 == 0 then return 0 end return v1/v2 end We move the tests related to the function add into their own table:: TestAdd = {} function TestAdd:testAddPositive() lu.assertEquals(add(1,1),2) end function TestAdd:testAddZero() lu.assertEquals(add(1,0),0) lu.assertEquals(add(0,5),0) lu.assertEquals(add(0,0),0) end function TestAdd:testAddError() lu.assertErrorMsgContains('Can only add positive or null numbers, received 2 and -3', add, 2, -3) end function TestAdd:testAdder() f = adder(3) lu.assertIsFunction( f ) lu.assertEquals( f(2), 5 ) end -- end of table TestAdd Then we create a second set of tests for div:: TestDiv = {} function TestDiv:testDivPositive() lu.assertEquals(div(4,2),2) end function TestDiv:testDivZero() lu.assertEquals(div(4,0),0) lu.assertEquals(div(0,5),0) lu.assertEquals(div(0,0),0) end function TestDiv:testDivError() lu.assertErrorMsgContains('Can only divide positive or null numbers, received 2 and -3', div, 2, -3) end -- end of table TestDiv Execution of the test suite now looks like this:: Started on 02/19/17 22:15:53 TestAdd.testAddError ... Ok TestAdd.testAddPositive ... Ok TestAdd.testAddZero ... Ok TestAdd.testAdder ... Ok TestDiv.testDivError ... Ok TestDiv.testDivPositive ... Ok TestDiv.testDivZero ... Ok ========================================================= Ran 7 tests in 0.006 seconds, 7 successes, 0 failures OK When tests are defined in tables, you can optionally define two special functions, *setUp()* and *tearDown()*, which will be executed respectively before and after every test. These function may be used to create specific resources for the test being executed and cleanup the test environment. For a practical example, imagine that we have a *log()* function that writes strings to a log file on disk. The file is created upon first usage of the function, and the filename is defined by calling the function *initLog()*. The tests for these functions would take advantage of the *setup/teardown* functionality to prepare a log filename shared by all tests, make sure that all tests start with a non existing log file name, and delete the log filename after every test:: TestLogger = {} function TestLogger:setUp() -- define the fname to use for logging self.fname = 'mytmplog.log' -- make sure the file does not already exists os.remove(self.fname) end function TestLogger:testLoggerCreatesFile() initLog(self.fname) log('toto') -- make sure that our log file was created f = io.open(self.fname, 'r') lu.assertNotNil( f ) f:close() end function TestLogger:tearDown() -- cleanup our log file after all tests os.remove(self.fname) end .. Note:: *Errors generated during execution of setUp() or tearDown() functions are considered test failures.* .. Note:: *For compatibility with luaunit v2 and other lua unit-test frameworks, setUp() and tearDown() may also be named setup(), SetUp(), Setup() and teardown(), TearDown(), Teardown().* Using the command-line ====================== You can control the LuaUnit execution from the command-line: **Output format** Choose the test output format with ``-o`` or ``--output``. Available formats are: * text: the default output format * nil: no output at all * tap: TAP format * junit: output junit xml Example of non-verbose text format:: $ lua doc/my_test_suite.lua ....... Ran 7 tests in 0.003 seconds, 7 successes, 0 failures OK Example of TAP format:: $ lua doc/my_test_suite.lua -o TAP 1..7 # Started on 02/19/17 22:15:53 # Starting class: TestAdd ok 1 TestAdd.testAddError ok 2 TestAdd.testAddPositive ok 3 TestAdd.testAddZero ok 4 TestAdd.testAdder # Starting class: TestDiv ok 5 TestDiv.testDivError ok 6 TestDiv.testDivPositive ok 7 TestDiv.testDivZero # Ran 7 tests in 0.007 seconds, 7 successes, 0 failures Output formats may also be controlled by the following environment variables: * LUAUNIT_OUTPUT: output format to use * LUAUNIT_JUNIT_FNAME: for junit output format, name of the xml file For a more detailed overview of all formats and their verbosity see the section `Output formats`_ . **List of tests to run** You can list some test names on the command-line to run only those tests. The name must be the exact match of either the test table, the test function or the test table and the test method. The option may be repeated. Example:: -- Run all TestAdd table tests and one test of TestDiv table. $ lua doc/my_test_suite.lua TestAdd TestDiv.testDivError -v Started on 02/19/17 22:15:53 TestAdd.testAddError ... Ok TestAdd.testAddPositive ... Ok TestAdd.testAddZero ... Ok TestAdd.testAdder ... Ok TestDiv.testDivError ... Ok ========================================================= Ran 5 tests in 0.003 seconds, 5 successes, 0 failures OK **Including / excluding tests** The most flexible approach for selecting tests to use the include and exclude functionality. With ``--pattern`` or ``-p``, you can provide a lua pattern and only the tests that contain the pattern will actually be run. Example:: -- Run all tests of zero testing and error testing -- by using the magic character . $ lua my_test_suite.lua -v -p Err.r -p Z.ro For our test suite, it gives the following output:: Started on 02/19/17 22:15:53 TestAdd.testAddError ... Ok TestAdd.testAddZero ... Ok TestDiv.testDivError ... Ok TestDiv.testDivZero ... Ok ========================================================= Ran 4 tests in 0.003 seconds, 4 successes, 0 failures, 3 non-selected OK The number of tests ignored by the selection is printed, along with the test result. The pattern can be any lua pattern. Be sure to exclude all magic characters with % (like -+?*) and protect your pattern from the shell interpretation by putting it in quotes. You can also exclude tests that match some patterns: Example:: -- Run all tests except zero testing and except error testing $ lua my_test_suite.lua -v -x Error -x Zero For our test suite, it gives the following output:: Started on 02/19/17 22:29:45 TestAdd.testAddPositive ... Ok TestAdd.testAdder ... Ok TestDiv.testDivPositive ... Ok ========================================================= Ran 3 tests in 0.003 seconds, 3 successes, 0 failures, 4 non-selected OK You can also combine test selection and test exclusion. See `Flexible test selection`_ Conclusion ========== You now know enough of LuaUnit to start writing your test suite. Check the reference documentation for a complete list of assertions, command-line options and specific behavior. Reference documentation *********************** Command-line options ==================== Usage: lua [options] [testname1 [testname2] ...] **Test names** When no test names are supplied, all tests are collected. The syntax for supplying test names can be either: name of the function, name of the table or [name of the table].[name of the function]. Only the supplied tests will be executed. Selecting tests with --pattern and --exclude is usually more flexible. See `Flexible test selection`_ **Options** --output, -o FORMAT Set output format to FORMAT. Possible values: text, tap, junit, nil . See `Output formats`_ --name, -n FILENAME For junit format only, mandatory name of xml file. Ignored for other formats. --pattern, -p PATTERN Execute all test names matching the Lua PATTERN. May be repeated to include severals patterns. See `Flexible test selection`_ --exclude, -x PATTERN Exclude all test names matching the Lua PATTERN. May be repeated to exclude severals patterns. See `Flexible test selection`_ --repeat, -r NUM Repeat all tests NUM times, e.g. to trigger the JIT. See `Other options`_ --shuffle, -s Shuffle tests before running them. See `Other options`_ --error, -e Stop on first error. See `Other options`_ --failure, -f Stop on first failure or error. See `Other options`_ --verbose, -v Increase verbosity --quiet, -q Set verbosity to minimum --help, -h Print help --version Version information of LuaUnit Output formats ---------------------- Choose the output format with the syntax ``-o FORMAT`` or ``--output FORMAT`` or the environment variable ``LUAUNIT_OUTPUT``. Formats available: * ``text``: the default output format of LuaUnit * ``tap``: output compatible with the `Test Anything Protocol`_ * ``junit``: output compatible with the *JUnit XML* format (used by many CI platforms). The XML is written to the file provided with the ``--name`` or ``-n`` option or the environment variable ``LUAUNIT_JUNIT_FNAME``. * ``nil``: no output at all .. _Test Anything Protocol: http://testanything.org/ For more information on each format, see `Output formats details`_ Other options -------------- **Stopping on first error or failure** If ``--failure`` or ``-f`` is passed as an option, LuaUnit will stop on the first failure or error and display the test results. If ``--error`` or ``-e`` is passed as an option, LuaUnit will stop on the first error (but continue on failures). **Randomize test order** If ``--shuffle`` or ``-s`` is passed as an option, LuaUnit will execute tests in random order. The randomisation works on all test functions and methods. As a consequence test methods of a given class may be splitted into multiple location, generating several test class creation and destruction. **Repeat test** When using luajit, the just-in-time compiler will kick in only after a given function has been executed a sufficient number of times. To make sure that the JIT is not introducing any bug, LuaUnit provides a way to repeat a test may times, with ``--repeat`` or ``-r`` followed by a number. Flexible test selection ------------------------- LuaUnit provides very flexible way to select which tests to execute. We will illustrate this with several examples. In the examples, we use a test suite composed of the following test funcions:: -- class: TestAdd TestAdd.testAddError TestAdd.testAddPositive TestAdd.testAddZero TestAdd.testAdder -- class: TestDiv TestDiv.testDivError TestDiv.testDivPositive TestDiv.testDivZero With ``--pattern`` or ``-p``, you can provide a lua pattern and only the tests that contain the pattern will actually be run. Example:: -- Run all tests of zero testing and error testing -- by using the magic character . $ lua mytest_suite.lua -v -p Err.r -p Z.ro Started on 02/19/17 22:29:45 TestAdd.testAddError ... Ok TestAdd.testAddZero ... Ok TestDiv.testDivError ... Ok TestDiv.testDivZero ... Ok ========================================================= Ran 4 tests in 0.004 seconds, 4 successes, 0 failures, 3 non-selected OK The number of tests ignored by the selection is printed, along with the test result. The tests *TestAdd.testAdder testAdd.testPositive and testDiv.testDivPositive* have been correctly ignored. The pattern can be any lua pattern. Be sure to exclude all magic characters with % (like ``-+?*``) and protect your pattern from the shell interpretation by putting it in quotes. With ``--exclude`` or ``-x``, you can provide a lua pattern of tests which should be excluded from execution. Example:: -- Run all tests except zero testing and except error testing $ lua mytest_suite.lua -v -x Error -x Zero Started on 02/19/17 22:29:45 TestAdd.testAddPositive ... Ok TestAdd.testAdder ... Ok TestDiv.testDivPositive ... Ok ========================================================= Ran 3 tests in 0.003 seconds, 3 successes, 0 failures, 4 non-selected OK You can also combine test selection and test exclusion. The rules are the following: * if the first argument encountered is a inclusion pattern, the list of tests start empty * if the first argument encountered is an exclusion pattern, the list of tests start with all tests of the suite * each subsequent inclusion pattern will add new tests to the list * each subsequent exclusion pattern will remove test from the list * the final list is the list of tests executed In pure logic term, inclusion is the equivalent of ``or match(pattern)`` and exclusion is ``and not match(pattern)`` . Let's look at some practical examples:: -- Add all tests which include the word Add -- except the test Adder -- and also include the Zero tests $ lua my_test_suite.lua -v --pattern Add --exclude Adder --pattern Zero Started on 02/19/17 22:29:45 TestAdd.testAddError ... Ok TestAdd.testAddPositive ... Ok TestAdd.testAddZero ... Ok TestDiv.testDivZero ... Ok ========================================================= Ran 4 tests in 0.003 seconds, 4 successes, 0 failures, 3 non-selected OK LuaUnit runner object ======================= The various options set on the command-line can be overridden by creating a LuaUnit runner explicitely and calling specific functions on it. .. function:: LuaUnit.new() The execution of a LuaUnit test suite is controlled through a runner object. This object is created with `LuaUnit.new()` . .. code-block:: lua lu = require('luaunit') runner = lu.LuaUnit.new() -- use the runner object... runner.runSuite() .. function:: runner:setVerbosity( verbosity ) Set the verbosity of the runner. The value is an integer ranging from lu.VERBOSITY_QUIET to lu.VERBOSITY_VERBOSE . .. function:: runner:setQuitOnError( quitOnError ) Set the quit-on-first-error behavior, like the command-line `--xx`. The argument is a boolean value. .. function:: runner:setQuitOnFailuer( quitOnFailure ) Set the quit-on-first-failure-or-error behavior, like the command-line `--xx`. The argument is a boolean value. .. function:: runner:setRepeat( repeatNumber ) Set the number of times a test function is executed, like the command-line `-xx`. The argument is an integer. .. function:: runner:setShuffle( shuffle ) Set whether the test are run in randomized, like the command-line `--shuffle`. The argument is a boolean value. .. function:: runner:setOutputType(type [, junit_fname]) Set the output type of the test suite. See `Output formats`_ for possible values. When setting the format `junit`, it is mandatory to set the filename receiving the xml output. This can be done by passing it as second argument of this function. .. function:: runner:runSuite( [arguments] ) This function runs the test suite. **Arguments** If no arguments are supplied, it parses the command-line arguments of the script and interpret them. If arguments are supplied to the function, they are parsed as the command-line. It uses the same syntax. Test names may be supplied in arguments, to execute only these specific tests. Note that when explicit names are provided LuaUnit does not require the test names to necessarily start with *test*. If no test names were supplied, a general test collection process is done and the resulting tests are executed. **Return value** It returns the number of failures and errors. On success 0 is returned, making is suitable for an exit code. .. code-block:: lua lu = require('luaunit') runner = lu.LuaUnit.new() os.exit(runner.runSuite()) Example of using pattern to select tests:: .. code-block:: lua lu = require('luaunit') runner = lu.LuaUnit.new() -- execute tests matching the 'withXY' pattern os.exit(runner.runSuite('--pattern', 'withXY') Example of explicitly selecting tests:: .. code-block:: lua lu = require('luaunit') runner = lu.LuaUnit.new() os.exit(runner.runSuite('testABC', 'testDEF')) .. function:: LuaUnit.run( [arguments] ) This function may be called directly from the LuaUnit table. It will create internally a LuaUnit runner and pass all arguments to it. Arguments and return value is the same as :func:`runner:runSuite()` Example:: .. code-block:: lua -- execute tests matching the 'withXY' pattern os.exit(lu.LuaUnit.run('--pattern', 'withXY')) .. function:: runner:runSuiteByInstances( listOfNameAndInstances ) This function runs test without performing the global test collection process on the global namespace, the test are explicitely provided as argument, along with their names. Before execution, the function will parse the script command-line, like :func:`funner:runSuite()`. Input is provided as a list of { name, test_instance } . test_instance can either be a function or a table containing test functions starting with the prefix "test". Example of using runSuiteByInstances .. code-block:: lua lu = require('luaunit') runner = lu.LuaUnit.new() os.exit(runner.runSuiteByInstances( {'mySpecialTest1', mySpecialTest1}, {'mySpecialTest2', mySpecialTest2} } ) Skipping and ending test ========================== LuaUnit allows to force test ending in several ways. **Test skipping** .. function:: skip( message ) Stops the ongoing test and mark it as skipped with the given message. This can be used to deactivate a given test. .. function:: skipIf( condition, message ) If the condition *condition* evaluates to *true*, stops the ongoing test and mark it as skipped with the given message. Else, continue the test execution normally. The expected usage is to call the function at the beginning of the test to verify if the conditions are met for executing such tests. .. function:: runOnlyIf( condition, message ) If condition evaluates to *false*, stops the ongoing test and mark it as skipped with the given message. This is the opposite behavior of :func:`skipIf()` . The expected usage is to call the function at the beginning of the test to verify if the conditions are met for executing such tests. Number of skipped tests, if any, are reported at the end of the execution. **Force test failing** .. function:: fail( message ) Stops the ongoing test and mark it as failed with the given message. .. function:: failIf( condition, message ) If the condition *condition* evaluates to *true*, stops the ongoing test and mark it as failed with the given message. Else, continue the test execution normally. **Force test success** .. function:: success() Stops the ongoing test and mark it as successful. .. function:: successIf( condition ) If the condition *condition* evaluates to *true*, stops the ongoing test and mark it as successful. Else, continue the test execution normally. Output formats details ======================= To demonstrate the different output formats, we will take the example of the `Getting started with LuaUnit`_ section and add the following two failing cases: .. code-block:: lua TestWithFailures = {} -- two failing tests function TestWithFailures:testFail1() local a="toto" local b="titi" lu.assertEquals( a, b ) --oops, two values are not equal end function TestWithFailures:testFail2() local a=1 local b='toto' local c = a + b --oops, can not add string and numbers return c end **Text format** By default, LuaUnit uses the output format TEXT, with minimum verbosity:: $ lua my_test_suite.lua .......FE Failed tests: ------------- 1) TestWithFailures.testFail1 doc\my_test_suite_with_failures.lua:79: expected: "titi" actual: "toto" stack traceback: doc\my_test_suite_with_failures.lua:79: in function 'TestWithFailures.testFail1' 2) TestWithFailures.testFail2 doc\my_test_suite_with_failures.lua:85: attempt to perform arithmetic on local 'b' (a string value) stack traceback: [C]: in function 'xpcall' Ran 9 tests in 0.001 seconds, 7 successes, 1 failure, 1 error This format is heavily inspired by python unit-test library. One character is printed for every test executed, a dot for a successful test, a **F** for a test with failure and a **E** for a test with an error. At the end of the test suite execution, the details of the failures or errors are given, with an informative message and a full stack trace. The last line sums up the number of test executed, successful, failed, in error and not selected if any. When all tests are successful, a line with just OK is added:: $ lua doc\my_test_suite.lua ....... Ran 7 tests in 0.002 seconds, 7 successes, 0 failures OK The text format is also available as a more verbose version, by adding the ``--verbose`` flag:: $ lua doc\my_test_suite_with_failures.lua --verbose Started on 02/20/17 21:47:21 TestAdd.testAddError ... Ok TestAdd.testAddPositive ... Ok TestAdd.testAddZero ... Ok TestAdd.testAdder ... Ok TestDiv.testDivError ... Ok TestDiv.testDivPositive ... Ok TestDiv.testDivZero ... Ok TestWithFailures.testFail1 ... FAIL doc\my_test_suite_with_failures.lua:79: expected: "titi" actual: "toto" TestWithFailures.testFail2 ... ERROR doc\my_test_suite_with_failures.lua:85: attempt to perform arithmetic on local 'b' (a string value) ========================================================= Failed tests: ------------- 1) TestWithFailures.testFail1 doc\my_test_suite_with_failures.lua:79: expected: "titi" actual: "toto" stack traceback: doc\my_test_suite_with_failures.lua:79: in function 'TestWithFailures.testFail1' 2) TestWithFailures.testFail2 doc\my_test_suite_with_failures.lua:85: attempt to perform arithmetic on local 'b' (a string value) stack traceback: [C]: in function 'xpcall' Ran 9 tests in 0.008 seconds, 7 successes, 1 failure, 1 error In this format, you get: * a first line with date-time at which the test was started * one line per test executed * the test line is ended by **Ok**, **FAIL**, or **ERROR** in case the test is not successful * a summary of the failed tests with all details, like in the compact version. This format is usually interesting if some tests print debug output, to match the output to the test. **JUNIT format** The Junit XML format was introduced by the `Java testing framework JUnit`_ and has been then used by many continuous integration platform as an interoperability format between test suites and the platform. .. _Java testing framework JUnit: http://junit.org/junit4/ To output in the JUnit XML format, you use the format junit with ``--output junit`` and specify the XML filename with ``--name `` . On the standard output, LuaUnit will print information about the test progress in a simple format. Let's see with a simple example:: $ lua my_test_suite_with_failures.lua -o junit -n toto.xml # XML output to toto.xml # Started on 02/24/17 09:54:59 # Starting class: TestAdd # Starting test: TestAdd.testAddError # Starting test: TestAdd.testAddPositive # Starting test: TestAdd.testAddZero # Starting test: TestAdd.testAdder # Starting class: TestDiv # Starting test: TestDiv.testDivError # Starting test: TestDiv.testDivPositive # Starting test: TestDiv.testDivZero # Starting class: TestWithFailures # Starting test: TestWithFailures.testFail1 # Failure: doc/my_test_suite_with_failures.lua:79: expected: "titi" # actual: "toto" # Starting test: TestWithFailures.testFail2 # Error: doc/my_test_suite_with_failures.lua:85: attempt to perform arithmetic on local 'b' (a string value) # Ran 9 tests in 0.007 seconds, 7 successes, 1 failure, 1 error On the standard output, you will see the date-time, the name of the XML file, one line for each test started, a summary of the failure or errors when they occurs and the usual one line summary of the test execution: number of tests run, successful, failed, in error and number of non selected tests if any. The XML file generated by this execution is the following:: As you can see, the XML file is quite rich in terms of information. The verbosity level has no effect on junit output, all verbosity give the same output. Slight inconsistencies exist in the exact XML format in the different continuous integration suites. LuaUnit provides a compatible output which is validated against `Jenkins/Hudson schema`_ . If you ever find an problem in the XML formats, please report a bug to us, more testing is always welcome. .. _Jenkins/Hudson schema: https://github.com/bluebird75/luaunit/blob/LUAUNIT_V3_2_1/junitxml/junit-jenkins.xsd **TAP format** The `TAP format`_ for test results has been around since 1988. LuaUnit produces TAP reports compatible with version 12 of the specification. .. _`TAP format`: https://testanything.org/ Example with minimal verbosiy:: $ lua my_test_suite_with_failures.lua -o tap --quiet 1..9 # Started on 02/24/17 22:09:31 # Starting class: TestAdd ok 1 TestAdd.testAddError ok 2 TestAdd.testAddPositive ok 3 TestAdd.testAddZero ok 4 TestAdd.testAdder # Starting class: TestDiv ok 5 TestDiv.testDivError ok 6 TestDiv.testDivPositive ok 7 TestDiv.testDivZero # Starting class: TestWithFailures not ok 8 TestWithFailures.testFail1 not ok 9 TestWithFailures.testFail2 # Ran 9 tests in 0.003 seconds, 7 successes, 1 failure, 1 error With minimal verbosity, you have one line for each test run, with the status of the test, and one comment line when starting the test suite, when starting a new class or when finishing the test. Example with default verbosiy:: $ lua my_test_suite_with_failures.lua -o tap 1..9 # Started on 02/24/17 22:09:31 # Starting class: TestAdd ok 1 TestAdd.testAddError ok 2 TestAdd.testAddPositive ok 3 TestAdd.testAddZero ok 4 TestAdd.testAdder # Starting class: TestDiv ok 5 TestDiv.testDivError ok 6 TestDiv.testDivPositive ok 7 TestDiv.testDivZero # Starting class: TestWithFailures not ok 8 TestWithFailures.testFail1 doc/my_test_suite_with_failures.lua:79: expected: "titi" actual: "toto" not ok 9 TestWithFailures.testFail2 doc/my_test_suite_with_failures.lua:85: attempt to perform arithmetic on local 'b' (a string value) # Ran 9 tests in 0.005 seconds, 7 successes, 1 failure, 1 error In the default mode, the failure or error message is displayed in the failing test diagnostic part. Example with full verbosiy:: $ lua my_test_suite_with_failures.lua -o tap --verbose 1..9 # Started on 02/24/17 22:09:31 # Starting class: TestAdd ok 1 TestAdd.testAddError ok 2 TestAdd.testAddPositive ok 3 TestAdd.testAddZero ok 4 TestAdd.testAdder # Starting class: TestDiv ok 5 TestDiv.testDivError ok 6 TestDiv.testDivPositive ok 7 TestDiv.testDivZero # Starting class: TestWithFailures not ok 8 TestWithFailures.testFail1 doc/my_test_suite_with_failures.lua:79: expected: "titi" actual: "toto" stack traceback: doc/my_test_suite_with_failures.lua:79: in function 'TestWithFailures.testFail1' not ok 9 TestWithFailures.testFail2 doc/my_test_suite_with_failures.lua:85: attempt to perform arithmetic on local 'b' (a string value) stack traceback: [C]: in function 'xpcall' # Ran 9 tests in 0.007 seconds, 7 successes, 1 failure, 1 error With maximum verbosity, the stack trace is also displayed in the test diagnostic. **NIL format** With the nil format output, absolutely nothing is displayed while running the tests. Only the exit code of the command can tell whether the test was successful or not:: $ lua my_test_suite_with_failures.lua -o nil --verbose $ This mode is used by LuaUnit for its internal validation. Test collection and execution process ====================================== Test collection ------------------- The test collection and execution process is the following: * If a list of tests is specified on the command-line or as argument to the *runSuite()* or *runSuiteByInstances()*, this the considered list of tests to run. * If no list of tests is specified, the global namespace *_G* is searched for names starting by *test* or *Test*. All such names are put into the list of tests to run (provided they reference either a function or a table). * All tables are then scanned for table functions starting with *test* or *Test*, which are then added to the list of tests to run * From the list of tests to run, include and exclude patterns are applied * If shuffling is activated, the list is randomized. Else, it is sorted in alphabetical order. This constitutes the final list of tests to run. Test execution ------------------- Each test function is run in a protected call. If any luaunit assertion fails (assertEquals, ...), the test is considered as a failure. If an error is generated during the test execution, the test is marked as in error. Both errors and failures are reported at the end of the execution. When executing a table containing tests, the following methods are also considered: * *setUp()* is called prior to each test execution. Any failure or error during *setUp()* will prevent the test from being executed and will be reported in the test suite. * *tearDown()* is called after each test, even if the *setUp()* or the test failed. Any failure or error during *tearDown()* will be reported in the test suite. Assertions functions ===================== We will now list all assertion functions. For every functions, the failure message tries to be as informative as possible, by displaying the expectation and value that caused the failure. It relies on the :func:`prettystr` for printing nicely formatted values. All function accept an optional extra message which if provided, is printed along with the failure message. .. Note:: see :ref:`table-printing` for more information on how LuaUnit prints tables. Equality assertions ---------------------- All equality assertions functions take two arguments, in the order *actual value* then *expected value*. Some people are more familiar with the order *expected value* then *actual value*. It is possible to configure LuaUnit to use the opposite order for all equality assertions, by setting up a module variable: .. code-block:: lua lu.ORDER_ACTUAL_EXPECTED=false The order only matters for the message that is displayed in case of failures. It does not influence the test itself. .. function:: assertEquals(actual, expected [, extra_msg] ) **Alias**: *assert_equals()* Assert that two values are equal. This is the most used function for assertion within LuaUnit. The values being compared may be integers, floats, strings, tables, functions or a combination of those. If provided, *extra_msg* is a string which will be printed along with the failure message. When comparing floating point numbers, it is better to use :func:`assertAlmostEquals` which supports a margin for the equality verification. For tables, the comparison supports nested tables and cyclic structures. To be equal, two tables must have the same keys and the value associated with a key must compare equal with assertEquals() (using a recursive algorithm). When displaying the difference between two tables used as lists, LuaUnit performs an analysis of the list content to pinpoint the place where the list actually differs. See the below example: .. code-block:: -- lua test code. Can you spot the difference ? function TestListCompare:test1() local A = { 121221, 122211, 121221, 122211, 121221, 122212, 121212, 122112, 122121, 121212, 122121 } local B = { 121221, 122211, 121221, 122211, 121221, 122212, 121212, 122112, 121221, 121212, 122121 } lu.assertEquals( A, B ) end $ lua test_some_lists_comparison.lua TestListCompare.test1 ... FAIL test/some_lists_comparisons.lua:22: expected: List difference analysis: * lists A (actual) and B (expected) have the same size * lists A and B start differing at index 9 * lists A and B are equal again from index 10 * Common parts: = A[1], B[1]: 121221 = A[2], B[2]: 122211 = A[3], B[3]: 121221 = A[4], B[4]: 122211 = A[5], B[5]: 121221 = A[6], B[6]: 122212 = A[7], B[7]: 121212 = A[8], B[8]: 122112 * Differing parts: - A[9]: 122121 + B[9]: 121221 * Common parts at the end of the lists = A[10], B[10]: 121212 = A[11], B[11]: 122121 .. Note:: see :ref:`comparing-table-keys-table` for information on comparison of tables containing keys of type table. LuaUnit provides other table-related assertions, see :ref:`assert-table` . .. function:: assertNotEquals(actual, expected [, extra_msg]) **Alias**: *assert_not_equals()* Assert that two values are different. The assertion fails if the two values are identical. It behaves exactly like :func:`assertEquals` but checks for the opposite condition. If provided, *extra_msg* is a string which will be printed along with the failure message. Value assertions ---------------------- LuaUnit contains several flavours of true/false assertions, to be used in different contexts. Usually, when asserting for *true* or *false*, you want strict assertions (*nil* should not assert to *false*); *assertTrue()* and *assertFalse()* are the functions for this purpose. In some cases though, you want Lua coercion rules to apply (e.g. value *1* or string *"hello"* yields *true*) and the right functions to use are *assertEvalToTrue()* and *assertEvalToFalse()*. Finally, you have the *assertNotTrue()* and *assertNotFalse()* to verify that a value is anything but the boolean *true* or *false*. The below table sums it up: **True assertion family** ============ ============ =================== ================ Input Value assertTrue() assertEvalToTrue() assertNotTrue() ============ ============ =================== ================ *true* OK OK OK *false* Fail Fail Fail *nil* Fail Fail OK *0* Fail OK OK *1* Fail OK OK *"hello"* Fail OK OK ============ ============ =================== ================ **False assertion family** ============ ================ ============= =================== Input Value assertNotFalse() assertFalse() assertEvalToFalse() ============ ================ ============= =================== *true* Fail Fail Fail *false* OK OK OK *nil* Fail OK OK *0* Fail Fail Fail *1* Fail Fail Fail *"hello"* Fail Fail Fail ============ ================ ============= =================== .. function:: assertEvalToTrue(value [, extra_msg]) **Alias**: *assert_eval_to_true()* Assert that a given value evals to ``true``. Lua coercion rules are applied so that values like ``0``, ``""``, ``1.17`` **succeed** in this assertion. If provided, extra_msg is a string which will be printed along with the failure message. See :func:`assertTrue` for a strict assertion to boolean ``true``. .. function:: assertEvalToFalse(value [, extra_msg]) **Alias**: *assert_eval_to_false()* Assert that a given value eval to ``false``. Lua coercion rules are applied so that ``nil`` and ``false`` **succeed** in this assertion. If provided, extra_msg is a string which will be printed along with the failure message. See :func:`assertFalse` for a strict assertion to boolean ``false``. .. function:: assertTrue(value [, extra_msg]) **Alias**: *assert_true()* Assert that a given value is strictly ``true``. Lua coercion rules do not apply so that values like ``0``, ``""``, ``1.17`` **fail** in this assertion. If provided, extra_msg is a string which will be printed along with the failure message. See :func:`assertEvalToTrue` for an assertion to ``true`` where Lua coercion rules apply. .. function:: assertFalse(value [, extra_msg]) **Alias**: *assert_false()* Assert that a given value is strictly ``false``. Lua coercion rules do not apply so that ``nil`` **fails** in this assertion. If provided, *extra_msg* is a string which will be printed along with the failure message. See :func:`assertEvalToFalse` for an assertion to ``false`` where Lua coertion fules apply. .. function:: assertNil(value [, extra_msg]) **Aliases**: *assert_nil()*, *assertIsNil()*, *assert_is_nil()* Assert that a given value is *nil* . If provided, *extra_msg* is a string which will be printed along with the failure message. .. function:: assertNotNil(value [, extra_msg]) **Aliases**: *assert_not_nil()*, *assertNotIsNil()*, *assert_not_is_nil()* Assert that a given value is not *nil* . Lua coercion rules are applied so that values like ``0``, ``""``, ``false`` all validate the assertion. If provided, *extra_msg* is a string which will be printed along with the failure message. .. function:: assertIs(actual, expected [, extra_msg]) **Alias**: *assert_is()* Assert that two variables are identical. For string, numbers, boolean and for nil, this gives the same result as :func:`assertEquals` . For the other types, identity means that the two variables refer to the same object. If provided, *extra_msg* is a string which will be printed along with the failure message. **Example :** .. code-block:: lua s1='toto' s2='to'..'to' t1={1,2} t2={1,2} v1=nil v2=false lu.assertIs(s1,s1) -- ok lu.assertIs(s1,s2) -- ok lu.assertIs(t1,t1) -- ok lu.assertIs(t1,t2) -- fail lu.assertIs(v1,v2) -- fail .. function:: assertNotIs(actual, expected [, extra_msg]) **Alias**: *assert_not_is()* Assert that two variables are not identical, in the sense that they do not refer to the same value. If provided, *extra_msg* is a string which will be printed along with the failure message. See :func:`assertIs` for more details. String assertions -------------------------- Assertions related to string and patterns. .. function:: assertStrContains( str, sub [, isPattern [, extra_msg ]] ) **Alias**: *assert_str_contains()* Assert that the string *str* contains the substring or pattern *sub*. If provided, *extra_msg* is a string which will be printed along with the failure message. By default, substring is searched in the string. If *isPattern* is provided and is true, *sub* is treated as a pattern which is searched inside the string *str* . .. function:: assertStrIContains( str, sub [, extra_msg] ) **Alias**: *assert_str_icontains()* Assert that the string *str* contains the given substring *sub*, irrespective of the case. If provided, *extra_msg* is a string which will be printed along with the failure message. Note that unlike :func:`assertStrcontains`, you can not search for a pattern. .. function:: assertNotStrContains( str, sub, [isPattern [, extra_msg]] ) **Alias**: *assert_not_str_contains()* Assert that the string *str* does not contain the substring or pattern *sub*. If provided, *extra_msg* is a string which will be printed along with the failure message. By default, the substring is searched in the string. If *isPattern* is provided and is true, *sub* is treated as a pattern which is searched inside the string *str* . .. function:: assertNotStrIContains( str, sub [, extra_msg] ) **Alias**: *assert_not_str_icontains()* Assert that the string *str* does not contain the substring *sub*, irrespective of the case. If provided, *extra_msg* is a string which will be printed along with the failure message. Note that unlike :func:`assertNotStrcontains`, you can not search for a pattern. .. function:: assertStrMatches( str, pattern [, start [, final [, extra_msg ]]] ) **Alias**: *assert_str_matches()* Assert that the string *str* matches the full pattern *pattern*. If *start* and *final* are not provided or are *nil*, the pattern must match the full string, from start to end. The function allows to specify the expected start and end position of the pattern in the string. If provided, *extra_msg* is a string which will be printed along with the failure message. Error assertions -------------------------- Error related assertions, to verify error generation and error messages. .. function:: assertError( func, ...) **Alias**: *assert_error()* Assert that calling functions *func* with the arguments yields an error. If the function does not yield an error, the assertion fails. Note that the error message itself is not checked, which means that this function does not distinguish between the legitimate error that you expect and another error that might be triggered by mistake. The next functions provide a better approach to error testing, by checking explicitly the error message content. .. Note:: When testing LuaUnit, switching from *assertError()* to *assertErrorMsgEquals()* revealed quite a few bugs! .. function:: assertErrorMsgEquals( expectedMsg, func, ... ) **Alias**: *assert_error_msg_equals()* Assert that calling function *func* will generate exactly the given error message. If the function does not yield an error, or if the error message is not identical, the assertion fails. Be careful when using this function that error messages usually contain the file name and line number information of where the error was generated. This is usually inconvenient so we have introduced the :func:`assertErrorMsgContentEquals` . Be sure to check it. .. function:: assertErrorMsgContentEquals( expectedMsg, func, ... ) **Alias**: *assert_error_msg_content_equals()* Assert that calling function *func* will generate exactly the given error message, excluding the file and line information. File and line information may change as your programs evolve so we find this version more convenient than :func:`assertErrorMsgEquals` . .. function:: assertErrorMsgContains( partialMsg, func, ... ) **Alias**: *assert_error_msg_contains()* Assert that calling function *func* will generate an error message containing *partialMsg* . If the function does not yield an error, or if the expected message is not contained in the error message, the assertion fails. .. function:: assertErrorMsgMatches( expectedPattern, func, ... ) **Alias**: *assert_error_msg_matches()* Assert that calling function *func* will generate an error message matching *expectedPattern* . If the function does not yield an error, or if the error message does not match the provided patternm the assertion fails. Note that matching is done from the start to the end of the error message. Be sure to escape magic all magic characters with ``%`` (like ``-+.?*``) . Type assertions -------------------------- The following functions all perform type checking on their argument. If the received value is not of the right type, the failure message will contain the expected type, the received type and the received value to help you identify better the problem. .. function:: assertIsNumber(value [, extra_msg]) **Aliases**: *assertNumber()*, *assert_is_number()*, *assert_number()* Assert that the argument is a number (integer or float). If provided, *extra_msg* is a string which will be printed along with the failure message. .. function:: assertIsString(value [, extra_msg]) **Aliases**: *assertString()*, *assert_is_string()*, *assert_string()* Assert that the argument is a string. If provided, *extra_msg* is a string which will be printed along with the failure message. .. function:: assertIsTable(value [, extra_msg]) **Aliases**: *assertTable()*, *assert_is_table()*, *assert_table()* Assert that the argument is a table. If provided, *extra_msg* is a string which will be printed along with the failure message. .. function:: assertIsBoolean(value [, extra_msg]) **Aliases**: *assertBoolean()*, *assert_is_boolean()*, *assert_boolean()* Assert that the argument is a boolean. If provided, *extra_msg* is a string which will be printed along with the failure message. .. function:: assertIsNil(value [, extra_msg]) **Aliases**: *assertNil()*, *assert_is_nil()*, *assert_nil()* Assert that the argument is nil. If provided, *extra_msg* is a string which will be printed along with the failure message. .. function:: assertIsFunction(value [, extra_msg]) **Aliases**: *assertFunction()*, *assert_is_function()*, *assert_function()* Assert that the argument is a function. If provided, *extra_msg* is a string which will be printed along with the failure message. .. function:: assertIsUserdata(value [, extra_msg]) **Aliases**: *assertUserdata()*, *assert_is_userdata()*, *assert_userdata()* Assert that the argument is a userdata. If provided, *extra_msg* is a string which will be printed along with the failure message. .. function:: assertIsCoroutine(value [, extra_msg]) **Aliases**: *assertCoroutine()*, *assert_is_coroutine()*, *assert_coroutine()* Assert that the argument is a coroutine (an object with type *thread* ). If provided, *extra_msg* is a string which will be printed along with the failure message. .. function:: assertIsThread(value [, extra_msg]) **Aliases**: *assertIsThread()*, *assertThread()*, *assert_is_thread()*, *assert_thread()* Same function as :func:assertIsCoroutine . Since Lua coroutines have the type thread, it's not clear which name is the clearer, so we provide syntax for both names. If provided, *extra_msg* is a string which will be printed along with the failure message. .. _assert-table: Table assertions -------------------------- .. function:: assertItemsEquals(actual, expected [, extra_msg]) **Alias**: *assert_items_equals()* Assert that two tables contain the same items, irrespective of their keys. If provided, *extra_msg* is a string which will be printed along with the failure message. This function is practical for example if you want to compare two lists but where items are not in the same order: .. code-block:: lua lu.assertItemsEquals( {1,2,3}, {3,2,1} ) -- assertion succeeds .. The comparison is not recursive on the items: if any of the items are tables, they are compared using table equality (like as in :func:`assertEquals` ), where the key matters. .. code-block:: lua lu.assertItemsEquals( {1,{2,3},4}, {4,{3,2,},1} ) -- assertion fails because {2,3} ~= {3,2} .. function:: assertTableContains(table, element [, extra_msg]) **Alias**: *assert_table_contains()* Assert that the table contains at least one key with value `element`. Element may be of any type (including table), the recursive equality algorithm of assertEquals() is used for verifying the presence of the element. If provided, *extra_msg* is a string which will be printed along with the failure message. .. code-block:: lua lu.assertTableContains( {'a', 'b', 'c', 'd'}, 'b' ) -- assertion succeeds lu.assertTableContains( {1, 2, 3, {4} }, {4} } -- assertion succeeds .. function:: assertNotTableContains(table, element [, extra_msg]) **Alias**: *assert_not_table_contains()* Negative version of :func:`assertTableContains` . Assert that the table contains no element with value `element`. Element may be of any type (including table), the recursive equality algorithm of assertEquals() is used for verifying the presence of the element. If provided, *extra_msg* is a string which will be printed along with the failure message. .. code-block:: lua lu.assertNotTableContains( {'a', 'b', 'c', 'd'}, 'e' ) -- assertion succeeds lu.assertNotTableContains( {1, 2, 3, {4} }, {5} } -- assertion succeeds Scientific computing and LuaUnit -------------------------------- LuaUnit is used by the CERN for the MAD-NG program, the forefront of computational physics in the field of particle accelerator design and simulation (See MAD_). Thank to the feedback of a scientific computing developer, LuaUnit has been enhanced with some facilities for scientific applications (see all assertions functions below). .. _MAD: http://mad.web.cern.ch/mad/ The floating point library used by Lua is the one provided by the C compiler which built Lua. It is usually compliant with IEEE-754_ . As such, it can yields results such as *plus infinity*, *minus infinity* or *Not a Number* (NaN). The precision of any calculation performed in Lua is related to the smallest representable floating point value (typically called *EPS*): 2^-52 for 64 bits floats (type double in the C language) and 2^-23 for 32 bits float (type float in C). .. _IEEE-754: https://en.wikipedia.org/wiki/IEEE_754 .. Note :: Lua may be compiled with numbers represented either as 32 bits floats or 64 bits double (as defined by the macro LUA_FLOAT_TYPE in luaconf.h ). LuaUnit has been validated in both these configurations and in particuluar, the epsilon value *EPS* is adjusted accordingly. For more information about performing calculations on computers, please read the reference paper `What Every Computer Scientist Should Know About Floating-Point Arithmetic`_ .. _What Every Computer Scientist Should Know About Floating-Point Arithmetic: https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html If your calculation shall be portable to multiple OS or compilers, you may get different calculation errors depending on the OS/compiler. It is therefore important to verify them on every target. .. _MinusZero: .. Note on minus zero:: If you need to deal with value *minus zero*, be very careful because Lua versions are inconsistent on how they treat the syntax *-0* : it creates either a *plus zero* or a *minus zero* . Multiplying or dividing *0* by *-1* also yields inconsistent results. The reliable way to create the *-0* value is : minusZero = -1 / (1/0) .. _EPS: **EPS** *constant* The machine epsilon, to be used with :func:`assertAlmostEquals` . This is either: * 2^-52 or ~2.22E-16 (with lua number defined as double) * 2^-23 or ~1.19E-07 (with lua number defined as float) .. function:: assertNan( value [, extra_msg]) **Alias**: *assert_nan()* Assert that a given number is a *NaN* (Not a Number), according to the definition of IEEE-754_ . If provided, *extra_msg* is a string which will be printed along with the failure message. .. function:: assertNotNan( value [, extra_msg]) **Alias**: *assert_not_nan()* Assert that a given number is NOT a *NaN* (Not a Number), according to the definition of IEEE-754_ . If provided, *extra_msg* is a string which will be printed along with the failure message. .. function:: assertPlusInf( value [, extra_msg]) **Alias**: *assert_plus_inf()* Assert that a given number is *plus infinity*, according to the definition of IEEE-754_ . If provided, *extra_msg* is a string which will be printed along with the failure message. .. function:: assertMinusInf( value [, extra_msg]) **Alias**: *assert_minus_inf()* Assert that a given number is *minus infinity*, according to the definition of IEEE-754_ . If provided, *extra_msg* is a string which will be printed along with the failure message. .. function:: assertInf( value [, extra_msg]) **Alias**: *assert_inf()* Assert that a given number is *infinity* (either positive or negative), according to the definition of IEEE-754_ . If provided, *extra_msg* is a string which will be printed along with the failure message. .. function:: assertNotPlusInf( value [, extra_msg]) **Alias**: *assert_not_plus_inf()* Assert that a given number is NOT *plus infinity*, according to the definition of IEEE-754_ . If provided, *extra_msg* is a string which will be printed along with the failure message. .. function:: assertNotMinusInf( value [, extra_msg]) **Alias**: *assert_not_minus_inf()* Assert that a given number is NOT *minus infinity*, according to the definition of IEEE-754_ . If provided, *extra_msg* is a string which will be printed along with the failure message. .. function:: assertNotInf( value [, extra_msg]) **Alias**: *assert_not_inf()* Assert that a given number is neither *infinity* nor *minus infinity*, according to the definition of IEEE-754_ . If provided, *extra_msg* is a string which will be printed along with the failure message. .. function:: assertPlusZero( value [, extra_msg]) **Alias**: *assert_plus_zero()* Assert that a given number is *+0*, according to the definition of IEEE-754_ . The verification is done by dividing by the provided number and verifying that it yields *infinity* . If provided, *extra_msg* is a string which will be printed along with the failure message. Be careful when dealing with *+0* and *-0*, see note above. .. function:: assertMinusZero( value [, extra_msg]) **Alias**: *assert_minus_zero()* Assert that a given number is *-0*, according to the definition of IEEE-754_ . The verification is done by dividing by the provided number and verifying that it yields *minus infinity* . If provided, *extra_msg* is a string which will be printed along with the failure message. Be careful when dealing with *+0* and *-0*, see MinusZero_ .. function:: assertNotPlusZero( value [, extra_msg]) **Alias**: *assert_not_plus_zero()* Assert that a given number is NOT *+0*, according to the definition of IEEE-754_ . If provided, *extra_msg* is a string which will be printed along with the failure message. Be careful when dealing with *+0* and *-0*, see MinusZero_ .. function:: assertNotMinusZero( value [, extra_msg]) **Alias**: *assert_not_minus_zero()* Assert that a given number is NOT *-0*, according to the definition of IEEE-754_ . If provided, *extra_msg* is a string which will be printed along with the failure message. Be careful when dealing with *+0* and *-0*, see MinusZero_ .. function:: assertAlmostEquals( actual, expected [, margin=EPS [, extra_msg]] ) **Alias**: *assert_almost_equals()* Assert that two floating point numbers or tables are equal by the defined margin. If margin is not provided, the machine epsilon *EPS* is used. If provided, *extra_msg* is a string which will be printed along with the failure message. The function accepts either floating point numbers or tables. Complex structures with nested tables are supported. Comparing tables with assertAlmostEquals works just like :func:`assertEquals` with the difference that values are compared with a margin instead of with direct equality. Be careful that depending on the calculation, it might make more sense to measure the absolute error or the relative error (see below): .. function:: assertNotAlmostEquals( actual, expected [, margin=EPS [, extra_msg]] ) **Alias**: *assert_not_almost_equals()* Assert that two floating point numbers are not equal by the defined margin. If margin is not provided, the machine epsilon *EPS* is used. If provided, *extra_msg* is a string which will be printed along with the failure message. Be careful that depending on the calculation, it might make more sense to measure the absolute error or the relative error (see below). **Example of absolute versus relative error** .. code-block:: lua -- convert pi/6 radian to 30 degree pi_div_6_deg_calculated = math.deg(math.pi/6) pi_div_6_deg_expected = 30 -- convert pi/3 radian to 60 degree pi_div_3_deg_calculated = math.deg(math.pi/3) pi_div_3_deg_expected = 60 -- check absolute error: it is not constant print( (pi_div_6_deg_expected - pi_div_6_deg_calculated) / lu.EPS ) -- prints: 16 print( (pi_div_3_deg_expected - pi_div_3_deg_calculated) / lu.EPS ) -- prints: 32 -- Better use relative error: print( ( (pi_div_6_deg_expected - pi_div_6_deg_calculated) / pi_div_6_deg_expected) / lu.EPS ) -- prints: 0.53333 print( ( (pi_div_3_deg_expected - pi_div_3_deg_calculated) / pi_div_3_deg_expected) / lu.EPS ) -- prints: 0.53333 -- relative error is constant. Assertion can take the form of: assertAlmostEquals( (pi_div_6_deg_expected - pi_div_6_deg_calculated) / pi_div_6_deg_expected, lu.EPS ) assertAlmostEquals( (pi_div_3_deg_expected - pi_div_3_deg_calculated) / pi_div_3_deg_expected, lu.EPS ) Pretty printing ---------------- .. function:: prettystr( value ) Converts *value* to a nicely formatted string, whatever the type of the value. It supports in particular tables, nested table and even recursive tables. You can use it in your code to replace calls to *tostring()* . **Example of prettystr()** .. code-block:: > lu = require('luaunit') > t1 = {1,2,3} > t1['toto'] = 'titi' > t1.f = function () end > t1.fa = (1 == 0) > t1.tr = (1 == 1) > print( lu.prettystr(t1) ) {1, 2, 3, f=function: 00635d68, fa=false, toto="titi", tr=true} .. _luaunit-global-asserts: Enabling global or module-level functions ========================================= Versions of LuaUnit before version 3.1 would export all assertions functions to the global namespace. A typical lua test file would look like this: .. code-block:: lua require('luaunit') TestToto = {} --class function TestToto:test1_withFailure() local a = 1 assertEquals( a , 1 ) -- will fail assertEquals( a , 2 ) end [...] However, this is an obsolete practice in Lua. It is now recommended to keep all functions inside the module. Starting from version 3.1 LuaUnit follows this practice and the code should be adapted to look like this: .. code-block:: lua -- the imported module must be stored lu = require('luaunit') TestToto = {} --class function TestToto:test1_withFailure() local a = 1 lu.assertEquals( a , 1 ) -- will fail lu.assertEquals( a , 2 ) end [...] If you prefer the old way, LuaUnit can continue to export assertions functions if you set the following global variable **prior** to importing LuaUnit: .. code-block:: lua -- this works EXPORT_ASSERT_TO_GLOBALS = true require('luaunit') TestToto = {} --class function TestToto:test1_withFailure() local a = 1 assertEquals( a , 1 ) -- will fail assertEquals( a , 2 ) end [...] Variables controlling LuaUnit behavior ========================================= luaunit.ORDER_ACTUAL_EXPECTED ------------------------------ This boolean value defines the order of arguments in assertion functions. For example, in the code `luaunit.assertEquals( a, b )` , LuaUnit will treat by default `a` as a calculated value under test (actual value) and `b` as a reference value aginst which `a` is compared (expected value). This will show up in the error reported for the test: .. code-block:: shell 1) TestWithFailures.testFail1 doc\my_test_suite_with_failures.lua:79: expected: "titi" actual: "toto" If you prefer the opposite convention, i.e having the expected argument as first and actual argument as second, set the *ORDER_ACTUAL_EXPECTED* to *false*. luaunit.PRINT_TABLE_REF_IN_ERROR_MSG ------------------------------------------ This controls whether table references are always printed along with table or not. See `table-printing`_ for details. The default is `false`. .. _strip_extra_entries_in_stack_trace: luaunit.STRIP_EXTRA_ENTRIES_IN_STACK_TRACE ------------------------------------------ This controls how many extra entries in a stack-trace are stripped. By default, LuaUnit hides all its internals functions to show only user code in the error stack trace. However, if LuaUnit is used as part of another test framework, and one wants to also hide this global test framework entries, you can increase the number here. The default is *0* . luaunit.VERSION ------------------------------------------ Current version of LuaUnit as a string. Developing LuaUnit ****************** Development ecosystem ====================== LuaUnit is developed on `GitHub`_. .. _GitHub: https://github.com/bluebird75/luaunit Bugs or feature requests should be reported using `GitHub issues`_. .. _GitHub issues: https://github.com/bluebird75/luaunit/issues LuaUnit is released under the BSD license. This documentation is available at `Read-the-docs`_. .. _Read-the-docs: http://luaunit.readthedocs.org/en/latest/ Contributing ============= You may contribute to LuaUnit by reporting bugs or wishes, or by contributing code directly with a pull request. Some issues on GitHub are marked with label *enhancement*. Feel also free to pick up such tasks and implement them. Changes should be proposed as *Pull Requests* on GitHub. Thank to our continuous integration setup with Travis-Ci and AppVeyor, all unit-tests and functional tests are run on Linux, Windows and MacOs, with all versions of Lua. So any *Pull Request* will show immediately if anything is going unexpected. Running unit-tests ------------------- All proposed changes should pass all unit-tests and if needed, add more unit-tests to cover the bug or the new functionality. Usage is pretty simple: .. code-block:: shell $ lua run_unit_tests.lua ................................................................................ ............................... Ran 111 tests in 0.120 seconds OK Running functional tests ---------------------------- Functional tests also exist to validate LuaUnit. Their management is slightly more complicated. The main goal of functional tests is to validate that LuaUnit output has not been altered. Since LuaUnit supports some standard compliant output (TAP, junitxml), this is very important (and it has been broken in the past). Functional tests perform the following actions: * Run the 2 suites: example_with_luaunit.lua, test_with_err_fail_pass.lua (with various options to have successe, failure and/or errors) * Run every suite with all output format, all verbosity * Validate the XML output with jenkins/hudson and junit schema * Compare the results with the reference output ( archived in test/ref ), with some tricks to make the comparison possible : * adjustment of the file separator to use the same output on Windows and Unix * date and test duration is zeroed so that it does not impact the comparison * adjust the stack trace format which has changed between Lua 5.1, 5.2 and 5.3 * Run some legacy suites or tricky output to manage and verify output: test_with_xml.lua, , compat_luaunit_v2x.lua, legacy_example_with_luaunit.lua For functional tests to run, *diff* must be available on the command line. *xmllint* is needed to perform the xml validation but this step is skipped if *xmllint* can not be found. When functional tests work well, it looks like this: .. code-block:: shell $ lua run_functional_tests.lua ............... Ran 15 tests in 9.676 seconds OK When functional test fail, a diff of the comparison between the reference output and the current output is displayed (it can be quite long). The list of faulty files is summed-up at the end. Modifying reference files for functional tests ----------------------------------------------- The script run_functional_tests.lua supports a --update option, with an optional argument. * *--update* without argument **overwrites all reference output** with the current output. Use only if you know what you are doing, this is usually a very bad idea! * The following argument overwrite a specific subset of reference files, select the one that fits your change: * TestXml: XML output of test_with_xml * ExampleXml: XML output of example_with_luaunit * ExampleTap: TAP output of example_with_luaunit * ExampleText: text output of example_with_luaunit * ExampleNil: nil output of example_with_luaunit * ErrFailPassText: text output of test_with_err_fail_pass * ErrFailPassTap: TAP output of test_with_err_fail_pass * ErrFailPassXml: XML output of test_with_err_fail_pass * StopOnError: errFailPassTextStopOnError-1.txt, -2.txt, -3.txt, -4.txt For example to record a change in the test_with_err_fail_pass output .. code-block:: shell $ lua run_functional_tests.lua --update ErrFailPassXml ErrFailPassTap ErrFailPassText >>>>>>> Generating test/ref/errFailPassXmlDefault.txt >>>>>>> Generating test/ref/errFailPassXmlDefault-success.txt >>>>>>> Generating test/ref/errFailPassXmlDefault-failures.txt >>>>>>> Generating test/ref/errFailPassXmlQuiet.txt >>>>>>> Generating test/ref/errFailPassXmlQuiet-success.txt >>>>>>> Generating test/ref/errFailPassXmlQuiet-failures.txt >>>>>>> Generating test/ref/errFailPassXmlVerbose.txt >>>>>>> Generating test/ref/errFailPassXmlVerbose-success.txt >>>>>>> Generating test/ref/errFailPassXmlVerbose-failures.txt >>>>>>> Generating test/ref/errFailPassTapDefault.txt >>>>>>> Generating test/ref/errFailPassTapDefault-success.txt >>>>>>> Generating test/ref/errFailPassTapDefault-failures.txt >>>>>>> Generating test/ref/errFailPassTapQuiet.txt >>>>>>> Generating test/ref/errFailPassTapQuiet-success.txt >>>>>>> Generating test/ref/errFailPassTapQuiet-failures.txt >>>>>>> Generating test/ref/errFailPassTapVerbose.txt >>>>>>> Generating test/ref/errFailPassTapVerbose-success.txt >>>>>>> Generating test/ref/errFailPassTapVerbose-failures.txt >>>>>>> Generating test/ref/errFailPassTextDefault.txt >>>>>>> Generating test/ref/errFailPassTextDefault-success.txt >>>>>>> Generating test/ref/errFailPassTextDefault-failures.txt >>>>>>> Generating test/ref/errFailPassTextQuiet.txt >>>>>>> Generating test/ref/errFailPassTextQuiet-success.txt >>>>>>> Generating test/ref/errFailPassTextQuiet-failures.txt >>>>>>> Generating test/ref/errFailPassTextVerbose.txt >>>>>>> Generating test/ref/errFailPassTextVerbose-success.txt >>>>>>> Generating test/ref/errFailPassTextVerbose-failures.txt $ You can then commit the new files into git. .. Note :: how to commit updated reference outputs When committing those changes into git, please use if possible an intelligent git committing tool to commit only the interesting changes. With SourceTree or SublimeMerge for example, in case of XML changes, I can select only the lines relevant to the change and avoid committing all the updates to test duration and test datestamp. Typical failures for functional tests --------------------------------------- Functional tests may start failing when: 1. Increasing LuaUnit version 2. Improving or breaking LuaUnit output This a good place to start looking if you see failures occurring. Using doit.py -------------- The utility *doit.py* is a useful developer tool to repeat common developer commands. **Running syntax check** .. code-block:: shell doit.py luacheck Run luacheck on the LuaUnit code. **Running unit-tests** .. code-block:: shell doit.py rununittests Use it to run all unit tests, on all installed versions of Lua on the sytem. **Running all tests** .. code-block:: shell doit.py runtests Run luacheck then run unit-tests then run functional tests. Just like the continuous integration. **Creating documentation** .. code-block:: shell doit.py makedoc Runs sphinx to generate the html documentation. You must have sphinx installed on your path. **Preparing a release** .. code-block:: shell doit.py buildrock Create a rock file ready to be uploaded to luarocks, containing a clone of the current git, with documentation generated README and LICENSE, tests, and everything else stripped out. .. code-block:: shell doit.py packageit Create a zip and tar.gz archive suitable to be uploaded to github. The archive is composed of a clone of the current git content, stripped from everything not related to using luaunit (no CI files, no doit.lu, ...) but with full documentation generated. Process of releasing a new version of LuaUnit ============================================= The steps are the following: * update luaunit with the desired functionality, ready for a release * update the version number in luaunit.lua * update the version number in doit.py * check that all tests pass on all supported lua versions .. code-block:: shell doit.py runtests * update *examples* if needed to reflect new features * update index.rst with documentation of new features/behavior * update README.md and index.rst with the release information (date and content) * generate package for github: .. code-block:: shell doit.py packageit * verify the content of the packages: * documentation must be properly generated * examples should work * unit-tests should pass Annexes ******** .. _table-printing: Annex A: More on table printing ================================ When asserting tables equality, by default, the table content is printed in case of failures. LuaUnit tries to print tables in a readable format. It is possible to always display the table id along with the content, by setting a module parameter PRINT_TABLE_REF_IN_ERROR_MSG . This helps identifying tables: .. code-block:: lua local lu = require('luaunit') local t1 = {1,2,3} -- normally, t1 is dispalyed as: "{1,2,3}" -- if setting this: lu.PRINT_TABLE_REF_IN_ERROR_MSG = true -- display of table t1 becomes: " {1,2,3}" .. Note :: table loops When displaying table content, it is possible to encounter loops, if for example two table references eachother. In such cases, LuaUnit display the full table content once, along with the table id, and displays only the table id for the looping reference. **Example:** displaying a table with reference loop .. code-block:: lua local t1 = {} local t2 = {} t1.t2 = t2 t1.a = {1,2,3} t2.t1 = t1 -- when displaying table t1: -- table t1 inside t2 is only displayed by its id because t1 is already being displayed -- table t2 is displayed along with its id because it is part of a loop. -- t1: " { a={1,2,3}, t2= {t1=} }" .. _comparing-table-keys-table: Annex B: Comparing tables with keys of type table ================================================== There are a few programs out there which use tables as keys for other tables. How to compare such tables is delicate. A small code block is worth a thousand pictures : .. code-block:: lua local lu = require('luaunit') -- let's define two tables t1 = { 1, 2 } t2 = { 1, 2 } lu.assertEquals( t1, t2 ) -- succeeds -- let's define three tables, with the two above tables as keys t3 = { t1='a' } t4 = { t2='a' } t5 = { t2='a' } The difference between t3 and t4 is that they both reference a key with different table references but identical table content. LuaUnit chooses to treat this as two different keys, so t3 and t4 are not considered equal. .. code-block:: lua lu.assertEquals( t3, t4 ) -- fails If using the same table as key, they are now considered equal: .. code-block:: lua lu.assertEquals( t4, t5 ) -- fails .. _Source_code_example: Annex C: Source code of example ================================= Source code of the example used in the `Getting started with LuaUnit`_ .. code-block:: lua -- -- The examples described in the documentation are below. -- lu = require('luaunit') function add(v1,v2) -- add positive numbers -- return 0 if any of the numbers are 0 -- error if any of the two numbers are negative if v1 < 0 or v2 < 0 then error('Can only add positive or null numbers, received '..v1..' and '..v2) end if v1 == 0 or v2 == 0 then return 0 end return v1+v2 end function adder(v) -- return a function that adds v to its argument using add function closure( x ) return x+v end return closure end function div(v1,v2) -- divide positive numbers -- return 0 if any of the numbers are 0 -- error if any of the two numbers are negative if v1 < 0 or v2 < 0 then error('Can only divide positive or null numbers, received '..v1..' and '..v2) end if v1 == 0 or v2 == 0 then return 0 end return v1/v2 end TestAdd = {} function TestAdd:testAddPositive() lu.assertEquals(add(1,1),2) end function TestAdd:testAddZero() lu.assertEquals(add(1,0),0) lu.assertEquals(add(0,5),0) lu.assertEquals(add(0,0),0) end function TestAdd:testAddError() lu.assertErrorMsgContains('Can only add positive or null numbers, received 2 and -3', add, 2, -3) end function TestAdd:testAdder() f = adder(3) lu.assertIsFunction( f ) lu.assertEquals( f(2), 5 ) end -- end of table TestAdd TestDiv = {} function TestDiv:testDivPositive() lu.assertEquals(div(4,2),2) end function TestDiv:testDivZero() lu.assertEquals(div(4,0),0) lu.assertEquals(div(0,5),0) lu.assertEquals(div(0,0),0) end function TestDiv:testDivError() lu.assertErrorMsgContains('Can only divide positive or null numbers, received 2 and -3', div, 2, -3) end -- end of table TestDiv --[[ -- -- Uncomment this section to see how failures are displayed -- TestWithFailures = {} -- two failing tests function TestWithFailures:testFail1() lu.assertEquals( "toto", "titi") end function TestWithFailures:testFail2() local a=1 local b='toto' local c = a + b -- oops, can not add string and numbers return c end -- end of table TestWithFailures ]] --[[ TestLogger = {} function TestLogger:setUp() -- define the fname to use for logging self.fname = 'mytmplog.log' -- make sure the file does not already exists os.remove(self.fname) end function TestLogger:testLoggerCreatesFile() initLog(self.fname) log('toto') f = io.open(self.fname, 'r') lu.assertNotNil( f ) f:close() end function TestLogger:tearDown() self.fname = 'mytmplog.log' -- cleanup our log file after all tests os.remove(self.fname) end -- end of table TestLogger ]] os.exit(lu.LuaUnit.run()) Annex D: BSD License ==================== This software is distributed under the BSD License. Copyright (c) 2005-2018, Philippe Fremy All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Index and Search page ********************** * :ref:`genindex` * :ref:`search` luaunit-LUAUNIT_V3_4/doc/make.bat000066400000000000000000000145031401773523200166320ustar00rootroot00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . set I18NSPHINXOPTS=%SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. texinfo to make Texinfo files echo. gettext to make PO message catalogs echo. changes to make an overview over all changed/added/deprecated items echo. xml to make Docutils-native XML files echo. pseudoxml to make pseudoxml-XML files for display purposes echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) %SPHINXBUILD% 1> nul 2> nul if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\LuaUnit.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\LuaUnit.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdf" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf cd %BUILDDIR%/.. echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "latexpdfja" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex make all-pdf-ja cd %BUILDDIR%/.. echo. echo.Build finished; the PDF files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "texinfo" ( %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo if errorlevel 1 exit /b 1 echo. echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. goto end ) if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 echo. echo.Build finished. The message catalogs are in %BUILDDIR%/locale. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) if "%1" == "xml" ( %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml if errorlevel 1 exit /b 1 echo. echo.Build finished. The XML files are in %BUILDDIR%/xml. goto end ) if "%1" == "pseudoxml" ( %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml if errorlevel 1 exit /b 1 echo. echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. goto end ) :end luaunit-LUAUNIT_V3_4/doc/my_test_suite.lua000066400000000000000000000056321401773523200206300ustar00rootroot00000000000000 -- -- The examples described in the documentation are below. -- lu = require('luaunit') function add(v1,v2) -- add positive numbers -- return 0 if any of the numbers are 0 -- error if any of the two numbers are negative if v1 < 0 or v2 < 0 then error('Can only add positive or null numbers, received '..v1..' and '..v2) end if v1 == 0 or v2 == 0 then return 0 end return v1+v2 end function adder(v) -- return a function that adds v to its argument using add function closure( x ) return x+v end return closure end function div(v1,v2) -- divide positive numbers -- return 0 if any of the numbers are 0 -- error if any of the two numbers are negative if v1 < 0 or v2 < 0 then error('Can only divide positive or null numbers, received '..v1..' and '..v2) end if v1 == 0 or v2 == 0 then return 0 end return v1/v2 end TestAdd = {} function TestAdd:testAddPositive() lu.assertEquals(add(1,1),2) end function TestAdd:testAddZero() lu.assertEquals(add(1,0),0) lu.assertEquals(add(0,5),0) lu.assertEquals(add(0,0),0) end function TestAdd:testAddError() lu.assertErrorMsgContains('Can only add positive or null numbers, received 2 and -3', add, 2, -3) end function TestAdd:testAdder() f = adder(3) lu.assertIsFunction( f ) lu.assertEquals( f(2), 5 ) end -- end of table TestAdd TestDiv = {} function TestDiv:testDivPositive() lu.assertEquals(div(4,2),2) end function TestDiv:testDivZero() lu.assertEquals(div(4,0),0) lu.assertEquals(div(0,5),0) lu.assertEquals(div(0,0),0) end function TestDiv:testDivError() lu.assertErrorMsgContains('Can only divide positive or null numbers, received 2 and -3', div, 2, -3) end -- end of table TestDiv --[[ -- -- Uncomment this section to see how failures are displayed -- TestWithFailures = {} -- two failing tests function TestWithFailures:testFail1() lu.assertEquals( "toto", "titi") end function TestWithFailures:testFail2() local a=1 local b='toto' local c = a + b -- oops, can not add string and numbers return c end -- end of table TestWithFailures ]] --[[ TestLogger = {} function TestLogger:setUp() -- define the fname to use for logging self.fname = 'mytmplog.log' -- make sure the file does not already exists os.remove(self.fname) end function TestLogger:testLoggerCreatesFile() initLog(self.fname) log('toto') f = io.open(self.fname, 'r') lu.assertNotNil( f ) f:close() end function TestLogger:tearDown() self.fname = 'mytmplog.log' -- cleanup our log file after all tests os.remove(self.fname) end -- end of table TestLogger ]] os.exit(lu.LuaUnit.run()) luaunit-LUAUNIT_V3_4/doit.py000066400000000000000000000173271401773523200160000ustar00rootroot00000000000000# My universal runner for this project, the equivalent of a Makefile import subprocess, sys, os, shutil, os.path, glob VERSION='3.4' RELEASE_NAME='luaunit-%s' % VERSION ROCK_RELEASE_NAME='rock-%s' % RELEASE_NAME RELEASE_DIR='release/' + RELEASE_NAME + '/' RELEASE_TAG='LUAUNIT_V' + VERSION.replace('.', '_') TARGET_ZIP=RELEASE_NAME + '.zip' TARGET_TGZ=RELEASE_NAME + '.tgz' REPO_PATH='d:/work/luaunit/luaunit1' PATH_LUACHECK='d:\\program\\dev\\lua\\luarocks\\systree\\bin\\luacheck.bat' LUA51='d:/program/dev/lua/lua51/lua51.exe' LUA52='d:/program/dev/lua/lua52/lua52.exe' LUA53='d:/program/dev/lua/lua53/lua53.exe' LUA54='d:/program/dev/lua/lua54/lua54.exe' LUAJIT='d:/program/dev/lua/luajit/luajit.exe' LUAJIT21='d:/program/dev/lua/luajit21/luajit.exe' ALL_LUA = ( (LUA54, 'Lua 5.4'), (LUA53, 'Lua 5.3'), (LUA52, 'Lua 5.2'), (LUA51, 'Lua 5.1'), (LUAJIT, 'Lua JIT 2.0'), (LUAJIT21, 'Lua JIT 2.1'), ) os.environ["nodosfilewarning"] = "1" def report( s ): print( '[[[[[[[[[[[[[ %s ]]]]]]]]]]]]]' % s ) def run_unit_tests(): '''Run unit-tests with all versions of lua''' for lua, luaversion in ALL_LUA: report( 'Running unit-tests tests with %s' % luaversion ) retcode = subprocess.call( [lua, 'run_unit_tests.lua', '--shuffle'] ) if retcode != 0: report( 'Invalid retcode when running tests: %d' % retcode ) sys.exit( retcode ) def run_tests(with_linting=True): '''Run tests with all versions of lua''' run_luacheck() run_unit_tests() for lua, luaversion in ALL_LUA: report( 'Running functional tests tests with %s' % luaversion ) args = [lua, 'run_functional_tests.lua'] if with_linting: args.append('--with-linting') retcode = subprocess.call( args ) if retcode != 0: report( 'Invalid retcode when running tests: %d' % retcode ) sys.exit( retcode ) report( 'All tests succeed!' ) def run_luacheck(): report('Running luacheck') subprocess.check_call([PATH_LUACHECK, 'example_with_luaunit.lua', 'luaunit.lua', 'run_unit_tests.lua', 'run_functional_tests.lua', 'test/'], shell=True) def run_example(): for lua, luaversion in ALL_LUA: report( 'Running examples with %s' % luaversion ) retcode = subprocess.call( [lua, 'example_with_luaunit.lua'] ) if retcode != 12: report( 'Invalid retcode when running examples: %d' % retcode ) sys.exit( retcode ) report( 'All examples ran!' ) def pre_packageit_or_buildrock_step1(): ''' - create a release directory - export the content of the git project but strips * git stuff * CI stuff (travis, appveyor) * doit.py, todo.txt * junitxml directory * rockspec * build documentation and move the html documentation to just doc ''' # shutil.rmtree('release', True) try: os.mkdir('release') except OSError: pass subprocess.check_call(['d:/program/utils/Git/bin/git.exe', 'clone', '--no-hardlinks', '--branch', RELEASE_TAG, REPO_PATH, RELEASE_DIR]) os.chdir( RELEASE_DIR ) # Release dir cleanup. shutil.rmtree('.git') os.unlink('.gitignore') shutil.rmtree('.travis') os.unlink('.travis.yml') shutil.rmtree('.appveyor') os.unlink('appveyor.yml') os.unlink('doit.py') os.unlink('TODO.txt') shutil.rmtree('junitxml/') for p in glob.glob('*.rockspec'): os.unlink(p) makedoc() # doc cleanup and simplification os.rename( 'doc', 'olddoc' ) shutil.copytree( 'olddoc/html', 'doc') os.unlink('doc/.buildinfo') shutil.copy( 'olddoc/my_test_suite.lua', 'doc') shutil.rmtree('olddoc/') run_tests(False) run_example() os.unlink('.luacheckrc') # keep it to run the tests successfully def packageit(): '''Generate zip and targz archives for a release to GitHub ''' pre_packageit_or_buildrock_step1() # Packaging into zip and tgz os.chdir('..') report('Start packaging') shutil.make_archive(RELEASE_NAME, 'zip', root_dir='.', base_dir=RELEASE_NAME ) shutil.make_archive(RELEASE_NAME, 'gztar', root_dir='.', base_dir=RELEASE_NAME ) report('Zip and tgz ready!') def buildrock(): pre_packageit_or_buildrock_step1() # Packaging into source rocks report('Start preparing rock') shutil.move('test/test_luaunit.lua', '.') shutil.rmtree('test') os.mkdir('test') shutil.move('test_luaunit.lua', 'test') shutil.move('run_unit_tests.lua', 'test') for p in glob.glob('*.lua'): if p == 'luaunit.lua': continue os.unlink(p) os.unlink('README.md') os.unlink('LICENSE.txt') os.chdir('..') shutil.move( RELEASE_NAME, ROCK_RELEASE_NAME ) shutil.make_archive( ROCK_RELEASE_NAME, 'zip', root_dir='.', base_dir=ROCK_RELEASE_NAME ) def help(): print( 'Available actions:') for opt in sorted(OptToFunc.keys()): print( '\t%s' % opt ) def makedoc(): os.chdir('doc') if os.path.exists('html'): shutil.rmtree('html') subprocess.check_call(['make.bat', 'html']) shutil.copytree('_build/html', 'html') os.chdir('..') def rundoctests(): lua = LUA52 for expretcode, l in ( (0, [ '-e', "lu = require('luaunit');os.exit(lu.LuaUnit.run())" ]), (0, [ 'doc/my_test_suite.lua', '-v', 'TestAdd.testAddPositive', 'TestAdd.testAddZero']), (0, [ 'doc/my_test_suite.lua', '-v' ]), (0, [ 'doc/my_test_suite.lua', ]), (0, [ 'doc/my_test_suite.lua', '-o','TAP']), (0, [ 'doc/my_test_suite.lua', 'TestAdd', 'TestDiv.testDivError' , '-v']), (0, [ 'doc/my_test_suite.lua', '-v', '-p', 'Err.r', '-p', 'Z.ro' ]), (0, [ 'doc/my_test_suite.lua', '-v', '--pattern', 'Add', '--exclude', 'Adder', '--pattern', 'Zero' ]), (0, [ 'doc/my_test_suite.lua', '-v', '-x', 'Error', '-x', 'Zero' ]), (2, [ 'doc/my_test_suite_with_failures.lua', '-o', 'text' ]), (2, [ 'doc/my_test_suite_with_failures.lua', '-o', 'text', '--verbose' ]), (2, [ 'doc/my_test_suite_with_failures.lua', '-o', 'tap', '--quiet' ]), (2, [ 'doc/my_test_suite_with_failures.lua', '-o', 'tap' ]), (2, [ 'doc/my_test_suite_with_failures.lua', '-o', 'tap', '--verbose' ]), (2, [ 'doc/my_test_suite_with_failures.lua', '-o', 'nil', '--verbose' ]), ): print( '%s %s' % ('\n$ lua', ' '.join(l).replace('doc/', '') ) ) retcode = subprocess.call( [lua] + l ) if retcode != expretcode: report( 'Invalid luacheck result' ) sys.exit( retcode ) for expretcode, l in ( (2, [ 'doc/my_test_suite_with_failures.lua', '-o', 'junit', '-n', 'toto.xml' ]), ): print( '%s %s' % ('\n$ lua', ' '.join(l).replace('doc/', '') ) ) retcode = subprocess.call( [lua] + l ) if retcode != expretcode: report( 'Invalid luacheck result' ) sys.exit( retcode ) print( open('toto.xml').read() ) OptToFunc = { 'rununittests' : run_unit_tests, 'run_unit_tests': run_unit_tests, # alias 'runtests' : run_tests, 'run_tests' : run_tests, # alis 'luacheck' : run_luacheck, 'runexample' : run_example, 'packageit' : packageit, 'buildrock' : buildrock, 'makedoc' : makedoc, 'rundoctests' : rundoctests, 'help' : help, } if __name__ == '__main__': doingNothing = True for arg in sys.argv[1:]: if arg in OptToFunc: doingNothing = False OptToFunc[arg]() else: print( 'No such action :', arg ) sys.exit(-1) if doingNothing: help() luaunit-LUAUNIT_V3_4/example_with_luaunit.lua000077500000000000000000000072061401773523200214170ustar00rootroot00000000000000#!/usr/bin/env lua local lu = require('luaunit') TestToto = {} --class function TestToto:setUp() -- set up tests self.a = 1 self.s = 'hop' self.t1 = {1,2,3} self.t2 = {one=1,two=2,three=3} self.t3 = {1,2,three=3} end function TestToto:test1_withFailure() -- print( "some stuff test 1" ) lu.assertEquals( self.a , 1 ) -- will fail lu.assertEquals( self.a , 2 ) lu.assertEquals( self.a , 2 ) end function TestToto:test2_withFailure() -- print( "some stuff test 2" ) lu.assertEquals( self.a , 1 ) lu.assertEquals( self.s , 'hop' ) -- will fail lu.assertEquals( self.s , 'bof' ) lu.assertEquals( self.s , 'bof' ) end function TestToto:test3() -- print( "some stuff test 3" ) lu.assertEquals( self.a , 1 ) lu.assertEquals( self.s , 'hop' ) lu.assertEquals( type(self.a), 'number' ) end function TestToto:test4() -- print( "some stuff test 4" ) lu.assertNotEquals( self.a , 1 ) end function TestToto:test5() -- print( "some stuff test 5" ) lu.assertEvalToTrue( self.a ) lu.assertEvalToFalse( self.a ) -- will trigger the failure end function TestToto:test6() -- print( "some stuff test 6" ) lu.assertTrue( true ) lu.assertFalse( false ) lu.assertEvalToFalse( nil ) lu.assertFalse( nil ) -- trigger the failure assertFalse is strict end function TestToto:test7() -- assertEquals( {1,2}, self.t1 ) -- assertEquals( {1,2}, self.t2 ) lu.assertEquals( {1,2}, self.t3 ) end function TestToto:test8a() -- failure occurs in a submethod self:funcWithError() end function TestToto:test8b() -- failure occurs in a submethod self:funcWithFuncWithError() end function TestToto:funcWithFuncWithError() self:funcWithError() end function TestToto:funcWithError() error('Bouhouhoum error!') end function TestToto:test_skipped() local test_conditions_are_met = false lu.skipIf( not test_conditions_are_met, "Test is skipped because ..." ) end -- class TestTiti TestTiti = {} --class function TestTiti:setUp() -- set up tests self.a = 1 self.s = 'hop' -- print( 'TestTiti:setUp' ) end function TestTiti:tearDown() -- some tearDown() code if necessary -- print( 'TestTiti:tearDown' ) end function TestTiti:test1_withFailure() -- print( "some stuff test 1" ) lu.assertEquals( self.a , 1 ) -- will fail lu.assertEquals( self.a , 2 ) lu.assertEquals( self.a , 2 ) end function TestTiti:test2_withFailure() -- print( "some stuff test 2" ) lu.assertEquals( self.a , 1 ) lu.assertEquals( self.s , 'hop' ) -- will fail lu.assertEquals( self.s , 'bof' ) lu.assertEquals( self.s , 'bof' ) end function TestTiti:test3() -- print( "some stuff test 3" ) lu.assertEquals( self.a , 1 ) lu.assertEquals( self.s , 'hop' ) end -- class TestTiti -- simple test functions that were written previously can be integrated -- in luaunit too function test1_withAssertionError() assert( 1 == 1) -- will fail assert( 1 == 2) end function test2_withAssertionError() assert( 'a' == 'a') -- will fail assert( 'a' == 'b') end function test3() assert( 1 == 1) assert( 'a' == 'a') end local runner = lu.LuaUnit.new() runner:setOutputType("text") os.exit( runner:runSuite() ) luaunit-LUAUNIT_V3_4/junitxml/000077500000000000000000000000001401773523200163275ustar00rootroot00000000000000luaunit-LUAUNIT_V3_4/junitxml/Makefile000066400000000000000000000010101401773523200177570ustar00rootroot00000000000000# # junitxml/Makefile # XMLLINT ?= xmllint TEST_APACHE = --noout --schema junit-apache-ant.xsd TEST_JENKINS = --noout --schema junit-jenkins.xsd validate-examples: validate-apache validate-jenkins # This example file is the only one that satisfies the Apache schema validate-apache: example-apache-ant.xml $(XMLLINT) $(TEST_APACHE) $< # The Jenkins schema is more relaxed, and should apply to all .xml files validate-jenkins: $(wildcard *.xml) for file in $^; do $(XMLLINT) $(TEST_JENKINS) $$file || exit 1; done luaunit-LUAUNIT_V3_4/junitxml/XMLJUnitResultFormatter.java.txt000066400000000000000000000225471401773523200245170ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.apache.tools.ant.taskdefs.optional.junit; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.Enumeration; import java.util.Hashtable; import java.util.Properties; import java.util.Date; import java.net.InetAddress; import java.net.UnknownHostException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import junit.framework.AssertionFailedError; import junit.framework.Test; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.util.DOMElementWriter; import org.apache.tools.ant.util.DateUtils; import org.apache.tools.ant.util.FileUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Text; /** * Prints XML output of the test to a specified Writer. * * @see FormatterElement */ public class XMLJUnitResultFormatter implements JUnitResultFormatter, XMLConstants { private static final double ONE_SECOND = 1000.0; /** constant for unnnamed testsuites/cases */ private static final String UNKNOWN = "unknown"; private static DocumentBuilder getDocumentBuilder() { try { return DocumentBuilderFactory.newInstance().newDocumentBuilder(); } catch (Exception exc) { throw new ExceptionInInitializerError(exc); } } /** * The XML document. */ private Document doc; /** * The wrapper for the whole testsuite. */ private Element rootElement; /** * Element for the current test. */ private Hashtable testElements = new Hashtable(); /** * tests that failed. */ private Hashtable failedTests = new Hashtable(); /** * Timing helper. */ private Hashtable testStarts = new Hashtable(); /** * Where to write the log to. */ private OutputStream out; /** No arg constructor. */ public XMLJUnitResultFormatter() { } /** {@inheritDoc}. */ public void setOutput(OutputStream out) { this.out = out; } /** {@inheritDoc}. */ public void setSystemOutput(String out) { formatOutput(SYSTEM_OUT, out); } /** {@inheritDoc}. */ public void setSystemError(String out) { formatOutput(SYSTEM_ERR, out); } /** * The whole testsuite started. * @param suite the testsuite. */ public void startTestSuite(JUnitTest suite) { doc = getDocumentBuilder().newDocument(); rootElement = doc.createElement(TESTSUITE); String n = suite.getName(); rootElement.setAttribute(ATTR_NAME, n == null ? UNKNOWN : n); //add the timestamp final String timestamp = DateUtils.format(new Date(), DateUtils.ISO8601_DATETIME_PATTERN); rootElement.setAttribute(TIMESTAMP, timestamp); //and the hostname. rootElement.setAttribute(HOSTNAME, getHostname()); // Output properties Element propsElement = doc.createElement(PROPERTIES); rootElement.appendChild(propsElement); Properties props = suite.getProperties(); if (props != null) { Enumeration e = props.propertyNames(); while (e.hasMoreElements()) { String name = (String) e.nextElement(); Element propElement = doc.createElement(PROPERTY); propElement.setAttribute(ATTR_NAME, name); propElement.setAttribute(ATTR_VALUE, props.getProperty(name)); propsElement.appendChild(propElement); } } } /** * get the local hostname * @return the name of the local host, or "localhost" if we cannot work it out */ private String getHostname() { try { return InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { return "localhost"; } } /** * The whole testsuite ended. * @param suite the testsuite. * @throws BuildException on error. */ public void endTestSuite(JUnitTest suite) throws BuildException { rootElement.setAttribute(ATTR_TESTS, "" + suite.runCount()); rootElement.setAttribute(ATTR_FAILURES, "" + suite.failureCount()); rootElement.setAttribute(ATTR_ERRORS, "" + suite.errorCount()); rootElement.setAttribute( ATTR_TIME, "" + (suite.getRunTime() / ONE_SECOND)); if (out != null) { Writer wri = null; try { wri = new BufferedWriter(new OutputStreamWriter(out, "UTF8")); wri.write("\n"); (new DOMElementWriter()).write(rootElement, wri, 0, " "); } catch (IOException exc) { throw new BuildException("Unable to write log file", exc); } finally { if (wri != null) { try { wri.flush(); } catch (IOException ex) { // ignore } } if (out != System.out && out != System.err) { FileUtils.close(wri); } } } } /** * Interface TestListener. * *

A new Test is started. * @param t the test. */ public void startTest(Test t) { testStarts.put(t, new Long(System.currentTimeMillis())); } /** * Interface TestListener. * *

A Test is finished. * @param test the test. */ public void endTest(Test test) { // Fix for bug #5637 - if a junit.extensions.TestSetup is // used and throws an exception during setUp then startTest // would never have been called if (!testStarts.containsKey(test)) { startTest(test); } Element currentTest = null; if (!failedTests.containsKey(test)) { currentTest = doc.createElement(TESTCASE); String n = JUnitVersionHelper.getTestCaseName(test); currentTest.setAttribute(ATTR_NAME, n == null ? UNKNOWN : n); // a TestSuite can contain Tests from multiple classes, // even tests with the same name - disambiguate them. currentTest.setAttribute(ATTR_CLASSNAME, JUnitVersionHelper.getTestCaseClassName(test)); rootElement.appendChild(currentTest); testElements.put(test, currentTest); } else { currentTest = (Element) testElements.get(test); } Long l = (Long) testStarts.get(test); currentTest.setAttribute(ATTR_TIME, "" + ((System.currentTimeMillis() - l.longValue()) / ONE_SECOND)); } /** * Interface TestListener for JUnit <= 3.4. * *

A Test failed. * @param test the test. * @param t the exception. */ public void addFailure(Test test, Throwable t) { formatError(FAILURE, test, t); } /** * Interface TestListener for JUnit > 3.4. * *

A Test failed. * @param test the test. * @param t the assertion. */ public void addFailure(Test test, AssertionFailedError t) { addFailure(test, (Throwable) t); } /** * Interface TestListener. * *

An error occurred while running the test. * @param test the test. * @param t the error. */ public void addError(Test test, Throwable t) { formatError(ERROR, test, t); } private void formatError(String type, Test test, Throwable t) { if (test != null) { endTest(test); failedTests.put(test, test); } Element nested = doc.createElement(type); Element currentTest = null; if (test != null) { currentTest = (Element) testElements.get(test); } else { currentTest = rootElement; } currentTest.appendChild(nested); String message = t.getMessage(); if (message != null && message.length() > 0) { nested.setAttribute(ATTR_MESSAGE, t.getMessage()); } nested.setAttribute(ATTR_TYPE, t.getClass().getName()); String strace = JUnitTestRunner.getFilteredTrace(t); Text trace = doc.createTextNode(strace); nested.appendChild(trace); } private void formatOutput(String type, String output) { Element nested = doc.createElement(type); rootElement.appendChild(nested); nested.appendChild(doc.createCDATASection(output)); } } // XMLJUnitResultFormatter luaunit-LUAUNIT_V3_4/junitxml/example-apache-ant.xml000066400000000000000000000021751401773523200225100ustar00rootroot00000000000000 Detailed failure content Detailed error content bla bla output bla bla bla bla error bla bla luaunit-LUAUNIT_V3_4/junitxml/example-bamboo-1.xml000077500000000000000000000124471401773523200221120ustar00rootroot00000000000000 junit.framework.AssertionFailedError: Should not have any errors. [Perforce client error:, Connect to server failed; check $P4PORT., TCP connect to keg failed., keg: host unknown.] expected:<0> but was:<4> at junit.framework.Assert.fail(Assert.java:47) at junit.framework.Assert.failNotEquals(Assert.java:282) at junit.framework.Assert.assertEquals(Assert.java:64) at junit.framework.Assert.assertEquals(Assert.java:201) at com.atlassian.bamboo.repository.perforce.PerforceSyncCommandTest.testUsingPerforceWhenNoFilesHaveChanged(PerforceSyncCommandTest.java:60) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at junit.framework.TestCase.runTest(TestCase.java:154) at junit.framework.TestCase.runBare(TestCase.java:127) at junit.framework.TestResult$1.protect(TestResult.java:106) at junit.framework.TestResult.runProtected(TestResult.java:124) at junit.framework.TestResult.run(TestResult.java:109) at junit.framework.TestCase.run(TestCase.java:118) at junit.framework.TestSuite.runTest(TestSuite.java:208) at junit.framework.TestSuite.run(TestSuite.java:203) at sun.reflect.GeneratedMethodAccessor17.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at org.apache.maven.surefire.battery.JUnitBattery.executeJUnit(JUnitBattery.java:242) at org.apache.maven.surefire.battery.JUnitBattery.execute(JUnitBattery.java:216) at org.apache.maven.surefire.Surefire.executeBattery(Surefire.java:215) at org.apache.maven.surefire.Surefire.run(Surefire.java:163) at org.apache.maven.surefire.Surefire.run(Surefire.java:87) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at org.apache.maven.surefire.SurefireBooter.runTestsInProcess(SurefireBooter.java:313) at org.apache.maven.surefire.SurefireBooter.run(SurefireBooter.java:221) at org.apache.maven.test.SurefirePlugin.execute(SurefirePlugin.java:371) at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:412) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:534) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalWithLifecycle(DefaultLifecycleExecutor.java:475) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:454) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:306) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:273) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:140) at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:322) at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:115) at org.apache.maven.cli.MavenCli.main(MavenCli.java:256) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315) at org.codehaus.classworlds.Launcher.launch(Launcher.java:255) at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430) at org.codehaus.classworlds.Launcher.main(Launcher.java:375) PerforceSyncCommand.command: /usr/local/bin/p4 luaunit-LUAUNIT_V3_4/junitxml/example-bamboo-2.xml000066400000000000000000000071151401773523200221040ustar00rootroot00000000000000 luaunit-LUAUNIT_V3_4/junitxml/example-jenkins.xml000066400000000000000000000022271401773523200221460ustar00rootroot00000000000000 bla bla Detailed failure content Detailed error content bla bla output bla bla bla bla error bla bla luaunit-LUAUNIT_V3_4/junitxml/junit-apache-ant.xsd000066400000000000000000000215741401773523200222100ustar00rootroot00000000000000 JUnit test result schema for the Apache Ant JUnit and JUnitReport tasks Copyright © 2011, Windy Road Technology Pty. Limited The Apache Ant JUnit XML Schema is distributed under the terms of the GNU Lesser General Public License (LGPL) http://www.gnu.org/licenses/lgpl.html Permission to waive conditions of this license may be requested from Windy Road Support (http://windyroad.org/support). Contains an aggregation of testsuite results Derived from testsuite/@name in the non-aggregated documents Starts at '0' for the first testsuite and is incremented by 1 for each following testsuite Contains the results of exexuting a testsuite Properties (e.g., environment settings) set during test execution Indicates that the test errored. An errored test is one that had an unanticipated problem. e.g., an unchecked throwable; or a problem with the implementation of the test. Contains as a text node relevant data for the error, e.g., a stack trace The error message. e.g., if a java exception is thrown, the return value of getMessage() The type of error that occured. e.g., if a java execption is thrown the full class name of the exception. Indicates that the test failed. A failure is a test which the code has explicitly failed by using the mechanisms for that purpose. e.g., via an assertEquals. Contains as a text node relevant data for the failure, e.g., a stack trace The message specified in the assert The type of the assert. Name of the test method Full class name for the class the test method is in. Time taken (in seconds) to execute the test Data that was written to standard out while the test was executed Data that was written to standard error while the test was executed Full class name of the test for non-aggregated testsuite documents. Class name without the package for aggregated testsuites documents when the test was executed. Timezone may not be specified. Host on which the tests were executed. 'localhost' should be used if the hostname cannot be determined. The total number of tests in the suite The total number of tests in the suite that failed. A failure is a test which the code has explicitly failed by using the mechanisms for that purpose. e.g., via an assertEquals The total number of tests in the suite that errorrd. An errored test is one that had an unanticipated problem. e.g., an unchecked throwable; or a problem with the implementation of the test. Time taken (in seconds) to execute the tests in the suite luaunit-LUAUNIT_V3_4/junitxml/junit-jenkins.xsd000066400000000000000000000100651401773523200216410ustar00rootroot00000000000000 luaunit-LUAUNIT_V3_4/junitxml/notes-junit-compatibility.txt000066400000000000000000000023711401773523200242210ustar00rootroot00000000000000Our source information: https://github.com/windyroad/JUnit-Schema * http://stackoverflow.com/questions/4922867/junit-xml-format-specification-that-hudson-supports (Jenkins) * https://github.com/jenkinsci/xunit-plugin/tree/master/src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd * http://help.catchsoftware.com/display/ET/JUnit+Format * http://llg.cubic.org/docs/junit/ * https://confluence.atlassian.com/bamboo/junit-parsing-in-bamboo-289277357.html * http://nose2.readthedocs.io/en/latest/plugins/junitxml.html * https://pzolee.blogs.balabit.com/2012/11/jenkins-vs-junit-xml-format/ * https://www.relishapp.com/cucumber/cucumber/docs/formatters/junit-output-formatter * http://stackoverflow.com/questions/11241781/python-unittests-in-jenkins * https://github.com/xmlrunner/unittest-xml-reporting/tree/master/ Notes: ====== Ant xml schema is much more restrictive than jenkins. Non allowed fields in ant, allowed in jenkins: testsuites: - apache ant forbids all attributes. testsuite: - apache ant forbids attributes: disabled, skipped - apache ant allows elements system-out and system-err, that are in testcase for jenkins testcase: - apache ant forbids attributes: assertions, status - apache ant forbids elements: skipped, system-out, system-err luaunit-LUAUNIT_V3_4/luaunit-3.4-1.rockspec000066400000000000000000000026501401773523200203340ustar00rootroot00000000000000package = "LuaUnit" version = "3.4-1" source = { url = 'https://github.com/bluebird75/luaunit/releases/download/LUAUNIT_V3_4/rock-luaunit-3.4.zip' } description = { summary = "A unit testing framework for Lua", detailed = [[ LuaUnit is a popular unit-testing framework for Lua, with an interface typical of xUnit libraries (Python unittest, Junit, NUnit, ...). It supports several output formats (Text, TAP, JUnit, ...) to be used directly or work with Continuous Integration platforms (Jenkins, Hudson, ...). For simplicity, LuaUnit is contained into a single-file and has no external dependency. Tutorial and reference documentation is available on [read-the-docs](http://luaunit.readthedocs.org/en/latest/) LuaUnit may also be used as an assertion library, to validate assertions inside a running program. In addition, it provides a pretty stringifier which converts any type into a nicely formatted string (including complex nested or recursive tables). To install LuaUnit from LuaRocks, you need at least LuaRocks version 2.4.4 (due to old versions of wget being incompatible with GitHub https downloading) ]], homepage = "http://github.com/bluebird75/luaunit", license = "BSD", maintainer = 'Philippe Fremy ', } dependencies = { "lua >= 5.1", "lua < 5.5" } build = { type = "builtin", modules = { luaunit = "luaunit.lua" }, copy_directories = { "doc", "test" } } luaunit-LUAUNIT_V3_4/luaunit.lua000077500000000000000000003671331401773523200166610ustar00rootroot00000000000000--[[ luaunit.lua Description: A unit testing framework Homepage: https://github.com/bluebird75/luaunit Development by Philippe Fremy Based on initial work of Ryu, Gwang (http://www.gpgstudy.com/gpgiki/LuaUnit) License: BSD License, see LICENSE.txt ]]-- require("math") local M={} -- private exported functions (for testing) M.private = {} M.VERSION='3.4' M._VERSION=M.VERSION -- For LuaUnit v2 compatibility -- a version which distinguish between regular Lua and LuaJit M._LUAVERSION = (jit and jit.version) or _VERSION --[[ Some people like assertEquals( actual, expected ) and some people prefer assertEquals( expected, actual ). ]]-- M.ORDER_ACTUAL_EXPECTED = true M.PRINT_TABLE_REF_IN_ERROR_MSG = false M.LINE_LENGTH = 80 M.TABLE_DIFF_ANALYSIS_THRESHOLD = 10 -- display deep analysis for more than 10 items M.LIST_DIFF_ANALYSIS_THRESHOLD = 10 -- display deep analysis for more than 10 items -- this setting allow to remove entries from the stack-trace, for -- example to hide a call to a framework which would be calling luaunit M.STRIP_EXTRA_ENTRIES_IN_STACK_TRACE = 0 --[[ EPS is meant to help with Lua's floating point math in simple corner cases like almostEquals(1.1-0.1, 1), which may not work as-is (e.g. on numbers with rational binary representation) if the user doesn't provide some explicit error margin. The default margin used by almostEquals() in such cases is EPS; and since Lua may be compiled with different numeric precisions (single vs. double), we try to select a useful default for it dynamically. Note: If the initial value is not acceptable, it can be changed by the user to better suit specific needs. See also: https://en.wikipedia.org/wiki/Machine_epsilon ]] M.EPS = 2^-52 -- = machine epsilon for "double", ~2.22E-16 if math.abs(1.1 - 1 - 0.1) > M.EPS then -- rounding error is above EPS, assume single precision M.EPS = 2^-23 -- = machine epsilon for "float", ~1.19E-07 end -- set this to false to debug luaunit local STRIP_LUAUNIT_FROM_STACKTRACE = true M.VERBOSITY_DEFAULT = 10 M.VERBOSITY_LOW = 1 M.VERBOSITY_QUIET = 0 M.VERBOSITY_VERBOSE = 20 M.DEFAULT_DEEP_ANALYSIS = nil M.FORCE_DEEP_ANALYSIS = true M.DISABLE_DEEP_ANALYSIS = false -- set EXPORT_ASSERT_TO_GLOBALS to have all asserts visible as global values -- EXPORT_ASSERT_TO_GLOBALS = true -- we need to keep a copy of the script args before it is overriden local cmdline_argv = rawget(_G, "arg") M.FAILURE_PREFIX = 'LuaUnit test FAILURE: ' -- prefix string for failed tests M.SUCCESS_PREFIX = 'LuaUnit test SUCCESS: ' -- prefix string for successful tests finished early M.SKIP_PREFIX = 'LuaUnit test SKIP: ' -- prefix string for skipped tests M.USAGE=[[Usage: lua [options] [testname1 [testname2] ... ] Options: -h, --help: Print this help --version: Print version information -v, --verbose: Increase verbosity -q, --quiet: Set verbosity to minimum -e, --error: Stop on first error -f, --failure: Stop on first failure or error -s, --shuffle: Shuffle tests before running them -o, --output OUTPUT: Set output type to OUTPUT Possible values: text, tap, junit, nil -n, --name NAME: For junit only, mandatory name of xml file -r, --repeat NUM: Execute all tests NUM times, e.g. to trig the JIT -p, --pattern PATTERN: Execute all test names matching the Lua PATTERN May be repeated to include several patterns Make sure you escape magic chars like +? with % -x, --exclude PATTERN: Exclude all test names matching the Lua PATTERN May be repeated to exclude several patterns Make sure you escape magic chars like +? with % testname1, testname2, ... : tests to run in the form of testFunction, TestClass or TestClass.testMethod You may also control LuaUnit options with the following environment variables: * LUAUNIT_OUTPUT: same as --output * LUAUNIT_JUNIT_FNAME: same as --name ]] ---------------------------------------------------------------- -- -- general utility functions -- ---------------------------------------------------------------- --[[ Note on catching exit I have seen the case where running a big suite of test cases and one of them would perform a os.exit(0), making the outside world think that the full test suite was executed successfully. This is an attempt to mitigate this problem: we override os.exit() to now let a test exit the framework while we are running. When we are not running, it behaves normally. ]] M.oldOsExit = os.exit os.exit = function(...) if M.LuaUnit and #M.LuaUnit.instances ~= 0 then local msg = [[You are trying to exit but there is still a running instance of LuaUnit. LuaUnit expects to run until the end before exiting with a complete status of successful/failed tests. To force exit LuaUnit while running, please call before os.exit (assuming lu is the luaunit module loaded): lu.unregisterCurrentSuite() ]] M.private.error_fmt(2, msg) end M.oldOsExit(...) end local function pcall_or_abort(func, ...) -- unpack is a global function for Lua 5.1, otherwise use table.unpack local unpack = rawget(_G, "unpack") or table.unpack local result = {pcall(func, ...)} if not result[1] then -- an error occurred print(result[2]) -- error message print() print(M.USAGE) os.exit(-1) end return unpack(result, 2) end local crossTypeOrdering = { number = 1, boolean = 2, string = 3, table = 4, other = 5 } local crossTypeComparison = { number = function(a, b) return a < b end, string = function(a, b) return a < b end, other = function(a, b) return tostring(a) < tostring(b) end, } local function crossTypeSort(a, b) local type_a, type_b = type(a), type(b) if type_a == type_b then local func = crossTypeComparison[type_a] or crossTypeComparison.other return func(a, b) end type_a = crossTypeOrdering[type_a] or crossTypeOrdering.other type_b = crossTypeOrdering[type_b] or crossTypeOrdering.other return type_a < type_b end local function __genSortedIndex( t ) -- Returns a sequence consisting of t's keys, sorted. local sortedIndex = {} for key,_ in pairs(t) do table.insert(sortedIndex, key) end table.sort(sortedIndex, crossTypeSort) return sortedIndex end M.private.__genSortedIndex = __genSortedIndex local function sortedNext(state, control) -- Equivalent of the next() function of table iteration, but returns the -- keys in sorted order (see __genSortedIndex and crossTypeSort). -- The state is a temporary variable during iteration and contains the -- sorted key table (state.sortedIdx). It also stores the last index (into -- the keys) used by the iteration, to find the next one quickly. local key --print("sortedNext: control = "..tostring(control) ) if control == nil then -- start of iteration state.count = #state.sortedIdx state.lastIdx = 1 key = state.sortedIdx[1] return key, state.t[key] end -- normally, we expect the control variable to match the last key used if control ~= state.sortedIdx[state.lastIdx] then -- strange, we have to find the next value by ourselves -- the key table is sorted in crossTypeSort() order! -> use bisection local lower, upper = 1, state.count repeat state.lastIdx = math.modf((lower + upper) / 2) key = state.sortedIdx[state.lastIdx] if key == control then break -- key found (and thus prev index) end if crossTypeSort(key, control) then -- key < control, continue search "right" (towards upper bound) lower = state.lastIdx + 1 else -- key > control, continue search "left" (towards lower bound) upper = state.lastIdx - 1 end until lower > upper if lower > upper then -- only true if the key wasn't found, ... state.lastIdx = state.count -- ... so ensure no match in code below end end -- proceed by retrieving the next value (or nil) from the sorted keys state.lastIdx = state.lastIdx + 1 key = state.sortedIdx[state.lastIdx] if key then return key, state.t[key] end -- getting here means returning `nil`, which will end the iteration end local function sortedPairs(tbl) -- Equivalent of the pairs() function on tables. Allows to iterate in -- sorted order. As required by "generic for" loops, this will return the -- iterator (function), an "invariant state", and the initial control value. -- (see http://www.lua.org/pil/7.2.html) return sortedNext, {t = tbl, sortedIdx = __genSortedIndex(tbl)}, nil end M.private.sortedPairs = sortedPairs -- seed the random with a strongly varying seed math.randomseed(math.floor(os.clock()*1E11)) local function randomizeTable( t ) -- randomize the item orders of the table t for i = #t, 2, -1 do local j = math.random(i) if i ~= j then t[i], t[j] = t[j], t[i] end end end M.private.randomizeTable = randomizeTable local function strsplit(delimiter, text) -- Split text into a list consisting of the strings in text, separated -- by strings matching delimiter (which may _NOT_ be a pattern). -- Example: strsplit(", ", "Anna, Bob, Charlie, Dolores") if delimiter == "" or delimiter == nil then -- this would result in endless loops error("delimiter is nil or empty string!") end if text == nil then return nil end local list, pos, first, last = {}, 1 while true do first, last = text:find(delimiter, pos, true) if first then -- found? table.insert(list, text:sub(pos, first - 1)) pos = last + 1 else table.insert(list, text:sub(pos)) break end end return list end M.private.strsplit = strsplit local function hasNewLine( s ) -- return true if s has a newline return (string.find(s, '\n', 1, true) ~= nil) end M.private.hasNewLine = hasNewLine local function prefixString( prefix, s ) -- Prefix all the lines of s with prefix return prefix .. string.gsub(s, '\n', '\n' .. prefix) end M.private.prefixString = prefixString local function strMatch(s, pattern, start, final ) -- return true if s matches completely the pattern from index start to index end -- return false in every other cases -- if start is nil, matches from the beginning of the string -- if final is nil, matches to the end of the string start = start or 1 final = final or string.len(s) local foundStart, foundEnd = string.find(s, pattern, start, false) return foundStart == start and foundEnd == final end M.private.strMatch = strMatch local function patternFilter(patterns, expr) -- Run `expr` through the inclusion and exclusion rules defined in patterns -- and return true if expr shall be included, false for excluded. -- Inclusion pattern are defined as normal patterns, exclusions -- patterns start with `!` and are followed by a normal pattern -- result: nil = UNKNOWN (not matched yet), true = ACCEPT, false = REJECT -- default: true if no explicit "include" is found, set to false otherwise local default, result = true, nil if patterns ~= nil then for _, pattern in ipairs(patterns) do local exclude = pattern:sub(1,1) == '!' if exclude then pattern = pattern:sub(2) else -- at least one include pattern specified, a match is required default = false end -- print('pattern: ',pattern) -- print('exclude: ',exclude) -- print('default: ',default) if string.find(expr, pattern) then -- set result to false when excluding, true otherwise result = not exclude end end end if result ~= nil then return result end return default end M.private.patternFilter = patternFilter local function xmlEscape( s ) -- Return s escaped for XML attributes -- escapes table: -- " " -- ' ' -- < < -- > > -- & & return string.gsub( s, '.', { ['&'] = "&", ['"'] = """, ["'"] = "'", ['<'] = "<", ['>'] = ">", } ) end M.private.xmlEscape = xmlEscape local function xmlCDataEscape( s ) -- Return s escaped for CData section, escapes: "]]>" return string.gsub( s, ']]>', ']]>' ) end M.private.xmlCDataEscape = xmlCDataEscape local function lstrip( s ) --[[Return s with all leading white spaces and tabs removed]] local idx = 0 while idx < s:len() do idx = idx + 1 local c = s:sub(idx,idx) if c ~= ' ' and c ~= '\t' then break end end return s:sub(idx) end M.private.lstrip = lstrip local function extractFileLineInfo( s ) --[[ From a string in the form "(leading spaces) dir1/dir2\dir3\file.lua:linenb: msg" Return the "file.lua:linenb" information ]] local s2 = lstrip(s) local firstColon = s2:find(':', 1, true) if firstColon == nil then -- string is not in the format file:line: return s end local secondColon = s2:find(':', firstColon+1, true) if secondColon == nil then -- string is not in the format file:line: return s end return s2:sub(1, secondColon-1) end M.private.extractFileLineInfo = extractFileLineInfo local function stripLuaunitTrace2( stackTrace, errMsg ) --[[ -- Example of a traceback: < [C]: in function 'xpcall' ./luaunit.lua:1449: in function 'protectedCall' ./luaunit.lua:1508: in function 'execOneFunction' ./luaunit.lua:1596: in function 'runSuiteByInstances' ./luaunit.lua:1660: in function 'runSuiteByNames' ./luaunit.lua:1736: in function 'runSuite' example_with_luaunit.lua:140: in main chunk [C]: in ?>> error message: <> Other example: < [C]: in function 'xpcall' ./luaunit.lua:1517: in function 'protectedCall' ./luaunit.lua:1578: in function 'execOneFunction' ./luaunit.lua:1677: in function 'runSuiteByInstances' ./luaunit.lua:1730: in function 'runSuiteByNames' ./luaunit.lua:1806: in function 'runSuite' example_with_luaunit.lua:140: in main chunk [C]: in ?>> error message: <> < [C]: in function 'xpcall' luaunit2/luaunit.lua:1532: in function 'protectedCall' luaunit2/luaunit.lua:1591: in function 'execOneFunction' luaunit2/luaunit.lua:1679: in function 'runSuiteByInstances' luaunit2/luaunit.lua:1743: in function 'runSuiteByNames' luaunit2/luaunit.lua:1819: in function 'runSuite' luaunit2/example_with_luaunit.lua:140: in main chunk [C]: in ?>> error message: <> -- first line is "stack traceback": KEEP -- next line may be luaunit line: REMOVE -- next lines are call in the program under testOk: REMOVE -- next lines are calls from luaunit to call the program under test: KEEP -- Strategy: -- keep first line -- remove lines that are part of luaunit -- kepp lines until we hit a luaunit line The strategy for stripping is: * keep first line "stack traceback:" * part1: * analyse all lines of the stack from bottom to top of the stack (first line to last line) * extract the "file:line:" part of the line * compare it with the "file:line" part of the error message * if it does not match strip the line * if it matches, keep the line and move to part 2 * part2: * anything NOT starting with luaunit.lua is the interesting part of the stack trace * anything starting again with luaunit.lua is part of the test launcher and should be stripped out ]] local function isLuaunitInternalLine( s ) -- return true if line of stack trace comes from inside luaunit return s:find('[/\\]luaunit%.lua:%d+: ') ~= nil end -- print( '<<'..stackTrace..'>>' ) local t = strsplit( '\n', stackTrace ) -- print( prettystr(t) ) local idx = 2 local errMsgFileLine = extractFileLineInfo(errMsg) -- print('emfi="'..errMsgFileLine..'"') -- remove lines that are still part of luaunit while t[idx] and extractFileLineInfo(t[idx]) ~= errMsgFileLine do -- print('Removing : '..t[idx] ) table.remove(t, idx) end -- keep lines until we hit luaunit again while t[idx] and (not isLuaunitInternalLine(t[idx])) do -- print('Keeping : '..t[idx] ) idx = idx + 1 end -- remove remaining luaunit lines while t[idx] do -- print('Removing2 : '..t[idx] ) table.remove(t, idx) end -- print( prettystr(t) ) return table.concat( t, '\n') end M.private.stripLuaunitTrace2 = stripLuaunitTrace2 local function prettystr_sub(v, indentLevel, printTableRefs, cycleDetectTable ) local type_v = type(v) if "string" == type_v then -- use clever delimiters according to content: -- enclose with single quotes if string contains ", but no ' if v:find('"', 1, true) and not v:find("'", 1, true) then return "'" .. v .. "'" end -- use double quotes otherwise, escape embedded " return '"' .. v:gsub('"', '\\"') .. '"' elseif "table" == type_v then --if v.__class__ then -- return string.gsub( tostring(v), 'table', v.__class__ ) --end return M.private._table_tostring(v, indentLevel, printTableRefs, cycleDetectTable) elseif "number" == type_v then -- eliminate differences in formatting between various Lua versions if v ~= v then return "#NaN" -- "not a number" end if v == math.huge then return "#Inf" -- "infinite" end if v == -math.huge then return "-#Inf" end if _VERSION == "Lua 5.3" then local i = math.tointeger(v) if i then return tostring(i) end end end return tostring(v) end local function prettystr( v ) --[[ Pretty string conversion, to display the full content of a variable of any type. * string are enclosed with " by default, or with ' if string contains a " * tables are expanded to show their full content, with indentation in case of nested tables ]]-- local cycleDetectTable = {} local s = prettystr_sub(v, 1, M.PRINT_TABLE_REF_IN_ERROR_MSG, cycleDetectTable) if cycleDetectTable.detected and not M.PRINT_TABLE_REF_IN_ERROR_MSG then -- some table contain recursive references, -- so we must recompute the value by including all table references -- else the result looks like crap cycleDetectTable = {} s = prettystr_sub(v, 1, true, cycleDetectTable) end return s end M.prettystr = prettystr function M.adjust_err_msg_with_iter( err_msg, iter_msg ) --[[ Adjust the error message err_msg: trim the FAILURE_PREFIX or SUCCESS_PREFIX information if needed, add the iteration message if any and return the result. err_msg: string, error message captured with pcall iter_msg: a string describing the current iteration ("iteration N") or nil if there is no iteration in this test. Returns: (new_err_msg, test_status) new_err_msg: string, adjusted error message, or nil in case of success test_status: M.NodeStatus.FAIL, SUCCESS or ERROR according to the information contained in the error message. ]] if iter_msg then iter_msg = iter_msg..', ' else iter_msg = '' end local RE_FILE_LINE = '.*:%d+: ' -- error message is not necessarily a string, -- so convert the value to string with prettystr() if type( err_msg ) ~= 'string' then err_msg = prettystr( err_msg ) end if (err_msg:find( M.SUCCESS_PREFIX ) == 1) or err_msg:match( '('..RE_FILE_LINE..')' .. M.SUCCESS_PREFIX .. ".*" ) then -- test finished early with success() return nil, M.NodeStatus.SUCCESS end if (err_msg:find( M.SKIP_PREFIX ) == 1) or (err_msg:match( '('..RE_FILE_LINE..')' .. M.SKIP_PREFIX .. ".*" ) ~= nil) then -- substitute prefix by iteration message err_msg = err_msg:gsub('.*'..M.SKIP_PREFIX, iter_msg, 1) -- print("failure detected") return err_msg, M.NodeStatus.SKIP end if (err_msg:find( M.FAILURE_PREFIX ) == 1) or (err_msg:match( '('..RE_FILE_LINE..')' .. M.FAILURE_PREFIX .. ".*" ) ~= nil) then -- substitute prefix by iteration message err_msg = err_msg:gsub(M.FAILURE_PREFIX, iter_msg, 1) -- print("failure detected") return err_msg, M.NodeStatus.FAIL end -- print("error detected") -- regular error, not a failure if iter_msg then local match -- "./test\\test_luaunit.lua:2241: some error msg match = err_msg:match( '(.*:%d+: ).*' ) if match then err_msg = err_msg:gsub( match, match .. iter_msg ) else -- no file:line: infromation, just add the iteration info at the beginning of the line err_msg = iter_msg .. err_msg end end return err_msg, M.NodeStatus.ERROR end local function tryMismatchFormatting( table_a, table_b, doDeepAnalysis, margin ) --[[ Prepares a nice error message when comparing tables, performing a deeper analysis. Arguments: * table_a, table_b: tables to be compared * doDeepAnalysis: M.DEFAULT_DEEP_ANALYSIS: (the default if not specified) perform deep analysis only for big lists and big dictionnaries M.FORCE_DEEP_ANALYSIS : always perform deep analysis M.DISABLE_DEEP_ANALYSIS: never perform deep analysis * margin: supplied only for almost equality Returns: {success, result} * success: false if deep analysis could not be performed in this case, just use standard assertion message * result: if success is true, a multi-line string with deep analysis of the two lists ]] -- check if table_a & table_b are suitable for deep analysis if type(table_a) ~= 'table' or type(table_b) ~= 'table' then return false end if doDeepAnalysis == M.DISABLE_DEEP_ANALYSIS then return false end local len_a, len_b, isPureList = #table_a, #table_b, true for k1, v1 in pairs(table_a) do if type(k1) ~= 'number' or k1 > len_a then -- this table a mapping isPureList = false break end end if isPureList then for k2, v2 in pairs(table_b) do if type(k2) ~= 'number' or k2 > len_b then -- this table a mapping isPureList = false break end end end if isPureList and math.min(len_a, len_b) < M.LIST_DIFF_ANALYSIS_THRESHOLD then if not (doDeepAnalysis == M.FORCE_DEEP_ANALYSIS) then return false end end if isPureList then return M.private.mismatchFormattingPureList( table_a, table_b, margin ) else -- only work on mapping for the moment -- return M.private.mismatchFormattingMapping( table_a, table_b, doDeepAnalysis ) return false end end M.private.tryMismatchFormatting = tryMismatchFormatting local function getTaTbDescr() if not M.ORDER_ACTUAL_EXPECTED then return 'expected', 'actual' end return 'actual', 'expected' end local function extendWithStrFmt( res, ... ) table.insert( res, string.format( ... ) ) end local function mismatchFormattingMapping( table_a, table_b, doDeepAnalysis ) --[[ Prepares a nice error message when comparing tables which are not pure lists, performing a deeper analysis. Returns: {success, result} * success: false if deep analysis could not be performed in this case, just use standard assertion message * result: if success is true, a multi-line string with deep analysis of the two lists ]] -- disable for the moment --[[ local result = {} local descrTa, descrTb = getTaTbDescr() local keysCommon = {} local keysOnlyTa = {} local keysOnlyTb = {} local keysDiffTaTb = {} local k, v for k,v in pairs( table_a ) do if is_equal( v, table_b[k] ) then table.insert( keysCommon, k ) else if table_b[k] == nil then table.insert( keysOnlyTa, k ) else table.insert( keysDiffTaTb, k ) end end end for k,v in pairs( table_b ) do if not is_equal( v, table_a[k] ) and table_a[k] == nil then table.insert( keysOnlyTb, k ) end end local len_a = #keysCommon + #keysDiffTaTb + #keysOnlyTa local len_b = #keysCommon + #keysDiffTaTb + #keysOnlyTb local limited_display = (len_a < 5 or len_b < 5) if math.min(len_a, len_b) < M.TABLE_DIFF_ANALYSIS_THRESHOLD then return false end if not limited_display then if len_a == len_b then extendWithStrFmt( result, 'Table A (%s) and B (%s) both have %d items', descrTa, descrTb, len_a ) else extendWithStrFmt( result, 'Table A (%s) has %d items and table B (%s) has %d items', descrTa, len_a, descrTb, len_b ) end if #keysCommon == 0 and #keysDiffTaTb == 0 then table.insert( result, 'Table A and B have no keys in common, they are totally different') else local s_other = 'other ' if #keysCommon then extendWithStrFmt( result, 'Table A and B have %d identical items', #keysCommon ) else table.insert( result, 'Table A and B have no identical items' ) s_other = '' end if #keysDiffTaTb ~= 0 then result[#result] = string.format( '%s and %d items differing present in both tables', result[#result], #keysDiffTaTb) else result[#result] = string.format( '%s and no %sitems differing present in both tables', result[#result], s_other, #keysDiffTaTb) end end 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 ) end local function keytostring(k) if "string" == type(k) and k:match("^[_%a][_%w]*$") then return k end return prettystr(k) end if #keysDiffTaTb ~= 0 then table.insert( result, 'Items differing in A and B:') for k,v in sortedPairs( keysDiffTaTb ) do extendWithStrFmt( result, ' - A[%s]: %s', keytostring(v), prettystr(table_a[v]) ) extendWithStrFmt( result, ' + B[%s]: %s', keytostring(v), prettystr(table_b[v]) ) end end if #keysOnlyTa ~= 0 then table.insert( result, 'Items only in table A:' ) for k,v in sortedPairs( keysOnlyTa ) do extendWithStrFmt( result, ' - A[%s]: %s', keytostring(v), prettystr(table_a[v]) ) end end if #keysOnlyTb ~= 0 then table.insert( result, 'Items only in table B:' ) for k,v in sortedPairs( keysOnlyTb ) do extendWithStrFmt( result, ' + B[%s]: %s', keytostring(v), prettystr(table_b[v]) ) end end if #keysCommon ~= 0 then table.insert( result, 'Items common to A and B:') for k,v in sortedPairs( keysCommon ) do extendWithStrFmt( result, ' = A and B [%s]: %s', keytostring(v), prettystr(table_a[v]) ) end end return true, table.concat( result, '\n') ]] end M.private.mismatchFormattingMapping = mismatchFormattingMapping local function mismatchFormattingPureList( table_a, table_b, margin ) --[[ Prepares a nice error message when comparing tables which are lists, performing a deeper analysis. margin is supplied only for almost equality Returns: {success, result} * success: false if deep analysis could not be performed in this case, just use standard assertion message * result: if success is true, a multi-line string with deep analysis of the two lists ]] local result, descrTa, descrTb = {}, getTaTbDescr() local len_a, len_b, refa, refb = #table_a, #table_b, '', '' if M.PRINT_TABLE_REF_IN_ERROR_MSG then refa, refb = string.format( '<%s> ', M.private.table_ref(table_a)), string.format('<%s> ', M.private.table_ref(table_b) ) end local longest, shortest = math.max(len_a, len_b), math.min(len_a, len_b) local deltalv = longest - shortest local commonUntil = shortest for i = 1, shortest do if not M.private.is_table_equals(table_a[i], table_b[i], margin) then commonUntil = i - 1 break end end local commonBackTo = shortest - 1 for i = 0, shortest - 1 do if not M.private.is_table_equals(table_a[len_a-i], table_b[len_b-i], margin) then commonBackTo = i - 1 break end end table.insert( result, 'List difference analysis:' ) if len_a == len_b then -- TODO: handle expected/actual naming extendWithStrFmt( result, '* lists %sA (%s) and %sB (%s) have the same size', refa, descrTa, refb, descrTb ) else 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 ) end extendWithStrFmt( result, '* lists A and B start differing at index %d', commonUntil+1 ) if commonBackTo >= 0 then if deltalv > 0 then extendWithStrFmt( result, '* lists A and B are equal again from index %d for A, %d for B', len_a-commonBackTo, len_b-commonBackTo ) else extendWithStrFmt( result, '* lists A and B are equal again from index %d', len_a-commonBackTo ) end end local function insertABValue(ai, bi) bi = bi or ai if M.private.is_table_equals( table_a[ai], table_b[bi], margin) then return extendWithStrFmt( result, ' = A[%d], B[%d]: %s', ai, bi, prettystr(table_a[ai]) ) else extendWithStrFmt( result, ' - A[%d]: %s', ai, prettystr(table_a[ai])) extendWithStrFmt( result, ' + B[%d]: %s', bi, prettystr(table_b[bi])) end end -- common parts to list A & B, at the beginning if commonUntil > 0 then table.insert( result, '* Common parts:' ) for i = 1, commonUntil do insertABValue( i ) end end -- diffing parts to list A & B if commonUntil < shortest - commonBackTo - 1 then table.insert( result, '* Differing parts:' ) for i = commonUntil + 1, shortest - commonBackTo - 1 do insertABValue( i ) end end -- display indexes of one list, with no match on other list if shortest - commonBackTo <= longest - commonBackTo - 1 then table.insert( result, '* Present only in one list:' ) for i = shortest - commonBackTo, longest - commonBackTo - 1 do if len_a > len_b then extendWithStrFmt( result, ' - A[%d]: %s', i, prettystr(table_a[i]) ) -- table.insert( result, '+ (no matching B index)') else -- table.insert( result, '- no matching A index') extendWithStrFmt( result, ' + B[%d]: %s', i, prettystr(table_b[i]) ) end end end -- common parts to list A & B, at the end if commonBackTo >= 0 then table.insert( result, '* Common parts at the end of the lists' ) for i = longest - commonBackTo, longest do if len_a > len_b then insertABValue( i, i-deltalv ) else insertABValue( i-deltalv, i ) end end end return true, table.concat( result, '\n') end M.private.mismatchFormattingPureList = mismatchFormattingPureList local function prettystrPairs(value1, value2, suffix_a, suffix_b) --[[ This function helps with the recurring task of constructing the "expected vs. actual" error messages. It takes two arbitrary values and formats corresponding strings with prettystr(). To keep the (possibly complex) output more readable in case the resulting strings contain line breaks, they get automatically prefixed with additional newlines. Both suffixes are optional (default to empty strings), and get appended to the "value1" string. "suffix_a" is used if line breaks were encountered, "suffix_b" otherwise. Returns the two formatted strings (including padding/newlines). ]] local str1, str2 = prettystr(value1), prettystr(value2) if hasNewLine(str1) or hasNewLine(str2) then -- line break(s) detected, add padding return "\n" .. str1 .. (suffix_a or ""), "\n" .. str2 end return str1 .. (suffix_b or ""), str2 end M.private.prettystrPairs = prettystrPairs local UNKNOWN_REF = 'table 00-unknown ref' local ref_generator = { value=1, [UNKNOWN_REF]=0 } local function table_ref( t ) -- return the default tostring() for tables, with the table ID, even if the table has a metatable -- with the __tostring converter local ref = '' local mt = getmetatable( t ) if mt == nil then ref = tostring(t) else local success, result success, result = pcall(setmetatable, t, nil) if not success then -- protected table, if __tostring is defined, we can -- not get the reference. And we can not know in advance. ref = tostring(t) if not ref:match( 'table: 0?x?[%x]+' ) then return UNKNOWN_REF end else ref = tostring(t) setmetatable( t, mt ) end end -- strip the "table: " part ref = ref:sub(8) if ref ~= UNKNOWN_REF and ref_generator[ref] == nil then -- Create a new reference number ref_generator[ref] = ref_generator.value ref_generator.value = ref_generator.value+1 end if M.PRINT_TABLE_REF_IN_ERROR_MSG then return string.format('table %02d-%s', ref_generator[ref], ref) else return string.format('table %02d', ref_generator[ref]) end end M.private.table_ref = table_ref local TABLE_TOSTRING_SEP = ", " local TABLE_TOSTRING_SEP_LEN = string.len(TABLE_TOSTRING_SEP) local function _table_tostring( tbl, indentLevel, printTableRefs, cycleDetectTable ) printTableRefs = printTableRefs or M.PRINT_TABLE_REF_IN_ERROR_MSG cycleDetectTable = cycleDetectTable or {} cycleDetectTable[tbl] = true local result, dispOnMultLines = {}, false -- like prettystr but do not enclose with "" if the string is just alphanumerical -- this is better for displaying table keys who are often simple strings local function keytostring(k) if "string" == type(k) and k:match("^[_%a][_%w]*$") then return k end return prettystr_sub(k, indentLevel+1, printTableRefs, cycleDetectTable) end local mt = getmetatable( tbl ) if mt and mt.__tostring then -- if table has a __tostring() function in its metatable, use it to display the table -- else, compute a regular table result = tostring(tbl) if type(result) ~= 'string' then return string.format( '', prettystr(result) ) end result = strsplit( '\n', result ) return M.private._table_tostring_format_multiline_string( result, indentLevel ) else -- no metatable, compute the table representation local entry, count, seq_index = nil, 0, 1 for k, v in sortedPairs( tbl ) do -- key part if k == seq_index then -- for the sequential part of tables, we'll skip the "=" output entry = '' seq_index = seq_index + 1 elseif cycleDetectTable[k] then -- recursion in the key detected cycleDetectTable.detected = true entry = "<"..table_ref(k)..">=" else entry = keytostring(k) .. "=" end -- value part if cycleDetectTable[v] then -- recursion in the value detected! cycleDetectTable.detected = true entry = entry .. "<"..table_ref(v)..">" else entry = entry .. prettystr_sub( v, indentLevel+1, printTableRefs, cycleDetectTable ) end count = count + 1 result[count] = entry end return M.private._table_tostring_format_result( tbl, result, indentLevel, printTableRefs ) end end M.private._table_tostring = _table_tostring -- prettystr_sub() needs it local function _table_tostring_format_multiline_string( tbl_str, indentLevel ) local indentString = '\n'..string.rep(" ", indentLevel - 1) return table.concat( tbl_str, indentString ) end M.private._table_tostring_format_multiline_string = _table_tostring_format_multiline_string local function _table_tostring_format_result( tbl, result, indentLevel, printTableRefs ) -- final function called in _table_to_string() to format the resulting list of -- string describing the table. local dispOnMultLines = false -- set dispOnMultLines to true if the maximum LINE_LENGTH would be exceeded with the values local totalLength = 0 for k, v in ipairs( result ) do totalLength = totalLength + string.len( v ) if totalLength >= M.LINE_LENGTH then dispOnMultLines = true break end end -- set dispOnMultLines to true if the max LINE_LENGTH would be exceeded -- with the values and the separators. if not dispOnMultLines then -- adjust with length of separator(s): -- two items need 1 sep, three items two seps, ... plus len of '{}' if #result > 0 then totalLength = totalLength + TABLE_TOSTRING_SEP_LEN * (#result - 1) end dispOnMultLines = (totalLength + 2 >= M.LINE_LENGTH) end -- now reformat the result table (currently holding element strings) if dispOnMultLines then local indentString = string.rep(" ", indentLevel - 1) result = { "{\n ", indentString, table.concat(result, ",\n " .. indentString), "\n", indentString, "}" } else result = {"{", table.concat(result, TABLE_TOSTRING_SEP), "}"} end if printTableRefs then table.insert(result, 1, "<"..table_ref(tbl).."> ") -- prepend table ref end return table.concat(result) end M.private._table_tostring_format_result = _table_tostring_format_result -- prettystr_sub() needs it local function table_findkeyof(t, element) -- Return the key k of the given element in table t, so that t[k] == element -- (or `nil` if element is not present within t). Note that we use our -- 'general' is_equal comparison for matching, so this function should -- handle table-type elements gracefully and consistently. if type(t) == "table" then for k, v in pairs(t) do if M.private.is_table_equals(v, element) then return k end end end return nil end local function _is_table_items_equals(actual, expected ) local type_a, type_e = type(actual), type(expected) if type_a ~= type_e then return false elseif (type_a == 'table') --[[and (type_e == 'table')]] then for k, v in pairs(actual) do if table_findkeyof(expected, v) == nil then return false -- v not contained in expected end end for k, v in pairs(expected) do if table_findkeyof(actual, v) == nil then return false -- v not contained in actual end end return true elseif actual ~= expected then return false end return true end --[[ This is a specialized metatable to help with the bookkeeping of recursions in _is_table_equals(). It provides an __index table that implements utility functions for easier management of the table. The "cached" method queries the state of a specific (actual,expected) pair; and the "store" method sets this state to the given value. The state of pairs not "seen" / visited is assumed to be `nil`. ]] local _recursion_cache_MT = { __index = { -- Return the cached value for an (actual,expected) pair (or `nil`) cached = function(t, actual, expected) local subtable = t[actual] or {} return subtable[expected] end, -- Store cached value for a specific (actual,expected) pair. -- Returns the value, so it's easy to use for a "tailcall" (return ...). store = function(t, actual, expected, value, asymmetric) local subtable = t[actual] if not subtable then subtable = {} t[actual] = subtable end subtable[expected] = value -- Unless explicitly marked "asymmetric": Consider the recursion -- on (expected,actual) to be equivalent to (actual,expected) by -- default, and thus cache the value for both. if not asymmetric then t:store(expected, actual, value, true) end return value end } } local function _is_table_equals(actual, expected, cycleDetectTable, marginForAlmostEqual) --[[Returns true if both table are equal. If argument marginForAlmostEqual is suppied, number comparison is done using alomstEqual instead of strict equality. cycleDetectTable is an internal argument used during recursion on tables. ]] --print('_is_table_equals( \n '..prettystr(actual)..'\n , '..prettystr(expected).. -- '\n , '..prettystr(cycleDetectTable)..'\n , '..prettystr(marginForAlmostEqual)..' )') local type_a, type_e = type(actual), type(expected) if type_a ~= type_e then return false -- different types won't match end if type_a == 'number' then if marginForAlmostEqual ~= nil then return M.almostEquals(actual, expected, marginForAlmostEqual) else return actual == expected end elseif type_a ~= 'table' then -- other types compare directly return actual == expected end cycleDetectTable = cycleDetectTable or { actual={}, expected={} } if cycleDetectTable.actual[ actual ] then -- oh, we hit a cycle in actual if cycleDetectTable.expected[ expected ] then -- uh, we hit a cycle at the same time in expected -- so the two tables have similar structure return true end -- cycle was hit only in actual, the structure differs from expected return false end if cycleDetectTable.expected[ expected ] then -- no cycle in actual, but cycle in expected -- the structure differ return false end -- at this point, no table cycle detected, we are -- seeing this table for the first time -- mark the cycle detection cycleDetectTable.actual[ actual ] = true cycleDetectTable.expected[ expected ] = true local actualKeysMatched = {} for k, v in pairs(actual) do actualKeysMatched[k] = true -- Keep track of matched keys if not _is_table_equals(v, expected[k], cycleDetectTable, marginForAlmostEqual) then -- table differs on this key -- clear the cycle detection before returning cycleDetectTable.actual[ actual ] = nil cycleDetectTable.expected[ expected ] = nil return false end end for k, v in pairs(expected) do if not actualKeysMatched[k] then -- Found a key that we did not see in "actual" -> mismatch -- clear the cycle detection before returning cycleDetectTable.actual[ actual ] = nil cycleDetectTable.expected[ expected ] = nil return false end -- Otherwise actual[k] was already matched against v = expected[k]. end -- all key match, we have a match ! cycleDetectTable.actual[ actual ] = nil cycleDetectTable.expected[ expected ] = nil return true end M.private._is_table_equals = _is_table_equals local function failure(main_msg, extra_msg_or_nil, level) -- raise an error indicating a test failure -- for error() compatibility we adjust "level" here (by +1), to report the -- calling context local msg if type(extra_msg_or_nil) == 'string' and extra_msg_or_nil:len() > 0 then msg = extra_msg_or_nil .. '\n' .. main_msg else msg = main_msg end error(M.FAILURE_PREFIX .. msg, (level or 1) + 1 + M.STRIP_EXTRA_ENTRIES_IN_STACK_TRACE) end local function is_table_equals(actual, expected, marginForAlmostEqual) return _is_table_equals(actual, expected, nil, marginForAlmostEqual) end M.private.is_table_equals = is_table_equals local function fail_fmt(level, extra_msg_or_nil, ...) -- failure with printf-style formatted message and given error level failure(string.format(...), extra_msg_or_nil, (level or 1) + 1) end M.private.fail_fmt = fail_fmt local function error_fmt(level, ...) -- printf-style error() error(string.format(...), (level or 1) + 1 + M.STRIP_EXTRA_ENTRIES_IN_STACK_TRACE) end M.private.error_fmt = error_fmt ---------------------------------------------------------------- -- -- assertions -- ---------------------------------------------------------------- local function errorMsgEquality(actual, expected, doDeepAnalysis, margin) -- margin is supplied only for almost equal verification if not M.ORDER_ACTUAL_EXPECTED then expected, actual = actual, expected end if type(expected) == 'string' or type(expected) == 'table' then local strExpected, strActual = prettystrPairs(expected, actual) local result = string.format("expected: %s\nactual: %s", strExpected, strActual) if margin then result = result .. '\nwere not equal by the margin of: '..prettystr(margin) end -- extend with mismatch analysis if possible: local success, mismatchResult success, mismatchResult = tryMismatchFormatting( actual, expected, doDeepAnalysis, margin ) if success then result = table.concat( { result, mismatchResult }, '\n' ) end return result end return string.format("expected: %s, actual: %s", prettystr(expected), prettystr(actual)) end function M.assertError(f, ...) -- assert that calling f with the arguments will raise an error -- example: assertError( f, 1, 2 ) => f(1,2) should generate an error if pcall( f, ... ) then failure( "Expected an error when calling function but no error generated", nil, 2 ) end end function M.fail( msg ) -- stops a test due to a failure failure( msg, nil, 2 ) end function M.failIf( cond, msg ) -- Fails a test with "msg" if condition is true if cond then failure( msg, nil, 2 ) end end function M.skip(msg) -- skip a running test error_fmt(2, M.SKIP_PREFIX .. msg) end function M.skipIf( cond, msg ) -- skip a running test if condition is met if cond then error_fmt(2, M.SKIP_PREFIX .. msg) end end function M.runOnlyIf( cond, msg ) -- continue a running test if condition is met, else skip it if not cond then error_fmt(2, M.SKIP_PREFIX .. prettystr(msg)) end end function M.success() -- stops a test with a success error_fmt(2, M.SUCCESS_PREFIX) end function M.successIf( cond ) -- stops a test with a success if condition is met if cond then error_fmt(2, M.SUCCESS_PREFIX) end end ------------------------------------------------------------------ -- Equality assertions ------------------------------------------------------------------ function M.assertEquals(actual, expected, extra_msg_or_nil, doDeepAnalysis) if type(actual) == 'table' and type(expected) == 'table' then if not is_table_equals(actual, expected) then failure( errorMsgEquality(actual, expected, doDeepAnalysis), extra_msg_or_nil, 2 ) end elseif type(actual) ~= type(expected) then failure( errorMsgEquality(actual, expected), extra_msg_or_nil, 2 ) elseif actual ~= expected then failure( errorMsgEquality(actual, expected), extra_msg_or_nil, 2 ) end end function M.almostEquals( actual, expected, margin ) if type(actual) ~= 'number' or type(expected) ~= 'number' or type(margin) ~= 'number' then error_fmt(3, 'almostEquals: must supply only number arguments.\nArguments supplied: %s, %s, %s', prettystr(actual), prettystr(expected), prettystr(margin)) end if margin < 0 then error_fmt(3, 'almostEquals: margin must not be negative, current value is ' .. margin) end return math.abs(expected - actual) <= margin end function M.assertAlmostEquals( actual, expected, margin, extra_msg_or_nil ) -- check that two floats are close by margin margin = margin or M.EPS if type(margin) ~= 'number' then error_fmt(2, 'almostEquals: margin must be a number, not %s', prettystr(margin)) end if type(actual) == 'table' and type(expected) == 'table' then -- handle almost equals for table if not is_table_equals(actual, expected, margin) then failure( errorMsgEquality(actual, expected, nil, margin), extra_msg_or_nil, 2 ) end elseif type(actual) == 'number' and type(expected) == 'number' and type(margin) == 'number' then if not M.almostEquals(actual, expected, margin) then if not M.ORDER_ACTUAL_EXPECTED then expected, actual = actual, expected end local delta = math.abs(actual - expected) fail_fmt(2, extra_msg_or_nil, 'Values are not almost equal\n' .. 'Actual: %s, expected: %s, delta %s above margin of %s', actual, expected, delta, margin) end else error_fmt(3, 'almostEquals: must supply only number or table arguments.\nArguments supplied: %s, %s, %s', prettystr(actual), prettystr(expected), prettystr(margin)) end end function M.assertNotEquals(actual, expected, extra_msg_or_nil) if type(actual) ~= type(expected) then return end if type(actual) == 'table' and type(expected) == 'table' then if not is_table_equals(actual, expected) then return end elseif actual ~= expected then return end fail_fmt(2, extra_msg_or_nil, 'Received the not expected value: %s', prettystr(actual)) end function M.assertNotAlmostEquals( actual, expected, margin, extra_msg_or_nil ) -- check that two floats are not close by margin margin = margin or M.EPS if M.almostEquals(actual, expected, margin) then if not M.ORDER_ACTUAL_EXPECTED then expected, actual = actual, expected end local delta = math.abs(actual - expected) fail_fmt(2, extra_msg_or_nil, 'Values are almost equal\nActual: %s, expected: %s' .. ', delta %s below margin of %s', actual, expected, delta, margin) end end function M.assertItemsEquals(actual, expected, extra_msg_or_nil) -- checks that the items of table expected -- are contained in table actual. Warning, this function -- is at least O(n^2) if not _is_table_items_equals(actual, expected ) then expected, actual = prettystrPairs(expected, actual) fail_fmt(2, extra_msg_or_nil, 'Content of the tables are not identical:\nExpected: %s\nActual: %s', expected, actual) end end ------------------------------------------------------------------ -- String assertion ------------------------------------------------------------------ function M.assertStrContains( str, sub, isPattern, extra_msg_or_nil ) -- this relies on lua string.find function -- a string always contains the empty string -- assert( type(str) == 'string', 'Argument 1 of assertStrContains() should be a string.' ) ) -- assert( type(sub) == 'string', 'Argument 2 of assertStrContains() should be a string.' ) ) if not string.find(str, sub, 1, not isPattern) then sub, str = prettystrPairs(sub, str, '\n') fail_fmt(2, extra_msg_or_nil, 'Could not find %s %s in string %s', isPattern and 'pattern' or 'substring', sub, str) end end function M.assertStrIContains( str, sub, extra_msg_or_nil ) -- this relies on lua string.find function -- a string always contains the empty string if not string.find(str:lower(), sub:lower(), 1, true) then sub, str = prettystrPairs(sub, str, '\n') fail_fmt(2, extra_msg_or_nil, 'Could not find (case insensitively) substring %s in string %s', sub, str) end end function M.assertNotStrContains( str, sub, isPattern, extra_msg_or_nil ) -- this relies on lua string.find function -- a string always contains the empty string if string.find(str, sub, 1, not isPattern) then sub, str = prettystrPairs(sub, str, '\n') fail_fmt(2, extra_msg_or_nil, 'Found the not expected %s %s in string %s', isPattern and 'pattern' or 'substring', sub, str) end end function M.assertNotStrIContains( str, sub, extra_msg_or_nil ) -- this relies on lua string.find function -- a string always contains the empty string if string.find(str:lower(), sub:lower(), 1, true) then sub, str = prettystrPairs(sub, str, '\n') fail_fmt(2, extra_msg_or_nil, 'Found (case insensitively) the not expected substring %s in string %s', sub, str) end end function M.assertStrMatches( str, pattern, start, final, extra_msg_or_nil ) -- Verify a full match for the string if not strMatch( str, pattern, start, final ) then pattern, str = prettystrPairs(pattern, str, '\n') fail_fmt(2, extra_msg_or_nil, 'Could not match pattern %s with string %s', pattern, str) end end local function _assertErrorMsgEquals( stripFileAndLine, expectedMsg, func, ... ) local no_error, error_msg = pcall( func, ... ) if no_error then failure( 'No error generated when calling function but expected error: '..M.prettystr(expectedMsg), nil, 3 ) end if type(expectedMsg) == "string" and type(error_msg) ~= "string" then -- table are converted to string automatically error_msg = tostring(error_msg) end local differ = false if stripFileAndLine then if error_msg:gsub("^.+:%d+: ", "") ~= expectedMsg then differ = true end else if error_msg ~= expectedMsg then local tr = type(error_msg) local te = type(expectedMsg) if te == 'table' then if tr ~= 'table' then differ = true else local ok = pcall(M.assertItemsEquals, error_msg, expectedMsg) if not ok then differ = true end end else differ = true end end end if differ then error_msg, expectedMsg = prettystrPairs(error_msg, expectedMsg) fail_fmt(3, nil, 'Error message expected: %s\nError message received: %s\n', expectedMsg, error_msg) end end function M.assertErrorMsgEquals( expectedMsg, func, ... ) -- assert that calling f with the arguments will raise an error -- example: assertError( f, 1, 2 ) => f(1,2) should generate an error _assertErrorMsgEquals(false, expectedMsg, func, ...) end function M.assertErrorMsgContentEquals(expectedMsg, func, ...) _assertErrorMsgEquals(true, expectedMsg, func, ...) end function M.assertErrorMsgContains( partialMsg, func, ... ) -- assert that calling f with the arguments will raise an error -- example: assertError( f, 1, 2 ) => f(1,2) should generate an error local no_error, error_msg = pcall( func, ... ) if no_error then failure( 'No error generated when calling function but expected error containing: '..prettystr(partialMsg), nil, 2 ) end if type(error_msg) ~= "string" then error_msg = tostring(error_msg) end if not string.find( error_msg, partialMsg, nil, true ) then error_msg, partialMsg = prettystrPairs(error_msg, partialMsg) fail_fmt(2, nil, 'Error message does not contain: %s\nError message received: %s\n', partialMsg, error_msg) end end function M.assertErrorMsgMatches( expectedMsg, func, ... ) -- assert that calling f with the arguments will raise an error -- example: assertError( f, 1, 2 ) => f(1,2) should generate an error local no_error, error_msg = pcall( func, ... ) if no_error then failure( 'No error generated when calling function but expected error matching: "'..expectedMsg..'"', nil, 2 ) end if type(error_msg) ~= "string" then error_msg = tostring(error_msg) end if not strMatch( error_msg, expectedMsg ) then expectedMsg, error_msg = prettystrPairs(expectedMsg, error_msg) fail_fmt(2, nil, 'Error message does not match pattern: %s\nError message received: %s\n', expectedMsg, error_msg) end end ------------------------------------------------------------------ -- Type assertions ------------------------------------------------------------------ function M.assertEvalToTrue(value, extra_msg_or_nil) if not value then failure("expected: a value evaluating to true, actual: " ..prettystr(value), extra_msg_or_nil, 2) end end function M.assertEvalToFalse(value, extra_msg_or_nil) if value then failure("expected: false or nil, actual: " ..prettystr(value), extra_msg_or_nil, 2) end end function M.assertIsTrue(value, extra_msg_or_nil) if value ~= true then failure("expected: true, actual: " ..prettystr(value), extra_msg_or_nil, 2) end end function M.assertNotIsTrue(value, extra_msg_or_nil) if value == true then failure("expected: not true, actual: " ..prettystr(value), extra_msg_or_nil, 2) end end function M.assertIsFalse(value, extra_msg_or_nil) if value ~= false then failure("expected: false, actual: " ..prettystr(value), extra_msg_or_nil, 2) end end function M.assertNotIsFalse(value, extra_msg_or_nil) if value == false then failure("expected: not false, actual: " ..prettystr(value), extra_msg_or_nil, 2) end end function M.assertIsNil(value, extra_msg_or_nil) if value ~= nil then failure("expected: nil, actual: " ..prettystr(value), extra_msg_or_nil, 2) end end function M.assertNotIsNil(value, extra_msg_or_nil) if value == nil then failure("expected: not nil, actual: nil", extra_msg_or_nil, 2) end end --[[ Add type assertion functions to the module table M. Each of these functions takes a single parameter "value", and checks that its Lua type matches the expected string (derived from the function name): M.assertIsXxx(value) -> ensure that type(value) conforms to "xxx" ]] for _, funcName in ipairs( {'assertIsNumber', 'assertIsString', 'assertIsTable', 'assertIsBoolean', 'assertIsFunction', 'assertIsUserdata', 'assertIsThread'} ) do local typeExpected = funcName:match("^assertIs([A-Z]%a*)$") -- Lua type() always returns lowercase, also make sure the match() succeeded typeExpected = typeExpected and typeExpected:lower() or error("bad function name '"..funcName.."' for type assertion") M[funcName] = function(value, extra_msg_or_nil) if type(value) ~= typeExpected then if type(value) == 'nil' then fail_fmt(2, extra_msg_or_nil, 'expected: a %s value, actual: nil', typeExpected, type(value), prettystrPairs(value)) else fail_fmt(2, extra_msg_or_nil, 'expected: a %s value, actual: type %s, value %s', typeExpected, type(value), prettystrPairs(value)) end end end end --[[ Add shortcuts for verifying type of a variable, without failure (luaunit v2 compatibility) M.isXxx(value) -> returns true if type(value) conforms to "xxx" ]] for _, typeExpected in ipairs( {'Number', 'String', 'Table', 'Boolean', 'Function', 'Userdata', 'Thread', 'Nil' } ) do local typeExpectedLower = typeExpected:lower() local isType = function(value) return (type(value) == typeExpectedLower) end M['is'..typeExpected] = isType M['is_'..typeExpectedLower] = isType end --[[ Add non-type assertion functions to the module table M. Each of these functions takes a single parameter "value", and checks that its Lua type differs from the expected string (derived from the function name): M.assertNotIsXxx(value) -> ensure that type(value) is not "xxx" ]] for _, funcName in ipairs( {'assertNotIsNumber', 'assertNotIsString', 'assertNotIsTable', 'assertNotIsBoolean', 'assertNotIsFunction', 'assertNotIsUserdata', 'assertNotIsThread'} ) do local typeUnexpected = funcName:match("^assertNotIs([A-Z]%a*)$") -- Lua type() always returns lowercase, also make sure the match() succeeded typeUnexpected = typeUnexpected and typeUnexpected:lower() or error("bad function name '"..funcName.."' for type assertion") M[funcName] = function(value, extra_msg_or_nil) if type(value) == typeUnexpected then fail_fmt(2, extra_msg_or_nil, 'expected: not a %s type, actual: value %s', typeUnexpected, prettystrPairs(value)) end end end function M.assertIs(actual, expected, extra_msg_or_nil) if actual ~= expected then if not M.ORDER_ACTUAL_EXPECTED then actual, expected = expected, actual end local old_print_table_ref_in_error_msg = M.PRINT_TABLE_REF_IN_ERROR_MSG M.PRINT_TABLE_REF_IN_ERROR_MSG = true expected, actual = prettystrPairs(expected, actual, '\n', '') M.PRINT_TABLE_REF_IN_ERROR_MSG = old_print_table_ref_in_error_msg fail_fmt(2, extra_msg_or_nil, 'expected and actual object should not be different\nExpected: %s\nReceived: %s', expected, actual) end end function M.assertNotIs(actual, expected, extra_msg_or_nil) if actual == expected then local old_print_table_ref_in_error_msg = M.PRINT_TABLE_REF_IN_ERROR_MSG M.PRINT_TABLE_REF_IN_ERROR_MSG = true local s_expected if not M.ORDER_ACTUAL_EXPECTED then s_expected = prettystrPairs(actual) else s_expected = prettystrPairs(expected) end M.PRINT_TABLE_REF_IN_ERROR_MSG = old_print_table_ref_in_error_msg fail_fmt(2, extra_msg_or_nil, 'expected and actual object should be different: %s', s_expected ) end end ------------------------------------------------------------------ -- Scientific assertions ------------------------------------------------------------------ function M.assertIsNaN(value, extra_msg_or_nil) if type(value) ~= "number" or value == value then failure("expected: NaN, actual: " ..prettystr(value), extra_msg_or_nil, 2) end end function M.assertNotIsNaN(value, extra_msg_or_nil) if type(value) == "number" and value ~= value then failure("expected: not NaN, actual: NaN", extra_msg_or_nil, 2) end end function M.assertIsInf(value, extra_msg_or_nil) if type(value) ~= "number" or math.abs(value) ~= math.huge then failure("expected: #Inf, actual: " ..prettystr(value), extra_msg_or_nil, 2) end end function M.assertIsPlusInf(value, extra_msg_or_nil) if type(value) ~= "number" or value ~= math.huge then failure("expected: #Inf, actual: " ..prettystr(value), extra_msg_or_nil, 2) end end function M.assertIsMinusInf(value, extra_msg_or_nil) if type(value) ~= "number" or value ~= -math.huge then failure("expected: -#Inf, actual: " ..prettystr(value), extra_msg_or_nil, 2) end end function M.assertNotIsPlusInf(value, extra_msg_or_nil) if type(value) == "number" and value == math.huge then failure("expected: not #Inf, actual: #Inf", extra_msg_or_nil, 2) end end function M.assertNotIsMinusInf(value, extra_msg_or_nil) if type(value) == "number" and value == -math.huge then failure("expected: not -#Inf, actual: -#Inf", extra_msg_or_nil, 2) end end function M.assertNotIsInf(value, extra_msg_or_nil) if type(value) == "number" and math.abs(value) == math.huge then failure("expected: not infinity, actual: " .. prettystr(value), extra_msg_or_nil, 2) end end function M.assertIsPlusZero(value, extra_msg_or_nil) if type(value) ~= 'number' or value ~= 0 then failure("expected: +0.0, actual: " ..prettystr(value), extra_msg_or_nil, 2) else if (1/value == -math.huge) then -- more precise error diagnosis failure("expected: +0.0, actual: -0.0", extra_msg_or_nil, 2) else if (1/value ~= math.huge) then -- strange, case should have already been covered failure("expected: +0.0, actual: " ..prettystr(value), extra_msg_or_nil, 2) end end end end function M.assertIsMinusZero(value, extra_msg_or_nil) if type(value) ~= 'number' or value ~= 0 then failure("expected: -0.0, actual: " ..prettystr(value), extra_msg_or_nil, 2) else if (1/value == math.huge) then -- more precise error diagnosis failure("expected: -0.0, actual: +0.0", extra_msg_or_nil, 2) else if (1/value ~= -math.huge) then -- strange, case should have already been covered failure("expected: -0.0, actual: " ..prettystr(value), extra_msg_or_nil, 2) end end end end function M.assertNotIsPlusZero(value, extra_msg_or_nil) if type(value) == 'number' and (1/value == math.huge) then failure("expected: not +0.0, actual: +0.0", extra_msg_or_nil, 2) end end function M.assertNotIsMinusZero(value, extra_msg_or_nil) if type(value) == 'number' and (1/value == -math.huge) then failure("expected: not -0.0, actual: -0.0", extra_msg_or_nil, 2) end end function M.assertTableContains(t, expected, extra_msg_or_nil) -- checks that table t contains the expected element if table_findkeyof(t, expected) == nil then t, expected = prettystrPairs(t, expected) fail_fmt(2, extra_msg_or_nil, 'Table %s does NOT contain the expected element %s', t, expected) end end function M.assertNotTableContains(t, expected, extra_msg_or_nil) -- checks that table t doesn't contain the expected element local k = table_findkeyof(t, expected) if k ~= nil then t, expected = prettystrPairs(t, expected) fail_fmt(2, extra_msg_or_nil, 'Table %s DOES contain the unwanted element %s (at key %s)', t, expected, prettystr(k)) end end ---------------------------------------------------------------- -- Compatibility layer ---------------------------------------------------------------- -- for compatibility with LuaUnit v2.x function M.wrapFunctions() -- In LuaUnit version <= 2.1 , this function was necessary to include -- a test function inside the global test suite. Nowadays, the functions -- are simply run directly as part of the test discovery process. -- so just do nothing ! io.stderr:write[[Use of WrapFunctions() is no longer needed. Just prefix your test function names with "test" or "Test" and they will be picked up and run by LuaUnit. ]] end local list_of_funcs = { -- { official function name , alias } -- general assertions { 'assertEquals' , 'assert_equals' }, { 'assertItemsEquals' , 'assert_items_equals' }, { 'assertNotEquals' , 'assert_not_equals' }, { 'assertAlmostEquals' , 'assert_almost_equals' }, { 'assertNotAlmostEquals' , 'assert_not_almost_equals' }, { 'assertEvalToTrue' , 'assert_eval_to_true' }, { 'assertEvalToFalse' , 'assert_eval_to_false' }, { 'assertStrContains' , 'assert_str_contains' }, { 'assertStrIContains' , 'assert_str_icontains' }, { 'assertNotStrContains' , 'assert_not_str_contains' }, { 'assertNotStrIContains' , 'assert_not_str_icontains' }, { 'assertStrMatches' , 'assert_str_matches' }, { 'assertError' , 'assert_error' }, { 'assertErrorMsgEquals' , 'assert_error_msg_equals' }, { 'assertErrorMsgContains' , 'assert_error_msg_contains' }, { 'assertErrorMsgMatches' , 'assert_error_msg_matches' }, { 'assertErrorMsgContentEquals', 'assert_error_msg_content_equals' }, { 'assertIs' , 'assert_is' }, { 'assertNotIs' , 'assert_not_is' }, { 'assertTableContains' , 'assert_table_contains' }, { 'assertNotTableContains' , 'assert_not_table_contains' }, { 'wrapFunctions' , 'WrapFunctions' }, { 'wrapFunctions' , 'wrap_functions' }, -- type assertions: assertIsXXX -> assert_is_xxx { 'assertIsNumber' , 'assert_is_number' }, { 'assertIsString' , 'assert_is_string' }, { 'assertIsTable' , 'assert_is_table' }, { 'assertIsBoolean' , 'assert_is_boolean' }, { 'assertIsNil' , 'assert_is_nil' }, { 'assertIsTrue' , 'assert_is_true' }, { 'assertIsFalse' , 'assert_is_false' }, { 'assertIsNaN' , 'assert_is_nan' }, { 'assertIsInf' , 'assert_is_inf' }, { 'assertIsPlusInf' , 'assert_is_plus_inf' }, { 'assertIsMinusInf' , 'assert_is_minus_inf' }, { 'assertIsPlusZero' , 'assert_is_plus_zero' }, { 'assertIsMinusZero' , 'assert_is_minus_zero' }, { 'assertIsFunction' , 'assert_is_function' }, { 'assertIsThread' , 'assert_is_thread' }, { 'assertIsUserdata' , 'assert_is_userdata' }, -- type assertions: assertIsXXX -> assertXxx { 'assertIsNumber' , 'assertNumber' }, { 'assertIsString' , 'assertString' }, { 'assertIsTable' , 'assertTable' }, { 'assertIsBoolean' , 'assertBoolean' }, { 'assertIsNil' , 'assertNil' }, { 'assertIsTrue' , 'assertTrue' }, { 'assertIsFalse' , 'assertFalse' }, { 'assertIsNaN' , 'assertNaN' }, { 'assertIsInf' , 'assertInf' }, { 'assertIsPlusInf' , 'assertPlusInf' }, { 'assertIsMinusInf' , 'assertMinusInf' }, { 'assertIsPlusZero' , 'assertPlusZero' }, { 'assertIsMinusZero' , 'assertMinusZero'}, { 'assertIsFunction' , 'assertFunction' }, { 'assertIsThread' , 'assertThread' }, { 'assertIsUserdata' , 'assertUserdata' }, -- type assertions: assertIsXXX -> assert_xxx (luaunit v2 compat) { 'assertIsNumber' , 'assert_number' }, { 'assertIsString' , 'assert_string' }, { 'assertIsTable' , 'assert_table' }, { 'assertIsBoolean' , 'assert_boolean' }, { 'assertIsNil' , 'assert_nil' }, { 'assertIsTrue' , 'assert_true' }, { 'assertIsFalse' , 'assert_false' }, { 'assertIsNaN' , 'assert_nan' }, { 'assertIsInf' , 'assert_inf' }, { 'assertIsPlusInf' , 'assert_plus_inf' }, { 'assertIsMinusInf' , 'assert_minus_inf' }, { 'assertIsPlusZero' , 'assert_plus_zero' }, { 'assertIsMinusZero' , 'assert_minus_zero' }, { 'assertIsFunction' , 'assert_function' }, { 'assertIsThread' , 'assert_thread' }, { 'assertIsUserdata' , 'assert_userdata' }, -- type assertions: assertNotIsXXX -> assert_not_is_xxx { 'assertNotIsNumber' , 'assert_not_is_number' }, { 'assertNotIsString' , 'assert_not_is_string' }, { 'assertNotIsTable' , 'assert_not_is_table' }, { 'assertNotIsBoolean' , 'assert_not_is_boolean' }, { 'assertNotIsNil' , 'assert_not_is_nil' }, { 'assertNotIsTrue' , 'assert_not_is_true' }, { 'assertNotIsFalse' , 'assert_not_is_false' }, { 'assertNotIsNaN' , 'assert_not_is_nan' }, { 'assertNotIsInf' , 'assert_not_is_inf' }, { 'assertNotIsPlusInf' , 'assert_not_plus_inf' }, { 'assertNotIsMinusInf' , 'assert_not_minus_inf' }, { 'assertNotIsPlusZero' , 'assert_not_plus_zero' }, { 'assertNotIsMinusZero' , 'assert_not_minus_zero' }, { 'assertNotIsFunction' , 'assert_not_is_function' }, { 'assertNotIsThread' , 'assert_not_is_thread' }, { 'assertNotIsUserdata' , 'assert_not_is_userdata' }, -- type assertions: assertNotIsXXX -> assertNotXxx (luaunit v2 compat) { 'assertNotIsNumber' , 'assertNotNumber' }, { 'assertNotIsString' , 'assertNotString' }, { 'assertNotIsTable' , 'assertNotTable' }, { 'assertNotIsBoolean' , 'assertNotBoolean' }, { 'assertNotIsNil' , 'assertNotNil' }, { 'assertNotIsTrue' , 'assertNotTrue' }, { 'assertNotIsFalse' , 'assertNotFalse' }, { 'assertNotIsNaN' , 'assertNotNaN' }, { 'assertNotIsInf' , 'assertNotInf' }, { 'assertNotIsPlusInf' , 'assertNotPlusInf' }, { 'assertNotIsMinusInf' , 'assertNotMinusInf' }, { 'assertNotIsPlusZero' , 'assertNotPlusZero' }, { 'assertNotIsMinusZero' , 'assertNotMinusZero' }, { 'assertNotIsFunction' , 'assertNotFunction' }, { 'assertNotIsThread' , 'assertNotThread' }, { 'assertNotIsUserdata' , 'assertNotUserdata' }, -- type assertions: assertNotIsXXX -> assert_not_xxx { 'assertNotIsNumber' , 'assert_not_number' }, { 'assertNotIsString' , 'assert_not_string' }, { 'assertNotIsTable' , 'assert_not_table' }, { 'assertNotIsBoolean' , 'assert_not_boolean' }, { 'assertNotIsNil' , 'assert_not_nil' }, { 'assertNotIsTrue' , 'assert_not_true' }, { 'assertNotIsFalse' , 'assert_not_false' }, { 'assertNotIsNaN' , 'assert_not_nan' }, { 'assertNotIsInf' , 'assert_not_inf' }, { 'assertNotIsPlusInf' , 'assert_not_plus_inf' }, { 'assertNotIsMinusInf' , 'assert_not_minus_inf' }, { 'assertNotIsPlusZero' , 'assert_not_plus_zero' }, { 'assertNotIsMinusZero' , 'assert_not_minus_zero' }, { 'assertNotIsFunction' , 'assert_not_function' }, { 'assertNotIsThread' , 'assert_not_thread' }, { 'assertNotIsUserdata' , 'assert_not_userdata' }, -- all assertions with Coroutine duplicate Thread assertions { 'assertIsThread' , 'assertIsCoroutine' }, { 'assertIsThread' , 'assertCoroutine' }, { 'assertIsThread' , 'assert_is_coroutine' }, { 'assertIsThread' , 'assert_coroutine' }, { 'assertNotIsThread' , 'assertNotIsCoroutine' }, { 'assertNotIsThread' , 'assertNotCoroutine' }, { 'assertNotIsThread' , 'assert_not_is_coroutine' }, { 'assertNotIsThread' , 'assert_not_coroutine' }, } -- Create all aliases in M for _,v in ipairs( list_of_funcs ) do local funcname, alias = v[1], v[2] M[alias] = M[funcname] if EXPORT_ASSERT_TO_GLOBALS then _G[funcname] = M[funcname] _G[alias] = M[funcname] end end ---------------------------------------------------------------- -- -- Outputters -- ---------------------------------------------------------------- -- A common "base" class for outputters -- For concepts involved (class inheritance) see http://www.lua.org/pil/16.2.html local genericOutput = { __class__ = 'genericOutput' } -- class local genericOutput_MT = { __index = genericOutput } -- metatable M.genericOutput = genericOutput -- publish, so that custom classes may derive from it function genericOutput.new(runner, default_verbosity) -- runner is the "parent" object controlling the output, usually a LuaUnit instance local t = { runner = runner } if runner then t.result = runner.result t.verbosity = runner.verbosity or default_verbosity t.fname = runner.fname else t.verbosity = default_verbosity end return setmetatable( t, genericOutput_MT) end -- abstract ("empty") methods function genericOutput:startSuite() -- Called once, when the suite is started end function genericOutput:startClass(className) -- Called each time a new test class is started end function genericOutput:startTest(testName) -- called each time a new test is started, right before the setUp() -- the current test status node is already created and available in: self.result.currentNode end function genericOutput:updateStatus(node) -- called with status failed or error as soon as the error/failure is encountered -- this method is NOT called for a successful test because a test is marked as successful by default -- and does not need to be updated end function genericOutput:endTest(node) -- called when the test is finished, after the tearDown() method end function genericOutput:endClass() -- called when executing the class is finished, before moving on to the next class of at the end of the test execution end function genericOutput:endSuite() -- called at the end of the test suite execution end ---------------------------------------------------------------- -- class TapOutput ---------------------------------------------------------------- local TapOutput = genericOutput.new() -- derived class local TapOutput_MT = { __index = TapOutput } -- metatable TapOutput.__class__ = 'TapOutput' -- For a good reference for TAP format, check: http://testanything.org/tap-specification.html function TapOutput.new(runner) local t = genericOutput.new(runner, M.VERBOSITY_LOW) return setmetatable( t, TapOutput_MT) end function TapOutput:startSuite() print("1.."..self.result.selectedCount) print('# Started on '..self.result.startDate) end function TapOutput:startClass(className) if className ~= '[TestFunctions]' then print('# Starting class: '..className) end end function TapOutput:updateStatus( node ) if node:isSkipped() then io.stdout:write("ok ", self.result.currentTestNumber, "\t# SKIP ", node.msg, "\n" ) return end io.stdout:write("not ok ", self.result.currentTestNumber, "\t", node.testName, "\n") if self.verbosity > M.VERBOSITY_LOW then print( prefixString( '# ', node.msg ) ) end if (node:isFailure() or node:isError()) and self.verbosity > M.VERBOSITY_DEFAULT then print( prefixString( '# ', node.stackTrace ) ) end end function TapOutput:endTest( node ) if node:isSuccess() then io.stdout:write("ok ", self.result.currentTestNumber, "\t", node.testName, "\n") end end function TapOutput:endSuite() print( '# '..M.LuaUnit.statusLine( self.result ) ) return self.result.notSuccessCount end -- class TapOutput end ---------------------------------------------------------------- -- class JUnitOutput ---------------------------------------------------------------- -- See directory junitxml for more information about the junit format local JUnitOutput = genericOutput.new() -- derived class local JUnitOutput_MT = { __index = JUnitOutput } -- metatable JUnitOutput.__class__ = 'JUnitOutput' function JUnitOutput.new(runner) local t = genericOutput.new(runner, M.VERBOSITY_LOW) t.testList = {} return setmetatable( t, JUnitOutput_MT ) end function JUnitOutput:startSuite() -- open xml file early to deal with errors if self.fname == nil then error('With Junit, an output filename must be supplied with --name!') end if string.sub(self.fname,-4) ~= '.xml' then self.fname = self.fname..'.xml' end self.fd = io.open(self.fname, "w") if self.fd == nil then error("Could not open file for writing: "..self.fname) end print('# XML output to '..self.fname) print('# Started on '..self.result.startDate) end function JUnitOutput:startClass(className) if className ~= '[TestFunctions]' then print('# Starting class: '..className) end end function JUnitOutput:startTest(testName) print('# Starting test: '..testName) end function JUnitOutput:updateStatus( node ) if node:isFailure() then print( '# Failure: ' .. prefixString( '# ', node.msg ):sub(4, nil) ) -- print('# ' .. node.stackTrace) elseif node:isError() then print( '# Error: ' .. prefixString( '# ' , node.msg ):sub(4, nil) ) -- print('# ' .. node.stackTrace) end end function JUnitOutput:endSuite() print( '# '..M.LuaUnit.statusLine(self.result)) -- XML file writing self.fd:write('\n') self.fd:write('\n') self.fd:write(string.format( ' \n', self.result.runCount, self.result.startIsodate, self.result.duration, self.result.errorCount, self.result.failureCount, self.result.skippedCount )) self.fd:write(" \n") self.fd:write(string.format(' \n', _VERSION ) ) self.fd:write(string.format(' \n', M.VERSION) ) -- XXX please include system name and version if possible self.fd:write(" \n") for i,node in ipairs(self.result.allTests) do self.fd:write(string.format(' \n', node.className, node.testName, node.duration ) ) if node:isNotSuccess() then self.fd:write(node:statusXML()) end self.fd:write(' \n') end -- Next two lines are needed to validate junit ANT xsd, but really not useful in general: self.fd:write(' \n') self.fd:write(' \n') self.fd:write(' \n') self.fd:write('\n') self.fd:close() return self.result.notSuccessCount end -- class TapOutput end ---------------------------------------------------------------- -- class TextOutput ---------------------------------------------------------------- --[[ Example of other unit-tests suite text output -- Python Non verbose: For each test: . or F or E If some failed tests: ============== ERROR / FAILURE: TestName (testfile.testclass) --------- Stack trace then -------------- then "Ran x tests in 0.000s" then OK or FAILED (failures=1, error=1) -- Python Verbose: testname (filename.classname) ... ok testname (filename.classname) ... FAIL testname (filename.classname) ... ERROR then -------------- then "Ran x tests in 0.000s" then OK or FAILED (failures=1, error=1) -- Ruby: Started . Finished in 0.002695 seconds. 1 tests, 2 assertions, 0 failures, 0 errors -- Ruby: >> ruby tc_simple_number2.rb Loaded suite tc_simple_number2 Started F.. Finished in 0.038617 seconds. 1) Failure: test_failure(TestSimpleNumber) [tc_simple_number2.rb:16]: Adding doesn't work. <3> expected but was <4>. 3 tests, 4 assertions, 1 failures, 0 errors -- Java Junit .......F. Time: 0,003 There was 1 failure: 1) testCapacity(junit.samples.VectorTest)junit.framework.AssertionFailedError at junit.samples.VectorTest.testCapacity(VectorTest.java:87) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) FAILURES!!! Tests run: 8, Failures: 1, Errors: 0 -- Maven # mvn test ------------------------------------------------------- T E S T S ------------------------------------------------------- Running math.AdditionTest Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.03 sec <<< FAILURE! Results : Failed tests: testLireSymbole(math.AdditionTest) Tests run: 2, Failures: 1, Errors: 0, Skipped: 0 -- LuaUnit ---- non verbose * display . or F or E when running tests ---- verbose * display test name + ok/fail ---- * blank line * number) ERROR or FAILURE: TestName Stack trace * blank line * number) ERROR or FAILURE: TestName Stack trace then -------------- then "Ran x tests in 0.000s (%d not selected, %d skipped)" then OK or FAILED (failures=1, error=1) ]] local TextOutput = genericOutput.new() -- derived class local TextOutput_MT = { __index = TextOutput } -- metatable TextOutput.__class__ = 'TextOutput' function TextOutput.new(runner) local t = genericOutput.new(runner, M.VERBOSITY_DEFAULT) t.errorList = {} return setmetatable( t, TextOutput_MT ) end function TextOutput:startSuite() if self.verbosity > M.VERBOSITY_DEFAULT then print( 'Started on '.. self.result.startDate ) end end function TextOutput:startTest(testName) if self.verbosity > M.VERBOSITY_DEFAULT then io.stdout:write( " ", self.result.currentNode.testName, " ... " ) end end function TextOutput:endTest( node ) if node:isSuccess() then if self.verbosity > M.VERBOSITY_DEFAULT then io.stdout:write("Ok\n") else io.stdout:write(".") io.stdout:flush() end else if self.verbosity > M.VERBOSITY_DEFAULT then print( node.status ) print( node.msg ) --[[ -- find out when to do this: if self.verbosity > M.VERBOSITY_DEFAULT then print( node.stackTrace ) end ]] else -- write only the first character of status E, F or S io.stdout:write(string.sub(node.status, 1, 1)) io.stdout:flush() end end end function TextOutput:displayOneFailedTest( index, fail ) print(index..") "..fail.testName ) print( fail.msg ) print( fail.stackTrace ) print() end function TextOutput:displayErroredTests() if #self.result.errorTests ~= 0 then print("Tests with errors:") print("------------------") for i, v in ipairs(self.result.errorTests) do self:displayOneFailedTest(i, v) end end end function TextOutput:displayFailedTests() if #self.result.failedTests ~= 0 then print("Failed tests:") print("-------------") for i, v in ipairs(self.result.failedTests) do self:displayOneFailedTest(i, v) end end end function TextOutput:endSuite() if self.verbosity > M.VERBOSITY_DEFAULT then print("=========================================================") else print() end self:displayErroredTests() self:displayFailedTests() print( M.LuaUnit.statusLine( self.result ) ) if self.result.notSuccessCount == 0 then print('OK') end end -- class TextOutput end ---------------------------------------------------------------- -- class NilOutput ---------------------------------------------------------------- local function nopCallable() --print(42) return nopCallable end local NilOutput = { __class__ = 'NilOuptut' } -- class local NilOutput_MT = { __index = nopCallable } -- metatable function NilOutput.new(runner) return setmetatable( { __class__ = 'NilOutput' }, NilOutput_MT ) end ---------------------------------------------------------------- -- -- class LuaUnit -- ---------------------------------------------------------------- M.LuaUnit = { outputType = TextOutput, verbosity = M.VERBOSITY_DEFAULT, __class__ = 'LuaUnit', instances = {} } local LuaUnit_MT = { __index = M.LuaUnit } if EXPORT_ASSERT_TO_GLOBALS then LuaUnit = M.LuaUnit end function M.LuaUnit.new() local newInstance = setmetatable( {}, LuaUnit_MT ) return newInstance end -----------------[[ Utility methods ]]--------------------- function M.LuaUnit.asFunction(aObject) -- return "aObject" if it is a function, and nil otherwise if 'function' == type(aObject) then return aObject end end function M.LuaUnit.splitClassMethod(someName) --[[ Return a pair of className, methodName strings for a name in the form "class.method". If no class part (or separator) is found, will return nil, someName instead (the latter being unchanged). This convention thus also replaces the older isClassMethod() test: You just have to check for a non-nil className (return) value. ]] local separator = string.find(someName, '.', 1, true) if separator then return someName:sub(1, separator - 1), someName:sub(separator + 1) end return nil, someName end function M.LuaUnit.isMethodTestName( s ) -- return true is the name matches the name of a test method -- default rule is that is starts with 'Test' or with 'test' return string.sub(s, 1, 4):lower() == 'test' end function M.LuaUnit.isTestName( s ) -- return true is the name matches the name of a test -- default rule is that is starts with 'Test' or with 'test' return string.sub(s, 1, 4):lower() == 'test' end function M.LuaUnit.collectTests() -- return a list of all test names in the global namespace -- that match LuaUnit.isTestName local testNames = {} for k, _ in pairs(_G) do if type(k) == "string" and M.LuaUnit.isTestName( k ) then table.insert( testNames , k ) end end table.sort( testNames ) return testNames end function M.LuaUnit.parseCmdLine( cmdLine ) -- parse the command line -- Supported command line parameters: -- --verbose, -v: increase verbosity -- --quiet, -q: silence output -- --error, -e: treat errors as fatal (quit program) -- --output, -o, + name: select output type -- --pattern, -p, + pattern: run test matching pattern, may be repeated -- --exclude, -x, + pattern: run test not matching pattern, may be repeated -- --shuffle, -s, : shuffle tests before reunning them -- --name, -n, + fname: name of output file for junit, default to stdout -- --repeat, -r, + num: number of times to execute each test -- [testnames, ...]: run selected test names -- -- Returns a table with the following fields: -- verbosity: nil, M.VERBOSITY_DEFAULT, M.VERBOSITY_QUIET, M.VERBOSITY_VERBOSE -- output: nil, 'tap', 'junit', 'text', 'nil' -- testNames: nil or a list of test names to run -- exeRepeat: num or 1 -- pattern: nil or a list of patterns -- exclude: nil or a list of patterns local result, state = {}, nil local SET_OUTPUT = 1 local SET_PATTERN = 2 local SET_EXCLUDE = 3 local SET_FNAME = 4 local SET_REPEAT = 5 if cmdLine == nil then return result end local function parseOption( option ) if option == '--help' or option == '-h' then result['help'] = true return elseif option == '--version' then result['version'] = true return elseif option == '--verbose' or option == '-v' then result['verbosity'] = M.VERBOSITY_VERBOSE return elseif option == '--quiet' or option == '-q' then result['verbosity'] = M.VERBOSITY_QUIET return elseif option == '--error' or option == '-e' then result['quitOnError'] = true return elseif option == '--failure' or option == '-f' then result['quitOnFailure'] = true return elseif option == '--shuffle' or option == '-s' then result['shuffle'] = true return elseif option == '--output' or option == '-o' then state = SET_OUTPUT return state elseif option == '--name' or option == '-n' then state = SET_FNAME return state elseif option == '--repeat' or option == '-r' then state = SET_REPEAT return state elseif option == '--pattern' or option == '-p' then state = SET_PATTERN return state elseif option == '--exclude' or option == '-x' then state = SET_EXCLUDE return state end error('Unknown option: '..option,3) end local function setArg( cmdArg, state ) if state == SET_OUTPUT then result['output'] = cmdArg return elseif state == SET_FNAME then result['fname'] = cmdArg return elseif state == SET_REPEAT then result['exeRepeat'] = tonumber(cmdArg) or error('Malformed -r argument: '..cmdArg) return elseif state == SET_PATTERN then if result['pattern'] then table.insert( result['pattern'], cmdArg ) else result['pattern'] = { cmdArg } end return elseif state == SET_EXCLUDE then local notArg = '!'..cmdArg if result['pattern'] then table.insert( result['pattern'], notArg ) else result['pattern'] = { notArg } end return end error('Unknown parse state: '.. state) end for i, cmdArg in ipairs(cmdLine) do if state ~= nil then setArg( cmdArg, state, result ) state = nil else if cmdArg:sub(1,1) == '-' then state = parseOption( cmdArg ) else if result['testNames'] then table.insert( result['testNames'], cmdArg ) else result['testNames'] = { cmdArg } end end end end if result['help'] then M.LuaUnit.help() end if result['version'] then M.LuaUnit.version() end if state ~= nil then error('Missing argument after '..cmdLine[ #cmdLine ],2 ) end return result end function M.LuaUnit.help() print(M.USAGE) os.exit(0) end function M.LuaUnit.version() print('LuaUnit v'..M.VERSION..' by Philippe Fremy ') os.exit(0) end ---------------------------------------------------------------- -- class NodeStatus ---------------------------------------------------------------- local NodeStatus = { __class__ = 'NodeStatus' } -- class local NodeStatus_MT = { __index = NodeStatus } -- metatable M.NodeStatus = NodeStatus -- values of status NodeStatus.SUCCESS = 'SUCCESS' NodeStatus.SKIP = 'SKIP' NodeStatus.FAIL = 'FAIL' NodeStatus.ERROR = 'ERROR' function NodeStatus.new( number, testName, className ) -- default constructor, test are PASS by default local t = { number = number, testName = testName, className = className } setmetatable( t, NodeStatus_MT ) t:success() return t end function NodeStatus:success() self.status = self.SUCCESS -- useless because lua does this for us, but it helps me remembering the relevant field names self.msg = nil self.stackTrace = nil end function NodeStatus:skip(msg) self.status = self.SKIP self.msg = msg self.stackTrace = nil end function NodeStatus:fail(msg, stackTrace) self.status = self.FAIL self.msg = msg self.stackTrace = stackTrace end function NodeStatus:error(msg, stackTrace) self.status = self.ERROR self.msg = msg self.stackTrace = stackTrace end function NodeStatus:isSuccess() return self.status == NodeStatus.SUCCESS end function NodeStatus:isNotSuccess() -- Return true if node is either failure or error or skip return (self.status == NodeStatus.FAIL or self.status == NodeStatus.ERROR or self.status == NodeStatus.SKIP) end function NodeStatus:isSkipped() return self.status == NodeStatus.SKIP end function NodeStatus:isFailure() return self.status == NodeStatus.FAIL end function NodeStatus:isError() return self.status == NodeStatus.ERROR end function NodeStatus:statusXML() if self:isError() then return table.concat( {' \n', ' \n'}) elseif self:isFailure() then return table.concat( {' \n', ' \n'}) elseif self:isSkipped() then return table.concat({' ', xmlEscape(self.msg),'\n' } ) end return ' \n' -- (not XSD-compliant! normally shouldn't get here) end --------------[[ Output methods ]]------------------------- local function conditional_plural(number, singular) -- returns a grammatically well-formed string "%d " local suffix = '' if number ~= 1 then -- use plural suffix = (singular:sub(-2) == 'ss') and 'es' or 's' end return string.format('%d %s%s', number, singular, suffix) end function M.LuaUnit.statusLine(result) -- return status line string according to results local s = { string.format('Ran %d tests in %0.3f seconds', result.runCount, result.duration), conditional_plural(result.successCount, 'success'), } if result.notSuccessCount > 0 then if result.failureCount > 0 then table.insert(s, conditional_plural(result.failureCount, 'failure')) end if result.errorCount > 0 then table.insert(s, conditional_plural(result.errorCount, 'error')) end else table.insert(s, '0 failures') end if result.skippedCount > 0 then table.insert(s, string.format("%d skipped", result.skippedCount)) end if result.nonSelectedCount > 0 then table.insert(s, string.format("%d non-selected", result.nonSelectedCount)) end return table.concat(s, ', ') end function M.LuaUnit:startSuite(selectedCount, nonSelectedCount) self.result = { selectedCount = selectedCount, nonSelectedCount = nonSelectedCount, successCount = 0, runCount = 0, currentTestNumber = 0, currentClassName = "", currentNode = nil, suiteStarted = true, startTime = os.clock(), startDate = os.date(os.getenv('LUAUNIT_DATEFMT')), startIsodate = os.date('%Y-%m-%dT%H:%M:%S'), patternIncludeFilter = self.patternIncludeFilter, -- list of test node status allTests = {}, failedTests = {}, errorTests = {}, skippedTests = {}, failureCount = 0, errorCount = 0, notSuccessCount = 0, skippedCount = 0, } self.outputType = self.outputType or TextOutput self.output = self.outputType.new(self) self.output:startSuite() end function M.LuaUnit:startClass( className, classInstance ) self.result.currentClassName = className self.output:startClass( className ) self:setupClass( className, classInstance ) end function M.LuaUnit:startTest( testName ) self.result.currentTestNumber = self.result.currentTestNumber + 1 self.result.runCount = self.result.runCount + 1 self.result.currentNode = NodeStatus.new( self.result.currentTestNumber, testName, self.result.currentClassName ) self.result.currentNode.startTime = os.clock() table.insert( self.result.allTests, self.result.currentNode ) self.output:startTest( testName ) end function M.LuaUnit:updateStatus( err ) -- "err" is expected to be a table / result from protectedCall() if err.status == NodeStatus.SUCCESS then return end local node = self.result.currentNode --[[ As a first approach, we will report only one error or one failure for one test. However, we can have the case where the test is in failure, and the teardown is in error. In such case, it's a good idea to report both a failure and an error in the test suite. This is what Python unittest does for example. However, it mixes up counts so need to be handled carefully: for example, there could be more (failures + errors) count that tests. What happens to the current node ? We will do this more intelligent version later. ]] -- if the node is already in failure/error, just don't report the new error (see above) if node.status ~= NodeStatus.SUCCESS then return end if err.status == NodeStatus.FAIL then node:fail( err.msg, err.trace ) table.insert( self.result.failedTests, node ) elseif err.status == NodeStatus.ERROR then node:error( err.msg, err.trace ) table.insert( self.result.errorTests, node ) elseif err.status == NodeStatus.SKIP then node:skip( err.msg ) table.insert( self.result.skippedTests, node ) else error('No such status: ' .. prettystr(err.status)) end self.output:updateStatus( node ) end function M.LuaUnit:endTest() local node = self.result.currentNode -- print( 'endTest() '..prettystr(node)) -- print( 'endTest() '..prettystr(node:isNotSuccess())) node.duration = os.clock() - node.startTime node.startTime = nil self.output:endTest( node ) if node:isSuccess() then self.result.successCount = self.result.successCount + 1 elseif node:isError() then if self.quitOnError or self.quitOnFailure then -- Runtime error - abort test execution as requested by -- "--error" option. This is done by setting a special -- flag that gets handled in internalRunSuiteByInstances(). print("\nERROR during LuaUnit test execution:\n" .. node.msg) self.result.aborted = true end elseif node:isFailure() then if self.quitOnFailure then -- Failure - abort test execution as requested by -- "--failure" option. This is done by setting a special -- flag that gets handled in internalRunSuiteByInstances(). print("\nFailure during LuaUnit test execution:\n" .. node.msg) self.result.aborted = true end elseif node:isSkipped() then self.result.runCount = self.result.runCount - 1 else error('No such node status: ' .. prettystr(node.status)) end self.result.currentNode = nil end function M.LuaUnit:endClass() self:teardownClass( self.lastClassName, self.lastClassInstance ) self.output:endClass() end function M.LuaUnit:endSuite() if self.result.suiteStarted == false then error('LuaUnit:endSuite() -- suite was already ended' ) end self.result.duration = os.clock()-self.result.startTime self.result.suiteStarted = false -- Expose test counts for outputter's endSuite(). This could be managed -- internally instead by using the length of the lists of failed tests -- but unit tests rely on these fields being present. self.result.failureCount = #self.result.failedTests self.result.errorCount = #self.result.errorTests self.result.notSuccessCount = self.result.failureCount + self.result.errorCount self.result.skippedCount = #self.result.skippedTests self.output:endSuite() end function M.LuaUnit:setOutputType(outputType, fname) -- Configures LuaUnit runner output -- outputType is one of: NIL, TAP, JUNIT, TEXT -- when outputType is junit, the additional argument fname is used to set the name of junit output file -- for other formats, fname is ignored if outputType:upper() == "NIL" then self.outputType = NilOutput return end if outputType:upper() == "TAP" then self.outputType = TapOutput return end if outputType:upper() == "JUNIT" then self.outputType = JUnitOutput if fname then self.fname = fname end return end if outputType:upper() == "TEXT" then self.outputType = TextOutput return end error( 'No such format: '..outputType,2) end --------------[[ Runner ]]----------------- function M.LuaUnit:protectedCall(classInstance, methodInstance, prettyFuncName) -- if classInstance is nil, this is just a function call -- else, it's method of a class being called. local function err_handler(e) -- transform error into a table, adding the traceback information return { status = NodeStatus.ERROR, msg = e, trace = string.sub(debug.traceback("", 1), 2) } end local ok, err if classInstance then -- stupid Lua < 5.2 does not allow xpcall with arguments so let's use a workaround ok, err = xpcall( function () methodInstance(classInstance) end, err_handler ) else ok, err = xpcall( function () methodInstance() end, err_handler ) end if ok then return {status = NodeStatus.SUCCESS} end -- print('ok="'..prettystr(ok)..'" err="'..prettystr(err)..'"') local iter_msg iter_msg = self.exeRepeat and 'iteration '..self.currentCount err.msg, err.status = M.adjust_err_msg_with_iter( err.msg, iter_msg ) if err.status == NodeStatus.SUCCESS or err.status == NodeStatus.SKIP then err.trace = nil return err end -- reformat / improve the stack trace if prettyFuncName then -- we do have the real method name err.trace = err.trace:gsub("in (%a+) 'methodInstance'", "in %1 '"..prettyFuncName.."'") end if STRIP_LUAUNIT_FROM_STACKTRACE then err.trace = stripLuaunitTrace2(err.trace, err.msg) end return err -- return the error "object" (table) end function M.LuaUnit:execOneFunction(className, methodName, classInstance, methodInstance) -- When executing a test function, className and classInstance must be nil -- When executing a class method, all parameters must be set if type(methodInstance) ~= 'function' then self:unregisterSuite() error( tostring(methodName)..' must be a function, not '..type(methodInstance)) end local prettyFuncName if className == nil then className = '[TestFunctions]' prettyFuncName = methodName else prettyFuncName = className..'.'..methodName end if self.lastClassName ~= className then if self.lastClassName ~= nil then self:endClass() end self:startClass( className, classInstance ) self.lastClassName = className self.lastClassInstance = classInstance end self:startTest(prettyFuncName) local node = self.result.currentNode for iter_n = 1, self.exeRepeat or 1 do if node:isNotSuccess() then break end self.currentCount = iter_n -- run setUp first (if any) if classInstance then local func = self.asFunction( classInstance.setUp ) or self.asFunction( classInstance.Setup ) or self.asFunction( classInstance.setup ) or self.asFunction( classInstance.SetUp ) if func then self:updateStatus(self:protectedCall(classInstance, func, className..'.setUp')) end end -- run testMethod() if node:isSuccess() then self:updateStatus(self:protectedCall(classInstance, methodInstance, prettyFuncName)) end -- lastly, run tearDown (if any) if classInstance then local func = self.asFunction( classInstance.tearDown ) or self.asFunction( classInstance.TearDown ) or self.asFunction( classInstance.teardown ) or self.asFunction( classInstance.Teardown ) if func then self:updateStatus(self:protectedCall(classInstance, func, className..'.tearDown')) end end end self:endTest() end function M.LuaUnit.expandOneClass( result, className, classInstance ) --[[ Input: a list of { name, instance }, a class name, a class instance Ouptut: modify result to add all test method instance in the form: { className.methodName, classInstance } ]] for methodName, methodInstance in sortedPairs(classInstance) do if M.LuaUnit.asFunction(methodInstance) and M.LuaUnit.isMethodTestName( methodName ) then table.insert( result, { className..'.'..methodName, classInstance } ) end end end function M.LuaUnit.expandClasses( listOfNameAndInst ) --[[ -- expand all classes (provided as {className, classInstance}) to a list of {className.methodName, classInstance} -- functions and methods remain untouched Input: a list of { name, instance } Output: * { function name, function instance } : do nothing * { class.method name, class instance }: do nothing * { class name, class instance } : add all method names in the form of (className.methodName, classInstance) ]] local result = {} for i,v in ipairs( listOfNameAndInst ) do local name, instance = v[1], v[2] if M.LuaUnit.asFunction(instance) then table.insert( result, { name, instance } ) else if type(instance) ~= 'table' then error( 'Instance must be a table or a function, not a '..type(instance)..' with value '..prettystr(instance)) end local className, methodName = M.LuaUnit.splitClassMethod( name ) if className then local methodInstance = instance[methodName] if methodInstance == nil then error( "Could not find method in class "..tostring(className).." for method "..tostring(methodName) ) end table.insert( result, { name, instance } ) else M.LuaUnit.expandOneClass( result, name, instance ) end end end return result end function M.LuaUnit.applyPatternFilter( patternIncFilter, listOfNameAndInst ) local included, excluded = {}, {} for i, v in ipairs( listOfNameAndInst ) do -- local name, instance = v[1], v[2] if patternFilter( patternIncFilter, v[1] ) then table.insert( included, v ) else table.insert( excluded, v ) end end return included, excluded end local function getKeyInListWithGlobalFallback( key, listOfNameAndInst ) local result = nil for i,v in ipairs( listOfNameAndInst ) do if(listOfNameAndInst[i][1] == key) then result = listOfNameAndInst[i][2] break end end if(not M.LuaUnit.asFunction( result ) ) then result = _G[key] end return result end function M.LuaUnit:setupSuite( listOfNameAndInst ) local setupSuite = getKeyInListWithGlobalFallback("setupSuite", listOfNameAndInst) if self.asFunction( setupSuite ) then self:updateStatus( self:protectedCall( nil, setupSuite, 'setupSuite' ) ) end end function M.LuaUnit:teardownSuite(listOfNameAndInst) local teardownSuite = getKeyInListWithGlobalFallback("teardownSuite", listOfNameAndInst) if self.asFunction( teardownSuite ) then self:updateStatus( self:protectedCall( nil, teardownSuite, 'teardownSuite') ) end end function M.LuaUnit:setupClass( className, instance ) if type( instance ) == 'table' and self.asFunction( instance.setupClass ) then self:updateStatus( self:protectedCall( instance, instance.setupClass, className..'.setupClass' ) ) end end function M.LuaUnit:teardownClass( className, instance ) if type( instance ) == 'table' and self.asFunction( instance.teardownClass ) then self:updateStatus( self:protectedCall( instance, instance.teardownClass, className..'.teardownClass' ) ) end end function M.LuaUnit:internalRunSuiteByInstances( listOfNameAndInst ) --[[ Run an explicit list of tests. Each item of the list must be one of: * { function name, function instance } * { class name, class instance } * { class.method name, class instance } This function is internal to LuaUnit. The official API to perform this action is runSuiteByInstances() ]] local expandedList = self.expandClasses( listOfNameAndInst ) if self.shuffle then randomizeTable( expandedList ) end local filteredList, filteredOutList = self.applyPatternFilter( self.patternIncludeFilter, expandedList ) self:startSuite( #filteredList, #filteredOutList ) self:setupSuite( listOfNameAndInst ) for i,v in ipairs( filteredList ) do local name, instance = v[1], v[2] if M.LuaUnit.asFunction(instance) then self:execOneFunction( nil, name, nil, instance ) else -- expandClasses() should have already taken care of sanitizing the input assert( type(instance) == 'table' ) local className, methodName = M.LuaUnit.splitClassMethod( name ) assert( className ~= nil ) local methodInstance = instance[methodName] assert(methodInstance ~= nil) self:execOneFunction( className, methodName, instance, methodInstance ) end if self.result.aborted then break -- "--error" or "--failure" option triggered end end if self.lastClassName ~= nil then self:endClass() end self:teardownSuite( listOfNameAndInst ) self:endSuite() if self.result.aborted then print("LuaUnit ABORTED (as requested by --error or --failure option)") self:unregisterSuite() os.exit(-2) end end function M.LuaUnit:internalRunSuiteByNames( listOfName ) --[[ Run LuaUnit with a list of generic names, coming either from command-line or from global namespace analysis. Convert the list into a list of (name, valid instances (table or function)) and calls internalRunSuiteByInstances. ]] local instanceName, instance local listOfNameAndInst = {} for i,name in ipairs( listOfName ) do local className, methodName = M.LuaUnit.splitClassMethod( name ) if className then instanceName = className instance = _G[instanceName] if instance == nil then self:unregisterSuite() error( "No such name in global space: "..instanceName ) end if type(instance) ~= 'table' then self:unregisterSuite() error( 'Instance of '..instanceName..' must be a table, not '..type(instance)) end local methodInstance = instance[methodName] if methodInstance == nil then self:unregisterSuite() error( "Could not find method in class "..tostring(className).." for method "..tostring(methodName) ) end else -- for functions and classes instanceName = name instance = _G[instanceName] end if instance == nil then self:unregisterSuite() error( "No such name in global space: "..instanceName ) end if (type(instance) ~= 'table' and type(instance) ~= 'function') then self:unregisterSuite() error( 'Name must match a function or a table: '..instanceName ) end table.insert( listOfNameAndInst, { name, instance } ) end self:internalRunSuiteByInstances( listOfNameAndInst ) end function M.LuaUnit.run(...) -- Run some specific test classes. -- If no arguments are passed, run the class names specified on the -- command line. If no class name is specified on the command line -- run all classes whose name starts with 'Test' -- -- If arguments are passed, they must be strings of the class names -- that you want to run or generic command line arguments (-o, -p, -v, ...) local runner = M.LuaUnit.new() return runner:runSuite(...) end function M.LuaUnit:registerSuite() -- register the current instance into our global array of instances -- print('-> Register suite') M.LuaUnit.instances[ #M.LuaUnit.instances+1 ] = self end function M.unregisterCurrentSuite() -- force unregister the last registered suite table.remove(M.LuaUnit.instances, #M.LuaUnit.instances) end function M.LuaUnit:unregisterSuite() -- print('<- Unregister suite') -- remove our current instqances from the global array of instances local instanceIdx = nil for i, instance in ipairs(M.LuaUnit.instances) do if instance == self then instanceIdx = i break end end if instanceIdx ~= nil then table.remove(M.LuaUnit.instances, instanceIdx) -- print('Unregister done') end end function M.LuaUnit:initFromArguments( ... ) --[[Parses all arguments from either command-line or direct call and set internal flags of LuaUnit runner according to it. Return the list of names which were possibly passed on the command-line or as arguments ]] local args = {...} if type(args[1]) == 'table' and args[1].__class__ == 'LuaUnit' then -- run was called with the syntax M.LuaUnit:runSuite() -- we support both M.LuaUnit.run() and M.LuaUnit:run() -- strip out the first argument self to make it a command-line argument list table.remove(args,1) end if #args == 0 then args = cmdline_argv end local options = pcall_or_abort( M.LuaUnit.parseCmdLine, args ) -- We expect these option fields to be either `nil` or contain -- valid values, so it's safe to always copy them directly. self.verbosity = options.verbosity self.quitOnError = options.quitOnError self.quitOnFailure = options.quitOnFailure self.exeRepeat = options.exeRepeat self.patternIncludeFilter = options.pattern self.shuffle = options.shuffle options.output = options.output or os.getenv('LUAUNIT_OUTPUT') options.fname = options.fname or os.getenv('LUAUNIT_JUNIT_FNAME') if options.output then if options.output:lower() == 'junit' and options.fname == nil then print('With junit output, a filename must be supplied with -n or --name') os.exit(-1) end pcall_or_abort(self.setOutputType, self, options.output, options.fname) end return options.testNames end function M.LuaUnit:runSuite( ... ) testNames = self:initFromArguments(...) self:registerSuite() self:internalRunSuiteByNames( testNames or M.LuaUnit.collectTests() ) self:unregisterSuite() return self.result.notSuccessCount end function M.LuaUnit:runSuiteByInstances( listOfNameAndInst, commandLineArguments ) --[[ Run all test functions or tables provided as input. Input: a list of { name, instance } instance can either be a function or a table containing test functions starting with the prefix "test" return the number of failures and errors, 0 meaning success ]] -- parse the command-line arguments testNames = self:initFromArguments( commandLineArguments ) self:registerSuite() self:internalRunSuiteByInstances( listOfNameAndInst ) self:unregisterSuite() return self.result.notSuccessCount end -- class LuaUnit -- For compatbility with LuaUnit v2 M.run = M.LuaUnit.run M.Run = M.LuaUnit.run function M:setVerbosity( verbosity ) -- set the verbosity value (as integer) M.LuaUnit.verbosity = verbosity end M.set_verbosity = M.setVerbosity M.SetVerbosity = M.setVerbosity return M luaunit-LUAUNIT_V3_4/run_functional_tests.lua000077500000000000000000001074101401773523200214360ustar00rootroot00000000000000#!/usr/bin/env lua require('os') local lu = require('luaunit') local function report( ... ) print('>>>>>>>', string.format(...)) end local function error_fmt( ... ) error(string.format(...), 2) -- (level 2 = report chunk calling error_fmt) end local IS_UNIX = ( package.config:sub(1,1) == '/' ) local LUA='"'..arg[-1]..'"' -- Escape a string so it can safely be used as a Lua pattern without triggering -- special semantics. This means prepending any "magic" character ^$()%.[]*+-? -- with a percent sign. Note: We DON'T expect embedded NUL chars, and thus -- won't escape those (%z) for Lua 5.1. local LUA_MAGIC_CHARS = "[%^%$%(%)%%%.%[%]%*%+%-%?]" local function escape_lua_pattern(s) return s:gsub(LUA_MAGIC_CHARS, "%%%1") -- substitute with '%' + matched char end local function string_gsub(s, orig, repl) -- replace occurrence of string orig by string repl -- just like string.gsub, but with no pattern matching -- print( 'gsub_input '..s..' '..orig..' '..repl) return s:gsub( escape_lua_pattern(orig), repl ) end function testStringSub() lu.assertEquals( string_gsub('aa a % b cc', 'a % b', 'a + b'), 'aa a + b cc' ) lu.assertEquals( string_gsub('aa: ?cc', ': ?', 'xx?'), 'aaxx?cc' ) lu.assertEquals( string_gsub('aa b: cc b: ee', 'b:', 'xx'), 'aa xx cc xx ee' ) end local function osExec( ... ) -- execute a command with os.execute and return true if exit code is 0 -- false in any other conditions local cmd = string.format(...) if not(IS_UNIX) and cmd:sub(1, 1) == '"' then -- In case we're running on Windows, and if the command starts with a -- quote: It's reasonable (or even necessary in some cases) to enclose -- the entire command string in another pair of quotes. (This is needed -- to preserve other quotes, due to how os.execute makes use of cmd.exe) -- see e.g. http://lua-users.org/lists/lua-l/2014-06/msg00551.html cmd = '"' .. cmd .. '"' end -- print('osExec('..cmd..')') local exitSuccess, exitReason, exitCode = os.execute( cmd ) -- print('\n', exitSuccess, exitReason, exitCode) if exitReason == nil and exitCode == nil then -- Lua 5.1 returns only the exit code exitReason = 'exit' if IS_UNIX then -- in C: exitCode = (exitSuccess >> 8) & 0xFF -- poor approximation that works: exitCode = (exitSuccess / 256) else -- Windows, life is simple exitCode = exitSuccess end end -- Use heuristics to determine negative exit codes, -- assuming that those are in the range -8 to -1: if exitCode >= 248 then exitCode = exitCode - 256 end -- Lua 5.2+ has a weird way of dealing with exit code -1, at least on Windows if exitReason == 'No error' then exitReason = 'exit' exitCode = -1 end if exitReason ~= 'exit' or exitCode ~= 0 then -- print('return false '..tostring(exitCode)) return false, exitCode end -- print('return true') return true, exitCode end local function osExpectedCodeExec( refExitCode, ... ) local cmd = string.format(...) local ret, exitCode = osExec( cmd ) if refExitCode and (exitCode ~= refExitCode) then error_fmt('Expected exit code %d, but got %d for: %s', refExitCode, exitCode, cmd) end return ret end local HAS_XMLLINT do local xmllint_output_fname = 'test/has_xmllint.txt' HAS_XMLLINT = osExec('xmllint --version 2> '..xmllint_output_fname) if not HAS_XMLLINT then report('WARNING: xmllint absent, can not validate xml validity') end os.remove(xmllint_output_fname) end local function adjustFile( fileOut, fileIn, pattern, mayBeAbsent, verbose ) --[[ Adjust the content of fileOut by copying lines matching pattern from fileIn fileIn lines are read and the first line matching pattern is analysed. The first pattern capture is memorized. fileOut lines are then read, and the first line matching pattern is modified, by applying the first capture of fileIn. fileOut is then rewritten. In most cases, pattern2 may be nil in which case, pattern is used when matching in fileout. ]] if verbose then print('Using reference file: '..fileIn) end local source, idxStart, idxEnd, capture = nil for line in io.lines(fileIn) do idxStart, idxEnd, capture = line:find( pattern ) if idxStart ~= nil then if capture == nil then error_fmt('Must specify a capture for pattern %s in function adjustFile()', pattern) end source = capture break end end if source == nil then if mayBeAbsent then return -- no capture, just return end error_fmt('No line in file %s matching pattern "%s"', fileIn, pattern) end if verbose then print('Captured in source: '.. source ) print('Modifying file: '..fileOut) end local dest, linesOut = nil, {} for line in io.lines(fileOut) do idxStart, idxEnd, capture = line:find( pattern ) while idxStart ~= nil do if capture == nil then print('missing pattern for outfile!') end dest = capture if verbose then print('Modifying line: '..line ) end line = string_gsub(line, dest, source) -- line = line:sub(1,idxStart-1)..source..line:sub(idxEnd+1) -- string.gsub( line, dest, source ) if verbose then print('Result : '..line ) end idxStart, idxEnd, capture = line:find( pattern, idxEnd ) end table.insert( linesOut, line ) end if dest == nil then if mayBeAbsent then return -- capture but nothing to adjust, just return end error_fmt('No line in file %s matching pattern "%s"', fileOut, pattern) end local f = io.open( fileOut, 'w') f:write(table.concat(linesOut, '\n'), '\n') f:close() end local function check_tap_output( fileToRun, options, output, refOutput, refExitCode, envOptions, outputArg ) -- remove output envOptions = envOptions or '' outputArg = outputArg or '' -- by default, if nothing is provided, we set output explicitely -- but we leave the option for the caller to provide either environment and/or output arguments if envOptions == '' and outputArg == '' then outputArg = '--output TAP' end if envOptions ~= '' then envOptions = '/usr/bin/env ' .. envOptions end osExpectedCodeExec(refExitCode, '%s %s %s %s %s > %s', envOptions, LUA, fileToRun, outputArg, options, output) adjustFile( output, refOutput, '# Started on (.*)') adjustFile( output, refOutput, '# Ran %d+ tests in (%d+.%d*).*') if _VERSION ~= 'Lua 5.2' and _VERSION ~= 'Lua 5.1' then -- For Lua 5.3: stack trace uses "method" instead of "function" adjustFile( output, refOutput, '.*%.lua:%d+: in (%S*) .*', true ) end if not osExec([[diff -NPw -u -I " *\.[/\\]luaunit.lua:[0123456789]\+:.*" %s %s]], refOutput, output) then error('TAP Output mismatch for file : '..output) end -- report('TAP Output ok: '..output) return 0 end local function check_text_output( fileToRun, options, output, refOutput, refExitCode ) -- remove output osExpectedCodeExec(refExitCode, '%s %s --output text %s > %s', LUA, fileToRun, options, output) if options:find( '--verbose' ) then adjustFile( output, refOutput, 'Started on (.*)') end adjustFile( output, refOutput, 'Ran .* tests in (%d.%d*) seconds' ) adjustFile( output, refOutput, 'Ran .* tests in (%d.%d*) seconds' ) adjustFile( output, refOutput, 'thread: (0?x?[%x]+)', true ) adjustFile( output, refOutput, 'function: (0?x?[%x]+)', true ) adjustFile( output, refOutput, '', true ) adjustFile( output, refOutput, '
', true ) if _VERSION ~= 'Lua 5.2' and _VERSION ~= 'Lua 5.1' then -- For Lua 5.3: stack trace uses "method" instead of "function" adjustFile( output, refOutput, '.*%.lua:%d+: in (%S*) .*', true ) end if not osExec([[diff -NPw -u -I " *\.[/\\]luaunit.lua:[0123456789]\+:.*" %s %s]], refOutput, output) then error('Text Output mismatch for file : '..output) end -- report('Text Output ok: '..output) return 0 end local function check_nil_output( fileToRun, options, output, refOutput, refExitCode ) -- remove output osExpectedCodeExec(refExitCode, '%s %s --output nil %s > %s', LUA, fileToRun, options, output) if not osExec([[diff -NPw -u -I " *\.[/\\]luaunit.lua:[0123456789]\+:.*" %s %s]], refOutput, output) then error('NIL Output mismatch for file : '..output) end -- report('NIL Output ok: '..output) return 0 end local function check_xml_output( fileToRun, options, output, xmlOutput, xmlLintOutput, refOutput, refXmlOutput, refExitCode, envOptions, outputArg ) local retcode = 0 envOptions = envOptions or '' outputArg = outputArg or '' -- by default, if nothing is provided, we set output explicitely -- but we leave the option for the caller to provide either environment and/or output arguments if envOptions == '' and outputArg == '' then outputArg = '--output junit --name '..xmlOutput end if envOptions ~= '' then envOptions = '/usr/bin/env ' .. envOptions end -- remove output osExpectedCodeExec(refExitCode, '%s %s %s %s %s > %s', envOptions, LUA, fileToRun, outputArg, options, output) adjustFile( output, refOutput, '# XML output to (.*)') adjustFile( output, refOutput, '# Started on (.*)') adjustFile( output, refOutput, '# Ran %d+ tests in (%d+.%d*).*') adjustFile( xmlOutput, refXmlOutput, '.*') if _VERSION ~= 'Lua 5.2' and _VERSION ~= 'Lua 5.1' then -- For Lua 5.3: stack trace uses "method" instead of "function" -- For Lua 5.4: stack trace uses "method" or "upvalue" instead of "function" adjustFile( output, refOutput, '.*%.lua:%d+: in (%S*) .*', true ) adjustFile( xmlOutput, refXmlOutput, '.*%.lua:%d+: in (%S*) .*', true ) end if HAS_XMLLINT then -- General xmllint validation if osExec('xmllint --noout %s > %s', xmlOutput, xmlLintOutput) then -- report('XMLLint validation ok: file %s', xmlLintOutput) else error_fmt('XMLLint reported errors : file %s', xmlLintOutput) retcode = retcode + 1 end -- we used to validate against apache and/maven xsd but the way it handles skipped test -- is just too specific. I prefer the jenkins way. -- Validation against jenkins/hudson schema if osExec('xmllint --noout --schema junitxml/junit-jenkins.xsd %s 2> %s', xmlOutput, xmlLintOutput) then -- report('XMLLint validation ok: file %s', xmlLintOutput) else error_fmt('XMLLint reported errors against jenkins schema: file %s', xmlLintOutput) retcode = retcode + 1 end end -- ignore change in line numbers for luaunit if not osExec([[diff -NPw -u -I " *\.[/\\]luaunit.lua:[0123456789]\+:.*" %s %s]], refXmlOutput, xmlOutput) then error('XML content mismatch for file : '..xmlOutput) retcode = retcode + 1 end if not osExec([[diff -NPw -u -I " *\.[/\\]luaunit.lua:[0123456789]\+:.*" %s %s]], refOutput, output) then error('XML Output mismatch for file : '..output) retcode = retcode + 1 end --[[ if retcode == 0 then report('XML Output ok: '..output) end --]] return retcode end -- check tap output function testTapDefault() lu.assertEquals( 0, check_tap_output('example_with_luaunit.lua', '', 'test/exampleTapDefault.txt', 'test/ref/exampleTapDefault.txt', 12) ) lu.assertEquals( 0, check_tap_output('test/test_with_err_fail_pass.lua', '', 'test/errFailPassTapDefault.txt', 'test/ref/errFailPassTapDefault.txt', 10 ) ) lu.assertEquals( 0, check_tap_output('test/test_with_err_fail_pass.lua', '-p Succ', 'test/errFailPassTapDefault-success.txt', 'test/ref/errFailPassTapDefault-success.txt', 0 ) ) lu.assertEquals( 0, check_tap_output('test/test_with_err_fail_pass.lua', '-p Succ -p Fail', 'test/errFailPassTapDefault-failures.txt', 'test/ref/errFailPassTapDefault-failures.txt', 5 ) ) if IS_UNIX then -- It is non-trivial to set the environment for new command execution -- on Windows, so we'll only attempt it on UNIX. These systems should -- all have /usr/bin/env lu.assertEquals( 0, check_tap_output('test/test_with_err_fail_pass.lua', '-p Succ -p Fail', 'test/errFailPassTapDefault-failures.txt', 'test/ref/errFailPassTapDefault-failures.txt', 5, 'LUAUNIT_OUTPUT=TAP' ) ) -- force an alternate file format, check that command-line option prevails lu.assertEquals( 0, check_tap_output('test/test_with_err_fail_pass.lua', '-p Succ -p Fail', 'test/errFailPassTapDefault-failures.txt', 'test/ref/errFailPassTapDefault-failures.txt', 5, 'LUAUNIT_OUTPUT=TEXT', '--output tap' ) ) end end function testTapVerbose() lu.assertEquals( 0, check_tap_output('example_with_luaunit.lua', '--verbose', 'test/exampleTapVerbose.txt', 'test/ref/exampleTapVerbose.txt', 12 ) ) lu.assertEquals( 0, check_tap_output('test/test_with_err_fail_pass.lua', '--verbose', 'test/errFailPassTapVerbose.txt', 'test/ref/errFailPassTapVerbose.txt', 10 ) ) lu.assertEquals( 0, check_tap_output('test/test_with_err_fail_pass.lua', '--verbose -p Succ', 'test/errFailPassTapVerbose-success.txt', 'test/ref/errFailPassTapVerbose-success.txt', 0 ) ) lu.assertEquals( 0, check_tap_output('test/test_with_err_fail_pass.lua', '--verbose -p Succ -p Fail', 'test/errFailPassTapVerbose-failures.txt', 'test/ref/errFailPassTapVerbose-failures.txt', 5 ) ) end function testTapQuiet() lu.assertEquals( 0, check_tap_output('example_with_luaunit.lua', '--quiet', 'test/exampleTapQuiet.txt', 'test/ref/exampleTapQuiet.txt', 12 ) ) lu.assertEquals( 0, check_tap_output('test/test_with_err_fail_pass.lua', '--quiet', 'test/errFailPassTapQuiet.txt', 'test/ref/errFailPassTapQuiet.txt', 10 ) ) lu.assertEquals( 0, check_tap_output('test/test_with_err_fail_pass.lua', '--quiet -p Succ', 'test/errFailPassTapQuiet-success.txt', 'test/ref/errFailPassTapQuiet-success.txt', 0 ) ) lu.assertEquals( 0, check_tap_output('test/test_with_err_fail_pass.lua', '--quiet -p Succ -p Fail', 'test/errFailPassTapQuiet-failures.txt', 'test/ref/errFailPassTapQuiet-failures.txt', 5 ) ) end -- check text output function testTextDefault() lu.assertEquals( 0, check_text_output('example_with_luaunit.lua', '', 'test/exampleTextDefault.txt', 'test/ref/exampleTextDefault.txt', 12 ) ) lu.assertEquals( 0, check_text_output('test/test_with_err_fail_pass.lua', '', 'test/errFailPassTextDefault.txt', 'test/ref/errFailPassTextDefault.txt', 10 ) ) lu.assertEquals( 0, check_text_output('test/test_with_err_fail_pass.lua', '-p Succ', 'test/errFailPassTextDefault-success.txt', 'test/ref/errFailPassTextDefault-success.txt', 0 ) ) lu.assertEquals( 0, check_text_output('test/test_with_err_fail_pass.lua', '-p Succ -p Fail', 'test/errFailPassTextDefault-failures.txt', 'test/ref/errFailPassTextDefault-failures.txt', 5 ) ) end function testTextVerbose() lu.assertEquals( 0, check_text_output('example_with_luaunit.lua', '--verbose', 'test/exampleTextVerbose.txt', 'test/ref/exampleTextVerbose.txt', 12 ) ) lu.assertEquals( 0, check_text_output('test/test_with_err_fail_pass.lua', '--verbose', 'test/errFailPassTextVerbose.txt', 'test/ref/errFailPassTextVerbose.txt', 10 ) ) lu.assertEquals( 0, check_text_output('test/test_with_err_fail_pass.lua', '--verbose -p Succ', 'test/errFailPassTextVerbose-success.txt', 'test/ref/errFailPassTextVerbose-success.txt', 0 ) ) lu.assertEquals( 0, check_text_output('test/test_with_err_fail_pass.lua', '--verbose -p Succ -p Fail', 'test/errFailPassTextVerbose-failures.txt', 'test/ref/errFailPassTextVerbose-failures.txt', 5 ) ) end function testTextQuiet() lu.assertEquals( 0, check_text_output('example_with_luaunit.lua', '--quiet', 'test/exampleTextQuiet.txt', 'test/ref/exampleTextQuiet.txt', 12 ) ) lu.assertEquals( 0, check_text_output('test/test_with_err_fail_pass.lua', '--quiet', 'test/errFailPassTextQuiet.txt', 'test/ref/errFailPassTextQuiet.txt', 10 ) ) lu.assertEquals( 0, check_text_output('test/test_with_err_fail_pass.lua', '--quiet -p Succ', 'test/errFailPassTextQuiet-success.txt', 'test/ref/errFailPassTextQuiet-success.txt', 0 ) ) lu.assertEquals( 0, check_text_output('test/test_with_err_fail_pass.lua', '--quiet -p Succ -p Fail', 'test/errFailPassTextQuiet-failures.txt', 'test/ref/errFailPassTextQuiet-failures.txt', 5 ) ) end -- check nil output function testNilDefault() lu.assertEquals( 0, check_nil_output('example_with_luaunit.lua', '', 'test/exampleNilDefault.txt', 'test/ref/exampleNilDefault.txt', 12 ) ) lu.assertEquals( 0, check_nil_output('test/test_with_err_fail_pass.lua', '', 'test/errFailPassNilDefault.txt', 'test/ref/errFailPassNilDefault.txt', 10 ) ) lu.assertEquals( 0, check_nil_output('test/test_with_err_fail_pass.lua', ' -p Succ', 'test/errFailPassNilDefault-success.txt', 'test/ref/errFailPassNilDefault-success.txt', 0 ) ) lu.assertEquals( 0, check_nil_output('test/test_with_err_fail_pass.lua', ' -p Succ -p Fail', 'test/errFailPassNilDefault-failures.txt', 'test/ref/errFailPassNilDefault-failures.txt', 5 ) ) end -- check xml output function testXmlDefault() lu.assertEquals( 0, check_xml_output('example_with_luaunit.lua', '', 'test/exampleXmlDefault.txt', 'test/exampleXmlDefault.xml', 'test/exampleXmllintDefault.xml', 'test/ref/exampleXmlDefault.txt', 'test/ref/exampleXmlDefault.xml', 12 ) ) lu.assertEquals( 0, check_xml_output('test/test_with_err_fail_pass.lua', '', 'test/errFailPassXmlDefault.txt', 'test/errFailPassXmlDefault.xml', 'test/errFailPassXmllintDefault.xml', 'test/ref/errFailPassXmlDefault.txt', 'test/ref/errFailPassXmlDefault.xml', 10 ) ) lu.assertEquals( 0, check_xml_output('test/test_with_err_fail_pass.lua', '-p Succ', 'test/errFailPassXmlDefault-success.txt', 'test/errFailPassXmlDefault-success.xml', 'test/errFailPassXmllintDefault.xml', 'test/ref/errFailPassXmlDefault-success.txt', 'test/ref/errFailPassXmlDefault-success.xml', 0 ) ) lu.assertEquals( 0, check_xml_output('test/test_with_err_fail_pass.lua', '-p Succ -p Fail', 'test/errFailPassXmlDefault-failures.txt', 'test/errFailPassXmlDefault-failures.xml', 'test/errFailPassXmllintDefault.xml', 'test/ref/errFailPassXmlDefault-failures.txt', 'test/ref/errFailPassXmlDefault-failures.xml', 5 ) ) -- disable this test not working ! if IS_UNIX and false then -- It is non-trivial to set the environment for new command execution -- on Windows, so we'll only attempt it on UNIX. These systems should -- all have /usr/bin/env lu.assertEquals( 0, check_xml_output('test/test_with_err_fail_pass.lua', '-p Succ -p Fail', 'test/errFailPassXmlDefault-failures.txt', 'test/errFailPassXmlDefault-failures.xml', 'test/errFailPassXmllintDefault.xml', 'test/ref/errFailPassXmlDefault-failures.txt', 'test/ref/errFailPassXmlDefault-failures.xml', 5, 'LUAUNIT_OUTPUT=JUNIT LUAUNIT_JUNIT_FNAME=test/ref/errFailPassXmlDefault-failures.xml', '' ) ) end end function testXmlVerbose() lu.assertEquals( 0, check_xml_output('example_with_luaunit.lua', '--verbose', 'test/exampleXmlVerbose.txt', 'test/exampleXmlVerbose.xml', 'test/exampleXmllintVerbose.xml', 'test/ref/exampleXmlVerbose.txt', 'test/ref/exampleXmlVerbose.xml', 12 ) ) lu.assertEquals( 0, check_xml_output('test/test_with_err_fail_pass.lua', '--verbose ', 'test/errFailPassXmlVerbose.txt', 'test/errFailPassXmlVerbose.xml', 'test/errFailPassXmllintVerbose.xml', 'test/ref/errFailPassXmlVerbose.txt', 'test/ref/errFailPassXmlVerbose.xml', 10 ) ) lu.assertEquals( 0, check_xml_output('test/test_with_err_fail_pass.lua', '--verbose -p Succ', 'test/errFailPassXmlVerbose-success.txt', 'test/errFailPassXmlVerbose-success.xml', 'test/errFailPassXmllintVerbose.xml', 'test/ref/errFailPassXmlVerbose-success.txt', 'test/ref/errFailPassXmlVerbose-success.xml', 0 ) ) lu.assertEquals( 0, check_xml_output('test/test_with_err_fail_pass.lua', '--verbose -p Succ -p Fail', 'test/errFailPassXmlVerbose-failures.txt', 'test/errFailPassXmlVerbose-failures.xml', 'test/errFailPassXmllintVerbose.xml', 'test/ref/errFailPassXmlVerbose-failures.txt', 'test/ref/errFailPassXmlVerbose-failures.xml', 5 ) ) end function testXmlQuiet() lu.assertEquals( 0, check_xml_output('example_with_luaunit.lua', '--quiet', 'test/exampleXmlQuiet.txt', 'test/exampleXmlQuiet.xml', 'test/exampleXmllintQuiet.xml', 'test/ref/exampleXmlQuiet.txt', 'test/ref/exampleXmlQuiet.xml', 12 ) ) lu.assertEquals( 0, check_xml_output('test/test_with_err_fail_pass.lua', '--quiet ', 'test/errFailPassXmlQuiet.txt', 'test/errFailPassXmlQuiet.xml', 'test/errFailPassXmllintQuiet.xml', 'test/ref/errFailPassXmlQuiet.txt', 'test/ref/errFailPassXmlQuiet.xml', 10 ) ) lu.assertEquals( 0, check_xml_output('test/test_with_err_fail_pass.lua', '--quiet -p Succ', 'test/errFailPassXmlQuiet-success.txt', 'test/errFailPassXmlQuiet-success.xml', 'test/errFailPassXmllintQuiet.xml', 'test/ref/errFailPassXmlQuiet-success.txt', 'test/ref/errFailPassXmlQuiet-success.xml', 0 ) ) lu.assertEquals( 0, check_xml_output('test/test_with_err_fail_pass.lua', '--quiet -p Succ -p Fail', 'test/errFailPassXmlQuiet-failures.txt', 'test/errFailPassXmlQuiet-failures.xml', 'test/errFailPassXmllintQuiet.xml', 'test/ref/errFailPassXmlQuiet-failures.txt', 'test/ref/errFailPassXmlQuiet-failures.xml', 5 ) ) end function testTestWithXmlDefault() lu.assertEquals( 0, check_xml_output('test/test_with_xml.lua', '', 'test/testWithXmlDefault.txt', 'test/testWithXmlDefault.xml', 'test/testWithXmlLintDefault.txt', 'test/ref/testWithXmlDefault.txt', 'test/ref/testWithXmlDefault.xml', 2 ) ) end function testTestWithXmlVerbose() lu.assertEquals( 0, check_xml_output('test/test_with_xml.lua', '--verbose', 'test/testWithXmlVerbose.txt', 'test/testWithXmlVerbose.xml', 'test/testWithXmlLintVerbose.txt', 'test/ref/testWithXmlVerbose.txt', 'test/ref/testWithXmlVerbose.xml', 2 ) ) end function testTestWithXmlQuiet() lu.assertEquals( 0, check_xml_output('test/test_with_xml.lua', '--quiet', 'test/testWithXmlQuiet.txt', 'test/testWithXmlQuiet.xml', 'test/testWithXmlLintQuiet.txt', 'test/ref/testWithXmlQuiet.txt', 'test/ref/testWithXmlQuiet.xml', 2 ) ) end function testListComparison() -- run test/some_lists_comparisons and check exit status lu.assertEquals( 0, check_text_output('test/some_lists_comparisons.lua', '--verbose', 'test/some_lists_comparisons.txt', 'test/ref/some_lists_comparisons.txt', 11 ) ) end function testLegacyLuaunitUsage() -- run test/legacy_example_usage and check exit status (expecting 12 failures) osExpectedCodeExec(12, '%s %s --output text > %s', LUA, "test/legacy_example_with_luaunit.lua", "test/legacyExample.txt") end function testLuaunitV2Usage() osExpectedCodeExec(0, '%s %s --output text 1> %s 2>&1', LUA, "test/compat_luaunit_v2x.lua", "test/compat_luaunit_v2x.txt") end function testBasicLuaunitOptions() osExpectedCodeExec(0, '%s example_with_luaunit.lua --help > test/null.txt', LUA) osExpectedCodeExec(0, '%s example_with_luaunit.lua --version > test/null.txt', LUA) -- test invalid syntax osExpectedCodeExec(-1, '%s example_with_luaunit.lua --foobar > test/null.txt', LUA) -- invalid option osExpectedCodeExec(-1, '%s example_with_luaunit.lua --output foobar > test/null.txt', LUA) -- invalid format osExpectedCodeExec(-1, '%s example_with_luaunit.lua --output junit > test/null.txt', LUA) -- missing output name os.remove('test/null.txt') end function testStopOnError() lu.assertEquals( 0, check_text_output('test/test_with_err_fail_pass.lua', '--quiet -p Succ --error --failure', 'test/errFailPassTextStopOnError-1.txt', 'test/ref/errFailPassTextStopOnError-1.txt', 0 ) ) lu.assertEquals( 0, check_text_output('test/test_with_err_fail_pass.lua', '--quiet -p TestSome --error', 'test/errFailPassTextStopOnError-2.txt', 'test/ref/errFailPassTextStopOnError-2.txt', -2 ) ) lu.assertEquals( 0, check_text_output('test/test_with_err_fail_pass.lua', '--quiet -p TestAnoth --failure', 'test/errFailPassTextStopOnError-3.txt', 'test/ref/errFailPassTextStopOnError-3.txt', -2 ) ) lu.assertEquals( 0, check_text_output('test/test_with_err_fail_pass.lua', '--quiet -p TestSome --failure', 'test/errFailPassTextStopOnError-4.txt', 'test/ref/errFailPassTextStopOnError-4.txt', -2 ) ) end local filesToGenerateExampleXml = { { 'example_with_luaunit.lua', '', '--output junit --name test/ref/exampleXmlDefault.xml', 'test/ref/exampleXmlDefault.txt' }, { 'example_with_luaunit.lua', '--quiet', '--output junit --name test/ref/exampleXmlQuiet.xml', 'test/ref/exampleXmlQuiet.txt' }, { 'example_with_luaunit.lua', '--verbose', '--output junit --name test/ref/exampleXmlVerbose.xml', 'test/ref/exampleXmlVerbose.txt' }, } local filesToGenerateExampleTap = { { 'example_with_luaunit.lua', '', '--output tap', 'test/ref/exampleTapDefault.txt' }, { 'example_with_luaunit.lua', '--quiet', '--output tap', 'test/ref/exampleTapQuiet.txt' }, { 'example_with_luaunit.lua', '--verbose', '--output tap', 'test/ref/exampleTapVerbose.txt' }, } local filesToGenerateExampleText = { { 'example_with_luaunit.lua', '', '--output text', 'test/ref/exampleTextDefault.txt' }, { 'example_with_luaunit.lua', '--quiet', '--output text', 'test/ref/exampleTextQuiet.txt' }, { 'example_with_luaunit.lua', '--verbose', '--output text', 'test/ref/exampleTextVerbose.txt' }, } local filesToGenerateExampleNil = { { 'example_with_luaunit.lua', '', '--output nil', 'test/ref/exampleNilDefault.txt' }, } local filesToGenerateErrFailPassXml = { { 'test/test_with_err_fail_pass.lua', '', '--output junit --name test/ref/errFailPassXmlDefault.xml', 'test/ref/errFailPassXmlDefault.txt' }, { 'test/test_with_err_fail_pass.lua', '', '-p Succ --output junit --name test/ref/errFailPassXmlDefault-success.xml', 'test/ref/errFailPassXmlDefault-success.txt' }, { 'test/test_with_err_fail_pass.lua', '', '-p Succ -p Fail --output junit --name test/ref/errFailPassXmlDefault-failures.xml', 'test/ref/errFailPassXmlDefault-failures.txt' }, { 'test/test_with_err_fail_pass.lua', '', '--quiet --output junit --name test/ref/errFailPassXmlQuiet.xml', 'test/ref/errFailPassXmlQuiet.txt' }, { 'test/test_with_err_fail_pass.lua', '', '-p Succ --quiet --output junit --name test/ref/errFailPassXmlQuiet-success.xml', 'test/ref/errFailPassXmlQuiet-success.txt' }, { 'test/test_with_err_fail_pass.lua', '', '-p Succ -p Fail --quiet --output junit --name test/ref/errFailPassXmlQuiet-failures.xml', 'test/ref/errFailPassXmlQuiet-failures.txt' }, { 'test/test_with_err_fail_pass.lua', '', '--verbose --output junit --name test/ref/errFailPassXmlVerbose.xml', 'test/ref/errFailPassXmlVerbose.txt' }, { 'test/test_with_err_fail_pass.lua', '', '-p Succ --verbose --output junit --name test/ref/errFailPassXmlVerbose-success.xml', 'test/ref/errFailPassXmlVerbose-success.txt' }, { 'test/test_with_err_fail_pass.lua', '', '-p Succ -p Fail --verbose --output junit --name test/ref/errFailPassXmlVerbose-failures.xml', 'test/ref/errFailPassXmlVerbose-failures.txt' }, } local filesToGenerateErrFailPassTap = { { 'test/test_with_err_fail_pass.lua', '', '--output tap', 'test/ref/errFailPassTapDefault.txt' }, { 'test/test_with_err_fail_pass.lua', '-p Succ', '--output tap', 'test/ref/errFailPassTapDefault-success.txt' }, { 'test/test_with_err_fail_pass.lua', '-p Succ -p Fail', '--output tap', 'test/ref/errFailPassTapDefault-failures.txt' }, { 'test/test_with_err_fail_pass.lua', '--quiet', '--output tap', 'test/ref/errFailPassTapQuiet.txt' }, { 'test/test_with_err_fail_pass.lua', '-p Succ --quiet', '--output tap', 'test/ref/errFailPassTapQuiet-success.txt' }, { 'test/test_with_err_fail_pass.lua', '-p Succ -p Fail --quiet', '--output tap', 'test/ref/errFailPassTapQuiet-failures.txt' }, { 'test/test_with_err_fail_pass.lua', '--verbose', '--output tap', 'test/ref/errFailPassTapVerbose.txt' }, { 'test/test_with_err_fail_pass.lua', '-p Succ --verbose', '--output tap', 'test/ref/errFailPassTapVerbose-success.txt' }, { 'test/test_with_err_fail_pass.lua', '-p Succ -p Fail --verbose', '--output tap', 'test/ref/errFailPassTapVerbose-failures.txt' }, } local filesToGenerateErrFailPassText = { { 'test/test_with_err_fail_pass.lua', '', '--output text', 'test/ref/errFailPassTextDefault.txt' }, { 'test/test_with_err_fail_pass.lua', '-p Succ', '--output text', 'test/ref/errFailPassTextDefault-success.txt' }, { 'test/test_with_err_fail_pass.lua', '-p Succ -p Fail', '--output text', 'test/ref/errFailPassTextDefault-failures.txt' }, { 'test/test_with_err_fail_pass.lua', '--quiet', '--output text', 'test/ref/errFailPassTextQuiet.txt' }, { 'test/test_with_err_fail_pass.lua', '-p Succ --quiet', '--output text', 'test/ref/errFailPassTextQuiet-success.txt' }, { 'test/test_with_err_fail_pass.lua', '-p Succ -p Fail --quiet', '--output text', 'test/ref/errFailPassTextQuiet-failures.txt' }, { 'test/test_with_err_fail_pass.lua', '--verbose', '--output text', 'test/ref/errFailPassTextVerbose.txt' }, { 'test/test_with_err_fail_pass.lua', '-p Succ --verbose', '--output text', 'test/ref/errFailPassTextVerbose-success.txt' }, { 'test/test_with_err_fail_pass.lua', '-p Succ -p Fail --verbose', '--output text', 'test/ref/errFailPassTextVerbose-failures.txt' }, } local filesToGenerateTestXml = { { 'test/test_with_xml.lua', '', '--output junit --name test/ref/testWithXmlDefault.xml', 'test/ref/testWithXmlDefault.txt' }, { 'test/test_with_xml.lua', '--verbose', '--output junit --name test/ref/testWithXmlVerbose.xml', 'test/ref/testWithXmlVerbose.txt' }, { 'test/test_with_xml.lua', '--quiet', '--output junit --name test/ref/testWithXmlQuiet.xml', 'test/ref/testWithXmlQuiet.txt' }, } local filesToGenerateStopOnError = { { 'test/test_with_err_fail_pass.lua', '', '--output text --quiet -p Succ --error --failure', 'test/ref/errFailPassTextStopOnError-1.txt'}, { 'test/test_with_err_fail_pass.lua', '', '--output text --quiet -p TestSome --error', 'test/ref/errFailPassTextStopOnError-2.txt'}, { 'test/test_with_err_fail_pass.lua', '', '--output text --quiet -p TestAnoth --failure', 'test/ref/errFailPassTextStopOnError-3.txt'}, { 'test/test_with_err_fail_pass.lua', '', '--output text --quiet -p TestSome --failure', 'test/ref/errFailPassTextStopOnError-4.txt'}, } local filesToGenerateListsComp = { { 'test/some_lists_comparisons.lua', '', '--output text --verbose', 'test/ref/some_lists_comparisons.txt'}, } local function table_join(...) local args = {...} local ret = {} for i,t in ipairs(args) do for _,v in ipairs(t) do table.insert( ret, v) end end return ret end local filesSetIndex = { ErrFailPassText=filesToGenerateErrFailPassText, ErrFailPassTap=filesToGenerateErrFailPassTap, ErrFailPassXml=filesToGenerateErrFailPassXml, ErrFail = table_join( filesToGenerateErrFailPassText, filesToGenerateErrFailPassTap, filesToGenerateErrFailPassXml ), ExampleNil=filesToGenerateExampleNil, ExampleText=filesToGenerateExampleText, ExampleTap=filesToGenerateExampleTap, ExampleXml=filesToGenerateExampleXml, Example = table_join( filesToGenerateExampleNil, filesToGenerateExampleText, filesToGenerateExampleTap, filesToGenerateExampleXml ), TestXml=filesToGenerateTestXml, StopOnError=filesToGenerateStopOnError, ListsComp=filesToGenerateListsComp, } local function updateRefFiles( filesToGenerate ) local ret for _,v in ipairs(filesToGenerate) do report('Generating '..v[4]) ret = osExec( '%s %s %s %s > %s', LUA, v[1], v[2], v[3], v[4] ) --[[ -- exitcode != 0 is not an error for us ... if ret == false then error('Error while generating '..prettystr(v) ) os.exit(1) end ]] -- neutralize all testcase time values in ref xml output local refXmlName = string.match(v[3], "--name (test/ref/.*%.xml)$") if refXmlName then adjustFile( refXmlName, refXmlName, '.*', startResult, breakerType) end local no_error, err_msg no_error, err_msg = pcall( require, 'test.test_luaunit') if not no_error then if nil == err_msg:find( "module 'test.test_luaunit' not found" ) then -- module found but error loading it -- display the error by reproducing it require('test.test_luaunit') end -- run_unit_tests shall also work when called directly from the test directory require('test_luaunit') -- we must disable this test, not working in this case because it expects -- the stack trace to start with test/test_luaunit.lua TestLuaUnitUtilities.test_FailFmt = nil end local lu = require('luaunit') lu.LuaUnit.verbosity = 2 os.exit( lu.LuaUnit.run() ) luaunit-LUAUNIT_V3_4/test/000077500000000000000000000000001401773523200154345ustar00rootroot00000000000000luaunit-LUAUNIT_V3_4/test/check_lua_calc_error.lua000066400000000000000000000017551401773523200222600ustar00rootroot00000000000000 local lu = require('luaunit') print( lu.EPS ) local pi_div_6_deg_expected, pi_div_6_deg_calculated, pi_div_3_deg_expected, pi_div_3_deg_calculated pi_div_6_deg_calculated = math.deg(math.pi/6) pi_div_6_deg_expected = 30 pi_div_3_deg_calculated = math.deg(math.pi/3) pi_div_3_deg_expected = 60 print( (pi_div_6_deg_expected - pi_div_6_deg_calculated) / lu.EPS ) -- prints: 16 print( (pi_div_3_deg_expected - pi_div_3_deg_calculated) / lu.EPS ) -- prints: 32 -- Better use relative error: print( ( (pi_div_6_deg_expected - pi_div_6_deg_calculated) / pi_div_6_deg_expected) / lu.EPS ) -- prints: 0.53333 print( ( (pi_div_3_deg_expected - pi_div_3_deg_calculated) / pi_div_3_deg_expected) / lu.EPS ) -- prints: 0.53333 -- relative error is constant. Assertion can take the form of: lu.assertAlmostEquals( (pi_div_6_deg_expected - pi_div_6_deg_calculated) / pi_div_6_deg_expected, 0, lu.EPS ) lu.assertAlmostEquals( (pi_div_3_deg_expected - pi_div_3_deg_calculated) / pi_div_3_deg_expected, 0, lu.EPS )luaunit-LUAUNIT_V3_4/test/compat_luaunit_v2x.lua000066400000000000000000000137531401773523200217730ustar00rootroot00000000000000EXPORT_ASSERT_TO_GLOBALS = true local lu = require('luaunit') --[[ Use Luaunit in the v2.1 fashion and check that it still works. Exercise every luaunit v2.1 function and have it executed successfully. Coverage: x Made LuaUnit:run() method able to be called with 'run' or 'Run'. x Made LuaUnit.wrapFunctions() function able to be called with 'wrapFunctions' or 'WrapFunctions' or 'wrap_functions'. x Moved wrapFunctions to the LuaUnit module table (e.g. local LuaUnit = require( "luaunit" ); LuaUnit.wrapFunctions( ... ) ) x Added LuaUnit.is and LuaUnit.is_ helper functions. (e.g. assert( LuaUnit.isString( getString() ) ) x Added assert and assert_ x Added assertNot and assert_not_ x Added _VERSION variable to hold the LuaUnit version x Added LuaUnit:setVerbosity(lvl) method to the LuaUnit. Alias: LuaUnit:SetVerbosity() and LuaUnit:set_verbosity(). x Added table deep compare x check that wrapFunctions works x Made "testable" classes able to start with 'test' or 'Test' for their name. x Made "testable" methods able to start with 'test' or 'Test' for their name. x Made testClass:setUp() methods able to be named with 'setUp' or 'Setup' or 'setup'. x Made testClass:tearDown() methods able to be named with 'tearDown' or 'TearDown' or 'teardown'. ]] TestLuaUnitV2Compat = {} function TestLuaUnitV2Compat:testRunAliases() -- some old function assertFunction( lu.run ) assertEquals( lu.Run, lu.run ) end function TestLuaUnitV2Compat:testWrapFunctionsAliases() assertFunction( lu.wrapFunctions ) assertEquals( lu.wrapFunctions, lu.WrapFunctions ) assertEquals( lu.wrapFunctions, lu.wrap_functions ) end local function typeAsserter( goodType, badType, goodAsserter, badAsserter ) goodAsserter( goodType ) if badAsserter ~= nil then badAsserter( badType ) end end function TestLuaUnitV2Compat:testAssertType() local f = function (v) return v+1 end local t = coroutine.create( function(v) local y=v+1 end ) local typesToVerify = { -- list of: { goodType, badType, goodAsserter, badAsserter } { true, "toto", assertBoolean, assertNotBoolean }, { true, "toto", assert_boolean, assert_not_boolean }, { 1 , "toto", assertNumber, assertNotNumber }, { 1 , "toto", assert_number, assert_not_number }, { "q" , 1 , assertString, assertNotString }, { "q" , 1 , assert_string, assert_not_string }, { nil , 1 , assertNil, assertNotNil }, { nil , 1 , assert_nil, assert_not_nil }, { {1,2}, "toto", assertTable, assertNotTable }, { {1,2}, "toto", assert_table, assert_not_table }, { f , "toto", assertFunction, assertNotFunction }, { f , "toto", assert_function,assert_not_function }, { t , "toto", assertThread, assertNotThread }, { t , "toto", assert_thread, assert_not_thread }, } for _,v in ipairs( typesToVerify ) do local goodType, badType, goodAsserter, badAsserter = v[1], v[2], v[3], v[4] typeAsserter( goodType, badType, goodAsserter, badAsserter ) end assertNotUserdata( "toto" ) local typesToVerify2 = { { true, "toto", lu.isBoolean }, { true, "toto", lu.is_boolean }, { 1, "toto", lu.isNumber }, { 1, "toto", lu.is_number }, { "t", 1, lu.isString }, { "t", 1, lu.is_string }, { nil, "toto", lu.isNil }, { nil, "toto", lu.is_nil }, { {1,2},"toto", lu.isTable }, { {1,2},"toto", lu.is_table }, { f, "toto", lu.isFunction }, { f, "toto", lu.is_function }, { t, "toto", lu.isThread }, { t, "toto", lu.is_thread }, } for _,v in ipairs( typesToVerify2 ) do local goodType, badType, goodTypeVerifier = v[1], v[2], v[3] if (v[3] == nil) then print('Missing function at index '.._) assertNotNil( v[3] ) end assertTrue ( goodTypeVerifier( goodType ) ) assertFalse( goodTypeVerifier( badType ) ) end end function TestLuaUnitV2Compat:testHasVersionKey() assertNotNil( lu.VERSION ) assertString( lu.VERSION ) assertNotNil( lu._VERSION ) assertTrue( lu.is_string( lu._VERSION ) ) end function TestLuaUnitV2Compat:testTableEquality() local t1 = {1,2} local t2 = t1 local t3 = {1,2} local t4 = {1,2,3} assertEquals( t1, t1 ) assertEquals( t1, t2 ) -- new in LuaUnit v2.0 , deep table compare assertEquals( t1, t3 ) assertError( assertEquals, t1, t4 ) end -- Setup local called = {} function test_w1() called.w1 = true end function test_w2() called.w2 = true end function test_w3() called.w3 = true end TestSomeFuncs = lu.wrapFunctions( 'test_w1', 'test_w2', 'test_w3' ) TestWithCap = {} function TestWithCap:setup() called.setup = true end function TestWithCap:Test1() called.t1 = true end function TestWithCap:test2() called.t2 = true end function TestWithCap:teardown() called.teardown = true end testWithoutCap = {} function testWithoutCap:Setup() called.Setup = true end function testWithoutCap:Test3() called.t3 = true end function testWithoutCap:test4() called.t4 = true end function testWithoutCap:tearDown() called.tearDown = true end TestWithUnderscore = {} function TestWithUnderscore:setUp() called.setUp = true end function TestWithUnderscore:Test1() called.t1 = true end function TestWithUnderscore:test2() called.t2 = true end function TestWithUnderscore:TearDown() called.TearDown = true end -- Run lu:setVerbosity( 1 ) lu:set_verbosity( 1 ) lu:SetVerbosity( 1 ) local results = lu.run() -- Verif assert( called.w1 == true ) assert( called.w2 == true ) assert( called.w3 == true ) assert( called.t1 == true ) assert( called.t2 == true ) assert( called.t3 == true ) assert( called.t4 == true ) assert( called.setup == true ) assert( called.setUp == true ) assert( called.Setup == true ) assert( called.teardown == true ) assert( called.tearDown == true ) assert( called.TearDown == true ) os.exit( results ) luaunit-LUAUNIT_V3_4/test/legacy_example_with_luaunit.lua000066400000000000000000000062351401773523200237200ustar00rootroot00000000000000EXPORT_ASSERT_TO_GLOBALS = true require('luaunit') TestToto = {} --class function TestToto:setUp() -- set up tests self.a = 1 self.s = 'hop' self.t1 = {1,2,3} self.t2 = {one=1,two=2,three=3} self.t3 = {1,2,three=3} end function TestToto:test1_withFailure() print( "some stuff test 1" ) assertEquals( self.a , 1 ) -- will fail assertEquals( self.a , 2 ) assertEquals( self.a , 2 ) end function TestToto:test2_withFailure() print( "some stuff test 2" ) assertEquals( self.a , 1 ) assertEquals( self.s , 'hop' ) -- will fail assertEquals( self.s , 'bof' ) assertEquals( self.s , 'bof' ) end function TestToto:test3() print( "some stuff test 3" ) assertEquals( self.a , 1 ) assertEquals( self.s , 'hop' ) assertEquals( type(self.a), 'number' ) end function TestToto:test4() print( "some stuff test 4" ) assertNotEquals( self.a , 1 ) end function TestToto:test5() print( "some stuff test 5" ) assertTrue( self.a ) assertFalse( self.a ) end function TestToto:test6() print( "some stuff test 6" ) assertTrue( false ) end function TestToto:test7() -- assertEquals( {1,2}, self.t1 ) -- assertEquals( {1,2}, self.t2 ) assertEquals( {1,2}, self.t3 ) end function TestToto:test8a() -- failure occurs in a submethod self:funcWithError() end function TestToto:test8b() -- failure occurs in a submethod self:funcWithFuncWithError() end function TestToto:funcWithFuncWithError() self:funcWithError() end function TestToto:funcWithError() error('Bouhouhoum error!') end -- class TestToto TestTiti = {} --class function TestTiti:setUp() -- set up tests self.a = 1 self.s = 'hop' print( 'TestTiti:setUp' ) end function TestTiti:tearDown() -- some tearDown() code if necessary print( 'TestTiti:tearDown' ) end function TestTiti:test1_withFailure() print( "some stuff test 1" ) assertEquals( self.a , 1 ) -- will fail assertEquals( self.a , 2 ) assertEquals( self.a , 2 ) end function TestTiti:test2_withFailure() print( "some stuff test 2" ) assertEquals( self.a , 1 ) assertEquals( self.s , 'hop' ) -- will fail assertEquals( self.s , 'bof' ) assertEquals( self.s , 'bof' ) end function TestTiti:test3() print( "some stuff test 3" ) assertEquals( self.a , 1 ) assertEquals( self.s , 'hop' ) end -- class TestTiti -- simple test functions that were written previously can be integrated -- in luaunit too function test1_withFailure() assert( 1 == 1) -- will fail assert( 1 == 2) end function test2_withFailure() assert( 'a' == 'a') -- will fail assert( 'a' == 'b') end function test3() assert( 1 == 1) assert( 'a' == 'a') end local lu = LuaUnit.new() lu:setOutputType("tap") os.exit( lu:runSuite() ) luaunit-LUAUNIT_V3_4/test/ref/000077500000000000000000000000001401773523200162105ustar00rootroot00000000000000luaunit-LUAUNIT_V3_4/test/ref/errFailPassNilDefault-failures.txt000066400000000000000000000000001401773523200247320ustar00rootroot00000000000000luaunit-LUAUNIT_V3_4/test/ref/errFailPassNilDefault-success.txt000066400000000000000000000000001401773523200245700ustar00rootroot00000000000000luaunit-LUAUNIT_V3_4/test/ref/errFailPassNilDefault.txt000066400000000000000000000000001401773523200231220ustar00rootroot00000000000000luaunit-LUAUNIT_V3_4/test/ref/errFailPassTapDefault-failures.txt000066400000000000000000000015231401773523200247470ustar00rootroot000000000000001..10 # Started on 03/22/16 21:58:32 # Starting class: TestAnotherThing ok 1 TestAnotherThing.test1_Success1 ok 2 TestAnotherThing.test1_Success2 not ok 3 TestAnotherThing.test3_Fail1 # test/test_with_err_fail_pass.lua:49: expected: 0, actual: 2 not ok 4 TestAnotherThing.test3_Fail2 # test/test_with_err_fail_pass.lua:53: expected: 0, actual: 3 # Starting class: TestSomething ok 5 TestSomething.test1_Success1 ok 6 TestSomething.test1_Success2 not ok 7 TestSomething.test2_Fail1 # test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 not ok 8 TestSomething.test2_Fail2 # test/test_with_err_fail_pass.lua:19: expected: 0, actual: 3 not ok 9 testFuncFail1 # test/test_with_err_fail_pass.lua:62: expected: 0, actual: 3 ok 10 testFuncSuccess1 # Ran 10 tests in 0.000 seconds, 5 successes, 5 failures, 5 non-selected luaunit-LUAUNIT_V3_4/test/ref/errFailPassTapDefault-success.txt000066400000000000000000000005501401773523200246040ustar00rootroot000000000000001..5 # Started on 03/22/16 21:58:32 # Starting class: TestAnotherThing ok 1 TestAnotherThing.test1_Success1 ok 2 TestAnotherThing.test1_Success2 # Starting class: TestSomething ok 3 TestSomething.test1_Success1 ok 4 TestSomething.test1_Success2 ok 5 testFuncSuccess1 # Ran 5 tests in 0.000 seconds, 5 successes, 0 failures, 10 non-selected luaunit-LUAUNIT_V3_4/test/ref/errFailPassTapDefault.txt000066400000000000000000000026561401773523200231470ustar00rootroot000000000000001..15 # Started on 03/22/16 21:58:32 # Starting class: TestAnotherThing ok 1 TestAnotherThing.test1_Success1 ok 2 TestAnotherThing.test1_Success2 not ok 3 TestAnotherThing.test2_Err1 # test/test_with_err_fail_pass.lua:41: attempt to perform arithmetic on a table value not ok 4 TestAnotherThing.test2_Err2 # test/test_with_err_fail_pass.lua:45: attempt to perform arithmetic on a table value not ok 5 TestAnotherThing.test3_Fail1 # test/test_with_err_fail_pass.lua:49: expected: 0, actual: 2 not ok 6 TestAnotherThing.test3_Fail2 # test/test_with_err_fail_pass.lua:53: expected: 0, actual: 3 # Starting class: TestSomething ok 7 TestSomething.test1_Success1 ok 8 TestSomething.test1_Success2 not ok 9 TestSomething.test2_Fail1 # test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 not ok 10 TestSomething.test2_Fail2 # test/test_with_err_fail_pass.lua:19: expected: 0, actual: 3 not ok 11 TestSomething.test3_Err1 # test/test_with_err_fail_pass.lua:23: attempt to perform arithmetic on a table value not ok 12 TestSomething.test3_Err2 # test/test_with_err_fail_pass.lua:27: attempt to perform arithmetic on a table value not ok 13 testFuncErr1 # test/test_with_err_fail_pass.lua:66: attempt to perform arithmetic on a table value not ok 14 testFuncFail1 # test/test_with_err_fail_pass.lua:62: expected: 0, actual: 3 ok 15 testFuncSuccess1 # Ran 15 tests in 0.003 seconds, 5 successes, 5 failures, 5 errors luaunit-LUAUNIT_V3_4/test/ref/errFailPassTapQuiet-failures.txt000066400000000000000000000010231401773523200244450ustar00rootroot000000000000001..10 # Started on 03/22/16 21:58:32 # Starting class: TestAnotherThing ok 1 TestAnotherThing.test1_Success1 ok 2 TestAnotherThing.test1_Success2 not ok 3 TestAnotherThing.test3_Fail1 not ok 4 TestAnotherThing.test3_Fail2 # Starting class: TestSomething ok 5 TestSomething.test1_Success1 ok 6 TestSomething.test1_Success2 not ok 7 TestSomething.test2_Fail1 not ok 8 TestSomething.test2_Fail2 not ok 9 testFuncFail1 ok 10 testFuncSuccess1 # Ran 10 tests in 0.002 seconds, 5 successes, 5 failures, 5 non-selected luaunit-LUAUNIT_V3_4/test/ref/errFailPassTapQuiet-success.txt000066400000000000000000000005501401773523200243070ustar00rootroot000000000000001..5 # Started on 03/22/16 21:58:32 # Starting class: TestAnotherThing ok 1 TestAnotherThing.test1_Success1 ok 2 TestAnotherThing.test1_Success2 # Starting class: TestSomething ok 3 TestSomething.test1_Success1 ok 4 TestSomething.test1_Success2 ok 5 testFuncSuccess1 # Ran 5 tests in 0.000 seconds, 5 successes, 0 failures, 10 non-selected luaunit-LUAUNIT_V3_4/test/ref/errFailPassTapQuiet.txt000066400000000000000000000012661401773523200226460ustar00rootroot000000000000001..15 # Started on 03/22/16 21:58:32 # Starting class: TestAnotherThing ok 1 TestAnotherThing.test1_Success1 ok 2 TestAnotherThing.test1_Success2 not ok 3 TestAnotherThing.test2_Err1 not ok 4 TestAnotherThing.test2_Err2 not ok 5 TestAnotherThing.test3_Fail1 not ok 6 TestAnotherThing.test3_Fail2 # Starting class: TestSomething ok 7 TestSomething.test1_Success1 ok 8 TestSomething.test1_Success2 not ok 9 TestSomething.test2_Fail1 not ok 10 TestSomething.test2_Fail2 not ok 11 TestSomething.test3_Err1 not ok 12 TestSomething.test3_Err2 not ok 13 testFuncErr1 not ok 14 testFuncFail1 ok 15 testFuncSuccess1 # Ran 15 tests in 0.002 seconds, 5 successes, 5 failures, 5 errors luaunit-LUAUNIT_V3_4/test/ref/errFailPassTapVerbose-failures.txt000066400000000000000000000025201401773523200247660ustar00rootroot000000000000001..10 # Started on 03/22/16 21:58:32 # Starting class: TestAnotherThing ok 1 TestAnotherThing.test1_Success1 ok 2 TestAnotherThing.test1_Success2 not ok 3 TestAnotherThing.test3_Fail1 # test/test_with_err_fail_pass.lua:49: expected: 0, actual: 2 # stack traceback: # test/test_with_err_fail_pass.lua:49: in function 'TestAnotherThing.test3_Fail1' not ok 4 TestAnotherThing.test3_Fail2 # test/test_with_err_fail_pass.lua:53: expected: 0, actual: 3 # stack traceback: # test/test_with_err_fail_pass.lua:53: in function 'TestAnotherThing.test3_Fail2' # Starting class: TestSomething ok 5 TestSomething.test1_Success1 ok 6 TestSomething.test1_Success2 not ok 7 TestSomething.test2_Fail1 # test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 # stack traceback: # test/test_with_err_fail_pass.lua:15: in function 'TestSomething.test2_Fail1' not ok 8 TestSomething.test2_Fail2 # test/test_with_err_fail_pass.lua:19: expected: 0, actual: 3 # stack traceback: # test/test_with_err_fail_pass.lua:19: in function 'TestSomething.test2_Fail2' not ok 9 testFuncFail1 # test/test_with_err_fail_pass.lua:62: expected: 0, actual: 3 # stack traceback: # test/test_with_err_fail_pass.lua:62: in function 'testFuncFail1' ok 10 testFuncSuccess1 # Ran 10 tests in 0.000 seconds, 5 successes, 5 failures, 5 non-selected luaunit-LUAUNIT_V3_4/test/ref/errFailPassTapVerbose-success.txt000066400000000000000000000005501401773523200246250ustar00rootroot000000000000001..5 # Started on 03/22/16 21:58:32 # Starting class: TestAnotherThing ok 1 TestAnotherThing.test1_Success1 ok 2 TestAnotherThing.test1_Success2 # Starting class: TestSomething ok 3 TestSomething.test1_Success1 ok 4 TestSomething.test1_Success2 ok 5 testFuncSuccess1 # Ran 5 tests in 0.000 seconds, 5 successes, 0 failures, 10 non-selected luaunit-LUAUNIT_V3_4/test/ref/errFailPassTapVerbose.txt000066400000000000000000000046431401773523200231660ustar00rootroot000000000000001..15 # Started on 03/22/16 21:58:32 # Starting class: TestAnotherThing ok 1 TestAnotherThing.test1_Success1 ok 2 TestAnotherThing.test1_Success2 not ok 3 TestAnotherThing.test2_Err1 # test/test_with_err_fail_pass.lua:41: attempt to perform arithmetic on a table value # stack traceback: # test/test_with_err_fail_pass.lua:41: in function 'TestAnotherThing.test2_Err1' not ok 4 TestAnotherThing.test2_Err2 # test/test_with_err_fail_pass.lua:45: attempt to perform arithmetic on a table value # stack traceback: # test/test_with_err_fail_pass.lua:45: in function 'TestAnotherThing.test2_Err2' not ok 5 TestAnotherThing.test3_Fail1 # test/test_with_err_fail_pass.lua:49: expected: 0, actual: 2 # stack traceback: # test/test_with_err_fail_pass.lua:49: in function 'TestAnotherThing.test3_Fail1' not ok 6 TestAnotherThing.test3_Fail2 # test/test_with_err_fail_pass.lua:53: expected: 0, actual: 3 # stack traceback: # test/test_with_err_fail_pass.lua:53: in function 'TestAnotherThing.test3_Fail2' # Starting class: TestSomething ok 7 TestSomething.test1_Success1 ok 8 TestSomething.test1_Success2 not ok 9 TestSomething.test2_Fail1 # test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 # stack traceback: # test/test_with_err_fail_pass.lua:15: in function 'TestSomething.test2_Fail1' not ok 10 TestSomething.test2_Fail2 # test/test_with_err_fail_pass.lua:19: expected: 0, actual: 3 # stack traceback: # test/test_with_err_fail_pass.lua:19: in function 'TestSomething.test2_Fail2' not ok 11 TestSomething.test3_Err1 # test/test_with_err_fail_pass.lua:23: attempt to perform arithmetic on a table value # stack traceback: # test/test_with_err_fail_pass.lua:23: in function 'TestSomething.test3_Err1' not ok 12 TestSomething.test3_Err2 # test/test_with_err_fail_pass.lua:27: attempt to perform arithmetic on a table value # stack traceback: # test/test_with_err_fail_pass.lua:27: in function 'TestSomething.test3_Err2' not ok 13 testFuncErr1 # test/test_with_err_fail_pass.lua:66: attempt to perform arithmetic on a table value # stack traceback: # test/test_with_err_fail_pass.lua:66: in function 'testFuncErr1' not ok 14 testFuncFail1 # test/test_with_err_fail_pass.lua:62: expected: 0, actual: 3 # stack traceback: # test/test_with_err_fail_pass.lua:62: in function 'testFuncFail1' ok 15 testFuncSuccess1 # Ran 15 tests in 0.000 seconds, 5 successes, 5 failures, 5 errors luaunit-LUAUNIT_V3_4/test/ref/errFailPassTextDefault-failures.txt000066400000000000000000000017771401773523200251620ustar00rootroot00000000000000..FF..FFF. Failed tests: ------------- 1) TestAnotherThing.test3_Fail1 test/test_with_err_fail_pass.lua:49: expected: 0, actual: 2 stack traceback: test/test_with_err_fail_pass.lua:49: in function 'TestAnotherThing.test3_Fail1' 2) TestAnotherThing.test3_Fail2 test/test_with_err_fail_pass.lua:53: expected: 0, actual: 3 stack traceback: test/test_with_err_fail_pass.lua:53: in function 'TestAnotherThing.test3_Fail2' 3) TestSomething.test2_Fail1 test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 stack traceback: test/test_with_err_fail_pass.lua:15: in function 'TestSomething.test2_Fail1' 4) TestSomething.test2_Fail2 test/test_with_err_fail_pass.lua:19: expected: 0, actual: 3 stack traceback: test/test_with_err_fail_pass.lua:19: in function 'TestSomething.test2_Fail2' 5) testFuncFail1 test/test_with_err_fail_pass.lua:62: expected: 0, actual: 3 stack traceback: test/test_with_err_fail_pass.lua:62: in function 'testFuncFail1' Ran 10 tests in 0.001 seconds, 5 successes, 5 failures, 5 non-selected luaunit-LUAUNIT_V3_4/test/ref/errFailPassTextDefault-success.txt000066400000000000000000000001201401773523200247750ustar00rootroot00000000000000..... Ran 5 tests in 0.000 seconds, 5 successes, 0 failures, 10 non-selected OK luaunit-LUAUNIT_V3_4/test/ref/errFailPassTextDefault.txt000066400000000000000000000040431401773523200233370ustar00rootroot00000000000000..EEFF..FFEEEF. Tests with errors: ------------------ 1) TestAnotherThing.test2_Err1 test/test_with_err_fail_pass.lua:41: attempt to perform arithmetic on a table value stack traceback: test/test_with_err_fail_pass.lua:41: in function 'TestAnotherThing.test2_Err1' 2) TestAnotherThing.test2_Err2 test/test_with_err_fail_pass.lua:45: attempt to perform arithmetic on a table value stack traceback: test/test_with_err_fail_pass.lua:45: in function 'TestAnotherThing.test2_Err2' 3) TestSomething.test3_Err1 test/test_with_err_fail_pass.lua:23: attempt to perform arithmetic on a table value stack traceback: test/test_with_err_fail_pass.lua:23: in function 'TestSomething.test3_Err1' 4) TestSomething.test3_Err2 test/test_with_err_fail_pass.lua:27: attempt to perform arithmetic on a table value stack traceback: test/test_with_err_fail_pass.lua:27: in function 'TestSomething.test3_Err2' 5) testFuncErr1 test/test_with_err_fail_pass.lua:66: attempt to perform arithmetic on a table value stack traceback: test/test_with_err_fail_pass.lua:66: in function 'testFuncErr1' Failed tests: ------------- 1) TestAnotherThing.test3_Fail1 test/test_with_err_fail_pass.lua:49: expected: 0, actual: 2 stack traceback: test/test_with_err_fail_pass.lua:49: in function 'TestAnotherThing.test3_Fail1' 2) TestAnotherThing.test3_Fail2 test/test_with_err_fail_pass.lua:53: expected: 0, actual: 3 stack traceback: test/test_with_err_fail_pass.lua:53: in function 'TestAnotherThing.test3_Fail2' 3) TestSomething.test2_Fail1 test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 stack traceback: test/test_with_err_fail_pass.lua:15: in function 'TestSomething.test2_Fail1' 4) TestSomething.test2_Fail2 test/test_with_err_fail_pass.lua:19: expected: 0, actual: 3 stack traceback: test/test_with_err_fail_pass.lua:19: in function 'TestSomething.test2_Fail2' 5) testFuncFail1 test/test_with_err_fail_pass.lua:62: expected: 0, actual: 3 stack traceback: test/test_with_err_fail_pass.lua:62: in function 'testFuncFail1' Ran 15 tests in 0.002 seconds, 5 successes, 5 failures, 5 errors luaunit-LUAUNIT_V3_4/test/ref/errFailPassTextQuiet-failures.txt000066400000000000000000000017771401773523200246650ustar00rootroot00000000000000..FF..FFF. Failed tests: ------------- 1) TestAnotherThing.test3_Fail1 test/test_with_err_fail_pass.lua:49: expected: 0, actual: 2 stack traceback: test/test_with_err_fail_pass.lua:49: in function 'TestAnotherThing.test3_Fail1' 2) TestAnotherThing.test3_Fail2 test/test_with_err_fail_pass.lua:53: expected: 0, actual: 3 stack traceback: test/test_with_err_fail_pass.lua:53: in function 'TestAnotherThing.test3_Fail2' 3) TestSomething.test2_Fail1 test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 stack traceback: test/test_with_err_fail_pass.lua:15: in function 'TestSomething.test2_Fail1' 4) TestSomething.test2_Fail2 test/test_with_err_fail_pass.lua:19: expected: 0, actual: 3 stack traceback: test/test_with_err_fail_pass.lua:19: in function 'TestSomething.test2_Fail2' 5) testFuncFail1 test/test_with_err_fail_pass.lua:62: expected: 0, actual: 3 stack traceback: test/test_with_err_fail_pass.lua:62: in function 'testFuncFail1' Ran 10 tests in 0.001 seconds, 5 successes, 5 failures, 5 non-selected luaunit-LUAUNIT_V3_4/test/ref/errFailPassTextQuiet-success.txt000066400000000000000000000001201401773523200245000ustar00rootroot00000000000000..... Ran 5 tests in 0.000 seconds, 5 successes, 0 failures, 10 non-selected OK luaunit-LUAUNIT_V3_4/test/ref/errFailPassTextQuiet.txt000066400000000000000000000040431401773523200230420ustar00rootroot00000000000000..EEFF..FFEEEF. Tests with errors: ------------------ 1) TestAnotherThing.test2_Err1 test/test_with_err_fail_pass.lua:41: attempt to perform arithmetic on a table value stack traceback: test/test_with_err_fail_pass.lua:41: in function 'TestAnotherThing.test2_Err1' 2) TestAnotherThing.test2_Err2 test/test_with_err_fail_pass.lua:45: attempt to perform arithmetic on a table value stack traceback: test/test_with_err_fail_pass.lua:45: in function 'TestAnotherThing.test2_Err2' 3) TestSomething.test3_Err1 test/test_with_err_fail_pass.lua:23: attempt to perform arithmetic on a table value stack traceback: test/test_with_err_fail_pass.lua:23: in function 'TestSomething.test3_Err1' 4) TestSomething.test3_Err2 test/test_with_err_fail_pass.lua:27: attempt to perform arithmetic on a table value stack traceback: test/test_with_err_fail_pass.lua:27: in function 'TestSomething.test3_Err2' 5) testFuncErr1 test/test_with_err_fail_pass.lua:66: attempt to perform arithmetic on a table value stack traceback: test/test_with_err_fail_pass.lua:66: in function 'testFuncErr1' Failed tests: ------------- 1) TestAnotherThing.test3_Fail1 test/test_with_err_fail_pass.lua:49: expected: 0, actual: 2 stack traceback: test/test_with_err_fail_pass.lua:49: in function 'TestAnotherThing.test3_Fail1' 2) TestAnotherThing.test3_Fail2 test/test_with_err_fail_pass.lua:53: expected: 0, actual: 3 stack traceback: test/test_with_err_fail_pass.lua:53: in function 'TestAnotherThing.test3_Fail2' 3) TestSomething.test2_Fail1 test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 stack traceback: test/test_with_err_fail_pass.lua:15: in function 'TestSomething.test2_Fail1' 4) TestSomething.test2_Fail2 test/test_with_err_fail_pass.lua:19: expected: 0, actual: 3 stack traceback: test/test_with_err_fail_pass.lua:19: in function 'TestSomething.test2_Fail2' 5) testFuncFail1 test/test_with_err_fail_pass.lua:62: expected: 0, actual: 3 stack traceback: test/test_with_err_fail_pass.lua:62: in function 'testFuncFail1' Ran 15 tests in 0.002 seconds, 5 successes, 5 failures, 5 errors luaunit-LUAUNIT_V3_4/test/ref/errFailPassTextStopOnError-1.txt000066400000000000000000000001201401773523200243350ustar00rootroot00000000000000..... Ran 5 tests in 0.000 seconds, 5 successes, 0 failures, 10 non-selected OK luaunit-LUAUNIT_V3_4/test/ref/errFailPassTextStopOnError-2.txt000066400000000000000000000016201401773523200243440ustar00rootroot00000000000000..FFE ERROR during LuaUnit test execution: test/test_with_err_fail_pass.lua:23: attempt to perform arithmetic on a table value Tests with errors: ------------------ 1) TestSomething.test3_Err1 test/test_with_err_fail_pass.lua:23: attempt to perform arithmetic on a table value stack traceback: test/test_with_err_fail_pass.lua:23: in function 'TestSomething.test3_Err1' Failed tests: ------------- 1) TestSomething.test2_Fail1 test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 stack traceback: test/test_with_err_fail_pass.lua:15: in function 'TestSomething.test2_Fail1' 2) TestSomething.test2_Fail2 test/test_with_err_fail_pass.lua:19: expected: 0, actual: 3 stack traceback: test/test_with_err_fail_pass.lua:19: in function 'TestSomething.test2_Fail2' Ran 5 tests in 0.000 seconds, 2 successes, 2 failures, 1 error, 9 non-selected LuaUnit ABORTED (as requested by --error or --failure option) luaunit-LUAUNIT_V3_4/test/ref/errFailPassTextStopOnError-3.txt000066400000000000000000000007721401773523200243540ustar00rootroot00000000000000..E ERROR during LuaUnit test execution: test/test_with_err_fail_pass.lua:41: attempt to perform arithmetic on a table value Tests with errors: ------------------ 1) TestAnotherThing.test2_Err1 test/test_with_err_fail_pass.lua:41: attempt to perform arithmetic on a table value stack traceback: test/test_with_err_fail_pass.lua:41: in function 'TestAnotherThing.test2_Err1' Ran 3 tests in 0.000 seconds, 2 successes, 1 error, 9 non-selected LuaUnit ABORTED (as requested by --error or --failure option) luaunit-LUAUNIT_V3_4/test/ref/errFailPassTextStopOnError-4.txt000066400000000000000000000007001401773523200243440ustar00rootroot00000000000000..F Failure during LuaUnit test execution: test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 Failed tests: ------------- 1) TestSomething.test2_Fail1 test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 stack traceback: test/test_with_err_fail_pass.lua:15: in function 'TestSomething.test2_Fail1' Ran 3 tests in 0.000 seconds, 2 successes, 1 failure, 9 non-selected LuaUnit ABORTED (as requested by --error or --failure option) luaunit-LUAUNIT_V3_4/test/ref/errFailPassTextVerbose-failures.txt000066400000000000000000000033661401773523200251770ustar00rootroot00000000000000Started on 03/22/16 21:29:18 TestAnotherThing.test1_Success1 ... Ok TestAnotherThing.test1_Success2 ... Ok TestAnotherThing.test3_Fail1 ... FAIL test/test_with_err_fail_pass.lua:49: expected: 0, actual: 2 TestAnotherThing.test3_Fail2 ... FAIL test/test_with_err_fail_pass.lua:53: expected: 0, actual: 3 TestSomething.test1_Success1 ... Ok TestSomething.test1_Success2 ... Ok TestSomething.test2_Fail1 ... FAIL test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 TestSomething.test2_Fail2 ... FAIL test/test_with_err_fail_pass.lua:19: expected: 0, actual: 3 testFuncFail1 ... FAIL test/test_with_err_fail_pass.lua:62: expected: 0, actual: 3 testFuncSuccess1 ... Ok ========================================================= Failed tests: ------------- 1) TestAnotherThing.test3_Fail1 test/test_with_err_fail_pass.lua:49: expected: 0, actual: 2 stack traceback: test/test_with_err_fail_pass.lua:49: in function 'TestAnotherThing.test3_Fail1' 2) TestAnotherThing.test3_Fail2 test/test_with_err_fail_pass.lua:53: expected: 0, actual: 3 stack traceback: test/test_with_err_fail_pass.lua:53: in function 'TestAnotherThing.test3_Fail2' 3) TestSomething.test2_Fail1 test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 stack traceback: test/test_with_err_fail_pass.lua:15: in function 'TestSomething.test2_Fail1' 4) TestSomething.test2_Fail2 test/test_with_err_fail_pass.lua:19: expected: 0, actual: 3 stack traceback: test/test_with_err_fail_pass.lua:19: in function 'TestSomething.test2_Fail2' 5) testFuncFail1 test/test_with_err_fail_pass.lua:62: expected: 0, actual: 3 stack traceback: test/test_with_err_fail_pass.lua:62: in function 'testFuncFail1' Ran 10 tests in 0.001 seconds, 5 successes, 5 failures, 5 non-selected luaunit-LUAUNIT_V3_4/test/ref/errFailPassTextVerbose-success.txt000066400000000000000000000005431401773523200250270ustar00rootroot00000000000000Started on 03/22/16 21:29:18 TestAnotherThing.test1_Success1 ... Ok TestAnotherThing.test1_Success2 ... Ok TestSomething.test1_Success1 ... Ok TestSomething.test1_Success2 ... Ok testFuncSuccess1 ... Ok ========================================================= Ran 5 tests in 0.000 seconds, 5 successes, 0 failures, 10 non-selected OK luaunit-LUAUNIT_V3_4/test/ref/errFailPassTextVerbose.txt000066400000000000000000000065661401773523200233740ustar00rootroot00000000000000Started on 03/22/16 21:29:18 TestAnotherThing.test1_Success1 ... Ok TestAnotherThing.test1_Success2 ... Ok TestAnotherThing.test2_Err1 ... ERROR test/test_with_err_fail_pass.lua:41: attempt to perform arithmetic on a table value TestAnotherThing.test2_Err2 ... ERROR test/test_with_err_fail_pass.lua:45: attempt to perform arithmetic on a table value TestAnotherThing.test3_Fail1 ... FAIL test/test_with_err_fail_pass.lua:49: expected: 0, actual: 2 TestAnotherThing.test3_Fail2 ... FAIL test/test_with_err_fail_pass.lua:53: expected: 0, actual: 3 TestSomething.test1_Success1 ... Ok TestSomething.test1_Success2 ... Ok TestSomething.test2_Fail1 ... FAIL test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 TestSomething.test2_Fail2 ... FAIL test/test_with_err_fail_pass.lua:19: expected: 0, actual: 3 TestSomething.test3_Err1 ... ERROR test/test_with_err_fail_pass.lua:23: attempt to perform arithmetic on a table value TestSomething.test3_Err2 ... ERROR test/test_with_err_fail_pass.lua:27: attempt to perform arithmetic on a table value testFuncErr1 ... ERROR test/test_with_err_fail_pass.lua:66: attempt to perform arithmetic on a table value testFuncFail1 ... FAIL test/test_with_err_fail_pass.lua:62: expected: 0, actual: 3 testFuncSuccess1 ... Ok ========================================================= Tests with errors: ------------------ 1) TestAnotherThing.test2_Err1 test/test_with_err_fail_pass.lua:41: attempt to perform arithmetic on a table value stack traceback: test/test_with_err_fail_pass.lua:41: in function 'TestAnotherThing.test2_Err1' 2) TestAnotherThing.test2_Err2 test/test_with_err_fail_pass.lua:45: attempt to perform arithmetic on a table value stack traceback: test/test_with_err_fail_pass.lua:45: in function 'TestAnotherThing.test2_Err2' 3) TestSomething.test3_Err1 test/test_with_err_fail_pass.lua:23: attempt to perform arithmetic on a table value stack traceback: test/test_with_err_fail_pass.lua:23: in function 'TestSomething.test3_Err1' 4) TestSomething.test3_Err2 test/test_with_err_fail_pass.lua:27: attempt to perform arithmetic on a table value stack traceback: test/test_with_err_fail_pass.lua:27: in function 'TestSomething.test3_Err2' 5) testFuncErr1 test/test_with_err_fail_pass.lua:66: attempt to perform arithmetic on a table value stack traceback: test/test_with_err_fail_pass.lua:66: in function 'testFuncErr1' Failed tests: ------------- 1) TestAnotherThing.test3_Fail1 test/test_with_err_fail_pass.lua:49: expected: 0, actual: 2 stack traceback: test/test_with_err_fail_pass.lua:49: in function 'TestAnotherThing.test3_Fail1' 2) TestAnotherThing.test3_Fail2 test/test_with_err_fail_pass.lua:53: expected: 0, actual: 3 stack traceback: test/test_with_err_fail_pass.lua:53: in function 'TestAnotherThing.test3_Fail2' 3) TestSomething.test2_Fail1 test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 stack traceback: test/test_with_err_fail_pass.lua:15: in function 'TestSomething.test2_Fail1' 4) TestSomething.test2_Fail2 test/test_with_err_fail_pass.lua:19: expected: 0, actual: 3 stack traceback: test/test_with_err_fail_pass.lua:19: in function 'TestSomething.test2_Fail2' 5) testFuncFail1 test/test_with_err_fail_pass.lua:62: expected: 0, actual: 3 stack traceback: test/test_with_err_fail_pass.lua:62: in function 'testFuncFail1' Ran 15 tests in 0.001 seconds, 5 successes, 5 failures, 5 errors luaunit-LUAUNIT_V3_4/test/ref/errFailPassXmlDefault-failures.txt000066400000000000000000000020121401773523200247550ustar00rootroot00000000000000# XML output to test/ref/errFailPassXmlDefault-failures.xml # Started on 04/30/19 20:22:52 # Starting class: TestAnotherThing # Starting test: TestAnotherThing.test1_Success1 # Starting test: TestAnotherThing.test1_Success2 # Starting test: TestAnotherThing.test3_Fail1 # Failure: test/test_with_err_fail_pass.lua:49: expected: 0, actual: 2 # Starting test: TestAnotherThing.test3_Fail2 # Failure: test/test_with_err_fail_pass.lua:53: expected: 0, actual: 3 # Starting class: TestSomething # Starting test: TestSomething.test1_Success1 # Starting test: TestSomething.test1_Success2 # Starting test: TestSomething.test2_Fail1 # Failure: test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 # Starting test: TestSomething.test2_Fail2 # Failure: test/test_with_err_fail_pass.lua:19: expected: 0, actual: 3 # Starting test: testFuncFail1 # Failure: test/test_with_err_fail_pass.lua:62: expected: 0, actual: 3 # Starting test: testFuncSuccess1 # Ran 10 tests in 0.000 seconds, 5 successes, 5 failures, 5 non-selected luaunit-LUAUNIT_V3_4/test/ref/errFailPassXmlDefault-failures.xml000066400000000000000000000051701401773523200247460ustar00rootroot00000000000000 luaunit-LUAUNIT_V3_4/test/ref/errFailPassXmlDefault-success.txt000066400000000000000000000007061401773523200246230ustar00rootroot00000000000000# XML output to test/ref/errFailPassXmlDefault-success.xml # Started on 04/30/19 20:22:52 # Starting class: TestAnotherThing # Starting test: TestAnotherThing.test1_Success1 # Starting test: TestAnotherThing.test1_Success2 # Starting class: TestSomething # Starting test: TestSomething.test1_Success1 # Starting test: TestSomething.test1_Success2 # Starting test: testFuncSuccess1 # Ran 5 tests in 0.000 seconds, 5 successes, 0 failures, 10 non-selected luaunit-LUAUNIT_V3_4/test/ref/errFailPassXmlDefault-success.xml000066400000000000000000000017721401773523200246100ustar00rootroot00000000000000 luaunit-LUAUNIT_V3_4/test/ref/errFailPassXmlDefault.txt000066400000000000000000000032471401773523200231600ustar00rootroot00000000000000# XML output to test/ref/errFailPassXmlDefault.xml # Started on 04/30/19 20:22:52 # Starting class: TestAnotherThing # Starting test: TestAnotherThing.test1_Success1 # Starting test: TestAnotherThing.test1_Success2 # Starting test: TestAnotherThing.test2_Err1 # Error: test/test_with_err_fail_pass.lua:41: attempt to perform arithmetic on a table value # Starting test: TestAnotherThing.test2_Err2 # Error: test/test_with_err_fail_pass.lua:45: attempt to perform arithmetic on a table value # Starting test: TestAnotherThing.test3_Fail1 # Failure: test/test_with_err_fail_pass.lua:49: expected: 0, actual: 2 # Starting test: TestAnotherThing.test3_Fail2 # Failure: test/test_with_err_fail_pass.lua:53: expected: 0, actual: 3 # Starting class: TestSomething # Starting test: TestSomething.test1_Success1 # Starting test: TestSomething.test1_Success2 # Starting test: TestSomething.test2_Fail1 # Failure: test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 # Starting test: TestSomething.test2_Fail2 # Failure: test/test_with_err_fail_pass.lua:19: expected: 0, actual: 3 # Starting test: TestSomething.test3_Err1 # Error: test/test_with_err_fail_pass.lua:23: attempt to perform arithmetic on a table value # Starting test: TestSomething.test3_Err2 # Error: test/test_with_err_fail_pass.lua:27: attempt to perform arithmetic on a table value # Starting test: testFuncErr1 # Error: test/test_with_err_fail_pass.lua:66: attempt to perform arithmetic on a table value # Starting test: testFuncFail1 # Failure: test/test_with_err_fail_pass.lua:62: expected: 0, actual: 3 # Starting test: testFuncSuccess1 # Ran 15 tests in 0.004 seconds, 5 successes, 5 failures, 5 errors luaunit-LUAUNIT_V3_4/test/ref/errFailPassXmlDefault.xml000066400000000000000000000105171401773523200231370ustar00rootroot00000000000000 luaunit-LUAUNIT_V3_4/test/ref/errFailPassXmlQuiet-failures.txt000066400000000000000000000020101401773523200244560ustar00rootroot00000000000000# XML output to test/ref/errFailPassXmlQuiet-failures.xml # Started on 04/30/19 20:22:53 # Starting class: TestAnotherThing # Starting test: TestAnotherThing.test1_Success1 # Starting test: TestAnotherThing.test1_Success2 # Starting test: TestAnotherThing.test3_Fail1 # Failure: test/test_with_err_fail_pass.lua:49: expected: 0, actual: 2 # Starting test: TestAnotherThing.test3_Fail2 # Failure: test/test_with_err_fail_pass.lua:53: expected: 0, actual: 3 # Starting class: TestSomething # Starting test: TestSomething.test1_Success1 # Starting test: TestSomething.test1_Success2 # Starting test: TestSomething.test2_Fail1 # Failure: test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 # Starting test: TestSomething.test2_Fail2 # Failure: test/test_with_err_fail_pass.lua:19: expected: 0, actual: 3 # Starting test: testFuncFail1 # Failure: test/test_with_err_fail_pass.lua:62: expected: 0, actual: 3 # Starting test: testFuncSuccess1 # Ran 10 tests in 0.000 seconds, 5 successes, 5 failures, 5 non-selected luaunit-LUAUNIT_V3_4/test/ref/errFailPassXmlQuiet-failures.xml000066400000000000000000000051701401773523200244510ustar00rootroot00000000000000 luaunit-LUAUNIT_V3_4/test/ref/errFailPassXmlQuiet-success.txt000066400000000000000000000007041401773523200243240ustar00rootroot00000000000000# XML output to test/ref/errFailPassXmlQuiet-success.xml # Started on 04/30/19 20:22:52 # Starting class: TestAnotherThing # Starting test: TestAnotherThing.test1_Success1 # Starting test: TestAnotherThing.test1_Success2 # Starting class: TestSomething # Starting test: TestSomething.test1_Success1 # Starting test: TestSomething.test1_Success2 # Starting test: testFuncSuccess1 # Ran 5 tests in 0.000 seconds, 5 successes, 0 failures, 10 non-selected luaunit-LUAUNIT_V3_4/test/ref/errFailPassXmlQuiet-success.xml000066400000000000000000000017721401773523200243130ustar00rootroot00000000000000 luaunit-LUAUNIT_V3_4/test/ref/errFailPassXmlQuiet.txt000066400000000000000000000032451401773523200226610ustar00rootroot00000000000000# XML output to test/ref/errFailPassXmlQuiet.xml # Started on 04/30/19 20:22:52 # Starting class: TestAnotherThing # Starting test: TestAnotherThing.test1_Success1 # Starting test: TestAnotherThing.test1_Success2 # Starting test: TestAnotherThing.test2_Err1 # Error: test/test_with_err_fail_pass.lua:41: attempt to perform arithmetic on a table value # Starting test: TestAnotherThing.test2_Err2 # Error: test/test_with_err_fail_pass.lua:45: attempt to perform arithmetic on a table value # Starting test: TestAnotherThing.test3_Fail1 # Failure: test/test_with_err_fail_pass.lua:49: expected: 0, actual: 2 # Starting test: TestAnotherThing.test3_Fail2 # Failure: test/test_with_err_fail_pass.lua:53: expected: 0, actual: 3 # Starting class: TestSomething # Starting test: TestSomething.test1_Success1 # Starting test: TestSomething.test1_Success2 # Starting test: TestSomething.test2_Fail1 # Failure: test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 # Starting test: TestSomething.test2_Fail2 # Failure: test/test_with_err_fail_pass.lua:19: expected: 0, actual: 3 # Starting test: TestSomething.test3_Err1 # Error: test/test_with_err_fail_pass.lua:23: attempt to perform arithmetic on a table value # Starting test: TestSomething.test3_Err2 # Error: test/test_with_err_fail_pass.lua:27: attempt to perform arithmetic on a table value # Starting test: testFuncErr1 # Error: test/test_with_err_fail_pass.lua:66: attempt to perform arithmetic on a table value # Starting test: testFuncFail1 # Failure: test/test_with_err_fail_pass.lua:62: expected: 0, actual: 3 # Starting test: testFuncSuccess1 # Ran 15 tests in 0.000 seconds, 5 successes, 5 failures, 5 errors luaunit-LUAUNIT_V3_4/test/ref/errFailPassXmlQuiet.xml000066400000000000000000000105171401773523200226420ustar00rootroot00000000000000 luaunit-LUAUNIT_V3_4/test/ref/errFailPassXmlVerbose-failures.txt000066400000000000000000000020121401773523200247760ustar00rootroot00000000000000# XML output to test/ref/errFailPassXmlVerbose-failures.xml # Started on 04/30/19 20:22:53 # Starting class: TestAnotherThing # Starting test: TestAnotherThing.test1_Success1 # Starting test: TestAnotherThing.test1_Success2 # Starting test: TestAnotherThing.test3_Fail1 # Failure: test/test_with_err_fail_pass.lua:49: expected: 0, actual: 2 # Starting test: TestAnotherThing.test3_Fail2 # Failure: test/test_with_err_fail_pass.lua:53: expected: 0, actual: 3 # Starting class: TestSomething # Starting test: TestSomething.test1_Success1 # Starting test: TestSomething.test1_Success2 # Starting test: TestSomething.test2_Fail1 # Failure: test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 # Starting test: TestSomething.test2_Fail2 # Failure: test/test_with_err_fail_pass.lua:19: expected: 0, actual: 3 # Starting test: testFuncFail1 # Failure: test/test_with_err_fail_pass.lua:62: expected: 0, actual: 3 # Starting test: testFuncSuccess1 # Ran 10 tests in 0.000 seconds, 5 successes, 5 failures, 5 non-selected luaunit-LUAUNIT_V3_4/test/ref/errFailPassXmlVerbose-failures.xml000066400000000000000000000051701401773523200247670ustar00rootroot00000000000000 luaunit-LUAUNIT_V3_4/test/ref/errFailPassXmlVerbose-success.txt000066400000000000000000000007061401773523200246440ustar00rootroot00000000000000# XML output to test/ref/errFailPassXmlVerbose-success.xml # Started on 04/30/19 20:22:53 # Starting class: TestAnotherThing # Starting test: TestAnotherThing.test1_Success1 # Starting test: TestAnotherThing.test1_Success2 # Starting class: TestSomething # Starting test: TestSomething.test1_Success1 # Starting test: TestSomething.test1_Success2 # Starting test: testFuncSuccess1 # Ran 5 tests in 0.000 seconds, 5 successes, 0 failures, 10 non-selected luaunit-LUAUNIT_V3_4/test/ref/errFailPassXmlVerbose-success.xml000066400000000000000000000017721401773523200246310ustar00rootroot00000000000000 luaunit-LUAUNIT_V3_4/test/ref/errFailPassXmlVerbose.txt000066400000000000000000000032471401773523200232010ustar00rootroot00000000000000# XML output to test/ref/errFailPassXmlVerbose.xml # Started on 04/30/19 20:22:53 # Starting class: TestAnotherThing # Starting test: TestAnotherThing.test1_Success1 # Starting test: TestAnotherThing.test1_Success2 # Starting test: TestAnotherThing.test2_Err1 # Error: test/test_with_err_fail_pass.lua:41: attempt to perform arithmetic on a table value # Starting test: TestAnotherThing.test2_Err2 # Error: test/test_with_err_fail_pass.lua:45: attempt to perform arithmetic on a table value # Starting test: TestAnotherThing.test3_Fail1 # Failure: test/test_with_err_fail_pass.lua:49: expected: 0, actual: 2 # Starting test: TestAnotherThing.test3_Fail2 # Failure: test/test_with_err_fail_pass.lua:53: expected: 0, actual: 3 # Starting class: TestSomething # Starting test: TestSomething.test1_Success1 # Starting test: TestSomething.test1_Success2 # Starting test: TestSomething.test2_Fail1 # Failure: test/test_with_err_fail_pass.lua:15: expected: 0, actual: 2 # Starting test: TestSomething.test2_Fail2 # Failure: test/test_with_err_fail_pass.lua:19: expected: 0, actual: 3 # Starting test: TestSomething.test3_Err1 # Error: test/test_with_err_fail_pass.lua:23: attempt to perform arithmetic on a table value # Starting test: TestSomething.test3_Err2 # Error: test/test_with_err_fail_pass.lua:27: attempt to perform arithmetic on a table value # Starting test: testFuncErr1 # Error: test/test_with_err_fail_pass.lua:66: attempt to perform arithmetic on a table value # Starting test: testFuncFail1 # Failure: test/test_with_err_fail_pass.lua:62: expected: 0, actual: 3 # Starting test: testFuncSuccess1 # Ran 15 tests in 0.000 seconds, 5 successes, 5 failures, 5 errors luaunit-LUAUNIT_V3_4/test/ref/errFailPassXmlVerbose.xml000066400000000000000000000105171401773523200231600ustar00rootroot00000000000000 luaunit-LUAUNIT_V3_4/test/ref/errPassFailTapQuiet.txt000066400000000000000000000012661401773523200226460ustar00rootroot000000000000001..15 # Started on 03/22/16 21:54:40 # Starting class: TestAnotherThing ok 1 TestAnotherThing.test1_Success1 ok 2 TestAnotherThing.test1_Success2 not ok 3 TestAnotherThing.test2_Err1 not ok 4 TestAnotherThing.test2_Err2 not ok 5 TestAnotherThing.test3_Fail1 not ok 6 TestAnotherThing.test3_Fail2 # Starting class: TestSomething ok 7 TestSomething.test1_Success1 ok 8 TestSomething.test1_Success2 not ok 9 TestSomething.test2_Fail1 not ok 10 TestSomething.test2_Fail2 not ok 11 TestSomething.test3_Err1 not ok 12 TestSomething.test3_Err2 not ok 13 testFuncErr1 not ok 14 testFuncFail1 ok 15 testFuncSuccess1 # Ran 15 tests in 0.000 seconds, 5 successes, 5 failures, 5 errors luaunit-LUAUNIT_V3_4/test/ref/exampleNilDefault.txt000066400000000000000000000000001401773523200223420ustar00rootroot00000000000000luaunit-LUAUNIT_V3_4/test/ref/exampleTapDefault.txt000066400000000000000000000025261401773523200223630ustar00rootroot000000000000001..16 # Started on 04/28/19 21:02:44 # Starting class: TestTiti not ok 1 TestTiti.test1_withFailure # example_with_luaunit.lua:109: expected: 2, actual: 1 not ok 2 TestTiti.test2_withFailure # example_with_luaunit.lua:118: expected: "bof" # actual: "hop" ok 3 TestTiti.test3 # Starting class: TestToto not ok 4 TestToto.test1_withFailure # example_with_luaunit.lua:21: expected: 2, actual: 1 not ok 5 TestToto.test2_withFailure # example_with_luaunit.lua:30: expected: "bof" # actual: "hop" ok 6 TestToto.test3 not ok 7 TestToto.test4 # example_with_luaunit.lua:43: Received the not expected value: 1 not ok 8 TestToto.test5 # example_with_luaunit.lua:49: expected: false or nil, actual: 1 not ok 9 TestToto.test6 # example_with_luaunit.lua:57: expected: false, actual: nil not ok 10 TestToto.test7 # example_with_luaunit.lua:63: expected: {1, 2, three=3} # actual: {1, 2} not ok 11 TestToto.test8a # example_with_luaunit.lua:81: Bouhouhoum error! not ok 12 TestToto.test8b # example_with_luaunit.lua:81: Bouhouhoum error! ok 13 # SKIP Test is skipped because ... not ok 14 test1_withAssertionError # example_with_luaunit.lua:134: assertion failed! not ok 15 test2_withAssertionError # example_with_luaunit.lua:140: assertion failed! ok 16 test3 # Ran 15 tests in 0.000 seconds, 3 successes, 8 failures, 4 errors, 1 skipped luaunit-LUAUNIT_V3_4/test/ref/exampleTapQuiet.txt000066400000000000000000000011751401773523200220650ustar00rootroot000000000000001..16 # Started on 04/28/19 21:02:44 # Starting class: TestTiti not ok 1 TestTiti.test1_withFailure not ok 2 TestTiti.test2_withFailure ok 3 TestTiti.test3 # Starting class: TestToto not ok 4 TestToto.test1_withFailure not ok 5 TestToto.test2_withFailure ok 6 TestToto.test3 not ok 7 TestToto.test4 not ok 8 TestToto.test5 not ok 9 TestToto.test6 not ok 10 TestToto.test7 not ok 11 TestToto.test8a not ok 12 TestToto.test8b ok 13 # SKIP Test is skipped because ... not ok 14 test1_withAssertionError not ok 15 test2_withAssertionError ok 16 test3 # Ran 15 tests in 0.000 seconds, 3 successes, 8 failures, 4 errors, 1 skipped luaunit-LUAUNIT_V3_4/test/ref/exampleTapVerbose.txt000066400000000000000000000051221401773523200223770ustar00rootroot000000000000001..16 # Started on 04/28/19 21:02:44 # Starting class: TestTiti not ok 1 TestTiti.test1_withFailure # example_with_luaunit.lua:109: expected: 2, actual: 1 # stack traceback: # example_with_luaunit.lua:109: in function 'TestTiti.test1_withFailure' not ok 2 TestTiti.test2_withFailure # example_with_luaunit.lua:118: expected: "bof" # actual: "hop" # stack traceback: # example_with_luaunit.lua:118: in function 'TestTiti.test2_withFailure' ok 3 TestTiti.test3 # Starting class: TestToto not ok 4 TestToto.test1_withFailure # example_with_luaunit.lua:21: expected: 2, actual: 1 # stack traceback: # example_with_luaunit.lua:21: in function 'TestToto.test1_withFailure' not ok 5 TestToto.test2_withFailure # example_with_luaunit.lua:30: expected: "bof" # actual: "hop" # stack traceback: # example_with_luaunit.lua:30: in function 'TestToto.test2_withFailure' ok 6 TestToto.test3 not ok 7 TestToto.test4 # example_with_luaunit.lua:43: Received the not expected value: 1 # stack traceback: # example_with_luaunit.lua:43: in function 'TestToto.test4' not ok 8 TestToto.test5 # example_with_luaunit.lua:49: expected: false or nil, actual: 1 # stack traceback: # example_with_luaunit.lua:49: in function 'TestToto.test5' not ok 9 TestToto.test6 # example_with_luaunit.lua:57: expected: false, actual: nil # stack traceback: # example_with_luaunit.lua:57: in function 'TestToto.test6' not ok 10 TestToto.test7 # example_with_luaunit.lua:63: expected: {1, 2, three=3} # actual: {1, 2} # stack traceback: # example_with_luaunit.lua:63: in function 'TestToto.test7' not ok 11 TestToto.test8a # example_with_luaunit.lua:81: Bouhouhoum error! # stack traceback: # example_with_luaunit.lua:81: in function 'funcWithError' # example_with_luaunit.lua:68: in function 'TestToto.test8a' not ok 12 TestToto.test8b # example_with_luaunit.lua:81: Bouhouhoum error! # stack traceback: # example_with_luaunit.lua:81: in function 'funcWithError' # example_with_luaunit.lua:77: in function 'funcWithFuncWithError' # example_with_luaunit.lua:73: in function 'TestToto.test8b' ok 13 # SKIP Test is skipped because ... not ok 14 test1_withAssertionError # example_with_luaunit.lua:134: assertion failed! # stack traceback: # example_with_luaunit.lua:134: in function 'test1_withAssertionError' not ok 15 test2_withAssertionError # example_with_luaunit.lua:140: assertion failed! # stack traceback: # example_with_luaunit.lua:140: in function 'test2_withAssertionError' ok 16 test3 # Ran 15 tests in 0.000 seconds, 3 successes, 8 failures, 4 errors, 1 skipped luaunit-LUAUNIT_V3_4/test/ref/exampleTextDefault.txt000066400000000000000000000043661401773523200225670ustar00rootroot00000000000000FF.FF.FFFFEESEE. Tests with errors: ------------------ 1) TestToto.test8a example_with_luaunit.lua:81: Bouhouhoum error! stack traceback: example_with_luaunit.lua:81: in function 'funcWithError' example_with_luaunit.lua:68: in function 'TestToto.test8a' 2) TestToto.test8b example_with_luaunit.lua:81: Bouhouhoum error! stack traceback: example_with_luaunit.lua:81: in function 'funcWithError' example_with_luaunit.lua:77: in function 'funcWithFuncWithError' example_with_luaunit.lua:73: in function 'TestToto.test8b' 3) test1_withAssertionError example_with_luaunit.lua:134: assertion failed! stack traceback: example_with_luaunit.lua:134: in function 'test1_withAssertionError' 4) test2_withAssertionError example_with_luaunit.lua:140: assertion failed! stack traceback: example_with_luaunit.lua:140: in function 'test2_withAssertionError' Failed tests: ------------- 1) TestTiti.test1_withFailure example_with_luaunit.lua:109: expected: 2, actual: 1 stack traceback: example_with_luaunit.lua:109: in function 'TestTiti.test1_withFailure' 2) TestTiti.test2_withFailure example_with_luaunit.lua:118: expected: "bof" actual: "hop" stack traceback: example_with_luaunit.lua:118: in function 'TestTiti.test2_withFailure' 3) TestToto.test1_withFailure example_with_luaunit.lua:21: expected: 2, actual: 1 stack traceback: example_with_luaunit.lua:21: in function 'TestToto.test1_withFailure' 4) TestToto.test2_withFailure example_with_luaunit.lua:30: expected: "bof" actual: "hop" stack traceback: example_with_luaunit.lua:30: in function 'TestToto.test2_withFailure' 5) TestToto.test4 example_with_luaunit.lua:43: Received the not expected value: 1 stack traceback: example_with_luaunit.lua:43: in function 'TestToto.test4' 6) TestToto.test5 example_with_luaunit.lua:49: expected: false or nil, actual: 1 stack traceback: example_with_luaunit.lua:49: in function 'TestToto.test5' 7) TestToto.test6 example_with_luaunit.lua:57: expected: false, actual: nil stack traceback: example_with_luaunit.lua:57: in function 'TestToto.test6' 8) TestToto.test7 example_with_luaunit.lua:63: expected: {1, 2, three=3} actual: {1, 2} stack traceback: example_with_luaunit.lua:63: in function 'TestToto.test7' Ran 15 tests in 0.009 seconds, 3 successes, 8 failures, 4 errors, 1 skipped luaunit-LUAUNIT_V3_4/test/ref/exampleTextQuiet.txt000066400000000000000000000043661401773523200222720ustar00rootroot00000000000000FF.FF.FFFFEESEE. Tests with errors: ------------------ 1) TestToto.test8a example_with_luaunit.lua:81: Bouhouhoum error! stack traceback: example_with_luaunit.lua:81: in function 'funcWithError' example_with_luaunit.lua:68: in function 'TestToto.test8a' 2) TestToto.test8b example_with_luaunit.lua:81: Bouhouhoum error! stack traceback: example_with_luaunit.lua:81: in function 'funcWithError' example_with_luaunit.lua:77: in function 'funcWithFuncWithError' example_with_luaunit.lua:73: in function 'TestToto.test8b' 3) test1_withAssertionError example_with_luaunit.lua:134: assertion failed! stack traceback: example_with_luaunit.lua:134: in function 'test1_withAssertionError' 4) test2_withAssertionError example_with_luaunit.lua:140: assertion failed! stack traceback: example_with_luaunit.lua:140: in function 'test2_withAssertionError' Failed tests: ------------- 1) TestTiti.test1_withFailure example_with_luaunit.lua:109: expected: 2, actual: 1 stack traceback: example_with_luaunit.lua:109: in function 'TestTiti.test1_withFailure' 2) TestTiti.test2_withFailure example_with_luaunit.lua:118: expected: "bof" actual: "hop" stack traceback: example_with_luaunit.lua:118: in function 'TestTiti.test2_withFailure' 3) TestToto.test1_withFailure example_with_luaunit.lua:21: expected: 2, actual: 1 stack traceback: example_with_luaunit.lua:21: in function 'TestToto.test1_withFailure' 4) TestToto.test2_withFailure example_with_luaunit.lua:30: expected: "bof" actual: "hop" stack traceback: example_with_luaunit.lua:30: in function 'TestToto.test2_withFailure' 5) TestToto.test4 example_with_luaunit.lua:43: Received the not expected value: 1 stack traceback: example_with_luaunit.lua:43: in function 'TestToto.test4' 6) TestToto.test5 example_with_luaunit.lua:49: expected: false or nil, actual: 1 stack traceback: example_with_luaunit.lua:49: in function 'TestToto.test5' 7) TestToto.test6 example_with_luaunit.lua:57: expected: false, actual: nil stack traceback: example_with_luaunit.lua:57: in function 'TestToto.test6' 8) TestToto.test7 example_with_luaunit.lua:63: expected: {1, 2, three=3} actual: {1, 2} stack traceback: example_with_luaunit.lua:63: in function 'TestToto.test7' Ran 15 tests in 0.000 seconds, 3 successes, 8 failures, 4 errors, 1 skipped luaunit-LUAUNIT_V3_4/test/ref/exampleTextVerbose.txt000066400000000000000000000067671401773523200226170ustar00rootroot00000000000000Started on 04/28/19 21:02:44 TestTiti.test1_withFailure ... FAIL example_with_luaunit.lua:109: expected: 2, actual: 1 TestTiti.test2_withFailure ... FAIL example_with_luaunit.lua:118: expected: "bof" actual: "hop" TestTiti.test3 ... Ok TestToto.test1_withFailure ... FAIL example_with_luaunit.lua:21: expected: 2, actual: 1 TestToto.test2_withFailure ... FAIL example_with_luaunit.lua:30: expected: "bof" actual: "hop" TestToto.test3 ... Ok TestToto.test4 ... FAIL example_with_luaunit.lua:43: Received the not expected value: 1 TestToto.test5 ... FAIL example_with_luaunit.lua:49: expected: false or nil, actual: 1 TestToto.test6 ... FAIL example_with_luaunit.lua:57: expected: false, actual: nil TestToto.test7 ... FAIL example_with_luaunit.lua:63: expected: {1, 2, three=3} actual: {1, 2} TestToto.test8a ... ERROR example_with_luaunit.lua:81: Bouhouhoum error! TestToto.test8b ... ERROR example_with_luaunit.lua:81: Bouhouhoum error! TestToto.test_skipped ... SKIP Test is skipped because ... test1_withAssertionError ... ERROR example_with_luaunit.lua:134: assertion failed! test2_withAssertionError ... ERROR example_with_luaunit.lua:140: assertion failed! test3 ... Ok ========================================================= Tests with errors: ------------------ 1) TestToto.test8a example_with_luaunit.lua:81: Bouhouhoum error! stack traceback: example_with_luaunit.lua:81: in function 'funcWithError' example_with_luaunit.lua:68: in function 'TestToto.test8a' 2) TestToto.test8b example_with_luaunit.lua:81: Bouhouhoum error! stack traceback: example_with_luaunit.lua:81: in function 'funcWithError' example_with_luaunit.lua:77: in function 'funcWithFuncWithError' example_with_luaunit.lua:73: in function 'TestToto.test8b' 3) test1_withAssertionError example_with_luaunit.lua:134: assertion failed! stack traceback: example_with_luaunit.lua:134: in function 'test1_withAssertionError' 4) test2_withAssertionError example_with_luaunit.lua:140: assertion failed! stack traceback: example_with_luaunit.lua:140: in function 'test2_withAssertionError' Failed tests: ------------- 1) TestTiti.test1_withFailure example_with_luaunit.lua:109: expected: 2, actual: 1 stack traceback: example_with_luaunit.lua:109: in function 'TestTiti.test1_withFailure' 2) TestTiti.test2_withFailure example_with_luaunit.lua:118: expected: "bof" actual: "hop" stack traceback: example_with_luaunit.lua:118: in function 'TestTiti.test2_withFailure' 3) TestToto.test1_withFailure example_with_luaunit.lua:21: expected: 2, actual: 1 stack traceback: example_with_luaunit.lua:21: in function 'TestToto.test1_withFailure' 4) TestToto.test2_withFailure example_with_luaunit.lua:30: expected: "bof" actual: "hop" stack traceback: example_with_luaunit.lua:30: in function 'TestToto.test2_withFailure' 5) TestToto.test4 example_with_luaunit.lua:43: Received the not expected value: 1 stack traceback: example_with_luaunit.lua:43: in function 'TestToto.test4' 6) TestToto.test5 example_with_luaunit.lua:49: expected: false or nil, actual: 1 stack traceback: example_with_luaunit.lua:49: in function 'TestToto.test5' 7) TestToto.test6 example_with_luaunit.lua:57: expected: false, actual: nil stack traceback: example_with_luaunit.lua:57: in function 'TestToto.test6' 8) TestToto.test7 example_with_luaunit.lua:63: expected: {1, 2, three=3} actual: {1, 2} stack traceback: example_with_luaunit.lua:63: in function 'TestToto.test7' Ran 15 tests in 0.000 seconds, 3 successes, 8 failures, 4 errors, 1 skipped luaunit-LUAUNIT_V3_4/test/ref/exampleXmlDefault.txt000066400000000000000000000031371401773523200223760ustar00rootroot00000000000000# XML output to test/ref/exampleXmlDefault.xml # Started on 04/28/19 21:02:44 # Starting class: TestTiti # Starting test: TestTiti.test1_withFailure # Failure: example_with_luaunit.lua:109: expected: 2, actual: 1 # Starting test: TestTiti.test2_withFailure # Failure: example_with_luaunit.lua:118: expected: "bof" # actual: "hop" # Starting test: TestTiti.test3 # Starting class: TestToto # Starting test: TestToto.test1_withFailure # Failure: example_with_luaunit.lua:21: expected: 2, actual: 1 # Starting test: TestToto.test2_withFailure # Failure: example_with_luaunit.lua:30: expected: "bof" # actual: "hop" # Starting test: TestToto.test3 # Starting test: TestToto.test4 # Failure: example_with_luaunit.lua:43: Received the not expected value: 1 # Starting test: TestToto.test5 # Failure: example_with_luaunit.lua:49: expected: false or nil, actual: 1 # Starting test: TestToto.test6 # Failure: example_with_luaunit.lua:57: expected: false, actual: nil # Starting test: TestToto.test7 # Failure: example_with_luaunit.lua:63: expected: {1, 2, three=3} # actual: {1, 2} # Starting test: TestToto.test8a # Error: example_with_luaunit.lua:81: Bouhouhoum error! # Starting test: TestToto.test8b # Error: example_with_luaunit.lua:81: Bouhouhoum error! # Starting test: TestToto.test_skipped # Starting test: test1_withAssertionError # Error: example_with_luaunit.lua:134: assertion failed! # Starting test: test2_withAssertionError # Error: example_with_luaunit.lua:140: assertion failed! # Starting test: test3 # Ran 15 tests in 0.009 seconds, 3 successes, 8 failures, 4 errors, 1 skipped luaunit-LUAUNIT_V3_4/test/ref/exampleXmlDefault.xml000066400000000000000000000112541401773523200223560ustar00rootroot00000000000000 Test is skipped because ... luaunit-LUAUNIT_V3_4/test/ref/exampleXmlQuiet.txt000066400000000000000000000031351401773523200220770ustar00rootroot00000000000000# XML output to test/ref/exampleXmlQuiet.xml # Started on 04/28/19 21:02:44 # Starting class: TestTiti # Starting test: TestTiti.test1_withFailure # Failure: example_with_luaunit.lua:109: expected: 2, actual: 1 # Starting test: TestTiti.test2_withFailure # Failure: example_with_luaunit.lua:118: expected: "bof" # actual: "hop" # Starting test: TestTiti.test3 # Starting class: TestToto # Starting test: TestToto.test1_withFailure # Failure: example_with_luaunit.lua:21: expected: 2, actual: 1 # Starting test: TestToto.test2_withFailure # Failure: example_with_luaunit.lua:30: expected: "bof" # actual: "hop" # Starting test: TestToto.test3 # Starting test: TestToto.test4 # Failure: example_with_luaunit.lua:43: Received the not expected value: 1 # Starting test: TestToto.test5 # Failure: example_with_luaunit.lua:49: expected: false or nil, actual: 1 # Starting test: TestToto.test6 # Failure: example_with_luaunit.lua:57: expected: false, actual: nil # Starting test: TestToto.test7 # Failure: example_with_luaunit.lua:63: expected: {1, 2, three=3} # actual: {1, 2} # Starting test: TestToto.test8a # Error: example_with_luaunit.lua:81: Bouhouhoum error! # Starting test: TestToto.test8b # Error: example_with_luaunit.lua:81: Bouhouhoum error! # Starting test: TestToto.test_skipped # Starting test: test1_withAssertionError # Error: example_with_luaunit.lua:134: assertion failed! # Starting test: test2_withAssertionError # Error: example_with_luaunit.lua:140: assertion failed! # Starting test: test3 # Ran 15 tests in 0.000 seconds, 3 successes, 8 failures, 4 errors, 1 skipped luaunit-LUAUNIT_V3_4/test/ref/exampleXmlQuiet.xml000066400000000000000000000112541401773523200220610ustar00rootroot00000000000000 Test is skipped because ... luaunit-LUAUNIT_V3_4/test/ref/exampleXmlVerbose.txt000066400000000000000000000031371401773523200224170ustar00rootroot00000000000000# XML output to test/ref/exampleXmlVerbose.xml # Started on 04/28/19 21:02:44 # Starting class: TestTiti # Starting test: TestTiti.test1_withFailure # Failure: example_with_luaunit.lua:109: expected: 2, actual: 1 # Starting test: TestTiti.test2_withFailure # Failure: example_with_luaunit.lua:118: expected: "bof" # actual: "hop" # Starting test: TestTiti.test3 # Starting class: TestToto # Starting test: TestToto.test1_withFailure # Failure: example_with_luaunit.lua:21: expected: 2, actual: 1 # Starting test: TestToto.test2_withFailure # Failure: example_with_luaunit.lua:30: expected: "bof" # actual: "hop" # Starting test: TestToto.test3 # Starting test: TestToto.test4 # Failure: example_with_luaunit.lua:43: Received the not expected value: 1 # Starting test: TestToto.test5 # Failure: example_with_luaunit.lua:49: expected: false or nil, actual: 1 # Starting test: TestToto.test6 # Failure: example_with_luaunit.lua:57: expected: false, actual: nil # Starting test: TestToto.test7 # Failure: example_with_luaunit.lua:63: expected: {1, 2, three=3} # actual: {1, 2} # Starting test: TestToto.test8a # Error: example_with_luaunit.lua:81: Bouhouhoum error! # Starting test: TestToto.test8b # Error: example_with_luaunit.lua:81: Bouhouhoum error! # Starting test: TestToto.test_skipped # Starting test: test1_withAssertionError # Error: example_with_luaunit.lua:134: assertion failed! # Starting test: test2_withAssertionError # Error: example_with_luaunit.lua:140: assertion failed! # Starting test: test3 # Ran 15 tests in 0.010 seconds, 3 successes, 8 failures, 4 errors, 1 skipped luaunit-LUAUNIT_V3_4/test/ref/exampleXmlVerbose.xml000066400000000000000000000112541401773523200223770ustar00rootroot00000000000000 Test is skipped because ... luaunit-LUAUNIT_V3_4/test/ref/some_lists_comparisons.txt000066400000000000000000000503131401773523200235510ustar00rootroot00000000000000Started on 11/08/16 21:28:53 TestListCompare.test1 ... FAIL test/some_lists_comparisons.lua:22: expected: { 121221, 122211, 121221, 122211, 121221, 122212, 121212, 122112, 121221, 121212, 122121 } actual: { 121221, 122211, 121221, 122211, 121221, 122212, 121212, 122112, 122121, 121212, 122121 } List difference analysis: * lists A (actual) and B (expected) have the same size * lists A and B start differing at index 9 * lists A and B are equal again from index 10 * Common parts: = A[1], B[1]: 121221 = A[2], B[2]: 122211 = A[3], B[3]: 121221 = A[4], B[4]: 122211 = A[5], B[5]: 121221 = A[6], B[6]: 122212 = A[7], B[7]: 121212 = A[8], B[8]: 122112 * Differing parts: - A[9]: 122121 + B[9]: 121221 * Common parts at the end of the lists = A[10], B[10]: 121212 = A[11], B[11]: 122121 TestListCompare.test1b ... FAIL test/some_lists_comparisons.lua:28: expected: { 121221, 122211, 121221, 122112, 121212, 121122, 121212, 122122, 121212, 122112, 121212 } actual: { 121221, 122211, 121221, 122112, 121212, 121122, 121212, 122122, 121212, 122112, 122112 } List difference analysis: * lists A (actual) and B (expected) have the same size * lists A and B start differing at index 11 * Common parts: = A[1], B[1]: 121221 = A[2], B[2]: 122211 = A[3], B[3]: 121221 = A[4], B[4]: 122112 = A[5], B[5]: 121212 = A[6], B[6]: 121122 = A[7], B[7]: 121212 = A[8], B[8]: 122122 = A[9], B[9]: 121212 = A[10], B[10]: 122112 * Differing parts: - A[11]: 122112 + B[11]: 121212 TestListCompare.test1c ... FAIL test/some_lists_comparisons.lua:34: expected: { 121212, 122121, 111212, 122121, 122121, 121212, 121121, 121212, 121221, 122212, 112121 } actual: { 122112, 122121, 111212, 122121, 122121, 121212, 121121, 121212, 121221, 122212, 112121 } List difference analysis: * lists A (actual) and B (expected) have the same size * lists A and B start differing at index 1 * lists A and B are equal again from index 2 * Differing parts: - A[1]: 122112 + B[1]: 121212 * Common parts at the end of the lists = A[2], B[2]: 122121 = A[3], B[3]: 111212 = A[4], B[4]: 122121 = A[5], B[5]: 122121 = A[6], B[6]: 121212 = A[7], B[7]: 121121 = A[8], B[8]: 121212 = A[9], B[9]: 121221 = A[10], B[10]: 122212 = A[11], B[11]: 112121 TestListCompare.test2 ... FAIL test/some_lists_comparisons.lua:43: expected: {1, 2, 3, 4, 5, 6, 8, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} actual: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} List difference analysis: * lists A (actual) and B (expected) have the same size * lists A and B start differing at index 7 * lists A and B are equal again from index 9 * Common parts: = A[1], B[1]: 1 = A[2], B[2]: 2 = A[3], B[3]: 3 = A[4], B[4]: 4 = A[5], B[5]: 5 = A[6], B[6]: 6 * Differing parts: - A[7]: 7 + B[7]: 8 - A[8]: 8 + B[8]: 7 * Common parts at the end of the lists = A[9], B[9]: 9 = A[10], B[10]: 10 = A[11], B[11]: 11 = A[12], B[12]: 12 = A[13], B[13]: 13 = A[14], B[14]: 14 = A[15], B[15]: 15 = A[16], B[16]: 16 = A[17], B[17]: 17 = A[18], B[18]: 18 = A[19], B[19]: 19 = A[20], B[20]: 20 TestListCompare.test3 ... FAIL test/some_lists_comparisons.lua:57: expected: {1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} actual: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} List difference analysis: * list sizes differ: list A (actual) has 20 items, list B (expected) has 19 items * lists A and B start differing at index 7 * lists A and B are equal again from index 8 for A, 7 for B * Common parts: = A[1], B[1]: 1 = A[2], B[2]: 2 = A[3], B[3]: 3 = A[4], B[4]: 4 = A[5], B[5]: 5 = A[6], B[6]: 6 * Present only in one list: - A[7]: 7 * Common parts at the end of the lists = A[8], B[7]: 8 = A[9], B[8]: 9 = A[10], B[9]: 10 = A[11], B[10]: 11 = A[12], B[11]: 12 = A[13], B[12]: 13 = A[14], B[13]: 14 = A[15], B[14]: 15 = A[16], B[15]: 16 = A[17], B[16]: 17 = A[18], B[17]: 18 = A[19], B[18]: 19 = A[20], B[19]: 20 TestListCompare.test4 ... FAIL test/some_lists_comparisons.lua:74: expected: {1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} actual: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} List difference analysis: * list sizes differ: list A (actual) has 20 items, list B (expected) has 17 items * lists A and B start differing at index 7 * lists A and B are equal again from index 10 for A, 7 for B * Common parts: = A[1], B[1]: 1 = A[2], B[2]: 2 = A[3], B[3]: 3 = A[4], B[4]: 4 = A[5], B[5]: 5 = A[6], B[6]: 6 * Present only in one list: - A[7]: 7 - A[8]: 8 - A[9]: 9 * Common parts at the end of the lists = A[10], B[7]: 10 = A[11], B[8]: 11 = A[12], B[9]: 12 = A[13], B[10]: 13 = A[14], B[11]: 14 = A[15], B[12]: 15 = A[16], B[13]: 16 = A[17], B[14]: 17 = A[18], B[15]: 18 = A[19], B[16]: 19 = A[20], B[17]: 20 TestListCompare.test5a ... FAIL test/some_lists_comparisons.lua:98: expected: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} actual: {1, 2, 3, 4, 6, 5, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} List difference analysis: * list sizes differ: list A (expected) has 17 items, list B (actual) has 20 items * lists A and B start differing at index 5 * lists A and B are equal again from index 7 for A, 10 for B * Common parts: = A[1], B[1]: 1 = A[2], B[2]: 2 = A[3], B[3]: 3 = A[4], B[4]: 4 * Differing parts: - A[5]: 6 + B[5]: 5 - A[6]: 5 + B[6]: 6 * Present only in one list: + B[7]: 7 + B[8]: 8 + B[9]: 9 * Common parts at the end of the lists = A[7], B[10]: 10 = A[8], B[11]: 11 = A[9], B[12]: 12 = A[10], B[13]: 13 = A[11], B[14]: 14 = A[12], B[15]: 15 = A[13], B[16]: 16 = A[14], B[17]: 17 = A[15], B[18]: 18 = A[16], B[19]: 19 = A[17], B[20]: 20 TestListCompare.test5b ... FAIL test/some_lists_comparisons.lua:103: expected: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} actual: {1, 2, 3, 4, 6, 5, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} List difference analysis: * list sizes differ: list A (actual) has 17 items, list B (expected) has 20 items * lists A and B start differing at index 5 * lists A and B are equal again from index 7 for A, 10 for B * Common parts: = A[1], B[1]: 1 = A[2], B[2]: 2 = A[3], B[3]: 3 = A[4], B[4]: 4 * Differing parts: - A[5]: 6 + B[5]: 5 - A[6]: 5 + B[6]: 6 * Present only in one list: + B[7]: 7 + B[8]: 8 + B[9]: 9 * Common parts at the end of the lists = A[7], B[10]: 10 = A[8], B[11]: 11 = A[9], B[12]: 12 = A[10], B[13]: 13 = A[11], B[14]: 14 = A[12], B[15]: 15 = A[13], B[16]: 16 = A[14], B[17]: 17 = A[15], B[18]: 18 = A[16], B[19]: 19 = A[17], B[20]: 20 TestListCompare.test5c ... FAIL test/some_lists_comparisons.lua:109: expected:
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} actual:
{1, 2, 3, 4, 6, 5, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} List difference analysis: * list sizes differ: list
A (actual) has 17 items, list
B (expected) has 20 items * lists A and B start differing at index 5 * lists A and B are equal again from index 7 for A, 10 for B * Common parts: = A[1], B[1]: 1 = A[2], B[2]: 2 = A[3], B[3]: 3 = A[4], B[4]: 4 * Differing parts: - A[5]: 6 + B[5]: 5 - A[6]: 5 + B[6]: 6 * Present only in one list: + B[7]: 7 + B[8]: 8 + B[9]: 9 * Common parts at the end of the lists = A[7], B[10]: 10 = A[8], B[11]: 11 = A[9], B[12]: 12 = A[10], B[13]: 13 = A[11], B[14]: 14 = A[12], B[15]: 15 = A[13], B[16]: 16 = A[14], B[17]: 17 = A[15], B[18]: 18 = A[16], B[19]: 19 = A[17], B[20]: 20 TestListCompare.test6 ... FAIL test/some_lists_comparisons.lua:117: expected: { "aaa", "bbb", "ccc", function: 00E70160, 1.1, 2.1, 8=true, 9=false, 10=thread: 00E35480, 11=thread: 00E35480, 12=thread: 00E35480 } actual: { "aaa", "bbb", "ccc", function: 00E70160, 1.1, 2.1, 8=false, 9=false, 10=thread: 00E35480, 11=thread: 00E35480, 12=thread: 00E35480 } List difference analysis: * lists A (actual) and B (expected) have the same size * lists A and B start differing at index 8 * lists A and B are equal again from index 9 * Common parts: = A[1], B[1]: "aaa" = A[2], B[2]: "bbb" = A[3], B[3]: "ccc" = A[4], B[4]: function: 00E70160 = A[5], B[5]: 1.1 = A[6], B[6]: 2.1 = A[7], B[7]: nil * Differing parts: - A[8]: false + B[8]: true * Common parts at the end of the lists = A[9], B[9]: false = A[10], B[10]: thread: 00E35480 = A[11], B[11]: thread: 00E35480 = A[12], B[12]: thread: 00E35480 TestListCompare.test7 ... FAIL test/some_lists_comparisons.lua:123: expected: {{1, 2, 3}, {1, 2}, {{1}, {2}}, {"aa", "cc"}, 1, 2, 1.33, #Inf, {a=1}, {}} actual: {{1, 2, 3}, {1, 2}, {{2}, {2}}, {"aa", "bb"}, 1, 2, 1.33, #Inf, {a=1}, {}} List difference analysis: * lists A (actual) and B (expected) have the same size * lists A and B start differing at index 3 * lists A and B are equal again from index 5 * Common parts: = A[1], B[1]: {1, 2, 3} = A[2], B[2]: {1, 2} * Differing parts: - A[3]: {{2}, {2}} + B[3]: {{1}, {2}} - A[4]: {"aa", "bb"} + B[4]: {"aa", "cc"} * Common parts at the end of the lists = A[5], B[5]: 1 = A[6], B[6]: 2 = A[7], B[7]: 1.33 = A[8], B[8]: #Inf = A[9], B[9]: {a=1} = A[10], B[10]: {} ========================================================= Failed tests: ------------- 1) TestListCompare.test1 test/some_lists_comparisons.lua:22: expected: { 121221, 122211, 121221, 122211, 121221, 122212, 121212, 122112, 121221, 121212, 122121 } actual: { 121221, 122211, 121221, 122211, 121221, 122212, 121212, 122112, 122121, 121212, 122121 } List difference analysis: * lists A (actual) and B (expected) have the same size * lists A and B start differing at index 9 * lists A and B are equal again from index 10 * Common parts: = A[1], B[1]: 121221 = A[2], B[2]: 122211 = A[3], B[3]: 121221 = A[4], B[4]: 122211 = A[5], B[5]: 121221 = A[6], B[6]: 122212 = A[7], B[7]: 121212 = A[8], B[8]: 122112 * Differing parts: - A[9]: 122121 + B[9]: 121221 * Common parts at the end of the lists = A[10], B[10]: 121212 = A[11], B[11]: 122121 stack traceback: test/some_lists_comparisons.lua:22: in function 'TestListCompare.test1' 2) TestListCompare.test1b test/some_lists_comparisons.lua:28: expected: { 121221, 122211, 121221, 122112, 121212, 121122, 121212, 122122, 121212, 122112, 121212 } actual: { 121221, 122211, 121221, 122112, 121212, 121122, 121212, 122122, 121212, 122112, 122112 } List difference analysis: * lists A (actual) and B (expected) have the same size * lists A and B start differing at index 11 * Common parts: = A[1], B[1]: 121221 = A[2], B[2]: 122211 = A[3], B[3]: 121221 = A[4], B[4]: 122112 = A[5], B[5]: 121212 = A[6], B[6]: 121122 = A[7], B[7]: 121212 = A[8], B[8]: 122122 = A[9], B[9]: 121212 = A[10], B[10]: 122112 * Differing parts: - A[11]: 122112 + B[11]: 121212 stack traceback: test/some_lists_comparisons.lua:28: in function 'TestListCompare.test1b' 3) TestListCompare.test1c test/some_lists_comparisons.lua:34: expected: { 121212, 122121, 111212, 122121, 122121, 121212, 121121, 121212, 121221, 122212, 112121 } actual: { 122112, 122121, 111212, 122121, 122121, 121212, 121121, 121212, 121221, 122212, 112121 } List difference analysis: * lists A (actual) and B (expected) have the same size * lists A and B start differing at index 1 * lists A and B are equal again from index 2 * Differing parts: - A[1]: 122112 + B[1]: 121212 * Common parts at the end of the lists = A[2], B[2]: 122121 = A[3], B[3]: 111212 = A[4], B[4]: 122121 = A[5], B[5]: 122121 = A[6], B[6]: 121212 = A[7], B[7]: 121121 = A[8], B[8]: 121212 = A[9], B[9]: 121221 = A[10], B[10]: 122212 = A[11], B[11]: 112121 stack traceback: test/some_lists_comparisons.lua:34: in function 'TestListCompare.test1c' 4) TestListCompare.test2 test/some_lists_comparisons.lua:43: expected: {1, 2, 3, 4, 5, 6, 8, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} actual: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} List difference analysis: * lists A (actual) and B (expected) have the same size * lists A and B start differing at index 7 * lists A and B are equal again from index 9 * Common parts: = A[1], B[1]: 1 = A[2], B[2]: 2 = A[3], B[3]: 3 = A[4], B[4]: 4 = A[5], B[5]: 5 = A[6], B[6]: 6 * Differing parts: - A[7]: 7 + B[7]: 8 - A[8]: 8 + B[8]: 7 * Common parts at the end of the lists = A[9], B[9]: 9 = A[10], B[10]: 10 = A[11], B[11]: 11 = A[12], B[12]: 12 = A[13], B[13]: 13 = A[14], B[14]: 14 = A[15], B[15]: 15 = A[16], B[16]: 16 = A[17], B[17]: 17 = A[18], B[18]: 18 = A[19], B[19]: 19 = A[20], B[20]: 20 stack traceback: test/some_lists_comparisons.lua:43: in function 'TestListCompare.test2' 5) TestListCompare.test3 test/some_lists_comparisons.lua:57: expected: {1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} actual: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} List difference analysis: * list sizes differ: list A (actual) has 20 items, list B (expected) has 19 items * lists A and B start differing at index 7 * lists A and B are equal again from index 8 for A, 7 for B * Common parts: = A[1], B[1]: 1 = A[2], B[2]: 2 = A[3], B[3]: 3 = A[4], B[4]: 4 = A[5], B[5]: 5 = A[6], B[6]: 6 * Present only in one list: - A[7]: 7 * Common parts at the end of the lists = A[8], B[7]: 8 = A[9], B[8]: 9 = A[10], B[9]: 10 = A[11], B[10]: 11 = A[12], B[11]: 12 = A[13], B[12]: 13 = A[14], B[13]: 14 = A[15], B[14]: 15 = A[16], B[15]: 16 = A[17], B[16]: 17 = A[18], B[17]: 18 = A[19], B[18]: 19 = A[20], B[19]: 20 stack traceback: test/some_lists_comparisons.lua:57: in function 'TestListCompare.test3' 6) TestListCompare.test4 test/some_lists_comparisons.lua:74: expected: {1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} actual: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} List difference analysis: * list sizes differ: list A (actual) has 20 items, list B (expected) has 17 items * lists A and B start differing at index 7 * lists A and B are equal again from index 10 for A, 7 for B * Common parts: = A[1], B[1]: 1 = A[2], B[2]: 2 = A[3], B[3]: 3 = A[4], B[4]: 4 = A[5], B[5]: 5 = A[6], B[6]: 6 * Present only in one list: - A[7]: 7 - A[8]: 8 - A[9]: 9 * Common parts at the end of the lists = A[10], B[7]: 10 = A[11], B[8]: 11 = A[12], B[9]: 12 = A[13], B[10]: 13 = A[14], B[11]: 14 = A[15], B[12]: 15 = A[16], B[13]: 16 = A[17], B[14]: 17 = A[18], B[15]: 18 = A[19], B[16]: 19 = A[20], B[17]: 20 stack traceback: test/some_lists_comparisons.lua:74: in function 'TestListCompare.test4' 7) TestListCompare.test5a test/some_lists_comparisons.lua:98: expected: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} actual: {1, 2, 3, 4, 6, 5, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} List difference analysis: * list sizes differ: list A (expected) has 17 items, list B (actual) has 20 items * lists A and B start differing at index 5 * lists A and B are equal again from index 7 for A, 10 for B * Common parts: = A[1], B[1]: 1 = A[2], B[2]: 2 = A[3], B[3]: 3 = A[4], B[4]: 4 * Differing parts: - A[5]: 6 + B[5]: 5 - A[6]: 5 + B[6]: 6 * Present only in one list: + B[7]: 7 + B[8]: 8 + B[9]: 9 * Common parts at the end of the lists = A[7], B[10]: 10 = A[8], B[11]: 11 = A[9], B[12]: 12 = A[10], B[13]: 13 = A[11], B[14]: 14 = A[12], B[15]: 15 = A[13], B[16]: 16 = A[14], B[17]: 17 = A[15], B[18]: 18 = A[16], B[19]: 19 = A[17], B[20]: 20 stack traceback: test/some_lists_comparisons.lua:98: in function 'TestListCompare.test5a' 8) TestListCompare.test5b test/some_lists_comparisons.lua:103: expected: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} actual: {1, 2, 3, 4, 6, 5, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} List difference analysis: * list sizes differ: list A (actual) has 17 items, list B (expected) has 20 items * lists A and B start differing at index 5 * lists A and B are equal again from index 7 for A, 10 for B * Common parts: = A[1], B[1]: 1 = A[2], B[2]: 2 = A[3], B[3]: 3 = A[4], B[4]: 4 * Differing parts: - A[5]: 6 + B[5]: 5 - A[6]: 5 + B[6]: 6 * Present only in one list: + B[7]: 7 + B[8]: 8 + B[9]: 9 * Common parts at the end of the lists = A[7], B[10]: 10 = A[8], B[11]: 11 = A[9], B[12]: 12 = A[10], B[13]: 13 = A[11], B[14]: 14 = A[12], B[15]: 15 = A[13], B[16]: 16 = A[14], B[17]: 17 = A[15], B[18]: 18 = A[16], B[19]: 19 = A[17], B[20]: 20 stack traceback: test/some_lists_comparisons.lua:103: in function 'TestListCompare.test5b' 9) TestListCompare.test5c test/some_lists_comparisons.lua:109: expected:
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} actual:
{1, 2, 3, 4, 6, 5, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} List difference analysis: * list sizes differ: list
A (actual) has 17 items, list
B (expected) has 20 items * lists A and B start differing at index 5 * lists A and B are equal again from index 7 for A, 10 for B * Common parts: = A[1], B[1]: 1 = A[2], B[2]: 2 = A[3], B[3]: 3 = A[4], B[4]: 4 * Differing parts: - A[5]: 6 + B[5]: 5 - A[6]: 5 + B[6]: 6 * Present only in one list: + B[7]: 7 + B[8]: 8 + B[9]: 9 * Common parts at the end of the lists = A[7], B[10]: 10 = A[8], B[11]: 11 = A[9], B[12]: 12 = A[10], B[13]: 13 = A[11], B[14]: 14 = A[12], B[15]: 15 = A[13], B[16]: 16 = A[14], B[17]: 17 = A[15], B[18]: 18 = A[16], B[19]: 19 = A[17], B[20]: 20 stack traceback: test/some_lists_comparisons.lua:109: in function 'TestListCompare.test5c' 10) TestListCompare.test6 test/some_lists_comparisons.lua:117: expected: { "aaa", "bbb", "ccc", function: 00E70160, 1.1, 2.1, 8=true, 9=false, 10=thread: 00E35480, 11=thread: 00E35480, 12=thread: 00E35480 } actual: { "aaa", "bbb", "ccc", function: 00E70160, 1.1, 2.1, 8=false, 9=false, 10=thread: 00E35480, 11=thread: 00E35480, 12=thread: 00E35480 } List difference analysis: * lists A (actual) and B (expected) have the same size * lists A and B start differing at index 8 * lists A and B are equal again from index 9 * Common parts: = A[1], B[1]: "aaa" = A[2], B[2]: "bbb" = A[3], B[3]: "ccc" = A[4], B[4]: function: 00E70160 = A[5], B[5]: 1.1 = A[6], B[6]: 2.1 = A[7], B[7]: nil * Differing parts: - A[8]: false + B[8]: true * Common parts at the end of the lists = A[9], B[9]: false = A[10], B[10]: thread: 00E35480 = A[11], B[11]: thread: 00E35480 = A[12], B[12]: thread: 00E35480 stack traceback: test/some_lists_comparisons.lua:117: in function 'TestListCompare.test6' 11) TestListCompare.test7 test/some_lists_comparisons.lua:123: expected: {{1, 2, 3}, {1, 2}, {{1}, {2}}, {"aa", "cc"}, 1, 2, 1.33, #Inf, {a=1}, {}} actual: {{1, 2, 3}, {1, 2}, {{2}, {2}}, {"aa", "bb"}, 1, 2, 1.33, #Inf, {a=1}, {}} List difference analysis: * lists A (actual) and B (expected) have the same size * lists A and B start differing at index 3 * lists A and B are equal again from index 5 * Common parts: = A[1], B[1]: {1, 2, 3} = A[2], B[2]: {1, 2} * Differing parts: - A[3]: {{2}, {2}} + B[3]: {{1}, {2}} - A[4]: {"aa", "bb"} + B[4]: {"aa", "cc"} * Common parts at the end of the lists = A[5], B[5]: 1 = A[6], B[6]: 2 = A[7], B[7]: 1.33 = A[8], B[8]: #Inf = A[9], B[9]: {a=1} = A[10], B[10]: {} stack traceback: test/some_lists_comparisons.lua:123: in function 'TestListCompare.test7' Ran 11 tests in 0.005 seconds, 0 successes, 11 failures luaunit-LUAUNIT_V3_4/test/ref/testWithXmlDefault.txt000066400000000000000000000010241401773523200225470ustar00rootroot00000000000000# XML output to test/ref/testWithXmlDefault.xml # Started on 04/28/19 21:05:11 # Starting class: TestFailuresWithXml # Starting test: TestFailuresWithXml.test_failure_with_cdata_xml # Failure: test/test_with_xml.lua:13: expected: "got it" # actual: "cdata does not like ]]>" # Starting test: TestFailuresWithXml.test_failure_with_simple_xml # Failure: test/test_with_xml.lua:9: expected: "got it" # actual: 'ti"ti' # Starting test: TestThatLastsALongTime # Ran 3 tests in 1.101 seconds, 1 success, 2 failures luaunit-LUAUNIT_V3_4/test/ref/testWithXmlDefault.xml000066400000000000000000000025651401773523200225430ustar00rootroot00000000000000 luaunit-LUAUNIT_V3_4/test/ref/testWithXmlQuiet.txt000066400000000000000000000010221401773523200222500ustar00rootroot00000000000000# XML output to test/ref/testWithXmlQuiet.xml # Started on 04/28/19 21:05:13 # Starting class: TestFailuresWithXml # Starting test: TestFailuresWithXml.test_failure_with_cdata_xml # Failure: test/test_with_xml.lua:13: expected: "got it" # actual: "cdata does not like ]]>" # Starting test: TestFailuresWithXml.test_failure_with_simple_xml # Failure: test/test_with_xml.lua:9: expected: "got it" # actual: 'ti"ti' # Starting test: TestThatLastsALongTime # Ran 3 tests in 1.105 seconds, 1 success, 2 failures luaunit-LUAUNIT_V3_4/test/ref/testWithXmlQuiet.xml000066400000000000000000000025651401773523200222460ustar00rootroot00000000000000 luaunit-LUAUNIT_V3_4/test/ref/testWithXmlVerbose.txt000066400000000000000000000010241401773523200225700ustar00rootroot00000000000000# XML output to test/ref/testWithXmlVerbose.xml # Started on 04/28/19 21:05:12 # Starting class: TestFailuresWithXml # Starting test: TestFailuresWithXml.test_failure_with_cdata_xml # Failure: test/test_with_xml.lua:13: expected: "got it" # actual: "cdata does not like ]]>" # Starting test: TestFailuresWithXml.test_failure_with_simple_xml # Failure: test/test_with_xml.lua:9: expected: "got it" # actual: 'ti"ti' # Starting test: TestThatLastsALongTime # Ran 3 tests in 1.101 seconds, 1 success, 2 failures luaunit-LUAUNIT_V3_4/test/ref/testWithXmlVerbose.xml000066400000000000000000000025651401773523200225640ustar00rootroot00000000000000 luaunit-LUAUNIT_V3_4/test/some_lists_comparisons.lua000066400000000000000000000101771401773523200227430ustar00rootroot00000000000000 local lu = require('luaunit') local function range(start, stop) -- return list of { start ... stop } local i local ret = {} i=start while i <= stop do table.insert(ret, i) i = i + 1 end return ret end TestListCompare = {} function TestListCompare:test1() local A = { 121221, 122211, 121221, 122211, 121221, 122212, 121212, 122112, 122121, 121212, 122121 } local B = { 121221, 122211, 121221, 122211, 121221, 122212, 121212, 122112, 121221, 121212, 122121 } lu.assertEquals( A, B ) end function TestListCompare:test1b() local A = { 121221, 122211, 121221, 122112, 121212, 121122, 121212, 122122, 121212, 122112, 122112 } local B = { 121221, 122211, 121221, 122112, 121212, 121122, 121212, 122122, 121212, 122112, 121212 } lu.assertEquals( A, B ) end function TestListCompare:test1c() local A = { 122112, 122121, 111212, 122121, 122121, 121212, 121121, 121212, 121221, 122212, 112121 } local B = { 121212, 122121, 111212, 122121, 122121, 121212, 121121, 121212, 121221, 122212, 112121 } lu.assertEquals( A, B ) end -- long list of numbers, same size, swapped values function TestListCompare:test2() local x=7 local A, B = range(1,20), range(1,20) B[x], B[x+1] = B[x+1], B[x] lu.assertEquals( A, B ) end -- long list of numbers, one hole function TestListCompare:test3() local x=7 local A, B = range(1,20), {} local i=1 while i <= #A do if i ~= x then table.insert( B, A[i] ) end i = i + 1 end lu.assertEquals( A, B ) end -- long list of numbers, one bigger hole function TestListCompare:test4() local x=7 local x2=8 local x3=9 local A, B = range(1,20), {} local i=1 while i <= #A do if i ~= x and i ~= x2 and i ~= x3 then table.insert( B, A[i] ) end i = i + 1 end lu.assertEquals( A, B ) end -- long list, difference + big hole function TestListCompare:sub_test5() local x=7 local x2=8 local x3=9 local A, B = range(1,20), {} local i=1 while i <= #A do if i ~= x and i ~= x2 and i ~= x3 then table.insert( B, A[i] ) end i = i + 1 end x = 5 B[x], B[x+1] = B[x+1], B[x] return A, B end function TestListCompare:test5a() local A, B = self:sub_test5() lu.ORDER_ACTUAL_EXPECTED = false lu.assertEquals( A, B ) end function TestListCompare:test5b() local A, B = self:sub_test5() lu.assertEquals( B, A ) end function TestListCompare:test5c() local A, B = self :sub_test5() lu.PRINT_TABLE_REF_IN_ERROR_MSG = true lu.assertEquals( B, A ) end function TestListCompare:test6() local f1 = function () return nil end local t1 = coroutine.create( function(v) local y=v+1 end ) local A = { 'aaa', 'bbb', 'ccc', f1, 1.1, 2.1, nil, true, false, t1, t1, t1 } local B = { 'aaa', 'bbb', 'ccc', f1, 1.1, 2.1, nil, false, false, t1, t1, t1 } lu.assertEquals( B, A ) end function TestListCompare:test7() local A = { {1,2,3}, {1,2}, { {1}, {2} }, { 'aa', 'cc'}, 1, 2, 1.33, 1/0, { a=1 }, {} } local B = { {1,2,3}, {1,2}, { {2}, {2} }, { 'aa', 'bb'}, 1, 2, 1.33, 1/0, { a=1 }, {} } lu.assertEquals( B, A ) end function TestListCompare:tearDown() -- cancel effect of test5a lu.ORDER_ACTUAL_EXPECTED = true -- cancel effect of test5c lu.PRINT_TABLE_REF_IN_ERROR_MSG = false end -- end TestListCompare --[[ TestDictCompare = {} function XTestDictCompare:test1() lu.assertEquals( {one=1,two=2, three=3}, {one=1,two=1, three=3} ) end function XTestDictCompare:test2() lu.assertEquals( {one=1,two=2, three=3, four=4, five=5}, {one=1,two=1, three=3, four=4, five=5} ) end -- end TestDictCompare ]] os.exit( lu.run() )luaunit-LUAUNIT_V3_4/test/test_luaunit.lua000066400000000000000000006120171401773523200206660ustar00rootroot00000000000000--[[ Author: Philippe Fremy License: BSD License, see LICENSE.txt ]]-- local TABLE_REF_PAT='table: 0?x?[%x]+' local TABLE_IDX_PAT='table %d%d' local TABLE_IDX_REF_PAT='table %d%d%-0?x?[%x]+' -- Return a function that appends its arguments to the `callInfo` table local function callRecorder( callInfo ) return function( ... ) for _, v in pairs({...}) do table.insert( callInfo, v ) end end end -- This is a bit tricky since the test uses the features that it tests. local function range(start, stop) -- return list of { start ... stop } local i local ret = {} i=start while i <= stop do table.insert(ret, i) i = i + 1 end return ret end local lu = require('luaunit') local Mock = { __class__ = 'Mock' } function Mock.new(runner) local t = lu.genericOutput.new(runner) t.calls = {} local t_MT = { __index = function( tab, key ) local callInfo = { key } table.insert( tab.calls, callInfo ) return callRecorder( callInfo ) end } return setmetatable( t, t_MT ) end TestMock = {} function TestMock:testMock() local m = Mock.new() m.titi( 42 ) m.toto( 33, "abc", { 21} ) lu.assertEquals( m.calls[1][1], 'titi' ) lu.assertEquals( m.calls[1][2], 42 ) lu.assertEquals( #m.calls[1], 2 ) lu.assertEquals( m.calls[2][1], 'toto' ) lu.assertEquals( m.calls[2][2], 33 ) lu.assertEquals( m.calls[2][3], 'abc' ) lu.assertEquals( m.calls[2][4][1], 21 ) lu.assertEquals( #m.calls[2], 4 ) lu.assertEquals( #m.calls, 2 ) end ------------------------------------------------------------------ -- -- Utility Tests -- ------------------------------------------------------------------ TestLuaUnitUtilities = { __class__ = 'TestLuaUnitUtilities' } function TestLuaUnitUtilities:setUp() self.old_PRINT_TABLE_REF_IN_ERROR_MSG = lu.PRINT_TABLE_REF_IN_ERROR_MSG end function TestLuaUnitUtilities:tearDown() lu.PRINT_TABLE_REF_IN_ERROR_MSG = self.old_PRINT_TABLE_REF_IN_ERROR_MSG end function TestLuaUnitUtilities:test_genSortedIndex() lu.assertEquals( lu.private.__genSortedIndex( { 2, 5, 7} ), {1,2,3} ) lu.assertEquals( lu.private.__genSortedIndex( { a='1', h='2', c='3' } ), {'a', 'c', 'h'} ) lu.assertEquals( lu.private.__genSortedIndex( { 1, 'z', a='1', h='2', c='3' } ), { 1, 2, 'a', 'c', 'h' } ) lu.assertEquals( lu.private.__genSortedIndex( { b=4, a=3, true, foo="bar", nil, bar=false, 42, c=5 } ), { 1, 3, 'a', 'b', 'bar', 'c', 'foo' } ) end function TestLuaUnitUtilities:test_sortedNextWorks() local t1 = {} local _ t1['aaa'] = 'abc' t1['ccc'] = 'def' t1['bbb'] = 'cba' -- mimic semantics of "generic for" loop local sortedNext, state = lu.private.sortedPairs(t1) local k, v = sortedNext( state, nil ) lu.assertEquals( k, 'aaa' ) lu.assertEquals( v, 'abc' ) k, v = sortedNext( state, k ) lu.assertEquals( k, 'bbb' ) lu.assertEquals( v, 'cba' ) k, v = sortedNext( state, k ) lu.assertEquals( k, 'ccc' ) lu.assertEquals( v, 'def' ) k, v = sortedNext( state, k ) lu.assertEquals( k, nil ) lu.assertEquals( v, nil ) -- check if starting the iteration a second time works k, v = sortedNext( state, nil ) lu.assertEquals( k, 'aaa' ) lu.assertEquals( v, 'abc' ) -- run a generic for loop (internally using a separate state) local tested = {} for _, v in lu.private.sortedPairs(t1) do table.insert(tested, v) end lu.assertEquals( tested, {'abc', 'cba', 'def'} ) -- test bisection algorithm by searching for non-existing key values k, v = sortedNext( state, '' ) -- '' would come before any of the keys lu.assertNil( k ) lu.assertNil( v ) k, v = sortedNext( state, 'xyz' ) -- 'xyz' would be after any other key lu.assertNil( k ) lu.assertNil( v ) -- finally let's see if we successfully find an "out of sequence" key k, v = sortedNext( state, 'bbb' ) lu.assertEquals( k, 'ccc' ) lu.assertEquals( v, 'def' ) end function TestLuaUnitUtilities:test_sortedNextWorksOnTwoTables() local t1 = { aaa = 'abc', ccc = 'def' } local t2 = { ['3'] = '33', ['1'] = '11' } local sortedNext, state1, state2, _ _, state1 = lu.private.sortedPairs(t1) sortedNext, state2 = lu.private.sortedPairs(t2) local k, v = sortedNext( state1, nil ) lu.assertEquals( k, 'aaa' ) lu.assertEquals( v, 'abc' ) k, v = sortedNext( state2, nil ) lu.assertEquals( k, '1' ) lu.assertEquals( v, '11' ) k, v = sortedNext( state1, 'aaa' ) lu.assertEquals( k, 'ccc' ) lu.assertEquals( v, 'def' ) k, v = sortedNext( state2, '1' ) lu.assertEquals( k, '3' ) lu.assertEquals( v, '33' ) end function TestLuaUnitUtilities:test_randomizeTable() local t, tref, n = {}, {}, 20 for i = 1, n do t[i], tref[i] = i, i end lu.assertEquals( #t, n ) lu.private.randomizeTable( t ) lu.assertEquals( #t, n ) lu.assertNotEquals( t, tref) table.sort(t) lu.assertEquals( t, tref ) end function TestLuaUnitUtilities:test_strSplitOneCharDelim() local t = lu.private.strsplit( '\n', '122333' ) lu.assertEquals( t[1], '122333') lu.assertEquals( #t, 1 ) local t = lu.private.strsplit( '\n', '1\n22\n333\n' ) lu.assertEquals( t[1], '1') lu.assertEquals( t[2], '22') lu.assertEquals( t[3], '333') lu.assertEquals( t[4], '') lu.assertEquals( #t, 4 ) -- test invalid (empty) delimiter lu.assertErrorMsgContains('delimiter is nil or empty string!', lu.private.strsplit, '', '1\n22\n333\n') lu.assertErrorMsgContains('delimiter is nil or empty string!', lu.private.strsplit, nil, '1\n22\n333\n') end function TestLuaUnitUtilities:test_strSplit3CharDelim() local t = lu.private.strsplit( '2\n3', '1\n22\n332\n3' ) lu.assertEquals( t[1], '1\n2') lu.assertEquals( t[2], '3') lu.assertEquals( t[3], '') lu.assertEquals( #t, 3 ) end function TestLuaUnitUtilities:test_strSplitWithNil() lu.assertEquals( nil, lu.private.strsplit('-', nil) ) end function TestLuaUnitUtilities:test_protectedCall() local function boom() error("Something went wrong.") end local err = lu.LuaUnit:protectedCall(nil, boom, "kaboom") -- check that err received the expected fields lu.assertEquals(err.status, "ERROR") lu.assertStrContains(err.msg, "Something went wrong.") lu.assertStrMatches(err.trace, "^stack traceback:.*in %a+ 'kaboom'.*") end function TestLuaUnitUtilities:test_prefixString() lu.assertEquals( lu.private.prefixString( '12 ', 'ab\ncd\nde'), '12 ab\n12 cd\n12 de' ) end function TestLuaUnitUtilities:test_is_table_equals() -- Make sure that _is_table_equals() doesn't fall for these traps -- (See https://github.com/bluebird75/luaunit/issues/48) local A, B, C = {}, {}, {} A.self = A B.self = B lu.assertEquals(A, B) A, B = {}, {} A.circular = C B.circular = A C.circular = B lu.assertEquals(A, B) lu.assertEquals(B, C) lu.assertEquals(C, A) A = {} A[{}] = A lu.assertEquals( A, A ) A = {} A[A] = 1 lu.assertEquals( A, A ) end function TestLuaUnitUtilities:test_suitableForMismatchFormatting() lu.assertFalse( lu.private.tryMismatchFormatting( {1,2}, {2,1} ) ) lu.assertFalse( lu.private.tryMismatchFormatting( nil, { 1,2,3} ) ) lu.assertFalse( lu.private.tryMismatchFormatting( {1,2,3}, {} ) ) lu.assertFalse( lu.private.tryMismatchFormatting( "123", "123" ) ) lu.assertFalse( lu.private.tryMismatchFormatting( "123", "123" ) ) lu.assertFalse( lu.private.tryMismatchFormatting( {'a','b','c'}, {'c', 'b', 'a'} )) lu.assertFalse( lu.private.tryMismatchFormatting( {1,2,3, toto='titi'}, {1,2,3, toto='tata', tutu="bloup" } ) ) lu.assertFalse( lu.private.tryMismatchFormatting( {1,2,3, [5]=1000}, {1,2,3} ) ) local i=0 local l1, l2={}, {} while i <= lu.LIST_DIFF_ANALYSIS_THRESHOLD+1 do i = i + 1 table.insert( l1, i ) table.insert( l2, i+1 ) end lu.assertTrue( lu.private.tryMismatchFormatting( l1, l2 ) ) end function TestLuaUnitUtilities:test_diffAnalysisThreshold() local threshold = lu.LIST_DIFF_ANALYSIS_THRESHOLD lu.assertFalse( lu.private.tryMismatchFormatting( range(1,threshold-1), range(1,threshold-2), lu.DEFAULT_DEEP_ANALYSIS ) ) lu.assertTrue( lu.private.tryMismatchFormatting( range(1,threshold), range(1,threshold), lu.DEFAULT_DEEP_ANALYSIS ) ) lu.assertFalse( lu.private.tryMismatchFormatting( range(1,threshold-1), range(1,threshold-2), lu.DISABLE_DEEP_ANALYSIS ) ) lu.assertFalse( lu.private.tryMismatchFormatting( range(1,threshold), range(1,threshold), lu.DISABLE_DEEP_ANALYSIS ) ) lu.assertTrue( lu.private.tryMismatchFormatting( range(1,threshold-1), range(1,threshold-2), lu.FORCE_DEEP_ANALYSIS ) ) lu.assertTrue( lu.private.tryMismatchFormatting( range(1,threshold), range(1,threshold), lu.FORCE_DEEP_ANALYSIS ) ) end function TestLuaUnitUtilities:test_table_ref_default() local unknown_table_idx = 'table 00%-unknown ref' local ts = function(t) return t[1]..t[2] end local t1 = {'1','2'} lu.assertStrMatches( tostring(t1), TABLE_REF_PAT ) lu.assertStrMatches( lu.private.table_ref(t1), TABLE_IDX_PAT ) local mt = { __tostring = ts } setmetatable( t1, mt ) lu.assertStrMatches( tostring(t1), '12' ) lu.assertStrMatches( lu.private.table_ref(t1), TABLE_IDX_PAT ) -- how does it deal with protected metatable ? -- metatable, obviously protected local t1 = setmetatable( { 1, 2 }, { __metatable="private" } ) lu.assertStrMatches( lu.private.table_ref(t1), TABLE_IDX_PAT ) -- metatable, protected but still returns a table so more difficult to catch local t1 = setmetatable( { 1, 2 }, { __metatable={ "private" } } ) lu.assertStrMatches( lu.private.table_ref(t1), TABLE_IDX_PAT ) -- protected metatable + __tostring, no way to get references local t1 = setmetatable( { 1, 2 }, { __metatable="private", __tostring=ts } ) lu.assertStrMatches( lu.private.table_ref(t1), unknown_table_idx ) local t1 = setmetatable( { 1, 2 }, { __metatable={ "private" }, __tostring=ts } ) lu.assertStrMatches( lu.private.table_ref(t1), unknown_table_idx ) end function TestLuaUnitUtilities:test_table_ref_print_ref() local unknown_table_ref = 'table 00%-unknown ref' lu.PRINT_TABLE_REF_IN_ERROR_MSG = true local ts = function(t) return t[1]..t[2] end local t1 = {'1','2'} lu.assertStrMatches( tostring(t1), TABLE_REF_PAT ) lu.assertStrMatches( lu.private.table_ref(t1), 'table %d%d%-0?x?[%x]+' ) local mt = { __tostring = ts } setmetatable( t1, mt ) lu.assertStrMatches( tostring(t1), '12' ) lu.assertStrMatches( lu.private.table_ref(t1), 'table %d%d%-0?x?[%x]+' ) -- how does it deal with protected metatable ? -- metatable, obviously protected local t1 = setmetatable( { 1, 2 }, { __metatable="private" } ) lu.assertStrMatches( lu.private.table_ref(t1), 'table %d%d%-0?x?[%x]+' ) -- metatable, protected but still returns a table so more difficult to catch local t1 = setmetatable( { 1, 2 }, { __metatable={ "private" } } ) lu.assertStrMatches( lu.private.table_ref(t1), 'table %d%d%-0?x?[%x]+' ) -- protected metatable + __tostring, no way to get references local t1 = setmetatable( { 1, 2 }, { __metatable="private", __tostring=ts } ) lu.assertStrMatches( lu.private.table_ref(t1), unknown_table_ref ) local t1 = setmetatable( { 1, 2 }, { __metatable={ "private" }, __tostring=ts } ) lu.assertStrMatches( lu.private.table_ref(t1), unknown_table_ref ) end function TestLuaUnitUtilities:test_prettystr_numbers() lu.assertEquals( lu.prettystr( 1 ), "1" ) if lu._LUAVERSION < 'Lua 5.4' or lu._LUAVERSION:sub(1,6) == "LuaJIT" then lu.assertEquals( lu.prettystr( 1 ), "1" ) lu.assertEquals( lu.prettystr( 1.0 ), "1" ) else lu.assertEquals( lu.prettystr( 1 ), "1" ) lu.assertEquals( lu.prettystr( 1.0 ), "1.0" ) end lu.assertEquals( lu.prettystr( 1.1 ), "1.1" ) lu.assertEquals( lu.prettystr( 1/0 ), "#Inf" ) lu.assertEquals( lu.prettystr( -1/0 ), "-#Inf" ) lu.assertEquals( lu.prettystr( 0/0 ), "#NaN" ) end function TestLuaUnitUtilities:test_prettystr_strings() lu.assertEquals( lu.prettystr( 'abc' ), '"abc"' ) lu.assertEquals( lu.prettystr( 'ab\ncd' ), '"ab\ncd"' ) lu.assertEquals( lu.prettystr( 'ab"cd' ), "'ab\"cd'" ) lu.assertEquals( lu.prettystr( "ab'cd" ), '"ab\'cd"' ) end function TestLuaUnitUtilities:test_prettystr_tables1() lu.assertEquals( lu.prettystr( {1,2,3} ), "{1, 2, 3}" ) lu.assertEquals( lu.prettystr( {a=1,bb=2,ab=3} ), '{a=1, ab=3, bb=2}' ) lu.assertEquals( lu.prettystr( { [{}] = 1 }), '{{}=1}' ) lu.assertEquals( lu.prettystr( { 1, [{}] = 1, 2 }), '{1, 2, {}=1}' ) lu.assertEquals( lu.prettystr( { 1, [{one=1}] = 1, 2, "test", false }), '{1, 2, "test", false, {one=1}=1}' ) end function TestLuaUnitUtilities:test_prettystr_tables2() -- test the (private) key string formatting within _table_tostring() lu.assertEquals( lu.prettystr( {a = 1} ), '{a=1}' ) lu.assertEquals( lu.prettystr( {a0 = 2} ), '{a0=2}' ) lu.assertEquals( lu.prettystr( {['a0!'] = 3} ), '{"a0!"=3}' ) lu.assertEquals( lu.prettystr( {["foo\nbar"] = 1}), [[{"foo bar"=1}]] ) lu.assertEquals( lu.prettystr( {["foo'bar"] = 2}), [[{"foo'bar"=2}]] ) lu.assertEquals( lu.prettystr( {['foo"bar'] = 3}), [[{'foo"bar'=3}]] ) end function TestLuaUnitUtilities:test_prettystr_tables3() -- test with a table containing a metatable for __tostring local t1 = {'1','2'} lu.assertStrMatches( tostring(t1), 'table: 0?x?[%x]+' ) lu.assertEquals( lu.prettystr(t1), '{"1", "2"}' ) -- add metatable local function ts(t) return string.format( 'Point<%s,%s>', t[1], t[2] ) end setmetatable( t1, { __tostring = ts } ) lu.assertEquals( tostring(t1), 'Point<1,2>' ) lu.assertEquals( lu.prettystr(t1), 'Point<1,2>' ) local function ts2(t) return string.format( 'Point:\n x=%s\n y=%s', t[1], t[2] ) end local t2 = {'1','2'} setmetatable( t2, { __tostring = ts2 } ) lu.assertEquals( tostring(t2), [[Point: x=1 y=2]] ) lu.assertEquals( lu.prettystr(t2), [[Point: x=1 y=2]] ) -- nested table local t3 = {'3', t1} lu.assertEquals( lu.prettystr(t3), [[{"3", Point<1,2>}]] ) local t4 = {'3', t2} lu.assertEquals( lu.prettystr(t4), [[{"3", Point: x=1 y=2}]] ) local t5 = {1,2,{3,4},string.rep('W', lu.LINE_LENGTH), t2, 33} lu.assertEquals( lu.prettystr(t5), [[{ 1, 2, {3, 4}, "]]..string.rep('W', lu.LINE_LENGTH)..[[", Point: x=1 y=2, 33 }]] ) end function TestLuaUnitUtilities:test_prettystr_adv_tables() local t1 = {1,2,3,4,5,6} lu.assertEquals(lu.prettystr(t1), "{1, 2, 3, 4, 5, 6}" ) local t2 = {'aaaaaaaaaaaaaaaaa', 'bbbbbbbbbbbbbbbbbbbb', 'ccccccccccccccccc', 'ddddddddddddd', 'eeeeeeeeeeeeeeeeee', 'ffffffffffffffff', 'ggggggggggg', 'hhhhhhhhhhhhhh'} lu.assertEquals(lu.prettystr(t2), table.concat( { '{', ' "aaaaaaaaaaaaaaaaa",', ' "bbbbbbbbbbbbbbbbbbbb",', ' "ccccccccccccccccc",', ' "ddddddddddddd",', ' "eeeeeeeeeeeeeeeeee",', ' "ffffffffffffffff",', ' "ggggggggggg",', ' "hhhhhhhhhhhhhh"', '}', } , '\n' ) ) lu.assertTrue( lu.private.hasNewLine( lu.prettystr(t2)) ) local t2bis = { 1,2,3,'12345678901234567890123456789012345678901234567890123456789012345678901234567890', 4,5,6 } lu.assertEquals(lu.prettystr(t2bis), [[{ 1, 2, 3, "12345678901234567890123456789012345678901234567890123456789012345678901234567890", 4, 5, 6 }]] ) local t3 = { l1a = { l2a = { l3a='012345678901234567890123456789012345678901234567890123456789' }, l2b='bbb' }, l1b = 4} lu.assertEquals(lu.prettystr(t3), [[{ l1a={ l2a={l3a="012345678901234567890123456789012345678901234567890123456789"}, l2b="bbb" }, l1b=4 }]] ) local t4 = { a=1, b=2, c=3 } lu.assertEquals(lu.prettystr(t4), '{a=1, b=2, c=3}' ) local t5 = { t1, t2, t3 } lu.assertEquals( lu.prettystr(t5), [[{ {1, 2, 3, 4, 5, 6}, { "aaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbb", "ccccccccccccccccc", "ddddddddddddd", "eeeeeeeeeeeeeeeeee", "ffffffffffffffff", "ggggggggggg", "hhhhhhhhhhhhhh" }, { l1a={ l2a={l3a="012345678901234567890123456789012345678901234567890123456789"}, l2b="bbb" }, l1b=4 } }]] ) local t6 = { t1=t1, t2=t2, t3=t3, t4=t4 } lu.assertEquals(lu.prettystr(t6),[[{ t1={1, 2, 3, 4, 5, 6}, t2={ "aaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbb", "ccccccccccccccccc", "ddddddddddddd", "eeeeeeeeeeeeeeeeee", "ffffffffffffffff", "ggggggggggg", "hhhhhhhhhhhhhh" }, t3={ l1a={ l2a={l3a="012345678901234567890123456789012345678901234567890123456789"}, l2b="bbb" }, l1b=4 }, t4={a=1, b=2, c=3} }]]) end function TestLuaUnitUtilities:test_prettystrTableCycles() local t = {} t.__index = t lu.assertStrMatches(lu.prettystr(t), "(<"..TABLE_IDX_PAT..">) {__index=%1}") local t1 = {} local t2 = {} t1.t2 = t2 t2.t1 = t1 local t3 = { t1 = t1, t2 = t2 } lu.assertStrMatches(lu.prettystr(t1), "(<"..TABLE_IDX_PAT..">) {t2=(<"..TABLE_IDX_PAT..">) {t1=%1}}") lu.assertStrMatches(lu.prettystr(t3), "(<"..TABLE_IDX_PAT..">) {t1=(<"..TABLE_IDX_PAT..">) {t2=(<"..TABLE_IDX_PAT..">) {t1=%2}}, t2=%3}") local t4 = {1,2} local t5 = {3,4,t4} t4[3] = t5 lu.assertStrMatches(lu.prettystr(t5), "(<"..TABLE_IDX_PAT..">) {3, 4, (<"..TABLE_IDX_PAT..">) {1, 2, %1}}") local t6 = {} t6[t6] = 1 lu.assertStrMatches(lu.prettystr(t6), "(<"..TABLE_IDX_PAT..">) {%1=1}" ) local t7, t8 = {"t7"}, {"t8"} t7[t8] = 1 t8[t7] = 2 lu.assertStrMatches(lu.prettystr(t7), '(<'..TABLE_IDX_PAT..'>) {"t7", (<'..TABLE_IDX_PAT..'>) {"t8", %1=2}=1}') local t9 = {"t9", {}} t9[{t9}] = 1 lu.assertStrMatches(lu.prettystr(t9, true), '(<'..TABLE_IDX_PAT..'>) {\n?%s*"t9",\n?%s*(<'..TABLE_IDX_PAT..'>) {},\n?%s*(<'..TABLE_IDX_PAT..'>) {%1}=1\n?}') end function TestLuaUnitUtilities:test_prettystrPairs() local foo, bar, str1, str2 = nil, nil -- test all combinations of: foo = nil, "foo", "fo\no" (embedded -- newline); and bar = nil, "bar", "bar\n" (trailing newline) str1, str2 = lu.private.prettystrPairs(foo, bar) lu.assertEquals(str1, "nil") lu.assertEquals(str2, "nil") str1, str2 = lu.private.prettystrPairs(foo, bar, "_A", "_B") lu.assertEquals(str1, "nil_B") lu.assertEquals(str2, "nil") bar = "bar" str1, str2 = lu.private.prettystrPairs(foo, bar) lu.assertEquals(str1, "nil") lu.assertEquals(str2, '"bar"') str1, str2 = lu.private.prettystrPairs(foo, bar, "_A", "_B") lu.assertEquals(str1, "nil_B") lu.assertEquals(str2, '"bar"') bar = "bar\n" str1, str2 = lu.private.prettystrPairs(foo, bar) lu.assertEquals(str1, "\nnil") lu.assertEquals(str2, '\n"bar\n"') str1, str2 = lu.private.prettystrPairs(foo, bar, "_A", "_B") lu.assertEquals(str1, "\nnil_A") lu.assertEquals(str2, '\n"bar\n"') foo = "foo" bar = nil str1, str2 = lu.private.prettystrPairs(foo, bar) lu.assertEquals(str1, '"foo"') lu.assertEquals(str2, "nil") str1, str2 = lu.private.prettystrPairs(foo, bar, "_A", "_B") lu.assertEquals(str1, '"foo"_B') lu.assertEquals(str2, "nil") bar = "bar" str1, str2 = lu.private.prettystrPairs(foo, bar) lu.assertEquals(str1, '"foo"') lu.assertEquals(str2, '"bar"') str1, str2 = lu.private.prettystrPairs(foo, bar, "_A", "_B") lu.assertEquals(str1, '"foo"_B') lu.assertEquals(str2, '"bar"') bar = "bar\n" str1, str2 = lu.private.prettystrPairs(foo, bar) lu.assertEquals(str1, '\n"foo"') lu.assertEquals(str2, '\n"bar\n"') str1, str2 = lu.private.prettystrPairs(foo, bar, "_A", "_B") lu.assertEquals(str1, '\n"foo"_A') lu.assertEquals(str2, '\n"bar\n"') foo = "fo\no" bar = nil str1, str2 = lu.private.prettystrPairs(foo, bar) lu.assertEquals(str1, '\n"fo\no"') lu.assertEquals(str2, "\nnil") str1, str2 = lu.private.prettystrPairs(foo, bar, "_A", "_B") lu.assertEquals(str1, '\n"fo\no"_A') lu.assertEquals(str2, "\nnil") bar = "bar" str1, str2 = lu.private.prettystrPairs(foo, bar) lu.assertEquals(str1, '\n"fo\no"') lu.assertEquals(str2, '\n"bar"') str1, str2 = lu.private.prettystrPairs(foo, bar, "_A", "_B") lu.assertEquals(str1, '\n"fo\no"_A') lu.assertEquals(str2, '\n"bar"') bar = "bar\n" str1, str2 = lu.private.prettystrPairs(foo, bar) lu.assertEquals(str1, '\n"fo\no"') lu.assertEquals(str2, '\n"bar\n"') str1, str2 = lu.private.prettystrPairs(foo, bar, "_A", "_B") lu.assertEquals(str1, '\n"fo\no"_A') lu.assertEquals(str2, '\n"bar\n"') end function TestLuaUnitUtilities:test_FailFmt() -- raise failure from within nested functions local function babar(level) lu.private.fail_fmt(level, 'toto', "hex=%X", 123) end local function bar(level) lu.private.fail_fmt(level, nil, "hex=%X", 123) end local function foo(level) bar(level) end local _, err = pcall(foo) -- default level 1 = error position in bar() local line1, prefix = err:match("test[\\/]test_luaunit%.lua:(%d+): (.*)hex=7B$") lu.assertEquals(prefix, lu.FAILURE_PREFIX) lu.assertNotNil(line1) _, err = pcall(foo, 2) -- level 2 = error position within foo() local line2 line2 , prefix = err:match("test[\\/]test_luaunit%.lua:(%d+): (.*)hex=7B$") lu.assertEquals(prefix, lu.FAILURE_PREFIX) lu.assertNotNil(line2) -- make sure that "line2" position is exactly 3 lines after "line1" lu.assertEquals(tonumber(line2), tonumber(line1) + 3) _, err = pcall(babar, 1) local _, prefix = err:match("test[\\/]test_luaunit%.lua:(%d+): (.*)hex=7B$") lu.assertEquals(prefix, lu.FAILURE_PREFIX .. 'toto\n') end function TestLuaUnitUtilities:test_IsFunction() -- previous LuaUnit.isFunction was superseded by LuaUnit.asFunction -- (which can also serve as a boolean expression) lu.assertNotNil( lu.LuaUnit.asFunction( function (v,y) end ) ) lu.assertNil( lu.LuaUnit.asFunction( nil ) ) lu.assertNil( lu.LuaUnit.asFunction( "not a function" ) ) end function TestLuaUnitUtilities:test_splitClassMethod() lu.assertEquals( lu.LuaUnit.splitClassMethod( 'toto' ), nil ) lu.assertEquals( {lu.LuaUnit.splitClassMethod( 'toto.titi' )}, {'toto', 'titi'} ) end function TestLuaUnitUtilities:test_isTestName() lu.assertEquals( lu.LuaUnit.isTestName( 'testToto' ), true ) lu.assertEquals( lu.LuaUnit.isTestName( 'TestToto' ), true ) lu.assertEquals( lu.LuaUnit.isTestName( 'TESTToto' ), true ) lu.assertEquals( lu.LuaUnit.isTestName( 'xTESTToto' ), false ) lu.assertEquals( lu.LuaUnit.isTestName( '' ), false ) end function TestLuaUnitUtilities:test_parseCmdLine() --test names lu.assertEquals( lu.LuaUnit.parseCmdLine(), {} ) lu.assertEquals( lu.LuaUnit.parseCmdLine( { 'someTest' } ), { testNames={'someTest'} } ) lu.assertEquals( lu.LuaUnit.parseCmdLine( { 'someTest', 'someOtherTest' } ), { testNames={'someTest', 'someOtherTest'} } ) -- verbosity lu.assertEquals( lu.LuaUnit.parseCmdLine( { '--verbose' } ), { verbosity=lu.VERBOSITY_VERBOSE } ) lu.assertEquals( lu.LuaUnit.parseCmdLine( { '-v' } ), { verbosity=lu.VERBOSITY_VERBOSE } ) lu.assertEquals( lu.LuaUnit.parseCmdLine( { '--quiet' } ), { verbosity=lu.VERBOSITY_QUIET } ) lu.assertEquals( lu.LuaUnit.parseCmdLine( { '-q' } ), { verbosity=lu.VERBOSITY_QUIET } ) lu.assertEquals( lu.LuaUnit.parseCmdLine( { '-v', '-q' } ), { verbosity=lu.VERBOSITY_QUIET } ) --output lu.assertEquals( lu.LuaUnit.parseCmdLine( { '--output', 'toto' } ), { output='toto'} ) lu.assertEquals( lu.LuaUnit.parseCmdLine( { '-o', 'toto' } ), { output='toto'} ) lu.assertErrorMsgContains( 'Missing argument after -o', lu.LuaUnit.parseCmdLine, { '-o', } ) --name lu.assertEquals( lu.LuaUnit.parseCmdLine( { '--name', 'toto' } ), { fname='toto'} ) lu.assertEquals( lu.LuaUnit.parseCmdLine( { '-n', 'toto' } ), { fname='toto'} ) lu.assertErrorMsgContains( 'Missing argument after -n', lu.LuaUnit.parseCmdLine, { '-n', } ) --patterns lu.assertEquals( lu.LuaUnit.parseCmdLine( { '--pattern', 'toto' } ), { pattern={'toto'} } ) lu.assertEquals( lu.LuaUnit.parseCmdLine( { '-p', 'toto' } ), { pattern={'toto'} } ) lu.assertEquals( lu.LuaUnit.parseCmdLine( { '-p', 'titi', '-p', 'toto' } ), { pattern={'titi', 'toto'} } ) lu.assertErrorMsgContains( 'Missing argument after -p', lu.LuaUnit.parseCmdLine, { '-p', } ) lu.assertEquals( lu.LuaUnit.parseCmdLine( { '--exclude', 'toto' } ), { pattern={'!toto'} } ) lu.assertEquals( lu.LuaUnit.parseCmdLine( { '-x', 'toto' } ), { pattern={'!toto'} } ) lu.assertEquals( lu.LuaUnit.parseCmdLine( { '-x', 'titi', '-x', 'toto' } ), { pattern={'!titi', '!toto'} } ) lu.assertEquals( lu.LuaUnit.parseCmdLine( { '-x', 'titi', '-p', 'foo', '-x', 'toto' } ), { pattern={'!titi', 'foo', '!toto'} } ) lu.assertErrorMsgContains( 'Missing argument after -x', lu.LuaUnit.parseCmdLine, { '-x', } ) -- repeat lu.assertEquals( lu.LuaUnit.parseCmdLine( { '--repeat', '123' } ), { exeRepeat=123 } ) lu.assertEquals( lu.LuaUnit.parseCmdLine( { '-r', '123' } ), { exeRepeat=123 } ) lu.assertErrorMsgContains( 'Malformed -r argument', lu.LuaUnit.parseCmdLine, { '-r', 'bad' } ) lu.assertErrorMsgContains( 'Missing argument after -r', lu.LuaUnit.parseCmdLine, { '-r', } ) -- shuffle lu.assertEquals( lu.LuaUnit.parseCmdLine( { '--shuffle' } ), { shuffle=true } ) lu.assertEquals( lu.LuaUnit.parseCmdLine( { '-s' } ), { shuffle=true } ) --megamix lu.assertEquals( lu.LuaUnit.parseCmdLine( { '-p', 'toto', 'titi', '-v', 'tata', '-o', 'tintin', '-p', 'tutu', 'prout', '-n', 'toto.xml' } ), { pattern={'toto', 'tutu'}, verbosity=lu.VERBOSITY_VERBOSE, output='tintin', testNames={'titi', 'tata', 'prout'}, fname='toto.xml' } ) lu.assertErrorMsgContains( 'option: -$', lu.LuaUnit.parseCmdLine, { '-$', } ) end function TestLuaUnitUtilities:test_patternFilter() lu.assertEquals( lu.private.patternFilter( nil, 'toto'), true ) lu.assertEquals( lu.private.patternFilter( {}, 'toto'), true ) -- positive pattern lu.assertEquals( lu.private.patternFilter( {'toto'}, 'toto'), true ) lu.assertEquals( lu.private.patternFilter( {'toto'}, 'yyytotoxxx'), true ) lu.assertEquals( lu.private.patternFilter( {'titi', 'toto'}, 'yyytotoxxx'), true ) lu.assertEquals( lu.private.patternFilter( {'titi', 'toto'}, 'tutu'), false ) lu.assertEquals( lu.private.patternFilter( {'titi', 'to..'}, 'yyytoxxx'), true ) -- negative pattern lu.assertEquals( lu.private.patternFilter( {'!toto'}, 'toto'), false ) lu.assertEquals( lu.private.patternFilter( {'!t.t.'}, 'titi'), false ) lu.assertEquals( lu.private.patternFilter( {'!toto'}, 'titi'), true ) lu.assertEquals( lu.private.patternFilter( {'!toto'}, 'yyytotoxxx'), false ) lu.assertEquals( lu.private.patternFilter( {'!titi', '!toto'}, 'yyytotoxxx'), false ) lu.assertEquals( lu.private.patternFilter( {'!titi', '!toto'}, 'tutu'), true ) lu.assertEquals( lu.private.patternFilter( {'!titi', '!to..'}, 'yyytoxxx'), false ) -- combine patterns lu.assertEquals( lu.private.patternFilter( { 'foo' }, 'foo'), true ) lu.assertEquals( lu.private.patternFilter( { 'foo', '!foo' }, 'foo'), false ) lu.assertEquals( lu.private.patternFilter( { 'foo', '!foo', 'foo' }, 'foo'), true ) lu.assertEquals( lu.private.patternFilter( { 'foo', '!foo', 'foo', '!foo' }, 'foo'), false ) lu.assertEquals( lu.private.patternFilter( { '!foo' }, 'foo'), false ) lu.assertEquals( lu.private.patternFilter( { '!foo', 'foo' }, 'foo'), true ) lu.assertEquals( lu.private.patternFilter( { '!foo', 'foo', '!foo' }, 'foo'), false ) lu.assertEquals( lu.private.patternFilter( { '!foo', 'foo', '!foo', 'foo' }, 'foo'), true ) lu.assertEquals( lu.private.patternFilter( { 'f..', '!foo', '__foo__' }, 'toto'), false ) lu.assertEquals( lu.private.patternFilter( { 'f..', '!foo', '__foo__' }, 'fii'), true ) lu.assertEquals( lu.private.patternFilter( { 'f..', '!foo', '__foo__' }, 'foo'), false ) lu.assertEquals( lu.private.patternFilter( { 'f..', '!foo', '__foo__' }, '__foo__'), true ) lu.assertEquals( lu.private.patternFilter( { '!f..', 'foo', '!__foo__' }, 'toto'), false ) lu.assertEquals( lu.private.patternFilter( { '!f..', 'foo', '!__foo__' }, 'fii'), false ) lu.assertEquals( lu.private.patternFilter( { '!f..', 'foo', '!__foo__' }, 'foo'), true ) lu.assertEquals( lu.private.patternFilter( { '!f..', 'foo', '!__foo__' }, '__foo__'), false ) end function TestLuaUnitUtilities:test_applyPatternFilter() local dummy = function() end local testset = { { 'toto.foo', dummy}, { 'toto.bar', dummy}, { 'titi.foo', dummy}, { 'titi.bar', dummy}, { 'tata.foo', dummy}, { 'tata.bar', dummy}, { 'foo.bar', dummy}, { 'foobar.test', dummy}, } -- default action: include everything local included, excluded = lu.LuaUnit.applyPatternFilter( nil, testset ) lu.assertEquals( #included, 8 ) lu.assertEquals( excluded, {} ) -- single exclude pattern (= select anything not matching "bar") included, excluded = lu.LuaUnit.applyPatternFilter( {'!bar'}, testset ) lu.assertEquals( included, {testset[1], testset[3], testset[5]} ) lu.assertEquals( #excluded, 5 ) -- single include pattern included, excluded = lu.LuaUnit.applyPatternFilter( {'t.t.'}, testset ) lu.assertEquals( #included, 6 ) lu.assertEquals( excluded, {testset[7], testset[8]} ) -- single include and exclude patterns included, excluded = lu.LuaUnit.applyPatternFilter( {'foo', '!test'}, testset ) lu.assertEquals( included, {testset[1], testset[3], testset[5], testset[7]} ) lu.assertEquals( #excluded, 4 ) -- multiple (specific) includes included, excluded = lu.LuaUnit.applyPatternFilter( {'toto', 'titi'}, testset ) lu.assertEquals( included, {testset[1], testset[2], testset[3], testset[4]} ) lu.assertEquals( #excluded, 4 ) -- multiple excludes included, excluded = lu.LuaUnit.applyPatternFilter( {'!tata', '!%.bar'}, testset ) lu.assertEquals( included, {testset[1], testset[3], testset[8]} ) lu.assertEquals( #excluded, 5 ) -- combined test included, excluded = lu.LuaUnit.applyPatternFilter( {'t[oai]', 'bar$', 'test', '!%.b', '!titi'}, testset ) lu.assertEquals( included, {testset[1], testset[5], testset[8]} ) lu.assertEquals( #excluded, 5 ) --[[ Combining positive and negative filters ]]-- included, excluded = lu.LuaUnit.applyPatternFilter( {'foo', 'bar', '!t.t.', '%.bar'}, testset ) lu.assertEquals( included, {testset[2], testset[4], testset[6], testset[7], testset[8]} ) lu.assertEquals( #excluded, 3 ) end function TestLuaUnitUtilities:test_strMatch() lu.assertEquals( lu.private.strMatch('toto', 't.t.'), true ) lu.assertEquals( lu.private.strMatch('toto', 't.t.', 1, 4), true ) lu.assertEquals( lu.private.strMatch('toto', 't.t.', 2, 5), false ) lu.assertEquals( lu.private.strMatch('toto', '.t.t.'), false ) lu.assertEquals( lu.private.strMatch('ototo', 't.t.'), false ) lu.assertEquals( lu.private.strMatch('totot', 't.t.'), false ) lu.assertEquals( lu.private.strMatch('ototot', 't.t.'), false ) lu.assertEquals( lu.private.strMatch('ototot', 't.t.',2,3), false ) lu.assertEquals( lu.private.strMatch('ototot', 't.t.',2,5), true ) lu.assertEquals( lu.private.strMatch('ototot', 't.t.',2,6), false ) end function TestLuaUnitUtilities:test_expandOneClass() local result = {} lu.LuaUnit.expandOneClass( result, 'titi', {} ) lu.assertEquals( result, {} ) result = {} lu.LuaUnit.expandOneClass( result, 'MyTestToto1', MyTestToto1 ) lu.assertEquals( result, { {'MyTestToto1.test1', MyTestToto1 }, {'MyTestToto1.test2', MyTestToto1 }, {'MyTestToto1.test3', MyTestToto1 }, {'MyTestToto1.testa', MyTestToto1 }, {'MyTestToto1.testb', MyTestToto1 }, } ) end function TestLuaUnitUtilities:test_expandClasses() local result result = lu.LuaUnit.expandClasses( {} ) lu.assertEquals( result, {} ) result = lu.LuaUnit.expandClasses( { { 'MyTestFunction', MyTestFunction } } ) lu.assertEquals( result, { { 'MyTestFunction', MyTestFunction } } ) result = lu.LuaUnit.expandClasses( { { 'MyTestToto1.test1', MyTestToto1 } } ) lu.assertEquals( result, { { 'MyTestToto1.test1', MyTestToto1 } } ) result = lu.LuaUnit.expandClasses( { { 'MyTestToto1', MyTestToto1 } } ) lu.assertEquals( result, { {'MyTestToto1.test1', MyTestToto1 }, {'MyTestToto1.test2', MyTestToto1 }, {'MyTestToto1.test3', MyTestToto1 }, {'MyTestToto1.testa', MyTestToto1 }, {'MyTestToto1.testb', MyTestToto1 }, } ) end function TestLuaUnitUtilities:test_xmlEscape() lu.assertEquals( lu.private.xmlEscape( 'abc' ), 'abc' ) lu.assertEquals( lu.private.xmlEscape( 'a"bc' ), 'a"bc' ) lu.assertEquals( lu.private.xmlEscape( "a'bc" ), 'a'bc' ) lu.assertEquals( lu.private.xmlEscape( "a" ), 'a<b&c>' ) end function TestLuaUnitUtilities:test_xmlCDataEscape() lu.assertEquals( lu.private.xmlCDataEscape( 'abc' ), 'abc' ) lu.assertEquals( lu.private.xmlCDataEscape( 'a"bc' ), 'a"bc' ) lu.assertEquals( lu.private.xmlCDataEscape( "a'bc" ), "a'bc" ) lu.assertEquals( lu.private.xmlCDataEscape( "a" ), 'a' ) lu.assertEquals( lu.private.xmlCDataEscape( "a--" ), 'a [C]: in function 'xpcall' ./luaunit.lua:1449: in function 'protectedCall' ./luaunit.lua:1508: in function 'execOneFunction' ./luaunit.lua:1596: in function 'internalRunSuiteByInstances' ./luaunit.lua:1660: in function 'internalRunSuiteByNames' ./luaunit.lua:1736: in function 'runSuite' example_with_luaunit.lua:140: in main chunk [C]: in ?]] local errMsg2 = 'example_with_luaunit.lua:58: expected 2, got 3' local realStackTrace2=[[stack traceback: example_with_luaunit.lua:58: in function 'TestToto.test7' ./luaunit.lua:1517: in function <./luaunit.lua:1517> [C]: in function 'xpcall' ./luaunit.lua:1517: in function 'protectedCall' ./luaunit.lua:1578: in function 'execOneFunction' ./luaunit.lua:1677: in function 'internalRunSuiteByInstances' ./luaunit.lua:1730: in function 'internalRunSuiteByNames' ./luaunit.lua:1806: in function 'runSuite' example_with_luaunit.lua:140: in main chunk [C]: in ?]] local errMsg3 = './test\\test_luaunit.lua:3013: expected: 2, actual: 1' local realStackTrace3 = [[stack traceback: ./luaunit.lua:1331: in function 'failure' ./luaunit.lua:1436: in function 'assertEquals' ./test\test_luaunit.lua:3013: in function 'methodInstance' ./luaunit.lua:3023: in function <./luaunit.lua:3023> [C]: in function 'xpcall' ./luaunit.lua:3023: in function 'protectedCall' ./luaunit.lua:3104: in function 'execOneFunction' ./luaunit.lua:3213: in function 'internalRunSuiteByInstances' ./luaunit.lua:3277: in function 'internalRunSuiteByNames' ... ./luaunit.lua:3023: in function <./luaunit.lua:3023> [C]: in function 'xpcall' ./luaunit.lua:3023: in function 'protectedCall' ./luaunit.lua:3104: in function 'execOneFunction' ./luaunit.lua:3213: in function 'internalRunSuiteByInstances' ./luaunit.lua:3277: in function 'internalRunSuiteByNames' ./luaunit.lua:3327: in function <./luaunit.lua:3293> (tail call): ? run_unit_tests.lua:22: in main chunk [C]: ? ]] local errMsg4_1 = 'reduce_reporting.lua:7: expected: 2, actual: 1' local errMsg4_2 = 'reduce_reporting.lua:12: expected: 2, actual: 1' local errMsg4_3 = 'reduce_reporting.lua:20: expected: 2, actual: 1' local realStackTrace4 = [[stack traceback: ./luaunit.lua:1199: in function 'failure' ./luaunit.lua:1304: in function 'assertEquals' reduce_reporting.lua:7: in function 'my_assertEquals' reduce_reporting.lua:12: in function 'my_sub_test_under_exec' reduce_reporting.lua:20: in function 'my_test_under_exec' ./luaunit.lua:2891: in function <./luaunit.lua:2891> [C]: in function 'xpcall' ./luaunit.lua:2891: in function 'protectedCall' ./luaunit.lua:2972: in function 'execOneFunction' ./luaunit.lua:3081: in function 'internalRunSuiteByInstances' ./luaunit.lua:3145: in function 'internalRunSuiteByNames' ./luaunit.lua:3195: in function 'runSuite' reduce_reporting.lua:18: in main chunk [C]: in ? ]] local strippedStackTrace local expectedStackTrace strippedStackTrace=lu.private.stripLuaunitTrace2( realStackTrace1, errMsg1 ) expectedStackTrace=[[stack traceback: example_with_luaunit.lua:130: in function 'test2_withFailure']] lu.assertEquals( strippedStackTrace, expectedStackTrace ) strippedStackTrace=lu.private.stripLuaunitTrace2( realStackTrace2, errMsg2 ) expectedStackTrace=[[stack traceback: example_with_luaunit.lua:58: in function 'TestToto.test7']] lu.assertEquals( strippedStackTrace, expectedStackTrace ) strippedStackTrace=lu.private.stripLuaunitTrace2( realStackTrace3, errMsg3 ) expectedStackTrace=[[stack traceback: ./test\test_luaunit.lua:3013: in function 'methodInstance']] lu.assertEquals( strippedStackTrace, expectedStackTrace ) strippedStackTrace=lu.private.stripLuaunitTrace2( realStackTrace4, errMsg4_1 ) expectedStackTrace=[[stack traceback: reduce_reporting.lua:7: in function 'my_assertEquals' reduce_reporting.lua:12: in function 'my_sub_test_under_exec' reduce_reporting.lua:20: in function 'my_test_under_exec']] lu.assertEquals( strippedStackTrace, expectedStackTrace ) strippedStackTrace=lu.private.stripLuaunitTrace2( realStackTrace4, errMsg4_2 ) expectedStackTrace=[[stack traceback: reduce_reporting.lua:12: in function 'my_sub_test_under_exec' reduce_reporting.lua:20: in function 'my_test_under_exec']] lu.assertEquals( strippedStackTrace, expectedStackTrace ) strippedStackTrace=lu.private.stripLuaunitTrace2( realStackTrace4, errMsg4_3 ) expectedStackTrace=[[stack traceback: reduce_reporting.lua:20: in function 'my_test_under_exec']] lu.assertEquals( strippedStackTrace, expectedStackTrace ) end function TestLuaUnitUtilities:test_lstrip() lu.assertEquals(lu.private.lstrip("toto"), "toto") lu.assertEquals(lu.private.lstrip("toto "), "toto ") lu.assertEquals(lu.private.lstrip(" toto "), "toto ") lu.assertEquals(lu.private.lstrip("\t\ttoto "), "toto ") lu.assertEquals(lu.private.lstrip("\t \ttoto "), "toto ") lu.assertEquals(lu.private.lstrip("\t \ttoto \n titi"), "toto \n titi") lu.assertEquals(lu.private.lstrip(""), "") end function TestLuaUnitUtilities:test_extractFileLineNbInfo() local s s = "luaunit2/example_with_luaunit.lua:124: in function 'test1_withFailure'" lu.assertEquals(lu.private.extractFileLineInfo(s), "luaunit2/example_with_luaunit.lua:124") s = " ./test\\test_luaunit.lua:2996: expected: 2, actual: 1" lu.assertEquals(lu.private.extractFileLineInfo(s), "./test\\test_luaunit.lua:2996" ) end function TestLuaUnitUtilities:test_eps_value() -- calculate epsilon local local_eps = 1.0 while (1.0 + 0.5 * local_eps) ~= 1.0 do local_eps = 0.5 * local_eps end -- print( local_eps, lu.EPS) lu.assertEquals( local_eps, lu.EPS ) end ------------------------------------------------------------------ -- -- Outputter Tests -- ------------------------------------------------------------------ TestLuaUnitOutputters = { __class__ = 'TestOutputters' } -- JUnitOutput:startSuite() can raise errors on its own, cover those function TestLuaUnitOutputters:testJUnitOutputErrors() local runner = lu.LuaUnit.new() runner:setOutputType('junit') local outputter = runner.outputType.new(runner) -- missing file name lu.assertErrorMsgContains('With Junit, an output filename must be supplied', outputter.startSuite, outputter) -- test adding .xml extension, catch output error outputter.fname = '/tmp/nonexistent.dir/foobar' lu.assertErrorMsgContains('Could not open file for writing: /tmp/nonexistent.dir/foobar.xml', outputter.startSuite, outputter) end ------------------------------------------------------------------ -- -- Assertion Tests -- ------------------------------------------------------------------ local function assertFailure( ... ) -- ensure that execution generates a failure type error lu.assertErrorMsgMatches(lu.FAILURE_PREFIX .. ".*", ...) end local function assertBadFindArgTable( ... ) lu.assertErrorMsgMatches( ".* bad argument .* to 'find' %(string expected, got table%)", ...) end local function assertBadFindArgNil( ... ) lu.assertErrorMsgMatches( ".* bad argument .* to 'find' %(string expected, got nil%)", ...) end local function assertBadIndexNumber( ... ) lu.assertErrorMsgMatches( ".* attempt to index .*a number value.*", ... ) end local function assertBadIndexNil( ... ) lu.assertErrorMsgMatches( ".* attempt to index .*a nil value.*", ... ) end local function assertBadMethodNil( ... ) lu.assertErrorMsgMatches( ".* attempt to call .*a nil value.*", ... ) end TestLuaUnitAssertions = { __class__ = 'TestLuaUnitAssertions' } function TestLuaUnitAssertions:test_assertEquals() local f = function() return true end local g = function() return true end lu.assertEquals( 1, 1 ) lu.assertEquals( "abc", "abc" ) lu.assertEquals( nil, nil ) lu.assertEquals( true, true ) lu.assertEquals( f, f) lu.assertEquals( {1,2,3}, {1,2,3}) lu.assertEquals( {one=1,two=2,three=3}, {one=1,two=2,three=3}) lu.assertEquals( {one=1,two=2,three=3}, {two=2,three=3,one=1}) lu.assertEquals( {one=1,two={1,2},three=3}, {two={1,2},three=3,one=1}) lu.assertEquals( {one=1,two={1,{2,nil}},three=3}, {two={1,{2,nil}},three=3,one=1}) lu.assertEquals( {nil}, {nil} ) assertFailure( lu.assertEquals, 1, 2) assertFailure( lu.assertEquals, 1, "abc" ) assertFailure( lu.assertEquals, 0, nil ) assertFailure( lu.assertEquals, false, nil ) assertFailure( lu.assertEquals, true, 1 ) assertFailure( lu.assertEquals, f, 1 ) assertFailure( lu.assertEquals, f, g ) assertFailure( lu.assertEquals, {1,2,3}, {2,1,3} ) assertFailure( lu.assertEquals, {1,2,3}, nil ) assertFailure( lu.assertEquals, {1,2,3}, 1 ) assertFailure( lu.assertEquals, {1,2,3}, true ) assertFailure( lu.assertEquals, {1,2,3}, {one=1,two=2,three=3} ) assertFailure( lu.assertEquals, {1,2,3}, {one=1,two=2,three=3,four=4} ) assertFailure( lu.assertEquals, {one=1,two=2,three=3}, {2,1,3} ) assertFailure( lu.assertEquals, {one=1,two=2,three=3}, nil ) assertFailure( lu.assertEquals, {one=1,two=2,three=3}, 1 ) assertFailure( lu.assertEquals, {one=1,two=2,three=3}, true ) assertFailure( lu.assertEquals, {one=1,two=2,three=3}, {1,2,3} ) assertFailure( lu.assertEquals, {one=1,two={1,2},three=3}, {two={2,1},three=3,one=1}) -- check assertions for which # operator returns two different length depending -- on how the table is built, eventhough the final table is the same local t1 = {1, nil, 3} -- length is 3 local t2 = {1, [3]=3} -- length is 1 lu.assertEquals( t1, t2 ) end function TestLuaUnitAssertions:test_assertEqualsTableWithCycles() -- Table with same cyclic structrure should compare equal local t1, t2 = {1}, {1} t1.self = t1 t2.self = t2 lu.assertEquals( t1, t2 ) -- add one differing element t1[2] = 2 t2[2] = 3 lu.assertNotEquals( t1, t2 ) -- cross cycle local t3, t4 = {}, {} t3.other = t4 t4.other = t3 lu.assertEquals( t3, t4 ) -- 3 level cycle local t5a, t6a, t7a = {}, {}, {} t6a.t5 = t5a t7a.t6 = t6a t5a.t7 = t7a local t5b, t6b, t7b = {}, {}, {} t6b.t5 = t5b t7b.t6 = t6b t5b.t7 = t7b lu.assertEquals( t5a, t5b ) lu.assertEquals( t6a, t6b ) lu.assertEquals( t7a, t7b ) lu.assertNotEquals( t5a, t6a ) -- 3 level cycles vs 2 level cycles local t8a, t9a, t10a = {}, {}, {} t8a.other = t9a t9a.other = t10a t10a.other = t8a local t8b, t9b = {}, {} t8b.other = t9b t9b.other = t8b -- print( 't8a='..lu.prettystr(t8a)) -- print( 't8b='..lu.prettystr(t8b)) lu.assertNotEquals( t8a, t8b ) local t11, t12 = {}, {} t11.cycle = t8a t12.cycle = t8b lu.assertNotEquals( t11, t12 ) -- issue #116 local a={} local b={} a.x = b; b.x = a local a1={} local b1={} a1.x = b1; b1.x = a1 lu.assertEquals(a, a1) end function TestLuaUnitAssertions:test_assertEqualsTableAsKeys() assertFailure( lu.assertEquals, {[{}] = 1}, { [{}] = 1}) assertFailure( lu.assertEquals, {[{one=1, two=2}] = 1}, { [{two=2, one=1}] = 1}) assertFailure( lu.assertEquals, {[{1}]=2, [{1}]=3}, {[{1}]=3, [{1}]=2} ) assertFailure( lu.assertEquals, {[{1}]=2, [{1}]=3}, {[{1}]=2, [{1}]=3} ) assertFailure( lu.assertEquals, {[{}] = 1}, {[{}] = 2}) assertFailure( lu.assertEquals, {[{}] = 1}, {[{one=1}] = 2}) assertFailure( lu.assertEquals, {[{}] = 1}, {[{}] = 1, 2}) assertFailure( lu.assertEquals, {[{}] = 1}, {[{}] = 1, [{}] = 1}) assertFailure( lu.assertEquals, {[{"one"}]=1}, {[{"one", 1}]=2} ) assertFailure( lu.assertEquals, {[{"one"}]=1,[{"one"}]=1}, {[{"one"}]=1} ) end function TestLuaUnitAssertions:test_assertAlmostEquals() lu.assertAlmostEquals( 1, 1, 0.1 ) lu.assertAlmostEquals( 1, 1 ) -- default margin (= M.EPS) lu.assertAlmostEquals( 1, 1, 0 ) -- zero margin assertFailure( lu.assertAlmostEquals, 0, lu.EPS, 0 ) -- zero margin lu.assertAlmostEquals( 1, 1.1, 0.2 ) lu.assertAlmostEquals( -1, -1.1, 0.2 ) lu.assertAlmostEquals( 0.1, -0.1, 0.3 ) lu.assertAlmostEquals( 0.1, -0.1, 0.2 ) -- Due to rounding errors, these user-supplied margins are too small. -- The tests should respect them, and so are required to fail. assertFailure( lu.assertAlmostEquals, 1, 1.1, 0.1 ) assertFailure( lu.assertAlmostEquals, -1, -1.1, 0.1 ) -- Check that an explicit zero margin gets respected too assertFailure( lu.assertAlmostEquals, 1.1 - 1, 0.1, 0 ) assertFailure( lu.assertAlmostEquals, -1 - (-1.1), 0.1, 0 ) -- Tests pass when adding M.EPS, either explicitly or implicitly lu.assertAlmostEquals( 1, 1.1, 0.1 + lu.EPS) lu.assertAlmostEquals( 1.1 - 1, 0.1 ) lu.assertAlmostEquals( -1, -1.1, 0.1 + lu.EPS ) lu.assertAlmostEquals( -1 - (-1.1), 0.1 ) assertFailure( lu.assertAlmostEquals, 1, 1.11, 0.1 ) assertFailure( lu.assertAlmostEquals, -1, -1.11, 0.1 ) end function TestLuaUnitAssertions:test_assertAlmostEqualsTables() lu.assertAlmostEquals( {1}, {1}, 0.1 ) lu.assertAlmostEquals( {1}, {1} ) -- default margin (= M.EPS) lu.assertAlmostEquals( {1}, {1}, 0 ) -- zero margin assertFailure( lu.assertAlmostEquals, {0}, {lu.EPS}, 0 ) -- zero margin lu.assertAlmostEquals( {1}, {1.1}, 0.2 ) lu.assertAlmostEquals( {-1}, {-1.1}, 0.2 ) lu.assertAlmostEquals( {0.1}, {-0.1}, 0.3 ) lu.assertAlmostEquals( {0.1}, {-0.1}, 0.2 ) lu.assertAlmostEquals( {1, -1, 0.1, 0.1}, {1.1, -1.1, 0.1, -0.1}, 0.3 ) lu.assertAlmostEquals( {a=1, b=-1, c=0.1, d=0.1}, {a=1.1, b=-1.1, c=0.1, d=-0.1}, 0.3 ) lu.assertAlmostEquals( {0, {a=1, b=-1, c=0.1, d=0.1}}, {0, {a=1.1, b=-1.1, c=0.1, d=-0.1}}, 0.3 ) -- Due to rounding errors, these user-supplied margins are too small. -- The tests should respect them, and so are required to fail. assertFailure( lu.assertAlmostEquals, {1}, {1.1}, 0.1 ) assertFailure( lu.assertAlmostEquals, {-1}, {-1.1}, 0.1 ) -- Check that an explicit zero margin gets respected too assertFailure( lu.assertAlmostEquals, {1.1 - 1}, {0.1}, 0 ) assertFailure( lu.assertAlmostEquals, {-1 - (-1.1)}, {0.1}, 0 ) -- Tests pass when adding M.EPS, either explicitly or implicitly lu.assertAlmostEquals( 1, 1.1, 0.1 + lu.EPS) lu.assertAlmostEquals( 1.1 - 1, 0.1 ) lu.assertAlmostEquals( -1, -1.1, 0.1 + lu.EPS ) lu.assertAlmostEquals( -1 - (-1.1), 0.1 ) lu.assertAlmostEquals( { 1, 1.1-1, -1}, {1.1, 0.1, -1.1}, 0.1 + lu.EPS ) -- tables with more diversity lu.assertAlmostEquals( {1 , 'abc', nil, false, true, {1,2} }, {1.1, 'abc', nil, false, true, {1,2} }, 0.3) lu.assertAlmostEquals( {1 , 'abc', { 2, 3}, false, true, {1,2} }, {1.1, 'abc', {2.1, 3.2}, false, true, {1,2} }, 0.3) -- difference on something else than numeric comparison assertFailure( lu.assertAlmostEquals, {1, 'abc'}, {1, 'def'}, 0.1 ) assertFailure( lu.assertAlmostEquals, {1, false}, {1, true}, 0.1 ) assertFailure( lu.assertAlmostEquals, {1, 'abc'}, {1, nil}, 0.1 ) end function TestLuaUnitAssertions:test_assertAlmostEqualsErrors() lu.assertErrorMsgContains( "margin must be a number", lu.assertAlmostEquals, -1, 1, "foobar" ) lu.assertErrorMsgContains( "must supply only number or table arguments", lu.assertAlmostEquals, -1, nil, 0 ) lu.assertErrorMsgContains( "must supply only number or table arguments", lu.assertAlmostEquals, nil, nil, 0 ) lu.assertErrorMsgContains( "must supply only number or table arguments", lu.assertAlmostEquals, '123', '345', 0 ) lu.assertErrorMsgContains( "margin must not be negative", lu.assertAlmostEquals, 1, 1.1, -0.1 ) end function TestLuaUnitAssertions:test_assertNotEquals() local f = function() return true end local g = function() return true end lu.assertNotEquals( 1, 2 ) lu.assertNotEquals( "abc", 2 ) lu.assertNotEquals( "abc", "def" ) lu.assertNotEquals( 1, 2) lu.assertNotEquals( 1, "abc" ) lu.assertNotEquals( 0, nil ) lu.assertNotEquals( false, nil ) lu.assertNotEquals( true, 1 ) lu.assertNotEquals( f, 1 ) lu.assertNotEquals( f, g ) lu.assertNotEquals( {one=1,two=2,three=3}, true ) lu.assertNotEquals( {one=1,two={1,2},three=3}, {two={2,1},three=3,one=1} ) assertFailure( lu.assertNotEquals, 1, 1) assertFailure( lu.assertNotEquals, "abc", "abc" ) assertFailure( lu.assertNotEquals, nil, nil ) assertFailure( lu.assertNotEquals, true, true ) assertFailure( lu.assertNotEquals, f, f) assertFailure( lu.assertNotEquals, {one=1,two={1,{2,nil}},three=3}, {two={1,{2,nil}},three=3,one=1}) end function TestLuaUnitAssertions:test_assertNotAlmostEquals() lu.assertNotAlmostEquals( 1, 1.2, 0.1 ) lu.assertNotAlmostEquals( 1, 1.01 ) -- default margin (= M.EPS) lu.assertNotAlmostEquals( 1, 1.01, 0 ) -- zero margin lu.assertNotAlmostEquals( 0, lu.EPS, 0 ) -- zero margin lu.assertNotAlmostEquals( 1, 1.3, 0.2 ) lu.assertNotAlmostEquals( -1, -1.3, 0.2 ) lu.assertNotAlmostEquals( 0.1, -0.1, 0.1 ) lu.assertNotAlmostEquals( 1, 1.1, 0.09 ) lu.assertNotAlmostEquals( -1, -1.1, 0.09 ) lu.assertNotAlmostEquals( 0.1, -0.1, 0.11 ) -- Due to rounding errors, these user-supplied margins are too small. -- The tests should respect them, and so are expected to pass. lu.assertNotAlmostEquals( 1, 1.1, 0.1 ) lu.assertNotAlmostEquals( -1, -1.1, 0.1 ) -- Check that an explicit zero margin gets respected too lu.assertNotAlmostEquals( 1.1 - 1, 0.1, 0 ) lu.assertNotAlmostEquals( -1 - (-1.1), 0.1, 0 ) -- Tests fail when adding M.EPS, either explicitly or implicitly assertFailure( lu.assertNotAlmostEquals, 1, 1.1, 0.1 + lu.EPS) assertFailure( lu.assertNotAlmostEquals, 1.1 - 1, 0.1 ) assertFailure( lu.assertNotAlmostEquals, -1, -1.1, 0.1 + lu.EPS ) assertFailure( lu.assertNotAlmostEquals, -1 - (-1.1), 0.1 ) assertFailure( lu.assertNotAlmostEquals, 1, 1.11, 0.2 ) assertFailure( lu.assertNotAlmostEquals, -1, -1.11, 0.2 ) lu.assertErrorMsgContains( "must supply only number arguments", lu.assertNotAlmostEquals, -1, 1, "foobar" ) lu.assertErrorMsgContains( "must supply only number arguments", lu.assertNotAlmostEquals, -1, nil, 0 ) lu.assertErrorMsgContains( "must supply only number arguments", lu.assertNotAlmostEquals, nil, 1, 0 ) lu.assertErrorMsgContains( "margin must not be negative", lu.assertNotAlmostEquals, 1, 1.1, -0.1 ) end function TestLuaUnitAssertions:test_assertNotEqualsDifferentTypes2() lu.assertNotEquals( 2, "abc" ) end function TestLuaUnitAssertions:test_assertIsTrue() lu.assertIsTrue(true) -- assertIsTrue is strict assertFailure( lu.assertIsTrue, false) assertFailure( lu.assertIsTrue, nil ) assertFailure( lu.assertIsTrue, 0) assertFailure( lu.assertIsTrue, 1) assertFailure( lu.assertIsTrue, "") assertFailure( lu.assertIsTrue, "abc") assertFailure( lu.assertIsTrue, function() return true end ) assertFailure( lu.assertIsTrue, {} ) assertFailure( lu.assertIsTrue, { 1 } ) end function TestLuaUnitAssertions:test_assertNotIsTrue() assertFailure( lu.assertNotIsTrue, true) lu.assertNotIsTrue( false) lu.assertNotIsTrue( nil ) lu.assertNotIsTrue( 0) lu.assertNotIsTrue( 1) lu.assertNotIsTrue( "") lu.assertNotIsTrue( "abc") lu.assertNotIsTrue( function() return true end ) lu.assertNotIsTrue( {} ) lu.assertNotIsTrue( { 1 } ) end function TestLuaUnitAssertions:test_assertIsFalse() lu.assertIsFalse(false) assertFailure( lu.assertIsFalse, nil) -- assertIsFalse is strict ! assertFailure( lu.assertIsFalse, true) assertFailure( lu.assertIsFalse, 0 ) assertFailure( lu.assertIsFalse, 1 ) assertFailure( lu.assertIsFalse, "" ) assertFailure( lu.assertIsFalse, "abc" ) assertFailure( lu.assertIsFalse, function() return true end ) assertFailure( lu.assertIsFalse, {} ) assertFailure( lu.assertIsFalse, { 1 } ) end function TestLuaUnitAssertions:test_assertNotIsFalse() assertFailure(lu.assertNotIsFalse, false) lu.assertNotIsFalse( true) lu.assertNotIsFalse( 0 ) lu.assertNotIsFalse( 1 ) lu.assertNotIsFalse( "" ) lu.assertNotIsFalse( "abc" ) lu.assertNotIsFalse( function() return true end ) lu.assertNotIsFalse( {} ) lu.assertNotIsFalse( { 1 } ) end function TestLuaUnitAssertions:test_assertEvalToTrue() lu.assertEvalToTrue(true) assertFailure( lu.assertEvalToTrue, false) assertFailure( lu.assertEvalToTrue, nil ) lu.assertEvalToTrue(0) lu.assertEvalToTrue(1) lu.assertEvalToTrue("") lu.assertEvalToTrue("abc") lu.assertEvalToTrue( function() return true end ) lu.assertEvalToTrue( {} ) lu.assertEvalToTrue( { 1 } ) end function TestLuaUnitAssertions:test_assertEvalToFalse() lu.assertEvalToFalse(false) lu.assertEvalToFalse(nil) assertFailure( lu.assertEvalToFalse, true) assertFailure( lu.assertEvalToFalse, 0 ) assertFailure( lu.assertEvalToFalse, 1 ) assertFailure( lu.assertEvalToFalse, "" ) assertFailure( lu.assertEvalToFalse, "abc" ) assertFailure( lu.assertEvalToFalse, function() return true end ) assertFailure( lu.assertEvalToFalse, {} ) assertFailure( lu.assertEvalToFalse, { 1 } ) end function TestLuaUnitAssertions:test_assertNil() lu.assertNil(nil) assertFailure( lu.assertTrue, false) assertFailure( lu.assertNil, 0) assertFailure( lu.assertNil, "") assertFailure( lu.assertNil, "abc") assertFailure( lu.assertNil, function() return true end ) assertFailure( lu.assertNil, {} ) assertFailure( lu.assertNil, { 1 } ) end function TestLuaUnitAssertions:test_assertNotNil() assertFailure( lu.assertNotNil, nil) lu.assertNotNil( false ) lu.assertNotNil( 0 ) lu.assertNotNil( "" ) lu.assertNotNil( "abc" ) lu.assertNotNil( function() return true end ) lu.assertNotNil( {} ) lu.assertNotNil( { 1 } ) end function TestLuaUnitAssertions:test_assertStrContains() lu.assertStrContains( 'abcdef', 'abc' ) lu.assertStrContains( 'abcdef', 'bcd' ) lu.assertStrContains( 'abcdef', 'abcdef' ) lu.assertStrContains( 'abc0', 0 ) assertFailure( lu.assertStrContains, 'ABCDEF', 'abc' ) assertFailure( lu.assertStrContains, '', 'abc' ) lu.assertStrContains( 'abcdef', '' ) assertFailure( lu.assertStrContains, 'abcdef', 'abcx' ) assertFailure( lu.assertStrContains, 'abcdef', 'abcdefg' ) assertFailure( lu.assertStrContains, 'abcdef', 0 ) assertBadFindArgTable( lu.assertStrContains, 'abcdef', {} ) assertBadFindArgNil( lu.assertStrContains, 'abcdef', nil ) lu.assertStrContains( 'abcdef', 'abc', false ) lu.assertStrContains( 'abcdef', 'abc', true ) lu.assertStrContains( 'abcdef', 'a.c', true ) assertFailure( lu.assertStrContains, 'abcdef', '.abc', true ) end function TestLuaUnitAssertions:test_assertStrIContains() lu.assertStrIContains( 'ABcdEF', 'aBc' ) lu.assertStrIContains( 'abCDef', 'bcd' ) lu.assertStrIContains( 'abcdef', 'abcDef' ) assertFailure( lu.assertStrIContains, '', 'aBc' ) lu.assertStrIContains( 'abcDef', '' ) assertFailure( lu.assertStrIContains, 'abcdef', 'abcx' ) assertFailure( lu.assertStrIContains, 'abcdef', 'abcdefg' ) end function TestLuaUnitAssertions:test_assertNotStrContains() assertFailure( lu.assertNotStrContains, 'abcdef', 'abc' ) assertFailure( lu.assertNotStrContains, 'abcdef', 'bcd' ) assertFailure( lu.assertNotStrContains, 'abcdef', 'abcdef' ) lu.assertNotStrContains( '', 'abc' ) assertFailure( lu.assertNotStrContains, 'abcdef', '' ) assertFailure( lu.assertNotStrContains, 'abc0', 0 ) lu.assertNotStrContains( 'abcdef', 'abcx' ) lu.assertNotStrContains( 'abcdef', 'abcdefg' ) assertBadFindArgTable( lu.assertNotStrContains, 'abcdef', {} ) assertBadFindArgNil( lu.assertNotStrContains, 'abcdef', nil ) assertFailure( lu.assertNotStrContains, 'abcdef', 'abc', false ) assertFailure( lu.assertNotStrContains, 'abcdef', 'a.c', true ) lu.assertNotStrContains( 'abcdef', 'a.cx', true ) end function TestLuaUnitAssertions:test_assertNotStrIContains() assertFailure( lu.assertNotStrIContains, 'aBcdef', 'abc' ) assertFailure( lu.assertNotStrIContains, 'abcdef', 'aBc' ) assertFailure( lu.assertNotStrIContains, 'abcdef', 'bcd' ) assertFailure( lu.assertNotStrIContains, 'abcdef', 'abcdef' ) lu.assertNotStrIContains( '', 'abc' ) assertFailure( lu.assertNotStrIContains, 'abcdef', '' ) assertBadIndexNumber( lu.assertNotStrIContains, 'abc0', 0 ) lu.assertNotStrIContains( 'abcdef', 'abcx' ) lu.assertNotStrIContains( 'abcdef', 'abcdefg' ) assertBadMethodNil( lu.assertNotStrIContains, 'abcdef', {} ) assertBadIndexNil( lu.assertNotStrIContains, 'abcdef', nil ) end function TestLuaUnitAssertions:test_assertStrMatches() lu.assertStrMatches( 'abcdef', 'abcdef' ) lu.assertStrMatches( 'abcdef', '..cde.' ) assertFailure( lu.assertStrMatches, 'abcdef', '..def') assertFailure( lu.assertStrMatches, 'abCDEf', '..cde.') lu.assertStrMatches( 'abcdef', 'bcdef', 2 ) lu.assertStrMatches( 'abcdef', 'bcde', 2, 5 ) lu.assertStrMatches( 'abcdef', 'b..e', 2, 5 ) lu.assertStrMatches( 'abcdef', 'ab..e', nil, 5 ) assertFailure( lu.assertStrMatches, 'abcdef', '' ) assertFailure( lu.assertStrMatches, '', 'abcdef' ) assertFailure( lu.assertStrMatches, 'abcdef', 0 ) assertBadFindArgTable( lu.assertStrMatches, 'abcdef', {} ) assertBadFindArgNil( lu.assertStrMatches, 'abcdef', nil ) end function TestLuaUnitAssertions:test_assertItemsEquals() lu.assertItemsEquals(nil, nil) lu.assertItemsEquals({},{}) lu.assertItemsEquals({1,2,3}, {3,1,2}) lu.assertItemsEquals({nil},{nil}) lu.assertItemsEquals({one=1,two=2,three=3}, {two=2,one=1,three=3}) lu.assertItemsEquals({one=1,two=2,three=3}, {a=1,b=2,c=3}) lu.assertItemsEquals({1,2,three=3}, {3,1,two=2}) assertFailure(lu.assertItemsEquals, {1}, {}) assertFailure(lu.assertItemsEquals, nil, {1,2,3}) assertFailure(lu.assertItemsEquals, {1,2,3}, nil) assertFailure(lu.assertItemsEquals, {1,2,3,4}, {3,1,2}) assertFailure(lu.assertItemsEquals, {1,2,3}, {3,1,2,4}) assertFailure(lu.assertItemsEquals, {one=1,two=2,three=3,four=4}, {a=1,b=2,c=3}) assertFailure(lu.assertItemsEquals, {one=1,two=2,three=3}, {a=1,b=2,c=3,d=4}) assertFailure(lu.assertItemsEquals, {1,2,three=3}, {3,4,a=1,b=2}) assertFailure(lu.assertItemsEquals, {1,2,three=3,four=4}, {3,a=1,b=2}) lu.assertItemsEquals({one=1,two={1,2},three=3}, {one={1,2},two=1,three=3}) lu.assertItemsEquals({one=1, two={1,{3,2,one=1}}, three=3}, {two={1,{3,2,one=1}}, one=1, three=3}) -- itemsEquals is not recursive: assertFailure( lu.assertItemsEquals,{1,{2,1},3}, {3,1,{1,2}}) assertFailure( lu.assertItemsEquals,{one=1,two={1,2},three=3}, {one={2,1},two=1,three=3}) assertFailure( lu.assertItemsEquals,{one=1,two={1,{3,2,one=1}},three=3}, {two={{3,one=1,2},1},one=1,three=3}) assertFailure( lu.assertItemsEquals,{one=1,two={1,{3,2,one=1}},three=3}, {two={{3,2,one=1},1},one=1,three=3}) assertFailure(lu.assertItemsEquals, {one=1,two=2,three=3}, {two=2,one=1,three=2}) assertFailure(lu.assertItemsEquals, {one=1,two=2,three=3}, {two=2,one=1,four=4}) assertFailure(lu.assertItemsEquals, {one=1,two=2,three=3}, {two=2,one=1,'three'}) assertFailure(lu.assertItemsEquals, {one=1,two=2,three=3}, {two=2,one=1,nil}) assertFailure(lu.assertItemsEquals, {one=1,two=2,three=3}, {two=2,one=1}) end function TestLuaUnitAssertions:test_assertTableContains() local t = {3, 'some value', 1, 2} assertFailure(lu.assertTableContains, t, 0) lu.assertTableContains(t, 1) lu.assertTableContains(t, 2) lu.assertTableContains(t, 3) assertFailure(lu.assertTableContains, t, 4) lu.assertTableContains(t, 'some value') assertFailure(lu.assertTableContains, t, 'other value') t = {red = 'cherry', yellow = 'lemon', blue = 'grape'} lu.assertTableContains(t, 'lemon') lu.assertTableContains(t, 'grape') lu.assertTableContains(t, 'cherry') assertFailure(lu.assertTableContains, t, 'kiwi') t = {a={1,2,3}, b={4,5,6} } lu.assertTableContains(t, {1,2,3} ) lu.assertTableContains(t, {4,5,6} ) assertFailure(lu.assertTableContains, t, {3,2,1} ) end function TestLuaUnitAssertions:test_assertNotTableContains() local t = {3, 'some value', 1, 2} lu.assertNotTableContains(t, 0) assertFailure(lu.assertNotTableContains, t, 1) assertFailure(lu.assertNotTableContains, t, 2) assertFailure(lu.assertNotTableContains, t, 3) lu.assertNotTableContains(t, 4) assertFailure(lu.assertNotTableContains, t, 'some value') lu.assertNotTableContains(t, 'other value') t = {red = 'cherry', yellow = 'lemon', blue = 'grape'} assertFailure(lu.assertNotTableContains, t, 'lemon') assertFailure(lu.assertNotTableContains, t, 'grape') assertFailure(lu.assertNotTableContains, t, 'cherry') lu.assertNotTableContains(t, 'kiwi') end function TestLuaUnitAssertions:test_assertIsNumber() lu.assertIsNumber(1) lu.assertIsNumber(1.4) assertFailure(lu.assertIsNumber, "hi there!") assertFailure(lu.assertIsNumber, nil) assertFailure(lu.assertIsNumber, {}) assertFailure(lu.assertIsNumber, {1,2,3}) assertFailure(lu.assertIsNumber, {1}) assertFailure(lu.assertIsNumber, coroutine.create( function(v) local y=v+1 end ) ) assertFailure(lu.assertIsNumber, true) end function TestLuaUnitAssertions:test_assertIsNaN() assertFailure(lu.assertIsNaN, "hi there!") assertFailure(lu.assertIsNaN, nil) assertFailure(lu.assertIsNaN, {}) assertFailure(lu.assertIsNaN, {1,2,3}) assertFailure(lu.assertIsNaN, {1}) assertFailure(lu.assertIsNaN, coroutine.create( function(v) local y=v+1 end ) ) lu.assertIsNaN(0 / 0) lu.assertIsNaN(-0 / 0) lu.assertIsNaN(0 / -0) lu.assertIsNaN(-0 / -0) local inf = math.huge lu.assertIsNaN(inf / inf) lu.assertIsNaN(-inf / inf) lu.assertIsNaN(inf / -inf) lu.assertIsNaN(-inf / -inf) lu.assertIsNaN(inf - inf) lu.assertIsNaN((-inf) + inf) lu.assertIsNaN(inf + (-inf)) lu.assertIsNaN((-inf) - (-inf)) lu.assertIsNaN(0 * inf) lu.assertIsNaN(-0 * inf) lu.assertIsNaN(0 * -inf) lu.assertIsNaN(-0 * -inf) lu.assertIsNaN(math.sqrt(-1)) if lu._LUAVERSION == "Lua 5.1" or lu._LUAVERSION == "Lua 5.2" then -- Lua 5.3 will complain/error "bad argument #2 to 'fmod' (zero)" lu.assertIsNaN(math.fmod(1, 0)) lu.assertIsNaN(math.fmod(1, -0)) end lu.assertIsNaN(math.fmod(inf, 1)) lu.assertIsNaN(math.fmod(-inf, 1)) assertFailure(lu.assertIsNaN, 0 / 1) -- 0.0 assertFailure(lu.assertIsNaN, 1 / 0) -- inf assertFailure(lu.assertIsNaN, -1 / 0)-- -inf end function TestLuaUnitAssertions:test_assertNotIsNaN() -- not NaN lu.assertNotIsNaN( "hi there!") lu.assertNotIsNaN( nil) lu.assertNotIsNaN( {}) lu.assertNotIsNaN( {1,2,3}) lu.assertNotIsNaN( {1}) lu.assertNotIsNaN( coroutine.create( function(v) local y=v+1 end ) ) -- is NaN lu.assertFailure( lu.assertNotIsNaN, 0 / 0) lu.assertFailure( lu.assertNotIsNaN, -0 / 0) lu.assertFailure( lu.assertNotIsNaN, 0 / -0) lu.assertFailure( lu.assertNotIsNaN, -0 / -0) local inf = math.huge lu.assertFailure( lu.assertNotIsNaN, inf / inf) lu.assertFailure( lu.assertNotIsNaN, -inf / inf) lu.assertFailure( lu.assertNotIsNaN, inf / -inf) lu.assertFailure( lu.assertNotIsNaN, -inf / -inf) lu.assertFailure( lu.assertNotIsNaN, inf - inf) lu.assertFailure( lu.assertNotIsNaN, (-inf) + inf) lu.assertFailure( lu.assertNotIsNaN, inf + (-inf)) lu.assertFailure( lu.assertNotIsNaN, (-inf) - (-inf)) lu.assertFailure( lu.assertNotIsNaN, 0 * inf) lu.assertFailure( lu.assertNotIsNaN, -0 * inf) lu.assertFailure( lu.assertNotIsNaN, 0 * -inf) lu.assertFailure( lu.assertNotIsNaN, -0 * -inf) lu.assertFailure( lu.assertNotIsNaN, math.sqrt(-1)) if lu._LUAVERSION == "Lua 5.1" or lu._LUAVERSION == "Lua 5.2" then -- Lua 5.3 will complain/error "bad argument #2 to 'fmod' (zero)" lu.assertFailure( lu.assertNotIsNaN, math.fmod(1, 0)) lu.assertFailure( lu.assertNotIsNaN, math.fmod(1, -0)) end lu.assertFailure( lu.assertNotIsNaN, math.fmod(inf, 1)) lu.assertFailure( lu.assertNotIsNaN, math.fmod(-inf, 1)) -- not NaN assertFailure(lu.assertNotIsNaN, 0 / 1) -- 0.0 assertFailure(lu.assertNotIsNaN, 1 / 0) -- inf assertFailure(lu.assertNotIdNaN, -1 / 0) -- -inf end function TestLuaUnitAssertions:test_assertIsInf() assertFailure(lu.assertIsInf, "hi there!") assertFailure(lu.assertIsInf, nil) assertFailure(lu.assertIsInf, {}) assertFailure(lu.assertIsInf, {1,2,3}) assertFailure(lu.assertIsInf, {1}) assertFailure(lu.assertIsInf, coroutine.create( function(v) local y=v+1 end ) ) assertFailure(lu.assertIsInf, 0 ) assertFailure(lu.assertIsInf, 1 ) assertFailure(lu.assertIsInf, 0 / 0) -- NaN assertFailure(lu.assertIsInf, -0 / 0) -- NaN assertFailure(lu.assertIsInf, 0 / 1) -- 0.0 lu.assertIsInf(1 / 0) -- inf lu.assertIsInf(math.log(0)) -- -inf lu.assertIsInf(math.huge) -- inf lu.assertIsInf(-math.huge) -- -inf end function TestLuaUnitAssertions:test_assertIsPlusInf() assertFailure(lu.assertIsPlusInf, "hi there!") assertFailure(lu.assertIsPlusInf, nil) assertFailure(lu.assertIsPlusInf, {}) assertFailure(lu.assertIsPlusInf, {1,2,3}) assertFailure(lu.assertIsPlusInf, {1}) assertFailure(lu.assertIsPlusInf, coroutine.create( function(v) local y=v+1 end ) ) assertFailure(lu.assertIsPlusInf, 0 ) assertFailure(lu.assertIsPlusInf, 1 ) assertFailure(lu.assertIsPlusInf, 0 / 0) -- NaN assertFailure(lu.assertIsPlusInf, -0 / 0) -- NaN assertFailure(lu.assertIsPlusInf, 0 / 1) -- 0.0 assertFailure(lu.assertIsPlusInf, math.log(0)) -- -inf assertFailure(lu.assertIsPlusInf, -math.huge) -- -inf lu.assertIsPlusInf(1 / 0) -- inf lu.assertIsPlusInf(math.huge) -- inf -- behavior with -0 is lua version dependant: -- lua51, lua53: -0 does NOT represent the value minus zero BUT plus zero -- lua52, luajit: -0 represents the value minus zero -- this is verified with the value 1/-0 -- lua 5.1, 5.3: 1/-0 = inf -- lua 5.2, luajit: 1/-0 = -inf if lu._LUAVERSION ~= "Lua 5.2" and lu._LUAVERSION:sub(1,6) ~= "LuaJIT" then lu.assertIsPlusInf( 1/-0 ) else assertFailure( lu.assertIsPlusInf, 1/-0 ) end end function TestLuaUnitAssertions:test_assertIsMinusInf() assertFailure(lu.assertIsMinusInf, "hi there!") assertFailure(lu.assertIsMinusInf, nil) assertFailure(lu.assertIsMinusInf, {}) assertFailure(lu.assertIsMinusInf, {1,2,3}) assertFailure(lu.assertIsMinusInf, {1}) assertFailure(lu.assertIsMinusInf, coroutine.create( function(v) local y=v+1 end ) ) assertFailure(lu.assertIsMinusInf, 0 ) assertFailure(lu.assertIsMinusInf, 1 ) assertFailure(lu.assertIsMinusInf, 0 / 0) -- NaN assertFailure(lu.assertIsMinusInf, -0 / 0) -- NaN assertFailure(lu.assertIsMinusInf, 0 / 1) -- 0.0 assertFailure(lu.assertIsMinusInf, -math.log(0)) -- inf assertFailure(lu.assertIsMinusInf, math.huge) -- inf lu.assertIsMinusInf( math.log(0)) -- -inf lu.assertIsMinusInf(-1 / 0) -- -inf lu.assertIsMinusInf(-math.huge) -- -inf -- behavior with -0 is lua version dependant: -- lua51, lua53: -0 does NOT represent the value minus zero BUT plus zero -- lua52, luajit: -0 represents the value minus zero -- this is verified with the value 1/-0 -- lua 5.1, 5.3: 1/-0 = inf -- lua 5.2, luajit: 1/-0 = -inf if lu._LUAVERSION ~= "Lua 5.2" and lu._LUAVERSION:sub(1,6) ~= "LuaJIT" then assertFailure( lu.assertIsMinusInf, 1/-0 ) else lu.assertIsMinusInf( 1/-0 ) end end function TestLuaUnitAssertions:test_assertNotIsInf() -- not inf lu.assertNotIsInf( "hi there!") lu.assertNotIsInf( nil) lu.assertNotIsInf( {}) lu.assertNotIsInf( {1,2,3}) lu.assertNotIsInf( {1}) lu.assertNotIsInf( coroutine.create( function(v) local y=v+1 end ) ) -- not inf lu.assertNotIsInf( 0 ) lu.assertNotIsInf( 1 ) lu.assertNotIsInf( 0 / 0) -- NaN lu.assertNotIsInf( -0 / 0) -- NaN lu.assertNotIsInf( 0 / 1) -- 0.0 -- inf assertFailure( lu.assertNotIsInf, 1 / 0) -- inf assertFailure( lu.assertNotIsInf, math.log(0)) -- -inf assertFailure( lu.assertNotIsInf, math.huge) -- inf assertFailure( lu.assertNotIsInf, math.huge) -- -inf end function TestLuaUnitAssertions:test_assertNotIsPlusInf() -- not inf lu.assertNotIsPlusInf( "hi there!") lu.assertNotIsPlusInf( nil) lu.assertNotIsPlusInf( {}) lu.assertNotIsPlusInf( {1,2,3}) lu.assertNotIsPlusInf( {1}) lu.assertNotIsPlusInf( coroutine.create( function(v) local y=v+1 end ) ) lu.assertNotIsPlusInf( 0 ) lu.assertNotIsPlusInf( 1 ) lu.assertNotIsPlusInf( 0 / 0) -- NaN lu.assertNotIsPlusInf( -0 / 0) -- NaN lu.assertNotIsPlusInf( 0 / 1) -- 0.0 lu.assertNotIsPlusInf( math.log(0)) -- -inf lu.assertNotIsPlusInf( -math.huge) -- -inf -- inf assertFailure( lu.assertNotIsPlusInf, 1 / 0) -- inf assertFailure( lu.assertNotIsPlusInf, math.huge) -- inf end function TestLuaUnitAssertions:test_assertNotIsMinusInf() -- not inf lu.assertNotIsMinusInf( "hi there!") lu.assertNotIsMinusInf( nil) lu.assertNotIsMinusInf( {}) lu.assertNotIsMinusInf( {1,2,3}) lu.assertNotIsMinusInf( {1}) lu.assertNotIsMinusInf( coroutine.create( function(v) local y=v+1 end ) ) lu.assertNotIsMinusInf( 0 ) lu.assertNotIsMinusInf( 1 ) lu.assertNotIsMinusInf( 0 / 0) -- NaN lu.assertNotIsMinusInf( -0 / 0) -- NaN lu.assertNotIsMinusInf( 0 / 1) -- 0.0 lu.assertNotIsMinusInf( -math.log(0)) -- inf lu.assertNotIsMinusInf( math.huge) -- inf -- inf assertFailure( lu.assertNotIsMinusInf, math.log(0)) -- -inf assertFailure( lu.assertNotIsMinusInf, -1 / 0) -- -inf assertFailure( lu.assertNotIsMinusInf, -math.huge) -- -inf end -- enable it only for debugging --[[ function Xtest_printHandlingOfZeroAndInf() local inf = 1/0 print( ' inf = ' .. inf ) print( '-inf = ' .. -inf ) print( ' 1/inf = ' .. 1/inf ) print( '-1/inf = ' .. -1/inf ) print( ' 1/-inf = ' .. 1/-inf ) print( '-1/-inf = ' .. -1/-inf ) print() print( ' 1/-0 = ' .. 1/-0 ) print() print( ' -0 = ' .. -0 ) print( ' 0/-1 = ' .. 0/-1 ) print( ' 0*-1 = ' .. 0*-1 ) print( '-0/-1 = ' .. -0/-1 ) print( '-0*-1 = ' .. -0*-1 ) print( '(-0)/-1 = ' .. (-0)/-1 ) print( ' 1/(0/-1) = ' .. 1/(0/-1) ) print( ' 1/(-0/-1) = ' .. 1/(-0/-1) ) print( '-1/(0/-1) = ' .. -1/(0/-1) ) print( '-1/(-0/-1) = ' .. -1/(-0/-1) ) print() local minusZero = -1 / (1/0) print( 'minusZero = -1 / (1/0)' ) print( 'minusZero = '..minusZero) print( ' 1/minusZero = ' .. 1/minusZero ) print() print( 'minusZero/-1 = ' .. minusZero/-1 ) print( 'minusZero*-1 = ' .. minusZero*-1 ) print( ' 1/(minusZero/-1) = ' .. 1/(minusZero/-1) ) print( '-1/(minusZero/-1) = ' .. -1/(minusZero/-1) ) end ]] --[[ #### Important note when dealing with -0 and infinity #### 1. Dealing with infinity is consistent, the only difference is whether the resulting 0 is integer or float Lua 5.3: dividing by infinity yields float 0 With inf = 1/0: -inf = -inf 1/inf = 0.0 -1/inf = -0.0 1/-inf = -0.0 -1/-inf = 0.0 Lua 5.2 and 5.1 and luajit: dividing by infinity yields integer 0 -inf =-1.#INF 1/inf = 0 -1/inf = -0 1/-inf = -0 -1/-inf = 0 2. Dealing with minus 0 is totally inconsistent mathematically and accross lua versions if you use the syntax -0. It works correctly if you create the value by minusZero = -1 / (1/0) Enable the function above to see the extent of the damage of -0 : Lua 5.1: * -0 is consistently considered as 0 * 0 multipllied or diveded by -1 is still 0 * -0 multipllied or diveded by -1 is still 0 Lua 5.2 and LuaJIT: * -0 is consistently -0 * 0 multipllied or diveded by -1 is correctly -0 * -0 multipllied or diveded by -1 is correctly 0 Lua 5.3: * -0 is consistently considered as 0 * 0 multipllied by -1 is correctly -0 but divided by -1 yields 0 * -0 multipllied by -1 is 0 but diveded by -1 is -0 ]] function TestLuaUnitAssertions:test_assertIsPlusZero() assertFailure(lu.assertIsPlusZero, "hi there!") assertFailure(lu.assertIsPlusZero, nil) assertFailure(lu.assertIsPlusZero, {}) assertFailure(lu.assertIsPlusZero, {1,2,3}) assertFailure(lu.assertIsPlusZero, {1}) assertFailure(lu.assertIsPlusZero, coroutine.create( function(v) local y=v+1 end ) ) local inf = 1/0 assertFailure(lu.assertIsPlusZero, 1 ) assertFailure(lu.assertIsPlusZero, 0 / 0) -- NaN assertFailure(lu.assertIsPlusZero, -0 / 0) -- NaN assertFailure(lu.assertIsPlusZero, math.log(0)) -- inf assertFailure(lu.assertIsPlusZero, math.huge) -- inf assertFailure(lu.assertIsPlusZero, -math.huge) -- -inf assertFailure(lu.assertIsPlusZero, -1/inf) -- -0.0 lu.assertIsPlusZero( 0 / 1) lu.assertIsPlusZero( 0 ) lu.assertIsPlusZero( 1/inf ) -- behavior with -0 is lua version dependant, see note above if lu._LUAVERSION ~= "Lua 5.2" and lu._LUAVERSION:sub(1,6) ~= "LuaJIT" then lu.assertIsPlusZero( -0 ) else assertFailure( lu.assertIsPlusZero, -0 ) end end function TestLuaUnitAssertions:test_assertNotIsPlusZero() -- not plus zero lu.assertNotIsPlusZero( "hi there!") lu.assertNotIsPlusZero( nil) lu.assertNotIsPlusZero( {}) lu.assertNotIsPlusZero( {1,2,3}) lu.assertNotIsPlusZero( {1}) lu.assertNotIsPlusZero( coroutine.create( function(v) local y=v+1 end ) ) local inf = 1/0 lu.assertNotIsPlusZero( 1 ) lu.assertNotIsPlusZero( 0 / 0) -- NaN lu.assertNotIsPlusZero( -0 / 0) -- NaN lu.assertNotIsPlusZero( math.log(0)) -- inf lu.assertNotIsPlusZero( math.huge) -- inf lu.assertNotIsPlusZero( -math.huge) -- -inf lu.assertNotIsPlusZero( -1/inf ) -- -0.0 -- plus zero assertFailure( lu.assertNotIsPlusZero, 0 / 1) assertFailure( lu.assertNotIsPlusZero, 0 ) assertFailure( lu.assertNotIsPlusZero, 1/inf ) -- behavior with -0 is lua version dependant, see note above if lu._LUAVERSION ~= "Lua 5.2" and lu._LUAVERSION:sub(1,6) ~= "LuaJIT" then assertFailure( lu.assertNotIsPlusZero, -0 ) else lu.assertNotIsPlusZero( -0 ) end end function TestLuaUnitAssertions:test_assertIsMinusZero() assertFailure(lu.assertIsMinusZero, "hi there!") assertFailure(lu.assertIsMinusZero, nil) assertFailure(lu.assertIsMinusZero, {}) assertFailure(lu.assertIsMinusZero, {1,2,3}) assertFailure(lu.assertIsMinusZero, {1}) assertFailure(lu.assertIsMinusZero, coroutine.create( function(v) local y=v+1 end ) ) local inf = 1/0 assertFailure(lu.assertIsMinusZero, 1 ) assertFailure(lu.assertIsMinusZero, 0 / 0) -- NaN assertFailure(lu.assertIsMinusZero, -0 / 0) -- NaN assertFailure(lu.assertIsMinusZero, math.log(0)) -- inf assertFailure(lu.assertIsMinusZero, math.huge) -- inf assertFailure(lu.assertIsMinusZero, -math.huge) -- -inf assertFailure(lu.assertIsMinusZero, 1/inf) -- -0.0 assertFailure(lu.assertIsMinusZero, 0 ) lu.assertIsMinusZero( -1/inf ) lu.assertIsMinusZero( 1/-inf ) -- behavior with -0 is lua version dependant, see note above if lu._LUAVERSION ~= "Lua 5.2" and lu._LUAVERSION:sub(1,6) ~= "LuaJIT" then assertFailure( lu.assertIsMinusZero, -0 ) else lu.assertIsMinusZero( -0 ) end end function TestLuaUnitAssertions:test_assertNotIsMinusZero() lu.assertNotIsMinusZero( "hi there!") lu.assertNotIsMinusZero( nil) lu.assertNotIsMinusZero( {}) lu.assertNotIsMinusZero( {1,2,3}) lu.assertNotIsMinusZero( {1}) lu.assertNotIsMinusZero( coroutine.create( function(v) local y=v+1 end ) ) local inf = 1/0 lu.assertNotIsMinusZero( 1 ) lu.assertNotIsMinusZero( 0 / 0) -- NaN lu.assertNotIsMinusZero( -0 / 0) -- NaN lu.assertNotIsMinusZero( math.log(0)) -- inf lu.assertNotIsMinusZero( math.huge) -- inf lu.assertNotIsMinusZero( -math.huge) -- -inf lu.assertNotIsMinusZero( 0 ) lu.assertNotIsMinusZero( 1/inf) -- -0.0 assertFailure( lu.assertNotIsMinusZero, -1/inf ) assertFailure( lu.assertNotIsMinusZero, 1/-inf ) -- behavior with -0 is lua version dependant, see note above if lu._LUAVERSION ~= "Lua 5.2" and lu._LUAVERSION:sub(1,6) ~= "LuaJIT" then lu.assertNotIsMinusZero( -0 ) else assertFailure( lu.assertNotIsMinusZero, -0 ) end end function TestLuaUnitAssertions:test_assertIsString() assertFailure(lu.assertIsString, 1) assertFailure(lu.assertIsString, 1.4) lu.assertIsString("hi there!") assertFailure(lu.assertIsString, nil) assertFailure(lu.assertIsString, {}) assertFailure(lu.assertIsString, {1,2,3}) assertFailure(lu.assertIsString, {1}) assertFailure(lu.assertIsString, coroutine.create( function(v) local y=v+1 end ) ) assertFailure(lu.assertIsString, true) end function TestLuaUnitAssertions:test_assertIsTable() assertFailure(lu.assertIsTable, 1) assertFailure(lu.assertIsTable, 1.4) assertFailure(lu.assertIsTable, "hi there!") assertFailure(lu.assertIsTable, nil) lu.assertIsTable({}) lu.assertIsTable({1,2,3}) lu.assertIsTable({1}) assertFailure(lu.assertIsTable, true) assertFailure(lu.assertIsTable, coroutine.create( function(v) local y=v+1 end ) ) end function TestLuaUnitAssertions:test_assertIsBoolean() assertFailure(lu.assertIsBoolean, 1) assertFailure(lu.assertIsBoolean, 1.4) assertFailure(lu.assertIsBoolean, "hi there!") assertFailure(lu.assertIsBoolean, nil) assertFailure(lu.assertIsBoolean, {}) assertFailure(lu.assertIsBoolean, {1,2,3}) assertFailure(lu.assertIsBoolean, {1}) assertFailure(lu.assertIsBoolean, coroutine.create( function(v) local y=v+1 end ) ) lu.assertIsBoolean(true) lu.assertIsBoolean(false) end function TestLuaUnitAssertions:test_assertIsNil() assertFailure(lu.assertIsNil, 1) assertFailure(lu.assertIsNil, 1.4) assertFailure(lu.assertIsNil, "hi there!") lu.assertIsNil(nil) assertFailure(lu.assertIsNil, {}) assertFailure(lu.assertIsNil, {1,2,3}) assertFailure(lu.assertIsNil, {1}) assertFailure(lu.assertIsNil, false) assertFailure(lu.assertIsNil, coroutine.create( function(v) local y=v+1 end ) ) end function TestLuaUnitAssertions:test_assertIsFunction() local f = function() return true end assertFailure(lu.assertIsFunction, 1) assertFailure(lu.assertIsFunction, 1.4) assertFailure(lu.assertIsFunction, "hi there!") assertFailure(lu.assertIsFunction, nil) assertFailure(lu.assertIsFunction, {}) assertFailure(lu.assertIsFunction, {1,2,3}) assertFailure(lu.assertIsFunction, {1}) assertFailure(lu.assertIsFunction, false) assertFailure(lu.assertIsFunction, coroutine.create( function(v) local y=v+1 end ) ) lu.assertIsFunction(f) end function TestLuaUnitAssertions:test_assertIsThread() assertFailure(lu.assertIsThread, 1) assertFailure(lu.assertIsThread, 1.4) assertFailure(lu.assertIsThread, "hi there!") assertFailure(lu.assertIsThread, nil) assertFailure(lu.assertIsThread, {}) assertFailure(lu.assertIsThread, {1,2,3}) assertFailure(lu.assertIsThread, {1}) assertFailure(lu.assertIsThread, false) assertFailure(lu.assertIsThread, function(v) local y=v+1 end ) lu.assertIsThread(coroutine.create( function(v) local y=v+1 end ) ) end function TestLuaUnitAssertions:test_assertIsUserdata() assertFailure(lu.assertIsUserdata, 1) assertFailure(lu.assertIsUserdata, 1.4) assertFailure(lu.assertIsUserdata, "hi there!") assertFailure(lu.assertIsUserdata, nil) assertFailure(lu.assertIsUserdata, {}) assertFailure(lu.assertIsUserdata, {1,2,3}) assertFailure(lu.assertIsUserdata, {1}) assertFailure(lu.assertIsUserdata, false) assertFailure(lu.assertIsUserdata, function(v) local y=v+1 end ) assertFailure(lu.assertIsUserdata, coroutine.create( function(v) local y=v+1 end ) ) end function TestLuaUnitAssertions:test_assertNotIsNumber() assertFailure(lu.assertNotIsNumber, 1 ) assertFailure(lu.assertNotIsNumber, 1.4 ) lu.assertNotIsNumber( "hi there!") lu.assertNotIsNumber( nil) lu.assertNotIsNumber( {}) lu.assertNotIsNumber( {1,2,3}) lu.assertNotIsNumber( {1}) lu.assertNotIsNumber( coroutine.create( function(v) local y=v+1 end ) ) lu.assertNotIsNumber( true) end function TestLuaUnitAssertions:test_assertNotIsNaN() lu.assertNotIsNaN( "hi there!" ) lu.assertNotIsNaN( nil ) lu.assertNotIsNaN( {} ) lu.assertNotIsNaN( {1,2,3} ) lu.assertNotIsNaN( {1} ) lu.assertNotIsNaN( coroutine.create( function(v) local y=v+1 end ) ) assertFailure(lu.assertNotIsNaN, 0 / 0) assertFailure(lu.assertNotIsNaN, -0 / 0) assertFailure(lu.assertNotIsNaN, 0 / -0) assertFailure(lu.assertNotIsNaN, -0 / -0) local inf = math.huge assertFailure(lu.assertNotIsNaN, inf / inf) assertFailure(lu.assertNotIsNaN, -inf / inf) assertFailure(lu.assertNotIsNaN, inf / -inf) assertFailure(lu.assertNotIsNaN, -inf / -inf) assertFailure(lu.assertNotIsNaN, inf - inf) assertFailure(lu.assertNotIsNaN, (-inf) + inf) assertFailure(lu.assertNotIsNaN, inf + (-inf)) assertFailure(lu.assertNotIsNaN, (-inf) - (-inf)) assertFailure(lu.assertNotIsNaN, 0 * inf) assertFailure(lu.assertNotIsNaN, -0 * inf) assertFailure(lu.assertNotIsNaN, 0 * -inf) assertFailure(lu.assertNotIsNaN, -0 * -inf) assertFailure(lu.assertNotIsNaN, math.sqrt(-1)) if lu._LUAVERSION == "Lua 5.1" or lu._LUAVERSION == "Lua 5.2" then -- Lua 5.3 will complain/error "bad argument #2 to 'fmod' (zero)" assertFailure(lu.assertNotIsNaN, math.fmod(1, 0)) assertFailure(lu.assertNotIsNaN, math.fmod(1, -0)) end assertFailure(lu.assertNotIsNaN, math.fmod(inf, 1)) assertFailure(lu.assertNotIsNaN, math.fmod(-inf, 1)) lu.assertNotIsNaN( 0 / 1 ) -- 0.0 lu.assertNotIsNaN( 1 / 0 ) -- inf end function TestLuaUnitAssertions:test_assertNotIsInf() lu.assertNotIsInf( "hi there!" ) lu.assertNotIsInf( nil) lu.assertNotIsInf( {}) lu.assertNotIsInf( {1,2,3}) lu.assertNotIsInf( {1}) lu.assertNotIsInf( coroutine.create( function(v) local y=v+1 end ) ) lu.assertNotIsInf( 0 / 0 ) -- NaN lu.assertNotIsInf( 0 / 1 ) -- 0.0 assertFailure(lu.assertNotIsInf, 1 / 0 ) assertFailure(lu.assertNotIsInf, math.log(0) ) assertFailure(lu.assertNotIsInf, math.huge ) assertFailure(lu.assertNotIsInf, -math.huge ) end function TestLuaUnitAssertions:test_assertNotIsString() lu.assertNotIsString( 1) lu.assertNotIsString( 1.4) assertFailure( lu.assertNotIsString, "hi there!") lu.assertNotIsString( nil) lu.assertNotIsString( {}) lu.assertNotIsString( {1,2,3}) lu.assertNotIsString( {1}) lu.assertNotIsString( coroutine.create( function(v) local y=v+1 end ) ) lu.assertNotIsString( true) end function TestLuaUnitAssertions:test_assertNotIsTable() lu.assertNotIsTable( 1) lu.assertNotIsTable( 1.4) lu.assertNotIsTable( "hi there!") lu.assertNotIsTable( nil) assertFailure( lu.assertNotIsTable, {}) assertFailure( lu.assertNotIsTable, {1,2,3}) assertFailure( lu.assertNotIsTable, {1}) lu.assertNotIsTable( true) lu.assertNotIsTable( coroutine.create( function(v) local y=v+1 end ) ) end function TestLuaUnitAssertions:test_assertNotIsBoolean() lu.assertNotIsBoolean( 1) lu.assertNotIsBoolean( 1.4) lu.assertNotIsBoolean( "hi there!") lu.assertNotIsBoolean( nil) lu.assertNotIsBoolean( {}) lu.assertNotIsBoolean( {1,2,3}) lu.assertNotIsBoolean( {1}) lu.assertNotIsBoolean( coroutine.create( function(v) local y=v+1 end ) ) assertFailure( lu.assertNotIsBoolean, true) assertFailure( lu.assertNotIsBoolean, false) end function TestLuaUnitAssertions:test_assertNotIsNil() lu.assertNotIsNil( 1) lu.assertNotIsNil( 1.4) lu.assertNotIsNil( "hi there!") assertFailure( lu.assertNotIsNil, nil) lu.assertNotIsNil( {}) lu.assertNotIsNil( {1,2,3}) lu.assertNotIsNil( {1}) lu.assertNotIsNil( false) lu.assertNotIsNil( coroutine.create( function(v) local y=v+1 end ) ) end function TestLuaUnitAssertions:test_assertNotIsFunction() local f = function() return true end lu.assertNotIsFunction( 1) lu.assertNotIsFunction( 1.4) lu.assertNotIsFunction( "hi there!") lu.assertNotIsFunction( nil) lu.assertNotIsFunction( {}) lu.assertNotIsFunction( {1,2,3}) lu.assertNotIsFunction( {1}) lu.assertNotIsFunction( false) lu.assertNotIsFunction( coroutine.create( function(v) local y=v+1 end ) ) assertFailure( lu.assertNotIsFunction, f) end function TestLuaUnitAssertions:test_assertNotIsThread() lu.assertNotIsThread( 1) lu.assertNotIsThread( 1.4) lu.assertNotIsThread( "hi there!") lu.assertNotIsThread( nil) lu.assertNotIsThread( {}) lu.assertNotIsThread( {1,2,3}) lu.assertNotIsThread( {1}) lu.assertNotIsThread( false) lu.assertNotIsThread( function(v) local y=v+1 end ) assertFailure( lu.assertNotIsThread, coroutine.create( function(v) local y=v+1 end ) ) end function TestLuaUnitAssertions:test_assertNotIsUserdata() lu.assertNotIsUserdata( 1) lu.assertNotIsUserdata( 1.4) lu.assertNotIsUserdata( "hi there!") lu.assertNotIsUserdata( nil) lu.assertNotIsUserdata( {}) lu.assertNotIsUserdata( {1,2,3}) lu.assertNotIsUserdata( {1}) lu.assertNotIsUserdata( false) lu.assertNotIsUserdata( function(v) local y=v+1 end ) lu.assertNotIsUserdata( coroutine.create( function(v) local y=v+1 end ) ) end function TestLuaUnitAssertions:test_assertIs() local f = function() return true end local g = function() return true end local t1= {} local t2={1,2} local t3={1,2} local t4= {a=1,{1,2},day="today"} local s1='toto' local s2='toto' local s3='to'..'to' local b1=true local b2=false lu.assertIs(1,1) lu.assertIs(f,f) lu.assertIs('toto', 'toto') lu.assertIs(s1, s2) lu.assertIs(s1, s3) lu.assertIs(t1,t1) lu.assertIs(t4,t4) lu.assertIs(b1, true) lu.assertIs(b2, false) assertFailure(lu.assertIs, 1, 2) assertFailure(lu.assertIs, 1.4, 1) assertFailure(lu.assertIs, "hi there!", "hola") assertFailure(lu.assertIs, nil, 1) assertFailure(lu.assertIs, {}, {}) assertFailure(lu.assertIs, {1,2,3}, f) assertFailure(lu.assertIs, f, g) assertFailure(lu.assertIs, t2,t3 ) assertFailure(lu.assertIs, b2, nil) -- tricky, table with protected metatable local t5 = setmetatable( {1,2}, {__metatable='private'}) local t6 = {1,2} lu.assertIs(t5, t5) assertFailure( lu.assertIs, t5, t6) end function TestLuaUnitAssertions:test_assertNotIs() local f = function() return true end local g = function() return true end local t1= {} local t2={1,2} local t3={1,2} local t4= {a=1,{1,2},day="today"} local s1='toto' local s2='toto' local b1=true local b2=false assertFailure( lu.assertNotIs, 1,1 ) assertFailure( lu.assertNotIs, f,f ) assertFailure( lu.assertNotIs, t1,t1 ) assertFailure( lu.assertNotIs, t4,t4) assertFailure( lu.assertNotIs, s1,s2 ) assertFailure( lu.assertNotIs, 'toto', 'toto' ) assertFailure( lu.assertNotIs, b1, true ) assertFailure( lu.assertNotIs, b2, false ) lu.assertNotIs(1, 2) lu.assertNotIs(1.4, 1) lu.assertNotIs("hi there!", "hola") lu.assertNotIs(nil, 1) lu.assertNotIs({}, {}) lu.assertNotIs({1,2,3}, f) lu.assertNotIs(f, g) lu.assertNotIs(t2,t3) lu.assertNotIs(b1, false) lu.assertNotIs(b2, true) lu.assertNotIs(b2, nil) end function TestLuaUnitAssertions:test_assertTableNum() lu.assertEquals( 3, 3 ) lu.assertNotEquals( 3, 4 ) lu.assertEquals( {3}, {3} ) lu.assertNotEquals( {3}, 3 ) lu.assertNotEquals( {3}, {4} ) lu.assertEquals( {x=1}, {x=1} ) lu.assertNotEquals( {x=1}, {x=2} ) lu.assertNotEquals( {x=1}, {y=1} ) end function TestLuaUnitAssertions:test_assertTableStr() lu.assertEquals( '3', '3' ) lu.assertNotEquals( '3', '4' ) lu.assertEquals( {'3'}, {'3'} ) lu.assertNotEquals( {'3'}, '3' ) lu.assertNotEquals( {'3'}, {'4'} ) lu.assertEquals( {x='1'}, {x='1'} ) lu.assertNotEquals( {x='1'}, {x='2'} ) lu.assertNotEquals( {x='1'}, {y='1'} ) end function TestLuaUnitAssertions:test_assertTableLev2() lu.assertEquals( {x={'a'}}, {x={'a'}} ) lu.assertNotEquals( {x={'a'}}, {x={'b'}} ) lu.assertNotEquals( {x={'a'}}, {z={'a'}} ) lu.assertEquals( {{x=1}}, {{x=1}} ) lu.assertNotEquals( {{x=1}}, {{y=1}} ) lu.assertEquals( {{x='a'}}, {{x='a'}} ) lu.assertNotEquals( {{x='a'}}, {{x='b'}} ) end function TestLuaUnitAssertions:test_assertTableList() lu.assertEquals( {3,4,5}, {3,4,5} ) lu.assertNotEquals( {3,4,5}, {3,4,6} ) lu.assertNotEquals( {3,4,5}, {3,5,4} ) lu.assertEquals( {3,4,x=5}, {3,4,x=5} ) lu.assertNotEquals( {3,4,x=5}, {3,4,x=6} ) lu.assertNotEquals( {3,4,x=5}, {3,x=4,5} ) lu.assertNotEquals( {3,4,5}, {2,3,4,5} ) lu.assertNotEquals( {3,4,5}, {3,2,4,5} ) lu.assertNotEquals( {3,4,5}, {3,4,5,6} ) end function TestLuaUnitAssertions:test_assertTableNil() lu.assertEquals( {3,4,5}, {3,4,5} ) lu.assertNotEquals( {3,4,5}, {nil,3,4,5} ) lu.assertNotEquals( {3,4,5}, {nil,4,5} ) lu.assertEquals( {3,4,5}, {3,4,5,nil} ) -- lua quirk lu.assertNotEquals( {3,4,5}, {3,4,nil} ) lu.assertNotEquals( {3,4,5}, {3,nil,5} ) lu.assertNotEquals( {3,4,5}, {3,4,nil,5} ) end function TestLuaUnitAssertions:test_assertTableNilFront() lu.assertEquals( {nil,4,5}, {nil,4,5} ) lu.assertNotEquals( {nil,4,5}, {nil,44,55} ) lu.assertEquals( {nil,'4','5'}, {nil,'4','5'} ) lu.assertNotEquals( {nil,'4','5'}, {nil,'44','55'} ) lu.assertEquals( {nil,{4,5}}, {nil,{4,5}} ) lu.assertNotEquals( {nil,{4,5}}, {nil,{44,55}} ) lu.assertNotEquals( {nil,{4}}, {nil,{44}} ) lu.assertEquals( {nil,{x=4,5}}, {nil,{x=4,5}} ) lu.assertEquals( {nil,{x=4,5}}, {nil,{5,x=4}} ) -- lua quirk lu.assertEquals( {nil,{x=4,y=5}}, {nil,{y=5,x=4}} ) -- lua quirk lu.assertNotEquals( {nil,{x=4,5}}, {nil,{y=4,5}} ) end function TestLuaUnitAssertions:test_assertTableAdditions() lu.assertEquals( {1,2,3}, {1,2,3} ) lu.assertNotEquals( {1,2,3}, {1,2,3,4} ) lu.assertNotEquals( {1,2,3,4}, {1,2,3} ) lu.assertEquals( {1,x=2,3}, {1,x=2,3} ) lu.assertNotEquals( {1,x=2,3}, {1,x=2,3,y=4} ) lu.assertNotEquals( {1,x=2,3,y=4}, {1,x=2,3} ) end function TestLuaUnitAssertions:test_assertTableProtectedMt() -- tricky, table with protected metatable local t1 = setmetatable( {1,2}, {__metatable='private'}) local t2 = {1,2} local t3 = setmetatable( {1,2}, {__metatable='private'}) lu.assertEquals(t1, t2) lu.assertEquals(t2, t3) end local function assertFailureEquals(msg, ...) lu.assertErrorMsgEquals(lu.FAILURE_PREFIX .. msg, ...) end local function assertFailureMatches(msg, ...) lu.assertErrorMsgMatches(lu.FAILURE_PREFIX .. msg, ...) end local function assertFailureContains(msg, ...) lu.assertErrorMsgContains(lu.FAILURE_PREFIX .. msg, ...) end TestLuaUnitAssertionsError = {} function TestLuaUnitAssertionsError:setUp() self.f = function ( v ) local y = v + 1 end self.f_with_error = function (v) local y = v + 2 error('This is an error', 2) end self.f_with_table_error = function (v) local y = v + 2 local ts = { __tostring = function() return 'This table has error!' end } -- the error message is a table which converts to string error( setmetatable( { this_table="has error" }, ts ) ) end end function TestLuaUnitAssertionsError:test_assertError() local x = 1 -- f_with_error generates an error local has_error = not pcall( self.f_with_error, x ) lu.assertEquals( has_error, true ) -- f does not generate an error has_error = not pcall( self.f, x ) lu.assertEquals( has_error, false ) -- lu.assertError is happy with f_with_error lu.assertError( self.f_with_error, x ) -- lu.assertError is unhappy with f assertFailureEquals( "Expected an error when calling function but no error generated", lu.assertError, self.f, x ) -- multiple arguments local function f_with_multi_arguments(a,b,c) if a == b and b == c then return end error("three arguments not equal") end lu.assertError( f_with_multi_arguments, 1, 1, 3 ) lu.assertError( f_with_multi_arguments, 1, 3, 1 ) lu.assertError( f_with_multi_arguments, 3, 1, 1 ) assertFailureEquals( "Expected an error when calling function but no error generated", lu.assertError, f_with_multi_arguments, 1, 1, 1 ) -- error generated as table lu.assertError( self.f_with_table_error, 1 ) end function TestLuaUnitAssertionsError:test_assertErrorMsgContains() local x = 1 assertFailure( lu.assertErrorMsgContains, 'toto', self.f, x ) lu.assertErrorMsgContains( 'is an err', self.f_with_error, x ) lu.assertErrorMsgContains( 'This is an error', self.f_with_error, x ) assertFailure( lu.assertErrorMsgContains, ' This is an error', self.f_with_error, x ) assertFailure( lu.assertErrorMsgContains, 'This .. an error', self.f_with_error, x ) lu.assertErrorMsgContains("50", function() error(500) end) -- error message is a table which converts to a string lu.assertErrorMsgContains( 'This table has error', self.f_with_table_error, 1 ) end function TestLuaUnitAssertionsError:test_assertErrorMsgEquals() local x = 1 assertFailure( lu.assertErrorMsgEquals, 'toto', self.f, x ) assertFailure( lu.assertErrorMsgEquals, 'is an err', self.f_with_error, x ) -- expected string, receive string lu.assertErrorMsgEquals( 'This is an error', self.f_with_error, x ) -- expected table, receive table lu.assertErrorMsgEquals({1,2,3,4}, function() error({1,2,3,4}) end) -- expected complex table, receive complex table lu.assertErrorMsgEquals({ details = {1,2,3,4}, id = 10, }, function() error({ details = {1,2,3,4}, id = 10, }) end) -- expected string, receive number converted to string lu.assertErrorMsgEquals("500", function() error(500, 2) end) -- one space added at the beginning assertFailure( lu.assertErrorMsgEquals, ' This is an error', self.f_with_error, x ) -- pattern does not work assertFailure( lu.assertErrorMsgEquals, 'This .. an error', self.f_with_error, x ) -- expected string, receive table which converts to string lu.assertErrorMsgEquals( "This table has error!", self.f_with_table_error, x) -- expected table, no error generated assertFailure( lu.assertErrorMsgEquals, { 1 }, function( v ) return "{ 1 }" end, 33 ) -- expected table, error generated as string, no match assertFailure( lu.assertErrorMsgEquals, { 1 }, function( v ) error( "{ 1 }" ) end, 33 ) end function TestLuaUnitAssertionsError:test_assertErrorMsgMatches() local x = 1 assertFailure( lu.assertErrorMsgMatches, 'toto', self.f, x ) assertFailure( lu.assertErrorMsgMatches, 'is an err', self.f_with_error, x ) lu.assertErrorMsgMatches( 'This is an error', self.f_with_error, x ) lu.assertErrorMsgMatches( 'This is .. error', self.f_with_error, x ) lu.assertErrorMsgMatches(".*500$", function() error(500, 2) end) lu.assertErrorMsgMatches("This .* has error!", self.f_with_table_error, 33 ) -- one space added to cause failure assertFailure( lu.assertErrorMsgMatches, ' This is an error', self.f_with_error, x ) assertFailure( lu.assertErrorMsgMatches, "This", self.f_with_table_error, 33 ) end ------------------------------------------------------------------ -- -- Failure message tests -- ------------------------------------------------------------------ TestLuaUnitErrorMsg = { __class__ = 'TestLuaUnitErrorMsg' } function TestLuaUnitErrorMsg:setUp() self.old_ORDER_ACTUAL_EXPECTED = lu.ORDER_ACTUAL_EXPECTED self.old_PRINT_TABLE_REF_IN_ERROR_MSG = lu.PRINT_TABLE_REF_IN_ERROR_MSG end function TestLuaUnitErrorMsg:tearDown() lu.ORDER_ACTUAL_EXPECTED = self.old_ORDER_ACTUAL_EXPECTED lu.PRINT_TABLE_REF_IN_ERROR_MSG = self.old_PRINT_TABLE_REF_IN_ERROR_MSG end function TestLuaUnitErrorMsg:test_adjust_err_msg_with_iter() local err_msg, status --------------- FAIL --------------------- -- file-line info, strip failure prefix, no iteration info err_msg, status = lu.adjust_err_msg_with_iter( '.\\test\\test_luaunit.lua:2247: LuaUnit test FAILURE: Expected an error when calling function but no error generated', nil ) lu.assertEquals( { err_msg, status }, { '.\\test\\test_luaunit.lua:2247: Expected an error when calling function but no error generated', lu.NodeStatus.FAIL } ) -- file-line info, strip failure prefix, with iteration info err_msg, status = lu.adjust_err_msg_with_iter( '.\\test\\test_luaunit.lua:2247: LuaUnit test FAILURE: Expected an error when calling function but no error generated', 'iteration 33' ) lu.assertEquals( { err_msg, status }, { '.\\test\\test_luaunit.lua:2247: iteration 33, Expected an error when calling function but no error generated', lu.NodeStatus.FAIL } ) -- no file-line info, strip failure prefix, no iteration info err_msg, status = lu.adjust_err_msg_with_iter( 'LuaUnit test FAILURE: Expected an error when calling function but no error generated', nil ) lu.assertEquals( { err_msg, status }, { 'Expected an error when calling function but no error generated', lu.NodeStatus.FAIL } ) -- no file-line info, strip failure prefix, with iteration info err_msg, status = lu.adjust_err_msg_with_iter( 'LuaUnit test FAILURE: Expected an error when calling function but no error generated', 'iteration 33' ) lu.assertEquals( { err_msg, status }, { 'iteration 33, Expected an error when calling function but no error generated', lu.NodeStatus.FAIL } ) --------------- ERROR --------------------- -- file-line info, pure error, no iteration info, do nothing err_msg, status = lu.adjust_err_msg_with_iter( '.\\test\\test_luaunit.lua:2723: teardown error', nil ) lu.assertEquals( { err_msg, status }, { '.\\test\\test_luaunit.lua:2723: teardown error', lu.NodeStatus.ERROR } ) -- file-line info, pure error, add iteration info err_msg, status = lu.adjust_err_msg_with_iter( '.\\test\\test_luaunit.lua:2723: teardown error', 'iteration 33' ) lu.assertEquals( { err_msg, status }, { '.\\test\\test_luaunit.lua:2723: iteration 33, teardown error', lu.NodeStatus.ERROR } ) -- no file-line info, pure error, no iteration info, do nothing err_msg, status = lu.adjust_err_msg_with_iter( 'teardown error', nil ) lu.assertEquals( { err_msg, status }, { 'teardown error', lu.NodeStatus.ERROR } ) -- no file-line info, pure error, add iteration info err_msg, status = lu.adjust_err_msg_with_iter( 'teardown error', 'iteration 33' ) lu.assertEquals( { err_msg, status }, { 'iteration 33, teardown error', lu.NodeStatus.ERROR } ) --------------- PASS --------------------- -- file-line info, success, return empty error message err_msg, status = lu.adjust_err_msg_with_iter( '.\\test\\test_luaunit.lua:2247: LuaUnit test SUCCESS: the test did actually work !', nil ) lu.assertEquals( { err_msg, status }, { nil, lu.NodeStatus.SUCCESS } ) -- file-line info, success, return empty error message, even with iteration err_msg, status = lu.adjust_err_msg_with_iter( '.\\test\\test_luaunit.lua:2247: LuaUnit test SUCCESS: the test did actually work !', 'iteration 33' ) lu.assertEquals( { err_msg, status }, { nil, lu.NodeStatus.SUCCESS } ) -- no file-line info, success, return empty error message err_msg, status = lu.adjust_err_msg_with_iter( 'LuaUnit test SUCCESS: the test did actually work !', nil ) lu.assertEquals( { err_msg, status }, { nil, lu.NodeStatus.SUCCESS } ) -- no file-line info, success, return empty error message, even with iteration err_msg, status = lu.adjust_err_msg_with_iter( 'LuaUnit test SUCCESS: the test did actually work !', 'iteration 33' ) lu.assertEquals( { err_msg, status }, { nil, lu.NodeStatus.SUCCESS } ) end function TestLuaUnitErrorMsg:test_assertEqualsMsg() assertFailureEquals( 'expected: 2, actual: 1', lu.assertEquals, 1, 2 ) assertFailureEquals( 'expected: "exp"\nactual: "act"', lu.assertEquals, 'act', 'exp' ) assertFailureEquals( 'expected: \n"exp\npxe"\nactual: \n"act\ntca"', lu.assertEquals, 'act\ntca', 'exp\npxe' ) assertFailureEquals( 'expected: true, actual: false', lu.assertEquals, false, true ) assertFailureEquals( 'expected: 1.2, actual: 1', lu.assertEquals, 1, 1.2) assertFailureMatches( 'expected: {1, 2}\nactual: {2, 1}', lu.assertEquals, {2,1}, {1,2} ) assertFailureMatches( 'expected: {one=1, two=2}\nactual: {3, 2, 1}', lu.assertEquals, {3,2,1}, {one=1,two=2} ) assertFailureEquals( 'expected: 2, actual: nil', lu.assertEquals, nil, 2 ) assertFailureEquals( 'toto\nexpected: 2, actual: nil', lu.assertEquals, nil, 2, 'toto' ) end function TestLuaUnitErrorMsg:test_assertEqualsOrderReversedMsg() lu.ORDER_ACTUAL_EXPECTED = false assertFailureEquals( 'expected: 1, actual: 2', lu.assertEquals, 1, 2 ) assertFailureEquals( 'expected: "act"\nactual: "exp"', lu.assertEquals, 'act', 'exp' ) end function TestLuaUnitErrorMsg:test_assertAlmostEqualsMsg() assertFailureEquals('Values are not almost equal\nActual: 2, expected: 1, delta 1 above margin of 0.1', lu.assertAlmostEquals, 2, 1, 0.1 ) assertFailureEquals('toto\nValues are not almost equal\nActual: 2, expected: 1, delta 1 above margin of 0.1', lu.assertAlmostEquals, 2, 1, 0.1, 'toto' ) end function TestLuaUnitErrorMsg:test_assertAlmostEqualsOrderReversedMsg() lu.ORDER_ACTUAL_EXPECTED = false assertFailureEquals('Values are not almost equal\nActual: 1, expected: 2, delta 1 above margin of 0.1', lu.assertAlmostEquals, 2, 1, 0.1 ) end function TestLuaUnitErrorMsg:test_assertNotAlmostEqualsMsg() -- single precision math Lua won't output an "exact" delta (0.1) here, so we do a partial match assertFailureContains('Values are almost equal\nActual: 1.1, expected: 1, delta 0.1 below margin of 0.2', lu.assertNotAlmostEquals, 1.1, 1, 0.2 ) assertFailureContains('toto\nValues are almost equal\nActual: 1.1, expected: 1, delta 0.1 below margin of 0.2', lu.assertNotAlmostEquals, 1.1, 1, 0.2, 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotAlmostEqualsOrderReversedMsg() -- single precision math Lua won't output an "exact" delta (0.1) here, so we do a partial match lu.ORDER_ACTUAL_EXPECTED = false assertFailureContains('Values are almost equal\nActual: 1, expected: 1.1, delta 0.1 below margin of 0.2', lu.assertNotAlmostEquals, 1.1, 1, 0.2 ) end function TestLuaUnitErrorMsg:test_assertNotEqualsMsg() assertFailureEquals( 'Received the not expected value: 1', lu.assertNotEquals, 1, 1 ) assertFailureMatches( 'Received the not expected value: {1, 2}', lu.assertNotEquals, {1,2}, {1,2} ) assertFailureEquals( 'Received the not expected value: nil', lu.assertNotEquals, nil, nil ) assertFailureEquals( 'toto\nReceived the not expected value: 1', lu.assertNotEquals, 1, 1, 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotEqualsOrderReversedMsg() lu.ORDER_ACTUAL_EXPECTED = false assertFailureEquals( 'Received the not expected value: 1', lu.assertNotEquals, 1, 1 ) end function TestLuaUnitErrorMsg:test_assertTrueFalse() assertFailureEquals( 'expected: true, actual: false', lu.assertTrue, false ) assertFailureEquals( 'expected: true, actual: nil', lu.assertTrue, nil ) assertFailureEquals( 'expected: false, actual: true', lu.assertFalse, true ) assertFailureEquals( 'expected: false, actual: nil', lu.assertFalse, nil ) assertFailureEquals( 'expected: false, actual: 0', lu.assertFalse, 0) assertFailureMatches( 'expected: false, actual: {}', lu.assertFalse, {}) assertFailureEquals( 'expected: false, actual: "abc"', lu.assertFalse, 'abc') assertFailureContains( 'expected: false, actual: function', lu.assertFalse, function () end ) assertFailureEquals( 'toto\nexpected: true, actual: false', lu.assertTrue, false, 'toto' ) assertFailureEquals( 'toto\nexpected: false, actual: 0', lu.assertFalse, 0, 'toto') end function TestLuaUnitErrorMsg:test_assertEvalToTrueFalse() assertFailureEquals( 'expected: a value evaluating to true, actual: false', lu.assertEvalToTrue, false ) assertFailureEquals( 'expected: a value evaluating to true, actual: nil', lu.assertEvalToTrue, nil ) assertFailureEquals( 'expected: false or nil, actual: true', lu.assertEvalToFalse, true ) assertFailureEquals( 'expected: false or nil, actual: 0', lu.assertEvalToFalse, 0) assertFailureMatches( 'expected: false or nil, actual: {}', lu.assertEvalToFalse, {}) assertFailureEquals( 'expected: false or nil, actual: "abc"', lu.assertEvalToFalse, 'abc') assertFailureContains( 'expected: false or nil, actual: function', lu.assertEvalToFalse, function () end ) assertFailureEquals( 'toto\nexpected: a value evaluating to true, actual: false', lu.assertEvalToTrue, false, 'toto' ) assertFailureEquals( 'toto\nexpected: false or nil, actual: 0', lu.assertEvalToFalse, 0, 'toto') end function TestLuaUnitErrorMsg:test_assertNil() assertFailureEquals( 'expected: nil, actual: false', lu.assertNil, false ) assertFailureEquals( 'toto\nexpected: nil, actual: false', lu.assertNil, false, 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotNil() assertFailureEquals( 'expected: not nil, actual: nil', lu.assertNotNil, nil ) assertFailureEquals( 'toto\nexpected: not nil, actual: nil', lu.assertNotNil, nil, 'toto' ) end function TestLuaUnitErrorMsg:test_assertStrContains() assertFailureEquals( 'Could not find substring "xxx" in string "abcdef"', lu.assertStrContains, 'abcdef', 'xxx' ) assertFailureEquals( 'Could not find substring "aBc" in string "abcdef"', lu.assertStrContains, 'abcdef', 'aBc' ) assertFailureEquals( 'Could not find substring "xxx" in string ""', lu.assertStrContains, '', 'xxx' ) assertFailureEquals( 'Could not find substring "xxx" in string "abcdef"', lu.assertStrContains, 'abcdef', 'xxx', false ) assertFailureEquals( 'Could not find substring "aBc" in string "abcdef"', lu.assertStrContains, 'abcdef', 'aBc', false ) assertFailureEquals( 'Could not find substring "xxx" in string ""', lu.assertStrContains, '', 'xxx', false ) assertFailureEquals( 'Could not find pattern "xxx" in string "abcdef"', lu.assertStrContains, 'abcdef', 'xxx', true ) assertFailureEquals( 'Could not find pattern "aBc" in string "abcdef"', lu.assertStrContains, 'abcdef', 'aBc', true ) assertFailureEquals( 'Could not find pattern "xxx" in string ""', lu.assertStrContains, '', 'xxx', true ) assertFailureEquals( 'toto\nCould not find pattern "xxx" in string ""', lu.assertStrContains, '', 'xxx', true, 'toto' ) end function TestLuaUnitErrorMsg:test_assertStrIContains() assertFailureEquals( 'Could not find (case insensitively) substring "xxx" in string "abcdef"', lu.assertStrIContains, 'abcdef', 'xxx' ) assertFailureEquals( 'Could not find (case insensitively) substring "xxx" in string ""', lu.assertStrIContains, '', 'xxx' ) assertFailureEquals( 'toto\nCould not find (case insensitively) substring "xxx" in string "abcdef"', lu.assertStrIContains, 'abcdef', 'xxx', 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotStrContains() assertFailureEquals( 'Found the not expected substring "abc" in string "abcdef"', lu.assertNotStrContains, 'abcdef', 'abc' ) assertFailureEquals( 'Found the not expected substring "abc" in string "abcdef"', lu.assertNotStrContains, 'abcdef', 'abc', false ) assertFailureEquals( 'Found the not expected pattern "..." in string "abcdef"', lu.assertNotStrContains, 'abcdef', '...', true) assertFailureEquals( 'toto\nFound the not expected substring "abc" in string "abcdef"', lu.assertNotStrContains, 'abcdef', 'abc', false, 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotStrIContains() assertFailureEquals( 'Found (case insensitively) the not expected substring "aBc" in string "abcdef"', lu.assertNotStrIContains, 'abcdef', 'aBc' ) assertFailureEquals( 'Found (case insensitively) the not expected substring "abc" in string "abcdef"', lu.assertNotStrIContains, 'abcdef', 'abc' ) assertFailureEquals( 'toto\nFound (case insensitively) the not expected substring "abc" in string "abcdef"', lu.assertNotStrIContains, 'abcdef', 'abc', 'toto' ) end function TestLuaUnitErrorMsg:test_assertStrMatches() assertFailureEquals('Could not match pattern "xxx" with string "abcdef"', lu.assertStrMatches, 'abcdef', 'xxx' ) assertFailureEquals('toto\nCould not match pattern "xxx" with string "abcdef"', lu.assertStrMatches, 'abcdef', 'xxx', nil, nil, 'toto' ) end function TestLuaUnitErrorMsg:test_assertIsNumber() assertFailureEquals( 'expected: a number value, actual: type string, value "abc"', lu.assertIsNumber, 'abc' ) assertFailureEquals( 'expected: a number value, actual: nil', lu.assertIsNumber, nil ) assertFailureEquals( 'toto\nexpected: a number value, actual: type string, value "abc"', lu.assertIsNumber, 'abc', 'toto' ) end function TestLuaUnitErrorMsg:test_assertIsString() assertFailureEquals( 'expected: a string value, actual: type number, value 1.2', lu.assertIsString, 1.2 ) assertFailureEquals( 'expected: a string value, actual: nil', lu.assertIsString, nil ) assertFailureEquals( 'toto\nexpected: a string value, actual: nil', lu.assertIsString, nil, 'toto' ) end function TestLuaUnitErrorMsg:test_assertIsTable() assertFailureEquals( 'expected: a table value, actual: type number, value 1.2', lu.assertIsTable, 1.2 ) assertFailureEquals( 'expected: a table value, actual: nil', lu.assertIsTable, nil ) assertFailureEquals( 'toto\nexpected: a table value, actual: nil', lu.assertIsTable, nil, 'toto' ) end function TestLuaUnitErrorMsg:test_assertIsBoolean() assertFailureEquals( 'expected: a boolean value, actual: type number, value 1.2', lu.assertIsBoolean, 1.2 ) assertFailureEquals( 'expected: a boolean value, actual: nil', lu.assertIsBoolean, nil ) assertFailureEquals( 'toto\nexpected: a boolean value, actual: nil', lu.assertIsBoolean, nil, 'toto' ) end function TestLuaUnitErrorMsg:test_assertIsFunction() assertFailureEquals( 'expected: a function value, actual: type number, value 1.2', lu.assertIsFunction, 1.2 ) assertFailureEquals( 'expected: a function value, actual: nil', lu.assertIsFunction, nil ) assertFailureEquals( 'toto\nexpected: a function value, actual: nil', lu.assertIsFunction, nil, 'toto' ) end function TestLuaUnitErrorMsg:test_assertIsThread() assertFailureEquals( 'expected: a thread value, actual: type number, value 1.2', lu.assertIsThread, 1.2 ) assertFailureEquals( 'expected: a thread value, actual: nil', lu.assertIsThread, nil ) assertFailureEquals( 'toto\nexpected: a thread value, actual: nil', lu.assertIsThread, nil, 'toto' ) end function TestLuaUnitErrorMsg:test_assertIsUserdata() assertFailureEquals( 'expected: a userdata value, actual: type number, value 1.2', lu.assertIsUserdata, 1.2 ) assertFailureEquals( 'expected: a userdata value, actual: nil', lu.assertIsUserdata, nil ) assertFailureEquals( 'toto\nexpected: a userdata value, actual: nil', lu.assertIsUserdata, nil, 'toto' ) end function TestLuaUnitErrorMsg:test_assertIsNan() assertFailureEquals( 'expected: NaN, actual: 33', lu.assertIsNaN, 33 ) assertFailureEquals( 'toto\nexpected: NaN, actual: 33', lu.assertIsNaN, 33, 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotIsNan() assertFailureEquals( 'expected: not NaN, actual: NaN', lu.assertNotIsNaN, 0 / 0 ) assertFailureEquals( 'toto\nexpected: not NaN, actual: NaN', lu.assertNotIsNaN, 0 / 0, 'toto' ) end function TestLuaUnitErrorMsg:test_assertIsInf() assertFailureEquals( 'expected: #Inf, actual: 33', lu.assertIsInf, 33 ) assertFailureEquals( 'toto\nexpected: #Inf, actual: 33', lu.assertIsInf, 33, 'toto' ) end function TestLuaUnitErrorMsg:test_assertIsPlusInf() assertFailureEquals( 'expected: #Inf, actual: 33', lu.assertIsPlusInf, 33 ) assertFailureEquals( 'toto\nexpected: #Inf, actual: 33', lu.assertIsPlusInf, 33, 'toto' ) end function TestLuaUnitErrorMsg:test_assertIsMinusInf() assertFailureEquals( 'expected: -#Inf, actual: 33', lu.assertIsMinusInf, 33 ) assertFailureEquals( 'toto\nexpected: -#Inf, actual: 33', lu.assertIsMinusInf, 33, 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotIsInf() assertFailureEquals( 'expected: not infinity, actual: #Inf', lu.assertNotIsInf, 1 / 0 ) assertFailureEquals( 'toto\nexpected: not infinity, actual: -#Inf', lu.assertNotIsInf, -1 / 0, 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotIsPlusInf() assertFailureEquals( 'expected: not #Inf, actual: #Inf', lu.assertNotIsPlusInf, 1 / 0 ) assertFailureEquals( 'toto\nexpected: not #Inf, actual: #Inf', lu.assertNotIsPlusInf, 1 / 0, 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotIsMinusInf() assertFailureEquals( 'expected: not -#Inf, actual: -#Inf', lu.assertNotIsMinusInf, -1 / 0 ) assertFailureEquals( 'toto\nexpected: not -#Inf, actual: -#Inf', lu.assertNotIsMinusInf, -1 / 0, 'toto' ) end function TestLuaUnitErrorMsg:test_assertIsPlusZero() assertFailureEquals( 'expected: +0.0, actual: 33', lu.assertIsPlusZero, 33 ) assertFailureEquals( 'toto\nexpected: +0.0, actual: 33', lu.assertIsPlusZero, 33, 'toto' ) end function TestLuaUnitErrorMsg:test_assertIsMinusZero() assertFailureEquals( 'expected: -0.0, actual: 33', lu.assertIsMinusZero, 33 ) assertFailureEquals( 'toto\nexpected: -0.0, actual: 33', lu.assertIsMinusZero, 33, 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotIsPlusZero() assertFailureEquals( 'expected: not +0.0, actual: +0.0', lu.assertNotIsPlusZero, 0 ) assertFailureEquals( 'toto\nexpected: not +0.0, actual: +0.0', lu.assertNotIsPlusZero, 0, 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotIsMinusZero() local minusZero = -1 / (1/0) assertFailureEquals( 'expected: not -0.0, actual: -0.0', lu.assertNotIsMinusZero, minusZero ) assertFailureEquals( 'toto\nexpected: not -0.0, actual: -0.0', lu.assertNotIsMinusZero, minusZero, 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotIsTrue() assertFailureEquals('expected: not true, actual: true', lu.assertNotIsTrue, true ) assertFailureEquals('toto\nexpected: not true, actual: true', lu.assertNotIsTrue, true, 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotIsFalse() assertFailureEquals('expected: not false, actual: false', lu.assertNotIsFalse, false ) assertFailureEquals('toto\nexpected: not false, actual: false', lu.assertNotIsFalse, false, 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotIsNil() assertFailureEquals( 'expected: not nil, actual: nil', lu.assertNotIsNil, nil ) assertFailureEquals( 'toto\nexpected: not nil, actual: nil', lu.assertNotIsNil, nil, 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotIsNumber() assertFailureEquals( 'expected: not a number type, actual: value 123', lu.assertNotIsNumber, 123 ) assertFailureEquals( 'toto\nexpected: not a number type, actual: value 123', lu.assertNotIsNumber, 123, 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotIsString() assertFailureEquals( 'expected: not a string type, actual: value "abc"', lu.assertNotIsString, "abc" ) assertFailureEquals( 'toto\nexpected: not a string type, actual: value "abc"', lu.assertNotIsString, "abc", 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotIsTable() assertFailureEquals( 'expected: not a table type, actual: value {1, 2, 3}', lu.assertNotIsTable, {1,2,3} ) assertFailureEquals( 'toto\nexpected: not a table type, actual: value {1, 2, 3}', lu.assertNotIsTable, {1,2,3}, 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotIsBoolean() assertFailureEquals( 'expected: not a boolean type, actual: value false', lu.assertNotIsBoolean, false ) assertFailureEquals( 'toto\nexpected: not a boolean type, actual: value false', lu.assertNotIsBoolean, false, 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotIsFunction() assertFailureContains( 'expected: not a function type, actual: value function:', lu.assertNotIsFunction, function() return true end ) assertFailureContains( 'toto\nexpected: not a function type, actual: value function:', lu.assertNotIsFunction, function() return true end, 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotIsThread() assertFailureContains( 'expected: not a thread type, actual: value thread:', lu.assertNotIsThread, coroutine.create( function(v) local y=v+1 end ) ) assertFailureContains( 'toto\nexpected: not a thread type, actual: value thread:', lu.assertNotIsThread, coroutine.create( function(v) local y=v+1 end ), 'toto' ) end --[[ How do you create UserData ? function TestLuaUnitErrorMsg:test_assertIsNotUserdata() assertFailureEquals( 'Not expected: a userdata type, actual: value XXX ???', lu.assertIsNotUserdata, XXX ??? ) end ]] function TestLuaUnitErrorMsg:test_assertIs() assertFailureEquals( 'expected and actual object should not be different\nExpected: 1\nReceived: 2', lu.assertIs, 2, 1 ) assertFailureMatches( 'expected and actual object should not be different\n'.. 'Expected: <'..TABLE_IDX_REF_PAT..'> {1, 2, 3, 4, 5, 6, 7, 8}\n'.. 'Received: <'..TABLE_IDX_REF_PAT..'> {1, 2, 3, 4, 5, 6, 7, 8}', lu.assertIs, {1,2,3,4,5,6,7,8}, {1,2,3,4,5,6,7,8} ) lu.ORDER_ACTUAL_EXPECTED = false assertFailureEquals( 'expected and actual object should not be different\nExpected: 2\nReceived: 1', lu.assertIs, 2, 1 ) assertFailureEquals( 'toto\nexpected and actual object should not be different\nExpected: 2\nReceived: 1', lu.assertIs, 2, 1, 'toto' ) end function TestLuaUnitErrorMsg:test_assertNotIs() local v = {1,2} assertFailureMatches( 'expected and actual object should be different: <'..TABLE_IDX_REF_PAT..'> {1, 2}', lu.assertNotIs, v, v ) lu.ORDER_ACTUAL_EXPECTED = false -- order shouldn't matter here, but let's cover it assertFailureMatches( 'expected and actual object should be different: <'..TABLE_IDX_REF_PAT..'> {1, 2}', lu.assertNotIs, v, v ) assertFailureMatches( 'toto\nexpected and actual object should be different: <'..TABLE_IDX_REF_PAT..'> {1, 2}', lu.assertNotIs, v, v, 'toto' ) end function TestLuaUnitErrorMsg:test_assertItemsEquals() assertFailureMatches('Content of the tables are not identical:\nExpected: {one=2, two=3}\nActual: {1, 2}' , lu.assertItemsEquals, {1,2}, {one=2, two=3} ) assertFailureContains('Content of the tables are not identical' , lu.assertItemsEquals, {}, {1} ) -- actual table empty, = doesn't contain expected value assertFailureContains('Content of the tables are not identical' , lu.assertItemsEquals, nil, 'foobar' ) -- type mismatch assertFailureContains('Content of the tables are not identical' , lu.assertItemsEquals, 'foo', 'bar' ) -- value mismatch assertFailureContains('toto\nContent of the tables are not identical' , lu.assertItemsEquals, 'foo', 'bar', 'toto' ) -- value mismatch end function TestLuaUnitErrorMsg:test_assertError() assertFailureEquals('Expected an error when calling function but no error generated' , lu.assertError, function( v ) local y = v+1 end, 3 ) end function TestLuaUnitErrorMsg:test_assertErrorMsgEquals() assertFailureEquals('No error generated when calling function but expected error: "bla bla bla"' , lu.assertErrorMsgEquals, 'bla bla bla', function( v ) local y = v+1 end, 3 ) assertFailureEquals('Error message expected: "bla bla bla"\n' .. 'Error message received: "toto xxx"\n' , lu.assertErrorMsgEquals, 'bla bla bla', function( v ) error('toto xxx',2) end, 3 ) assertFailureEquals('Error message expected: {1, 2, 3, 4}\nError message received: {1, 2, 3}\n' , lu.assertErrorMsgEquals, {1,2,3,4}, function( v ) error(v) end, {1,2,3}) assertFailureEquals('Error message expected: {details="bla bla bla"}\nError message received: {details="ble ble ble"}\n' , lu.assertErrorMsgEquals, {details="bla bla bla"}, function( v ) error(v) end, {details="ble ble ble"}) end function TestLuaUnitErrorMsg:test_assertErrorMsgContains() assertFailureEquals('No error generated when calling function but expected error containing: "bla bla bla"' , lu.assertErrorMsgContains, 'bla bla bla', function( v ) local y = v+1 end, 3 ) assertFailureEquals('Error message does not contain: "bla bla bla"\nError message received: "toto xxx"\n' , lu.assertErrorMsgContains, 'bla bla bla', function( v ) error('toto xxx',2) end, 3 ) end function TestLuaUnitErrorMsg:test_assertErrorMsgMatches() assertFailureEquals('No error generated when calling function but expected error matching: "bla bla bla"' , lu.assertErrorMsgMatches, 'bla bla bla', function( v ) local y = v+1 end, 3 ) assertFailureEquals('Error message does not match pattern: "bla bla bla"\n' .. 'Error message received: "toto xxx"\n' , lu.assertErrorMsgMatches, 'bla bla bla', function( v ) error('toto xxx',2) end, 3 ) end function TestLuaUnitErrorMsg:test_assertErrorMsgContentEquals() local f = function() error("This is error message") end lu.assertErrorMsgContentEquals("This is error message", f) local f1 = function(v1, v2) error("This is error message") end lu.assertErrorMsgContentEquals("This is error message", f, 1, 2) end function TestLuaUnitErrorMsg:test_printTableWithRef() lu.PRINT_TABLE_REF_IN_ERROR_MSG = true assertFailureMatches( 'Received the not expected value: <'..TABLE_IDX_REF_PAT..'> {1, 2}', lu.assertNotEquals, {1,2}, {1,2} ) -- trigger multiline prettystr assertFailureMatches( 'Received the not expected value: <'..TABLE_IDX_REF_PAT..'> {1, 2, 3, 4}', lu.assertNotEquals, {1,2,3,4}, {1,2,3,4} ) assertFailureMatches( 'expected: false, actual: <'..TABLE_IDX_REF_PAT..'> {}', lu.assertFalse, {}) local v = {1,2} assertFailureMatches( 'expected and actual object should be different: <'..TABLE_IDX_REF_PAT..'> {1, 2}', lu.assertNotIs, v, v ) assertFailureMatches('Content of the tables are not identical:\nExpected: <'..TABLE_IDX_REF_PAT..'> {one=2, two=3}\nActual: <'..TABLE_IDX_REF_PAT..'> {1, 2}' , lu.assertItemsEquals, {1,2}, {one=2, two=3} ) assertFailureMatches( 'expected: <'..TABLE_IDX_REF_PAT..'> {1, 2}\nactual: <'..TABLE_IDX_REF_PAT..'> {2, 1}', lu.assertEquals, {2,1}, {1,2} ) -- trigger multiline prettystr assertFailureMatches( 'expected: <'..TABLE_IDX_REF_PAT..'> {one=1, two=2}\nactual: <'..TABLE_IDX_REF_PAT..'> {3, 2, 1}', lu.assertEquals, {3,2,1}, {one=1,two=2} ) -- trigger mismatch formatting lu.assertErrorMsgContains( [[lists
5 then error( 'Exceeding 5') end end _G.MyTestWithIteration = MyTestWithIteration nbIter = 0 runner:runSuite( '--repeat', '10', 'MyTestWithIteration') _G.MyTestWithIteration = nil -- clean up -- check if the current iteration got reflected in the failure message lu.assertEquals( runner.result.successCount, 0 ) lu.assertEquals( runner.result.failureCount, 0 ) lu.assertEquals( runner.result.errorCount, 1 ) lu.assertEquals( runner.exeRepeat, 10 ) lu.assertEquals( runner.currentCount, 6 ) -- print( lu.prettystr( runner.result ) ) lu.assertStrContains(runner.result.errorTests[1].msg, "iteration 6") lu.assertStrContains(runner.result.errorTests[1].msg, "Exceeding 5" ) end function TestLuaUnitExecution:testOutputInterface() local runner = lu.LuaUnit.new() runner.outputType = Mock runner:runSuite( 'MyTestWithErrorsAndFailures', 'MyTestOk' ) local m = runner.output lu.assertEquals( m.calls[1][1], 'startSuite' ) lu.assertEquals(#m.calls[1], 2 ) lu.assertEquals( m.calls[2][1], 'startClass' ) lu.assertEquals( m.calls[2][3], 'MyTestWithErrorsAndFailures' ) lu.assertEquals(#m.calls[2], 3 ) lu.assertEquals( m.calls[3][1], 'startTest' ) lu.assertEquals( m.calls[3][3], 'MyTestWithErrorsAndFailures.testOk' ) lu.assertEquals(#m.calls[3], 3 ) lu.assertEquals( m.calls[4][1], 'endTest' ) lu.assertEquals(#m.calls[4], 3 ) lu.assertIsTable( m.calls[4][3] ) lu.assertEquals( m.calls[4][3].status, lu.NodeStatus.SUCCESS ) lu.assertEquals( m.calls[5][1], 'startTest' ) lu.assertEquals( m.calls[5][3], 'MyTestWithErrorsAndFailures.testWithError1' ) lu.assertEquals(#m.calls[5], 3 ) lu.assertEquals( m.calls[6][1], 'updateStatus' ) lu.assertEquals(#m.calls[6], 3 ) lu.assertEquals( m.calls[7][1], 'endTest' ) lu.assertEquals(#m.calls[7], 3 ) lu.assertIsTable( m.calls[7][3] ) lu.assertEquals( m.calls[7][3].status, lu.NodeStatus.ERROR ) lu.assertEquals( m.calls[8][1], 'startTest' ) lu.assertEquals( m.calls[8][3], 'MyTestWithErrorsAndFailures.testWithFailure1' ) lu.assertEquals(#m.calls[8], 3 ) lu.assertEquals( m.calls[9][1], 'updateStatus' ) lu.assertEquals(#m.calls[9], 3 ) lu.assertEquals( m.calls[10][1], 'endTest' ) lu.assertEquals(#m.calls[10], 3 ) lu.assertIsTable( m.calls[10][3] ) lu.assertEquals( m.calls[10][3].status, lu.NodeStatus.FAIL ) lu.assertEquals( m.calls[11][1], 'startTest' ) lu.assertEquals( m.calls[11][3], 'MyTestWithErrorsAndFailures.testWithFailure2' ) lu.assertEquals(#m.calls[11], 3 ) lu.assertEquals( m.calls[12][1], 'updateStatus' ) lu.assertEquals(#m.calls[12], 3 ) lu.assertEquals( m.calls[13][1], 'endTest' ) lu.assertEquals(#m.calls[13], 3 ) lu.assertIsTable(m.calls[13][3] ) lu.assertEquals( m.calls[13][3].status, lu.NodeStatus.FAIL ) lu.assertEquals( m.calls[14][1], 'endClass' ) lu.assertEquals(#m.calls[14], 2 ) lu.assertEquals( m.calls[15][1], 'startClass' ) lu.assertEquals( m.calls[15][3], 'MyTestOk' ) lu.assertEquals(#m.calls[15], 3 ) lu.assertEquals( m.calls[16][1], 'startTest' ) lu.assertEquals( m.calls[16][3], 'MyTestOk.testOk1' ) lu.assertEquals(#m.calls[16], 3 ) lu.assertEquals( m.calls[17][1], 'endTest' ) lu.assertEquals(#m.calls[17], 3 ) lu.assertIsTable( m.calls[17][3] ) lu.assertEquals( m.calls[17][3].status, lu.NodeStatus.SUCCESS ) lu.assertEquals( m.calls[18][1], 'startTest' ) lu.assertEquals( m.calls[18][3], 'MyTestOk.testOk2' ) lu.assertEquals(#m.calls[18], 3 ) lu.assertEquals( m.calls[19][1], 'endTest' ) lu.assertEquals(#m.calls[19], 3 ) lu.assertIsTable( m.calls[19][3] ) lu.assertEquals( m.calls[19][3].status, lu.NodeStatus.SUCCESS ) lu.assertEquals( m.calls[20][1], 'endClass' ) lu.assertEquals(#m.calls[20], 2 ) lu.assertEquals( m.calls[21][1], 'endSuite' ) lu.assertEquals(#m.calls[21], 2 ) lu.assertEquals( m.calls[22], nil ) end function TestLuaUnitExecution:testInvocation() lu.assertEquals( #lu.LuaUnit.instances, 1) local runner = lu.LuaUnit.new() -- this does not create a new registered instance lu.assertEquals( #lu.LuaUnit.instances, 1) -- test alternative "object" syntax for run(), passing self runner:run('--output', 'nil', 'MyTestOk') -- this does not create a new registered instance lu.assertEquals( #lu.LuaUnit.instances, 1) -- select class instance by name runner.run('--output', 'nil', 'MyTestOk.testOk2') -- this does not create a new registered instance lu.assertEquals( #lu.LuaUnit.instances, 1) -- check error handling lu.assertErrorMsgContains('No such name in global space', runner.runSuite, runner, 'foobar') lu.assertEquals( #lu.LuaUnit.instances, 1) lu.assertErrorMsgContains('Name must match a function or a table', runner.runSuite, runner, '_VERSION') lu.assertEquals( #lu.LuaUnit.instances, 1) lu.assertErrorMsgContains('No such name in global space', runner.runSuite, runner, 'foo.bar') lu.assertEquals( #lu.LuaUnit.instances, 1) lu.assertErrorMsgContains('must be a function, not', runner.runSuite, runner, '_G._VERSION') lu.assertEquals( #lu.LuaUnit.instances, 1) lu.assertErrorMsgContains('Could not find method in class', runner.runSuite, runner, 'MyTestOk.foobar') lu.assertEquals( #lu.LuaUnit.instances, 1) lu.assertErrorMsgContains('Instance must be a table or a function', runner.expandClasses, {{'foobar', 'INVALID'}}) lu.assertEquals( #lu.LuaUnit.instances, 1) lu.assertErrorMsgContains('Could not find method in class', runner.expandClasses, {{'MyTestOk.foobar', {}}}) lu.assertEquals( #lu.LuaUnit.instances, 1) end function TestLuaUnitExecution:test_filterWithPattern() local runner = lu.LuaUnit.new() runner:setOutputType( "NIL" ) runner:runSuite('-p', 'Function', '-p', 'Toto.' ) lu.assertEquals( executedTests[1], "MyTestFunction" ) lu.assertEquals( executedTests[2], "MyTestToto1:test1" ) lu.assertEquals( executedTests[3], "MyTestToto1:test2" ) lu.assertEquals( executedTests[4], "MyTestToto1:test3" ) lu.assertEquals( executedTests[5], "MyTestToto1:testa" ) lu.assertEquals( executedTests[6], "MyTestToto1:testb" ) lu.assertEquals( executedTests[7], "MyTestToto2:test1" ) lu.assertEquals( #executedTests, 7) runner:runSuite('-p', 'Toto.', '-x', 'Toto2' ) lu.assertEquals( runner.result.selectedCount, 5) -- MyTestToto2 excluded end function TestLuaUnitExecution:test_endSuiteTwice() local runner = lu.LuaUnit.new() runner:setOutputType( "NIL" ) runner:runSuite( 'MyTestWithErrorsAndFailures', 'MyTestOk' ) lu.assertErrorMsgContains('suite was already ended', runner.endSuite, runner) end function TestLuaUnitExecution:test_withTableErrorInside(args) local function my_test_with_table_error() error {code = 123} end local runner = lu.LuaUnit.new() runner:setOutputType( "NIL" ) runner:runSuiteByInstances { { 'my_test_with_table_error', my_test_with_table_error } } lu.assertStrContains(runner.result.allTests[1].msg, '{code=123}') end ------------------------------------------------------------------ -- -- Results Tests -- ------------------------------------------------------------------ TestLuaUnitResults = { __class__ = 'TestLuaUnitResults' } function TestLuaUnitResults:tearDown() executedTests = {} lu.LuaUnit.isTestName = lu.LuaUnit.isTestNameOld end function TestLuaUnitResults:setUp() executedTests = {} lu.LuaUnit.isTestNameOld = lu.LuaUnit.isTestName lu.LuaUnit.isTestName = function( s ) return (string.sub(s,1,6) == 'MyTest') end end function TestLuaUnitResults:test_statusLine() -- full success local r = {runCount=5, duration=0.17, successCount=5, notSuccessCount=0, failureCount=0, errorCount=0, nonSelectedCount=0, skippedCount=0} lu.assertEquals( lu.LuaUnit.statusLine(r), 'Ran 5 tests in 0.170 seconds, 5 successes, 0 failures') -- 1 failure, nothing more displayed r = {runCount=5, duration=0.17, successCount=4, notSuccessCount=1, failureCount=1, errorCount=0, nonSelectedCount=0, skippedCount=0} lu.assertEquals( lu.LuaUnit.statusLine(r), 'Ran 5 tests in 0.170 seconds, 4 successes, 1 failure') -- 1 error, no failure displayed r = {runCount=5, duration=0.17, successCount=4, notSuccessCount=1, failureCount=0, errorCount=1, nonSelectedCount=0, skippedCount=0} lu.assertEquals( lu.LuaUnit.statusLine(r), 'Ran 5 tests in 0.170 seconds, 4 successes, 1 error') -- 1 error, 1 failure r = {runCount=5, duration=0.17, successCount=3, notSuccessCount=2, failureCount=1, errorCount=1, nonSelectedCount=0, skippedCount=0} lu.assertEquals( lu.LuaUnit.statusLine(r), 'Ran 5 tests in 0.170 seconds, 3 successes, 1 failure, 1 error') -- 1 error, 1 failure, 1 non selected r = {runCount=5, duration=0.17, successCount=3, notSuccessCount=2, failureCount=1, errorCount=1, nonSelectedCount=1, skippedCount=0} lu.assertEquals( lu.LuaUnit.statusLine(r), 'Ran 5 tests in 0.170 seconds, 3 successes, 1 failure, 1 error, 1 non-selected') -- full success, 1 non selected r = {runCount=5, duration=0.17, successCount=5, notSuccessCount=0, failureCount=0, errorCount=0, nonSelectedCount=1, skippedCount=0} lu.assertEquals( lu.LuaUnit.statusLine(r), 'Ran 5 tests in 0.170 seconds, 5 successes, 0 failures, 1 non-selected') -- 1 error, 1 failure, 1 skipped r = {runCount=5, duration=0.17, successCount=3, notSuccessCount=2, failureCount=1, errorCount=1, nonSelectedCount=0, skippedCount=1} lu.assertEquals( lu.LuaUnit.statusLine(r), 'Ran 5 tests in 0.170 seconds, 3 successes, 1 failure, 1 error, 1 skipped') -- full success, 1 skipped r = {runCount=5, duration=0.17, successCount=5, notSuccessCount=0, failureCount=0, errorCount=0, nonSelectedCount=0, skippedCount=1} lu.assertEquals( lu.LuaUnit.statusLine(r), 'Ran 5 tests in 0.170 seconds, 5 successes, 0 failures, 1 skipped') -- full success, 1 skipped, 1 non-selected r = {runCount=5, duration=0.17, successCount=5, notSuccessCount=0, failureCount=0, errorCount=0, nonSelectedCount=1, skippedCount=1} lu.assertEquals( lu.LuaUnit.statusLine(r), 'Ran 5 tests in 0.170 seconds, 5 successes, 0 failures, 1 skipped, 1 non-selected') end function TestLuaUnitResults:test_nodeStatus() local es = lu.NodeStatus.new() lu.assertEquals( es.status, lu.NodeStatus.SUCCESS ) lu.assertTrue( es:isSuccess() ) lu.assertNil( es.msg ) lu.assertNil( es.stackTrace ) lu.assertStrContains( es:statusXML(), "ti"ti', 'got it' ) end function TestFailuresWithXml:test_failure_with_cdata_xml() lu.assertEquals( 'cdata does not like ]]>', 'got it' ) end function TestThatLastsALongTime() local start = os.clock() while os.clock() - start < 1.1 do end end lu.LuaUnit.verbosity = 2 os.exit( lu.LuaUnit.run() )