add luaunit framework, extend lua tests, fix shared-table bug (values were not updatable)
This commit is contained in:
parent
52128c4078
commit
bacdc889c0
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +1,6 @@
|
|||||||
[submodule "src/sol"]
|
[submodule "src/sol"]
|
||||||
path = src/sol
|
path = src/sol
|
||||||
url = https://github.com/ThePhD/sol2.git
|
url = https://github.com/ThePhD/sol2.git
|
||||||
|
[submodule "lua-tests/luaunit"]
|
||||||
|
path = lua-tests/luaunit
|
||||||
|
url = https://github.com/bluebird75/luaunit
|
||||||
|
|||||||
@ -25,6 +25,4 @@ set_target_properties(woofer PROPERTIES COMPILE_FLAGS "${ENABLE_WARNINGS} ${GENE
|
|||||||
# INSTALL -
|
# INSTALL -
|
||||||
#----------
|
#----------
|
||||||
|
|
||||||
FILE(GLOB TESTS tests/*)
|
install(FILES ${LUA_SOURCES} DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
|
||||||
FILE(GLOB LUA_SOURCES lua-api/*.lua)
|
|
||||||
install(FILES ${TESTS} ${LUA_SOURCES} DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
--local thr = require('libbevy')
|
|
||||||
package.cpath = package.cpath .. ";./?.dylib" -- MAC OS support
|
|
||||||
local api = require('libwoofer')
|
|
||||||
api.thread.thread_id = nil
|
|
||||||
api.thread.join = nil
|
|
||||||
return api
|
|
||||||
1
lua-tests/luaunit
Submodule
1
lua-tests/luaunit
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit d2f1ffa86582d51b77dc29b1f7216e75fe2bc6d0
|
||||||
59
lua-tests/run_tests.lua
Executable file
59
lua-tests/run_tests.lua
Executable file
@ -0,0 +1,59 @@
|
|||||||
|
#!/usr/bin/lua
|
||||||
|
|
||||||
|
package.cpath = package.cpath .. ";../build/?.so;;../build/?.dylib"
|
||||||
|
test = require "luaunit.luaunit"
|
||||||
|
|
||||||
|
do
|
||||||
|
-- Hack input arguments to make tests verbose by default
|
||||||
|
local found = false
|
||||||
|
for _, v in ipairs(arg) do
|
||||||
|
if v == '-o' or v == '--output' then
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not found then
|
||||||
|
table.insert(arg, '-o')
|
||||||
|
table.insert(arg, 'TAP')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function log(...)
|
||||||
|
local msg = '@\t\t' .. os.date('%Y-%m-%d %H:%M:%S ',os.time())
|
||||||
|
for _, val in ipairs({...}) do
|
||||||
|
msg = msg .. tostring(val) .. ' '
|
||||||
|
end
|
||||||
|
io.write(msg .. '\n')
|
||||||
|
io.flush()
|
||||||
|
end
|
||||||
|
|
||||||
|
function wait(timeInSec, condition)
|
||||||
|
local startTime = os.time()
|
||||||
|
while ( (os.time() - startTime) <= timeInSec) do
|
||||||
|
if condition ~= nil then
|
||||||
|
if type(condition) == 'function' then
|
||||||
|
if condition() then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if condition then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function sleep(timeInSec)
|
||||||
|
wait(timeInMsec, nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
-----------
|
||||||
|
-- TESTS --
|
||||||
|
-----------
|
||||||
|
|
||||||
|
require("smoke_test")
|
||||||
|
|
||||||
|
-----------
|
||||||
|
os.exit( test.LuaUnit.run() )
|
||||||
52
lua-tests/smoke_test.lua
Normal file
52
lua-tests/smoke_test.lua
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
TestSmoke = {}
|
||||||
|
|
||||||
|
function TestSmoke:testGeneralWorkability()
|
||||||
|
local woofer = require('libwoofer')
|
||||||
|
local share = woofer.share()
|
||||||
|
|
||||||
|
share["number"] = 100500
|
||||||
|
share["string"] = "string value"
|
||||||
|
share["bool"] = true
|
||||||
|
|
||||||
|
log "Start thread"
|
||||||
|
local thread = woofer.thread(
|
||||||
|
function(share)
|
||||||
|
share["child.number"] = share["number"]
|
||||||
|
share["child.string"] = share["string"]
|
||||||
|
share["child.bool"] = share["bool"]
|
||||||
|
end,
|
||||||
|
share
|
||||||
|
)
|
||||||
|
log "Join thread"
|
||||||
|
thread:join()
|
||||||
|
|
||||||
|
log "Check values"
|
||||||
|
test.assertEquals(share["child.number"], share["number"],
|
||||||
|
"'number' fields are not equal")
|
||||||
|
test.assertEquals(share["child.string"], share["string"],
|
||||||
|
"'string' fields are not equal")
|
||||||
|
test.assertEquals(share["child.bool"], share["bool"],
|
||||||
|
"'bool' fields are not equal")
|
||||||
|
end
|
||||||
|
|
||||||
|
function TestSmoke:testDetach()
|
||||||
|
local woofer = require('libwoofer')
|
||||||
|
local share = woofer.share()
|
||||||
|
|
||||||
|
share["finished"] = false
|
||||||
|
log "Start thread"
|
||||||
|
local thread = woofer.thread(
|
||||||
|
function(share)
|
||||||
|
local startTime = os.time()
|
||||||
|
while ( (os.time() - startTime) <= 3) do --[[ Like we are working 3sec ... ]] end
|
||||||
|
share["finished"] = true
|
||||||
|
end,
|
||||||
|
share
|
||||||
|
)
|
||||||
|
log "Detach thread"
|
||||||
|
thread:detach()
|
||||||
|
|
||||||
|
log "Waiting for thread completion..."
|
||||||
|
test.assertEquals(wait(4, function() return share["finished"] end) , true)
|
||||||
|
log "Stop waiting"
|
||||||
|
end
|
||||||
@ -1,16 +1,26 @@
|
|||||||
#include "lua.hpp"
|
|
||||||
|
|
||||||
#include "threading.h"
|
#include "threading.h"
|
||||||
#include "shared-table.h"
|
#include "shared-table.h"
|
||||||
|
|
||||||
|
#include <lua.hpp>
|
||||||
|
|
||||||
|
static sol::object create_thread(sol::this_state lua, sol::function func, const sol::variadic_args& args)
|
||||||
|
{
|
||||||
|
return sol::make_object(lua, std::make_unique<threading::LuaThread>(func, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
static sol::object create_share(sol::this_state lua)
|
||||||
|
{
|
||||||
|
return sol::make_object(lua, std::make_unique<share_data::SharedTable>());
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" int luaopen_libwoofer(lua_State *L)
|
extern "C" int luaopen_libwoofer(lua_State *L)
|
||||||
{
|
{
|
||||||
sol::state_view lua(L);
|
sol::state_view lua(L);
|
||||||
auto thread_obj = threading::LuaThread::get_user_type(lua);
|
threading::LuaThread::get_user_type(lua);
|
||||||
auto share_obj = share_data::SharedTable::get_user_type(lua);
|
share_data::SharedTable::get_user_type(lua);
|
||||||
sol::table public_api = lua.create_table_with(
|
sol::table public_api = lua.create_table_with(
|
||||||
"thread", thread_obj,
|
"thread", create_thread,
|
||||||
"share", share_obj
|
"share", create_share
|
||||||
);
|
);
|
||||||
sol::stack::push(lua, public_api);
|
sol::stack::push(lua, public_api);
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@ -27,7 +27,7 @@ void SharedTable::luaSet(sol::stack_object luaKey, sol::stack_object luaValue) n
|
|||||||
} else {
|
} else {
|
||||||
StoredObject value(luaValue);
|
StoredObject value(luaValue);
|
||||||
std::lock_guard<SpinMutex> g(lock_);
|
std::lock_guard<SpinMutex> g(lock_);
|
||||||
data_.emplace(std::make_pair(std::move(key), std::move(value)));
|
data_[std::move(key)] = std::move(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,11 +27,11 @@ LuaThread::LuaThread(const sol::function& function, const sol::variadic_args& ar
|
|||||||
|
|
||||||
void LuaThread::store_args(const sol::variadic_args& args) noexcept
|
void LuaThread::store_args(const sol::variadic_args& args) noexcept
|
||||||
{
|
{
|
||||||
const auto end = --args.end();
|
p_arguments_ = std::make_shared<std::vector<sol::object>>();
|
||||||
for(auto iter = args.begin(); iter != end; iter++)
|
for(auto iter = args.begin(); iter != args.end(); iter++)
|
||||||
{
|
{
|
||||||
share_data::StoredObject store(iter->get<sol::object>());
|
share_data::StoredObject store(iter->get<sol::object>());
|
||||||
arguments_.push_back(store.unpack(sol::this_state{p_state_->lua_state()}));
|
p_arguments_->push_back(store.unpack(sol::this_state{p_state_->lua_state()}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,16 +42,31 @@ void LuaThread::join() noexcept
|
|||||||
p_thread_->join();
|
p_thread_->join();
|
||||||
p_thread_.reset();
|
p_thread_.reset();
|
||||||
}
|
}
|
||||||
arguments_.clear();
|
if (p_arguments_.get())
|
||||||
|
p_arguments_.reset();
|
||||||
if (p_state_.get())
|
if (p_state_.get())
|
||||||
p_state_.reset();
|
p_state_.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LuaThread::detach() noexcept
|
||||||
|
{
|
||||||
|
p_thread_->detach();
|
||||||
|
}
|
||||||
|
|
||||||
void LuaThread::work() noexcept
|
void LuaThread::work() noexcept
|
||||||
{
|
{
|
||||||
sol::state& lua = *p_state_;
|
if (p_state_.get() && p_arguments_.get())
|
||||||
sol::function_result func = lua["loadstring"](str_function_);
|
{
|
||||||
func.get<sol::function>()(sol::as_args(arguments_));
|
std::string func_owner = std::move(str_function_);
|
||||||
|
std::shared_ptr<sol::state> state_owner = p_state_;
|
||||||
|
std::shared_ptr<std::vector<sol::object>> arguments_owner = p_arguments_;
|
||||||
|
sol::function_result func = (*state_owner)["loadstring"](func_owner);
|
||||||
|
func.get<sol::function>()(sol::as_args(*arguments_owner));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw sol::error("Internal error: invalid thread Lua state");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string LuaThread::thread_id() noexcept
|
std::string LuaThread::thread_id() noexcept
|
||||||
@ -66,6 +81,7 @@ sol::object LuaThread::get_user_type(sol::state_view& lua) noexcept
|
|||||||
static sol::usertype<LuaThread> type(
|
static sol::usertype<LuaThread> type(
|
||||||
sol::call_construction(), sol::constructors<sol::types<sol::function, sol::variadic_args>>(),
|
sol::call_construction(), sol::constructors<sol::types<sol::function, sol::variadic_args>>(),
|
||||||
"join", &LuaThread::join,
|
"join", &LuaThread::join,
|
||||||
|
"detach", &LuaThread::detach,
|
||||||
"thread_id", &LuaThread::thread_id
|
"thread_id", &LuaThread::thread_id
|
||||||
);
|
);
|
||||||
sol::stack::push(lua, type);
|
sol::stack::push(lua, type);
|
||||||
|
|||||||
@ -16,6 +16,7 @@ public:
|
|||||||
LuaThread(const sol::function& function, const sol::variadic_args& args) noexcept;
|
LuaThread(const sol::function& function, const sol::variadic_args& args) noexcept;
|
||||||
virtual ~LuaThread() noexcept = default;
|
virtual ~LuaThread() noexcept = default;
|
||||||
void join() noexcept;
|
void join() noexcept;
|
||||||
|
void detach() noexcept;
|
||||||
|
|
||||||
static std::string thread_id() noexcept;
|
static std::string thread_id() noexcept;
|
||||||
static sol::object get_user_type(sol::state_view& lua) noexcept;
|
static sol::object get_user_type(sol::state_view& lua) noexcept;
|
||||||
@ -27,7 +28,7 @@ private:
|
|||||||
std::string str_function_;
|
std::string str_function_;
|
||||||
std::shared_ptr<sol::state> p_state_;
|
std::shared_ptr<sol::state> p_state_;
|
||||||
std::shared_ptr<std::thread> p_thread_;
|
std::shared_ptr<std::thread> p_thread_;
|
||||||
std::vector<sol::object> arguments_;
|
std::shared_ptr<std::vector<sol::object>> p_arguments_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
1
tests/lua/lunatest
Submodule
1
tests/lua/lunatest
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 32e3ecfdb64d37c7f5e72b33bd32fdc3992b967d
|
||||||
@ -1,55 +0,0 @@
|
|||||||
function compare(o1, o2)
|
|
||||||
if o1 == o2 then return true end
|
|
||||||
local o1Type = type(o1)
|
|
||||||
local o2Type = type(o2)
|
|
||||||
if o1Type ~= o2Type then return false end
|
|
||||||
if o1Type ~= 'table' then return false end
|
|
||||||
|
|
||||||
local keySet = {}
|
|
||||||
for key1, value1 in pairs(o1) do
|
|
||||||
local value2 = o2[key1]
|
|
||||||
if value2 == nil or equals(value1, value2) == false then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
keySet[key1] = true
|
|
||||||
end
|
|
||||||
|
|
||||||
for key2, _ in pairs(o2) do
|
|
||||||
if not keySet[key2] then return false end
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
function check(left, right)
|
|
||||||
if not compare(left, right) then
|
|
||||||
print("ERROR")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-----------
|
|
||||||
-- TESTS --
|
|
||||||
-----------
|
|
||||||
|
|
||||||
do -- Simple smoke
|
|
||||||
package.cpath = package.cpath .. ";./?.dylib" -- MAC OS support
|
|
||||||
local woofer = require('libwoofer')
|
|
||||||
local share = woofer.share()
|
|
||||||
|
|
||||||
share["number"] = 100500
|
|
||||||
share["string"] = "string value"
|
|
||||||
share["bool"] = true
|
|
||||||
|
|
||||||
local thread = woofer.thread(
|
|
||||||
function(share)
|
|
||||||
share["child.number"] = share["number"]
|
|
||||||
share["child.string"] = share["string"]
|
|
||||||
share["child.bool"] = share["bool"]
|
|
||||||
end,
|
|
||||||
share
|
|
||||||
)
|
|
||||||
thread:join()
|
|
||||||
|
|
||||||
check(share["child.number"], share["number"])
|
|
||||||
check(share["child.string"], share["string"])
|
|
||||||
check(share["child.bool"], share["bool"])
|
|
||||||
end
|
|
||||||
Loading…
x
Reference in New Issue
Block a user