# vim:set ft= ts=4 sw=4 et fdm=marker: use Test::Nginx::Socket::Lua::Stream; #worker_connections(1014); #master_on(); #workers(2); log_level('warn'); repeat_each(2); plan tests => repeat_each() * (blocks() * 2 + 1); #no_diff(); #no_long_string(); run_tests(); __DATA__ === TEST 1: sanity --- stream_server_config content_by_lua_block { m = ngx.re.match("hello, 1234", "([0-9]+)", "o") if m then ngx.say(m[0]) else ngx.say("not matched!") end } --- stream_response 1234 === TEST 2: escaping sequences --- stream_server_config content_by_lua_block { m = ngx.re.match("hello, 1234", "(\\d+)", "o") if m then ngx.say(m[0]) else ngx.say("not matched!") end } --- stream_response 1234 === TEST 3: single capture --- stream_server_config content_by_lua_block { m = ngx.re.match("hello, 1234", "([0-9]{2})[0-9]+", "o") if m then ngx.say(m[0]) ngx.say(m[1]) else ngx.say("not matched!") end } --- stream_response 1234 12 === TEST 4: multiple captures --- stream_server_config content_by_lua_block { m = ngx.re.match("hello, 1234", "([a-z]+).*?([0-9]{2})[0-9]+", "o") if m then ngx.say(m[0]) ngx.say(m[1]) ngx.say(m[2]) else ngx.say("not matched!") end } --- stream_response hello, 1234 hello 12 === TEST 5: not matched --- stream_server_config content_by_lua_block { m = ngx.re.match("hello, 1234", "foo", "o") if m then ngx.say(m[0]) else ngx.say("not matched: ", m) end } --- stream_response not matched: nil === TEST 6: case sensitive by default --- stream_server_config content_by_lua_block { m = ngx.re.match("hello, 1234", "HELLO", "o") if m then ngx.say(m[0]) else ngx.say("not matched: ", m) end } --- stream_response not matched: nil === TEST 7: case sensitive by default --- stream_server_config content_by_lua_block { m = ngx.re.match("hello, 1234", "HELLO", "oi") if m then ngx.say(m[0]) else ngx.say("not matched: ", m) end } --- stream_response hello === TEST 8: UTF-8 mode --- stream_server_config content_by_lua_block { local rc, m = pcall(ngx.re.match, "hello章亦春", "HELLO.{2}", "iou") if not rc then ngx.say("error: ", m) return end if m then ngx.say(m[0]) else ngx.say("not matched: ", m) end } --- stream_response_like chop this version of PCRE is not compiled with PCRE_UTF8 support|^hello章亦$ === TEST 9: multi-line mode (^ at line head) --- stream_server_config content_by_lua_block { m = ngx.re.match("hello\nworld", "^world", "mo") if m then ngx.say(m[0]) else ngx.say("not matched: ", m) end } --- stream_response world === TEST 10: multi-line mode (. does not match \n) --- stream_server_config content_by_lua_block { m = ngx.re.match("hello\nworld", ".*", "om") if m then ngx.say(m[0]) else ngx.say("not matched: ", m) end } --- stream_response hello === TEST 11: single-line mode (^ as normal) --- stream_server_config content_by_lua_block { m = ngx.re.match("hello\nworld", "^world", "so") if m then ngx.say(m[0]) else ngx.say("not matched: ", m) end } --- stream_response not matched: nil === TEST 12: single-line mode (dot all) --- stream_server_config content_by_lua_block { m = ngx.re.match("hello\nworld", ".*", "os") if m then ngx.say(m[0]) else ngx.say("not matched: ", m) end } --- stream_response hello world === TEST 13: extended mode (ignore whitespaces) --- stream_server_config content_by_lua_block { m = ngx.re.match("hello\nworld", [[\w \w]], "xo") if m then ngx.say(m[0]) else ngx.say("not matched: ", m) end } --- stream_response he === TEST 14: bad pattern --- stream_server_config content_by_lua_block { local m, err = ngx.re.match("hello\\nworld", "(abc", "o") if m then ngx.say(m[0]) else if err then ngx.say("error: ", err) else ngx.say("not matched: ", m) end end } --- stream_response eval $Test::Nginx::Util::PcreVersion == 2 ? "error: pcre2_compile() failed: missing closing parenthesis in \"(abc\"\n" : "error: pcre_compile() failed: missing ) in \"(abc\"\n" --- no_error_log [error] === TEST 15: bad option --- stream_server_config content_by_lua_block { rc, m = pcall(ngx.re.match, "hello\\nworld", ".*", "Ho") if rc then if m then ngx.say(m[0]) else ngx.say("not matched: ", m) end else ngx.say("error: ", m) end } --- stream_response_like chop ^error: .*?unknown flag "H" === TEST 16: extended mode (ignore whitespaces) --- stream_server_config content_by_lua_block { m = ngx.re.match("hello, world", "(world)|(hello)", "xo") if m then ngx.say(m[0]) ngx.say(m[1]) ngx.say(m[2]) else ngx.say("not matched: ", m) end } --- stream_response hello false hello === TEST 17: optional trailing captures --- stream_server_config content_by_lua_block { m = ngx.re.match("hello, 1234", "([0-9]+)(h?)", "o") if m then ngx.say(m[0]) ngx.say(m[1]) ngx.say(m[2]) else ngx.say("not matched!") end } --- stream_response eval "1234 1234 " === TEST 18: anchored match (failed) --- stream_server_config content_by_lua_block { m = ngx.re.match("hello, 1234", "([0-9]+)", "oa") if m then ngx.say(m[0]) else ngx.say("not matched!") end } --- stream_response not matched! === TEST 19: anchored match (succeeded) --- stream_server_config content_by_lua_block { m = ngx.re.match("1234, hello", "([0-9]+)", "ao") if m then ngx.say(m[0]) else ngx.say("not matched!") end } --- stream_response 1234 === TEST 20: match with ctx but no pos --- stream_server_config content_by_lua_block { local ctx = {} m = ngx.re.match("1234, hello", "([0-9]+)", "o", ctx) if m then ngx.say(m[0]) ngx.say(ctx.pos) else ngx.say("not matched!") ngx.say(ctx.pos) end } --- stream_response 1234 5 === TEST 21: match with ctx and a pos --- stream_server_config content_by_lua_block { local ctx = { pos = 3 } m = ngx.re.match("1234, hello", "([0-9]+)", "o", ctx) if m then ngx.say(m[0]) ngx.say(ctx.pos) else ngx.say("not matched!") ngx.say(ctx.pos) end } --- stream_response 34 5 === TEST 22: match (look-behind assertion) --- stream_server_config content_by_lua_block { local ctx = {} local m = ngx.re.match("{foobarbaz}", "(?<=foo)bar|(?<=bar)baz", "o", ctx) ngx.say(m and m[0]) m = ngx.re.match("{foobarbaz}", "(?<=foo)bar|(?<=bar)baz", "o", ctx) ngx.say(m and m[0]) } --- stream_response bar baz === TEST 23: match (with regex cache) --- stream_server_config content_by_lua_block { local m = ngx.re.match("hello, 1234", "([A-Z]+)", "io") ngx.say(m and m[0]) m = ngx.re.match("1234, okay", "([A-Z]+)", "io") ngx.say(m and m[0]) m = ngx.re.match("hello, 1234", "([A-Z]+)", "o") ngx.say(m and m[0]) } --- stream_response hello okay nil === TEST 24: match (with regex cache and ctx) --- stream_server_config content_by_lua_block { local ctx = {} local m = ngx.re.match("hello, 1234", "([A-Z]+)", "io", ctx) ngx.say(m and m[0]) ngx.say(ctx.pos) m = ngx.re.match("1234, okay", "([A-Z]+)", "io", ctx) ngx.say(m and m[0]) ngx.say(ctx.pos) ctx.pos = 1 m = ngx.re.match("hi, 1234", "([A-Z]+)", "o", ctx) ngx.say(m and m[0]) ngx.say(ctx.pos) } --- stream_response hello 6 okay 11 nil 1 === TEST 25: exceeding regex cache max entries --- stream_config lua_regex_cache_max_entries 2; --- stream_server_config content_by_lua_block { local m = ngx.re.match("hello, 1234", "([0-9]+)", "o") ngx.say(m and m[0]) m = ngx.re.match("howdy, 567", "([0-9]+)", "oi") ngx.say(m and m[0]) m = ngx.re.match("hiya, 98", "([0-9]+)", "ox") ngx.say(m and m[0]) } --- stream_response 1234 567 98 === TEST 26: disable regex cache completely --- stream_config lua_regex_cache_max_entries 0; --- stream_server_config content_by_lua_block { local m = ngx.re.match("hello, 1234", "([0-9]+)", "o") ngx.say(m and m[0]) m = ngx.re.match("howdy, 567", "([0-9]+)", "oi") ngx.say(m and m[0]) m = ngx.re.match("hiya, 98", "([0-9]+)", "ox") ngx.say(m and m[0]) } --- stream_response 1234 567 98 === TEST 27: named subpatterns w/ extraction --- stream_server_config content_by_lua_block { local m = ngx.re.match("hello, 1234", "(?[a-z]+), [0-9]+", "o") if m then ngx.say(m[0]) ngx.say(m[1]) ngx.say(m.first) ngx.say(m.second) else ngx.say("not matched!") end } --- stream_response hello, 1234 hello hello nil === TEST 28: duplicate named subpatterns w/ extraction --- stream_server_config content_by_lua_block { local m = ngx.re.match("hello, 1234", "(?[a-z]+), (?[0-9]+)", "Do") if m then ngx.say(m[0]) ngx.say(m[1]) ngx.say(m[2]) ngx.say(table.concat(m.first,"-")) else ngx.say("not matched!") end } --- stream_response hello, 1234 hello 1234 hello-1234 === TEST 29: named captures are empty strings --- stream_server_config content_by_lua_block { local m = ngx.re.match("1234", "(?[a-z]*)([0-9]+)", "o") if m then ngx.say(m[0]) ngx.say(m.first) ngx.say(m[1]) ngx.say(m[2]) else ngx.say("not matched!") end } --- stream_response 1234 1234 === TEST 30: named captures are nil --- stream_server_config content_by_lua_block { local m = ngx.re.match("hello, world", "(world)|(hello)|(?howdy)", "o") if m then ngx.say(m[0]) ngx.say(m[1]) ngx.say(m[2]) ngx.say(m[3]) ngx.say(m["named"]) else ngx.say("not matched!") end } --- stream_response hello false hello false false