aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorF. Jason Park2022-03-21 05:40:16 -0700
committerF. Jason Park2022-06-30 15:19:53 -0700
commitf46547294d2684d80bb473bd4c85f273ff661a7d (patch)
tree9957e4f497d0588560cad7639441e0b01ca8b123 /test
parenta9d89d083ac5bf0b9fd5568d42e565aba0b6e13f (diff)
downloademacs-f46547294d2684d80bb473bd4c85f273ff661a7d.tar.gz
emacs-f46547294d2684d80bb473bd4c85f273ff661a7d.zip
Improve ERC's handling of multiline prompt input
* lisp/erc/erc.el (erc--pre-send-split-functions): Add new internal hook allowing members to revise individual lines before sending. This was created with an eye toward possibly exporting it publicly as a customizable option. (erc-last-input-time): Tweak meaning of variable to match likely original intent, which is that it's only updated on successful calls to `erc-send-current-line'. (erc--discard-trailing-multiline-nulls): Conditionally truncate list of lines to be sent, skipping trailing blanks. This constitutes a behavioral change. But, considering the nature of the bug being fixed, it is thought to be justified. (erc--input-split): Add new internal struct containing split input lines and flag for command detection. (erc--input-line-delim-regexp): Add regex var for splitting multiline prompt input. (erc--blank-in-multiline-p): Add helper for detecting blank lines. (erc--check-prompt-input-for-multiline-blanks, erc--check-prompt-input-for-point-in-bounds, erc--check-prompt-input-for-running-process): New functions to encapsulate logic for various pre-flight idiot checks. (erc--check-prompt-input-functions): Add new hook for validating prompt input prior to clearing it, internal for now. (erc-send-current-line): Pre-screen for blank lines and bail out if necessary. (erc-send-input): Add optional param to skip checking for blank lines. Call hook `erc--pre-send-split-functions'. * test/lisp/erc/erc-tests.el (erc-ring-previous-command): Use new test helper. (erc--input-line-delim-regexp, erc--blank-in-multiline-input-p): Add tests. (erc-tests--send-prep, erc-tests--set-fake-server-process, erc-tests--with-process-input-spy): Add test helpers. (erc--check-prompt-input-functions, erc-send-current-line, erc-send-whitespace-lines): Add tests. (Bug#54536)
Diffstat (limited to 'test')
-rw-r--r--test/lisp/erc/erc-tests.el208
1 files changed, 208 insertions, 0 deletions
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
index afe9cc7b8cb..986988a3356 100644
--- a/test/lisp/erc/erc-tests.el
+++ b/test/lisp/erc/erc-tests.el
@@ -588,6 +588,214 @@
588 (kill-buffer "*erc-protocol*") 588 (kill-buffer "*erc-protocol*")
589 (should-not erc-debug-irc-protocol))) 589 (should-not erc-debug-irc-protocol)))
590 590
591(ert-deftest erc--input-line-delim-regexp ()
592 (let ((p erc--input-line-delim-regexp))
593 ;; none
594 (should (equal '("a" "b") (split-string "a\r\nb" p)))
595 (should (equal '("a" "b") (split-string "a\nb" p)))
596 (should (equal '("a" "b") (split-string "a\rb" p)))
597
598 ;; one
599 (should (equal '("") (split-string "" p)))
600 (should (equal '("a" "" "b") (split-string "a\r\rb" p)))
601 (should (equal '("a" "" "b") (split-string "a\n\rb" p)))
602 (should (equal '("a" "" "b") (split-string "a\n\nb" p)))
603 (should (equal '("a" "" "b") (split-string "a\r\r\nb" p)))
604 (should (equal '("a" "" "b") (split-string "a\n\r\nb" p)))
605 (should (equal '("a" "") (split-string "a\n" p)))
606 (should (equal '("a" "") (split-string "a\r" p)))
607 (should (equal '("a" "") (split-string "a\r\n" p)))
608 (should (equal '("" "b") (split-string "\nb" p)))
609 (should (equal '("" "b") (split-string "\rb" p)))
610 (should (equal '("" "b") (split-string "\r\nb" p)))
611
612 ;; two
613 (should (equal '("" "") (split-string "\r" p)))
614 (should (equal '("" "") (split-string "\n" p)))
615 (should (equal '("" "") (split-string "\r\n" p)))
616
617 ;; three
618 (should (equal '("" "" "") (split-string "\r\r" p)))
619 (should (equal '("" "" "") (split-string "\n\n" p)))
620 (should (equal '("" "" "") (split-string "\n\r" p)))))
621
622(ert-deftest erc--blank-in-multiline-input-p ()
623 (let ((check (lambda (s)
624 (erc--blank-in-multiline-input-p
625 (split-string s erc--input-line-delim-regexp)))))
626
627 (ert-info ("With `erc-send-whitespace-lines'")
628 (let ((erc-send-whitespace-lines t))
629 (should (funcall check ""))
630 (should-not (funcall check "\na"))
631 (should-not (funcall check "/msg a\n")) ; real /cmd
632 (should-not (funcall check "a\n\nb")) ; "" allowed
633 (should-not (funcall check "/msg a\n\nb")) ; non-/cmd
634 (should-not (funcall check " "))
635 (should-not (funcall check "\t"))
636 (should-not (funcall check "a\nb"))
637 (should-not (funcall check "a\n "))
638 (should-not (funcall check "a\n \t"))
639 (should-not (funcall check "a\n \f"))
640 (should-not (funcall check "a\n \nb"))
641 (should-not (funcall check "a\n \t\nb"))
642 (should-not (funcall check "a\n \f\nb"))))
643
644 (should (funcall check ""))
645 (should (funcall check " "))
646 (should (funcall check "\t"))
647 (should (funcall check "a\n\nb"))
648 (should (funcall check "a\n\nb"))
649 (should (funcall check "a\n "))
650 (should (funcall check "a\n \t"))
651 (should (funcall check "a\n \f"))
652 (should (funcall check "a\n \nb"))
653 (should (funcall check "a\n \t\nb"))
654
655 (should-not (funcall check "a\rb"))
656 (should-not (funcall check "a\nb"))
657 (should-not (funcall check "a\r\nb"))))
658
659(defun erc-tests--with-process-input-spy (test)
660 (with-current-buffer (get-buffer-create "FakeNet")
661 (let* ((erc-pre-send-functions
662 (remove #'erc-add-to-input-ring erc-pre-send-functions)) ; for now
663 (inhibit-message noninteractive)
664 (erc-server-current-nick "tester")
665 (erc-last-input-time 0)
666 erc-accidental-paste-threshold-seconds
667 ;;
668 calls)
669 (cl-letf (((symbol-function 'erc-process-input-line)
670 (lambda (&rest r) (push r calls)))
671 ((symbol-function 'erc-server-buffer)
672 (lambda () (current-buffer))))
673 (erc-tests--send-prep)
674 (funcall test (lambda () (pop calls)))))
675 (when noninteractive (kill-buffer))))
676
677(ert-deftest erc--check-prompt-input-functions ()
678 (erc-tests--with-process-input-spy
679 (lambda (next)
680
681 (ert-info ("Errors when point not in prompt area") ; actually just dings
682 (insert "/msg #chan hi")
683 (forward-line -1)
684 (let ((e (should-error (erc-send-current-line))))
685 (should (equal "Point is not in the input area" (cadr e))))
686 (goto-char (point-max))
687 (ert-info ("Input remains untouched")
688 (should (save-excursion (erc-bol) (looking-at "/msg #chan hi")))))
689
690 (ert-info ("Errors when no process running")
691 (let ((e (should-error (erc-send-current-line))))
692 (should (equal "ERC: No process running" (cadr e))))
693 (ert-info ("Input remains untouched")
694 (should (save-excursion (erc-bol) (looking-at "/msg #chan hi")))))
695
696 (ert-info ("Errors when line contains empty newline")
697 (erc-bol)
698 (delete-region (point) (point-max))
699 (insert "one\n")
700 (let ((e (should-error (erc-send-current-line))))
701 (should (equal "Blank line - ignoring..." (cadr e))))
702 (goto-char (point-max))
703 (ert-info ("Input remains untouched")
704 (should (save-excursion (goto-char erc-input-marker)
705 (looking-at "one\n")))))
706
707 (should (= 0 erc-last-input-time))
708 (should-not (funcall next)))))
709
710;; These also indirectly tests `erc-send-input'
711
712(ert-deftest erc-send-current-line ()
713 (erc-tests--with-process-input-spy
714 (lambda (next)
715 (erc-tests--set-fake-server-process "sleep" "1")
716 (should (= 0 erc-last-input-time))
717
718 (ert-info ("Simple command")
719 (insert "/msg #chan hi")
720 (erc-send-current-line)
721 (ert-info ("Prompt restored")
722 (forward-line 0)
723 (should (looking-at-p erc-prompt)))
724 (ert-info ("Input cleared")
725 (erc-bol)
726 (should (eq (point) (point-max))))
727 ;; Commands are forced (no flood protection)
728 (should (equal (funcall next) '("/msg #chan hi\n" t nil))))
729
730 (ert-info ("Simple non-command")
731 (insert "hi")
732 (erc-send-current-line)
733 (should (eq (point) (point-max)))
734 (should (save-excursion (forward-line -1)
735 (search-forward "<tester> hi")))
736 ;; Non-ommands are forced only when `erc-flood-protect' is nil
737 (should (equal (funcall next) '("hi\n" nil t))))
738
739 (should (consp erc-last-input-time)))))
740
741(ert-deftest erc-send-whitespace-lines ()
742 (erc-tests--with-process-input-spy
743 (lambda (next)
744 (erc-tests--set-fake-server-process "sleep" "1")
745 (setq-local erc-send-whitespace-lines t)
746
747 (ert-info ("Multiline hunk with blank line correctly split")
748 (insert "one\n\ntwo")
749 (erc-send-current-line)
750 (ert-info ("Prompt restored")
751 (forward-line 0)
752 (should (looking-at-p erc-prompt)))
753 (ert-info ("Input cleared")
754 (erc-bol)
755 (should (eq (point) (point-max))))
756 (should (equal (funcall next) '("two\n" nil t)))
757 (should (equal (funcall next) '("\n" nil t)))
758 (should (equal (funcall next) '("one\n" nil t))))
759
760 (ert-info ("Multiline hunk with trailing newline filtered")
761 (insert "hi\n")
762 (erc-send-current-line)
763 (ert-info ("Input cleared")
764 (erc-bol)
765 (should (eq (point) (point-max))))
766 (should (equal (funcall next) '("hi\n" nil t)))
767 (should-not (funcall next)))
768
769 (ert-info ("Multiline hunk with trailing carriage filtered")
770 (insert "hi\r")
771 (erc-send-current-line)
772 (ert-info ("Input cleared")
773 (erc-bol)
774 (should (eq (point) (point-max))))
775 (should (equal (funcall next) '("hi\n" nil t)))
776 (should-not (funcall next)))
777
778 (ert-info ("Multiline command with trailing blank filtered")
779 (pcase-dolist (`(,p . ,q)
780 '(("/a b\r" "/a b\n") ("/a b\n" "/a b\n")
781 ("/a b\n\n" "/a b\n") ("/a b\r\n" "/a b\n")
782 ("a b\nc\n\n" "c\n" "a b\n")
783 ("/a b\nc\n\n" "c\n" "/a b\n")
784 ("/a b\n\nc\n\n" "c\n" "\n" "/a b\n")))
785 (insert p)
786 (erc-send-current-line)
787 (erc-bol)
788 (should (eq (point) (point-max)))
789 (while q
790 (should (equal (funcall next) (list (pop q) nil t))))
791 (should-not (funcall next))))
792
793 (ert-info ("Multiline hunk with trailing whitespace not filtered")
794 (insert "there\n ")
795 (erc-send-current-line)
796 (should (equal (funcall next) '(" \n" nil t)))
797 (should (equal (funcall next) '("there\n" nil t)))
798 (should-not (funcall next))))))
591 799
592;; The point of this test is to ensure output is handled identically 800;; The point of this test is to ensure output is handled identically
593;; regardless of whether a command handler is summoned. 801;; regardless of whether a command handler is summoned.