# vim:set ft= ts=4 sw=4 et fdm=marker: use lib '.'; use t::TestCore; use Cwd qw(cwd); #worker_connections(1014); #master_process_enabled(1); log_level('debug'); #repeat_each(120); repeat_each(2); plan tests => repeat_each() * (blocks() * 3 + 13); #no_diff(); #no_long_string(); my $pwd = cwd(); add_block_preprocessor(sub { my $block = shift; my $http_config = $block->http_config || ''; $http_config .= <<_EOC_; lua_package_path "$pwd/lib/?.lua;\$prefix/html/?.lua;../lua-resty-lrucache/lib/?.lua;;"; init_by_lua_block { local verbose = false if verbose then local dump = require "jit.dump" dump.on(nil, "$Test::Nginx::Util::ErrLogFile") else local v = require "jit.v" v.on("$Test::Nginx::Util::ErrLogFile") end require "resty.core" -- jit.off() } _EOC_ $block->set_value("http_config", $http_config); }); check_accum_error_log(); $ENV{TEST_NGINX_HTML_DIR} ||= html_dir(); run_tests(); __DATA__ === TEST 1: get ngx.ctx --- config location = /t { content_by_lua_block { for i = 1, 100 do ngx.ctx.foo = i end ngx.say("ctx.foo = ", ngx.ctx.foo) } } --- request GET /t --- response_body ctx.foo = 100 --- no_error_log [error] -- NYI: bad argument --- error_log eval qr/\[TRACE\s+\d+\s+content_by_lua\(nginx\.conf:\d+\):2 loop\]/ === TEST 2: set ngx.ctx --- config location = /t { content_by_lua_block { for i = 1, 100 do ngx.ctx = {foo = i} end ngx.say("ctx.foo = ", ngx.ctx.foo) } } --- request GET /t --- response_body ctx.foo = 100 --- no_error_log [error] -- NYI: bad argument --- error_log eval qr/\[TRACE\s+\d+\s+content_by_lua\(nginx\.conf:\d+\):2 loop\]/ === TEST 3: ngx.ctx in ssl_certificate_by_lua --- http_config server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; ssl_certificate_by_lua_block { ngx.ctx.answer = 42 ngx.log(ngx.WARN, "ngx.ctx.answer = ", ngx.ctx.answer) ngx.ctx.count = 0 } ssl_certificate ../../cert/test.crt; ssl_certificate_key ../../cert/test.key; server_tokens off; location /foo { content_by_lua_block { ngx.say(ngx.ctx.answer) ngx.ctx.count = ngx.ctx.count + 1 ngx.say(ngx.ctx.count) } } } --- config lua_ssl_trusted_certificate ../../cert/test.crt; location /t { content_by_lua_block { do local sock = ngx.socket.tcp() sock:settimeout(3000) local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") if not ok then ngx.say("failed to connect: ", err) return end local sess, err = sock:sslhandshake(nil, "test.com", true) if not sess then ngx.say("failed to do SSL handshake: ", err) return end for i = 1, 2 do local req = "GET /foo HTTP/1.1\r\nHost: test.com\r\n\r\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) return end local body_seen = false while true do local line, err = sock:receive() if not line then break end if body_seen then if line == "0" then assert(sock:receive()) break end local line, err = sock:receive(line) ngx.print("received: ", line) assert(sock:receive()) elseif line == "" then body_seen = true end end end sock:close() end -- do -- collectgarbage() } } --- request GET /t --- response_body received: 42 received: 1 received: 42 received: 1 --- error_log ngx.ctx.answer = 42 --- grep_error_log eval qr/lua release ngx.ctx at ref \d+/ --- grep_error_log_out eval ["lua release ngx.ctx at ref 2 lua release ngx.ctx at ref 2 lua release ngx.ctx at ref 1 ", "lua release ngx.ctx at ref 2 lua release ngx.ctx at ref 2 lua release ngx.ctx at ref 1 lua release ngx.ctx at ref 2 lua release ngx.ctx at ref 2 lua release ngx.ctx at ref 1 "] --- no_error_log [error] === TEST 4: ngx.ctx in ssl_certificate_by_lua (share objects) --- http_config server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; ssl_certificate_by_lua_block { ngx.ctx.req = { count = 0 } } ssl_certificate ../../cert/test.crt; ssl_certificate_key ../../cert/test.key; server_tokens off; location /foo { content_by_lua_block { ngx.ctx.req.count = ngx.ctx.req.count + 1 ngx.say(ngx.ctx.req.count) } } } --- config lua_ssl_trusted_certificate ../../cert/test.crt; location /t { content_by_lua_block { do local sock = ngx.socket.tcp() sock:settimeout(3000) local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") if not ok then ngx.say("failed to connect: ", err) return end local sess, err = sock:sslhandshake(nil, "test.com", true) if not sess then ngx.say("failed to do SSL handshake: ", err) return end for i = 1, 2 do local req = "GET /foo HTTP/1.1\r\nHost: test.com\r\n\r\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) return end local body_seen = false while true do local line, err = sock:receive() if not line then break end if body_seen then if line == "0" then assert(sock:receive()) break end local line, err = sock:receive(line) ngx.print("received: ", line) assert(sock:receive()) elseif line == "" then body_seen = true end end end sock:close() end -- do -- collectgarbage() } } --- request GET /t --- response_body received: 1 received: 2 --- no_error_log [error] === TEST 5: ngx.ctx in ssl_certificate_by_lua (release ctx when client aborted) --- http_config server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; ssl_certificate_by_lua_block { local ssl = require "ngx.ssl" ssl.clear_certs() ngx.ctx.answer = 42 } ssl_certificate ../../cert/test.crt; ssl_certificate_key ../../cert/test.key; server_tokens off; location /foo { return 200 "ok"; } } --- config lua_ssl_trusted_certificate ../../cert/test.crt; location /t { content_by_lua_block { do local sock = ngx.socket.tcp() sock:settimeout(3000) local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") if not ok then ngx.say("failed to connect: ", err) return end local sess, err = sock:sslhandshake(nil, "test.com", true) if not sess then ngx.say("failed to do SSL handshake: ", err) end sock:close() end -- do -- collectgarbage() } } --- request GET /t --- response_body failed to do SSL handshake: handshake failed --- grep_error_log eval qr/lua release ngx.ctx at ref \d+/ --- grep_error_log_out eval ["lua release ngx.ctx at ref 1 ", "lua release ngx.ctx at ref 1 lua release ngx.ctx at ref 1 "] === TEST 6: ngx.ctx in ssl_session_store_by_lua --- http_config ssl_session_store_by_lua_block { ngx.ctx.answer = 42 ngx.log(ngx.WARN, "ngx.ctx.answer = ", ngx.ctx.answer) ngx.ctx.count = 0 } server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; ssl_session_tickets off; ssl_certificate ../../cert/test.crt; ssl_certificate_key ../../cert/test.key; server_tokens off; location /foo { content_by_lua_block { ngx.say(ngx.ctx.answer) ngx.ctx.count = ngx.ctx.count + 1 ngx.say(ngx.ctx.count) } } } --- config lua_ssl_trusted_certificate ../../cert/test.crt; lua_ssl_protocols TLSv1.2; location /t { content_by_lua_block { do local sock = ngx.socket.tcp() sock:settimeout(3000) local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") if not ok then ngx.say("failed to connect: ", err) return end local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) if not sess then ngx.say("failed to do SSL handshake: ", err) return end for i = 1, 2 do local req = "GET /foo HTTP/1.1\r\nHost: test.com\r\n\r\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) return end local body_seen = false while true do local line, err = sock:receive() if not line then break end if body_seen then if line == "0" then assert(sock:receive()) break end local line, err = sock:receive(line) ngx.print("received: ", line) assert(sock:receive()) elseif line == "" then body_seen = true end end end package.loaded.session = sess sock:close() end -- do } } --- request GET /t --- response_body received: 42 received: 1 received: 42 received: 1 --- error_log ngx.ctx.answer = 42 --- grep_error_log eval qr/lua release ngx.ctx at ref \d+/ --- grep_error_log_out eval ["lua release ngx.ctx at ref 2 lua release ngx.ctx at ref 2 lua release ngx.ctx at ref 1 ", "lua release ngx.ctx at ref 2 lua release ngx.ctx at ref 2 lua release ngx.ctx at ref 1 lua release ngx.ctx at ref 2 lua release ngx.ctx at ref 2 lua release ngx.ctx at ref 1 "] --- no_error_log [error] === TEST 7: ngx.ctx in ssl_session_store_by_lua (release ctx when client aborted) --- http_config ssl_session_store_by_lua_block { ngx.ctx.answer = 42 } server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; ssl_session_tickets off; ssl_certificate ../../cert/test.crt; ssl_certificate_key ../../cert/test.key; server_tokens off; location /foo { return 200 "ok"; } } --- config lua_ssl_trusted_certificate ../../cert/test.crt; lua_ssl_protocols TLSv1.2; location /t { content_by_lua_block { do local sock = ngx.socket.tcp() sock:settimeout(3000) local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") if not ok then ngx.say("failed to connect: ", err) return end local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) if not sess then ngx.say("failed to do SSL handshake: ", err) return end ngx.say("closed") sock:close() end -- do } } --- request GET /t --- response_body closed --- grep_error_log eval qr/lua release ngx.ctx at ref \d+/ --- grep_error_log_out eval ["lua release ngx.ctx at ref 1 ", "lua release ngx.ctx at ref 1 lua release ngx.ctx at ref 1 "] --- no_error_log [error] === TEST 8: ngx.ctx in ssl_session_fetch_by_lua --- http_config ssl_session_fetch_by_lua_block { ngx.ctx.answer = 42 ngx.ctx.count = 0 } server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; ssl_session_tickets off; ssl_certificate ../../cert/test.crt; ssl_certificate_key ../../cert/test.key; ssl_protocols TLSv1.2; server_tokens off; location /foo { content_by_lua_block { if package.loaded.session then ngx.say(ngx.ctx.answer) ngx.ctx.count = ngx.ctx.count + 1 ngx.say(ngx.ctx.count) end } } } --- config lua_ssl_trusted_certificate ../../cert/test.crt; location /t { content_by_lua_block { do local sock = ngx.socket.tcp() sock:settimeout(3000) local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") if not ok then ngx.say("failed to connect: ", err) return end local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) if not sess then ngx.say("failed to do SSL handshake: ", err) return end for i = 1, 2 do local req = "GET /foo HTTP/1.1\r\nHost: test.com\r\n\r\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) return end local body_seen = false while true do local line, err = sock:receive() if not line then break end if body_seen then if line == "0" then assert(sock:receive()) break end local line, err = sock:receive(line) ngx.log(ngx.WARN, "received: ", line) assert(sock:receive()) elseif line == "" then body_seen = true end end end package.loaded.session = sess sock:close() end -- do } } --- request GET /t --- grep_error_log eval qr/(received: \w+|lua release ngx.ctx at ref \d+)/ --- grep_error_log_out eval ["lua release ngx.ctx at ref 1 ", "lua release ngx.ctx at ref 1 lua release ngx.ctx at ref 2 received: 42 received: 1 lua release ngx.ctx at ref 2 received: 42 received: 1 lua release ngx.ctx at ref 1 "] --- no_error_log [error] === TEST 9: ngx.ctx in ssl_session_fetch_by_lua (release ctx when client aborted) --- http_config ssl_session_fetch_by_lua_block { ngx.ctx.answer = 42 } server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; ssl_session_tickets off; ssl_certificate ../../cert/test.crt; ssl_certificate_key ../../cert/test.key; ssl_protocols TLSv1.2; server_tokens off; location /foo { return 200 "ok"; } } --- config lua_ssl_trusted_certificate ../../cert/test.crt; location /t { content_by_lua_block { do local sock = ngx.socket.tcp() sock:settimeout(3000) local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") if not ok then ngx.say("failed to connect: ", err) return end local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) if not sess then ngx.say("failed to do SSL handshake: ", err) return end package.loaded.session = sess ngx.say("closed") sock:close() end -- do } } --- request GET /t --- response_body closed --- grep_error_log eval qr/lua release ngx.ctx at ref \d+/ --- grep_error_log_out eval ["lua release ngx.ctx at ref 1 ", "lua release ngx.ctx at ref 1 lua release ngx.ctx at ref 1 "] --- no_error_log [error] === TEST 10: ngx.ctx in ssl* and other phases --- http_config ssl_session_store_by_lua_block { ngx.ctx.count = ngx.ctx.count and (ngx.ctx.count + 1) or 1 } ssl_session_fetch_by_lua_block { ngx.ctx.count = ngx.ctx.count and (ngx.ctx.count + 10) or 10 } server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; ssl_session_tickets off; ssl_certificate ../../cert/test.crt; ssl_certificate_key ../../cert/test.key; ssl_protocols TLSv1.2; ssl_certificate_by_lua_block { ngx.ctx.count = ngx.ctx.count and (ngx.ctx.count + 100) or 100 } server_tokens off; location /foo { content_by_lua_block { ngx.ctx.count = ngx.ctx.count + 1 ngx.say(ngx.ctx.count) } } } --- config lua_ssl_trusted_certificate ../../cert/test.crt; location /t { content_by_lua_block { do local sock = ngx.socket.tcp() sock:settimeout(3000) local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") if not ok then ngx.say("failed to connect: ", err) return end local sess, err = sock:sslhandshake(package.loaded.session, "test.com", true) if not sess then ngx.say("failed to do SSL handshake: ", err) return end for i = 1, 2 do local req = "GET /foo HTTP/1.1\r\nHost: test.com\r\n\r\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) return end local body_seen = false while true do local line, err = sock:receive() if not line then break end if body_seen then if line == "0" then assert(sock:receive()) break end local line, err = sock:receive(line) ngx.log(ngx.WARN, "received: ", line) assert(sock:receive()) elseif line == "" then body_seen = true end end end package.loaded.session = sess sock:close() end -- do } } --- request GET /t --- grep_error_log eval qr/(received: \w+|lua release ngx.ctx at ref \d+)/ --- grep_error_log_out eval ["lua release ngx.ctx at ref 2 received: 112 lua release ngx.ctx at ref 2 received: 112 lua release ngx.ctx at ref 1 ", "lua release ngx.ctx at ref 2 received: 112 lua release ngx.ctx at ref 2 received: 112 lua release ngx.ctx at ref 1 lua release ngx.ctx at ref 2 received: 112 lua release ngx.ctx at ref 2 received: 112 lua release ngx.ctx at ref 1 "] --- no_error_log [error] === TEST 11: overwrite values will only take affect in the current http request --- http_config server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; ssl_certificate_by_lua_block { ngx.ctx.answer = 0 } ssl_certificate ../../cert/test.crt; ssl_certificate_key ../../cert/test.key; server_tokens off; location /foo1 { content_by_lua_block { ngx.say(ngx.ctx.answer) ngx.ctx.answer = 42 } } location /foo2 { content_by_lua_block { ngx.say(ngx.ctx.answer) } } } --- config lua_ssl_trusted_certificate ../../cert/test.crt; location /t { content_by_lua_block { do local sock = ngx.socket.tcp() sock:settimeout(3000) local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") if not ok then ngx.say("failed to connect: ", err) return end local sess, err = sock:sslhandshake(nil, "test.com", true) if not sess then ngx.say("failed to do SSL handshake: ", err) return end for i = 1, 2 do local req = "GET /foo" .. i .. " HTTP/1.1\r\nHost: test.com\r\n\r\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) return end local body_seen = false while true do local line, err = sock:receive() if not line then break end if body_seen then if line == "0" then assert(sock:receive()) break end local line, err = sock:receive(line) ngx.print("received: ", line) assert(sock:receive()) elseif line == "" then body_seen = true end end end sock:close() end -- do -- collectgarbage() } } --- request GET /t --- response_body received: 0 received: 0 === TEST 12: prohibit setting ngx.ctx to non-table value --- config location = /t { content_by_lua_block { local ok, err = pcall(function() ngx.ctx = nil end) if not ok then ngx.say(err) end } } --- request GET /t --- response_body_like ctx should be a table while getting a nil --- no_error_log [error] === TEST 13: get_ctx_table --- config location = /t { content_by_lua_block { local get_ctx_table = require "resty.core.ctx" .get_ctx_table local reused_ctx = {} local ctx = get_ctx_table(reused_ctx) if ctx == reused_ctx then ngx.say("reused") end local ctx2 = get_ctx_table() if ctx2 == reused_ctx then ngx.say("reused again") end } } --- request GET /t --- response_body reused reused again --- no_error_log [error] === TEST 14: ngx.ctx in ssl_client_hello_by_lua --- http_config server { listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; server_name test.com; ssl_client_hello_by_lua_block { ngx.ctx.answer = 42 ngx.log(ngx.WARN, "ngx.ctx.answer = ", ngx.ctx.answer) ngx.ctx.count = 0 } ssl_certificate ../../cert/test.crt; ssl_certificate_key ../../cert/test.key; server_tokens off; location /foo { content_by_lua_block { ngx.say(ngx.ctx.answer) ngx.ctx.count = ngx.ctx.count + 1 ngx.say(ngx.ctx.count) } } } --- config lua_ssl_trusted_certificate ../../cert/test.crt; location /t { content_by_lua_block { do local sock = ngx.socket.tcp() sock:settimeout(3000) local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") if not ok then ngx.say("failed to connect: ", err) return end local sess, err = sock:sslhandshake(nil, "test.com", true) if not sess then ngx.say("failed to do SSL handshake: ", err) return end for i = 1, 2 do local req = "GET /foo HTTP/1.1\r\nHost: test.com\r\n\r\n" local bytes, err = sock:send(req) if not bytes then ngx.say("failed to send http request: ", err) return end local body_seen = false while true do local line, err = sock:receive() if not line then break end if body_seen then if line == "0" then assert(sock:receive()) break end local line, err = sock:receive(line) ngx.print("received: ", line) assert(sock:receive()) elseif line == "" then body_seen = true end end end sock:close() end -- do -- collectgarbage() } } --- request GET /t --- response_body received: 42 received: 1 received: 42 received: 1 --- error_log ngx.ctx.answer = 42 --- grep_error_log eval qr/lua release ngx.ctx at ref \d+/ --- grep_error_log_out eval ["lua release ngx.ctx at ref 2 lua release ngx.ctx at ref 2 lua release ngx.ctx at ref 1 ", "lua release ngx.ctx at ref 2 lua release ngx.ctx at ref 2 lua release ngx.ctx at ref 1 lua release ngx.ctx at ref 2 lua release ngx.ctx at ref 2 lua release ngx.ctx at ref 1 "] --- no_error_log [error]