aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spec/LuaRuntimeSpec.cpp123
-rw-r--r--src/LuaRuntime.cpp35
-rw-r--r--src/LuaRuntime.hpp6
3 files changed, 117 insertions, 47 deletions
diff --git a/spec/LuaRuntimeSpec.cpp b/spec/LuaRuntimeSpec.cpp
index 149e1e1..924681a 100644
--- a/spec/LuaRuntimeSpec.cpp
+++ b/spec/LuaRuntimeSpec.cpp
@@ -1,73 +1,108 @@
-#include "testUtils.h"
#include <QtCore>
-#include <atomic>
#include <uv.h>
#include "LuaRuntime.hpp"
+#include "testUtils.h"
class LuaRuntimeSpec : public QObject {
Q_OBJECT
private slots:
- void cleanupTestCase() { uv_library_shutdown(); }
+ void beforeTestCase() { LuaRuntime::instance()->startEventLoop(); }
- void testSanityCheckBuiltins() {
- auto lua = LuaRuntime::instance();
+ void cleanupTestCase() {
+ LuaRuntime::instance()->stopEventLoop();
+ uv_library_shutdown();
+ }
- it("evaluates simple expression") {
- lua->startEventLoop();
- std::atomic<int> foobar = 2;
+ void testEvaluate() {
+ context("when given an expression returning a number");
+ it("emits evaluationCompleted with the result") {
+ auto lua = LuaRuntime::instance();
+ QSignalSpy evaluationCompletedSpy(lua, &LuaRuntime::evaluationCompleted);
- lua->queueTask([&foobar]() { foobar = 10; });
+ lua->evaluate("return 20 + 1 * 5");
- lua->evaluate(R"(
- print('Hello -- ');
- local timer = uv.new_timer();
- timer:start(1000, 0, function()
- print('inside timer 1')
- print('inside timer 2')
- print('inside timer 3')
- print('inside timer 4')
- print('inside timer 5')
- timer:close()
- end);
- print('-- end');
- )");
- lua->queueTask([]() { qDebug() << "---- 1"; });
- lua->queueTask([]() { qDebug() << "---- 2"; });
- lua->queueTask([]() { qDebug() << "---- 3"; });
- std::this_thread::sleep_for(std::chrono::seconds(2));
- // std::this_thread::sleep_for(std::chrono::milliseconds(20));
- lua->stopEventLoop();
+ evaluationCompletedSpy.wait();
+ QCOMPARE(evaluationCompletedSpy.count(), 1);
+ QVariant result = evaluationCompletedSpy.takeFirst().at(0);
+ QCOMPARE(result, 25);
+ }
+
+ context("when given an expression returning a string");
+ it("emits evaluationCompleted with the result") {
+ auto lua = LuaRuntime::instance();
+ QSignalSpy evaluationCompletedSpy(lua, &LuaRuntime::evaluationCompleted);
+
+ lua->evaluate("local name = 'world'; return 'hello ' .. name");
- qDebug() << "foobar" << foobar;
+ evaluationCompletedSpy.wait();
+ QCOMPARE(evaluationCompletedSpy.count(), 1);
+ QVariant result = evaluationCompletedSpy.takeFirst().at(0);
+ QCOMPARE(result, "hello world");
+ }
+
+ context("when given an expression returning a boolean");
+ it("emits evaluationCompleted with the result") {
+ auto lua = LuaRuntime::instance();
+ QSignalSpy evaluationCompletedSpy(lua, &LuaRuntime::evaluationCompleted);
+
+ lua->evaluate("local num = 5; return 5 == num");
- QCOMPARE(1, 1);
+ evaluationCompletedSpy.wait();
+ QCOMPARE(evaluationCompletedSpy.count(), 1);
+ QVariant result = evaluationCompletedSpy.takeFirst().at(0);
+ QCOMPARE(result, true);
+ }
+
+ context("when given an expression returning nil");
+ it("emits evaluationCompleted with the result") {
+ auto lua = LuaRuntime::instance();
+ QSignalSpy evaluationCompletedSpy(lua, &LuaRuntime::evaluationCompleted);
+
+ lua->evaluate("return nil");
+
+ QVERIFY(evaluationCompletedSpy.wait());
+ QCOMPARE(evaluationCompletedSpy.count(), 1);
+ QVariant result = evaluationCompletedSpy.takeFirst().at(0);
+ QCOMPARE(result, 0);
}
}
- void testSanityCheckBuiltins2() {
- auto lua = LuaRuntime::instance();
+ void testQueueTask() {
+ context("when task is queued");
+ it("evaluates task asynchronously") {
+ auto lua = LuaRuntime::instance();
+ bool wasTaskCalled = false;
+
+ lua->queueTask([&wasTaskCalled]() { wasTaskCalled = true; });
+ QVERIFY(NOT wasTaskCalled);
+
+ QVERIFY(QTest::qWaitFor([&wasTaskCalled]() { return wasTaskCalled; }));
+ QVERIFY(wasTaskCalled);
+ }
+ }
- it("evaluates again") {
- lua->startEventLoop();
+ void testSanityCheckUV() {
+ context("when a 1 second timer is set");
+ it("calls callback after 1 second") {
+ auto lua = LuaRuntime::instance();
+ QSignalSpy evaluationCompletedSpy(lua, &LuaRuntime::evaluationCompleted);
- lua->queueTask([]() { qDebug() << "---- 5"; });
lua->evaluate(R"(
- print('Hello -- ');
+ _G.wasTimerCalled = false;
local timer = uv.new_timer();
timer:start(1000, 0, function()
- print('%%%%% blagb')
+ _G.wasTimerCalled = true;
timer:close()
- end);
- print('-- end');
+ end)
)");
- lua->queueTask([]() { qDebug() << "---- 5"; });
- // TODO: Impl
- std::this_thread::sleep_for(std::chrono::seconds(2));
- lua->stopEventLoop();
+ QVERIFY(evaluationCompletedSpy.wait());
+ QVERIFY(NOT lua->evaluateSync("return _G.wasTimerCalled").toBool());
- QCOMPARE(1, 1);
+ QVERIFY(QTest::qWaitFor([&lua]() {
+ return lua->evaluateSync("return _G.wasTimerCalled").toBool();
+ }));
}
}
};
diff --git a/src/LuaRuntime.cpp b/src/LuaRuntime.cpp
index e61fbf5..e9a30b1 100644
--- a/src/LuaRuntime.cpp
+++ b/src/LuaRuntime.cpp
@@ -52,13 +52,42 @@ void LuaRuntime::stopEventLoop() {
void LuaRuntime::evaluate(QString code) {
eventLoop->queueTask([this, code]() {
if (luaL_dostring(state, code.toStdString().c_str())) {
- qDebug() << "Lua Error: " << lua_tostring(state, -1);
+ auto value = lua_tostring(state, -1);
lua_pop(state, 1);
- } else
- qDebug() << "done";
+
+ qDebug() << "Lua Error: " << value;
+ emit evaluationFailed(value);
+ } else {
+ auto value = getValue(-1);
+ lua_pop(state, 1);
+
+ qDebug() << "result: " << value;
+ emit evaluationCompleted(value);
+ }
});
}
+QVariant LuaRuntime::evaluateSync(QString code) {
+ auto result = luaL_dostring(state, code.toStdString().c_str());
+ return getValue(-1); // TODO: error handling
+}
+
+QVariant LuaRuntime::getValue(int idx) {
+ if (lua_isstring(state, idx))
+ return lua_tostring(state, idx);
+
+ if (lua_isnumber(state, idx))
+ return lua_tonumber(state, idx);
+
+ if (lua_isboolean(state, idx))
+ return lua_toboolean(state, idx);
+
+ if (lua_isnil(state, idx))
+ return 0; // TODO: nil representation
+
+ return lua_tostring(state, idx);
+}
+
int LuaRuntime::lua_onUrlOpen(lua_State *state) {
const char *url = luaL_optstring(state, 1, "");
auto runtime = LuaRuntime::instance();
diff --git a/src/LuaRuntime.hpp b/src/LuaRuntime.hpp
index 443dec5..dd5c0ec 100644
--- a/src/LuaRuntime.hpp
+++ b/src/LuaRuntime.hpp
@@ -16,14 +16,20 @@ public:
}
void evaluate(QString code);
+ QVariant evaluateSync(QString code);
void stopEventLoop();
void startEventLoop();
+ QVariant getValue(int idx);
+
DELEGATE(eventLoop, queueTask, queueTask)
signals:
void urlOpened(QString url, OpenType openType);
+ void evaluationCompleted(QVariant value);
+ void evaluationFailed(QString value);
+ // void outputProduced(QVariant value);
protected:
LuaRuntime();