blob: d8936520933a2caeab3116721dde8594bc6b82da [file] [log] [blame] [raw]
# vim:set ft= ts=4 sw=4 et fdm=marker:
BEGIN {
$ENV{TEST_NGINX_POSTPONE_OUTPUT} = 1;
}
use lib 'lib';
use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_on();
#workers(2);
#log_level('warn');
repeat_each(2);
plan tests => repeat_each() * 55;
#no_diff();
no_long_string();
run_tests();
__DATA__
=== TEST 1: flush wait - content
--- config
location /test {
content_by_lua '
ngx.say("hello, world")
local ok, err = ngx.flush(true)
if not ok then
ngx.log(ngx.ERR, "flush failed: ", err)
return
end
ngx.say("hiya")
';
}
--- request
GET /test
--- response_body
hello, world
hiya
--- no_error_log
[error]
--- error_log
lua reuse free buf memory 13 >= 5
=== TEST 2: flush no wait - content
--- config
send_timeout 500ms;
location /test {
content_by_lua '
ngx.say("hello, world")
local ok, err = ngx.flush(false)
if not ok then
ngx.log(ngx.ERR, "flush failed: ", err)
return
end
ngx.say("hiya")
';
}
--- request
GET /test
--- response_body
hello, world
hiya
=== TEST 3: flush wait - rewrite
--- config
location /test {
rewrite_by_lua '
ngx.say("hello, world")
ngx.flush(true)
ngx.say("hiya")
';
content_by_lua return;
}
--- request
GET /test
--- response_body
hello, world
hiya
=== TEST 4: flush no wait - rewrite
--- config
location /test {
rewrite_by_lua '
ngx.say("hello, world")
ngx.flush(false)
ngx.say("hiya")
';
content_by_lua return;
}
--- request
GET /test
--- response_body
hello, world
hiya
=== TEST 5: http 1.0 (sync)
--- config
location /test {
content_by_lua '
ngx.say("hello, world")
ngx.flush(true)
ngx.say("hiya")
ngx.flush(true)
ngx.say("blah")
';
}
--- request
GET /test HTTP/1.0
--- response_body
hello, world
hiya
blah
--- response_headers
Content-Length: 23
--- timeout: 5
--- error_log
lua buffering output bufs for the HTTP 1.0 request
lua http 1.0 buffering makes ngx.flush() a no-op
=== TEST 6: http 1.0 (async)
--- config
location /test {
content_by_lua '
ngx.say("hello, world")
local ok, err = ngx.flush(false)
if not ok then
ngx.log(ngx.WARN, "1: failed to flush: ", err)
end
ngx.say("hiya")
local ok, err = ngx.flush(false)
if not ok then
ngx.log(ngx.WARN, "2: failed to flush: ", err)
end
ngx.say("blah")
';
}
--- request
GET /test HTTP/1.0
--- response_body
hello, world
hiya
blah
--- response_headers
Content-Length: 23
--- error_log
lua buffering output bufs for the HTTP 1.0 request
lua http 1.0 buffering makes ngx.flush() a no-op
1: failed to flush: buffering
2: failed to flush: buffering
--- timeout: 5
=== TEST 7: flush wait - big data
--- config
location /test {
content_by_lua '
ngx.say(string.rep("a", 1024 * 64))
ngx.flush(true)
ngx.say("hiya")
';
}
--- request
GET /test
--- response_body
hello, world
hiya
--- SKIP
=== TEST 8: flush wait - content
--- config
location /test {
content_by_lua '
ngx.say("hello, world")
ngx.flush(true)
local res = ngx.location.capture("/sub")
ngx.print(res.body)
ngx.flush(true)
';
}
location /sub {
echo sub;
}
--- request
GET /test
--- response_body
hello, world
sub
=== TEST 9: http 1.0 (sync + buffering off)
--- config
lua_http10_buffering off;
location /test {
content_by_lua '
ngx.say("hello, world")
ngx.flush(true)
ngx.say("hiya")
ngx.flush(true)
ngx.say("blah")
';
}
--- request
GET /test HTTP/1.0
--- response_body
hello, world
hiya
blah
--- response_headers
!Content-Length
--- timeout: 5
--- no_error_log
lua buffering output bufs for the HTTP 1.0 request
lua http 1.0 buffering makes ngx.flush() a no-op
=== TEST 10: http 1.0 (async)
--- config
lua_http10_buffering on;
location /test {
lua_http10_buffering off;
content_by_lua '
ngx.say("hello, world")
ngx.flush(false)
ngx.say("hiya")
ngx.flush(false)
ngx.say("blah")
';
}
--- request
GET /test HTTP/1.0
--- response_body
hello, world
hiya
blah
--- response_headers
!Content-Length
--- no_error_log
lua buffering output bufs for the HTTP 1.0 request
lua http 1.0 buffering makes ngx.flush() a no-op
--- timeout: 5
=== TEST 11: http 1.0 (sync) - buffering explicitly off
--- config
location /test {
lua_http10_buffering on;
content_by_lua '
ngx.say("hello, world")
ngx.flush(true)
ngx.say("hiya")
ngx.flush(true)
ngx.say("blah")
';
}
--- request
GET /test HTTP/1.0
--- response_body
hello, world
hiya
blah
--- response_headers
Content-Length: 23
--- timeout: 5
--- error_log
lua buffering output bufs for the HTTP 1.0 request
lua http 1.0 buffering makes ngx.flush() a no-op
=== TEST 12: http 1.0 (async) - buffering explicitly off
--- config
location /test {
lua_http10_buffering on;
content_by_lua '
ngx.say("hello, world")
ngx.flush(false)
ngx.say("hiya")
ngx.flush(false)
ngx.say("blah")
';
}
--- request
GET /test HTTP/1.0
--- response_body
hello, world
hiya
blah
--- response_headers
Content-Length: 23
--- error_log
lua buffering output bufs for the HTTP 1.0 request
lua http 1.0 buffering makes ngx.flush() a no-op
--- timeout: 5
=== TEST 13: flush wait in a user coroutine
--- config
location /test {
content_by_lua '
function f()
ngx.say("hello, world")
ngx.flush(true)
coroutine.yield()
ngx.say("hiya")
end
local c = coroutine.create(f)
ngx.say(coroutine.resume(c))
ngx.say(coroutine.resume(c))
';
}
--- request
GET /test
--- stap2
F(ngx_http_lua_wev_handler) {
printf("wev handler: wev:%d\n", $r->connection->write->ready)
}
global ids, cur
function gen_id(k) {
if (ids[k]) return ids[k]
ids[k] = ++cur
return cur
}
F(ngx_http_handler) {
delete ids
cur = 0
}
/*
F(ngx_http_lua_run_thread) {
id = gen_id($ctx->cur_co)
printf("run thread %d\n", id)
}
probe process("/usr/local/openresty-debug/luajit/lib/libluajit-5.1.so.2").function("lua_resume") {
id = gen_id($L)
printf("lua resume %d\n", id)
}
*/
M(http-lua-user-coroutine-resume) {
p = gen_id($arg2)
c = gen_id($arg3)
printf("resume %x in %x\n", c, p)
}
M(http-lua-entry-coroutine-yield) {
println("entry coroutine yield")
}
/*
F(ngx_http_lua_coroutine_yield) {
printf("yield %x\n", gen_id($L))
}
*/
M(http-lua-user-coroutine-yield) {
p = gen_id($arg2)
c = gen_id($arg3)
printf("yield %x in %x\n", c, p)
}
F(ngx_http_lua_atpanic) {
printf("lua atpanic(%d):", gen_id($L))
print_ubacktrace();
}
M(http-lua-user-coroutine-create) {
p = gen_id($arg2)
c = gen_id($arg3)
printf("create %x in %x\n", c, p)
}
F(ngx_http_lua_ngx_exec) { println("exec") }
F(ngx_http_lua_ngx_exit) { println("exit") }
F(ngx_http_writer) { println("http writer") }
--- response_body
hello, world
true
hiya
true
--- error_log
lua reuse free buf memory 13 >= 5
=== TEST 14: flush before sending out the header
--- config
location /test {
content_by_lua '
ngx.flush()
ngx.status = 404
ngx.say("not found")
';
}
--- request
GET /test
--- response_body
not found
--- error_code: 404
--- no_error_log
[error]
=== TEST 15: flush wait - gzip
--- config
gzip on;
gzip_min_length 1;
gzip_types text/plain;
location /test {
content_by_lua '
ngx.say("hello, world")
local ok, err = ngx.flush(true)
if not ok then
ngx.log(ngx.ERR, "flush failed: ", err)
return
end
ngx.say("hiya")
';
}
--- request
GET /test
--- more_headers
Accept-Encoding: gzip
--- response_body_like: .{15}
--- response_headers
Content-Encoding: gzip
--- no_error_log
[error]
=== TEST 16: flush wait - gunzip
--- config
location /test {
gunzip on;
content_by_lua '
local f, err = io.open(ngx.var.document_root .. "/gzip.bin", "r")
if not f then
ngx.say("failed to open file: ", err)
return
end
local data = f:read(100)
ngx.header.content_encoding = "gzip"
ngx.print(data)
local ok, err = ngx.flush(true)
if not ok then
ngx.log(ngx.ERR, "flush failed: ", err)
return
end
data = f:read("*a")
ngx.print(data)
';
}
--- user_files eval
">>> gzip.bin
\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\x62\x64\x62\x62\x61\x62\x64\x63\x61\xe4\xe0\xe2\xe6\xe4\x61\xe4\xe4\xe7\x63\x12\xe4\xe1\xe0\x60\x14\x12\xe3\x91\xe4\xe4\xe4\x13\x60\xe3\x95\x12\x90\x15\xe0\x11\x50\x92\xd1\x16\x17\xe2\xd3\x17\x14\x11\x95\x95\x57\x96\x63\x37\xd2\x36\xd6\x51\x34\xb1\xe6\x62\x17\x95\xb0\x77\x60\xe3\x96\x33\x95\xb6\x91\x75\x97\x30\xe4\x66\x0c\xd0\xe3\xe0\xb5\xd3\x33\xf6\x90\x16\xb2\x90\x77\x56\x31\xe7\x55\x32\x11\x74\xe0\x02\x00\x00\x00\xff\xff\xcb\xc8\xac\x4c\xe4\x02\x00\x19\x15\xa9\x77\x6a\x00\x00\x00"
--- request
GET /test
--- ignore_response
--- no_error_log
[error]