From f47ff4dcb4f6305946a162db9734475633fe17bd Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Mon, 10 Nov 2014 11:39:17 +0400 Subject: [PATCH] Init commit. --- .gitignore | 4 + .travis.yml | 36 +++++ .travis/platform.sh | 15 ++ .travis/setup_lua.sh | 96 +++++++++++++ lakeconfig.lua | 260 +++++++++++++++++++++++++++++++++++ lakefile | 33 +++++ msvc/try.sln | 20 +++ msvc/try.vcproj | 196 ++++++++++++++++++++++++++ rockspecs/try-scm-0.rockspec | 32 +++++ src/try.c | 196 ++++++++++++++++++++++++++ test/test.lua | 167 ++++++++++++++++++++++ 11 files changed, 1055 insertions(+) create mode 100644 .travis.yml create mode 100644 .travis/platform.sh create mode 100644 .travis/setup_lua.sh create mode 100644 lakeconfig.lua create mode 100644 lakefile create mode 100644 msvc/try.sln create mode 100644 msvc/try.vcproj create mode 100644 rockspecs/try-scm-0.rockspec create mode 100644 src/try.c create mode 100644 test/test.lua diff --git a/.gitignore b/.gitignore index edf6645..a0f490b 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,7 @@ *.i*86 *.x86_64 *.hex + +# +*.exp +*.d \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..1c89bb9 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,36 @@ +language: c + +env: + global: + - LUAROCKS=2.2.0 + matrix: + - LUA=lua5.1 + - LUA=lua5.2 + - LUA=luajit + +services: + - memcached + +branches: + only: + - master + +before_install: + - bash .travis/setup_lua.sh + - sudo luarocks install lunitx + - sudo pip install cpp-coveralls + +install: + - sudo luarocks make rockspecs/try-scm-0.rockspec CFLAGS="-O2 -fPIC -ftest-coverage -fprofile-arcs" LIBFLAG="-shared --coverage" + +script: + - cd test + - lunit.sh test.lua + +after_success: + - coveralls -b .. -r .. + +notifications: + email: + on_success: change + on_failure: always diff --git a/.travis/platform.sh b/.travis/platform.sh new file mode 100644 index 0000000..4a3af0d --- /dev/null +++ b/.travis/platform.sh @@ -0,0 +1,15 @@ +if [ -z "$PLATFORM" ]; then + PLATFORM=$TRAVIS_OS_NAME; +fi + +if [ "$PLATFORM" == "osx" ]; then + PLATFORM="macosx"; +fi + +if [ -z "$PLATFORM" ]; then + if [ "$(uname)" == "Linux" ]; then + PLATFORM="linux"; + else + PLATFORM="macosx"; + fi; +fi diff --git a/.travis/setup_lua.sh b/.travis/setup_lua.sh new file mode 100644 index 0000000..c44b79a --- /dev/null +++ b/.travis/setup_lua.sh @@ -0,0 +1,96 @@ +#! /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 + +LUAJIT_BASE="LuaJIT-2.0.3" + +source .travis/platform.sh + +LUAJIT="no" + +if [ "$PLATFORM" == "macosx" ]; then + if [ "$LUA" == "luajit" ]; then + LUAJIT="yes"; + fi + if [ "$LUA" == "luajit2.0" ]; then + LUAJIT="yes"; + fi + if [ "$LUA" == "luajit2.1" ]; then + LUAJIT="yes"; + fi; +elif [ "$(expr substr $LUA 1 6)" == "luajit" ]; then + LUAJIT="yes"; +fi + +if [ "$LUAJIT" == "yes" ]; then + + if [ "$LUA" == "luajit" ]; then + curl http://luajit.org/download/$LUAJIT_BASE.tar.gz | tar xz; + else + git clone http://luajit.org/git/luajit-2.0.git $LUAJIT_BASE; + fi + + cd $LUAJIT_BASE + + if [ "$LUA" == "luajit2.1" ]; then + git checkout v2.1; + fi + + make && sudo make install + + if [ "$LUA" == "luajit2.1" ]; then + sudo ln -s /usr/local/bin/luajit-2.1.0-alpha /usr/local/bin/luajit + sudo ln -s /usr/local/bin/luajit /usr/local/bin/lua; + else + sudo ln -s /usr/local/bin/luajit /usr/local/bin/lua; + fi; + +else + if [ "$LUA" == "lua5.1" ]; then + curl http://www.lua.org/ftp/lua-5.1.5.tar.gz | tar xz + cd lua-5.1.5; + elif [ "$LUA" == "lua5.2" ]; then + curl http://www.lua.org/ftp/lua-5.2.3.tar.gz | tar xz + cd lua-5.2.3; + fi + sudo make $PLATFORM install; +fi + +cd $TRAVIS_BUILD_DIR; + +LUAROCKS_BASE=luarocks-$LUAROCKS + +# curl http://luarocks.org/releases/$LUAROCKS_BASE.tar.gz | tar xz + +git clone https://github.com/keplerproject/luarocks.git $LUAROCKS_BASE +cd $LUAROCKS_BASE + +git checkout v$LUAROCKS + +if [ "$LUA" == "luajit" ]; then + ./configure --lua-suffix=jit --with-lua-include=/usr/local/include/luajit-2.0; +elif [ "$LUA" == "luajit2.0" ]; then + ./configure --lua-suffix=jit --with-lua-include=/usr/local/include/luajit-2.0; +elif [ "$LUA" == "luajit2.1" ]; then + ./configure --lua-suffix=jit --with-lua-include=/usr/local/include/luajit-2.1; +else + ./configure; +fi + +make build && sudo make install + +cd $TRAVIS_BUILD_DIR + +rm -rf $LUAROCKS_BASE + +if [ "$LUAJIT" == "yes" ]; then + rm -rf $LUAJIT_BASE; +elif [ "$LUA" == "lua5.1" ]; then + rm -rf lua-5.1.5; +elif [ "$LUA" == "lua5.2" ]; then + rm -rf lua-5.2.3; +fi diff --git a/lakeconfig.lua b/lakeconfig.lua new file mode 100644 index 0000000..0125d13 --- /dev/null +++ b/lakeconfig.lua @@ -0,0 +1,260 @@ +local io = require "io" +io.stdout:setvbuf"no" +io.stderr:setvbuf"no" + +function vc_version() + local VER = lake.compiler_version() + MSVC_VER = ({ + [15] = '9'; + [16] = '10'; + })[VER.MAJOR] or '' + return MSVC_VER +end + +if not L then + +local function arkey(t) + assert(type(t) == 'table') + local keys = {} + for k in pairs(t) do + assert(type(k) == 'number') + table.insert(keys, k) + end + table.sort(keys) + return keys +end + +local function ikeys(t) + local keys = arkey(t) + local i = 0 + return function() + i = i + 1 + local k = keys[i] + if k == nil then return end + return k, t[k] + end +end + +local function expand(arr, t) + if t == nil then return arr end + + if type(t) ~= 'table' then + table.insert(arr, t) + return arr + end + + for _, v in ikeys(t) do + expand(arr, v) + end + + return arr +end + +function L(...) + return expand({}, {...}) +end + +end + +J = J or path.join + +IF = IF or lake.choose or choose + +DIR_SEP = package.config:sub(1,1) + +function prequire(...) + local ok, mod = pcall(require, ...) + if ok then return mod end +end + +function clone(t, o) + o = o or {} + for k, v in pairs(t) do + if o[k] == nil then o[k] = v end + end + return o +end + +function each_join(dir, list) + for i, v in ipairs(list) do + list[i] = path.join(dir, v) + end + return list +end + +function run(file, cwd) + print() + print("run " .. file) + if not TESTING then + if cwd then lake.chdir(cwd) end + local status, code = utils.execute( LUA_RUNNER .. ' ' .. file ) + if cwd then lake.chdir("<") end + print() + return status, code + end + return true, 0 +end + +function exec(file, cwd) + print() + print("exec " .. file) + if not TESTING then + if cwd then lake.chdir(cwd) end + local status, code = utils.execute( file ) + if cwd then lake.chdir("<") end + print() + return status, code + end + return true, 0 +end + +local TESTS = {} + +function run_test(name, params) + local test_dir = TESTDIR or J(ROOT, 'test') + local cmd = J(test_dir, name) + if params then cmd = cmd .. ' ' .. params end + local ok = run(cmd, test_dir) + + table.insert(TESTS, {cmd = cmd, result = ok}) + + print("TEST " .. name .. (ok and ' - pass!' or ' - fail!')) +end + +function exec_test(name, params) + local test_dir = TESTDIR or J(ROOT, 'test') + local cmd = J(test_dir, name) + if params then cmd = cmd .. ' ' .. params end + local ok = exec(cmd, test_dir) + + table.insert(TESTS, {cmd = cmd, result = ok}) + + print("TEST " .. name .. (ok and ' - pass!' or ' - fail!')) +end + +function test_summary() + local ok = true + print("") + print("------------------------------------") + print("Number of tests:", #TESTS) + for _, t in ipairs(TESTS) do + ok = ok and t.result + print((t.result and ' Pass' or ' Fail') .. " - TEST " .. t.cmd) + end + print("------------------------------------") + print("") + return ok +end + +--[[spawn]] if WINDOWS then + function spawn(file, cwd) + local winapi = prequire "winapi" + if not winapi then + quit('needs winapi for spawn!') + return false + end + + print("spawn " .. file) + if not TESTING then + if cwd then lake.chdir(cwd) end + assert(winapi.shell_exec(nil, LUA_RUNNER, file, cwd)) + if cwd then lake.chdir("<") end + print() + end + return true + end +else + function spawn(file, cwd) + print("spawn " .. file) + if not TESTING then + assert(run(file .. ' &', cwd)) + end + return true + end +end + +function as_bool(v,d) + if v == nil then return not not d end + local n = tonumber(v) + if n == 0 then return false end + if n then return true end + return false +end + +--- set global variables +-- LUA_NEED +-- LUA_DIR +-- LUA_RUNNER +-- ROOT +-- LUADIR +-- LIBDIR +-- TESTDIR +-- DOCDIR +-- DYNAMIC +function INITLAKEFILE() + if LUA_VER == '5.3' then + LUA_NEED = 'lua53' + LUA_DIR = ENV.LUA_DIR_5_3 or ENV.LUA_DIR + LUA_RUNNER = LUA_RUNNER or 'lua53' + elseif LUA_VER == '5.2' then + LUA_NEED = 'lua52' + LUA_DIR = ENV.LUA_DIR_5_2 or ENV.LUA_DIR + LUA_RUNNER = LUA_RUNNER or 'lua52' + elseif LUA_VER == '5.1' then + LUA_NEED = 'lua51' + LUA_DIR = ENV.LUA_DIR + LUA_RUNNER = LUA_RUNNER or 'lua' + else + LUA_NEED = 'lua' + LUA_DIR = ENV.LUA_DIR + LUA_RUNNER = LUA_RUNNER or 'lua' + end + ROOT = ROOT or J( LUA_DIR, 'libs', PROJECT ) + LUADIR = LUADIR or J( ROOT, 'share' ) + LIBDIR = LIBDIR or J( ROOT, 'share' ) + TESTDIR = TESTDIR or J( ROOT, 'test' ) + DOCDIR = DOCDIR or J( ROOT, 'doc' ) + DYNAMIC = as_bool(DYNAMIC, false) +end + +----------------------- +-- needs -- +----------------------- + +lake.define_need('lua53', function() + return { + incdir = J(ENV.LUA_DIR_5_3, 'include'); + libdir = J(ENV.LUA_DIR_5_3, 'lib'); + libs = {'lua53'}; + } +end) + +lake.define_need('lua52', function() + return { + incdir = J(ENV.LUA_DIR_5_2, 'include'); + libdir = J(ENV.LUA_DIR_5_2, 'lib'); + libs = {'lua52'}; + } +end) + +lake.define_need('lua51', function() + return { + incdir = J(ENV.LUA_DIR, 'include'); + libdir = J(ENV.LUA_DIR, 'lib'); + libs = {'lua5.1'}; + } +end) + +local UV_DIR = UV_DIR or ENV.UV_DIR or J(ENV.CPPLIB_DIR, 'uv') + +lake.define_need('libuv', function() + return { + incdir = J(UV_DIR, 'include'); + libdir = J(UV_DIR, 'lib'); + libs = {'libuv'}; + } +end) + +lake.define_need('winsock2', function() + return {libs = {"ws2_32"}} +end) \ No newline at end of file diff --git a/lakefile b/lakefile new file mode 100644 index 0000000..3e5b31f --- /dev/null +++ b/lakefile @@ -0,0 +1,33 @@ +PROJECT = 'try' + +INITLAKEFILE() + +DEFINES = L{DEFINES, + IF(WINDOWS, 'DLL_EXPORT', ''); +} + +try = c.shared{'try', + base = 'src', + src = '*.c', + needs = {LUA_NEED}, + defines = DEFINES, + dynamic = DYNAMIC, + strip = true, +} + +target('build', try) + +install = target('install', { + file.group{odir=LIBDIR; src = try }; + -- file.group{odir=LIBDIR; src = J("src", "lua") ; recurse = true }; + -- file.group{odir=J(ROOT, 'examples'); src = 'examples'; recurse = true }; + file.group{odir=TESTDIR; src = 'test'; recurse = true }; +}) + +target('test', install, function() + run_test('test.lua') + + if not test_summary() then + quit("test fail") + end +end) \ No newline at end of file diff --git a/msvc/try.sln b/msvc/try.sln new file mode 100644 index 0000000..0c343ae --- /dev/null +++ b/msvc/try.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "try", "try.vcproj", "{C9D035B7-BBF9-4D7A-960F-B8ED2CB6FF8E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C9D035B7-BBF9-4D7A-960F-B8ED2CB6FF8E}.Debug|Win32.ActiveCfg = Debug|Win32 + {C9D035B7-BBF9-4D7A-960F-B8ED2CB6FF8E}.Debug|Win32.Build.0 = Debug|Win32 + {C9D035B7-BBF9-4D7A-960F-B8ED2CB6FF8E}.Release|Win32.ActiveCfg = Release|Win32 + {C9D035B7-BBF9-4D7A-960F-B8ED2CB6FF8E}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/msvc/try.vcproj b/msvc/try.vcproj new file mode 100644 index 0000000..f8ff092 --- /dev/null +++ b/msvc/try.vcproj @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rockspecs/try-scm-0.rockspec b/rockspecs/try-scm-0.rockspec new file mode 100644 index 0000000..1694465 --- /dev/null +++ b/rockspecs/try-scm-0.rockspec @@ -0,0 +1,32 @@ +package = "try" +version = "scm-0" + +source = { + url = "https://github.com/moteus/lua-try/archive/master.zip", + dir = "lua-try-master", +} + +description = { + summary = "Simple exception support based on LuaSocket", + homepage = "https://github.com/moteus/lua-try", + license = "MIT/X11", + maintainer = "Alexey Melnichuk", + detailed = [[ + ]], +} + +dependencies = { + "lua >= 5.1, < 5.4" +} + +build = { + copy_directories = {'test'}, + + type = "builtin", + + modules = { + try = { + sources = { "src/try.c" }, + }, + } +} diff --git a/src/try.c b/src/try.c new file mode 100644 index 0000000..09fdfd0 --- /dev/null +++ b/src/try.c @@ -0,0 +1,196 @@ +/*=========================================================================*\ +* Simple exception support +* LuaSocket toolkit +\*=========================================================================*/ +#include + +#include "lua.h" +#include "lauxlib.h" + +/*export*/ +#ifdef _WIN32 +# define EXPORT_API __declspec(dllexport) +#else +# define EXPORT_API LUALIB_API +#endif + +static const char *TRY_ERROR_IDX = "Dummy"; +static const char *TRY_ERROR_NIL = "NIL"; + + +/*=========================================================================*\ +* Internal function prototypes. +\*=========================================================================*/ +static int try_new_assert(lua_State *L); +static int try_new_protect(lua_State *L); + +/* except functions */ +static luaL_Reg func[] = { + {"new", try_new_assert}, + {"protect", try_new_protect}, + {NULL, NULL} +}; + +#if LUA_VERSION_NUM < 502 + +#define lua_absindex(L, i) (((i)>0)?(i):((i)<=LUA_REGISTRYINDEX?(i):(lua_gettop(L)+(i)+1))) + +void lua_rawgetp(lua_State *L, int index, const void *p){ + index = lua_absindex(L, index); + lua_pushlightuserdata(L, (void *)p); + lua_rawget(L, index); +} + +void lua_rawsetp (lua_State *L, int index, const void *p){ + index = lua_absindex(L, index); + lua_pushlightuserdata(L, (void *)p); + lua_insert(L, -2); + lua_rawset(L, index); +} + +#endif + +/*-------------------------------------------------------------------------*\ +* Error wrapper +\*-------------------------------------------------------------------------*/ +static int try_check_error(lua_State *L) { + if(lua_istable(L, -1)){ + lua_rawgetp(L, -1, TRY_ERROR_IDX); + + if(lua_isnil(L, -1)){ /*not try error*/ + lua_pop(L, 1); + return 0; + } + + if(lua_touserdata(L, -1) == TRY_ERROR_NIL){ /*no value*/ + lua_pop(L, 1); + lua_pushnil(L); + } + + lua_pushnil(L); + lua_insert(L, -2); + return 1; + } + + return 0; +} + + +static int try_error(lua_State *L){ + lua_newtable(L); + if(lua_isnil(L, -2)){ + lua_pushlightuserdata(L, (void*)TRY_ERROR_NIL); + } + else{ + lua_pushvalue(L, -2); + } + lua_rawsetp(L, -2, TRY_ERROR_IDX); + return lua_error(L); +} + +/*-------------------------------------------------------------------------*\ +* Try factory +\*-------------------------------------------------------------------------*/ + +static int try_assert(lua_State *L) { + if(!lua_toboolean(L, 1)){ + /* call finalizer */ + if(!lua_isnil(L, lua_upvalueindex(1))){ + lua_pushvalue(L, lua_upvalueindex(1)); + lua_pcall(L, 0, 0, 0); + } + lua_settop(L, 2); + + return try_error(L); + } + return lua_gettop(L); +} + +static int try_new_assert(lua_State *L) { + lua_settop(L, 1); + lua_pushcclosure(L, try_assert, 1); + return 1; +} + +/*-------------------------------------------------------------------------*\ +* Protect factory +\*-------------------------------------------------------------------------*/ + +#if LUA_VERSION_NUM < 503 + +typedef int lua_KContext; + +#endif + +#if LUA_VERSION_NUM <= 501 +#ifndef LUA_OK +#define LUA_OK 0 +#endif +#endif + +static int try_protected(lua_State *L); + +static int try_protected_k(lua_State *L, int status, lua_KContext ctx){ + if(status == LUA_OK){ + lua_pushvalue(L, lua_upvalueindex(1)); + lua_insert(L, 1); + + status = +#if LUA_VERSION_NUM <= 501 + lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); +#else + lua_pcallk(L, lua_gettop(L) - 1, LUA_MULTRET, 0, 0, +#if LUA_VERSION_NUM == 502 + try_protected +#else + try_protected_k +#endif + ); +#endif + if(status == LUA_OK) status = LUA_YIELD; + } + + if(status == LUA_YIELD){ + return lua_gettop(L); + } + + if(status == LUA_ERRRUN){ + if(try_check_error(L)) return 2; + } + + lua_error(L); + return 0; +} + +static int try_protected(lua_State *L){ + int status; + lua_KContext ctx; + +#if LUA_VERSION_NUM == 502 + status = lua_getctx(L, &ctx); +#else + status = LUA_OK; + ctx = 0; +#endif + + return try_protected_k(L, status, ctx); +} + +static int try_new_protect(lua_State *L){ + lua_pushcclosure(L, try_protected, 1); + return 1; +} + + +/*-------------------------------------------------------------------------*\ +* Init module +\*-------------------------------------------------------------------------*/ +EXPORT_API int luaopen_try(lua_State *L) { + lua_newtable(L); +#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE) + luaL_setfuncs(L, func, 0); +#else + luaL_openlib(L, NULL, func, 0); +#endif + return 1; +} diff --git a/test/test.lua b/test/test.lua new file mode 100644 index 0000000..d6c7f0b --- /dev/null +++ b/test/test.lua @@ -0,0 +1,167 @@ +local lunit = lunit + +local RUN = lunit and function()end or function () + local res = lunit.run() + if res.errors + res.failed > 0 then + os.exit(-1) + end + return os.exit(0) +end + +lunit = require "lunit" + +local TEST_CASE = assert(lunit.TEST_CASE) +local skip = lunit.skip or function() end + +local try = require "try" +local coroutine = require "coroutine" + +local function nreturn(...) + return select("#", ...), ... +end + +local pcall, error = pcall, error + +local IS_LUA_51 = (_VERSION == "Lua 5.1") + +local ENABLE = true + +local _ENV = TEST_CASE'try.basic' if ENABLE then + +local it = setmetatable(_ENV or _M, {__call = function(self, describe, fn) + self["test " .. describe] = fn +end}) + +function setup() end + +function teardown() end + +it("return value", function() + local fn = assert_function(try.protect(function() + return 1, nil, 3, nil + end)) + local n, a, b, c, d = nreturn(fn()) + assert_equal(4, n) + assert_equal(1, a) + assert_nil(b) + assert_equal(3, c) + assert_nil(d) +end) + +it("call finalizer", function() + local n = 0 + local EVALUE = 'some value' + local check = try.new(function() n = n + 1 end) + + local fn = assert_function(try.protect(function() + check(nil, EVALUE) + end)) + + local _, b = assert_nil(fn()) + assert_equal(EVALUE, b) + assert_equal(1, n) +end) + +it("call finalizer and return nil", function() + local n = 0 + local EVALUE = nil + local check = try.new(function() n = n + 1 end) + + local fn = assert_function(try.protect(function() + check(nil, EVALUE) + end)) + + local _, b = assert_nil(fn()) + assert_equal(EVALUE, b) + assert_equal(1, n) +end) + +it("raise error", function() + local n = 0 + local EVALUE = "some value" + local check = try.new(function() n = n + 1 end) + + local fn = assert_function(try.protect(function() + error(EVALUE) + end)) + + local ok, err = pcall(fn) + assert_false(ok) + assert_match(EVALUE, err) +end) + +it("raise error and return table", function() + local n = 0 + local EVALUE = {"some value"} + local check = try.new(function() n = n + 1 end) + + local fn = assert_function(try.protect(function() + error(EVALUE) + end)) + + local ok, err = pcall(fn) + assert_false(ok) + assert_equal(EVALUE, err) +end) + +end + +local _ENV = TEST_CASE'try.coro' if ENABLE and not IS_LUA_51 then + +local it = setmetatable(_ENV or _M, {__call = function(self, describe, fn) + self["test " .. describe] = fn +end}) + +function setup() end + +function teardown() end + +it("return value", function() + local co = coroutine.create(try.protect(function(...) + return ... + end)) + + local n, ok, a, b, c, d = nreturn(coroutine.resume(co, 1, nil, 3, nil)) + assert_equal(5, n) + assert_true(ok) + assert_equal(1, a) + assert_nil(b) + assert_equal(3, c) + assert_nil(d) +end) + +it("yeild inside protect", function() + local co = coroutine.create(try.protect(function(...) + return coroutine.yield(...) + end)) + + local n, ok, a, b, c, d = nreturn(coroutine.resume(co, 1, nil, 3, nil)) + assert_equal(5, n) + assert_true(ok) + assert_equal(1, a) + assert_nil(b) + assert_equal(3, c) + assert_nil(d) + + assert_true(coroutine.resume(co)) +end) + +it("check inside coroutine", function() + local n = 0 + local EVALUE = 'some value' + local check = try.new(function() n = n + 1 end) + + local co = coroutine.create(try.protect(function(...) + check(nil, EVALUE) + end)) + + local n, ok, a, b = nreturn(coroutine.resume(co, 1, nil, 3, nil)) + assert_equal(3, n) + assert_true(ok) + assert_nil(a) + assert_equal(EVALUE, b) +end) + +end + +RUN()