Browse Source

Add QTIS tests

master
Denis Tereshkin 4 years ago
parent
commit
4b12d3b667
  1. 1548
      3rdparty/JSON.lua
  2. 216
      qtis.lua
  3. 15
      quik_api.lua
  4. 44
      tests/test_qtis.lua
  5. 1
      tests/test_zeromq.lua

1548
3rdparty/JSON.lua vendored

File diff suppressed because it is too large Load Diff

216
qtis.lua

@ -1,143 +1,17 @@ @@ -1,143 +1,17 @@
local alien = require("alien")
-- QUIK Ticker Information System
json = require "JSON"
date = require "date"
require "string"
struct = require "alien.struct"
w32sleep = alien.kernel32.Sleep
w32sleep:types { ret = "void", abi = "stdcall", "int" }
zmq_pollitem = alien.defstruct {
{"socket", "pointer"},
{"fd", "int"},
{"events", "short"},
{"revents", "short"}
}
zmq_ctx_new = alien.libzmq.zmq_ctx_new
zmq_ctx_new:types { ret = "pointer", abi="stdcall" }
zmq_ctx_term = alien.libzmq.zmq_ctx_term
zmq_ctx_term:types { ret = "int", abi="stdcall", "pointer" }
zmq_bind = alien.libzmq.zmq_bind
zmq_bind:types { ret = "int", abi="stdcall", "pointer", "string" }
zmq_close = alien.libzmq.zmq_close
zmq_close:types { ret = "int", abi="stdcall", "pointer" }
zmq_disconnect = alien.libzmq.zmq_disconnect
zmq_disconnect:types { ret = "int", abi="stdcall", "pointer", "string" }
zmq_setsockopt = alien.libzmq.zmq_setsockopt
zmq_setsockopt:types { ret = "int", abi="stdcall", "pointer", "int", "pointer", "int" }
zmq_getsockopt = alien.libzmq.zmq_setsockopt
zmq_getsockopt:types { ret = "int", abi="stdcall", "pointer", "int", "pointer", "int" }
zmq_errno = alien.libzmq.zmq_errno
zmq_errno:types { ret = "int", abi="stdcall" }
zmq_msg_close = alien.libzmq.zmq_msg_close
zmq_msg_close:types { ret = "int", abi="stdcall", "pointer" }
zmq_msg_data = alien.libzmq.zmq_msg_data
zmq_msg_data:types { ret = "pointer", abi="stdcall", "pointer" }
zmq_msg_get = alien.libzmq.zmq_msg_get
zmq_msg_get:types { ret = "int", abi="stdcall", "pointer", "int" }
zmq_msg_init_size = alien.libzmq.zmq_msg_init_size
zmq_msg_init_size:types { ret = "int", abi="stdcall", "pointer", "int" }
zmq_msg_init = alien.libzmq.zmq_msg_init
zmq_msg_init:types { ret = "int", abi="stdcall", "pointer" }
zmq_msg_more = alien.libzmq.zmq_msg_more
zmq_msg_more:types { ret = "int", abi="stdcall", "pointer" }
zmq_msg_recv = alien.libzmq.zmq_msg_recv
zmq_msg_recv:types { ret = "int", abi="stdcall", "pointer", "pointer", "int" }
zmq_msg_send = alien.libzmq.zmq_msg_send
zmq_msg_send:types { ret = "int", abi="stdcall", "pointer", "pointer", "int" }
zmq_msg_set = alien.libzmq.zmq_msg_set
zmq_msg_set:types { ret = "int", abi="stdcall", "pointer", "int", "int" }
zmq_msg_size = alien.libzmq.zmq_msg_size
zmq_msg_size:types { ret = "int", abi="stdcall", "pointer" }
zmq_poll = alien.libzmq.zmq_poll
zmq_poll:types { ret = "int", abi="stdcall", "pointer", "int", "int" }
zmq_recv = alien.libzmq.zmq_recv
zmq_recv:types { ret = "int", abi="stdcall", "pointer", "pointer", "int", "int"}
zmq_send = alien.libzmq.zmq_send
zmq_send:types { ret = "int", abi="stdcall", "pointer", "pointer", "int", "int"}
zmq_socket = alien.libzmq.zmq_socket
zmq_socket:types { ret = "pointer", abi="stdcall", "pointer", "int"}
zmq_version = alien.libzmq.zmq_version
zmq_version:types { ret = "void", abi="stdcall", "ref int", "ref int", "ref int"}
zmq_unbind = alien.libzmq.zmq_unbind
zmq_unbind:types { ret = "int", abi="stdcall", "pointer", "string"}
function zmq_msg_new()
local buf = alien.buffer(64)
return buf
end
function zmq_msg_as_string(msg)
return alien.tostring(zmq_msg_data(msg), zmq_msg_size(msg))
end
ZMQ_PAIR = 0
ZMQ_PUB = 1
ZMQ_SUB = 2
ZMQ_REQ = 3
ZMQ_REP = 4
ZMQ_DEALER = 5
ZMQ_ROUTER = 6
ZMQ_PULL = 7
ZMQ_PUSH = 8
ZMQ_XPUB = 9
ZMQ_XSUB = 10
ZMQ_STREAM = 11
ZMQ_POLLIN = 1
ZMQ_POLLOUT = 2
ZMQ_POLLERR = 4
ZMQ_SNDMORE = 2
ZMQ_LINGER = 17
local zmq = require "zeromq"
local quik = require "quik_api"
running = true
function zmq_msg_from_string(str)
local msg = zmq_msg_new()
zmq_msg_init_size(msg, str:len())
buf = zmq_msg_data(msg)
bsource = alien.buffer(str)
alien.memcpy(buf, bsource, str:len())
return msg
end
function zmq_msg_empty()
local msg = zmq_msg_new()
zmq_msg_init(msg)
return msg
end
function get_data(class, code)
local lot_size = tonumber(getParamEx(class, code, "LOTSIZE").param_value)
local tick_size = tonumber(getParamEx(class, code, "SEC_PRICE_STEP").param_value)
local tick_value = tonumber(getParamEx(class, code, "STEPPRICET").param_value)
local long_name = getParamEx(class, code, "LONGNAME").param_image
local lot_size = tonumber(quik.getParamEx(class, code, "LOTSIZE").param_value)
local tick_size = tonumber(quik.getParamEx(class, code, "SEC_PRICE_STEP").param_value)
local tick_value = tonumber(quik.getParamEx(class, code, "STEPPRICET").param_value)
local long_name = quik.getParamEx(class, code, "LONGNAME").param_image
return { ticker = class .. "#" .. code,
lot_size = lot_size,
@ -147,76 +21,66 @@ function get_data(class, code) @@ -147,76 +21,66 @@ function get_data(class, code)
end
function handle_message(msg)
message("Incoming message")
local rq = json:decode(zmq_msg_as_string(msg))
quik.message("Incoming message")
local rq = json:decode(msg)
local class, code = string.match(rq.ticker, "(%w+)#(%w+)")
message("Requested: " .. rq.ticker)
quik.message("Requested: " .. rq.ticker)
local data = get_data(class, code)
if data == nil then
message("Error")
return zmq_msg_from_string("ERROR: can't get data: (" .. class .. "/" .. code .. ")" ), zmq_msg_empty()
quik.message("Error")
return "ERROR: can't get data: (" .. class .. "/" .. code .. ")", ""
end
message("Returning data")
return zmq_msg_from_string("OK"), zmq_msg_from_string(json:encode(data))
quik.message("Returning data")
return "OK", json:encode(data)
end
ctx = nil
sock = nil
Ctx = nil
Sock = nil
function OnStop()
if sock then
zmq_close(sock)
sock = nil
if Sock then
Sock:close()
Sock = nil
end
if ctx then
zmq_ctx_term(ctx)
ctx = nil
if Ctx then
Ctx:term()
Ctx = nil
end
end
function main()
local status, err = pcall(pmain)
if not status then
message("Error: " .. err)
quik.message("Error: " .. err)
end
OnStop()
end
function pmain()
ctx = zmq_ctx_new()
sock = zmq_socket(ctx, ZMQ_REP)
local linger = alien.array("int", {0})
zmq_setsockopt(sock, ZMQ_LINGER, linger.buffer, 4)
local rc = zmq_bind(sock, "tcp://*:5523")
if rc ~= 0 then
message("Bind error: " .. tostring(rc))
local err
Ctx = zmq.new_ctx()
Sock = Ctx:socket(zmq.REP)
Sock:setsockopt_int(zmq.SOCKOPT_LINGER, 0)
_, err = Sock:bind("tcp://*:5523")
if err then
quik.message("Bind error: " .. tostring(rc))
return
end
local poller = Ctx:poller()
poller:add(Sock, zmq.POLLIN)
while running do
local pi = zmq_pollitem:new()
pi.socket = sock
pi.fd = 0
pi.events = ZMQ_POLLIN
pi.revents = 0
rc = zmq_poll(pi(), 1, 60000)
if rc > 0 and pi.revents == ZMQ_POLLIN then
message("Incoming")
local msg = zmq_msg_new()
zmq_msg_init(msg)
rc = zmq_msg_recv(msg, sock, 0)
if rc == -1 then
running = false
message("rc: " .. tostring(rc) .. "; " .. tostring(zmq_errno()))
else
local events, msg
events, err = poller:poll(60000)
if #events > 0 then
quik.message("Incoming")
msg, err = Sock:recv()
if not err then
local outmsg_header, outmsg_data = handle_message(msg)
zmq_msg_send(outmsg_header, sock, ZMQ_SNDMORE)
zmq_msg_send(outmsg_data, sock, 0)
Sock:send({outmsg_header, outmsg_data})
end
zmq_msg_close(msg)
end
end
end

15
quik_api.lua

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
local P =
{
message = message,
getParamEx = getParamEx,
}
if _REQUIREDNAME == nil then
zmq = P
else
_G[_REQUIREDNAME] = P
end
return P

44
tests/test_qtis.lua

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
require "luarocks.loader"
package.path = package.path .. ";../?.lua" .. ";../3rdparty/?.lua"
local lu = require "luaunit"
require "qtis"
local json = require "JSON"
local Mock = require "test.mock.Mock"
local Match = require "test.mock.ValueMatcher"
quik = require "quik_api"
function test_handle_message()
local class = "TESTCLASS"
local ticker = "TESTTICKER"
local lot_size = 42
local price_step = 0.01
local tick_value = 10
local long_name = "The test ticker Inc."
quik.getParamEx = Mock()
quik.message = Mock()
quik.message:whenCalled { with={Match.anyString}, thenReturn=nil }
quik.getParamEx:whenCalled { with={class, ticker, "LOTSIZE"}, thenReturn = {{param_value = tostring(lot_size)}} }
quik.getParamEx:whenCalled { with={class, ticker, "SEC_PRICE_STEP"}, thenReturn = {{param_value = tostring(price_step)}} }
quik.getParamEx:whenCalled { with={class, ticker, "STEPPRICET"}, thenReturn = {{param_value = tostring(tick_value)}} }
quik.getParamEx:whenCalled { with={class, ticker, "LONGNAME"}, thenReturn = {{param_image = long_name}} }
local ok, data = handle_message( json:encode { ticker = class .. "#" .. ticker })
local resp = json:decode(data)
lu.assertEquals(ok, "OK")
lu.assertEquals(resp.ticker, class .. "#" .. ticker)
lu.assertEquals(resp.lot_size, lot_size)
lu.assertEquals(resp.tick_size, price_step)
lu.assertEquals(resp.tick_value, tick_value)
lu.assertEquals(resp.long_name, long_name)
end
os.exit(lu.LuaUnit.run())

1
tests/test_zeromq.lua

@ -84,4 +84,5 @@ function test_poll() @@ -84,4 +84,5 @@ function test_poll()
end
end
os.exit(lu.LuaUnit.run())

Loading…
Cancel
Save