aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/testclnt.lua174
-rw-r--r--test/utestclnt.lua45
2 files changed, 219 insertions, 0 deletions
diff --git a/test/testclnt.lua b/test/testclnt.lua
index 170e187..3e897c9 100644
--- a/test/testclnt.lua
+++ b/test/testclnt.lua
@@ -619,6 +619,177 @@ remote([[
619end 619end
620 620
621------------------------------------------------------------------------ 621------------------------------------------------------------------------
622function test_maxsize()
623 -- Group A: argument errors, raised before any I/O
624 reconnect()
625 printf("argument errors: ")
626 -- bounds pre-implementation calls (where arg 4 is silently dropped and
627 -- these become real, otherwise-unbounded blocking reads on an idle
628 -- socket) so a meaningful failure doesn't hang the suite
629 data:settimeout(0.2)
630 local ok
631 ok = pcall(data.receive, data, "*l", nil, 0)
632 assert(not ok, "A1 failed: maxsize=0 should raise")
633 ok = pcall(data.receive, data, "*l", nil, -1)
634 assert(not ok, "A2 failed: maxsize=-1 should raise")
635 ok = pcall(data.receive, data, "*l", nil, "abc")
636 assert(not ok, "A3 failed: non-number maxsize should raise")
637 ok = pcall(data.receive, data, "*l", string.rep("x", 10), 10)
638 assert(not ok, "A4 failed: #prefix == maxsize should raise")
639 ok = pcall(data.receive, data, "*l", string.rep("x", 11), 10)
640 assert(not ok, "A5 failed: #prefix > maxsize should raise")
641 ok = pcall(data.receive, data, 100, nil, 50)
642 assert(not ok, "A6 failed: wanted > maxsize should raise")
643 data:settimeout(0.1)
644 ok = pcall(data.receive, data, 50, nil, 100)
645 assert(ok, "A7 failed: wanted <= maxsize should not raise")
646 data:settimeout(-1)
647 remote [[ data:send('intact\n') ]]
648 local line, err = data:receive("*l", nil, 100)
649 assert(line == "intact",
650 "A8 failed: socket touched by a failed argcheck (err=" ..
651 tostring(err) .. ")")
652 pass("ok")
653
654 -- Group B: *l boundary
655 reconnect()
656 printf("*l boundary: ")
657 remote [[ data:send('hello\n') ]]
658 local d, e, p = data:receive("*l", nil, 100)
659 assert(d == "hello" and e == nil, "B1 failed")
660
661 remote(string.format([[data:send(string.rep('a',%d) .. '\n')]], 100))
662 d, e = data:receive("*l", nil, 100)
663 assert(d == string.rep("a", 100) and e == nil,
664 "B2 failed: exact-budget line should succeed")
665
666 remote(string.format([[data:send(string.rep('a',%d) .. '\n')]], 101))
667 d, e, p = data:receive("*l", nil, 100)
668 assert(d == nil and e == "oversized" and p == string.rep("a", 100),
669 "B3 failed: one-over-budget should be oversized")
670 d, e = data:receive("*l", nil, 100)
671 assert(d == "a" and e == nil,
672 "B3 failed: leftover byte and terminator should still be there")
673
674 remote(string.format([[data:send(string.rep('\r',%d) .. string.rep('a',%d) .. '\n')]], 50, 100))
675 d, e = data:receive("*l", nil, 100)
676 assert(d == string.rep("a", 100) and e == nil, "B4 failed: CRs must not count")
677
678 remote(string.format([[data:send(string.rep('a',%d) .. '\r\n')]], 100))
679 d, e = data:receive("*l", nil, 100)
680 assert(d == string.rep("a", 100) and e == nil, "B5 failed: CRLF at boundary")
681 pass("ok")
682
683 -- Group C: *l and I1 (timeout/close at the cap)
684 reconnect()
685 printf("I1 (timeout/closed at the cap): ")
686 remote(string.format([[data:send(string.rep('a',%d))]], 50))
687 data:settimeout(0.5)
688 d, e, p = data:receive("*l", nil, 100)
689 assert(d == nil and e == "timeout", "C1 failed: expected timeout below cap")
690 assert(#p < 100, "C1 failed: timeout partial must be strictly < maxsize")
691 ok = pcall(data.receive, data, "*l", p, 100)
692 assert(ok, "C1 failed: retry with prefix=partial, same maxsize must not raise")
693
694 reconnect()
695 remote(string.format([[data:send(string.rep('a',%d))]], 100))
696 data:settimeout(0.5)
697 d, e, p = data:receive("*l", nil, 100)
698 assert(e == "oversized" and #p == 100,
699 "C2 failed: exactly-at-cap timeout must be oversized, got " .. tostring(e))
700
701 reconnect()
702 remote(string.format([[data:send(string.rep('a',%d)) data:close() data = nil]], 100))
703 d, e, p = data:receive("*l", nil, 100)
704 assert(e == "oversized" and #p == 100,
705 "C3 failed: exactly-at-cap close must be oversized, got " .. tostring(e))
706 pass("ok")
707
708 -- Group D: drain idiom
709 -- 5030 (not a multiple of the 100 cap) so the boundary of the 50th
710 -- oversized chunk doesn't land exactly on the '\n': when it does, the
711 -- terminator check wins over the cap check (by design -- see B2/I1) and
712 -- the would-be 50th oversized chunk instead succeeds outright.
713 reconnect()
714 printf("drain idiom: ")
715 remote(string.format([[data:send(string.rep('x',%d) .. '\n' .. 'next\n')]], 5030))
716 local iterations = 0
717 repeat
718 d, e, p = data:receive("*l", "", 100)
719 if e == "oversized" then
720 assert(#p == 100, "D1 failed: oversized partial length " .. #p)
721 iterations = iterations + 1
722 end
723 until e ~= "oversized"
724 assert(iterations == 50,
725 "D1 failed: expected 50 oversized iterations, got " .. iterations)
726 assert(d == string.rep("x", 30) and e == nil, "D1 failed: final call should succeed")
727 local nextline = data:receive("*l")
728 assert(nextline == "next", "D1 failed: stream misaligned, got " .. tostring(nextline))
729 pass("ok")
730
731 -- Group E: *a
732 reconnect()
733 printf("*a boundary: ")
734 remote [[ data:send('abc') data:close() data = nil ]]
735 d, e = data:receive("*a", nil, 100)
736 assert(d == "abc" and e == nil, "E1 failed")
737
738 reconnect()
739 remote(string.format([[data:send(string.rep('a',%d)) data:close() data = nil]], 100))
740 d, e = data:receive("*a", nil, 100)
741 assert(d == string.rep("a", 100) and e == nil,
742 "E2 failed: completion should beat the cap")
743
744 reconnect()
745 remote(string.format([[data:send(string.rep('a',%d)) data:close() data = nil]], 250))
746 d, e, p = data:receive("*a", "", 100)
747 assert(e == "oversized" and #p == 100, "E3 failed: first chunk")
748 d, e, p = data:receive("*a", "", 100)
749 assert(e == "oversized" and #p == 100, "E3 failed: second chunk")
750 d, e = data:receive("*a", "", 100)
751 assert(d == string.rep("a", 50) and e == nil, "E3 failed: final chunk")
752
753 reconnect()
754 remote(string.format([[data:send(string.rep('a',%d))]], 100))
755 data:settimeout(0.3)
756 d, e, p = data:receive("*a", nil, 100)
757 assert(e == "oversized" and #p == 100,
758 "E4 failed: expected oversized not timeout, got " .. tostring(e))
759
760 reconnect()
761 remote(string.format([[data:send(string.rep('a',%d))]], 50))
762 data:settimeout(0.3)
763 d, e, p = data:receive("*a", nil, 100)
764 assert(e == "timeout" and #p < 100, "E5 failed")
765 pass("ok")
766
767 -- Group F: numeric pattern (recvraw untouched)
768 reconnect()
769 printf("numeric pattern (recvraw unchanged): ")
770 remote(string.format([[data:send(string.rep('a',%d))]], 50))
771 d, e = data:receive(50, nil, 100)
772 assert(d == string.rep("a", 50) and e == nil, "F1 failed")
773
774 reconnect()
775 remote(string.format([[data:send(string.rep('a',%d))]], 25))
776 d, e = data:receive(50, string.rep("p", 25), 100)
777 assert(e == nil and #d == 50, "F2 failed")
778 pass("ok")
779
780 -- Group G: no-maxsize regression snapshot
781 reconnect()
782 printf("no-maxsize regression: ")
783 remote(string.format([[data:send(string.rep('a',%d) .. '\n')]], 5000))
784 d, e = data:receive("*l")
785 assert(d == string.rep("a", 5000) and e == nil, "G2 failed: plain *l")
786 remote(string.format([[data:send(string.rep('a',%d) .. '\n')]], 5000))
787 d, e = data:receive("*l", "")
788 assert(d == string.rep("a", 5000) and e == nil, "G2 failed: *l with prefix")
789 pass("ok")
790end
791
792------------------------------------------------------------------------
622test("method registration") 793test("method registration")
623 794
624local tcp_methods = { 795local tcp_methods = {
@@ -796,6 +967,9 @@ test_blockingtimeoutreceive(800091, 2, 3)
796test_blockingtimeoutreceive(800091, 3, 2) 967test_blockingtimeoutreceive(800091, 3, 2)
797test_blockingtimeoutreceive(800091, 3, 1) 968test_blockingtimeoutreceive(800091, 3, 1)
798 969
970test("receive maxsize")
971test_maxsize()
972
799test("shutting server down") 973test("shutting server down")
800reconnect() 974reconnect()
801remote("os.exit()") 975remote("os.exit()")
diff --git a/test/utestclnt.lua b/test/utestclnt.lua
index 7f10643..395260c 100644
--- a/test/utestclnt.lua
+++ b/test/utestclnt.lua
@@ -511,6 +511,48 @@ remote(string.format([[
511end 511end
512 512
513------------------------------------------------------------------------ 513------------------------------------------------------------------------
514function test_maxsize()
515 -- A4: #prefix == maxsize raises (mirrors testclnt.lua group A)
516 reconnect()
517 pass("argument errors")
518 -- bounds the pre-implementation call (arg 4 silently dropped, so this
519 -- becomes a real blocking read on an idle socket) so a meaningful
520 -- failure doesn't hang the suite
521 data:settimeout(0.2)
522 local ok = pcall(data.receive, data, "*l", string.rep("x", 10), 10)
523 assert(not ok, "A4 failed: #prefix == maxsize should raise")
524 data:settimeout(-1)
525
526 -- B2/B3: *l boundary (mirrors testclnt.lua group B)
527 pass("*l boundary")
528 remote(string.format([[data:send(string.rep('a',%d) .. '\n')]], 100))
529 local d, e, p = data:receive("*l", nil, 100)
530 assert(d == string.rep("a", 100) and e == nil, "B2 failed")
531
532 remote(string.format([[data:send(string.rep('a',%d) .. '\n')]], 101))
533 d, e, p = data:receive("*l", nil, 100)
534 assert(d == nil and e == "oversized" and p == string.rep("a", 100), "B3 failed")
535 d, e = data:receive("*l", nil, 100)
536 assert(d == "a" and e == nil, "B3 failed: leftover byte")
537
538 -- C2: timeout exactly at the cap is oversized, not timeout (I1)
539 reconnect()
540 remote(string.format([[data:send(string.rep('a',%d))]], 100))
541 data:settimeout(0.5)
542 d, e, p = data:receive("*l", nil, 100)
543 assert(e == "oversized" and #p == 100,
544 "C2 failed: expected oversized, got " .. tostring(e))
545
546 -- E2: completion beats the cap (I2)
547 reconnect()
548 remote(string.format([[data:send(string.rep('a',%d)) data:close() data = nil]], 100))
549 d, e = data:receive("*a", nil, 100)
550 assert(d == string.rep("a", 100) and e == nil,
551 "E2 failed: completion should beat the cap")
552 pass("ok")
553end
554
555------------------------------------------------------------------------
514 556
515test("method registration") 557test("method registration")
516test_methods(socket.unix(), { 558test_methods(socket.unix(), {
@@ -641,4 +683,7 @@ test_blockingtimeoutreceive(800091, 2, 3)
641test_blockingtimeoutreceive(800091, 3, 2) 683test_blockingtimeoutreceive(800091, 3, 2)
642test_blockingtimeoutreceive(800091, 3, 1) 684test_blockingtimeoutreceive(800091, 3, 1)
643 685
686test("receive maxsize")
687test_maxsize()
688
644test(string.format("done in %.2fs", socket.gettime() - start)) 689test(string.format("done in %.2fs", socket.gettime() - start))