pax_global_header00006660000000000000000000000064107675241530014524gustar00rootroot0000000000000052 comment=76a816b704c3699f93e302c7031e5386297056fe shake-1.0.2/000077500000000000000000000000001076752415300126175ustar00rootroot00000000000000shake-1.0.2/Makefile000066400000000000000000000014641076752415300142640ustar00rootroot00000000000000# $Id: Makefile,v 1.5 2007/12/14 18:18:19 carregal Exp $ CONFIG= ./config include $(CONFIG) SHAKE_BIN = src/bin/shake ROOT_LUAS = src/shake/shake.lua SHAKE_LUAS= src/shake/stir.lua APP_FILES = src/apps/shake/helper.lua src/apps/shake/init.lua src/apps/shake/shake_suite.lp src/apps/shake/shake.lp APP_CSS = src/apps/shake/css/doc.css src/apps/shake/css/shake.css APP_IMG = src/apps/shake/img/shake.gif all: install: chmod +x $(SHAKE_BIN) mkdir -p $(LUA_DIR)/shake cp $(ROOT_LUAS) $(LUA_DIR) cp $(SHAKE_LUAS) $(LUA_DIR)/shake cp $(SHAKE_BIN) $(SYS_BINDIR) install_app: mkdir -p $(CGILUA_APPSDIR)/shake mkdir -p $(CGILUA_APPSDIR)/shake/css mkdir -p $(CGILUA_APPSDIR)/shake/img cp $(APP_FILES) $(CGILUA_APPSDIR)/shake cp $(APP_CSS) $(CGILUA_APPSDIR)/shake/css cp $(APP_IMG) $(CGILUA_APPSDIR)/shake/img shake-1.0.2/Makefile.win000066400000000000000000000022171076752415300150550ustar00rootroot00000000000000# $Id: Makefile.win,v 1.5 2007/12/21 19:20:10 carregal Exp $ include config.win SHAKE_BINS = src\bin\shake src\bin\shake.bat ROOT_LUAS = src\shake\shake.lua SHAKE_LUAS= src\shake\stir.lua APP_FILES = src\apps\shake\helper.lua src\apps\shake\init.lua src\apps\shake\shake_suite.lp src\apps\shake\shake.lp APP_CSS = src\apps\shake\css\doc.css src\apps\shake\css\shake.css APP_IMG = src\apps\shake\img\shake.gif install: IF NOT EXIST $(LUA_DIR) mkdir $(LUA_DIR) IF NOT EXIST $(LUA_DIR)\shake mkdir $(LUA_DIR)\shake FOR %i IN ($(SHAKE_LUAS)) DO copy %i $(LUA_DIR)\shake copy $(ROOT_LUAS) $(LUA_DIR)\ FOR %i IN ($(SHAKE_BINS)) DO copy %i $(SYS_BINDIR)\ install_app: IF NOT EXIST "$(CGILUA_APPSDIR)" mkdir "$(CGILUA_APPSDIR)" IF NOT EXIST "$(CGILUA_APPSDIR)\shake" mkdir "$(CGILUA_APPSDIR)\shake" IF NOT EXIST "$(CGILUA_APPSDIR)\shake\css" mkdir "$(CGILUA_APPSDIR)\shake\css" IF NOT EXIST "$(CGILUA_APPSDIR)\shake\img" mkdir "$(CGILUA_APPSDIR)\shake\img" FOR %i IN ($(APP_FILES)) DO copy %i "$(CGILUA_APPSDIR)\shake" FOR %i IN ($(APP_CSS)) DO copy %i "$(CGILUA_APPSDIR)\shake\css" FOR %i IN ($(APP_IMG)) DO copy %i "$(CGILUA_APPSDIR)\shake\img"shake-1.0.2/README000066400000000000000000000025741076752415300135070ustar00rootroot00000000000000Shake (http://shake.luaforge.net/) Shake is a simple and transparent test engine for Lua that assumes that tests only use standard assert and print calls. If you are looking for a xUnit style framework, check lunit and luaunit instead. Shake is distributed as a Lua module, a command line runner and a CGILua application. Shake is free software and uses the same license as Lua 5.1. Current version is 1.0.1. It was developed for Lua 5.1. Download Shake source can be downloaded from its Lua Forge page: http://luaforge.net/frs/?group_id=310 Dependencies Shake depends on two modules: * LuaFileSystem 1.3.0 * Leg 0.1.2 History Version 1.0.1 [21/Dec/2007] * Added support for dostring and loadstring (patch by Fábio Mascarenhas) * Shake was not considering the filename parameter (bug found by Leo Razoumov) * Improves the output of shake -r * Adding -v flag for version and -h flag for help (patch by Enrico Tassi) * Fixes a bug in the print implementation when the parameters where not strings (patch by Jean-Claude Wippler) Version 1.0 [14/Dec/2007] * First public release * Command line and CGILua application versions Installing If you are using LuaRocks just install it as any other Rock, if you are using Unix use make install. For details on the CGILua application installation please check the Shake documentation. shake-1.0.2/config000066400000000000000000000012001076752415300140000ustar00rootroot00000000000000# $Id: config,v 1.2 2007/11/16 16:50:21 carregal Exp $ # Default installation prefix PREFIX=/usr/local # System's libraries directory (where binary libraries are installed) LUA_LIBDIR= $(PREFIX)/lib/lua/5.1 # System's lua directory (where Lua libraries are installed) LUA_DIR= $(PREFIX)/share/lua/5.1 # System's executables directory (where binary or script executables are installed) SYS_BINDIR= $(PREFIX)/bin # Complete path to Lua command line interpreter LUA_INTERPRETER= $(PREFIX)/bin/lua5.1 # Default Kepler installation prefix KEPLER_PREFIX= # CGILua Apps directory CGILUA_APPSDIR = $(KEPLER_PREFIX)/etc/kepler/1.1/apps/cgiluashake-1.0.2/config.win000066400000000000000000000010631076752415300146030ustar00rootroot00000000000000# $Id: config.win,v 1.3 2007/12/21 19:20:10 carregal Exp $ # System's libraries directory (where binary libraries are installed) LUA_LIBDIR= c:\lua5.1 # System's lua directory (where Lua libraries are installed) LUA_DIR= c:\lua5.1\lua # System's executables directory (where binary or script executables are installed) SYS_BINDIR= c:\lua5.1 # Complete path to Lua command line interpreter LUA_INTERPRETER= c:\lua5.1\lua5.1 # Default Kepler installation prefix KEPLER_PREFIX=c:\Kepler\1.1 # CGILua Apps directory CGILUA_APPSDIR = $(KEPLER_PREFIX)\apps\cgiluashake-1.0.2/doc/000077500000000000000000000000001076752415300133645ustar00rootroot00000000000000shake-1.0.2/doc/us/000077500000000000000000000000001076752415300140135ustar00rootroot00000000000000shake-1.0.2/doc/us/doc.css000066400000000000000000000074271076752415300153040ustar00rootroot00000000000000body { margin-left: 1em; margin-right: 1em; font-family: arial, helvetica, geneva, sans-serif; background-color:#ffffff; margin:0px; } code { font-family: "Andale Mono", monospace; } tt { font-family: "Andale Mono", monospace; } body, td, th { font-size: 11pt; } h1, h2, h3, h4 { margin-left: 0em; } textarea, pre, tt { font-size:10pt; } body, td, th { color:#000000; } small { font-size:0.85em; } h1 { font-size:1.5em; } h2 { font-size:1.25em; } h3 { font-size:1.15em; } h4 { font-size:1.06em; } a:link { font-weight:bold; color: #004080; text-decoration: none; } a:visited { font-weight:bold; color: #006699; text-decoration: none; } a:link:hover { text-decoration:underline; } hr { color:#cccccc } img { border-width: 0px; } h3 { padding-top: 1em; } p { margin-left: 1em; } p.name { font-family: "Andale Mono", monospace; padding-top: 1em; margin-left: 0em; } blockquote { margin-left: 3em; } .example { background-color: rgb(245, 245, 245); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: silver; border-right-color: silver; border-bottom-color: silver; border-left-color: silver; padding: 1em; margin-left: 1em; margin-right: 1em; font-family: "Andale Mono", monospace; font-size: smaller; } hr { margin-left: 0em; background: #00007f; border: 0px; height: 1px; } ul { list-style-type: disc; } table.index { border: 1px #00007f; } table.index td { text-align: left; vertical-align: top; } table.index ul { padding-top: 0em; margin-top: 0em; } table { border: 1px solid black; border-collapse: collapse; margin-left: auto; margin-right: auto; } th { border: 1px solid black; padding: 0.5em; } td { border: 1px solid black; padding: 0.5em; } div.header, div.footer { margin-left: 0em; } #container { margin-left: 1em; margin-right: 1em; background-color: #f0f0f0; } #product { text-align: center; border-bottom: 1px solid #cccccc; background-color: #ffffff; } #product big { font-size: 2em; } #product_logo { } #product_name { } #product_description { } #main { background-color: #f0f0f0; border-left: 2px solid #cccccc; } #navigation { float: left; width: 12em; margin: 0; vertical-align: top; background-color: #f0f0f0; overflow:visible; } #navigation h1 { background-color:#e7e7e7; font-size:1.1em; color:#000000; text-align:left; margin:0px; padding:0.2em; border-top:1px solid #dddddd; border-bottom:1px solid #dddddd; } #navigation ul { font-size:1em; list-style-type: none; padding: 0; margin: 1px; } #navigation li { text-indent: -1em; margin: 0em 0em 0em 0.5em; display: block; padding: 3px 0px 0px 12px; } #navigation li li a { padding: 0px 3px 0px -1em; } #content { margin-left: 12em; padding: 1em; border-left: 2px solid #cccccc; border-right: 2px solid #cccccc; background-color: #ffffff; } #about { clear: both; margin: 0; padding: 5px; border-top: 2px solid #cccccc; background-color: #ffffff; } @media print { body { font: 10pt "Times New Roman", "TimeNR", Times, serif; } a { font-weight:bold; color: #004080; text-decoration: underline; } #main { background-color: #ffffff; border-left: 0px; } #container { margin-left: 2%; margin-right: 2%; background-color: #ffffff; } #content { margin-left: 0px; padding: 1em; border-left: 0px; border-right: 0px; background-color: #ffffff; } #navigation { display: none; } #product_logo { display: none; } #about img { display: none; } .example { font-family: "Andale Mono", monospace; font-size: 8pt; page-break-inside: avoid; } } shake-1.0.2/doc/us/examples.html000066400000000000000000000145401076752415300165230ustar00rootroot00000000000000 Shake - A Simple Lua Test Engine
Shake
A Simple Lua Test Engine

Examples

Running Shake in the command line

Assuming you have a module like LuaFileSystem installed and you go to its /tests directory and run Shake from there, the output would be:

~/workspace/luafilesystem/tests$ shake
->  test.lua OK!
_________________

Tests: 27
Failures: 0
Errors: 0

On the other hand, if you have a test script like the one below that includes two assertions that are supposed to fail (lines are numbered):

 1	items = 10
 2	-- checks the correct case
 3	assert (items == 10, "this should not fail")
 4
 5	items = 20
 6	-- checks an overflow case
 7	assert (items == 10, "wrong number of items")
 8
 9	print("Verifying the total")
10	items = 10
11	total = 30
12	assert (items == total, "wrong total")

Shake would register the failures but would run the whole test script, reporting at the end:

:~/workspace$ shake
----------------    test.lua failed!   ----------------

-- checks an overflow case
   #7 assert (items == 10, "wrong number of items")
   items -> 20

Verifying the total
   #12 assert (items == total, "wrong total")
   items -> 10
   total -> 30
_________________

Tests: 3
Failures: 2
Errors: 0

Note how much more informative this is when compared to the default output of running the test script with Lua:

:~/workspace$ lua5.1 test.lua
lua5.1: test.lua:7: wrong number of items
stack traceback:
        [C]: in function 'assert'
        test.lua:7: in main chunk
        [C]: ?

Implementing a simple Shake runner

Here we show how to use the Shake API to implement runners. Note that if you just want to execute tests, the built in runners (command line and CGILua app) may be enough. On the other hand, if you need to show more detailed information about the tests results or if you want to use Shake as part of your application runtime, then you will need to use the Shake API.

The minimal Shake runner would be like:

require "shake"
local run = shake.runner()
run:test("somefile.lua")
print (run:summary())

This would be basically equivalent to the command line Shake runner, and if you want to report more details than the default summary does, you will need to drill down the results using something like:

function ReportModules(run)
   local results = run.results
   for cs, suite in ipairs(results.suites) do
       -- displays information about the suite.title
       if suite.error then
	-- displays information about the suite error
       elseif suite.failed > 0 then
	-- displays information about the suite.failed results
       else
	-- displays information about the suite.passed and suite.failed results
       end
   end
end

For even more details, you may want to inspect each test result and decide what to show:

function ReportModule(run)
  local results = run.results
  for _, suite in ipairs(results.suites) do
    if suite.error == -1 then
      -- displays information about the error
    else
      for _, context in ipairs(suite.contexts) do
        if next(context.tests) then
          if context.output[1] ~= "" or context.comments then
            -- displays information about the context
            for _, output in ipairs(context.output) do
              if output and output ~= "" then
                -- using context.output
              end
            end
            if context.comments and context.comments ~= "" then
              --  or context.comments
            end
          end
          for _, test in ipairs (context.tests) do
	  local linenumber = test.linenumber or "???"
	  local op = test.op
	   local val2 = tostring(test.val2)
	  -- when there is no comparision operator, assume that this is an assert(x) case
	  if not op then
	    val2 = "True value" -- just to diferentiate from the Lua "true"
	  end
	  if not op or op == "==" then
	    op = ""
	  end
	  -- displays information about the test result using
	  -- linenumber, test.exp1, op, val2, test.val1 and test.msg
	end
       end
    end
end

Valid XHTML 1.0!

$Id: examples.html,v 1.5 2007/12/21 22:55:20 carregal Exp $

shake-1.0.2/doc/us/index.html000066400000000000000000000112341076752415300160110ustar00rootroot00000000000000 Shake - A Simple Lua Test Engine
Shake
A Simple Lua Test Engine

Overview

Shake is a simple and transparent test engine for Lua that assumes that tests only use standard assert and print calls. If you are looking for a xUnit style framework, check lunit and luaunit instead.

Shake is distributed as a Lua module, a command line runner and a CGILua application.

Shake is free software and uses the same license as Lua 5.1.

Status

Current version is 1.0.1. It was developed for Lua 5.1.

Download

Shake source can be downloaded from its Lua Forge page.

Dependencies

Shake depends on two modules:

History

Version 1.0.1 [21/Dec/2007]
  • Adds support for dostring and loadstring (patch by Fábio Mascarenhas)
  • Shake was not considering the filename parameter (bug found by Leo Razoumov)
  • Improves the output of shake -r
  • Adds -v flag for version and -h flag for help (patch by Enrico Tassi)
  • Fixes a bug in the print implementation when the parameters where not strings (patch by Jean-Claude Wippler)
Version 1.0 [14/Dec/2007]
  • First public release
  • Command line and CGILua application versions

Credits

Shake was designed by André Carregal and Humberto Santos as part of the Kepler Project, which holds its copyright.

Contact us

For more information please contact us. Comments are welcome!

You can also reach other Kepler developers and users on the Kepler Project mailing list.

Valid XHTML 1.0!

$Id: index.html,v 1.10 2007/12/21 22:55:20 carregal Exp $

shake-1.0.2/doc/us/license.html000066400000000000000000000103671076752415300163320ustar00rootroot00000000000000 Shake - A Simple Lua Test Engine
Shake
A Simple Lua Test Engine

License

Shake is free software: it can be used for both academic and commercial purposes at absolutely no cost. There are no royalties or GNU-like "copyleft" restrictions. Shake qualifies as Open Source software. Its licenses are compatible with GPL. Shake is not in the public domain and the Kepler Project keep its copyright. The legal details are below.

The spirit of the license is that you are free to use Shake for any purpose at no cost without having to ask us. The only requirement is that if you do use Shake, then you should give us credit by including the appropriate copyright notice somewhere in your product or its documentation.

The Shake library is designed and implemented by André Carregal and Humberto Santos. The implementation is not derived from licensed software.


Copyright © 2007 Kepler Project.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Valid XHTML 1.0!

$Id: license.html,v 1.5 2007/12/21 22:55:20 carregal Exp $

shake-1.0.2/doc/us/manual.html000066400000000000000000000274051076752415300161660ustar00rootroot00000000000000 Shake - A Simple Lua Test Engine
Shake
A Simple Lua Test Engine

Introduction

Many Lua modules and applications use a simple pattern for internal tests. They have a script (usually called test.lua) that exercises the module API using API calls and assert() calls to verify the results. It is also common practice in those modules to use print() to output information about the test progress and to use Lua comments to inform what is being tested to whoever reads the source. Although widespread this approach may be too crude for those wanting to test more than one module at a time or to have a more detailed view of the results.

Shake assumes that the tests have been implemented for the above scenario but offers a transparent test engine for those wanting the execution of the tests in batch mode or those wanting to get an overview of the various results. The Shake engine can inform not only the number of tests, failures and errors found in a group of test scripts, but it can infer information about the test context using the output and comments associated with the assert() calls.

The main characteristic of Shake is being transparent, which means that the module authors and test writers do not have to be aware that tests are going to be run with Shake. As long as the tests call assert() Shake can obtain quite a lot of information from the source and run time execution. This is done through the pre-processing of the tests source code using Leg (and therefore LPeg) to replace every call to assert() with one that can extract information about the expressions, values and operators involved in the assertion.

Another common alternative to testing is the one adopted by test frameworks like lunit and luaunit, which offer a quite sophisticated API for those test scripts. For those wanting to use a xUnit style framework these two Lua modules are very useful but in this case the test authors have to be aware that the tests are going to be executed by a xUnit framework.

One of the strong points of the xUnit framework style is being able to report failures in a much more detailed view than a simple assertion. In Lua, a call to assert() is basically equivalent to an if that displays nice error messages (provided in the assert() call). Unfortunately, an assertion just checks if an expression is true or false and report that as an error in the second case.

This makes the test scripts much simpler, but also means that you have to provide decent error messages for every assertion and that once one assertion fails, your test stops running. Another disvantage of a simple assert() call is that it is does not provide much information about what caused the error. For example, in an assertion like:

assert(items == 10, "too many items")

If the assertion does not fail then you can be certain that you have 10 items, but if it fails then all you can say is that items is not the number 10. If you want to know what is the current value of items in that assertion you would have to add it to the error message.

The Shake engine offers an alternative way to obtain that information by preprocessing the test script before it is executed and constructing a Lua table representation of the test execution. Once the tests are run, we can iterate over this results table and display a lot more information about the test execution than is usually available. In the above example Shake would not only be able to inform that the assertion failed, but also the value of items and even that the asserted expression involved a non terminal called "items" which was supposed to be equal to the number 10.

Since a results table is usually quite long and have a lot of information that may be useful for some users but not others, Shake offers the separation of a test runner and a test reporter. A test runner is responsible for determining which test scripts are going to be executed and accumulating the results in the runner results table. A test reporter uses the results table and displays information about the results in some way. Shake offers two built in runners, one to be used in the command line and another to be used as a web application. Shake also offers two built in reporters, one that outputs a summary of the results as a text message and another that displays a much more complete report using HTML tables and CSS to format the results.

For those wanting more control on the test execution and reporting, the Shake module (the engine itself) can be used as an standard module and offers an API for test execution and for accessing the results. For more details see the examples and the API reference.

Installation

The Shake source distribution contains two components. The first one is a Lua module and command line runner, the second is a CGILua application runner.

The easiest way to install the Shake module and command line runner is using LuaRocks:

luarocks install shake

If you prefer to install Shake manually and you are using Unix then you can install the command line runner and the Shake module using the command below (where the optional PREFIX parameter assumes /usr/local as default):

make PREFIX=prefix_path install

After you have the Shake engine installed you can optionally install the CGILua application using a similar command (note that the CGILua application cannot be installed by using LuaRocks):

make KEPLER_PREFIX=prefix_path install_app

Finally, if you are using Kepler in Windows you would have to copy the Shake source files to your KEPLER_BIN, KEPLER_LUA (and CGILUA_APPS if you want to use the Shake CGILua application) directories as the example below shows:

Kepler Base
    /apps
    /cgilua
        /shake		-- from /src/apps/shake
    /bin
        shake			-- from /src/bin
        shake.bat		-- from /src/bin
    /lua
        shake.lua		-- from /src/shake
        /shake
            stir.lua		-- from /src/shake

Running Shake

Once installed Shake can be run as a command line command or as a CGILua web application.

Command line runner

The Shake command line runner is called shake and uses the following syntax:

shake [options] [filename]

This command runs a test file called filename (assuming test.lua by default) in the current directory or any of its subdirectories if the -r option is given.

The command options are:

-h, --help
Prints this help message
-r, --recursive
Recursively scans subdirectories for test.lua files and runs them
-v, --version
Prints the Shake version

Check the examples page for an output of a Shake run.

CGILua application runner

If you have installed the Shake CGILua application in your CGILUA_APPS directory, Shake assumes that the tests to be run will be in the SHAKE_TESTS directory. If you don't define SHAKE_TESTS in your CGILua configuration file, Shake assumes the default of KEPLER_CONF.."/tests".

The SHAKE_TESTS directory should contain one directory for each module that you want to test. When you access the URL

/app.lua/shake

Shake will look into those directories for a test.lua file and execute it if present. After all the test scripts are executed Shake will report a summary of the results for all the tests executed.

This report is an HTML table that also offers a link to a more detailed view to the results of a single module test run. Once you click on that link Shake will show the full results of the test execution, including every assertion involved, even the succesfull ones

Reference

For those interested in more control over the runner and the report, Shake offers the following functions (check the examples for more information):

shake.runner()
Returns a Shake runner that offers the functions:
runner.test(filename)
Executes a test suite and stores the results in the runner.results table.
runner.summary()
Outputs a summary of the results from the runner.results table.
shake.isterminal(expression)
Returns a boolean value indicating if the expression refers to a terminal symbol.

Valid XHTML 1.0!

$Id: manual.html,v 1.6 2007/12/21 22:55:20 carregal Exp $

shake-1.0.2/doc/us/shake.png000066400000000000000000000165511076752415300156240ustar00rootroot00000000000000PNG  IHDRL\ pHYsHHFk>IDATxy@SWBž@@AD (ւj-ֺoRgөֶVjmQ = {ȞH_ IMrC諿ޓ}|gs@3g 03/`f^̼y!33AПgz3w|}},--͝)N&HfΜbǿ 'O$HsDׯ`44ܾ>P(rMTFGG߿okkkgghoo19T}}¾>!R(V$aB[H$&'---}}}gɓ'[vq7>*D"Lbj+ Y,Ȉ@ P(AAAWF B43kKJ8<ި깫mL WpnܸѱeR#GV^ץRirrrSSScc#͎1 !Ri__Ϊ~~~F++Μ>>nڻwR{ܼyH${yyp8IO555$I ?^9 dX,OΟ??22rժU`Њ]CTVlmmذaCqq5kRŋmllT,--Y,ֶmۈDaA9:6 xQP& D"Jrtb0HdWW[ؕXb􏎨PtL&vڥ,H$:wAׯrHHHppp+!qQUU=}}B?$pHh{{Cyӧˍ"%G,޷/B!:@׷{n2|ڮ[d2#Wef֗p ,IOJ X*p[?3|%))@!p8EEE$ 4GG^{M>ߟxb3,2";utyvvL@cb%K7m KHEb|γ$f-k׮PԶիWiooٳg}||^~#HtH$KOeMM|E޻aLݫBtʔ#"# q2?qD\\ٳA HBAAs%K rEzӏ>*lk@aaLaRSз.۹s ###k׮UU@ ɩpQQQL&ҥKH,)aޝ]QpBBhGGG{hhABv 445ւrrrM9cgdd̘1ֶ!00Jh4jx;~ӽ4Ο9A$x<09>18~++p߿77d;;; ǏCBB`-R ԩ۷ed$Λv~fi)ǰEߎX_[TP]]ݕ+Wr9g2-Ry kkko߮;RSߟ#'r|Yܞ=jhtTcNN^m= jhh(++`0L&GKBq)x?H۷p @g"APaaaiiە Wrv˄գ10][C"ϟKK9s蹶b0ʕ|px ҝlll***VZC /XVnWGX,A\QfM^GZ= '3 dHN$!.X|VH$R||F *%%K2<X,`gbb@Dӓlkk!C ୷~Aj`W[[ R@сπ h_FActOIaxljr5c.wt,$B ni!6}i.$pff(?1 ᰰ) jY?K[|ʕ+a!Aeee xϞ[H …dzaA? 766*Aa{\aF8dM\{So_*B+HsYUUemmk?Ø5k *XYჂ?OM}fRx{{/[ 矗oɤQDÇ\|YahY}vжqܓ1eCCyɓfTٔfw>9BqrrjllMd7@OKA׷QD"DH_hѱe55Z]3::rsZ~~~Ú?zBovR *6[QY)(hӦ 8p@i0xlgggT*Gœ9w7o6 a0F2AYY;r Ohhff34$..f B!ǣkajYR(]XYpH$/// ~I]ش)3 .Fh W\ _pƿulma E"y;5 .S~OH`eee55ipFg5k<,V_DęjZ*n֭"DI$:%z5&W]݃$=aʿWVvnۇbbm>5+ s UuuϜ9888(@GmlT믿pq>Cj2o|}ERR.!J g?Pqa77ƦCY }}}]\\tkk&= .\Ύ`kk!)RPH^^^j(%\~=* +3АxhHVl]]OS:aB!ˑ6=7OoxaP(xaԾ?"4&]J 9P@,1%ı݌WFDtr'lł/_Q,u}x<~ڴiHrOs^^k0:*RmipǏk޴rvy>ӧll,X\VWfg[a †C,,&ooʡCp )q5 `׮9/%DD#"۲H7+&ΗKaNx_=}#BT|mgGH_W}C" 8Cs NXАxϞl/>sqc'N|@Fi\DM>>AAA'߾#P+^ t ftFaRiUUPoz59M@l,c߷Ώ)JpJ%99$d/Br^d 'EEy(G}7O"nkA0))W[Non7"2@xV,)ew>!!HHnI߿Qu 6@ܱc C"=Us8twRm^0?;w6ljDp@@@NNγgϴ#+VPX,WLP$߽ۦ;jj+jcuA_w횫 vǎ~~hD=##i jaj,H@rٳ6񕗗Csn}22*KQ?HM}aT̈r/˔˙uuܠTU<8kG觟j338!O]o HDv[gf>''Ύd+Hco0^{Ҷ< xKz˫}UwYsAz78v#I&9c?4.1 Iɪr3REG>x*TN0{\}W\ioo뭷W%ǎ=S/[hz[+WX)S PͮXb3v+8vz{Jںu]\ \+H$?ctt19AYŋWFbXxle^^+Xg$&DLWA]]] e͚5F1;9?՘((Xx?G|>~C%BL++kꩩ}cHtǸyzMs>9<ߟl$D~;8L ZXX 9g0R eʓ %B": O ڵk4-%%(,e4%%%aaaK.Eh孓mFSSӣG^~˗ަ'H .GEEEFFN/FFF`4 RA˶^z%$Gb1Mc̙3/77Ir}}}[lAՆ;aeD$|>F-^`L@̬+++LĔV7]]]3ϟ߽{q̙aaaaRH$cϏH$8nX&4VB1I#"ŝ]]]jvgΜx<a]v>d>1,--I$' |mp8bX&dpUSd|>ΎH$}dUo! Bff/%JLtEXtComment Image generated by GPL Ghostscript SVN PRE-RELEASE (device=pnmraw) =8IENDB`shake-1.0.2/rockspecs/000077500000000000000000000000001076752415300146135ustar00rootroot00000000000000shake-1.0.2/rockspecs/shake-1.0.2-1.rockspec000066400000000000000000000014061076752415300202340ustar00rootroot00000000000000package = "Shake" version = "1.0.2-1" source = { url = "http://luaforge.net/frs/download.php/3009/shake-1.0.1.tar.gz" } description = { summary = "A Simple Lua Test Engine", detailed = [[ Shake is a simple and transparent test engine for Lua that assumes that tests only use standard assert and print calls. Shake uses Leg and LPeg to preprocess test files and extract a lot more information than what is usually available when tests use standard Lua assertions. ]], license = "MIT/X11", homepage = "http://shake.luaforge.net/" } dependencies = { "lua >= 5.1", "leg >= 0.1.2", "luafilesystem >= 1.3.0", } build = { type = "make", variables = { LUA_DIR = "$(LUADIR)", SYS_BINDIR = "$(BINDIR)" } } shake-1.0.2/rockspecs/shake-cvs-1.rockspec000066400000000000000000000014261076752415300203730ustar00rootroot00000000000000package = "Shake" version = "cvs-1" source = { url = "cvs://:pserver:anonymous:@cvs.luaforge.net:/cvsroot/shake", cvs_tag = "HEAD", } description = { summary = "A Simple Lua Test Engine", detailed = [[ Shake is a simple and transparent test engine for Lua that assumes that tests only use standard assert and print calls. Shake uses Leg and LPeg to preprocess test files and extract a lot more information than what is usually available when tests use standard Lua assertions. ]], license = "MIT/X11", homepage = "http://shake.luaforge.net/" } dependencies = { "lua >= 5.1", "leg >= 0.1.2", "luafilesystem >= 1.3.0", } build = { type = "make", variables = { LUA_DIR = "$(LUADIR)", SYS_BINDIR = "$(BINDIR)" } }shake-1.0.2/src/000077500000000000000000000000001076752415300134065ustar00rootroot00000000000000shake-1.0.2/src/apps/000077500000000000000000000000001076752415300143515ustar00rootroot00000000000000shake-1.0.2/src/apps/shake/000077500000000000000000000000001076752415300154445ustar00rootroot00000000000000shake-1.0.2/src/apps/shake/css/000077500000000000000000000000001076752415300162345ustar00rootroot00000000000000shake-1.0.2/src/apps/shake/css/doc.css000066400000000000000000000074271076752415300175250ustar00rootroot00000000000000body { margin-left: 1em; margin-right: 1em; font-family: arial, helvetica, geneva, sans-serif; background-color:#ffffff; margin:0px; } code { font-family: "Andale Mono", monospace; } tt { font-family: "Andale Mono", monospace; } body, td, th { font-size: 11pt; } h1, h2, h3, h4 { margin-left: 0em; } textarea, pre, tt { font-size:10pt; } body, td, th { color:#000000; } small { font-size:0.85em; } h1 { font-size:1.5em; } h2 { font-size:1.25em; } h3 { font-size:1.15em; } h4 { font-size:1.06em; } a:link { font-weight:bold; color: #004080; text-decoration: none; } a:visited { font-weight:bold; color: #006699; text-decoration: none; } a:link:hover { text-decoration:underline; } hr { color:#cccccc } img { border-width: 0px; } h3 { padding-top: 1em; } p { margin-left: 1em; } p.name { font-family: "Andale Mono", monospace; padding-top: 1em; margin-left: 0em; } blockquote { margin-left: 3em; } .example { background-color: rgb(245, 245, 245); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: silver; border-right-color: silver; border-bottom-color: silver; border-left-color: silver; padding: 1em; margin-left: 1em; margin-right: 1em; font-family: "Andale Mono", monospace; font-size: smaller; } hr { margin-left: 0em; background: #00007f; border: 0px; height: 1px; } ul { list-style-type: disc; } table.index { border: 1px #00007f; } table.index td { text-align: left; vertical-align: top; } table.index ul { padding-top: 0em; margin-top: 0em; } table { border: 1px solid black; border-collapse: collapse; margin-left: auto; margin-right: auto; } th { border: 1px solid black; padding: 0.5em; } td { border: 1px solid black; padding: 0.5em; } div.header, div.footer { margin-left: 0em; } #container { margin-left: 1em; margin-right: 1em; background-color: #f0f0f0; } #product { text-align: center; border-bottom: 1px solid #cccccc; background-color: #ffffff; } #product big { font-size: 2em; } #product_logo { } #product_name { } #product_description { } #main { background-color: #f0f0f0; border-left: 2px solid #cccccc; } #navigation { float: left; width: 12em; margin: 0; vertical-align: top; background-color: #f0f0f0; overflow:visible; } #navigation h1 { background-color:#e7e7e7; font-size:1.1em; color:#000000; text-align:left; margin:0px; padding:0.2em; border-top:1px solid #dddddd; border-bottom:1px solid #dddddd; } #navigation ul { font-size:1em; list-style-type: none; padding: 0; margin: 1px; } #navigation li { text-indent: -1em; margin: 0em 0em 0em 0.5em; display: block; padding: 3px 0px 0px 12px; } #navigation li li a { padding: 0px 3px 0px -1em; } #content { margin-left: 12em; padding: 1em; border-left: 2px solid #cccccc; border-right: 2px solid #cccccc; background-color: #ffffff; } #about { clear: both; margin: 0; padding: 5px; border-top: 2px solid #cccccc; background-color: #ffffff; } @media print { body { font: 10pt "Times New Roman", "TimeNR", Times, serif; } a { font-weight:bold; color: #004080; text-decoration: underline; } #main { background-color: #ffffff; border-left: 0px; } #container { margin-left: 2%; margin-right: 2%; background-color: #ffffff; } #content { margin-left: 0px; padding: 1em; border-left: 0px; border-right: 0px; background-color: #ffffff; } #navigation { display: none; } #product_logo { display: none; } #about img { display: none; } .example { font-family: "Andale Mono", monospace; font-size: 8pt; page-break-inside: avoid; } } shake-1.0.2/src/apps/shake/css/shake.css000077500000000000000000000020701076752415300200430ustar00rootroot00000000000000/* Shake Stylesheet */ /* Copyright 2007 Kepler Project */ /* $Id: shake.css,v 1.2 2007/10/29 20:19:05 carregal Exp $ */ div.shakecontext { background-color: rgb(245, 245, 245); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: silver; border-right-color: silver; border-bottom-color: silver; border-left-color: silver; padding: 1em; margin-left: 1em; margin-right: 1em; margin-top: 3em; margin-bottom: 1em; font-family: "Andale Mono", monospace; font-size: smaller; } table.shake { padding: 1em; margin-top: 2em; margin-bottom: 2em; } table.shake th { text-align:left; background-color: #E7E7E7; } table.shake thead th {text-align:center} table.shake td {text-align:center} table.shake td.passed {} table.shake td.failed {background-color:#F0E68C} table.shake td.noerror {} table.shake td.error {background-color:#FFA07A}shake-1.0.2/src/apps/shake/helper.lua000066400000000000000000000174531076752415300174400ustar00rootroot00000000000000-- Helper file for the CGILua based Shake runner -- -- Auxiliary formating function for tables (shows only the first level) local function _expandtable(t) local s = "{" for i,v in pairs (t) do s = s.."
\n" if type(v) == "table" then local vv = "{
\n" for a,b in pairs(v) do vv = string.format ("%s %s = %s,
\n", vv, a, tostring(b)) end v = vv.." }," s = s..string.format (" %s = %s", i, tostring(v)) else s = s..string.format (" %s = %s,", i, tostring(v)) end end if next(t) then s = s.."
\n" end s = s.."}
\n" return s end -- Auxiliary formating function local function _tostring(obj) if type(obj) == "table" then return _expandtable(obj) else return tostring(obj) end end -- Lists the available test modules using a
  • ..
  • format function ListModules(modules) return function() if not next(modules) then cgilua.put("
  • (No modules)
  • ") else for _, module_name in ipairs(modules) do cgilua.put([[
  • ]]..module_name..[[
  • ]]) end end end end -- Report the Shake results for all the modules as a HTML table function ReportModules(run) return function() local results = run.results for cs, suite in ipairs(results.suites) do cgilua.put("\n") cgilua.put(""..[[]]..suite.title..[[]].."\n".."\n") if suite.error then cgilua.put([[]]..suite.passed + suite.failed.."\n") cgilua.put([[ 0) and [[ class="failed">]]..suite.failed) or ">").."\n") cgilua.put([[1]].."\n") elseif suite.failed > 0 then cgilua.put([[]]..suite.passed + suite.failed.."\n") cgilua.put([[]]..suite.failed.."\n") cgilua.put([[]].."\n") else cgilua.put([[]]..suite.passed + suite.failed.."\n") cgilua.put([[]].."\n") cgilua.put([[]].."\n") end cgilua.put("\n") end cgilua.put("") cgilua.put("\n") cgilua.put("Totals\n") cgilua.put(""..results.failed + results.passed.."\n") cgilua.put([[]]..results.failed) or [[passed">]]).."\n") cgilua.put([[]]..results.errors) or [[noerror">]]).."\n") cgilua.put("\n") cgilua.put("") end end -- Report Shake results of single Module run as a table function ReportModule(run) return function() local results = run.results for _, suite in ipairs(results.suites) do if suite.error == -1 then cgilua.put("

    ERROR:

    ") cgilua.put("

    "..suite.error.."

    ") else for _, context in ipairs(suite.contexts) do if next(context.tests) then if context.output[1] ~= "" or context.comments then cgilua.put([[
    ]].."\n") for _, output in ipairs(context.output) do if output and output ~= "" then cgilua.put([[
    ]]..tostring(output).."
    \n") end end if context.comments and context.comments ~= "" then cgilua.put([[
    ]]..context.comments.."
    \n") end cgilua.put("
    ") end cgilua.put([[ ]]) for _, test in ipairs (context.tests) do local linenumber = test.linenumber or "???" local op = test.op local val2 = tostring(test.val2) if not op then val2 = "True value" end if not op or op == "==" then op = "" end cgilua.put("") local testclass = "passed" if not test.passed then testclass = "failed" end cgilua.put([[") cgilua.put([[") cgilua.put([[") cgilua.put([[") if not test.passed then cgilua.put([[") else cgilua.put([[") end cgilua.put("") end cgilua.put("
    Line # Expected Actual Message
    ]]..linenumber.."]]..test.exp1.."]]..op..val2.."]].._tostring(test.val1).."]]..(test.msg or "").."]].."
    ") end end end end end end -- Reports a module Shake summary as a HTML table function ModuleSummary(run) return function() local results = run.results for cs, suite in ipairs(results.suites) do cgilua.put("\n") cgilua.put(""..suite.title.."\n") if suite.error then cgilua.put([[]]..suite.passed + suite.failed.."\n") cgilua.put([[ 0) and [[ class="failed">]]..suite.failed) or ">").."\n") cgilua.put([[1]].."\n") elseif suite.failed > 0 then cgilua.put([[]]..suite.passed + suite.failed.."\n") cgilua.put([[]]..suite.failed.."\n") cgilua.put([[]].."\n") else cgilua.put([[]]..suite.passed + suite.failed.."\n") cgilua.put([[]].."\n") cgilua.put([[]].."\n") end cgilua.put("\n") end end end -- Reports the full Shake summary as HTML function ShakeSummary(run) return function() local results = run.results if results.errors > 0 or results.failed > 0 then cgilua.put("

    Shake output:

    ") cgilua.put([[
    ]])
    		    cgilua.put(run:summary())
    		    cgilua.put("
    ") end end end shake-1.0.2/src/apps/shake/img/000077500000000000000000000000001076752415300162205ustar00rootroot00000000000000shake-1.0.2/src/apps/shake/img/shake.gif000066400000000000000000000044051076752415300200050ustar00rootroot00000000000000GIF89a4@@@ ```000PPPppp((--ŤnnMM mmDDpp\\II((z˕))!,4pH,Ȥrl:ШtJZجvzxL.znA"~χNv}n;50 // 05;x\$;04::40;$M; ;m))E//b!҂!C:ɲV,#".1%%1."#,=ǰK20BcPxAƦNDGHEaʼn OBEETq 5x M2(ٓND AȧTt!´ACH +KlTIIKo[]IYw֑U\iQ;TeYX9f ,]h ЦS”; /݋F| 昵y/E5/eG;=$iBD A! mu(;늢 IF:4xHKcd3-©5"n$$hA}($MЮ,CW % BʐH&2n]9,)H=0Dq[xza"<;8'#tfDVr L΂GjNtP4|xk$فtș"C,ov V2.S:WNj y̵5d\E"fa X㚫uuR$Bn~z{$]ї;"ttف]7@@K!jhf{RZʝuML ء< a%C0 ji(sM'QpX)LQεBJxA"! dJF )2%! AC /_!&=8!rLXG;ymvsк9p<#WF5,f/ h2n]0)"h)ƝE" *xM fWVհgMZָB;shake-1.0.2/src/apps/shake/init.lua000066400000000000000000000040051076752415300171110ustar00rootroot00000000000000-- Shake runner that uses CGILua to offer a drill down of the test results -- -- This file acts as the general controller for the application using URLs like: -- /shake/all - Shakes all the modules in SHAKE_TESTS -- /shake/module - Shake a specific module in SHAKE_TESTS -- /shake/... - Processes the resource as a path to a file in the Shake app home directory require"shake" -- get the optional configuration cgilua.doif("shake_conf.lua") -- load output helper functions cgilua.doif("helper.lua") local SHAKE_TESTS = SHAKE_TESTS or KEPLER_CONF.."/tests" local path_info = cgilua.script_vpath local cmd, rest = cgilua.splitonfirst(path_info) cmd = cmd or "all" -- Finds all available modules local modules = {} for dir in lfs.dir(SHAKE_TESTS) do local attr = lfs.attributes (SHAKE_TESTS.."/"..dir) if attr.mode == "directory" and dir ~= "." and dir ~= ".." then table.insert(modules, dir) end end table.sort(modules) local run = shake.runner() local curr_dir = lfs.currentdir () if cmd == "all" then -- Shakes all modules for _, module_name in ipairs(modules) do lfs.chdir(SHAKE_TESTS.."/"..module_name) run:test("test.lua", module_name) lfs.chdir("..") end lfs.chdir(curr_dir) local env = { SHAKE_TESTS = SHAKE_TESTS, ListModules = ListModules(modules), ReportModules = ReportModules(run), ShakeSummary = ShakeSummary(run), cgilua = cgilua } cgilua.handlelp("shake.lp", env) elseif cmd == "module" then -- Shakes a single module local module_name = cgilua.splitonfirst(rest) lfs.chdir(SHAKE_TESTS.."/"..module_name) run:test("test.lua", module_name) lfs.chdir(curr_dir) local env = { SHAKE_TESTS = SHAKE_TESTS, module_name = module_name, ListModules = ListModules(modules), ReportModule = ReportModule(run, module_name), ModuleSummary = ModuleSummary(run, module_name), ShakeSummary = ShakeSummary(run), cgilua = cgilua } cgilua.handlelp("shake_suite.lp", env) else -- processes resource URLs cgilua.handle(cgilua.script_pdir..path_info) end return trueshake-1.0.2/src/apps/shake/shake.lp000066400000000000000000000037111076752415300170760ustar00rootroot00000000000000 Shake Tests " type="text/css"/> " type="text/css"/>

    Shake Summary

    Here you have the number of tests, failures and errors for every test module in <%= SHAKE_TESTS %>

    <% ReportModules() %>
    Tests Failures Errors
    <% ShakeSummary() %>





    Valid XHTML 1.0

    $Id: shake.lp,v 1.4 2007/11/16 16:26:10 carregal Exp $

    shake-1.0.2/src/apps/shake/shake_suite.lp000066400000000000000000000037401076752415300203110ustar00rootroot00000000000000 Shake Tests " type="text/css"/> " type="text/css"/>

    Shake details for the <%= module_name %> module

    Here you have a more detailed view of the <%= module_name %> module tests results: <% ModuleSummary() %>
    Tests Failures Errors
    <% ReportModule() %> <% ShakeSummary() %>





    Valid XHTML 1.0

    $Id: shake_suite.lp,v 1.4 2007/11/16 16:26:10 carregal Exp $

    shake-1.0.2/src/bin/000077500000000000000000000000001076752415300141565ustar00rootroot00000000000000shake-1.0.2/src/bin/shake000066400000000000000000000044561076752415300152050ustar00rootroot00000000000000#!/usr/bin/env lua ------------------------------------------------------------------------------- -- Command line runner for Shake -- -- Authors: Andre Carregal, Humberto dos Anjos -- Copyright (c) 2007 Kepler Project -- -- $Id: shake,v 1.16 2008/03/04 21:51:18 carregal Exp $ ------------------------------------------------------------------------------- require"shake" -- Shake looks first for a shake_test file and runs it if present, -- otherwise it looks for a user_test file and runs it if present local shake_test = "shake_test.lua" local user_test = "test.lua" local recursive = false -- checks for recursive flag if arg[1] == "-r" or arg[1] == "--recursive" then recursive = true table.remove(arg, 1) end -- checks for version flag if arg[1] == "-v" or arg[1] == "--version" then print (shake._VERSION) os.exit(0) end -- checks for help flag if arg[1] == "-h" or arg[1] == "--help" then print (shake._DESCRIPTION.."\n\n"..[[ Usage: shake [options] [filename] Runs a test file called filename (assuming "]]..user_test..[[" by default) in the current directory or any of its subdirectories if the -r option is given. Options: -h, --help Prints this help message -r, --recursive Recursively scans subdirectories for "]]..user_test..[[" files and runs them -v, --version Prints the Shake version ]]) os.exit(0) end local filename = arg[1] or user_test _tested = false local run = shake.runner() local function _testlocal(title) local f, errmsg = loadfile(shake_test) if f then -- passes the runner to shake_test f(run) return true end f, errmsg = io.open(filename) if f then run:test(filename, title) return true end end local function _iterate(path) path = path or "" for dir in lfs.dir(".") do local attr = lfs.attributes (dir) or {} if attr.mode == "directory" and dir ~= "." and dir ~= ".." then lfs.chdir(dir) if _testlocal(path.."/"..dir) then _tested = true else _iterate(dir) end lfs.chdir("..") end end end if recursive then print("Shaking the tree...\n") end if _testlocal() then _tested = true elseif recursive then _iterate() end if _tested then print(run:summary()) else print("No test files found") end if run.results.errors > 0 then os.exit(1) endshake-1.0.2/src/bin/shake.bat000066400000000000000000000000601076752415300157350ustar00rootroot00000000000000@echo off c:\lua5.1\lua5.1 c:\lua5.1\shake %1 %2shake-1.0.2/src/shake/000077500000000000000000000000001076752415300145015ustar00rootroot00000000000000shake-1.0.2/src/shake/shake.lua000066400000000000000000000243331076752415300163040ustar00rootroot00000000000000------------------------------------------------------------------------------- -- Shake, a simple test engine for Lua -- -- Authors: Andre Carregal, Humberto dos Anjos -- Copyright (c) 2007 Kepler Project -- -- $Id: shake.lua,v 1.14 2008/03/17 17:20:43 carregal Exp $ ------------------------------------------------------------------------------- local io = require "io" local lfs = require "lfs" local table = require "table" local string = require "string" local _G, error, unpack, loadstring, pcall, xpcall, ipairs, setmetatable, setfenv, loadfile, dofile = _G, error, unpack, loadstring, pcall, xpcall, ipairs, setmetatable, setfenv, loadfile, dofile require "shake.stir" -- tries to get the debug table local debug = debug if not next(debug) then -- uses a stub when debug information is not available debug = { getinfo = function() return {linenumber = "???"} end, traceback = function() return "No traceback information: debug is not available" end, } end local getinfo = debug.getinfo local traceback = debug.traceback module(...) _COPYRIGHT = "Copyright (C) 2007 Kepler Project" _DESCRIPTION = "Shake is a simple and transparent test engine for Lua that assumes that tests only use standard assert and print calls." _VERSION = "Shake 1.0.2" ----------- local functions ------------ -- Version of loadstring that stirs the file before compiling it local function _loadstring(s, filename) s = string.gsub(s, "^#![^\n]*\n", "-- keeps one line in place of an eventual one with a #! at the start\n") s = stir(s) return loadstring(s, filename) end -- Version of loadfile that stirs the file before compiling it local function _loadfile(filename) local f local file = io.open(filename) if not file then return else local s = file:read'*a' f, errmsg = _loadstring(s, filename) end return f, errmsg end -- Version of dostring that stirs the string before executing it local function _dostring(s, filename) local results = {pcall(_loadstring(s, filename))} if results[1] then table.remove(results, 1) end return unpack(results) end -- Version of dofile that stirs the file before executing it local function _dofile(filename) local results = {pcall(_loadfile(filename))} if results[1] then table.remove(results, 1) end return unpack(results) end -- Returns a new suite local function _newsuite(filename, title, errmsg) local source = {} if not errmsg then for line in io.lines(filename) do source[#source + 1] = line end end return {title = title, filename = filename, passed = 0, failed = 0, error = errmsg, source = source, contexts = {} } end -- Returns a new context local function _newcontext(...) return {output = {...}, passed = 0, failed = 0, tests = {} } end -- Returns a contextualized assert() function _newassert(suite, context) return function(val1, op, val2, msg, exp1, exp2, comments) if comments then context = _newcontext(comments) suite.contexts[#suite.contexts + 1] = context end local test = { message = msg or "" } context.tests[#context.tests + 1] = test local PASSED = false if not op then PASSED = val1 elseif op == '==' then PASSED = val1 == val2 elseif op == '~=' then PASSED = val1 ~= val2 end if PASSED then context.passed = context.passed + 1 suite.passed = suite.passed + 1 else context.failed = context.failed + 1 suite.failed = suite.failed + 1 end test.val1 = val1 test.op = op test.val2 = val2 test.exp1 = exp1 test.exp2 = exp2 test.msg = msg test.passed = PASSED test.linenumber = getinfo(2, "l").currentline test.traceback = traceback("", 2) return PASSED, msg end end ------------------------------------------------------------------------------- -- Runs a suite of tests from filename using a title -- Test results are added to the results table ------------------------------------------------------------------------------- local function _test(self, filename, title) f, errmsg = _loadfile(filename) local results = self.results title = title or "" if not f then -- error loading the file errmsg = string.gsub(errmsg, '%[string "'..filename..'"%]', filename) results.suites[#results.suites + 1] = _newsuite(filename, title, errmsg) results.errors = results.errors + 1 else -- runs the test suite local _print = _G.print local _write = _G.io.write local ___STIR_assert = _G.___STIR_assert local lf = _G.loadfile local df = _G.dofile local ls = _G.loadstring local ds = _G.dostring _G.loadfile = _loadfile _G.dofile = _dofile _G.loadstring = _loadstring _G.dostring = _dostring local suite = _newsuite(filename, title) local context = _newcontext("") _G.___STIR_assert = _newassert(suite, context) -- so assertions works even without a previous context suite.contexts[#suite.contexts + 1] = context -- separate contexts at every print or io.write -- keeping the output stored in the context table _G.print = function(...) local context = suite.contexts[#suite.contexts] if context.passed + context.failed > 0 then -- create a new context if there was an assert before the previous context context = _newcontext(...) suite.contexts[#suite.contexts + 1] = context else -- converts all parameters to strings local temp = {} for i = 1, _G.select('#',...) do table.insert(temp, _G.tostring(_G.select(i,...))) end -- and concatenates them context.output[#context.output + 1] = table.concat(temp, "\t") end _G.___STIR_assert = _newassert(suite, context) end _G.io.write = _G.print -- executes the suite local res, errmsg = xpcall(f, function(err) return err end) if not res then -- error executing the suite errmsg = errmsg or "" suite.error = string.gsub(errmsg, '%[string "'..filename..'"%]', filename) results.errors = results.errors + 1 end results.passed = results.passed + suite.passed results.failed = results.failed + suite.failed results.suites[#results.suites + 1] = suite -- restores the environment _G.loadfile = lf _G.dofile = df _G.loadstring = ls _G.dostring = ds _G.print = _print _G.io.write = _write _G.___STIR_assert = ___STIR_assert end end ------------------------------------------------------------------------------- -- Returns a summary of the test results using an optional line separator ------------------------------------------------------------------------------- local function _summary(self, sep) local out = {} local results = self.results sep = sep or "\n" for cs, suite in ipairs(results.suites) do if suite.error then out[#out + 1] = ">>>>>>>>>>>>>>>> "..suite.title.." "..suite.filename.." has an error!!!".." <<<<<<<<<<<<<<<<" out[#out + 1] = "" out[#out + 1] = suite.error out[#out + 1] = "" elseif suite.failed > 0 then out[#out + 1] = "---------------- "..suite.title.." "..suite.filename.." failed!".." ----------------" for cg, context in ipairs(suite.contexts) do if context.failed > 0 then out[#out + 1] = "" for _, output in ipairs(context.output) do out[#out + 1] = _G.tostring(output) end if context.comments then out[#out + 1] = context.comments end for ct, test in ipairs (context.tests) do if not test.passed then if suite.source[test.linenumber] then out[#out + 1] = " #"..test.linenumber.." "..suite.source[test.linenumber] end if not isTerminal(test.exp1, test.val1) then out[#out + 1] = " "..test.exp1.." -> ".._G.tostring(test.val1) end if not isTerminal(test.exp2, test.val2) then out[#out + 1] = " "..test.exp2.." -> ".._G.tostring(test.val2) end end end end end else out[#out + 1] = "-> "..suite.title.." "..suite.filename.." OK!" end end out[#out + 1] = "_________________" out[#out + 1] = "" out[#out + 1] = "Tests: "..results.failed + results.passed out[#out + 1] = "Failures: "..results.failed out[#out + 1] = "Errors: "..results.errors out[#out + 1] = "" return table.concat(out, sep) end ---------- Public functions -------------- ------------------------------------------------------------------------------- -- Returns a new runner with the functions -- test(filename) -- summary() ------------------------------------------------------------------------------- function runner() local runner = {results = {passed = 0, failed = 0, errors = 0, suites = {} } } setmetatable(runner, {__index = {test = _test, summary = _summary} }) return runner end ------------------------------------------------------------------------------- -- Checks if an expression string represents a terminal value ------------------------------------------------------------------------------- function isTerminal(exp, val) if not exp then return true end local chunk = loadstring('return '..exp) local env = {} setmetatable(env, {__index = function() return "___nil___" end}) setfenv(chunk, env) local status, ret = pcall(chunk) if status then return ret == val end end shake-1.0.2/src/shake/stir.lua000066400000000000000000000155241076752415300161740ustar00rootroot00000000000000-- basic modules local _G = _G local string = string local table = table -- basic functions local ipairs = ipairs local pairs = pairs local print = print local require = require local tostring = tostring local type = type -- imported modules local m = require 'lpeg' local scanner = require 'leg.scanner' local parser = require 'leg.parser' local grammar = require 'leg.grammar' -- module declaration module 'shake' -- HELPER VALUES AND FUNCTIONS ------------ -- matches one or more "ignorable" strings (spaces or comments) local S = scanner.IGNORED -- matches all space characters local SPACES = scanner.SPACE^0 -- pretty-prints a list on screen, here for debugging purposes local function list2string(t, level) level = level or 0 local indent = string.rep(' ', level) if type(t) == 'string' then return string.format('%q', tostring(t)) --return scanner.text2string(t) elseif type(t) ~= 'table' then return tostring(t) else local str = '{' for k, v in pairs(t) do str = str..'\n'..indent..' ['..list2string(k)..'] = ' ..list2string(v, level + 1) end return str..'\n'..indent..'}' end end -- removes the final newline character from comments local function removeNewline(comment) if type(comment) == 'string' then -- it's a single comment if comment:sub(-1, -1) == '\n' then return comment:sub(1, -2) else return comment end elseif type(comment) == 'table' then -- it's a list of comments for i, v in ipairs(comment) do comment[i] = removeNewline(v) end return comment end end -- Lua 5.1 operator precedence table local ops = { ['or'] = { precedence = 1, left = true, arity = 2 }, ['and'] = { precedence = 2, left = true, arity = 2 }, ['=='] = { precedence = 3, left = true, arity = 2 }, ['~='] = { precedence = 3, left = true, arity = 2 }, ['<='] = { precedence = 3, left = true, arity = 2 }, ['>='] = { precedence = 3, left = true, arity = 2 }, ['<'] = { precedence = 3, left = true, arity = 2 }, ['>'] = { precedence = 3, left = true, arity = 2 }, ['..'] = { precedence = 4, right = true, arity = 2 }, ['+'] = { precedence = 5, left = true, arity = 2 }, ['-'] = { precedence = 5, left = true, arity = 2 }, ['*'] = { precedence = 6, left = true, arity = 2 }, ['/'] = { precedence = 6, left = true, arity = 2 }, ['%'] = { precedence = 6, left = true, arity = 2 }, ['not'] = { precedence = 7, arity = 1 }, ['#'] = { precedence = 7, arity = 1 }, ['unm'] = { precedence = 7, arity = 1 }, ['^'] = { precedence = 8, right = true, arity = 2 } } -- operator precedence algorithm, adapted to find the outmost binary operator's -- index in list local function getOuterOp(list) local stack = {} local function makeNode(index, node) return { index = index, node = node } end for i, v in ipairs(list) do if ops[v] then -- it's an operator, and in this case, binary local top, op = stack[#stack], ops[v] while top and ((op.right and op.precedence < ops[top.node].precedence) or (op.left and op.precedence <= ops[top.node].precedence)) do table.remove(stack) top = stack[#stack] end stack[#stack + 1] = makeNode(i, v) end end -- getting the outmost operator's index return stack[1] and stack[1].index end -- SPECIAL TOKENS ------------------------ -- pretty obvious, isn't it? local OPEN = S* m.P'(' -- same here local CLOSE = S* m.P')' -- self explaining pattern local COMMA = S* m.P',' -- the special operators, here == and ~= local OP = S* m.C(m.P'~=' + m.P'==') -- matches and captures a Lua expression. The capture may return either a -- single expression or an expression, an operator (matched by OP) and an -- expression local EXP = S* (grammar.apply(parser.rules, m.C(m.V'_SimpleExp') * (S* m.C(m.V'BinOp') *S* m.C(m.V'_SimpleExp'))^0, { -- the capture table [1] = function (...) local infix = { ... } local outerOp = getOuterOp(infix) if OP:match(infix[outerOp] or '') then -- return the left side, the operator, and the right side separately return table.concat(infix, ' ', 1, outerOp - 1), infix[outerOp], table.concat(infix, ' ', outerOp + 1) else -- return the whole expression return table.concat(infix, ' ') end end, })) -- matches and captures the message local MSG = S* m.C(grammar.apply(parser.rules, m.V'Exp')) -- matches and captures one or more comments, separated at most by one newline local COMMENT = m.C((scanner.COMMENT * m.P'\n'^-1) ^ 1) -- makes it easier for optional patterns with overarching captures local EPSILON = m.P'' / function() return nil end -- PATTERNS --------------------------------- -- matches an expression EXP and packages its captures in a table local LINE = EXP / function (exp1, op, exp2) return { exp1 = exp1, op = op, exp2 = exp2 } end -- matches an assert call and packages all relevant information in a table local ASSERT = ((COMMENT + EPSILON) *SPACES* m.Cp() * m.P'assert' * OPEN * LINE * ((COMMA * MSG) + EPSILON) * CLOSE * m.Cp()) / function (comment, start, line, msg, finish) return { start = start, comment = (comment ~= nil) and removeNewline(comment) or nil, exp = line, msg = msg, finish = finish, } end -- matches all ASSERTs in a given input and packages them in a list local ALL = m.Ct((ASSERT + 1)^0) -- FUNCTIONS --------------------------------- -- takes an ASSERT capture and builds the equivalent [assertName] call local function buildNewAssert(info, assertName) local exp1, op, exp2 = info.exp.exp1, info.exp.op, info.exp.exp2 local comment, msg, text = info.comment, info.msg, info.text local newassert = '' local str1 = scanner.text2string(exp1) local str2 = (exp2 == nil) and 'nil' or scanner.text2string(exp2) local com = (comment == nil) and 'nil' or scanner.text2string(comment) local textStr = scanner.text2string(text) return newassert..assertName..'('..exp1 ..', '..(op and '"'..op..'"' or 'nil') ..', '..(exp2 or 'nil') ..', '..(msg or 'nil') ..', '..str1 ..', '..str2 ..', '..com ..', '..textStr ..')' end -- replaces str's substring from i to j with new_str local function sub(str, new_str, i, j) i, j = i or 1, j or #str return str:sub(1, i - 1)..new_str..str:sub(j) end -- replaces all asserts in input by their ___STIR_assert counterparts function stir(input, assertName) assertName = assertName or '___STIR_assert' local asserts = ALL:match(input) for i = #asserts, 1, -1 do local v = asserts[i] v.text = input:sub(v.start, v.finish) input = sub(input, buildNewAssert(v, assertName), v.start, v.finish) end return input endshake-1.0.2/src/web/000077500000000000000000000000001076752415300141635ustar00rootroot00000000000000shake-1.0.2/src/web/css/000077500000000000000000000000001076752415300147535ustar00rootroot00000000000000shake-1.0.2/src/web/css/shake.css000066400000000000000000000020701076752415300165570ustar00rootroot00000000000000/* Shake Stylesheet */ /* Copyright 2007 Kepler Project */ /* $Id: shake.css,v 1.2 2007/10/29 20:19:05 carregal Exp $ */ div.shakecontext { background-color: rgb(245, 245, 245); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: silver; border-right-color: silver; border-bottom-color: silver; border-left-color: silver; padding: 1em; margin-left: 1em; margin-right: 1em; margin-top: 3em; margin-bottom: 1em; font-family: "Andale Mono", monospace; font-size: smaller; } table.shake { padding: 1em; margin-top: 2em; margin-bottom: 2em; } table.shake th { text-align:left; background-color: #E7E7E7; } table.shake thead th {text-align:center} table.shake td {text-align:center} table.shake td.passed {} table.shake td.failed {background-color:#F0E68C} table.shake td.noerror {} table.shake td.error {background-color:#FFA07A}shake-1.0.2/tests/000077500000000000000000000000001076752415300137615ustar00rootroot00000000000000shake-1.0.2/tests/test.lua000066400000000000000000000040641076752415300154470ustar00rootroot00000000000000------------------------------------------------------------------------------- -- Test suite for Shake -- -- Authors: Andre Carregal -- Copyright (c) 2007 Kepler Project -- -- $Id: test.lua,v 1.2 2007/10/24 23:41:05 carregal Exp $ ------------------------------------------------------------------------------- require"shake" local run local summary local results -- checks if correct tests passes run = shake.runner() run:test("test1_ok.lua") run:test("test2_ok.lua") results = run.results assert(results.passed == 3, "Unexpected tests in results!") assert(results.failed == 0, "Unexpected failures in results!") assert(results.errors == 0, "Unexpected errors in results!") assert(#results.suites == 2, "Unexpected suites in results!") assert(#results.suites[1].contexts == 1, "Unexpected groups in results!") summary = run:summary() assert(string.find(summary, "failed!") == nil, "Summary contains a failure message") assert(string.find(summary, "has an error!!!") == nil, "Summary contains an error message") -- checks if Shake is detecting failures run = shake.runner() run:test("test1_fail.lua") results = run.results assert(results.passed == 0, "Unexpected tests in results!") assert(results.failed == 6, "Unexpected failures in results!") assert(results.errors == 0, "Unexpected errors in results!") summary = run:summary() assert(string.find(summary, "failed!"), "Summary does not contains a failure message") assert(string.find(summary, "has an error!!!") == nil, "Summary contains an error message") -- checks if Shake is detecting errors run = shake.runner() run:test("test1_error.lua") results = run.results assert(results.passed == 0, "Unexpected tests in results!") assert(results.failed == 0, "Unexpected failures in results!") assert(results.errors == 1, "Unexpected errors in results!") summary = run:summary() -- checks for a failure assert(string.find(summary, "failed!") == nil, "Summary contains a failure message") -- there should be one error in the summary assert(string.find(summary, "has an error!!!"), "Summary does not contains an error message") shake-1.0.2/tests/test1_error.lua000066400000000000000000000010611076752415300167330ustar00rootroot00000000000000------------------------------------------------------------------------------- -- Fake test suite for Shake -- -- Authors: Andre Carregal -- Copyright (c) 2007 Kepler Project -- -- $Id: test1_error.lua,v 1.1 2007/10/23 02:39:40 carregal Exp $ ------------------------------------------------------------------------------- print("Forcing an error") assert(_not_a_table.field == 1, "Strings don't have fields!") print("Agrouping contexts") print("(for an error)") assert(true, "this should not be considered a test since the previous error will stop the run")shake-1.0.2/tests/test1_fail.lua000066400000000000000000000014641076752415300165240ustar00rootroot00000000000000------------------------------------------------------------------------------- -- Fake test suite for Shake -- -- Authors: Andre Carregal -- Copyright (c) 2007 Kepler Project -- -- $Id: test1_fail.lua,v 1.2 2007/10/24 23:41:05 carregal Exp $ ------------------------------------------------------------------------------- print("Forcing a failure") assert(true == false, "booleans went south!") print("Agrouping contexts") assert(x == 3) print("using print") assert(true == false, "true went south!") -- testing the comments for a new context assert(x == 2, "what x?") print("this should not create a new context") print("nor this") print("but this one should") assert (function() return end == 4 + 34) -- and you can create contexts -- by using a multi line comment -- too assert(x == 6, "see?")shake-1.0.2/tests/test1_ok.lua000066400000000000000000000006231076752415300162160ustar00rootroot00000000000000------------------------------------------------------------------------------- -- Fake test suite for Shake -- -- Authors: Andre Carregal -- Copyright (c) 2007 Kepler Project -- -- $Id: test1_ok.lua,v 1.1 2007/10/23 02:39:40 carregal Exp $ ------------------------------------------------------------------------------- print("This simple test always passes") assert(true == true, "true went postal!")shake-1.0.2/tests/test2_ok.lua000066400000000000000000000007241076752415300162210ustar00rootroot00000000000000------------------------------------------------------------------------------- -- Fake test suite for Shake -- -- Authors: Andre Carregal -- Copyright (c) 2007 Kepler Project -- -- $Id: test2_ok.lua,v 1.1 2007/10/23 02:39:40 carregal Exp $ ------------------------------------------------------------------------------- print("This simple test always passes") assert(true == true, "true went postal!") print("Agrouping contexts") print("(for a pass)") assert (true)