Merge pull request #3 from loud-hound/cooper_features
Add luaunit framework, extend lua tests, fix shared-table bug (values…
This commit is contained in:
commit
ca7978e852
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -4,3 +4,6 @@
|
||||
[submodule "tests/gtest"]
|
||||
path = tests/gtest
|
||||
url = https://github.com/google/googletest.git
|
||||
[submodule "lua-tests/luaunit"]
|
||||
path = lua-tests/luaunit
|
||||
url = https://github.com/bluebird75/luaunit
|
||||
|
||||
@ -43,6 +43,4 @@ set_target_properties(tests PROPERTIES COMPILE_FLAGS "${ENABLE_WARNINGS} ${GENER
|
||||
# INSTALL -
|
||||
#----------
|
||||
|
||||
FILE(GLOB TESTS tests/*.lua)
|
||||
FILE(GLOB LUA_SOURCES lua-api/*.lua)
|
||||
install(FILES ${TESTS} ${LUA_SOURCES} DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
|
||||
install(FILES ${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 "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)
|
||||
{
|
||||
sol::state_view lua(L);
|
||||
auto thread_obj = threading::LuaThread::get_user_type(lua);
|
||||
auto share_obj = share_data::SharedTable::get_user_type(lua);
|
||||
threading::LuaThread::get_user_type(lua);
|
||||
share_data::SharedTable::get_user_type(lua);
|
||||
sol::table public_api = lua.create_table_with(
|
||||
"thread", thread_obj,
|
||||
"share", share_obj
|
||||
"thread", create_thread,
|
||||
"share", create_share
|
||||
);
|
||||
sol::stack::push(lua, public_api);
|
||||
return 1;
|
||||
|
||||
@ -27,7 +27,7 @@ void SharedTable::luaSet(sol::stack_object luaKey, sol::stack_object luaValue) n
|
||||
} else {
|
||||
StoredObject value(luaValue);
|
||||
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
|
||||
{
|
||||
const auto end = --args.end();
|
||||
for(auto iter = args.begin(); iter != end; iter++)
|
||||
p_arguments_ = std::make_shared<std::vector<sol::object>>();
|
||||
for(auto iter = args.begin(); iter != args.end(); iter++)
|
||||
{
|
||||
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_.reset();
|
||||
}
|
||||
arguments_.clear();
|
||||
if (p_arguments_.get())
|
||||
p_arguments_.reset();
|
||||
if (p_state_.get())
|
||||
p_state_.reset();
|
||||
}
|
||||
|
||||
void LuaThread::detach() noexcept
|
||||
{
|
||||
p_thread_->detach();
|
||||
}
|
||||
|
||||
void LuaThread::work() noexcept
|
||||
{
|
||||
sol::state& lua = *p_state_;
|
||||
sol::function_result func = lua["loadstring"](str_function_);
|
||||
func.get<sol::function>()(sol::as_args(arguments_));
|
||||
if (p_state_.get() && p_arguments_.get())
|
||||
{
|
||||
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
|
||||
@ -66,6 +81,7 @@ sol::object LuaThread::get_user_type(sol::state_view& lua) noexcept
|
||||
static sol::usertype<LuaThread> type(
|
||||
sol::call_construction(), sol::constructors<sol::types<sol::function, sol::variadic_args>>(),
|
||||
"join", &LuaThread::join,
|
||||
"detach", &LuaThread::detach,
|
||||
"thread_id", &LuaThread::thread_id
|
||||
);
|
||||
sol::stack::push(lua, type);
|
||||
|
||||
@ -16,6 +16,7 @@ public:
|
||||
LuaThread(const sol::function& function, const sol::variadic_args& args) noexcept;
|
||||
virtual ~LuaThread() noexcept = default;
|
||||
void join() noexcept;
|
||||
void detach() noexcept;
|
||||
|
||||
static std::string thread_id() noexcept;
|
||||
static sol::object get_user_type(sol::state_view& lua) noexcept;
|
||||
@ -27,7 +28,7 @@ private:
|
||||
std::string str_function_;
|
||||
std::shared_ptr<sol::state> p_state_;
|
||||
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