summaryrefslogtreecommitdiff
path: root/test/lisp/erc/erc-scenarios-base-chan-modes.el
blob: 3183cd2737030275bde78c07432380c7f910bc3d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
;;; erc-scenarios-base-chan-modes.el --- Channel mode scenarios -*- lexical-binding: t -*-

;; Copyright (C) 2023-2024 Free Software Foundation, Inc.

;; This file is part of GNU Emacs.

;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.

;;; Code:

(require 'ert-x)
(eval-and-compile
  (let ((load-path (cons (ert-resource-directory) load-path)))
    (require 'erc-scenarios-common)))

;; This asserts that a bug present in ERC 5.4+ is now absent.
;; Previously, ERC would attempt to parse a nullary channel mode as if
;; it were a status prefix update, which led to a wrong-type error.
;; This test does not address similar collisions with unary modes,
;; such as "MODE +q foo!*@*", but it should.
(ert-deftest erc-scenarios-base-chan-modes--plus-q ()
  :tags '(:expensive-test)
  (erc-scenarios-common-with-cleanup
      ((erc-scenarios-common-dialog "base/modes")
       (erc-server-flood-penalty 0.1)
       (dumb-server (erc-d-run "localhost" t 'chan-changed))
       (erc-modules (cons 'fill-wrap erc-modules))
       (erc-autojoin-channels-alist '((Libera.Chat "#chan")))
       (expect (erc-d-t-make-expecter)))

    (ert-info ("Connect to Libera.Chat")
      (with-current-buffer (erc :server "127.0.0.1"
                                :port (process-contact dumb-server :service)
                                :nick "tester"
                                :full-name "tester")
        (funcall expect 5 "changed mode")))

    (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
      (should-not erc-channel-key)
      (should-not erc-channel-user-limit)

      (ert-info ("Receive notice that mode has changed")
        (erc-d-t-wait-for 10 (equal erc-channel-modes '("n" "t")))
        (erc-scenarios-common-say "ready before")
        (funcall expect 10 "<Chad> before")
        (funcall expect 10 " has changed mode for #chan to +Qu")
        (erc-d-t-wait-for 10 (equal erc-channel-modes '("Q" "n" "t" "u"))))

      (ert-info ("Key stored locally")
        (erc-scenarios-common-say "ready key")
        (funcall expect 10 "<Chad> doing key")
        (funcall expect 10 " has changed mode for #chan to +k hunter2")
        (should (equal erc-channel-key "hunter2")))

      (ert-info ("Limit stored locally")
        (erc-scenarios-common-say "ready limit")
        (funcall expect 10 "<Chad> doing limit")
        (funcall expect 10 " has changed mode for #chan to +l 3")
        (erc-d-t-wait-for 10 (eql erc-channel-user-limit 3))
        (should (equal erc-channel-modes '("Q" "n" "t" "u"))))

      (ert-info ("Modes removed and local state deletion succeeds")
        (erc-scenarios-common-say "ready drop")
        (funcall expect 10 "<Chad> dropping")
        (funcall expect 10 " has changed mode for #chan to -lu")
        (funcall expect 10 " has changed mode for #chan to -Qk *")
        (erc-d-t-wait-for 10 (equal erc-channel-modes '("n" "t"))))

      (should-not erc-channel-key)
      (should-not erc-channel-user-limit)
      (funcall expect 10 "<Chad> after"))))

;; This asserts proper recognition of nonstandard prefixes advertised
;; via the "PREFIX=" ISUPPORT parameter.  Note that without the IRCv3
;; `multi-prefix' extension, we can't easily sync a user's channel
;; membership status on receipt of a 352/353 by parsing the "flags"
;; parameter because even though servers remember multiple prefixes,
;; they only ever return the one with the highest rank.  For example,
;; if on receipt of a 352, we were to "update" someone we believe to
;; be @+ by changing them to a to @, we'd be guilty of willful
;; munging.  And if they later lose that @, we'd then see them as null
;; when in fact they're still +.  However, we *could* use a single
;; degenerate prefix to "validate" an existing record to ensure
;; correctness of our processing logic, but it's unclear how such a
;; discrepancy ought to be handled beyond asking the user to file a
;; bug.
(ert-deftest erc-scenarios-base-chan-modes--speaker-status ()
  :tags '(:expensive-test)
  (erc-scenarios-common-with-cleanup
      ((erc-scenarios-common-dialog "base/modes")
       (erc-server-flood-penalty 0.1)
       (dumb-server (erc-d-run "localhost" t 'speaker-status))
       (erc-show-speaker-membership-status t)
       (erc-autojoin-channels-alist '(("." "#chan")))
       (expect (erc-d-t-make-expecter)))

    (ert-info ("Connect to foonet")
      (with-current-buffer (erc :server "127.0.0.1"
                                :port (process-contact dumb-server :service)
                                :nick "tester"
                                :user "tester")
        (funcall expect 5 "Here on foonet, we provide services")))

    (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))

      (ert-info ("Prefixes printed correctly in 353")
        (funcall expect 10 "chan: +alice @fsbot -bob !foop"))

      (ert-info ("Speakers honor option `erc-show-speaker-membership-status'")
        (funcall expect 10 "<-bob> alice: Of that which hath")
        (funcall expect 10 "<+alice> Hie you, make haste")
        (funcall expect 10 "<!foop> hi"))

      (ert-info ("Status conferred and rescinded")
        (funcall expect 10 "*** foop (user@netadmin.example.net) has changed ")
        (funcall expect 10 "mode for #chan to +v bob")
        (funcall expect 10 "<+bob> alice: Fair as a text B")
        (funcall expect 10 "<+alice> bob: Even as Apemantus")
        (funcall expect 10 "mode for #chan to -v bob")
        (funcall expect 10 "<-bob> alice: That's the way")
        (funcall expect 10 "<+alice> Give it the beasts"))

      ;; If it had instead overwritten it, our two states would be
      ;; out of sync.  (See comment above.)
      (ert-info ("/WHO output confirms server shadowed V status")
        (erc-scenarios-common-say "/who #chan")
        (funcall expect 10 '(: "bob" (+ " ") "H-"))
        (funcall expect 10 "<-bob> alice: Remains in danger")
        (erc-cmd-QUIT "")))))

;;; erc-scenarios-base-chan-modes.el ends here