mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
Remove unused test files for lua-resty-mlcache
This commit is contained in:
parent
597aa7d2e3
commit
d3a25aca34
16 changed files with 0 additions and 10024 deletions
603
src/deps/src/lua-resty-mlcache/t/00-ipc.t
vendored
603
src/deps/src/lua-resty-mlcache/t/00-ipc.t
vendored
|
|
@ -1,603 +0,0 @@
|
|||
# vim:set ts=4 sts=4 sw=4 et ft=:
|
||||
|
||||
use strict;
|
||||
use lib '.';
|
||||
use t::TestMLCache;
|
||||
|
||||
plan tests => repeat_each() * blocks() * 5;
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: new() ensures shm exists
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache_ipc = require "resty.mlcache.ipc"
|
||||
|
||||
local ipc, err = mlcache_ipc.new("foo")
|
||||
ngx.say(err)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
no such lua_shared_dict: foo
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
[alert]
|
||||
|
||||
|
||||
|
||||
=== TEST 2: broadcast() sends an event through shm
|
||||
--- http_config
|
||||
init_worker_by_lua_block {
|
||||
local mlcache_ipc = require "resty.mlcache.ipc"
|
||||
|
||||
ipc = assert(mlcache_ipc.new("ipc_shm", true))
|
||||
|
||||
ipc:subscribe("my_channel", function(data)
|
||||
ngx.log(ngx.NOTICE, "received event from my_channel: ", data)
|
||||
end)
|
||||
}
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
assert(ipc:broadcast("my_channel", "hello world"))
|
||||
assert(ipc:poll())
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- error_log
|
||||
received event from my_channel: hello world
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
[alert]
|
||||
|
||||
|
||||
|
||||
=== TEST 3: broadcast() runs event callback in protected mode
|
||||
--- http_config
|
||||
init_worker_by_lua_block {
|
||||
local mlcache_ipc = require "resty.mlcache.ipc"
|
||||
|
||||
ipc = assert(mlcache_ipc.new("ipc_shm", true))
|
||||
|
||||
ipc:subscribe("my_channel", function(data)
|
||||
error("my callback had an error")
|
||||
end)
|
||||
}
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
assert(ipc:broadcast("my_channel", "hello world"))
|
||||
assert(ipc:poll())
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- error_log eval
|
||||
qr/\[error\] .*? \[ipc\] callback for channel 'my_channel' threw a Lua error: init_worker_by_lua(.*?)?:\d: my callback had an error/
|
||||
--- no_error_log
|
||||
lua entry thread aborted: runtime error
|
||||
[crit]
|
||||
[alert]
|
||||
|
||||
|
||||
|
||||
=== TEST 4: poll() catches invalid timeout arg
|
||||
--- http_config
|
||||
init_worker_by_lua_block {
|
||||
local mlcache_ipc = require "resty.mlcache.ipc"
|
||||
|
||||
ipc = assert(mlcache_ipc.new("ipc_shm", true))
|
||||
}
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local ok, err = pcall(ipc.poll, ipc, false)
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
timeout must be a number
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
[alert]
|
||||
|
||||
|
||||
|
||||
=== TEST 5: poll() catches up with all events
|
||||
--- http_config
|
||||
init_worker_by_lua_block {
|
||||
local mlcache_ipc = require "resty.mlcache.ipc"
|
||||
|
||||
ipc = assert(mlcache_ipc.new("ipc_shm", true))
|
||||
|
||||
ipc:subscribe("my_channel", function(data)
|
||||
ngx.log(ngx.NOTICE, "received event from my_channel: ", data)
|
||||
end)
|
||||
}
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
assert(ipc:broadcast("my_channel", "msg 1"))
|
||||
assert(ipc:broadcast("my_channel", "msg 2"))
|
||||
assert(ipc:broadcast("my_channel", "msg 3"))
|
||||
assert(ipc:poll())
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- error_log
|
||||
received event from my_channel: msg 1
|
||||
received event from my_channel: msg 2
|
||||
received event from my_channel: msg 3
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 6: poll() resumes to current idx if events were previously evicted
|
||||
This ensures new workers spawned during a master process' lifecycle do not
|
||||
attempt to replay all events from index 0.
|
||||
https://github.com/thibaultcha/lua-resty-mlcache/issues/87
|
||||
https://github.com/thibaultcha/lua-resty-mlcache/issues/93
|
||||
--- http_config
|
||||
lua_shared_dict ipc_shm 32k;
|
||||
|
||||
init_by_lua_block {
|
||||
require "resty.core"
|
||||
local mlcache_ipc = require "resty.mlcache.ipc"
|
||||
|
||||
ipc = assert(mlcache_ipc.new("ipc_shm", true))
|
||||
|
||||
ipc:subscribe("my_channel", function(data)
|
||||
ngx.log(ngx.NOTICE, "my_channel event: ", data)
|
||||
end)
|
||||
|
||||
for i = 1, 32 do
|
||||
-- fill shm, simulating busy workers
|
||||
-- this must trigger eviction for this test to succeed
|
||||
assert(ipc:broadcast("my_channel", string.rep(".", 2^10)))
|
||||
end
|
||||
}
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
ngx.say("ipc.idx: ", ipc.idx)
|
||||
|
||||
assert(ipc:broadcast("my_channel", "first broadcast"))
|
||||
assert(ipc:broadcast("my_channel", "second broadcast"))
|
||||
|
||||
-- first poll without new() to simulate new worker
|
||||
assert(ipc:poll())
|
||||
|
||||
-- ipc.idx set to shm_idx-1 ("second broadcast")
|
||||
ngx.say("ipc.idx: ", ipc.idx)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
ipc.idx: 0
|
||||
ipc.idx: 34
|
||||
--- error_log
|
||||
my_channel event: second broadcast
|
||||
--- no_error_log
|
||||
my_channel event: first broadcast
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 7: poll() does not execute events from self (same pid)
|
||||
--- http_config
|
||||
init_worker_by_lua_block {
|
||||
local mlcache_ipc = require "resty.mlcache.ipc"
|
||||
|
||||
ipc = assert(mlcache_ipc.new("ipc_shm"))
|
||||
|
||||
ipc:subscribe("my_channel", function(data)
|
||||
ngx.log(ngx.NOTICE, "received event from my_channel: ", data)
|
||||
end)
|
||||
}
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
assert(ipc:broadcast("my_channel", "hello world"))
|
||||
assert(ipc:poll())
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- no_error_log
|
||||
received event from my_channel: hello world
|
||||
[error]
|
||||
[crit]
|
||||
[alert]
|
||||
|
||||
|
||||
|
||||
=== TEST 8: poll() runs all registered callbacks for a channel
|
||||
--- http_config
|
||||
init_worker_by_lua_block {
|
||||
local mlcache_ipc = require "resty.mlcache.ipc"
|
||||
|
||||
ipc = assert(mlcache_ipc.new("ipc_shm", true))
|
||||
|
||||
ipc:subscribe("my_channel", function(data)
|
||||
ngx.log(ngx.NOTICE, "callback 1 from my_channel: ", data)
|
||||
end)
|
||||
|
||||
ipc:subscribe("my_channel", function(data)
|
||||
ngx.log(ngx.NOTICE, "callback 2 from my_channel: ", data)
|
||||
end)
|
||||
|
||||
ipc:subscribe("my_channel", function(data)
|
||||
ngx.log(ngx.NOTICE, "callback 3 from my_channel: ", data)
|
||||
end)
|
||||
}
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
assert(ipc:broadcast("my_channel", "hello world"))
|
||||
assert(ipc:poll())
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- error_log
|
||||
callback 1 from my_channel: hello world
|
||||
callback 2 from my_channel: hello world
|
||||
callback 3 from my_channel: hello world
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 9: poll() exits when no event to poll
|
||||
--- http_config
|
||||
init_worker_by_lua_block {
|
||||
local mlcache_ipc = require "resty.mlcache.ipc"
|
||||
|
||||
ipc = assert(mlcache_ipc.new("ipc_shm", true))
|
||||
|
||||
ipc:subscribe("my_channel", function(data)
|
||||
ngx.log(ngx.NOTICE, "callback from my_channel: ", data)
|
||||
end)
|
||||
}
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
assert(ipc:poll())
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- no_error_log
|
||||
callback from my_channel: hello world
|
||||
[error]
|
||||
[crit]
|
||||
[alert]
|
||||
|
||||
|
||||
|
||||
=== TEST 10: poll() runs all callbacks from all channels
|
||||
--- http_config
|
||||
init_worker_by_lua_block {
|
||||
local mlcache_ipc = require "resty.mlcache.ipc"
|
||||
|
||||
ipc = assert(mlcache_ipc.new("ipc_shm", true))
|
||||
|
||||
ipc:subscribe("my_channel", function(data)
|
||||
ngx.log(ngx.NOTICE, "callback 1 from my_channel: ", data)
|
||||
end)
|
||||
|
||||
ipc:subscribe("my_channel", function(data)
|
||||
ngx.log(ngx.NOTICE, "callback 2 from my_channel: ", data)
|
||||
end)
|
||||
|
||||
ipc:subscribe("other_channel", function(data)
|
||||
ngx.log(ngx.NOTICE, "callback 1 from other_channel: ", data)
|
||||
end)
|
||||
|
||||
ipc:subscribe("other_channel", function(data)
|
||||
ngx.log(ngx.NOTICE, "callback 2 from other_channel: ", data)
|
||||
end)
|
||||
}
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
assert(ipc:broadcast("my_channel", "hello world"))
|
||||
assert(ipc:broadcast("other_channel", "hello ipc"))
|
||||
assert(ipc:broadcast("other_channel", "hello ipc 2"))
|
||||
assert(ipc:poll())
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- grep_error_log eval: qr/callback \d+ from [^,]*/
|
||||
--- grep_error_log_out
|
||||
callback 1 from my_channel: hello world
|
||||
callback 2 from my_channel: hello world
|
||||
callback 1 from other_channel: hello ipc
|
||||
callback 2 from other_channel: hello ipc
|
||||
callback 1 from other_channel: hello ipc 2
|
||||
callback 2 from other_channel: hello ipc 2
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
[alert]
|
||||
|
||||
|
||||
|
||||
=== TEST 11: poll() catches tampered shm (by third-party users)
|
||||
--- http_config
|
||||
init_worker_by_lua_block {
|
||||
local mlcache_ipc = require "resty.mlcache.ipc"
|
||||
|
||||
ipc = assert(mlcache_ipc.new("ipc_shm", true))
|
||||
}
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
assert(ipc:broadcast("my_channel", "msg 1"))
|
||||
|
||||
assert(ngx.shared.ipc_shm:set("lua-resty-ipc:index", false))
|
||||
|
||||
local ok, err = ipc:poll()
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
index is not a number, shm tampered with
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
[alert]
|
||||
|
||||
|
||||
|
||||
=== TEST 12: poll() retries getting an event until timeout
|
||||
--- http_config
|
||||
init_worker_by_lua_block {
|
||||
local mlcache_ipc = require "resty.mlcache.ipc"
|
||||
|
||||
ipc = assert(mlcache_ipc.new("ipc_shm", true))
|
||||
}
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
assert(ipc:broadcast("my_channel", "msg 1"))
|
||||
|
||||
ngx.shared.ipc_shm:delete(1)
|
||||
ngx.shared.ipc_shm:flush_expired()
|
||||
|
||||
local ok, err = ipc:poll()
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, "could not poll: ", err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- grep_error_log eval: qr/((\[error\] .*?)|(\[ipc\] no event data at index '\d+', retrying .*?))[^,]*/
|
||||
--- grep_error_log_out eval
|
||||
qr/\[ipc\] no event data at index '1', retrying in: 0\.001s
|
||||
\[ipc\] no event data at index '1', retrying in: 0\.002s
|
||||
\[ipc\] no event data at index '1', retrying in: 0\.004s
|
||||
\[ipc\] no event data at index '1', retrying in: 0\.008s
|
||||
\[ipc\] no event data at index '1', retrying in: 0\.016s
|
||||
\[ipc\] no event data at index '1', retrying in: 0\.032s
|
||||
\[ipc\] no event data at index '1', retrying in: 0\.064s
|
||||
\[ipc\] no event data at index '1', retrying in: 0\.128s
|
||||
\[ipc\] no event data at index '1', retrying in: 0\.045s
|
||||
\[error\] .*? could not poll: timeout/
|
||||
--- no_error_log
|
||||
[warn]
|
||||
[crit]
|
||||
[alert]
|
||||
|
||||
|
||||
|
||||
=== TEST 13: poll() reaches custom timeout
|
||||
--- http_config
|
||||
init_worker_by_lua_block {
|
||||
local mlcache_ipc = require "resty.mlcache.ipc"
|
||||
|
||||
ipc = assert(mlcache_ipc.new("ipc_shm", true))
|
||||
}
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
assert(ipc:broadcast("my_channel", "msg 1"))
|
||||
|
||||
ngx.shared.ipc_shm:delete(1)
|
||||
ngx.shared.ipc_shm:flush_expired()
|
||||
|
||||
local ok, err = ipc:poll(0.01)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, "could not poll: ", err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- grep_error_log eval: qr/((\[error\] .*?)|(\[ipc\] no event data at index '\d+', retrying .*?))[^,]*/
|
||||
--- grep_error_log_out eval
|
||||
qr/\[ipc\] no event data at index '1', retrying in: 0\.001s
|
||||
\[ipc\] no event data at index '1', retrying in: 0\.002s
|
||||
\[ipc\] no event data at index '1', retrying in: 0\.004s
|
||||
\[ipc\] no event data at index '1', retrying in: 0\.003s
|
||||
\[error\] .*? could not poll: timeout/
|
||||
--- no_error_log
|
||||
[warn]
|
||||
[crit]
|
||||
[alert]
|
||||
|
||||
|
||||
|
||||
=== TEST 14: poll() logs errors and continue if event has been tampered with
|
||||
--- http_config
|
||||
init_worker_by_lua_block {
|
||||
local mlcache_ipc = require "resty.mlcache.ipc"
|
||||
|
||||
ipc = assert(mlcache_ipc.new("ipc_shm", true))
|
||||
|
||||
ipc:subscribe("my_channel", function(data)
|
||||
ngx.log(ngx.NOTICE, "callback from my_channel: ", data)
|
||||
end)
|
||||
}
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
assert(ipc:broadcast("my_channel", "msg 1"))
|
||||
assert(ipc:broadcast("my_channel", "msg 2"))
|
||||
|
||||
assert(ngx.shared.ipc_shm:set(1, false))
|
||||
|
||||
assert(ipc:poll())
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- error_log eval
|
||||
[
|
||||
qr/\[error\] .*? \[ipc\] event at index '1' is not a string, shm tampered with/,
|
||||
qr/\[notice\] .*? callback from my_channel: msg 2/,
|
||||
]
|
||||
--- no_error_log
|
||||
[warn]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 15: poll() is safe to be called in contexts that don't support ngx.sleep()
|
||||
--- http_config
|
||||
init_worker_by_lua_block {
|
||||
local mlcache_ipc = require "resty.mlcache.ipc"
|
||||
|
||||
ipc = assert(mlcache_ipc.new("ipc_shm", true))
|
||||
|
||||
ipc:subscribe("my_channel", function(data)
|
||||
ngx.log(ngx.NOTICE, "callback from my_channel: ", data)
|
||||
end)
|
||||
}
|
||||
--- config
|
||||
location /t {
|
||||
return 200;
|
||||
|
||||
log_by_lua_block {
|
||||
assert(ipc:broadcast("my_channel", "msg 1"))
|
||||
|
||||
ngx.shared.ipc_shm:delete(1)
|
||||
ngx.shared.ipc_shm:flush_expired()
|
||||
|
||||
local ok, err = ipc:poll()
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, "could not poll: ", err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- error_log eval
|
||||
[
|
||||
qr/\[info\] .*? \[ipc\] no event data at index '1', retrying in: 0\.001s/,
|
||||
qr/\[warn\] .*? \[ipc\] could not sleep before retry: API disabled in the context of log_by_lua/,
|
||||
qr/\[error\] .*? could not poll: timeout/,
|
||||
]
|
||||
--- no_error_log
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 16: poll() guards self.idx from growing beyond the current shm idx
|
||||
--- http_config
|
||||
init_worker_by_lua_block {
|
||||
local mlcache_ipc = require "resty.mlcache.ipc"
|
||||
|
||||
ipc = assert(mlcache_ipc.new("ipc_shm", true))
|
||||
|
||||
ipc:subscribe("my_channel", function(data)
|
||||
ngx.log(ngx.NOTICE, "callback from my_channel: ", data)
|
||||
end)
|
||||
}
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
assert(ipc:broadcast("other_channel", ""))
|
||||
assert(ipc:poll())
|
||||
assert(ipc:broadcast("my_channel", "fist broadcast"))
|
||||
assert(ipc:broadcast("other_channel", ""))
|
||||
assert(ipc:broadcast("my_channel", "second broadcast"))
|
||||
|
||||
-- shm idx is 5, let's mess with the instance's idx
|
||||
ipc.idx = 10
|
||||
assert(ipc:poll())
|
||||
|
||||
-- we may have skipped the above events, but we are able to resume polling
|
||||
assert(ipc:broadcast("other_channel", ""))
|
||||
assert(ipc:broadcast("my_channel", "third broadcast"))
|
||||
assert(ipc:poll())
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- error_log
|
||||
callback from my_channel: third broadcast
|
||||
--- no_error_log
|
||||
callback from my_channel: first broadcast
|
||||
callback from my_channel: second broadcast
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 17: poll() JITs
|
||||
--- http_config
|
||||
init_worker_by_lua_block {
|
||||
local mlcache_ipc = require "resty.mlcache.ipc"
|
||||
|
||||
ipc = assert(mlcache_ipc.new("ipc_shm", true))
|
||||
|
||||
ipc:subscribe("my_channel", function(data)
|
||||
ngx.log(ngx.NOTICE, "callback from my_channel: ", data)
|
||||
end)
|
||||
}
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
for i = 1, 10e3 do
|
||||
assert(ipc:poll())
|
||||
end
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- error_log eval
|
||||
qr/\[TRACE\s+\d+ content_by_lua\(nginx\.conf:\d+\):2 loop\]/
|
||||
--- no_error_log
|
||||
[warn]
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 18: broadcast() JITs
|
||||
--- http_config
|
||||
init_worker_by_lua_block {
|
||||
local mlcache_ipc = require "resty.mlcache.ipc"
|
||||
|
||||
ipc = assert(mlcache_ipc.new("ipc_shm", true))
|
||||
|
||||
ipc:subscribe("my_channel", function(data)
|
||||
ngx.log(ngx.NOTICE, "callback from my_channel: ", data)
|
||||
end)
|
||||
}
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
for i = 1, 10e3 do
|
||||
assert(ipc:broadcast("my_channel", "hello world"))
|
||||
end
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- error_log eval
|
||||
qr/\[TRACE\s+\d+ content_by_lua\(nginx\.conf:\d+\):2 loop\]/
|
||||
--- no_error_log
|
||||
[warn]
|
||||
[error]
|
||||
[crit]
|
||||
533
src/deps/src/lua-resty-mlcache/t/01-new.t
vendored
533
src/deps/src/lua-resty-mlcache/t/01-new.t
vendored
|
|
@ -1,533 +0,0 @@
|
|||
# vim:set ts=4 sts=4 sw=4 et ft=:
|
||||
|
||||
use strict;
|
||||
use lib '.';
|
||||
use t::TestMLCache;
|
||||
|
||||
repeat_each(2);
|
||||
|
||||
plan tests => repeat_each() * blocks() * 3;
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: module has version number
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
ngx.say(mlcache._VERSION)
|
||||
}
|
||||
}
|
||||
--- response_body_like
|
||||
\d+\.\d+\.\d+
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 2: new() validates name
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local ok, err = pcall(mlcache.new)
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
name must be a string
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 3: new() validates shm
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local ok, err = pcall(mlcache.new, "name")
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
shm must be a string
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 4: new() validates opts
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local ok, err = pcall(mlcache.new, "name", "cache_shm", "foo")
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
opts must be a table
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 5: new() ensures shm exists
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("name", "foo")
|
||||
if not cache then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
no such lua_shared_dict: foo
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 6: new() supports ipc_shm option and validates it
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local ok, err = pcall(mlcache.new, "name", "cache_shm", { ipc_shm = 1 })
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
opts.ipc_shm must be a string
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 7: new() supports opts.ipc_shm and ensures it exists
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("name", "cache_shm", { ipc_shm = "ipc" })
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- error_log eval
|
||||
qr/\[error\] .*? no such lua_shared_dict: ipc/
|
||||
--- no_error_log
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 8: new() supports ipc options and validates it
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local ok, err = pcall(mlcache.new, "name", "cache_shm", { ipc = false })
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
opts.ipc must be a table
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 9: new() prevents both opts.ipc_shm and opts.ipc to be given
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local ok, err = pcall(mlcache.new, "name", "cache_shm", {
|
||||
ipc_shm = "ipc",
|
||||
ipc = {}
|
||||
})
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
cannot specify both of opts.ipc_shm and opts.ipc
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 10: new() validates ipc.register_listeners + ipc.broadcast + ipc.poll (type: custom)
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local args = {
|
||||
"register_listeners",
|
||||
"broadcast",
|
||||
"poll",
|
||||
}
|
||||
|
||||
for _, arg in ipairs(args) do
|
||||
local ipc_opts = {
|
||||
register_listeners = function() end,
|
||||
broadcast = function() end,
|
||||
poll = function() end,
|
||||
}
|
||||
|
||||
ipc_opts[arg] = false
|
||||
|
||||
local ok, err = pcall(mlcache.new, "name", "cache_shm", {
|
||||
ipc = ipc_opts,
|
||||
})
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
opts.ipc.register_listeners must be a function
|
||||
opts.ipc.broadcast must be a function
|
||||
opts.ipc.poll must be a function
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 11: new() ipc.register_listeners can return nil + err (type: custom)
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("name", "cache_shm", {
|
||||
ipc = {
|
||||
register_listeners = function()
|
||||
return nil, "something happened"
|
||||
end,
|
||||
broadcast = function() end,
|
||||
poll = function() end,
|
||||
}
|
||||
})
|
||||
if not cache then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body_like
|
||||
failed to initialize custom IPC \(opts\.ipc\.register_listeners returned an error\): something happened
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 12: new() calls ipc.register_listeners with events array (type: custom)
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("name", "cache_shm", {
|
||||
ipc = {
|
||||
register_listeners = function(events)
|
||||
local res = {}
|
||||
for ev_name, ev in pairs(events) do
|
||||
table.insert(res, string.format("%s | channel: %s | handler: %s",
|
||||
ev_name, ev.channel, type(ev.handler)))
|
||||
end
|
||||
|
||||
table.sort(res)
|
||||
|
||||
for i = 1, #res do
|
||||
ngx.say(res[i])
|
||||
end
|
||||
end,
|
||||
broadcast = function() end,
|
||||
poll = function() end,
|
||||
}
|
||||
})
|
||||
if not cache then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
invalidation | channel: mlcache:invalidations:name | handler: function
|
||||
purge | channel: mlcache:purge:name | handler: function
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 13: new() ipc.poll is optional (some IPC libraries might not need it
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("name", "cache_shm", {
|
||||
ipc = {
|
||||
register_listeners = function() end,
|
||||
broadcast = function() end,
|
||||
poll = nil
|
||||
}
|
||||
})
|
||||
if not cache then
|
||||
ngx.say(err)
|
||||
end
|
||||
|
||||
ngx.say("ok")
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
ok
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 14: new() validates opts.lru_size
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local ok, err = pcall(mlcache.new, "name", "cache_shm", {
|
||||
lru_size = "",
|
||||
})
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
|
||||
--- error_log
|
||||
opts.lru_size must be a number
|
||||
|
||||
|
||||
|
||||
=== TEST 15: new() validates opts.ttl
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local ok, err = pcall(mlcache.new, "name", "cache_shm", {
|
||||
ttl = ""
|
||||
})
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
|
||||
local ok, err = pcall(mlcache.new, "name", "cache_shm", {
|
||||
ttl = -1
|
||||
})
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
opts.ttl must be a number
|
||||
opts.ttl must be >= 0
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 16: new() validates opts.neg_ttl
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local ok, err = pcall(mlcache.new, "name", "cache_shm", {
|
||||
neg_ttl = ""
|
||||
})
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
|
||||
local ok, err = pcall(mlcache.new, "name", "cache_shm", {
|
||||
neg_ttl = -1
|
||||
})
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
opts.neg_ttl must be a number
|
||||
opts.neg_ttl must be >= 0
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 17: new() validates opts.resty_lock_opts
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local ok, err = pcall(mlcache.new, "name", "cache_shm", {
|
||||
resty_lock_opts = false,
|
||||
})
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
opts.resty_lock_opts must be a table
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 18: new() validates opts.shm_set_tries
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local values = {
|
||||
false,
|
||||
-1,
|
||||
0,
|
||||
}
|
||||
|
||||
for _, v in ipairs(values) do
|
||||
local ok, err = pcall(mlcache.new, "name", "cache_shm", {
|
||||
shm_set_tries = v,
|
||||
})
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
opts.shm_set_tries must be a number
|
||||
opts.shm_set_tries must be >= 1
|
||||
opts.shm_set_tries must be >= 1
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 19: new() validates opts.shm_miss
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local ok, err = pcall(mlcache.new, "name", "cache_shm", {
|
||||
shm_miss = false,
|
||||
})
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
opts.shm_miss must be a string
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 20: new() ensures opts.shm_miss exists
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local ok, err = mlcache.new("name", "cache_shm", {
|
||||
shm_miss = "foo",
|
||||
})
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
no such lua_shared_dict for opts.shm_miss: foo
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 21: new() creates an mlcache object with default attributes
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("name", "cache_shm")
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
|
||||
ngx.say(type(cache))
|
||||
ngx.say(type(cache.ttl))
|
||||
ngx.say(type(cache.neg_ttl))
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
table
|
||||
number
|
||||
number
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 22: new() accepts user-provided LRU instances via opts.lru
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
local pureffi_lrucache = require "resty.lrucache.pureffi"
|
||||
|
||||
local my_lru = pureffi_lrucache.new(100)
|
||||
|
||||
local cache = assert(mlcache.new("name", "cache_shm", { lru = my_lru }))
|
||||
|
||||
ngx.say("lru is user-provided: ", cache.lru == my_lru)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
lru is user-provided: true
|
||||
--- no_error_log
|
||||
[error]
|
||||
2627
src/deps/src/lua-resty-mlcache/t/02-get.t
vendored
2627
src/deps/src/lua-resty-mlcache/t/02-get.t
vendored
File diff suppressed because it is too large
Load diff
611
src/deps/src/lua-resty-mlcache/t/03-peek.t
vendored
611
src/deps/src/lua-resty-mlcache/t/03-peek.t
vendored
|
|
@ -1,611 +0,0 @@
|
|||
# vim:set ts=4 sts=4 sw=4 et ft=:
|
||||
|
||||
use strict;
|
||||
use lib '.';
|
||||
use t::TestMLCache;
|
||||
|
||||
workers(2);
|
||||
#repeat_each(2);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 4);
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: peek() validates key
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm")
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local ok, err = pcall(cache.peek, cache)
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
key must be a string
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 2: peek() returns nil if a key has never been fetched before
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm")
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local ttl, err = cache:peek("my_key")
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("ttl: ", ttl)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
ttl: nil
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 3: peek() returns the remaining ttl if a key has been fetched before
|
||||
--- main_config
|
||||
timer_resolution 10ms;
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm")
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local function cb()
|
||||
return nil
|
||||
end
|
||||
|
||||
local val, err = cache:get("my_key", { neg_ttl = 19 }, cb)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local ttl, err = cache:peek("my_key")
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("ttl: ", math.ceil(ttl))
|
||||
|
||||
ngx.sleep(1)
|
||||
|
||||
local ttl, err = cache:peek("my_key")
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("ttl: ", math.ceil(ttl))
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
ttl: 19
|
||||
ttl: 18
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 4: peek() returns a 0 remaining_ttl if the ttl was 0
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm"))
|
||||
|
||||
local function cb()
|
||||
return nil
|
||||
end
|
||||
|
||||
local val, err = cache:get("my_key", { neg_ttl = 0 }, cb)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.sleep(1)
|
||||
|
||||
local ttl = assert(cache:peek("my_key"))
|
||||
ngx.say("ttl: ", math.ceil(ttl))
|
||||
|
||||
ngx.sleep(1)
|
||||
|
||||
local ttl = assert(cache:peek("my_key"))
|
||||
ngx.say("ttl: ", math.ceil(ttl))
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
ttl: 0
|
||||
ttl: 0
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 5: peek() returns remaining ttl if shm_miss is specified
|
||||
--- main_config
|
||||
timer_resolution 10ms;
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
shm_miss = "cache_shm_miss",
|
||||
}))
|
||||
|
||||
local function cb()
|
||||
return nil
|
||||
end
|
||||
|
||||
local val, err = cache:get("my_key", { neg_ttl = 19 }, cb)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local ttl, err = cache:peek("my_key")
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("ttl: ", math.ceil(ttl))
|
||||
|
||||
ngx.sleep(1)
|
||||
|
||||
local ttl, err = cache:peek("my_key")
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("ttl: ", math.ceil(ttl))
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
ttl: 19
|
||||
ttl: 18
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 6: peek() returns the value if a key has been fetched before
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm")
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local function cb_number()
|
||||
return 123
|
||||
end
|
||||
|
||||
local function cb_nil()
|
||||
return nil
|
||||
end
|
||||
|
||||
local val, err = cache:get("my_key", nil, cb_number)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local val, err = cache:get("my_nil_key", nil, cb_nil)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local ttl, err, val = cache:peek("my_key")
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("ttl: ", math.ceil(ttl), " val: ", val)
|
||||
|
||||
local ttl, err, val = cache:peek("my_nil_key")
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("ttl: ", math.ceil(ttl), " nil_val: ", val)
|
||||
}
|
||||
}
|
||||
--- response_body_like
|
||||
ttl: \d* val: 123
|
||||
ttl: \d* nil_val: nil
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 7: peek() returns the value if shm_miss is specified
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
shm_miss = "cache_shm_miss",
|
||||
}))
|
||||
|
||||
local function cb_nil()
|
||||
return nil
|
||||
end
|
||||
|
||||
local val, err = cache:get("my_nil_key", nil, cb_nil)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local ttl, err, val = cache:peek("my_nil_key")
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("ttl: ", math.ceil(ttl), " nil_val: ", val)
|
||||
}
|
||||
}
|
||||
--- response_body_like
|
||||
ttl: \d* nil_val: nil
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 8: peek() JITs on hit
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm"))
|
||||
|
||||
local function cb()
|
||||
return 123456
|
||||
end
|
||||
|
||||
local val = assert(cache:get("key", nil, cb))
|
||||
ngx.say("val: ", val)
|
||||
|
||||
for i = 1, 10e3 do
|
||||
assert(cache:peek("key"))
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
val: 123456
|
||||
--- error_log eval
|
||||
qr/\[TRACE\s+\d+ content_by_lua\(nginx\.conf:\d+\):13 loop\]/
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 9: peek() JITs on miss
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm"))
|
||||
|
||||
for i = 1, 10e3 do
|
||||
local ttl, err, val = cache:peek("key")
|
||||
assert(err == nil)
|
||||
assert(ttl == nil)
|
||||
assert(val == nil)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- error_log eval
|
||||
qr/\[TRACE\s+\d+ content_by_lua\(nginx\.conf:\d+\):6 loop\]/
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 10: peek() returns nil if a value expired
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm")
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
assert(cache:get("my_key", { ttl = 0.3 }, function()
|
||||
return 123
|
||||
end))
|
||||
|
||||
ngx.sleep(0.3)
|
||||
|
||||
local ttl, err, data, stale = cache:peek("my_key")
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("ttl: ", ttl)
|
||||
ngx.say("data: ", data)
|
||||
ngx.say("stale: ", stale)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
ttl: nil
|
||||
data: nil
|
||||
stale: nil
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 11: peek() returns nil if a value expired in 'shm_miss'
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm", {
|
||||
shm_miss = "cache_shm_miss"
|
||||
})
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local data, err = cache:get("my_key", { neg_ttl = 0.3 }, function()
|
||||
return nil
|
||||
end)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.sleep(0.3)
|
||||
|
||||
local ttl, err, data, stale = cache:peek("my_key")
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("ttl: ", ttl)
|
||||
ngx.say("data: ", data)
|
||||
ngx.say("stale: ", stale)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
ttl: nil
|
||||
data: nil
|
||||
stale: nil
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 12: peek() accepts stale arg and returns stale values
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm")
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
assert(cache:get("my_key", { ttl = 0.3 }, function()
|
||||
return 123
|
||||
end))
|
||||
|
||||
ngx.sleep(0.3)
|
||||
|
||||
local ttl, err, data, stale = cache:peek("my_key", true)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("ttl: ", ttl)
|
||||
ngx.say("data: ", data)
|
||||
ngx.say("stale: ", stale)
|
||||
}
|
||||
}
|
||||
--- response_body_like chomp
|
||||
ttl: -0\.\d+
|
||||
data: 123
|
||||
stale: true
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 13: peek() accepts stale arg and returns stale values from 'shm_miss'
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm", {
|
||||
shm_miss = "cache_shm_miss"
|
||||
})
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local data, err = cache:get("my_key", { neg_ttl = 0.3 }, function()
|
||||
return nil
|
||||
end)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.sleep(0.3)
|
||||
|
||||
local ttl, err, data, stale = cache:peek("my_key", true)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("ttl: ", ttl)
|
||||
ngx.say("data: ", data)
|
||||
ngx.say("stale: ", stale)
|
||||
}
|
||||
}
|
||||
--- response_body_like chomp
|
||||
ttl: -0\.\d+
|
||||
data: nil
|
||||
stale: true
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 14: peek() does not evict stale items from L2 shm
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ttl = 0.3,
|
||||
}))
|
||||
|
||||
local data, err = cache:get("key", nil, function()
|
||||
return 123
|
||||
end)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.sleep(0.3)
|
||||
|
||||
for i = 1, 3 do
|
||||
remaining_ttl, err, data = cache:peek("key", true)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
ngx.say("remaining_ttl: ", remaining_ttl)
|
||||
ngx.say("data: ", data)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body_like chomp
|
||||
remaining_ttl: -\d\.\d+
|
||||
data: 123
|
||||
remaining_ttl: -\d\.\d+
|
||||
data: 123
|
||||
remaining_ttl: -\d\.\d+
|
||||
data: 123
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 15: peek() does not evict stale negative data from L2 shm_miss
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
neg_ttl = 0.3,
|
||||
shm_miss = "cache_shm_miss",
|
||||
}))
|
||||
|
||||
local data, err = cache:get("key", nil, function()
|
||||
return nil
|
||||
end)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.sleep(0.3)
|
||||
|
||||
for i = 1, 3 do
|
||||
remaining_ttl, err, data = cache:peek("key", true)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
ngx.say("remaining_ttl: ", remaining_ttl)
|
||||
ngx.say("data: ", data)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body_like chomp
|
||||
remaining_ttl: -\d\.\d+
|
||||
data: nil
|
||||
remaining_ttl: -\d\.\d+
|
||||
data: nil
|
||||
remaining_ttl: -\d\.\d+
|
||||
data: nil
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
81
src/deps/src/lua-resty-mlcache/t/04-update.t
vendored
81
src/deps/src/lua-resty-mlcache/t/04-update.t
vendored
|
|
@ -1,81 +0,0 @@
|
|||
# vim:set ts=4 sts=4 sw=4 et ft=:
|
||||
|
||||
use strict;
|
||||
use lib '.';
|
||||
use t::TestMLCache;
|
||||
|
||||
workers(2);
|
||||
#repeat_each(2);
|
||||
|
||||
plan tests => repeat_each() * blocks() * 3;
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: update() errors if no ipc
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm"))
|
||||
|
||||
local ok, err = pcall(cache.update, cache, "foo")
|
||||
ngx.say(err)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
no polling configured, specify opts.ipc_shm or opts.ipc.poll
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 2: update() calls ipc poll() with timeout arg
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc = {
|
||||
register_listeners = function() end,
|
||||
broadcast = function() end,
|
||||
poll = function(...)
|
||||
ngx.say("called poll() with args: ", ...)
|
||||
return true
|
||||
end,
|
||||
}
|
||||
}))
|
||||
|
||||
assert(cache:update(3.5, "not me"))
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
called poll() with args: 3.5
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 3: update() JITs when no events to catch up
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
}))
|
||||
|
||||
for i = 1, 10e3 do
|
||||
assert(cache:update())
|
||||
end
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- error_log eval
|
||||
qr/\[TRACE\s+\d+ content_by_lua\(nginx\.conf:\d+\):8 loop\]/
|
||||
--- no_error_log
|
||||
[error]
|
||||
588
src/deps/src/lua-resty-mlcache/t/05-set.t
vendored
588
src/deps/src/lua-resty-mlcache/t/05-set.t
vendored
|
|
@ -1,588 +0,0 @@
|
|||
# vim:set ts=4 sts=4 sw=4 et ft=:
|
||||
|
||||
use strict;
|
||||
use lib '.';
|
||||
use t::TestMLCache;
|
||||
|
||||
#repeat_each(2);
|
||||
|
||||
plan tests => repeat_each() * blocks() * 4;
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: set() errors if no ipc
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm"))
|
||||
|
||||
local ok, err = pcall(cache.set, cache, "foo")
|
||||
ngx.say(err)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
no ipc to propagate update, specify opts.ipc_shm or opts.ipc
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 2: set() validates key
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
}))
|
||||
|
||||
local ok, err = pcall(cache.set, cache)
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
key must be a string
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 3: set() puts a value directly in shm
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
}))
|
||||
|
||||
-- setting a value in shm
|
||||
|
||||
assert(cache:set("my_key", nil, 123))
|
||||
|
||||
-- declaring a callback that MUST NOT be called
|
||||
|
||||
local function cb()
|
||||
ngx.log(ngx.ERR, "callback was called but should not have")
|
||||
end
|
||||
|
||||
-- try to get()
|
||||
|
||||
local value = assert(cache:get("my_key", nil, cb))
|
||||
|
||||
ngx.say("value from get(): ", value)
|
||||
|
||||
-- value MUST BE in lru
|
||||
|
||||
local value_lru = cache.lru:get("my_key")
|
||||
|
||||
ngx.say("cache lru value after get(): ", value_lru)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
value from get(): 123
|
||||
cache lru value after get(): 123
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 4: set() puts a negative hit directly in shm_miss if specified
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
shm_miss = "cache_shm_miss",
|
||||
}))
|
||||
|
||||
-- setting a value in shm
|
||||
|
||||
assert(cache:set("my_key", nil, nil))
|
||||
|
||||
-- declaring a callback that MUST NOT be called
|
||||
|
||||
local function cb()
|
||||
ngx.log(ngx.ERR, "callback was called but should not have")
|
||||
end
|
||||
|
||||
-- try to get()
|
||||
|
||||
local value, err = cache:get("my_key", nil, cb)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("value from get(): ", value)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
value from get(): nil
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 5: set() puts a value directly in its own LRU
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
}))
|
||||
|
||||
-- setting a value in shm
|
||||
|
||||
assert(cache:set("my_key", nil, 123))
|
||||
|
||||
-- value MUST BE be in lru
|
||||
|
||||
local value_lru = cache.lru:get("my_key")
|
||||
|
||||
ngx.say("cache lru value after set(): ", value_lru)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
cache lru value after set(): 123
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 6: set() respects 'ttl' for non-nil values
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
}))
|
||||
|
||||
-- setting a non-nil value in shm
|
||||
|
||||
assert(cache:set("my_key", {
|
||||
ttl = 0.2,
|
||||
neg_ttl = 1,
|
||||
}, 123))
|
||||
|
||||
-- declaring a callback that logs accesses
|
||||
|
||||
local function cb()
|
||||
ngx.say("callback called")
|
||||
return 123
|
||||
end
|
||||
|
||||
-- try to get() (callback MUST NOT be called)
|
||||
|
||||
ngx.say("calling get()")
|
||||
local value = assert(cache:get("my_key", nil, cb))
|
||||
ngx.say("value from get(): ", value)
|
||||
|
||||
-- wait until expiry
|
||||
|
||||
ngx.say("waiting until expiry...")
|
||||
ngx.sleep(0.3)
|
||||
ngx.say("waited 0.3s")
|
||||
|
||||
-- try to get() (callback MUST be called)
|
||||
|
||||
ngx.say("calling get()")
|
||||
local value = assert(cache:get("my_key", nil, cb))
|
||||
ngx.say("value from get(): ", value)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
calling get()
|
||||
value from get(): 123
|
||||
waiting until expiry...
|
||||
waited 0.3s
|
||||
calling get()
|
||||
callback called
|
||||
value from get(): 123
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 7: set() respects 'neg_ttl' for nil values
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
}))
|
||||
|
||||
-- setting a nil value in shm
|
||||
|
||||
assert(cache:set("my_key", {
|
||||
ttl = 1,
|
||||
neg_ttl = 0.2,
|
||||
}, nil))
|
||||
|
||||
-- declaring a callback that logs accesses
|
||||
|
||||
local function cb()
|
||||
ngx.say("callback called")
|
||||
return nil
|
||||
end
|
||||
|
||||
-- try to get() (callback MUST NOT be called)
|
||||
|
||||
ngx.say("calling get()")
|
||||
local value, err = cache:get("my_key", nil, cb)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
ngx.say("value from get(): ", value)
|
||||
|
||||
-- wait until expiry
|
||||
|
||||
ngx.say("waiting until expiry...")
|
||||
ngx.sleep(0.3)
|
||||
ngx.say("waited 0.3s")
|
||||
|
||||
-- try to get() (callback MUST be called)
|
||||
|
||||
ngx.say("calling get()")
|
||||
local value, err = cache:get("my_key", nil, cb)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
end
|
||||
ngx.say("value from get(): ", value)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
calling get()
|
||||
value from get(): nil
|
||||
waiting until expiry...
|
||||
waited 0.3s
|
||||
calling get()
|
||||
callback called
|
||||
value from get(): nil
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 8: set() respects 'set_shm_tries'
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local dict = ngx.shared.cache_shm
|
||||
dict:flush_all()
|
||||
dict:flush_expired()
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
-- fill up shm
|
||||
|
||||
local idx = 0
|
||||
|
||||
while true do
|
||||
local ok, err, forcible = dict:set(idx, string.rep("a", 2^2))
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
if forcible then
|
||||
break
|
||||
end
|
||||
|
||||
idx = idx + 1
|
||||
end
|
||||
|
||||
-- shm:set() will evict up to 30 items when the shm is full
|
||||
-- now, trigger a hit with a larger value which should trigger LRU
|
||||
-- eviction and force the slab allocator to free pages
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
}))
|
||||
|
||||
local data, err = cache:set("key", {
|
||||
shm_set_tries = 5,
|
||||
}, string.rep("a", 2^12))
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
-- from shm
|
||||
|
||||
cache.lru:delete("key")
|
||||
|
||||
local cb_called
|
||||
local function cb()
|
||||
cb_called = true
|
||||
end
|
||||
|
||||
local data, err = cache:get("key", nil, cb)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("type of data in shm: ", type(data))
|
||||
ngx.say("callback was called: ", cb_called ~= nil)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
type of data in shm: string
|
||||
callback was called: false
|
||||
--- no_error_log
|
||||
[warn]
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 9: set() with shm_miss can set a nil where a value was
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
shm_miss = "cache_shm_miss",
|
||||
}))
|
||||
|
||||
local function cb()
|
||||
return 123
|
||||
end
|
||||
|
||||
-- install a non-nil value in the cache
|
||||
|
||||
local value, err = cache:get("my_key", nil, cb)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("initial value from get(): ", value)
|
||||
|
||||
-- override that value with a negative hit that
|
||||
-- must go in the shm_miss (and the shm value must be
|
||||
-- erased)
|
||||
|
||||
assert(cache:set("my_key", nil, nil))
|
||||
|
||||
-- and remove it from the LRU
|
||||
|
||||
cache.lru:delete("my_key")
|
||||
|
||||
-- ok, now we should be getting nil from the cache
|
||||
|
||||
local value, err = cache:get("my_key", nil, cb)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("value from get() after set(): ", value)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
initial value from get(): 123
|
||||
value from get() after set(): nil
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 10: set() with shm_miss can set a value where a nil was
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
shm_miss = "cache_shm_miss",
|
||||
}))
|
||||
|
||||
local function cb()
|
||||
return nil
|
||||
end
|
||||
|
||||
-- install a non-nil value in the cache
|
||||
|
||||
local value, err = cache:get("my_key", nil, cb)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("initial value from get(): ", value)
|
||||
|
||||
-- override that value with a negative hit that
|
||||
-- must go in the shm_miss (and the shm value must be
|
||||
-- erased)
|
||||
|
||||
assert(cache:set("my_key", nil, 123))
|
||||
|
||||
-- and remove it from the LRU
|
||||
|
||||
cache.lru:delete("my_key")
|
||||
|
||||
-- ok, now we should be getting nil from the cache
|
||||
|
||||
local value, err = cache:get("my_key", nil, cb)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("value from get() after set(): ", value)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
initial value from get(): nil
|
||||
value from get() after set(): 123
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 11: set() returns 'no memory' errors upon fragmentation in the shm
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
}))
|
||||
|
||||
-- fill shm
|
||||
|
||||
local idx = 0
|
||||
|
||||
while true do
|
||||
local ok, err, forcible = ngx.shared.cache_shm:set(idx, true)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
if forcible then
|
||||
break
|
||||
end
|
||||
|
||||
idx = idx + 1
|
||||
end
|
||||
|
||||
-- set large value
|
||||
|
||||
local ok, err = cache:set("my_key", { shm_set_tries = 1 }, string.rep("a", 2^10))
|
||||
ngx.say(ok)
|
||||
ngx.say(err)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
nil
|
||||
could not write to lua_shared_dict 'cache_shm': no memory
|
||||
--- no_error_log
|
||||
[warn]
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 12: set() does not set LRU upon shm insertion error
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
}))
|
||||
|
||||
-- fill shm
|
||||
|
||||
local idx = 0
|
||||
|
||||
while true do
|
||||
local ok, err, forcible = ngx.shared.cache_shm:set(idx, true)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
if forcible then
|
||||
break
|
||||
end
|
||||
|
||||
idx = idx + 1
|
||||
end
|
||||
|
||||
-- set large value
|
||||
|
||||
local ok = cache:set("my_key", { shm_set_tries = 1 }, string.rep("a", 2^10))
|
||||
assert(ok == nil)
|
||||
|
||||
local data = cache.lru:get("my_key")
|
||||
ngx.say(data)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
nil
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 13: set() calls broadcast() with invalidated key
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc = {
|
||||
register_listeners = function() end,
|
||||
broadcast = function(channel, data, ...)
|
||||
ngx.say("channel: ", channel)
|
||||
ngx.say("data: ", data)
|
||||
ngx.say("other args:", ...)
|
||||
return true
|
||||
end,
|
||||
poll = function() end,
|
||||
}
|
||||
}))
|
||||
|
||||
assert(cache:set("my_key", nil, nil))
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
channel: mlcache:invalidations:my_mlcache
|
||||
data: my_key
|
||||
other args:
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
228
src/deps/src/lua-resty-mlcache/t/06-delete.t
vendored
228
src/deps/src/lua-resty-mlcache/t/06-delete.t
vendored
|
|
@ -1,228 +0,0 @@
|
|||
# vim:set ts=4 sts=4 sw=4 et ft=:
|
||||
|
||||
use strict;
|
||||
use lib '.';
|
||||
use t::TestMLCache;
|
||||
|
||||
workers(2);
|
||||
#repeat_each(2);
|
||||
|
||||
plan tests => repeat_each() * blocks() * 3;
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: delete() errors if no ipc
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm"))
|
||||
|
||||
local ok, err = pcall(cache.delete, cache, "foo")
|
||||
ngx.say(err)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
no ipc to propagate deletion, specify opts.ipc_shm or opts.ipc
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 2: delete() validates key
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
}))
|
||||
|
||||
local ok, err = pcall(cache.delete, cache, 123)
|
||||
ngx.say(err)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
key must be a string
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 3: delete() removes a cached value from LRU + shm
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
}))
|
||||
|
||||
local value = 123
|
||||
|
||||
local function cb()
|
||||
ngx.say("in callback")
|
||||
return value
|
||||
end
|
||||
|
||||
-- set a value (callback call)
|
||||
|
||||
local data = assert(cache:get("key", nil, cb))
|
||||
ngx.say("from callback: ", data)
|
||||
|
||||
-- get a value (no callback call)
|
||||
|
||||
data = assert(cache:get("key", nil, cb))
|
||||
ngx.say("from LRU: ", data)
|
||||
|
||||
-- test if value is set from shm (safer to check due to the key)
|
||||
|
||||
local v = ngx.shared.cache_shm:get(cache.name .. "key")
|
||||
ngx.say("shm has value before delete: ", v ~= nil)
|
||||
|
||||
-- delete the value
|
||||
|
||||
assert(cache:delete("key"))
|
||||
|
||||
local v = ngx.shared.cache_shm:get(cache.name .. "key")
|
||||
ngx.say("shm has value after delete: ", v ~= nil)
|
||||
|
||||
-- ensure LRU was also deleted
|
||||
|
||||
v = cache.lru:get("key")
|
||||
ngx.say("from LRU: ", v)
|
||||
|
||||
-- start over from callback again
|
||||
|
||||
value = 456
|
||||
|
||||
data = assert(cache:get("key", nil, cb))
|
||||
ngx.say("from callback: ", data)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
in callback
|
||||
from callback: 123
|
||||
from LRU: 123
|
||||
shm has value before delete: true
|
||||
shm has value after delete: false
|
||||
from LRU: nil
|
||||
in callback
|
||||
from callback: 456
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 4: delete() removes a cached nil from shm_miss if specified
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
shm_miss = "cache_shm_miss",
|
||||
}))
|
||||
|
||||
local value = nil
|
||||
|
||||
local function cb()
|
||||
ngx.say("in callback")
|
||||
return value
|
||||
end
|
||||
|
||||
-- set a value (callback call)
|
||||
|
||||
local data, err = cache:get("key", nil, cb)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
ngx.say("from callback: ", data)
|
||||
|
||||
-- get a value (no callback call)
|
||||
|
||||
data, err = cache:get("key", nil, cb)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
ngx.say("from LRU: ", data)
|
||||
|
||||
-- test if value is set from shm (safer to check due to the key)
|
||||
|
||||
local v = ngx.shared.cache_shm_miss:get(cache.name .. "key")
|
||||
ngx.say("shm_miss has value before delete: ", v ~= nil)
|
||||
|
||||
-- delete the value
|
||||
|
||||
assert(cache:delete("key"))
|
||||
|
||||
local v = ngx.shared.cache_shm_miss:get(cache.name .. "key")
|
||||
ngx.say("shm_miss has value after delete: ", v ~= nil)
|
||||
|
||||
-- ensure LRU was also deleted
|
||||
|
||||
v = cache.lru:get("key")
|
||||
ngx.say("from LRU: ", v)
|
||||
|
||||
-- start over from callback again
|
||||
|
||||
value = 456
|
||||
|
||||
data, err = cache:get("key", nil, cb)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
ngx.say("from callback again: ", data)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
in callback
|
||||
from callback: nil
|
||||
from LRU: nil
|
||||
shm_miss has value before delete: true
|
||||
shm_miss has value after delete: false
|
||||
from LRU: nil
|
||||
in callback
|
||||
from callback again: 456
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 5: delete() calls broadcast with invalidated key
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc = {
|
||||
register_listeners = function() end,
|
||||
broadcast = function(channel, data, ...)
|
||||
ngx.say("channel: ", channel)
|
||||
ngx.say("data: ", data)
|
||||
ngx.say("other args:", ...)
|
||||
return true
|
||||
end,
|
||||
poll = function() end,
|
||||
}
|
||||
}))
|
||||
|
||||
assert(cache:delete("my_key"))
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
channel: mlcache:invalidations:my_mlcache
|
||||
data: my_key
|
||||
other args:
|
||||
--- no_error_log
|
||||
[error]
|
||||
811
src/deps/src/lua-resty-mlcache/t/07-l1_serializer.t
vendored
811
src/deps/src/lua-resty-mlcache/t/07-l1_serializer.t
vendored
|
|
@ -1,811 +0,0 @@
|
|||
# vim:set ts=4 sts=4 sw=4 et ft=:
|
||||
|
||||
use strict;
|
||||
use lib '.';
|
||||
use t::TestMLCache;
|
||||
|
||||
workers(2);
|
||||
#repeat_each(2);
|
||||
|
||||
plan tests => repeat_each() * blocks() * 3;
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: l1_serializer is validated by the constructor
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local ok, err = pcall(mlcache.new, "my_mlcache", "cache_shm", {
|
||||
l1_serializer = false,
|
||||
})
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
opts.l1_serializer must be a function
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 2: l1_serializer is called on L1+L2 cache misses
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm", {
|
||||
l1_serializer = function(s)
|
||||
return string.format("transform(%q)", s)
|
||||
end,
|
||||
})
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local data, err = cache:get("key", nil, function() return "foo" end)
|
||||
if not data then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say(data)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
transform("foo")
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 3: get() JITs when hit of scalar value coming from shm with l1_serializer
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm", {
|
||||
l1_serializer = function(i)
|
||||
return i + 2
|
||||
end,
|
||||
})
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local function cb_number()
|
||||
return 123456
|
||||
end
|
||||
|
||||
for i = 1, 10e2 do
|
||||
local data = assert(cache:get("number", nil, cb_number))
|
||||
assert(data == 123458)
|
||||
|
||||
cache.lru:delete("number")
|
||||
end
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- error_log eval
|
||||
qr/\[TRACE\s+\d+ content_by_lua\(nginx\.conf:\d+\):18 loop\]/
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 4: l1_serializer is not called on L1 hits
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local calls = 0
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm", {
|
||||
l1_serializer = function(s)
|
||||
calls = calls + 1
|
||||
return string.format("transform(%q)", s)
|
||||
end,
|
||||
})
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
for i = 1, 3 do
|
||||
local data, err = cache:get("key", nil, function() return "foo" end)
|
||||
if not data then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say(data)
|
||||
end
|
||||
|
||||
ngx.say("calls: ", calls)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
transform("foo")
|
||||
transform("foo")
|
||||
transform("foo")
|
||||
calls: 1
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 5: l1_serializer is called on each L2 hit
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local calls = 0
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm", {
|
||||
l1_serializer = function(s)
|
||||
calls = calls + 1
|
||||
return string.format("transform(%q)", s)
|
||||
end,
|
||||
})
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
for i = 1, 3 do
|
||||
local data, err = cache:get("key", nil, function() return "foo" end)
|
||||
if not data then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say(data)
|
||||
cache.lru:delete("key")
|
||||
end
|
||||
|
||||
ngx.say("calls: ", calls)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
transform("foo")
|
||||
transform("foo")
|
||||
transform("foo")
|
||||
calls: 3
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 6: l1_serializer is called on boolean false hits
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm", {
|
||||
l1_serializer = function(s)
|
||||
return string.format("transform_boolean(%q)", s)
|
||||
end,
|
||||
})
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local function cb()
|
||||
return false
|
||||
end
|
||||
|
||||
local data, err = cache:get("key", nil, cb)
|
||||
if not data then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say(data)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
transform_boolean("false")
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 7: l1_serializer is called on lock timeout
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
-- insert 2 dummy values to ensure that lock acquisition (which
|
||||
-- uses shm:set) will _not_ evict out stale cached value
|
||||
ngx.shared.cache_shm:set(1, true, 0.2)
|
||||
ngx.shared.cache_shm:set(2, true, 0.2)
|
||||
|
||||
local mlcache = require "resty.mlcache"
|
||||
local cache_1 = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ttl = 0.3,
|
||||
resurrect_ttl = 0.3,
|
||||
l1_serializer = function(s)
|
||||
return "from cache_1"
|
||||
end,
|
||||
}))
|
||||
local cache_2 = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ttl = 0.3,
|
||||
resurrect_ttl = 0.3,
|
||||
l1_serializer = function(s)
|
||||
return "from cache_2"
|
||||
end,
|
||||
resty_lock_opts = {
|
||||
timeout = 0.2
|
||||
}
|
||||
}))
|
||||
|
||||
local function cb(delay, return_val)
|
||||
if delay then
|
||||
ngx.sleep(delay)
|
||||
end
|
||||
|
||||
return return_val or 123
|
||||
end
|
||||
|
||||
-- cache in shm
|
||||
|
||||
local data, err, hit_lvl = cache_1:get("my_key", nil, cb)
|
||||
assert(data == "from cache_1")
|
||||
assert(err == nil)
|
||||
assert(hit_lvl == 3)
|
||||
|
||||
-- make shm + LRU expire
|
||||
|
||||
ngx.sleep(0.3)
|
||||
|
||||
local t1 = ngx.thread.spawn(function()
|
||||
-- trigger L3 callback again, but slow to return this time
|
||||
|
||||
cache_1:get("my_key", nil, cb, 0.3, 456)
|
||||
end)
|
||||
|
||||
local t2 = ngx.thread.spawn(function()
|
||||
-- make this mlcache wait on other's callback, and timeout
|
||||
|
||||
local data, err, hit_lvl = cache_2:get("my_key", nil, cb)
|
||||
ngx.say("data: ", data)
|
||||
ngx.say("err: ", err)
|
||||
ngx.say("hit_lvl: ", hit_lvl)
|
||||
end)
|
||||
|
||||
assert(ngx.thread.wait(t1))
|
||||
assert(ngx.thread.wait(t2))
|
||||
|
||||
ngx.say()
|
||||
ngx.say("-> subsequent get()")
|
||||
data, err, hit_lvl = cache_2:get("my_key", nil, cb, nil, 123)
|
||||
ngx.say("data: ", data)
|
||||
ngx.say("err: ", err)
|
||||
ngx.say("hit_lvl: ", hit_lvl) -- should be 1 since LRU instances are shared by mlcache namespace, and t1 finished
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
data: from cache_2
|
||||
err: nil
|
||||
hit_lvl: 4
|
||||
|
||||
-> subsequent get()
|
||||
data: from cache_1
|
||||
err: nil
|
||||
hit_lvl: 1
|
||||
--- error_log eval
|
||||
qr/\[warn\] .*? could not acquire callback lock: timeout/
|
||||
|
||||
|
||||
|
||||
=== TEST 8: l1_serializer is called when value has < 1ms remaining_ttl
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local forced_now = ngx.now()
|
||||
ngx.now = function()
|
||||
return forced_now
|
||||
end
|
||||
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ttl = 0.2,
|
||||
l1_serializer = function(s)
|
||||
return "override"
|
||||
end,
|
||||
}))
|
||||
|
||||
local function cb(v)
|
||||
return v or 42
|
||||
end
|
||||
|
||||
local data, err = cache:get("key", nil, cb)
|
||||
assert(data == "override", err or "invalid data value: " .. data)
|
||||
|
||||
-- drop L1 cache value
|
||||
cache.lru:delete("key")
|
||||
|
||||
-- advance 0.2 second in the future, and simulate another :get()
|
||||
-- call; the L2 shm entry will still be alive (as its clock is
|
||||
-- not faked), but mlcache will compute a remaining_ttl of 0;
|
||||
-- In such cases, we should _not_ cache the value indefinitely in
|
||||
-- the L1 LRU cache.
|
||||
forced_now = forced_now + 0.2
|
||||
|
||||
local data, err, hit_lvl = cache:get("key", nil, cb)
|
||||
assert(data == "override", err or "invalid data value: " .. data)
|
||||
|
||||
ngx.say("+0.200s hit_lvl: ", hit_lvl)
|
||||
|
||||
-- the value is not cached in LRU (too short ttl anyway)
|
||||
|
||||
data, err, hit_lvl = cache:get("key", nil, cb)
|
||||
assert(data == "override", err or "invalid data value: " .. data)
|
||||
|
||||
ngx.say("+0.200s hit_lvl: ", hit_lvl)
|
||||
|
||||
-- make it expire in shm (real wait)
|
||||
ngx.sleep(0.201)
|
||||
|
||||
data, err, hit_lvl = cache:get("key", nil, cb, 91)
|
||||
assert(data == "override", err or "invalid data value: " .. data)
|
||||
|
||||
ngx.say("+0.201s hit_lvl: ", hit_lvl)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
+0.200s hit_lvl: 2
|
||||
+0.200s hit_lvl: 2
|
||||
+0.201s hit_lvl: 3
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 9: l1_serializer is called in protected mode (L2 miss)
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm", {
|
||||
l1_serializer = function(s)
|
||||
error("cannot transform")
|
||||
end,
|
||||
})
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local data, err = cache:get("key", nil, function() return "foo" end)
|
||||
if not data then
|
||||
ngx.say(err)
|
||||
end
|
||||
|
||||
ngx.say(data)
|
||||
}
|
||||
}
|
||||
--- response_body_like
|
||||
l1_serializer threw an error: .*?: cannot transform
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 10: l1_serializer is called in protected mode (L2 hit)
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local called = false
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm", {
|
||||
l1_serializer = function(s)
|
||||
if called then error("cannot transform") end
|
||||
called = true
|
||||
return string.format("transform(%q)", s)
|
||||
end,
|
||||
})
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
assert(cache:get("key", nil, function() return "foo" end))
|
||||
cache.lru:delete("key")
|
||||
|
||||
local data, err = cache:get("key", nil, function() return "foo" end)
|
||||
if not data then
|
||||
ngx.say(err)
|
||||
end
|
||||
|
||||
ngx.say(data)
|
||||
}
|
||||
}
|
||||
--- response_body_like
|
||||
l1_serializer threw an error: .*?: cannot transform
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 11: l1_serializer is not called for L2+L3 misses (no record)
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local called = false
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm", {
|
||||
l1_serializer = function(s)
|
||||
called = true
|
||||
return string.format("transform(%s)", s)
|
||||
end,
|
||||
})
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local data, err = cache:get("key", nil, function() return nil end)
|
||||
if data ~= nil then
|
||||
ngx.log(ngx.ERR, "got a value for a L3 miss: ", tostring(data))
|
||||
return
|
||||
elseif err ~= nil then
|
||||
ngx.log(ngx.ERR, "got an error for a L3 miss: ", tostring(err))
|
||||
return
|
||||
end
|
||||
|
||||
-- our L3 returned nil, we do not call the l1_serializer and
|
||||
-- we store the LRU nil sentinel value
|
||||
|
||||
ngx.say("l1_serializer called for L3 miss: ", called)
|
||||
|
||||
-- delete from LRU, and try from L2 again
|
||||
|
||||
cache.lru:delete("key")
|
||||
|
||||
local data, err = cache:get("key", nil, function() error("not supposed to call") end)
|
||||
if data ~= nil then
|
||||
ngx.log(ngx.ERR, "got a value for a L3 miss: ", tostring(data))
|
||||
return
|
||||
elseif err ~= nil then
|
||||
ngx.log(ngx.ERR, "got an error for a L3 miss: ", tostring(err))
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("l1_serializer called for L2 negative hit: ", called)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
l1_serializer called for L3 miss: false
|
||||
l1_serializer called for L2 negative hit: false
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 12: l1_serializer is not supposed to return a nil value
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm", {
|
||||
l1_serializer = function(s)
|
||||
return nil
|
||||
end,
|
||||
})
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local ok, err = cache:get("key", nil, function() return "foo" end)
|
||||
assert(not ok, "get() should not return successfully")
|
||||
ngx.say(err)
|
||||
}
|
||||
}
|
||||
--- response_body_like
|
||||
l1_serializer returned a nil value
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 13: l1_serializer can return nil + error
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm", {
|
||||
l1_serializer = function(s)
|
||||
return nil, "l1_serializer: cannot transform"
|
||||
end,
|
||||
})
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local data, err = cache:get("key", nil, function() return "foo" end)
|
||||
if not data then
|
||||
ngx.say(err)
|
||||
end
|
||||
|
||||
ngx.say("data: ", data)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
l1_serializer: cannot transform
|
||||
data: nil
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 14: l1_serializer can be given as a get() argument
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm")
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local data, err = cache:get("key", {
|
||||
l1_serializer = function(s)
|
||||
return string.format("transform(%q)", s)
|
||||
end
|
||||
}, function() return "foo" end)
|
||||
if not data then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say(data)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
transform("foo")
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 15: l1_serializer as get() argument has precedence over the constructor one
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm", {
|
||||
l1_serializer = function(s)
|
||||
return string.format("constructor(%q)", s)
|
||||
end
|
||||
})
|
||||
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local data, err = cache:get("key1", {
|
||||
l1_serializer = function(s)
|
||||
return string.format("get_argument(%q)", s)
|
||||
end
|
||||
}, function() return "foo" end)
|
||||
if not data then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say(data)
|
||||
|
||||
local data, err = cache:get("key2", nil, function() return "bar" end)
|
||||
if not data then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say(data)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
get_argument("foo")
|
||||
constructor("bar")
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 16: get() validates l1_serializer is a function
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm")
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local ok, err = pcall(cache.get, cache, "key", {
|
||||
l1_serializer = false,
|
||||
}, function() return "foo" end)
|
||||
if not data then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
opts.l1_serializer must be a function
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 17: set() calls l1_serializer
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
l1_serializer = function(s)
|
||||
return string.format("transform(%q)", s)
|
||||
end
|
||||
})
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local ok, err = cache:set("key", nil, "value")
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local value, err = cache:get("key", nil, error)
|
||||
if not value then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say(value)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
transform("value")
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 18: set() calls l1_serializer for boolean false values
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
l1_serializer = function(s)
|
||||
return string.format("transform_boolean(%q)", s)
|
||||
end
|
||||
})
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local ok, err = cache:set("key", nil, false)
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local value, err = cache:get("key", nil, error)
|
||||
if not value then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say(value)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
transform_boolean("false")
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 19: l1_serializer as set() argument has precedence over the constructor one
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
l1_serializer = function(s)
|
||||
return string.format("constructor(%q)", s)
|
||||
end
|
||||
})
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local ok, err = cache:set("key", {
|
||||
l1_serializer = function(s)
|
||||
return string.format("set_argument(%q)", s)
|
||||
end
|
||||
}, "value")
|
||||
if not ok then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local value, err = cache:get("key", nil, error)
|
||||
if not value then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say(value)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
set_argument("value")
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 20: set() validates l1_serializer is a function
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache, err = mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
})
|
||||
if not cache then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
local ok, err = pcall(cache.set, cache, "key", {
|
||||
l1_serializer = true
|
||||
}, "value")
|
||||
if not data then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
opts.l1_serializer must be a function
|
||||
--- no_error_log
|
||||
[error]
|
||||
362
src/deps/src/lua-resty-mlcache/t/08-purge.t
vendored
362
src/deps/src/lua-resty-mlcache/t/08-purge.t
vendored
|
|
@ -1,362 +0,0 @@
|
|||
# vim:set ts=4 sts=4 sw=4 et ft=:
|
||||
|
||||
use strict;
|
||||
use lib '.';
|
||||
use t::TestMLCache;
|
||||
|
||||
#repeat_each(2);
|
||||
|
||||
plan tests => repeat_each() * blocks() * 3;
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: purge() errors if no ipc
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm"))
|
||||
|
||||
local ok, err = pcall(cache.purge, cache)
|
||||
ngx.say(err)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
no ipc to propagate purge, specify opts.ipc_shm or opts.ipc
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 2: purge() deletes all items from L1 + L2 (sanity 1/2)
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
}))
|
||||
|
||||
-- populate mlcache
|
||||
|
||||
for i = 1, 100 do
|
||||
assert(cache:get(tostring(i), nil, function() return i end))
|
||||
end
|
||||
|
||||
-- purge
|
||||
|
||||
assert(cache:purge())
|
||||
|
||||
for i = 1, 100 do
|
||||
local value, err = cache:get(tostring(i), nil, function() return nil end)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
if value ~= nil then
|
||||
ngx.say("key ", i, " had: ", value)
|
||||
end
|
||||
end
|
||||
|
||||
ngx.say("ok")
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
ok
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 3: purge() deletes all items from L1 (sanity 2/2)
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
}))
|
||||
|
||||
-- populate mlcache
|
||||
|
||||
for i = 1, 100 do
|
||||
assert(cache:get(tostring(i), nil, function() return i end))
|
||||
end
|
||||
|
||||
-- purge
|
||||
|
||||
assert(cache:purge())
|
||||
|
||||
for i = 1, 100 do
|
||||
local value = cache.lru:get(tostring(i))
|
||||
|
||||
if value ~= nil then
|
||||
ngx.say("key ", i, " had: ", value)
|
||||
end
|
||||
end
|
||||
|
||||
ngx.say("ok")
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
ok
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 4: purge() deletes all items from L1 with a custom LRU
|
||||
--- skip_eval: 3: t::TestMLCache::skip_openresty('<', '1.13.6.2')
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
local lrucache = require "resty.lrucache"
|
||||
|
||||
local lru = lrucache.new(100)
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
lru = lru,
|
||||
}))
|
||||
|
||||
-- populate mlcache
|
||||
|
||||
for i = 1, 100 do
|
||||
assert(cache:get(tostring(i), nil, function() return i end))
|
||||
end
|
||||
|
||||
-- purge
|
||||
|
||||
assert(cache:purge())
|
||||
|
||||
for i = 1, 100 do
|
||||
local value = cache.lru:get(tostring(i))
|
||||
|
||||
if value ~= nil then
|
||||
ngx.say("key ", i, " had: ", value)
|
||||
end
|
||||
end
|
||||
|
||||
ngx.say("ok")
|
||||
ngx.say("lru instance is the same one: ", lru == cache.lru)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
ok
|
||||
lru instance is the same one: true
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 5: purge() is prevented if custom LRU does not support flush_all()
|
||||
--- skip_eval: 3: t::TestMLCache::skip_openresty('>', '1.13.6.1')
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
local lrucache = require "resty.lrucache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
lru = lrucache.new(10),
|
||||
}))
|
||||
|
||||
local pok, perr = pcall(cache.purge, cache)
|
||||
if not pok then
|
||||
ngx.say(perr)
|
||||
return
|
||||
end
|
||||
|
||||
ngx.say("ok")
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
cannot purge when using custom LRU cache with OpenResty < 1.13.6.2
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 6: purge() deletes all items from shm_miss is specified
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
shm_miss = "cache_shm_miss",
|
||||
}))
|
||||
|
||||
-- populate mlcache
|
||||
|
||||
for i = 1, 100 do
|
||||
local _, err = cache:get(tostring(i), nil, function() return nil end)
|
||||
if err then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- purge
|
||||
|
||||
assert(cache:purge())
|
||||
|
||||
local called = 0
|
||||
|
||||
for i = 1, 100 do
|
||||
local value, err = cache:get(tostring(i), nil, function() return i end)
|
||||
|
||||
if value ~= i then
|
||||
ngx.say("key ", i, " had: ", value)
|
||||
end
|
||||
end
|
||||
|
||||
ngx.say("ok")
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
ok
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 7: purge() does not call shm:flush_expired() by default
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
do
|
||||
local cache_shm = ngx.shared.cache_shm
|
||||
local mt = getmetatable(cache_shm)
|
||||
local orig_cache_shm_flush_expired = mt.flush_expired
|
||||
|
||||
mt.flush_expired = function(self, ...)
|
||||
ngx.say("flush_expired called with 'max_count'")
|
||||
|
||||
return orig_cache_shm_flush_expired(self, ...)
|
||||
end
|
||||
end
|
||||
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
}))
|
||||
|
||||
assert(cache:purge())
|
||||
}
|
||||
}
|
||||
--- response_body_unlike
|
||||
flush_expired called with 'max_count'
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 8: purge() calls shm:flush_expired() if argument specified
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
do
|
||||
local cache_shm = ngx.shared.cache_shm
|
||||
local mt = getmetatable(cache_shm)
|
||||
local orig_cache_shm_flush_expired = mt.flush_expired
|
||||
|
||||
mt.flush_expired = function(self, ...)
|
||||
local arg = { ... }
|
||||
local n = arg[1]
|
||||
ngx.say("flush_expired called with 'max_count': ", n)
|
||||
|
||||
return orig_cache_shm_flush_expired(self, ...)
|
||||
end
|
||||
end
|
||||
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
}))
|
||||
|
||||
assert(cache:purge(true))
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
flush_expired called with 'max_count': nil
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 9: purge() calls shm:flush_expired() if shm_miss is specified
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
do
|
||||
local cache_shm = ngx.shared.cache_shm
|
||||
local mt = getmetatable(cache_shm)
|
||||
local orig_cache_shm_flush_expired = mt.flush_expired
|
||||
|
||||
mt.flush_expired = function(self, ...)
|
||||
local arg = { ... }
|
||||
local n = arg[1]
|
||||
ngx.say("flush_expired called with 'max_count': ", n)
|
||||
|
||||
return orig_cache_shm_flush_expired(self, ...)
|
||||
end
|
||||
end
|
||||
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
shm_miss = "cache_shm_miss",
|
||||
}))
|
||||
|
||||
assert(cache:purge(true))
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
flush_expired called with 'max_count': nil
|
||||
flush_expired called with 'max_count': nil
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 10: purge() calls broadcast() on purge channel
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc = {
|
||||
register_listeners = function() end,
|
||||
broadcast = function(channel, data, ...)
|
||||
ngx.say("channel: ", channel)
|
||||
ngx.say("data:", data)
|
||||
ngx.say("other args:", ...)
|
||||
return true
|
||||
end,
|
||||
poll = function() end,
|
||||
}
|
||||
}))
|
||||
|
||||
assert(cache:purge())
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
channel: mlcache:purge:my_mlcache
|
||||
data:
|
||||
other args:
|
||||
--- no_error_log
|
||||
[error]
|
||||
344
src/deps/src/lua-resty-mlcache/t/09-isolation.t
vendored
344
src/deps/src/lua-resty-mlcache/t/09-isolation.t
vendored
|
|
@ -1,344 +0,0 @@
|
|||
# vim:set ts=4 sts=4 sw=4 et ft=:
|
||||
|
||||
use strict;
|
||||
use lib '.';
|
||||
use t::TestMLCache;
|
||||
|
||||
repeat_each(2);
|
||||
|
||||
plan tests => repeat_each() * blocks() * 3;
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: multiple instances with the same name have same lua-resty-lru instance
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache_1 = assert(mlcache.new("my_mlcache", "cache_shm"))
|
||||
local cache_2 = assert(mlcache.new("my_mlcache", "cache_shm"))
|
||||
|
||||
ngx.say("lua-resty-lru instances are the same: ",
|
||||
cache_1.lru == cache_2.lru)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
lua-resty-lru instances are the same: true
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 2: multiple instances with different names have different lua-resty-lru instances
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache_1 = assert(mlcache.new("my_mlcache_1", "cache_shm"))
|
||||
local cache_2 = assert(mlcache.new("my_mlcache_2", "cache_shm"))
|
||||
|
||||
ngx.say("lua-resty-lru instances are the same: ",
|
||||
cache_1.lru == cache_2.lru)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
lua-resty-lru instances are the same: false
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 3: garbage-collected instances also GC their lru instance
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
collectgarbage("collect")
|
||||
local cache_1 = assert(mlcache.new("my_mlcache", "cache_shm"))
|
||||
local cache_2 = assert(mlcache.new("my_mlcache", "cache_shm"))
|
||||
|
||||
-- cache something in cache_1's LRU
|
||||
|
||||
cache_1.lru:set("key", 123)
|
||||
|
||||
-- GC cache_1 (the LRU should survive because it is shared with cache_2)
|
||||
|
||||
cache_1 = nil
|
||||
collectgarbage("collect")
|
||||
|
||||
-- prove LRU survived
|
||||
|
||||
ngx.say((cache_2.lru:get("key")))
|
||||
|
||||
-- GC cache_2 (and the LRU this time, since no more references)
|
||||
|
||||
cache_2 = nil
|
||||
collectgarbage("collect")
|
||||
|
||||
-- re-create the caches and a new LRU
|
||||
|
||||
cache_1 = assert(mlcache.new("my_mlcache", "cache_shm"))
|
||||
cache_2 = assert(mlcache.new("my_mlcache", "cache_shm"))
|
||||
|
||||
-- this is a new LRU, it has nothing in it
|
||||
|
||||
ngx.say((cache_2.lru:get("key")))
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
123
|
||||
nil
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 4: multiple instances with different names get() of the same key are isolated
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
-- create 2 mlcache
|
||||
|
||||
local cache_1 = assert(mlcache.new("my_mlcache_1", "cache_shm"))
|
||||
local cache_2 = assert(mlcache.new("my_mlcache_2", "cache_shm"))
|
||||
|
||||
-- set a value in both mlcaches
|
||||
|
||||
local data_1 = assert(cache_1:get("my_key", nil, function() return "value A" end))
|
||||
local data_2 = assert(cache_2:get("my_key", nil, function() return "value B" end))
|
||||
|
||||
-- get values from LRU
|
||||
|
||||
local lru_1_value = cache_1.lru:get("my_key")
|
||||
local lru_2_value = cache_2.lru:get("my_key")
|
||||
|
||||
ngx.say("cache_1 lru has: ", lru_1_value)
|
||||
ngx.say("cache_2 lru has: ", lru_2_value)
|
||||
|
||||
-- delete values from LRU
|
||||
|
||||
cache_1.lru:delete("my_key")
|
||||
cache_2.lru:delete("my_key")
|
||||
|
||||
-- get values from shm
|
||||
|
||||
local shm_1_value = assert(cache_1:get("my_key", nil, function() end))
|
||||
local shm_2_value = assert(cache_2:get("my_key", nil, function() end))
|
||||
|
||||
ngx.say("cache_1 shm has: ", shm_1_value)
|
||||
ngx.say("cache_2 shm has: ", shm_2_value)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
cache_1 lru has: value A
|
||||
cache_2 lru has: value B
|
||||
cache_1 shm has: value A
|
||||
cache_2 shm has: value B
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 5: multiple instances with different names delete() of the same key are isolated
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
-- create 2 mlcache
|
||||
|
||||
local cache_1 = assert(mlcache.new("my_mlcache_1", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
}))
|
||||
local cache_2 = assert(mlcache.new("my_mlcache_2", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
}))
|
||||
|
||||
-- set 2 values in both mlcaches
|
||||
|
||||
local data_1 = assert(cache_1:get("my_key", nil, function() return "value A" end))
|
||||
local data_2 = assert(cache_2:get("my_key", nil, function() return "value B" end))
|
||||
|
||||
-- test if value is set from shm (safer to check due to the key)
|
||||
|
||||
local shm_v = ngx.shared.cache_shm:get(cache_1.name .. "my_key")
|
||||
ngx.say("cache_1 shm has a value: ", shm_v ~= nil)
|
||||
|
||||
-- delete value from mlcache 1
|
||||
|
||||
ngx.say("delete from cache_1")
|
||||
assert(cache_1:delete("my_key"))
|
||||
|
||||
-- ensure cache 1 key is deleted from LRU
|
||||
|
||||
local lru_v = cache_1.lru:get("my_key")
|
||||
ngx.say("cache_1 lru has: ", lru_v)
|
||||
|
||||
-- ensure cache 1 key is deleted from shm
|
||||
|
||||
local shm_v = ngx.shared.cache_shm:get(cache_1.name .. "my_key")
|
||||
ngx.say("cache_1 shm has: ", shm_v)
|
||||
|
||||
-- ensure cache 2 still has its value
|
||||
|
||||
local shm_v_2 = ngx.shared.cache_shm:get(cache_2.name .. "my_key")
|
||||
ngx.say("cache_2 shm has a value: ", shm_v_2 ~= nil)
|
||||
|
||||
local lru_v_2 = cache_2.lru:get("my_key")
|
||||
ngx.say("cache_2 lru has: ", lru_v_2)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
cache_1 shm has a value: true
|
||||
delete from cache_1
|
||||
cache_1 lru has: nil
|
||||
cache_1 shm has: nil
|
||||
cache_2 shm has a value: true
|
||||
cache_2 lru has: value B
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 6: multiple instances with different names peek() of the same key are isolated
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
-- must reset the shm so that when repeated, this tests doesn't
|
||||
-- return unpredictible TTLs (0.9xxxs)
|
||||
ngx.shared.cache_shm:flush_all()
|
||||
ngx.shared.cache_shm:flush_expired()
|
||||
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
-- create 2 mlcaches
|
||||
|
||||
local cache_1 = assert(mlcache.new("my_mlcache_1", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
}))
|
||||
local cache_2 = assert(mlcache.new("my_mlcache_2", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
}))
|
||||
|
||||
-- reset LRUs so repeated tests allow the below get() to set the
|
||||
-- value in the shm
|
||||
|
||||
cache_1.lru:delete("my_key")
|
||||
cache_2.lru:delete("my_key")
|
||||
|
||||
-- set a value in both mlcaches
|
||||
|
||||
local data_1 = assert(cache_1:get("my_key", { ttl = 1 }, function() return "value A" end))
|
||||
local data_2 = assert(cache_2:get("my_key", { ttl = 2 }, function() return "value B" end))
|
||||
|
||||
-- peek cache 1
|
||||
|
||||
local ttl, err, val = assert(cache_1:peek("my_key"))
|
||||
|
||||
ngx.say("cache_1 ttl: ", ttl)
|
||||
ngx.say("cache_1 value: ", val)
|
||||
|
||||
-- peek cache 2
|
||||
|
||||
local ttl, err, val = assert(cache_2:peek("my_key"))
|
||||
|
||||
ngx.say("cache_2 ttl: ", ttl)
|
||||
ngx.say("cache_2 value: ", val)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
cache_1 ttl: 1
|
||||
cache_1 value: value A
|
||||
cache_2 ttl: 2
|
||||
cache_2 value: value B
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 7: non-namespaced instances use different delete() broadcast channel
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
-- create 2 mlcaches
|
||||
|
||||
local cache_1 = assert(mlcache.new("my_mlcache_1", "cache_shm", {
|
||||
ipc = {
|
||||
register_listeners = function() end,
|
||||
broadcast = function(channel)
|
||||
ngx.say("cache_1 channel: ", channel)
|
||||
return true
|
||||
end,
|
||||
poll = function() end,
|
||||
}
|
||||
}))
|
||||
local cache_2 = assert(mlcache.new("my_mlcache_2", "cache_shm", {
|
||||
ipc = {
|
||||
register_listeners = function() end,
|
||||
broadcast = function(channel)
|
||||
ngx.say("cache_2 channel: ", channel)
|
||||
return true
|
||||
end,
|
||||
poll = function() end,
|
||||
}
|
||||
}))
|
||||
|
||||
assert(cache_1:delete("my_key"))
|
||||
assert(cache_2:delete("my_key"))
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
cache_1 channel: mlcache:invalidations:my_mlcache_1
|
||||
cache_2 channel: mlcache:invalidations:my_mlcache_2
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 8: non-namespaced instances use different purge() broadcast channel
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
-- create 2 mlcaches
|
||||
|
||||
local cache_1 = assert(mlcache.new("my_mlcache_1", "cache_shm", {
|
||||
ipc = {
|
||||
register_listeners = function() end,
|
||||
broadcast = function(channel)
|
||||
ngx.say("cache_1 channel: ", channel)
|
||||
return true
|
||||
end,
|
||||
poll = function() end,
|
||||
}
|
||||
}))
|
||||
local cache_2 = assert(mlcache.new("my_mlcache_2", "cache_shm", {
|
||||
ipc = {
|
||||
register_listeners = function() end,
|
||||
broadcast = function(channel)
|
||||
ngx.say("cache_2 channel: ", channel)
|
||||
return true
|
||||
end,
|
||||
poll = function() end,
|
||||
}
|
||||
}))
|
||||
|
||||
assert(cache_1:purge())
|
||||
assert(cache_2:purge())
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
cache_1 channel: mlcache:purge:my_mlcache_1
|
||||
cache_2 channel: mlcache:purge:my_mlcache_2
|
||||
--- no_error_log
|
||||
[error]
|
||||
275
src/deps/src/lua-resty-mlcache/t/10-ipc_shm.t
vendored
275
src/deps/src/lua-resty-mlcache/t/10-ipc_shm.t
vendored
|
|
@ -1,275 +0,0 @@
|
|||
# vim:set ts=4 sts=4 sw=4 et ft=:
|
||||
|
||||
use strict;
|
||||
use lib '.';
|
||||
use t::TestMLCache;
|
||||
|
||||
workers(2);
|
||||
#repeat_each(2);
|
||||
|
||||
plan tests => repeat_each() * blocks() * 4;
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: update() with ipc_shm catches up with invalidation events
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
debug = true -- allows same worker to receive its own published events
|
||||
}))
|
||||
|
||||
cache.ipc:subscribe(cache.events.invalidation.channel, function(data)
|
||||
ngx.log(ngx.NOTICE, "received event from invalidations: ", data)
|
||||
end)
|
||||
|
||||
assert(cache:delete("my_key"))
|
||||
assert(cache:update())
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- error_log
|
||||
received event from invalidations: my_key
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 2: update() with ipc_shm timeouts when waiting for too long
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
debug = true -- allows same worker to receive its own published events
|
||||
}))
|
||||
|
||||
cache.ipc:subscribe(cache.events.invalidation.channel, function(data)
|
||||
ngx.log(ngx.NOTICE, "received event from invalidations: ", data)
|
||||
end)
|
||||
|
||||
assert(cache:delete("my_key"))
|
||||
assert(cache:delete("my_other_key"))
|
||||
ngx.shared.ipc_shm:delete(2)
|
||||
|
||||
local ok, err = cache:update(0.1)
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
could not poll ipc events: timeout
|
||||
--- error_log
|
||||
received event from invalidations: my_key
|
||||
--- no_error_log
|
||||
[error]
|
||||
received event from invalidations: my_other
|
||||
|
||||
|
||||
|
||||
=== TEST 3: update() with ipc_shm JITs when no events to catch up
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm", {
|
||||
ipc_shm = "ipc_shm",
|
||||
debug = true -- allows same worker to receive its own published events
|
||||
}))
|
||||
for i = 1, 10e3 do
|
||||
assert(cache:update())
|
||||
end
|
||||
}
|
||||
}
|
||||
--- ignore_response_body
|
||||
--- error_log eval
|
||||
qr/\[TRACE\s+\d+ content_by_lua\(nginx\.conf:\d+\):7 loop\]/
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 4: set() with ipc_shm invalidates other workers' LRU cache
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local opts = {
|
||||
ipc_shm = "ipc_shm",
|
||||
debug = true -- allows same worker to receive its own published events
|
||||
}
|
||||
|
||||
local cache = assert(mlcache.new("namespace", "cache_shm", opts))
|
||||
local cache_clone = assert(mlcache.new("namespace", "cache_shm", opts))
|
||||
|
||||
do
|
||||
local lru_delete = cache.lru.delete
|
||||
cache.lru.delete = function(self, key)
|
||||
ngx.say("called lru:delete() with key: ", key)
|
||||
return lru_delete(self, key)
|
||||
end
|
||||
end
|
||||
|
||||
assert(cache:set("my_key", nil, nil))
|
||||
|
||||
ngx.say("calling update on cache")
|
||||
assert(cache:update())
|
||||
|
||||
ngx.say("calling update on cache_clone")
|
||||
assert(cache_clone:update())
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
calling update on cache
|
||||
called lru:delete() with key: my_key
|
||||
calling update on cache_clone
|
||||
called lru:delete() with key: my_key
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 5: delete() with ipc_shm invalidates other workers' LRU cache
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local opts = {
|
||||
ipc_shm = "ipc_shm",
|
||||
debug = true -- allows same worker to receive its own published events
|
||||
}
|
||||
|
||||
local cache = assert(mlcache.new("namespace", "cache_shm", opts))
|
||||
local cache_clone = assert(mlcache.new("namespace", "cache_shm", opts))
|
||||
|
||||
do
|
||||
local lru_delete = cache.lru.delete
|
||||
cache.lru.delete = function(self, key)
|
||||
ngx.say("called lru:delete() with key: ", key)
|
||||
return lru_delete(self, key)
|
||||
end
|
||||
end
|
||||
|
||||
assert(cache:delete("my_key"))
|
||||
|
||||
ngx.say("calling update on cache")
|
||||
assert(cache:update())
|
||||
|
||||
ngx.say("calling update on cache_clone")
|
||||
assert(cache_clone:update())
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
called lru:delete() with key: my_key
|
||||
calling update on cache
|
||||
called lru:delete() with key: my_key
|
||||
calling update on cache_clone
|
||||
called lru:delete() with key: my_key
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 6: purge() with mlcache_shm invalidates other workers' LRU cache (OpenResty < 1.13.6.2)
|
||||
--- skip_eval: 3: t::TestMLCache::skip_openresty('>=', '1.13.6.2')
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local opts = {
|
||||
ipc_shm = "ipc_shm",
|
||||
debug = true -- allows same worker to receive its own published events
|
||||
}
|
||||
|
||||
local cache = assert(mlcache.new("namespace", "cache_shm", opts))
|
||||
local cache_clone = assert(mlcache.new("namespace", "cache_shm", opts))
|
||||
|
||||
local lru = cache.lru
|
||||
local lru_clone = cache_clone.lru
|
||||
|
||||
assert(cache:purge())
|
||||
|
||||
-- cache.lru should be different now
|
||||
ngx.say("cache has new lru: ", cache.lru ~= lru)
|
||||
|
||||
ngx.say("cache_clone still has same lru: ", cache_clone.lru == lru_clone)
|
||||
|
||||
ngx.say("calling update on cache_clone")
|
||||
assert(cache_clone:update())
|
||||
|
||||
-- cache.lru should be different now
|
||||
ngx.say("cache_clone has new lru: ", cache_clone.lru ~= lru_clone)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
cache has new lru: true
|
||||
cache_clone still has same lru: true
|
||||
calling update on cache_clone
|
||||
cache_clone has new lru: true
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 7: purge() with mlcache_shm invalidates other workers' LRU cache (OpenResty >= 1.13.6.2)
|
||||
--- skip_eval: 3: t::TestMLCache::skip_openresty('<', '1.13.6.2')
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local opts = {
|
||||
ipc_shm = "ipc_shm",
|
||||
debug = true -- allows same worker to receive its own published events
|
||||
}
|
||||
|
||||
local cache = assert(mlcache.new("namespace", "cache_shm", opts))
|
||||
local cache_clone = assert(mlcache.new("namespace", "cache_shm", opts))
|
||||
|
||||
local lru = cache.lru
|
||||
|
||||
ngx.say("both instances use the same lru: ", cache.lru == cache_clone.lru)
|
||||
|
||||
do
|
||||
local lru_flush_all = lru.flush_all
|
||||
cache.lru.flush_all = function(self)
|
||||
ngx.say("called lru:flush_all()")
|
||||
return lru_flush_all(self)
|
||||
end
|
||||
end
|
||||
|
||||
assert(cache:purge())
|
||||
|
||||
ngx.say("calling update on cache_clone")
|
||||
assert(cache_clone:update())
|
||||
|
||||
ngx.say("both instances use the same lru: ", cache.lru == cache_clone.lru)
|
||||
ngx.say("lru didn't change after purge: ", cache.lru == lru)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
both instances use the same lru: true
|
||||
called lru:flush_all()
|
||||
calling update on cache_clone
|
||||
called lru:flush_all()
|
||||
both instances use the same lru: true
|
||||
lru didn't change after purge: true
|
||||
--- no_error_log
|
||||
[error]
|
||||
[crit]
|
||||
80
src/deps/src/lua-resty-mlcache/t/11-locks_shm.t
vendored
80
src/deps/src/lua-resty-mlcache/t/11-locks_shm.t
vendored
|
|
@ -1,80 +0,0 @@
|
|||
# vim:set ts=4 sts=4 sw=4 et ft=:
|
||||
|
||||
use strict;
|
||||
use lib '.';
|
||||
use t::TestMLCache;
|
||||
|
||||
plan tests => repeat_each() * blocks() * 3;
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: new() validates opts.shm_locks
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local ok, err = pcall(mlcache.new, "name", "cache_shm", {
|
||||
shm_locks = false,
|
||||
})
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
opts.shm_locks must be a string
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 2: new() ensures opts.shm_locks exists
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local ok, err = mlcache.new("name", "cache_shm", {
|
||||
shm_locks = "foo",
|
||||
})
|
||||
if not ok then
|
||||
ngx.say(err)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
no such lua_shared_dict for opts.shm_locks: foo
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 3: get() stores resty-locks in opts.shm_locks if specified
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local cache = assert(mlcache.new("name", "cache_shm", {
|
||||
shm_locks = "locks_shm",
|
||||
}))
|
||||
|
||||
local function cb()
|
||||
local keys = ngx.shared.locks_shm:get_keys()
|
||||
for i, key in ipairs(keys) do
|
||||
ngx.say(i, ": ", key)
|
||||
end
|
||||
|
||||
return 123
|
||||
end
|
||||
|
||||
cache:get("key", nil, cb)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
1: lua-resty-mlcache:lock:namekey
|
||||
--- no_error_log
|
||||
[error]
|
||||
1009
src/deps/src/lua-resty-mlcache/t/12-resurrect-stale.t
vendored
1009
src/deps/src/lua-resty-mlcache/t/12-resurrect-stale.t
vendored
File diff suppressed because it is too large
Load diff
1591
src/deps/src/lua-resty-mlcache/t/13-get_bulk.t
vendored
1591
src/deps/src/lua-resty-mlcache/t/13-get_bulk.t
vendored
File diff suppressed because it is too large
Load diff
178
src/deps/src/lua-resty-mlcache/t/14-bulk-and-res.t
vendored
178
src/deps/src/lua-resty-mlcache/t/14-bulk-and-res.t
vendored
|
|
@ -1,178 +0,0 @@
|
|||
# vim:set ts=4 sts=4 sw=4 et ft=:
|
||||
|
||||
use strict;
|
||||
use lib '.';
|
||||
use t::TestMLCache;
|
||||
|
||||
workers(2);
|
||||
#repeat_each(2);
|
||||
|
||||
plan tests => repeat_each() * blocks() * 3;
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: new_bulk() creates a bulk
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local bulk = mlcache.new_bulk()
|
||||
|
||||
ngx.say("type: ", type(bulk))
|
||||
ngx.say("size: ", #bulk)
|
||||
ngx.say("bulk.n: ", bulk.n)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
type: table
|
||||
size: 0
|
||||
bulk.n: 0
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 2: new_bulk() creates a bulk with narr in arg #1
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local bulk = mlcache.new_bulk(3)
|
||||
|
||||
ngx.say("type: ", type(bulk))
|
||||
ngx.say("size: ", #bulk)
|
||||
ngx.say("bulk.n: ", bulk.n)
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
type: table
|
||||
size: 0
|
||||
bulk.n: 0
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 3: bulk:add() adds bulk operations
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local function cb() end
|
||||
|
||||
local bulk = mlcache.new_bulk(3)
|
||||
|
||||
for i = 1, 3 do
|
||||
bulk:add("key_" .. i, nil, cb, i)
|
||||
end
|
||||
|
||||
for i = 1, 3*4, 4 do
|
||||
ngx.say(tostring(bulk[i]), " ",
|
||||
tostring(bulk[i + 1]), " ",
|
||||
tostring(bulk[i + 2]), " ",
|
||||
tostring(bulk[i + 3]))
|
||||
end
|
||||
|
||||
ngx.say("bulk.n: ", bulk.n)
|
||||
}
|
||||
}
|
||||
--- response_body_like
|
||||
key_1 nil function: 0x[0-9a-fA-F]+ 1
|
||||
key_2 nil function: 0x[0-9a-fA-F]+ 2
|
||||
key_3 nil function: 0x[0-9a-fA-F]+ 3
|
||||
bulk\.n: 3
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 4: bulk:add() can be given to get_bulk()
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm"))
|
||||
|
||||
local function cb(i) return i end
|
||||
|
||||
local bulk = mlcache.new_bulk(3)
|
||||
|
||||
for i = 1, 3 do
|
||||
bulk:add("key_" .. i, nil, cb, i)
|
||||
end
|
||||
|
||||
local res, err = cache:get_bulk(bulk)
|
||||
if not res then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
for i = 1, res.n, 3 do
|
||||
ngx.say(tostring(res[i]), " ",
|
||||
tostring(res[i + 1]), " ",
|
||||
tostring(res[i + 2]))
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
1 nil 3
|
||||
2 nil 3
|
||||
3 nil 3
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 5: each_bulk_res() iterates over get_bulk() results
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
local cache = assert(mlcache.new("my_mlcache", "cache_shm"))
|
||||
|
||||
local res, err = cache:get_bulk {
|
||||
"key_a", nil, function() return 1 end, nil,
|
||||
"key_b", nil, function() return 2 end, nil,
|
||||
"key_c", nil, function() return 3 end, nil,
|
||||
n = 3,
|
||||
}
|
||||
if not res then
|
||||
ngx.log(ngx.ERR, err)
|
||||
return
|
||||
end
|
||||
|
||||
for i, data, err, hit_lvl in mlcache.each_bulk_res(res) do
|
||||
ngx.say(i, " ", data, " ", err, " ", hit_lvl)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
1 1 nil 3
|
||||
2 2 nil 3
|
||||
3 3 nil 3
|
||||
--- no_error_log
|
||||
[error]
|
||||
|
||||
|
||||
|
||||
=== TEST 6: each_bulk_res() throws an error on unrocognized res
|
||||
--- config
|
||||
location /t {
|
||||
content_by_lua_block {
|
||||
local mlcache = require "resty.mlcache"
|
||||
|
||||
local pok, perr = pcall(mlcache.each_bulk_res, {})
|
||||
if not pok then
|
||||
ngx.say(perr)
|
||||
end
|
||||
}
|
||||
}
|
||||
--- response_body
|
||||
res must have res.n field; is this a get_bulk() result?
|
||||
--- no_error_log
|
||||
[error]
|
||||
103
src/deps/src/lua-resty-mlcache/t/TestMLCache.pm
vendored
103
src/deps/src/lua-resty-mlcache/t/TestMLCache.pm
vendored
|
|
@ -1,103 +0,0 @@
|
|||
package t::TestMLCache;
|
||||
|
||||
use strict;
|
||||
use Test::Nginx::Socket::Lua -Base;
|
||||
use Cwd qw(cwd);
|
||||
|
||||
our $pwd = cwd();
|
||||
|
||||
our @EXPORT = qw(
|
||||
$pwd
|
||||
skip_openresty
|
||||
);
|
||||
|
||||
my $PackagePath = qq{lua_package_path "$pwd/lib/?.lua;;";};
|
||||
|
||||
my $HttpConfig = qq{
|
||||
lua_shared_dict cache_shm 1m;
|
||||
lua_shared_dict cache_shm_miss 1m;
|
||||
lua_shared_dict locks_shm 1m;
|
||||
lua_shared_dict ipc_shm 1m;
|
||||
|
||||
init_by_lua_block {
|
||||
-- local verbose = true
|
||||
local verbose = false
|
||||
local outfile = "$Test::Nginx::Util::ErrLogFile"
|
||||
-- local outfile = "/tmp/v.log"
|
||||
if verbose then
|
||||
local dump = require "jit.dump"
|
||||
dump.on(nil, outfile)
|
||||
else
|
||||
local v = require "jit.v"
|
||||
v.on(outfile)
|
||||
end
|
||||
|
||||
require "resty.core"
|
||||
-- jit.opt.start("hotloop=1")
|
||||
-- jit.opt.start("loopunroll=1000000")
|
||||
-- jit.off()
|
||||
}
|
||||
};
|
||||
|
||||
add_block_preprocessor(sub {
|
||||
my $block = shift;
|
||||
|
||||
if (!defined $block->request) {
|
||||
$block->set_value("request", "GET /t");
|
||||
}
|
||||
|
||||
my $http_config = $block->http_config || '';
|
||||
$http_config .= $PackagePath;
|
||||
|
||||
if ($http_config !~ m/init_by_lua_block/) {
|
||||
$http_config .= $HttpConfig;
|
||||
}
|
||||
|
||||
$block->set_value("http_config", $http_config);
|
||||
});
|
||||
|
||||
sub get_openresty_canon_version (@) {
|
||||
sprintf "%d.%03d%03d%03d", $_[0], $_[1], $_[2], $_[3];
|
||||
}
|
||||
|
||||
sub get_openresty_version () {
|
||||
my $NginxBinary = $ENV{TEST_NGINX_BINARY} || 'nginx';
|
||||
my $out = `$NginxBinary -V 2>&1`;
|
||||
|
||||
if (!defined $out || $? != 0) {
|
||||
bail_out("Failed to get the version of the OpenResty in PATH");
|
||||
die;
|
||||
}
|
||||
|
||||
if ($out =~ m{openresty[^/]*/(\d+)\.(\d+)\.(\d+)\.(\d+)}s) {
|
||||
return get_openresty_canon_version($1, $2, $3, $4);
|
||||
}
|
||||
|
||||
if ($out =~ m{nginx[^/]*/(\d+)\.(\d+)\.(\d+)}s) {
|
||||
return;
|
||||
}
|
||||
|
||||
bail_out("Failed to parse the output of \"nginx -V\": $out\n");
|
||||
die;
|
||||
}
|
||||
|
||||
sub skip_openresty ($$) {
|
||||
my ($op, $ver) = @_;
|
||||
my $OpenrestyVersion = get_openresty_version();
|
||||
|
||||
if ($ver =~ m{(\d+)\.(\d+)\.(\d+)\.(\d+)}s) {
|
||||
$ver = get_openresty_canon_version($1, $2, $3, $4);
|
||||
|
||||
} else {
|
||||
bail_out("Invalid skip_openresty() arg: $ver");
|
||||
die;
|
||||
}
|
||||
|
||||
if (defined $OpenrestyVersion and eval "$OpenrestyVersion $op $ver") {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
no_long_string();
|
||||
|
||||
1;
|
||||
Loading…
Reference in a new issue