1# vim:set ft= ts=4 sw=4 et fdm=marker:
2
3use Test::Nginx::Socket::Lua;
4use t::StapThread;
5
6our $GCScript = <<_EOC_;
7$t::StapThread::GCScript
8
9F(ngx_http_lua_check_broken_connection) {
10    println("lua check broken conn")
11}
12
13F(ngx_http_lua_request_cleanup) {
14    println("lua req cleanup")
15}
16_EOC_
17
18our $StapScript = $t::StapThread::StapScript;
19
20repeat_each(2);
21
22plan tests => repeat_each() * (blocks() * 3 - 1);
23
24$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8';
25$ENV{TEST_NGINX_MEMCACHED_PORT} ||= '11211';
26$ENV{TEST_NGINX_REDIS_PORT} ||= '6379';
27
28#no_shuffle();
29no_long_string();
30run_tests();
31
32__DATA__
33
34=== TEST 1: sleep + stop
35--- config
36    location /t {
37        lua_check_client_abort on;
38        access_by_lua '
39            ngx.sleep(1)
40        ';
41    }
42--- request
43GET /t
44
45--- stap2 eval: $::StapScript
46--- stap eval: $::GCScript
47--- stap_out
48lua check broken conn
49lua req cleanup
50delete thread 1
51
52--- wait: 0.1
53--- timeout: 0.2
54--- abort
55--- ignore_response
56--- no_error_log
57[error]
58--- error_log
59client prematurely closed connection
60
61
62
63=== TEST 2: sleep + stop (log handler still gets called)
64--- config
65    location /t {
66        lua_check_client_abort on;
67        access_by_lua '
68            ngx.sleep(1)
69        ';
70        log_by_lua '
71            ngx.log(ngx.NOTICE, "here in log by lua")
72        ';
73    }
74--- request
75GET /t
76
77--- stap2 eval: $::StapScript
78--- stap eval: $::GCScript
79--- stap_out
80lua check broken conn
81lua req cleanup
82delete thread 1
83
84--- timeout: 0.2
85--- wait: 0.1
86--- abort
87--- ignore_response
88--- no_error_log
89[error]
90--- error_log
91client prematurely closed connection
92here in log by lua
93
94
95
96=== TEST 3: sleep + ignore
97--- config
98    location /t {
99        lua_check_client_abort off;
100        access_by_lua '
101            ngx.sleep(1)
102        ';
103        content_by_lua return;
104    }
105--- request
106GET /t
107
108--- stap2 eval: $::StapScript
109--- stap eval: $::GCScript
110--- stap_out
111terminate 1: ok
112delete thread 1
113terminate 2: ok
114delete thread 2
115lua req cleanup
116
117--- wait: 1
118--- timeout: 0.2
119--- abort
120--- ignore_response
121--- no_error_log
122[error]
123
124
125
126=== TEST 4: subrequest + stop
127--- config
128    location /t {
129        lua_check_client_abort on;
130        access_by_lua '
131            ngx.location.capture("/sub")
132            error("bad things happen")
133        ';
134    }
135
136    location /sub {
137        echo_sleep 1;
138    }
139--- request
140GET /t
141
142--- stap2 eval: $::StapScript
143--- stap eval: $::GCScript
144--- stap_out
145lua check broken conn
146lua req cleanup
147delete thread 1
148
149--- timeout: 0.2
150--- abort
151--- ignore_response
152--- no_error_log
153[error]
154--- error_log
155client prematurely closed connection
156
157
158
159=== TEST 5: subrequest + ignore
160--- config
161    location /t {
162        lua_check_client_abort off;
163        access_by_lua '
164            ngx.location.capture("/sub")
165            error("bad things happen")
166        ';
167    }
168
169    location /sub {
170        echo_sleep 1;
171    }
172--- request
173GET /t
174
175--- stap2 eval: $::StapScript
176--- stap eval: $::GCScript
177--- stap_out
178terminate 1: fail
179lua req cleanup
180delete thread 1
181
182--- wait: 1.1
183--- timeout: 0.2
184--- abort
185--- ignore_response
186--- error_log
187bad things happen
188
189
190
191=== TEST 6: subrequest + stop (proxy, ignore client abort)
192--- config
193    location = /t {
194        lua_check_client_abort on;
195        access_by_lua '
196            ngx.location.capture("/sub")
197            error("bad things happen")
198        ';
199    }
200
201    location = /sub {
202        proxy_ignore_client_abort on;
203        proxy_pass http://127.0.0.2:12345/;
204    }
205
206    location = /sleep {
207        lua_check_client_abort on;
208        access_by_lua '
209            ngx.sleep(1)
210        ';
211    }
212--- request
213GET /t
214
215--- stap2 eval: $::StapScript
216--- stap eval: $::GCScript
217--- stap_out
218lua check broken conn
219lua req cleanup
220delete thread 1
221
222--- timeout: 0.2
223--- abort
224--- ignore_response
225--- no_error_log
226[error]
227--- error_log
228client prematurely closed connection
229
230
231
232=== TEST 7: subrequest + stop (proxy, check client abort)
233--- config
234    location = /t {
235        lua_check_client_abort on;
236        access_by_lua '
237            ngx.location.capture("/sub")
238            error("bad things happen")
239        ';
240    }
241
242    location = /sub {
243        proxy_ignore_client_abort off;
244        proxy_pass http://127.0.0.2:12345/;
245    }
246--- request
247GET /t
248
249--- stap2 eval: $::StapScript
250--- stap eval: $::GCScript
251--- stap_out
252lua check broken conn
253lua req cleanup
254delete thread 1
255
256--- timeout: 0.2
257--- abort
258--- ignore_response
259--- no_error_log
260[error]
261--- error_log
262client prematurely closed connection
263
264
265
266=== TEST 8: need body on + sleep + stop (log handler still gets called)
267--- config
268    location /t {
269        lua_check_client_abort on;
270        lua_need_request_body on;
271        access_by_lua '
272            ngx.sleep(1)
273        ';
274        log_by_lua '
275            ngx.log(ngx.NOTICE, "here in log by lua")
276        ';
277    }
278--- request
279POST /t
280hello
281
282--- stap2 eval: $::StapScript
283--- stap eval: $::GCScript
284--- stap_out
285lua check broken conn
286lua req cleanup
287delete thread 1
288
289--- timeout: 0.2
290--- abort
291--- ignore_response
292--- no_error_log
293[error]
294--- error_log
295client prematurely closed connection
296here in log by lua
297
298
299
300=== TEST 9: ngx.req.read_body + sleep + stop (log handler still gets called)
301--- config
302    location /t {
303        lua_check_client_abort on;
304        access_by_lua '
305            ngx.req.read_body()
306            ngx.sleep(1)
307        ';
308        log_by_lua '
309            ngx.log(ngx.NOTICE, "here in log by lua")
310        ';
311    }
312--- request
313POST /t
314hello
315
316--- stap2 eval: $::StapScript
317--- stap eval: $::GCScript
318--- stap_out
319lua check broken conn
320lua req cleanup
321delete thread 1
322
323--- timeout: 0.2
324--- abort
325--- ignore_response
326--- no_error_log
327[error]
328--- error_log
329client prematurely closed connection
330here in log by lua
331
332
333
334=== TEST 10: ngx.req.socket + receive() + sleep + stop
335--- config
336    location /t {
337        lua_check_client_abort on;
338        access_by_lua '
339            local sock = ngx.req.socket()
340            sock:receive()
341            ngx.sleep(1)
342        ';
343    }
344--- request
345POST /t
346hello
347
348--- stap2 eval: $::StapScript
349--- stap eval: $::GCScript
350--- stap_out
351lua check broken conn
352lua req cleanup
353delete thread 1
354
355--- timeout: 0.2
356--- abort
357--- ignore_response
358--- no_error_log
359[error]
360--- error_log
361client prematurely closed connection
362
363
364
365=== TEST 11: ngx.req.socket + receive(N) + sleep + stop
366--- config
367    location /t {
368        lua_check_client_abort on;
369        access_by_lua '
370            local sock = ngx.req.socket()
371            sock:receive(5)
372            ngx.sleep(1)
373        ';
374    }
375--- request
376POST /t
377hello
378
379--- stap2 eval: $::StapScript
380--- stap eval: $::GCScript
381--- stap_out
382lua check broken conn
383lua check broken conn
384lua req cleanup
385delete thread 1
386
387--- wait: 0.1
388--- timeout: 0.2
389--- abort
390--- ignore_response
391--- no_error_log
392[error]
393--- error_log
394client prematurely closed connection
395
396
397
398=== TEST 12: ngx.req.socket + receive(n) + sleep + stop
399--- config
400    location /t {
401        lua_check_client_abort on;
402        access_by_lua '
403            local sock = ngx.req.socket()
404            sock:receive(2)
405            ngx.sleep(1)
406        ';
407        content_by_lua return;
408    }
409--- request
410POST /t
411hello
412
413--- stap2 eval: $::StapScript
414--- stap eval: $::GCScript
415--- stap_out_like
416^(?:lua check broken conn
417terminate 1: ok
418delete thread 1
419terminate 2: ok
420delete thread 2
421lua req cleanup|lua check broken conn
422lua req cleanup
423delete thread 1)$
424
425--- wait: 1
426--- timeout: 0.2
427--- abort
428--- ignore_response
429--- no_error_log
430[error]
431
432
433
434=== TEST 13: ngx.req.socket + m * receive(n) + sleep + stop
435--- config
436    location /t {
437        lua_check_client_abort on;
438        access_by_lua '
439            local sock = ngx.req.socket()
440            sock:receive(2)
441            sock:receive(2)
442            sock:receive(1)
443            ngx.sleep(1)
444        ';
445    }
446--- request
447POST /t
448hello
449
450--- stap2 eval: $::StapScript
451--- stap eval: $::GCScript
452--- stap_out
453lua check broken conn
454lua check broken conn
455lua req cleanup
456delete thread 1
457
458--- wait: 1
459--- timeout: 0.2
460--- abort
461--- ignore_response
462--- no_error_log
463[error]
464--- error_log
465client prematurely closed connection
466
467
468
469=== TEST 14: ngx.req.socket + receiveuntil + sleep + stop
470--- config
471    location /t {
472        lua_check_client_abort on;
473        access_by_lua '
474            local sock = ngx.req.socket()
475            local it = sock:receiveuntil("\\n")
476            it()
477            ngx.sleep(1)
478        ';
479    }
480--- request
481POST /t
482hello
483
484--- stap2 eval: $::StapScript
485--- stap eval: $::GCScript
486--- stap_out
487lua check broken conn
488lua req cleanup
489delete thread 1
490
491--- wait: 1
492--- timeout: 0.2
493--- abort
494--- ignore_response
495--- no_error_log
496[error]
497--- error_log
498client prematurely closed connection
499
500
501
502=== TEST 15: ngx.req.socket + receiveuntil + it(n) + sleep + stop
503--- config
504    location /t {
505        lua_check_client_abort on;
506        access_by_lua '
507            local sock = ngx.req.socket()
508            local it = sock:receiveuntil("\\n")
509            it(2)
510            it(3)
511            ngx.sleep(1)
512        ';
513    }
514--- request
515POST /t
516hello
517
518--- stap2 eval: $::StapScript
519--- stap eval: $::GCScript
520--- stap_out
521lua check broken conn
522lua check broken conn
523lua req cleanup
524delete thread 1
525
526--- timeout: 0.2
527--- abort
528--- ignore_response
529--- no_error_log
530[error]
531--- error_log
532client prematurely closed connection
533
534
535
536=== TEST 16: cosocket + stop
537--- config
538    location /t {
539        lua_check_client_abort on;
540        access_by_lua '
541            ngx.req.discard_body()
542
543            local sock, err = ngx.socket.tcp()
544            if not sock then
545                ngx.log(ngx.ERR, "failed to get socket: ", err)
546                return
547            end
548
549            local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_REDIS_PORT)
550            if not ok then
551                ngx.log(ngx.ERR, "failed to connect: ", err)
552                return
553            end
554
555            local bytes, err = sock:send("blpop nonexist 2\\r\\n")
556            if not bytes then
557                ngx.log(ngx.ERR, "failed to send query: ", err)
558                return
559            end
560
561            -- ngx.log(ngx.ERR, "about to receive")
562
563            local res, err = sock:receive()
564            if not res then
565                ngx.log(ngx.ERR, "failed to receive query: ", err)
566                return
567            end
568
569            ngx.log(ngx.ERR, "res: ", res)
570        ';
571    }
572--- request
573GET /t
574
575--- stap2 eval: $::StapScript
576--- stap eval: $::GCScript
577--- stap_out
578lua check broken conn
579lua req cleanup
580delete thread 1
581
582--- wait: 1
583--- timeout: 0.2
584--- abort
585--- ignore_response
586--- no_error_log
587[error]
588--- error_log
589client prematurely closed connection
590
591
592
593=== TEST 17: ngx.req.socket + receive n < content-length + stop
594--- config
595    location /t {
596        lua_check_client_abort on;
597        access_by_lua '
598            local sock = ngx.req.socket()
599            local res, err = sock:receive("*a")
600            if not res then
601                ngx.log(ngx.NOTICE, "failed to receive: ", err)
602                return
603            end
604            error("bad")
605        ';
606        content_by_lua return;
607    }
608--- raw_request eval
609"POST /t HTTP/1.0\r
610Host: localhost\r
611Connection: close\r
612Content-Length: 100\r
613\r
614hello"
615--- stap2 eval: $::StapScript
616--- stap eval: $::GCScript
617--- stap_out
618terminate 1: ok
619delete thread 1
620terminate 2: ok
621delete thread 2
622lua req cleanup
623
624--- timeout: 0.2
625--- abort
626--- ignore_response
627--- no_error_log
628[error]
629--- error_log
630failed to receive: client aborted
631
632
633
634=== TEST 18: ngx.req.socket + receive n == content-length + stop
635--- config
636    location /t {
637        lua_check_client_abort on;
638        access_by_lua '
639            local sock = ngx.req.socket()
640            local res, err = sock:receive("*a")
641            if not res then
642                ngx.log(ngx.NOTICE, "failed to receive: ", err)
643                return
644            end
645            ngx.sleep(1)
646            error("bad")
647        ';
648
649        content_by_lua return;
650    }
651--- raw_request eval
652"POST /t HTTP/1.0\r
653Host: localhost\r
654Connection: close\r
655Content-Length: 5\r
656\r
657hello"
658--- stap2 eval: $::StapScript
659--- stap eval: $::GCScript
660--- stap_out
661lua check broken conn
662lua check broken conn
663lua req cleanup
664delete thread 1
665
666--- timeout: 0.2
667--- abort
668--- ignore_response
669--- no_error_log
670[error]
671--- error_log
672client prematurely closed connection
673
674
675
676=== TEST 19: ngx.req.socket + receive n == content-length + ignore
677--- config
678    location /t {
679        access_by_lua '
680            local sock = ngx.req.socket()
681            local res, err = sock:receive("*a")
682            if not res then
683                ngx.log(ngx.NOTICE, "failed to receive: ", err)
684                return
685            end
686            ngx.say("done")
687        ';
688        content_by_lua return;
689    }
690--- raw_request eval
691"POST /t HTTP/1.0\r
692Host: localhost\r
693Connection: close\r
694Content-Length: 5\r
695\r
696hello"
697--- stap2 eval: $::StapScript
698--- stap eval: $::GCScript
699--- stap_out
700terminate 1: ok
701delete thread 1
702terminate 2: ok
703delete thread 2
704lua req cleanup
705
706--- shutdown: 1
707--- ignore_response
708--- no_error_log
709[error]
710[alert]
711
712
713
714=== TEST 20: ngx.req.read_body + sleep + stop (log handler still gets called)
715--- config
716    location /t {
717        lua_check_client_abort on;
718        access_by_lua '
719            ngx.req.read_body()
720        ';
721        content_by_lua return;
722    }
723--- request
724POST /t
725hello
726
727--- stap2 eval: $::StapScript
728--- stap eval: $::GCScript
729--- stap_out
730terminate 1: ok
731delete thread 1
732terminate 2: ok
733delete thread 2
734lua req cleanup
735
736--- shutdown: 1
737--- wait: 0.1
738--- ignore_response
739--- no_error_log
740[error]
741
742
743
744=== TEST 21: exec to lua + ignore
745--- config
746    location = /t {
747        lua_check_client_abort on;
748        access_by_lua '
749            ngx.exec("/t2")
750        ';
751    }
752
753    location = /t2 {
754        lua_check_client_abort off;
755        content_by_lua '
756            ngx.sleep(1)
757        ';
758    }
759--- request
760GET /t
761
762--- stap2 eval: $::StapScript
763--- stap eval: $::GCScript
764--- stap_out
765terminate 1: ok
766lua req cleanup
767delete thread 1
768terminate 2: ok
769delete thread 2
770lua req cleanup
771
772--- wait: 1
773--- timeout: 0.2
774--- abort
775--- ignore_response
776--- no_error_log
777[error]
778[alert]
779
780
781
782=== TEST 22: exec to proxy + ignore
783--- config
784    location = /t {
785        lua_check_client_abort on;
786        access_by_lua '
787            ngx.exec("/t2")
788        ';
789    }
790
791    location = /t2 {
792        proxy_ignore_client_abort on;
793        proxy_pass http://127.0.0.1:$server_port/sleep;
794    }
795
796    location = /sleep {
797        echo_sleep 1;
798    }
799--- request
800GET /t
801
802--- stap2 eval: $::StapScript
803--- stap eval: $::GCScript
804--- stap_out
805terminate 1: ok
806lua req cleanup
807delete thread 1
808
809--- wait: 1
810--- timeout: 0.2
811--- abort
812--- ignore_response
813--- no_error_log
814[error]
815[alert]
816
817
818
819=== TEST 23: exec (named location) to proxy + ignore
820--- config
821    location = /t {
822        lua_check_client_abort on;
823        access_by_lua '
824            ngx.exec("@t2")
825        ';
826    }
827
828    location @t2 {
829        proxy_ignore_client_abort on;
830        proxy_pass http://127.0.0.1:$server_port/sleep;
831    }
832
833    location = /sleep {
834        echo_sleep 1;
835    }
836--- request
837GET /t
838
839--- stap2 eval: $::StapScript
840--- stap eval: $::GCScript
841--- stap_out
842terminate 1: ok
843lua req cleanup
844delete thread 1
845
846--- wait: 1
847--- timeout: 0.2
848--- abort
849--- ignore_response
850--- no_error_log
851[error]
852[alert]
853