Skip to content

Commit

Permalink
feat(*): add testing=true for resty cli testing (#24)
Browse files Browse the repository at this point in the history
Add a new option `testing=true`
  • Loading branch information
chronolaw authored Apr 6, 2023
1 parent 67806db commit a34e860
Show file tree
Hide file tree
Showing 4 changed files with 322 additions and 3 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,13 @@ The `opts` parameter is a Lua table with named options:

The return value will be the event object or `nil`.

There is a special parameter `testing`, which means the library will not enable
unix domain socket listening, and the events will only be propagated in the worker process internally.
In the meanwhile, `unique_timeout` will be meanless.

This feature is very useful for testing, such as `resty cli`.
The default value for `testing` is `false`.

[Back to TOC](#table-of-contents)

init_worker
Expand Down Expand Up @@ -157,6 +164,8 @@ it must be called in `content_by_lua*`.

`ev` object must be the same object returned by [new](#new).

Should not call it if `testing` is set to `true`.

[Back to TOC](#table-of-contents)

publish
Expand Down
11 changes: 9 additions & 2 deletions lualib/resty/events/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ local str_sub = string.sub
local worker_count = ngx.worker.count()

local _M = {
_VERSION = '0.1.3',
_VERSION = '0.1.4',
}
local _MT = { __index = _M, }

Expand Down Expand Up @@ -66,6 +66,12 @@ local function check_options(opts)
return nil, '"max_queue_len" option is invalid'
end

opts.testing = opts.testing or false

if type(opts.testing) ~= "boolean" then
return nil, '"testing" option must be a boolean'
end

return true
end

Expand All @@ -87,7 +93,8 @@ function _M:init_worker()

local worker_id = ngx_worker_id() or -1

local is_broker = worker_id == opts.broker_id
local is_broker = opts.broker_id == worker_id or
opts.testing == true

local ok, err

Expand Down
21 changes: 20 additions & 1 deletion lualib/resty/events/worker.lua
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ local PAYLOAD_T = {
local _worker_id = ngx.worker.id() or -1

local _M = {
_VERSION = '0.1.2',
_VERSION = '0.1.4',
}
local _MT = { __index = _M, }

Expand Down Expand Up @@ -107,6 +107,12 @@ function _M:communicate(premature)
return
end

-- only for testing, skip read/write/events threads
if self._opts.testing == true then
self._connected = true
return
end

local listening = self._opts.listening

if not check_sock_exist(listening) then
Expand Down Expand Up @@ -306,6 +312,19 @@ function _M:publish(target, source, event, data)
assert(type(source) == "string" and source ~= "", "source is required")
assert(type(event) == "string" and event ~= "", "event is required")

-- fall back to local events
if self._opts.testing == true then
log(DEBUG, "event published to 1 workers")

do_event(self, {
source = source,
event = event,
data = data,
})

return true
end

if target == "current" then
ok, err = self._sub_queue:push({
source = source,
Expand Down
284 changes: 284 additions & 0 deletions t/listening-off.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
# vim:set ft= ts=4 sw=4 et fdm=marker:
use Test::Nginx::Socket::Lua;

#worker_connections(1014);
#master_process_enabled(1);
#log_level('warn');

#repeat_each(2);

plan tests => repeat_each() * (blocks() * 7);

$ENV{TEST_NGINX_HTML_DIR} ||= html_dir();

#no_diff();
#no_long_string();
#master_on();
#workers(2);
run_tests();

__DATA__

=== TEST 1: posting events and handling events, broadcast and local
--- http_config
lua_package_path "../lua-resty-core/lib/?.lua;lualib/?/init.lua;lualib/?.lua;;";
init_worker_by_lua_block {
local opts = {
--broker_id = 0,
listening = "unix:$TEST_NGINX_HTML_DIR/nginx.sock",
testing = true,
}

local ev = require("resty.events").new(opts)
if not ev then
ngx.log(ngx.ERR, "failed to new events")
end

local ok, err = ev:init_worker()
if not ok then
ngx.log(ngx.ERR, "failed to init_worker events: ", err)
end

assert(not ev:is_ready())

ev:subscribe("*", "*", function(data, event, source, wid)
ngx.log(ngx.DEBUG, "worker-events: handler event; ","source=",source,", event=",event, ", wid=", wid,
", data=", data)
end)

_G.ev = ev
}
--- config
location = /test {
content_by_lua_block {
local ev = _G.ev
assert(ev:is_ready())
ev:publish("all", "content_by_lua","request1","01234567890")
ev:publish("current", "content_by_lua","request2","01234567890")
ev:publish("all", "content_by_lua","request3","01234567890")
ngx.say("ok")
}
}
--- request
GET /test
--- response_body
ok
--- error_log
event published to 1 workers
--- no_error_log
[error]
[crit]
[alert]
--- grep_error_log eval: qr/worker-events: .*/
--- grep_error_log_out eval
qr/^worker-events: handling event; source=content_by_lua, event=request1, wid=nil
worker-events: handler event; source=content_by_lua, event=request1, wid=nil, data=01234567890
worker-events: handling event; source=content_by_lua, event=request2, wid=nil
worker-events: handler event; source=content_by_lua, event=request2, wid=nil, data=01234567890
worker-events: handling event; source=content_by_lua, event=request3, wid=nil
worker-events: handler event; source=content_by_lua, event=request3, wid=nil, data=01234567890$/


=== TEST 2: worker.events handling remote events
--- http_config
lua_package_path "../lua-resty-core/lib/?.lua;lualib/?/init.lua;lualib/?.lua;;";
init_worker_by_lua_block {
local opts = {
--broker_id = 0,
listening = "unix:$TEST_NGINX_HTML_DIR/nginx.sock",
testing = true,
}

local ev = require("resty.events").new(opts)
if not ev then
ngx.log(ngx.ERR, "failed to new events")
end

local ok, err = ev:init_worker()
if not ok then
ngx.log(ngx.ERR, "failed to init_worker events: ", err)
end

assert(not ev:is_ready())

ev:subscribe("*", "*", function(data, event, source, wid)
ngx.log(ngx.DEBUG, "worker-events: handler event; ","source=",source,", event=",event, ", wid=", wid,
", data=", tostring(data))
end)

_G.ev = ev
}
--- config
location = /test {
content_by_lua_block {
local ev = _G.ev
assert(ev:is_ready())
ev:publish("all", "content_by_lua","request1","01234567890")
ev:publish("current", "content_by_lua","request2","01234567890")
ev:publish("all", "content_by_lua","request3","01234567890")
ngx.say("ok")
}
}
--- request
GET /test
--- response_body
ok
--- error_log
event published to 1 workers
--- no_error_log
[error]
[crit]
[alert]
--- grep_error_log eval: qr/worker-events: .*/
--- grep_error_log_out eval
qr/^worker-events: handling event; source=content_by_lua, event=request1, wid=nil
worker-events: handler event; source=content_by_lua, event=request1, wid=nil, data=01234567890
worker-events: handling event; source=content_by_lua, event=request2, wid=nil
worker-events: handler event; source=content_by_lua, event=request2, wid=nil, data=01234567890
worker-events: handling event; source=content_by_lua, event=request3, wid=nil
worker-events: handler event; source=content_by_lua, event=request3, wid=nil, data=01234567890$/


=== TEST 3: worker.events 'one' being done, and only once
--- http_config
lua_package_path "../lua-resty-core/lib/?.lua;lualib/?/init.lua;lualib/?.lua;;";
init_worker_by_lua_block {
local opts = {
unique_timeout = 0.04,
--broker_id = 0,
listening = "unix:$TEST_NGINX_HTML_DIR/nginx.sock",
testing = true,
}

local ev = require("resty.events").new(opts)
if not ev then
ngx.log(ngx.ERR, "failed to new events")
end

local ok, err = ev:init_worker()
if not ok then
ngx.log(ngx.ERR, "failed to init_worker events: ", err)
end

assert(not ev:is_ready())

ev:subscribe("*", "*", function(data, event, source, wid)
ngx.log(ngx.DEBUG, "worker-events: handler event; ","source=",source,", event=",event, ", wid=", wid,
", data=", tostring(data))
end)

_G.ev = ev
}
--- config
location = /test {
content_by_lua_block {
local ev = _G.ev
assert(ev:is_ready())
ev:publish("all", "content_by_lua","request1","01234567890")
ev:publish("unique_value", "content_by_lua","request2","01234567890")
ev:publish("unique_value", "content_by_lua","request3","01234567890")
ngx.sleep(0.1) -- wait for unique timeout to expire
ev:publish("unique_value", "content_by_lua","request4","01234567890")
ev:publish("unique_value", "content_by_lua","request5","01234567890")
ev:publish("all", "content_by_lua","request6","01234567890")
ngx.say("ok")
}
}
--- request
GET /test
--- response_body
ok
--- error_log
event published to 1 workers
--- no_error_log
[error]
[crit]
[alert]
--- grep_error_log eval: qr/worker-events: .*/
--- grep_error_log_out eval
qr/^worker-events: handling event; source=content_by_lua, event=request1, wid=nil
worker-events: handler event; source=content_by_lua, event=request1, wid=nil, data=01234567890
worker-events: handling event; source=content_by_lua, event=request2, wid=nil
worker-events: handler event; source=content_by_lua, event=request2, wid=nil, data=01234567890
worker-events: handling event; source=content_by_lua, event=request3, wid=nil
worker-events: handler event; source=content_by_lua, event=request3, wid=nil, data=01234567890
worker-events: handling event; source=content_by_lua, event=request4, wid=nil
worker-events: handler event; source=content_by_lua, event=request4, wid=nil, data=01234567890
worker-events: handling event; source=content_by_lua, event=request5, wid=nil
worker-events: handler event; source=content_by_lua, event=request5, wid=nil, data=01234567890
worker-events: handling event; source=content_by_lua, event=request6, wid=nil
worker-events: handler event; source=content_by_lua, event=request6, wid=nil, data=01234567890$/


=== TEST 4: publish events at anywhere
--- http_config
lua_package_path "../lua-resty-core/lib/?.lua;lualib/?/init.lua;lualib/?.lua;;";
init_worker_by_lua_block {
local opts = {
--broker_id = 0,
listening = "unix:$TEST_NGINX_HTML_DIR/nginx.sock",
testing = true,
}

local ev = require("resty.events").new(opts)
if not ev then
ngx.log(ngx.ERR, "failed to new events")
end

ev:subscribe("*", "*", function(data, event, source, wid)
ngx.log(ngx.DEBUG, "worker-events: handler event; ","source=",source,", event=",event, ", wid=", wid,
", data=", tostring(data))
end)

ev:publish("all", "content_by_lua","request1","01234567890")

local ok, err = ev:init_worker()
if not ok then
ngx.log(ngx.ERR, "failed to init_worker events: ", err)
end

assert(not ev:is_ready())

ev:publish("current", "content_by_lua","request2","01234567890")

ev:publish("all", "content_by_lua","request3","01234567890")

_G.ev = ev
}
--- config
location = /test {
content_by_lua_block {
ngx.say("ok")
}
}
--- request
GET /test
--- response_body
ok
--- error_log
event published to 1 workers
--- no_error_log
[error]
[crit]
[alert]
--- grep_error_log eval: qr/worker-events: .*/
--- grep_error_log_out eval
qr/^worker-events: handling event; source=content_by_lua, event=request1, wid=nil
worker-events: handler event; source=content_by_lua, event=request1, wid=nil, data=01234567890
worker-events: handling event; source=content_by_lua, event=request2, wid=nil
worker-events: handler event; source=content_by_lua, event=request2, wid=nil, data=01234567890
worker-events: handling event; source=content_by_lua, event=request3, wid=nil
worker-events: handler event; source=content_by_lua, event=request3, wid=nil, data=01234567890$/


0 comments on commit a34e860

Please sign in to comment.