1
# vim:set ft= ts=4 sw=4 et fdm=marker:
4
use Test::Nginx::Socket;
7
our $GCScript = $t::StapThread::GCScript;
8
our $StapScript = $t::StapThread::StapScript;
12
plan tests => repeat_each() * (blocks() * 4 + 1);
14
$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8';
15
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= '11211';
23
=== TEST 1: simple user thread without I/O
28
ngx.say("hello in thread")
35
content_by_lua return;
40
<<'_EOC_' . $::StapScript;
42
F(ngx_http_lua_send_chain_link) {
43
printf("send link %p\n", $in)
46
F(ngx_http_core_content_phase) {
47
println("core content phase")
51
--- stap eval: $::GCScript
54
spawn user thread 2 in 1
71
=== TEST 2: two simple user threads without I/O
76
ngx.say("in thread 1")
80
ngx.say("in thread 2")
91
content_by_lua return;
95
--- stap2 eval: $::StapScript
96
--- stap eval: $::GCScript
99
spawn user thread 2 in 1
102
spawn user thread 3 in 1
123
=== TEST 3: simple user thread with sleep
128
ngx.say("before sleep")
130
ngx.say("after sleep")
133
ngx.say("before thread create")
135
ngx.say("after thread create")
137
content_by_lua return;
141
--- stap2 eval: $::StapScript
142
--- stap eval: $::GCScript
145
spawn user thread 2 in 1
163
=== TEST 4: two simple user threads with sleep
168
ngx.say("1: before sleep")
170
ngx.say("1: after sleep")
174
ngx.say("2: before sleep")
176
ngx.say("2: after sleep")
179
ngx.say("1: before thread create")
181
ngx.say("1: after thread create")
183
ngx.say("2: before thread create")
185
ngx.say("2: after thread create")
187
content_by_lua return;
191
--- stap2 eval: $::StapScript
192
--- stap eval: $::GCScript
195
spawn user thread 2 in 1
197
spawn user thread 3 in 1
208
1: before thread create
210
1: after thread create
211
2: before thread create
213
2: after thread create
221
=== TEST 5: error in user thread
232
content_by_lua return;
236
--- stap2 eval: $::StapScript
237
--- stap eval: $::GCScript
240
spawn user thread 2 in 1
251
lua user thread aborted: runtime error: [string "rewrite_by_lua"]:3: attempt to call field 'blah' (a nil value)
255
=== TEST 6: simple user threads doing a single subrequest (entry quits early)
260
ngx.say("before capture")
261
res = ngx.location.capture("/proxy")
262
ngx.say("after capture: ", res.body)
265
ngx.say("before thread create")
267
ngx.say("after thread create")
269
content_by_lua return;
273
proxy_pass http://127.0.0.1:$server_port/foo;
282
--- stap2 eval: $::StapScript
283
--- stap eval: $::GCScript
286
spawn user thread 2 in 1
298
after capture: hello world
304
=== TEST 7: simple user threads doing a single subrequest (entry also does a subrequest and quits early)
309
ngx.say("before capture")
310
local res = ngx.location.capture("/proxy?foo")
311
ngx.say("after capture: ", res.body)
314
ngx.say("before thread create")
316
ngx.say("after thread create")
317
local res = ngx.location.capture("/proxy?bar")
318
ngx.say("capture: ", res.body)
320
content_by_lua return;
324
proxy_pass http://127.0.0.1:$server_port/$args;
337
--- stap2 eval: $::StapScript
338
--- stap eval: $::GCScript
341
spawn user thread 2 in 1
354
after capture: hello foo
360
=== TEST 8: simple user threads doing a single subrequest (entry also does a subrequest and quits late)
365
ngx.say("before capture")
366
local res = ngx.location.capture("/proxy?foo")
367
ngx.say("after capture: ", res.body)
370
ngx.say("before thread create")
372
ngx.say("after thread create")
373
local res = ngx.location.capture("/proxy?bar")
374
ngx.say("capture: ", res.body)
376
content_by_lua return;
380
proxy_pass http://127.0.0.1:$server_port/$args;
394
--- stap2 eval: $::StapScript
395
--- stap eval: $::GCScript
398
spawn user thread 2 in 1
410
after capture: hello foo
417
=== TEST 9: two simple user threads doing single subrequests (entry also does a subrequest and quits between)
422
ngx.say("f: before capture")
423
local res = ngx.location.capture("/proxy?foo")
424
ngx.say("f: after capture: ", res.body)
428
ngx.say("g: before capture")
429
local res = ngx.location.capture("/proxy?bah")
430
ngx.say("g: after capture: ", res.body)
433
ngx.say("before thread 1 create")
435
ngx.say("after thread 1 create")
437
ngx.say("before thread 2 create")
439
ngx.say("after thread 2 create")
441
local res = ngx.location.capture("/proxy?bar")
442
ngx.say("capture: ", res.body)
444
content_by_lua return;
448
proxy_pass http://127.0.0.1:$server_port/$args;
467
--- stap2 eval: $::StapScript
468
--- stap eval: $::GCScript
471
spawn user thread 2 in 1
473
spawn user thread 3 in 1
484
before thread 1 create
486
after thread 1 create
487
before thread 2 create
489
after thread 2 create
490
f: after capture: hello foo
492
g: after capture: hello bah
498
=== TEST 10: nested user threads
509
ngx.say("hello in g()")
516
content_by_lua return;
520
--- stap2 eval: $::StapScript
521
--- stap eval: $::GCScript
524
spawn user thread 2 in 1
526
spawn user thread 3 in 2
547
=== TEST 11: nested user threads (with I/O)
559
ngx.say("hello in g()")
566
content_by_lua return;
570
--- stap2 eval: $::StapScript
571
--- stap eval: $::GCScript
574
spawn user thread 2 in 1
576
spawn user thread 3 in 2
597
=== TEST 12: coroutine status of a running user thread
603
co = coroutine.running()
608
ngx.say("status: ", coroutine.status(co))
610
content_by_lua return;
614
--- stap2 eval: $::StapScript
615
--- stap eval: $::GCScript
618
spawn user thread 2 in 1
633
=== TEST 13: coroutine status of a dead user thread
639
co = coroutine.running()
643
ngx.say("status: ", coroutine.status(co))
645
content_by_lua return;
649
--- stap2 eval: $::StapScript
650
--- stap eval: $::GCScript
653
spawn user thread 2 in 1
668
=== TEST 14: coroutine status of a "normal" user thread
674
co = coroutine.running()
675
local co2 = coroutine.create(g)
676
coroutine.resume(co2)
684
ngx.say("status: ", coroutine.status(co))
686
content_by_lua return;
690
--- stap2 eval: $::StapScript
691
--- stap eval: $::GCScript
694
spawn user thread 2 in 1
711
=== TEST 15: creating user threads in a user coroutine
722
ngx.say("hello in g()")
726
local co = coroutine.create(f)
730
content_by_lua return;
734
--- stap2 eval: $::StapScript
735
--- stap eval: $::GCScript
739
spawn user thread 3 in 2
759
=== TEST 16: manual time slicing between a user thread and the entry thread
763
local yield = coroutine.yield
766
local self = coroutine.running()
774
local self = coroutine.running()
785
content_by_lua return;
789
--- stap2 eval: $::StapScript
790
--- stap eval: $::GCScript
793
spawn user thread 2 in 1
815
=== TEST 17: manual time slicing between two user threads
819
local yield = coroutine.yield
822
local self = coroutine.running()
831
local self = coroutine.running()
843
content_by_lua return;
847
--- stap2 eval: $::StapScript
848
--- stap eval: $::GCScript
851
spawn user thread 2 in 1
853
spawn user thread 3 in 1
876
=== TEST 18: entry thread and a user thread flushing at the same time
881
ngx.say("hello in thread")
882
coroutine.yield(coroutine.running)
891
content_by_lua return;
895
--- stap2 eval: $::StapScript
896
--- stap eval: $::GCScript
899
spawn user thread 2 in 1
916
=== TEST 19: two user threads flushing at the same time
921
ngx.say("hello from f")
926
ngx.say("hello from g")
933
content_by_lua return;
937
--- stap2 eval: $::StapScript
938
--- stap eval: $::GCScript
941
spawn user thread 2 in 1
943
spawn user thread 3 in 1
949
delete thread 3|create 2 in 1
950
spawn user thread 2 in 1
953
spawn user thread 3 in 1
970
=== TEST 20: user threads + ngx.socket.tcp
975
local sock = ngx.socket.tcp()
976
local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_MEMCACHED_PORT)
978
ngx.say("failed to connect: ", err)
981
local bytes, err = sock:send("flush_all\\r\\n")
983
ngx.say("failed to send query: ", err)
987
local line, err = sock:receive()
989
ngx.say("failed to receive: ", err)
993
ngx.say("received: ", line)
1000
content_by_lua return;
1004
--- stap2 eval: $::StapScript
1005
--- stap eval: $::GCScript
1008
spawn user thread 2 in 1
1025
=== TEST 21: user threads + ngx.socket.udp
1030
local sock = ngx.socket.udp()
1031
local ok, err = sock:setpeername("127.0.0.1", 12345)
1032
local bytes, err = sock:send("blah")
1034
ngx.say("failed to send query: ", err)
1038
local line, err = sock:receive()
1040
ngx.say("failed to receive: ", err)
1044
ngx.say("received: ", line)
1051
content_by_lua return;
1055
--- stap2 eval: $::StapScript
1056
--- stap eval: $::GCScript
1057
--- stap_out_like chop
1059
spawn user thread 2 in 1
1067
spawn user thread 2 in 1
1075
--- udp_listen: 12345
1077
--- udp_reply: hello udp
1078
--- response_body_like chop
1091
=== TEST 22: simple user thread with ngx.req.read_body()
1097
local body = ngx.req.get_body_data()
1098
ngx.say("body: ", body)
1105
content_by_lua return;
1110
--- stap2 eval: $::StapScript
1111
--- stap eval: $::GCScript
1112
--- stap_out_like chop
1114
spawn user thread 2 in 1
1118
delete thread 1|create 2 in 1
1119
spawn user thread 2 in 1
1127
--- response_body_like chop
1139
=== TEST 23: simple user thread with ngx.req.socket()
1144
local sock = ngx.req.socket()
1145
local body, err = sock:receive(11)
1147
ngx.say("failed to read body: ", err)
1151
ngx.say("body: ", body)
1158
content_by_lua return;
1163
--- stap2 eval: $::StapScript
1164
--- stap eval: $::GCScript
1165
--- stap_out_like chop
1167
spawn user thread 2 in 1
1171
delete thread 1|create 2 in 1
1172
spawn user thread 2 in 1
1180
--- response_body_like chop
1192
=== TEST 24: multiple user threads + subrequests returning 404 immediately
1196
local capture = ngx.location.capture
1197
local insert = table.insert
1200
local res = capture("/proxy/" .. i)
1201
ngx.say("status: ", res.status)
1206
local co = ngx.thread.spawn(f, i)
1212
content_by_lua return;
1215
location ~ ^/proxy/(\d+) {
1220
--- stap2 eval: $::StapScript
1225
F(ngx_http_finalize_request) {
1226
printf("finalize request %s: rc:%d c:%d a:%d\n", ngx_http_req_uri($r), $rc, $r->main->count, $r == $r->main);
1232
M(http-subrequest-done) {
1233
printf("subrequest %s done\n", ngx_http_req_uri($r))
1236
F(ngx_http_lua_post_subrequest) {
1237
printf("post subreq: %s rc=%d, status=%d a=%d\n", ngx_http_req_uri($r), $rc,
1238
$r->headers_out->status, $r == $r->main)
1242
--- stap_out_like chop
1244
spawn user thread 2 in 1
1246
spawn user thread 3 in 1
1249
finalize request /proxy/1: rc:404 c:3 a:0
1250
post subreq: /proxy/1 rc=404, status=0 a=0
1251
subrequest /proxy/1 done
1254
finalize request /proxy/2: rc:404 c:2 a:0
1255
post subreq: /proxy/2 rc=404, status=0 a=0
1256
subrequest /proxy/2 done
1261
finalize request /t: rc:0 c:1 a:1
1262
(?:finalize request /t: rc:0 c:1 a:1)?$
1274
=== TEST 25: multiple user threads + subrequests returning 404 remotely (no wait)
1278
local capture = ngx.location.capture
1279
local insert = table.insert
1282
local res = capture("/proxy/" .. i)
1283
ngx.say("status: ", res.status)
1288
local co = ngx.thread.spawn(f, i)
1294
content_by_lua return;
1297
location ~ ^/proxy/(\d+) {
1298
proxy_pass http://127.0.0.1:$server_port/d/$1;
1307
--- stap2 eval: $::StapScript
1308
--- stap eval: $::GCScript
1309
--- stap_out_like chop
1311
spawn user thread 2 in 1
1313
spawn user thread 3 in 1
1315
spawn user thread 4 in 1
1317
spawn user thread 5 in 1
1319
spawn user thread 6 in 1
1331
delete thread 6|terminate 6: ok
1357
=== TEST 26: multiple user threads + subrequests returning 201 immediately
1361
local capture = ngx.location.capture
1362
local insert = table.insert
1365
local res = capture("/proxy/" .. i)
1366
ngx.say("status: ", res.status)
1371
local co = ngx.thread.spawn(f, i)
1377
content_by_lua return;
1380
location ~ ^/proxy/(\d+) {
1381
content_by_lua 'ngx.exit(201)';
1385
--- stap2 eval: $::StapScript
1390
F(ngx_http_finalize_request) {
1391
printf("finalize request %s: rc:%d c:%d a:%d\n", ngx_http_req_uri($r), $rc, $r->main->count, $r == $r->main);
1397
M(http-subrequest-done) {
1398
printf("subrequest %s done\n", ngx_http_req_uri($r))
1401
F(ngx_http_lua_post_subrequest) {
1402
printf("post subreq: %s rc=%d, status=%d a=%d\n", ngx_http_req_uri($r), $rc,
1403
$r->headers_out->status, $r == $r->main)
1407
--- stap_out_like chop
1409
spawn user thread 2 in 1
1411
spawn user thread 3 in 1
1416
finalize request /proxy/1: rc:201 c:3 a:0
1417
post subreq: /proxy/1 rc=201, status=201 a=0
1418
subrequest /proxy/1 done
1423
finalize request /proxy/2: rc:201 c:2 a:0
1424
post subreq: /proxy/2 rc=201, status=201 a=0
1425
subrequest /proxy/2 done
1430
finalize request /t: rc:0 c:1 a:1
1431
(?:finalize request /t: rc:0 c:1 a:1)?$
1443
=== TEST 27: multiple user threads + subrequests returning 204 immediately
1447
local capture = ngx.location.capture
1448
local insert = table.insert
1451
local res = capture("/proxy/" .. i)
1452
ngx.say("status: ", res.status)
1457
local co = ngx.thread.spawn(f, i)
1463
content_by_lua return;
1466
location ~ ^/proxy/(\d+) {
1467
content_by_lua 'ngx.exit(204)';
1471
--- stap2 eval: $::StapScript
1476
F(ngx_http_finalize_request) {
1477
printf("finalize request %s: rc:%d c:%d a:%d\n", ngx_http_req_uri($r), $rc, $r->main->count, $r == $r->main);
1483
M(http-subrequest-done) {
1484
printf("subrequest %s done\n", ngx_http_req_uri($r))
1487
F(ngx_http_lua_post_subrequest) {
1488
printf("post subreq: %s rc=%d, status=%d a=%d\n", ngx_http_req_uri($r), $rc,
1489
$r->headers_out->status, $r == $r->main)
1494
--- stap_out_like chop
1496
spawn user thread 2 in 1
1498
spawn user thread 3 in 1
1503
finalize request /proxy/1: rc:204 c:3 a:0
1504
post subreq: /proxy/1 rc=204, status=204 a=0
1505
subrequest /proxy/1 done
1510
finalize request /proxy/2: rc:204 c:2 a:0
1511
post subreq: /proxy/2 rc=204, status=204 a=0
1512
subrequest /proxy/2 done
1517
finalize request /t: rc:0 c:1 a:1
1518
(?:finalize request /t: rc:0 c:1 a:1)?$