diff options
author | F. Jason Park <jp@neverwas.me> | 2021-05-03 05:54:56 -0700 |
---|---|---|
committer | F. Jason Park <jp@neverwas.me> | 2022-06-30 15:03:26 -0700 |
commit | 752e860db4800a26599c4cd6ca2c39ab1909b425 (patch) | |
tree | 8a2dfd5e98c8bfdda3375e5fe9145a4f7eaa8ee1 /test/lisp | |
parent | 9be08ceb314888c7f86bddbec6490e7ead718a88 (diff) | |
download | emacs-752e860db4800a26599c4cd6ca2c39ab1909b425.tar.gz emacs-752e860db4800a26599c4cd6ca2c39ab1909b425.tar.bz2 emacs-752e860db4800a26599c4cd6ca2c39ab1909b425.zip |
Address long-standing ERC buffer-naming issues
* lisp/erc/erc-backend.el (erc-server-connected): Revise doc string.
(erc-server-reconnect, erc-server-JOIN): Reuse original ID param from
the first connection when calling `erc-open'.
(erc-server-NICK): Apply same name generation process used by
`erc-open'; except here, do so for the purpose of "re-nicking".
Update network identifier and maybe buffer names after a user's own
nick changes.
* lisp/erc/erc-networks.el (erc-networks--id, erc-networks--id-fixed,
erc-networks--id-qualifying): Define new set of structs to contain all
info relevant to specifying a unique identifier for a network context.
Add a new variable `erc-networks--id' to store a local reference to a
`erc-networks--id' object, shared among all buffers in a logical
session.
(erc-networks--id-given, erc-networks--id-create,
erc-networks--id-on-connect, erc-networks--id--equal-p,
erc-networks--id-qualifying-init-parts,
erc-networks--id-qualifying-init-symbol,
erc-networks--id-qualifying-grow-id,
erc-networks--id-qualifying-reset-id,
erc-networks--id-qualifying-prefix-length,
erc-networks--id-qualifying-update, erc-networks--id-reload,
erc-networks--id-ensure-comparable, erc-networks--id-sort-buffers):
Add new functions to support management of `erc-networks--id' struct
instances.
(erc-networks--id-sep): New variable for to help when formatting
buffer names.
(erc-obsolete-var): Define new generic context rewriter.
(erc-networks-shrink-ids-and-buffer-names,
erc-networks--refresh-buffer-names,
erc-networks--shrink-ids-and-buffer-names-any): Add functions to
reassess all network IDs and shrink them if necessary along with
affected buffer names. Also add function to rename buffers so that
their names are unique. Register these on all three of ERC's
kill-buffer hooks because an orphaned target buffer is enough to keep
its session alive.
(erc-networks-rename-surviving-target-buffer): Add new function that
renames a target buffer when it becomes the sole bearer of a name
based on a target that has become unique across all sessions and, in
most cases, all networks. IOW, remove the @NETWORK-ID suffix from the
last remaining channel or query buffer after its namesakes have all
been killed off. Register this function with ERC's target-related
kill-buffer hooks.
(erc-networks--examine-targets): Add new utility function that visits
all ERC buffers and runs callbacks when a buffer-name collision is
encountered.
(erc-networks--qualified-sep): Add constant to hold separator between
target and suffix.
(erc-networks--construct-target-buffer-name,
erc-networks--ensure-unique-target-buffer-name,
erc-networks--ensure-unique-server-buffer-name,
erc-networks--maybe-update-buffer-name): Add helpers to support
`erc-networks--reconcile-buffer-names' and friends.
(erc-networks--reconcile-buffer-names): Add new buffer-naming strategy
function and helper for `erc-generate-new-buffer-name' that only run
in target buffers.
(erc-determine-network, erc-networks--determine): Deprecate former and
partially replace with latter, which demotes RPL_ISUPPORT-derived
NETWORK name to fallback in favor of known `erc-networks-alist'
members as part of shift to network-based connection-identity policy.
Return sentinel on failure. Expect `erc-server-announced-name' to be
set, and signal when it's not.
(erc-networks--name-missing-sentinel): Value returned when new
function `erc-networks--determine' fails to find network name. The
rationale for not making this customizable is that the value signifies
the pathological case where a user of an uncommon IRC setup has not
yet set a mapping from announced- to network name. And the chances of
there being multiple unknown networks is low.
(erc-set-network-name, erc-networks--set-name): Deprecate former and
partially replace with latter. Ding with helpful message, and don't
set `erc-network' when network name is not found.
(erc-networks--ensure-announced): Add new fallback function to ensure
`erc-server-announced-name' is set. Register with post-MOTD hooks.
(erc-unset-network-name): Deprecate function unused internally.
(erc-networks--insert-transplanted-content,
erc-networks--reclaim-orphaned-target-buffers,
erc-networks--copy-over-server-buffer-contents,
erc--update-server-identity): Add helpers for
`erc-networks--rename-server-buffer'. The first re-associates all
existing target buffers that ought to be owned by the new server
process. The second grabs buffer text from an old, dead server buffer
before killing it. It then inserts that text above everything in the
current, replacement server buffer. The other two massage the IDs of
related sessions, possibly renaming them as well. They may also
uniquify the current session's network ID.
(erc-networks--init-identity): Add new function to perform one-time
session-related setup. This could be combined with
`erc-set-network-name'.
(erc-networks--rename-server-buffer): Add new function to replace
`erc-unset-network-name' as default `erc-disconnected-hook' member;
renames server buffers once network is discovered; added to/removed
from `erc-after-connect' hook on `erc-networks' minor mode.
(erc-networks--bouncer-targets): Add constant to hold target symbols
of well known bouncer-configuration bots.
(erc-networks-on-MOTD-end): Add primary network-context handler to run
on 376/422 functions, just before logical connection is officially
established.
(erc-networks-enable, erc-networks-mode): Register main network-setup
handler with 376/422 hooks.
* lisp/erc/erc.el (erc-rename-buffers): Change this option's default
to t, remove the only instance where it's actually used, and make it
an obsolete variable.
(erc-reuse-buffers): Make this an obsolete variable, but take pains to
ensure its pre-28.1 behavior is preserved. That is, undo the
regression involving unwanted automatic reassociation of channel
buffers during joins, which arrived in ERC 5.4 and effectively
inverted the meaning of this variable, when nil, for channel buffers,
all without accompanying documentation or announcement.
(erc-generate-new-buffer-name): Replace current policy of appending a
slash and the invocation host name. Favor instead temporary names for
server buffers and network-based uniquifying suffixes for channels and
query buffers. Fall back to the TCP host:port<n> convention when
necessary. Accept additional optional params after the others.
(erc-get-buffer-create): Don't generate a new name when reconnecting,
just return the same buffer. `erc-open' starts from a clean slate
anyway, so this just keeps things simple. Also add optional params.
(erc-open): Add new ID param to for a network identifier explicitly
passed to an entry-point command. This is stored in the `given' slot
of the `erc-network--id' object. Also initialize the latter in new
connections and otherwise copy it over. As part of the push to recast
erc-networks.el as an essential library, set `erc-network' explicitly,
when known, rather than via hooks.
(erc, erc-tls): Add new ID keyword parameter and pass it to
`erc-open'.
(erc-log-irc-protocol): Use `erc--network-id' instead of the function
`erc-network' to determine preferred peer name.
(erc-format-target-and/or-network): This is called frequently from
mode-line updates, so renaming buffers here is not ideal. Instead, do
so in `erc-networks--rename-server-buffer'.
(erc-kill-server-hook): Add `erc-networks-shrink-ids-and-buffer-names'
as default member.
(erc-kill-channel-hook, erc-kill-buffer-hook): Add
`erc-networks-shrink-ids-and-buffer-names' and
`erc-networks-rename-surviving-target-buffer' as default member.
* test/lisp/erc/erc-tests.el (erc-log-irc-protocol): Use network-ID
focused internal API.
* test/lisp/erc/erc-networks-tests.el: Add new file that includes
tests for the above network-ID focused functions.
See bug#48598 for background on all of the above.
Diffstat (limited to 'test/lisp')
-rw-r--r-- | test/lisp/erc/erc-networks-tests.el | 1707 | ||||
-rw-r--r-- | test/lisp/erc/erc-tests.el | 3 |
2 files changed, 1709 insertions, 1 deletions
diff --git a/test/lisp/erc/erc-networks-tests.el b/test/lisp/erc/erc-networks-tests.el new file mode 100644 index 00000000000..dcda04692ec --- /dev/null +++ b/test/lisp/erc/erc-networks-tests.el @@ -0,0 +1,1707 @@ +;;; erc-networks-tests.el --- Tests for erc-networks. -*- lexical-binding:t -*- + +;; Copyright (C) 2020-2022 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) ; cl-lib +(require 'erc-networks) + +(defun erc-networks-tests--create-dead-proc (&optional buf) + (let ((p (start-process "true" (or buf (current-buffer)) "true"))) + (while (process-live-p p) (sit-for 0.1)) + p)) + +(defun erc-networks-tests--create-live-proc (&optional buf) + (let ((proc (start-process "sleep" (or buf (current-buffer)) "sleep" "1"))) + (set-process-query-on-exit-flag proc nil) + proc)) + +;; When we drop 27, call `get-buffer-create with INHIBIT-BUFFER-HOOKS. +(defun erc-networks-tests--clean-bufs () + (let (erc-kill-channel-hook + erc-kill-server-hook + erc-kill-buffer-hook) + (dolist (buf (erc-buffer-list)) + (kill-buffer buf)))) + +(defun erc-networks-tests--bufnames (prefix) + (let* ((case-fold-search) + (pred (lambda (b) (string-prefix-p prefix (buffer-name b)))) + (prefixed (seq-filter pred (buffer-list)))) + (sort (mapcar #'buffer-name prefixed) #'string<))) + +(ert-deftest erc-networks--id () + (cl-letf (((symbol-function 'float-time) + (lambda () 0.0))) + + ;; Fixed + (should (equal (erc-networks--id-fixed-create 'foo) + (make-erc-networks--id-fixed :ts (float-time) + :symbol 'foo))) + + ;; Eliding + (let* ((erc-network 'FooNet) + (erc-server-current-nick "Joe") + (identity (erc-networks--id-create nil))) + + (should (equal identity #s(erc-networks--id-qualifying + 0.0 FooNet [FooNet "joe"] 1))) + (should (equal (erc-networks--id-qualifying-grow-id identity) + 'FooNet/joe)) + (should (equal identity #s(erc-networks--id-qualifying + 0.0 FooNet/joe [FooNet "joe"] 2))) + (should-not (erc-networks--id-qualifying-grow-id identity)) + (should (equal identity #s(erc-networks--id-qualifying + 0.0 FooNet/joe [FooNet "joe"] 2)))) + + ;; Compat + (with-current-buffer (get-buffer-create "fake.chat") + (with-suppressed-warnings ((obsolete erc-rename-buffers)) + (let (erc-rename-buffers) + (should (equal (erc-networks--id-create nil) + (make-erc-networks--id-fixed :ts (float-time) + :symbol 'fake.chat))))) + (kill-buffer)))) + +(ert-deftest erc-networks--id-create () + (cl-letf (((symbol-function 'float-time) + (lambda () 0.0))) + + (should (equal (erc-networks--id-create 'foo) + (make-erc-networks--id-fixed :ts (float-time) + :symbol 'foo))) + (should (equal (erc-networks--id-create "foo") + (make-erc-networks--id-fixed :ts (float-time) + :symbol 'foo))) + (should (equal (erc-networks--id-create [h i]) + (make-erc-networks--id-fixed :ts (float-time) + :symbol (quote \[h\ \i\])))) + + (with-current-buffer (get-buffer-create "foo") + (let ((expected (make-erc-networks--id-fixed :ts (float-time) + :symbol 'foo))) + (with-suppressed-warnings ((obsolete erc-rename-buffers)) + (let (erc-rename-buffers) + (should (equal (erc-networks--id-create nil) expected)))) + (with-suppressed-warnings ((obsolete erc-reuse-buffers)) + (let (erc-reuse-buffers) + (should (equal (erc-networks--id-create nil) expected)) + (should (equal (erc-networks--id-create 'bar) expected))))) + (kill-buffer)))) + +(ert-deftest erc-networks--id-qualifying-prefix-length () + (should-not (erc-networks--id-qualifying-prefix-length + (make-erc-networks--id-qualifying) + (make-erc-networks--id-qualifying))) + + (should-not (erc-networks--id-qualifying-prefix-length + (make-erc-networks--id-qualifying :parts [1 2]) + (make-erc-networks--id-qualifying :parts [2 3]))) + + (should (= 1 (erc-networks--id-qualifying-prefix-length + (make-erc-networks--id-qualifying :parts [1]) + (make-erc-networks--id-qualifying :parts [1 2])))) + + (should (= 1 (erc-networks--id-qualifying-prefix-length + (make-erc-networks--id-qualifying :parts [1 2]) + (make-erc-networks--id-qualifying :parts [1 3])))) + + (should (= 2 (erc-networks--id-qualifying-prefix-length + (make-erc-networks--id-qualifying :parts [1 2]) + (make-erc-networks--id-qualifying :parts [1 2])))) + + (should (= 1 (erc-networks--id-qualifying-prefix-length + (make-erc-networks--id-qualifying :parts ["1"]) + (make-erc-networks--id-qualifying :parts ["1"]))))) + +(ert-deftest erc-networks--id-sort-buffers () + (let (oldest middle newest) + + (with-temp-buffer + (setq erc-networks--id (erc-networks--id-fixed-create 'oldest) + oldest (current-buffer)) + + (with-temp-buffer + (setq erc-networks--id (erc-networks--id-fixed-create 'middle) + middle (current-buffer)) + + (with-temp-buffer + (setq erc-networks--id (erc-networks--id-fixed-create 'newest) + newest (current-buffer)) + + (should (equal (erc-networks--id-sort-buffers + (list oldest newest middle)) + (list newest middle oldest)))))))) + +(ert-deftest erc-networks-rename-surviving-target-buffer--channel () + (should (memq #'erc-networks-rename-surviving-target-buffer + erc-kill-channel-hook)) + + (let ((chan-foonet-buffer (get-buffer-create "#chan@foonet"))) + + (with-current-buffer chan-foonet-buffer + (erc-mode) + (setq erc-networks--id (make-erc-networks--id-qualifying + :parts [foonet "bob"] :len 1) + erc--target (erc--target-from-string "#chan"))) + + (with-current-buffer (get-buffer-create "#chan@barnet") + (erc-mode) + (setq erc-networks--id (make-erc-networks--id-qualifying + :parts [barnet "bob"] :len 1) + erc--target (erc--target-from-string "#chan"))) + + (kill-buffer "#chan@barnet") + (should (equal (erc-networks-tests--bufnames "#chan") '("#chan"))) + (should (eq chan-foonet-buffer (get-buffer "#chan")))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks-rename-surviving-target-buffer--query () + (should (memq #'erc-networks-rename-surviving-target-buffer + erc-kill-buffer-hook)) + + (let ((bob-foonet (get-buffer-create "bob@foonet"))) + + (with-current-buffer bob-foonet + (erc-mode) + (setq erc-networks--id (make-erc-networks--id-qualifying + :parts [foonet "bob"] :len 1) + erc--target (erc--target-from-string "bob"))) + + (with-current-buffer (get-buffer-create "bob@barnet") + (erc-mode) + (setq erc-networks--id (make-erc-networks--id-qualifying + :parts [barnet "bob"] :len 1) + erc--target (erc--target-from-string "bob"))) + + (kill-buffer "bob@barnet") + (should (equal (erc-networks-tests--bufnames "bob") '("bob"))) + (should (eq bob-foonet (get-buffer "bob")))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks-rename-surviving-target-buffer--multi () + + (ert-info ("Multiple leftover channels untouched") + (with-current-buffer (get-buffer-create "#chan@foonet") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan"))) + (with-current-buffer (get-buffer-create "#chan@barnet") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan"))) + (with-current-buffer (get-buffer-create "#chan@baznet") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan"))) + (kill-buffer "#chan@baznet") + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@barnet" "#chan@foonet"))) + (erc-networks-tests--clean-bufs)) + + (ert-info ("Multiple leftover queries untouched") + (with-current-buffer (get-buffer-create "bob@foonet") + (erc-mode) + (setq erc--target (erc--target-from-string "bob"))) + (with-current-buffer (get-buffer-create "bob@barnet") + (erc-mode) + (setq erc--target (erc--target-from-string "bob"))) + (with-current-buffer (get-buffer-create "bob@baznet") + (erc-mode) + (setq erc--target (erc--target-from-string "bob"))) + (kill-buffer "bob@baznet") + (should (equal (erc-networks-tests--bufnames "bob") + '("bob@barnet" "bob@foonet"))) + (erc-networks-tests--clean-bufs))) + +;; As of May 2022, this "shrink" stuff runs whenever an ERC buffer is +;; killed because `erc-networks-shrink-ids-and-buffer-names' is a +;; default member of all three erc-kill-* functions. + +;; Note: this overlaps a fair bit with the "hook" variants, i.e., +;; `erc-networks--shrink-ids-and-buffer-names--hook-outstanding-*' If +;; this ever fails, just delete this and fix those. But please copy +;; over and adapt the comments first. + +(ert-deftest erc-networks--shrink-ids-and-buffer-names--perform-outstanding () + ;; While some buffer #a@barnet/dummy is being killed, its display ID + ;; is not collapsed because collisions still exist. + ;; + ;; Note that we don't have to set `erc-server-connected' because + ;; this function is intentionally connectivity agnostic. + (with-current-buffer (get-buffer-create "foonet/tester") + (erc-mode) + (setq erc-server-current-nick "tester" ; Always set (`erc-open') + ;; Set when transport connected + erc-server-process (erc-networks-tests--create-live-proc) + ;; Both set just before IRC (logically) connected (post MOTD) + erc-network 'foonet + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/tester + :parts [foonet "tester"] + :len 2))) ; is/was a plain foonet collision + + ;; Presumably, some server buffer named foonet/dummy was just + ;; killed, hence the length 2 display ID. + + ;; A target buffer for chan #a exists for foonet/tester. The + ;; precise form of its name should not affect shrinking. + (with-current-buffer (get-buffer-create + (elt ["#a" "#a@foonet" "#a@foonet/tester"] (random 3))) + (erc-mode) + (setq erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "foonet/tester")) + erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "foonet/tester")) + erc--target (erc--target-from-string "#a"))) + + ;; Another network context exists (so we have buffers to iterate + ;; over), and it's also part of a collision group. + (with-current-buffer (get-buffer-create "barnet/tester") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'barnet/tester + :parts [barnet "tester"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer (get-buffer-create "barnet/dummy") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "dummy" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'barnet/dummy + :parts [barnet "dummy"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + ;; The buffer being killed is not part of the foonet collision + ;; group, which contains one display ID eligible for shrinkage. + (with-current-buffer (get-buffer-create + (elt ["#a@barnet" "#a@barnet/tester"] (random 2))) + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "barnet/tester")) + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "barnet/tester")) + erc--target (erc--target-from-string "#a"))) + + (with-temp-buffer ; doesn't matter what the current buffer is + (setq erc-networks--id (make-erc-networks--id-qualifying)) ; mock + (erc-networks--shrink-ids-and-buffer-names)) + + (should (equal (mapcar #'buffer-name (erc-buffer-list)) + '("foonet" ; shrunk + "#a@foonet" ; shrunk + "barnet/tester" + "barnet/dummy" + "#a@barnet/tester"))) + + (erc-networks-tests--clean-bufs)) + +;; This likewise overlaps with the "hook" variants below. If this +;; should ever fail, just delete it and optionally fix those. + +(ert-deftest erc-networks--shrink-ids-and-buffer-names--perform-collapse () + ;; This is similar to the "outstanding" variant above, but both + ;; groups are eligible for renaming, which is abnormal but possible + ;; when recovering from some mishap. + (with-current-buffer (get-buffer-create "foonet/tester") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/tester + :parts [foonet "tester"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer + (get-buffer-create (elt ["#a" "#a@foonet/tester"] (random 2))) + (erc-mode) + (setq erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "foonet/tester")) + erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "foonet/tester")) + erc--target (erc--target-from-string "#a"))) + + (with-current-buffer (get-buffer-create "barnet/tester") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'barnet/tester + :parts [barnet "tester"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer + (get-buffer-create (elt ["#b" "#b@foonet/tester"] (random 2))) + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "barnet/tester")) + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "barnet/tester")) + erc--target (erc--target-from-string "#b"))) + + (with-temp-buffer + (setq erc-networks--id (make-erc-networks--id-qualifying)) + (erc-networks--shrink-ids-and-buffer-names)) + + (should (equal (mapcar #'buffer-name (erc-buffer-list)) + '("foonet" "#a" "barnet" "#b"))) + + (erc-networks-tests--clean-bufs)) + +(defun erc-networks--shrink-ids-and-buffer-names--hook-outstanding-common () + + (with-current-buffer (get-buffer-create "foonet/tester") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/tester + :parts [foonet "tester"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer (get-buffer-create "#a@foonet/tester") + (erc-mode) + (setq erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "foonet/tester")) + erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "foonet/tester")) + erc--target (erc--target-from-string "#a"))) + + (with-current-buffer (get-buffer-create "barnet/tester") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'barnet/tester + :parts [barnet "tester"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer (get-buffer-create "barnet/dummy") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "dummy" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'barnet/dummy + :parts [barnet "dummy"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer (get-buffer-create "#a@barnet/tester") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "barnet/tester")) + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "barnet/tester")) + erc--target (erc--target-from-string "#a")))) + +(ert-deftest erc-networks--shrink-ids-and-buffer-names--hook-outstanding-srv () + (erc-networks--shrink-ids-and-buffer-names--hook-outstanding-common) + (with-current-buffer (get-buffer-create "foonet/dummy") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "dummy" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/dummy + :parts [foonet "dummy"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc)) + (kill-buffer)) + + (should (equal (mapcar #'buffer-name (erc-buffer-list)) + '("foonet" + "#a@foonet" + "barnet/tester" + "barnet/dummy" + "#a@barnet/tester"))) + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--shrink-ids-and-buffer-names--hook-outstanding-tgt () + (erc-networks--shrink-ids-and-buffer-names--hook-outstanding-common) + (with-current-buffer (get-buffer-create "#a@foonet/dummy") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "dummy" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/dummy + :parts [foonet "dummy"] + :len 2) + erc--target (erc--target-from-string "#a") + erc-server-process (with-temp-buffer + (erc-networks-tests--create-dead-proc)))) + + (with-current-buffer "#a@foonet/dummy" (kill-buffer)) + + ;; Identical to *-server variant above + (should (equal (mapcar #'buffer-name (erc-buffer-list)) + '("foonet" + "#a@foonet" + "barnet/tester" + "barnet/dummy" + "#a@barnet/tester"))) + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks-rename-surviving-target-buffer--shrink () + (erc-networks--shrink-ids-and-buffer-names--hook-outstanding-common) + + ;; This buffer isn't "#a@foonet" (yet) because the shrink-ids hook + ;; hasn't run. However, when it's the rename hook runs, its network + ;; id *is* "foonet", not "foonet/tester". + (with-current-buffer "#a@foonet/tester" (kill-buffer)) + + (should (equal (mapcar #'buffer-name (erc-buffer-list)) + '("foonet" + "barnet/tester" + "barnet/dummy" + "#a"))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--shrink-ids-and-buffer-names--server () + + (with-current-buffer (get-buffer-create "foonet/tester") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/tester + :parts [foonet "tester"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer (get-buffer-create "foonet/dummy") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "dummy" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/dummy + :parts [foonet "dummy"] + :len 2) + erc-server-process (erc-networks-tests--create-dead-proc)) + (kill-buffer)) + + (should (equal (mapcar #'buffer-name (erc-buffer-list)) '("foonet"))) + + (erc-networks-tests--clean-bufs)) + +(defun erc-networks--shrink-ids-and-buffer-names--hook-collapse (check) + + (with-current-buffer (get-buffer-create "foonet/tester") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/tester + :parts [foonet "tester"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer (get-buffer-create "#a@foonet/tester") + (erc-mode) + (setq erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "foonet/tester")) + erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "foonet/tester")) + erc--target (erc--target-from-string "#a"))) + + (with-current-buffer (get-buffer-create "barnet/tester") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'barnet/tester + :parts [barnet "tester"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer (get-buffer-create "#b@foonet/tester") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "barnet/tester")) + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "barnet/tester")) + erc--target (erc--target-from-string "#b"))) + + (funcall check) + + (should (equal (mapcar #'buffer-name (erc-buffer-list)) + '("foonet" "#a" "barnet" "#b"))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--shrink-ids-and-buffer-names--hook-collapse-server () + (erc-networks--shrink-ids-and-buffer-names--hook-collapse + (lambda () + (with-current-buffer (get-buffer-create "foonet/dummy") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "dummy" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/dummy + :parts [foonet "dummy"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc)) + (kill-buffer))))) + +(ert-deftest erc-networks--shrink-ids-and-buffer-names--hook-collapse-target () + (erc-networks--shrink-ids-and-buffer-names--hook-collapse + (lambda () + (with-current-buffer (get-buffer-create "#a@foonet/dummy") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "dummy" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/dummy + :parts [foonet "dummy"] + :len 2) + ;; `erc-kill-buffer-function' uses legacy target detection + ;; but falls back on buffer name, so no need for: + ;; + ;; erc-default-recipients '("#a") + ;; + erc--target (erc--target-from-string "#a") + erc-server-process (with-temp-buffer + (erc-networks-tests--create-dead-proc))) + (kill-buffer))))) + +;; FIXME this test is old and may describe impossible states: +;; leftover identities being qual-equal but not eq (implies +;; `erc-networks--reclaim-orphaned-target-buffers' is somehow broken). +;; +;; Otherwise, the point of this test is to show that server process +;; identity does not impact the hunt for duplicates. + +(defun erc-tests--prep-erc-networks--reconcile-buffer-names--duplicates (start) + + (with-current-buffer (get-buffer-create "foonet") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create nil) + erc-server-process (funcall start))) + + (with-current-buffer (get-buffer-create "#chan") ; prior session + (erc-mode) + (setq erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "foonet")) + erc--target (erc--target-from-string "#chan") + erc-networks--id (erc-networks--id-create nil))) + + (ert-info ("Conflicts not recognized as ERC buffers and not renamed") + (get-buffer-create "#chan@foonet") + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan" "#chan@foonet")))) + + ;; These are dupes (not "collisions") + + (with-current-buffer "#chan@foonet" ; same proc + (erc-mode) + (setq erc--target (erc--target-from-string "#chan") + erc-network 'foonet + erc-server-current-nick "tester" + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "foonet")) + erc-networks--id (erc-networks--id-create nil))) + + (with-current-buffer (get-buffer-create "#chan@foonet<dead>") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan") + erc-server-process (erc-networks-tests--create-dead-proc) + erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create nil))) + + (with-current-buffer (get-buffer-create "#chan@foonet<live>") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan") + erc-server-process (erc-networks-tests--create-live-proc) + erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create nil))) + + (let ((created (list (get-buffer "#chan@foonet<live>") + (get-buffer "#chan@foonet<dead>") + (get-buffer "#chan@foonet")))) + + (with-current-buffer "foonet" + (should (string= (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id) + "#chan"))) + + (ert-info ("All buffers considered dupes renamed") + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan" "#chan<2>" "#chan<3>" "#chan<4>")))) + + (ert-info ("All buffers renamed from newest to oldest") + (should (equal created (list (get-buffer "#chan<2>") + (get-buffer "#chan<3>") + (get-buffer "#chan<4>")))))) + + (erc-networks-tests--clean-bufs)) + +(defun erc-tests--prep-erc-networks--reconcile-buffer-names--dupes-given (go) + + ;; The connection's network is discovered before target buffers are + ;; created. This shows that the network doesn't matter when only + ;; "given" IDs are present. + (with-current-buffer (get-buffer-create "oofnet") + (erc-mode) + (setq erc-networks--id (erc-networks--id-create 'oofnet) + erc-network 'foonet + erc-server-current-nick "tester" + erc-server-process (funcall go))) + + (with-current-buffer (get-buffer-create "#chan") ; prior session + (erc-mode) + (setq erc-networks--id (erc-networks--id-create 'oofnet) + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "oofnet")) + erc--target (erc--target-from-string "#chan"))) + + (with-current-buffer (get-buffer-create "#chan@oofnet") ;dupe/not collision + (erc-mode) + (setq erc-networks--id (erc-networks--id-create 'oofnet) + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "oofnet")) + erc--target (erc--target-from-string "#chan"))) + + (with-current-buffer "oofnet" + (should (string= (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id) + "#chan"))) + + (ert-info ("All buffers matching target and network renamed") + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan" "#chan<2>")))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--reconcile-buffer-names--duplicates () + (ert-info ("Process live, no error") + (erc-tests--prep-erc-networks--reconcile-buffer-names--duplicates + #'erc-networks-tests--create-live-proc)) + + (ert-info ("Process live, no error, given ID") + (erc-tests--prep-erc-networks--reconcile-buffer-names--dupes-given + #'erc-networks-tests--create-live-proc)) + + (ert-info ("Process dead") + (erc-tests--prep-erc-networks--reconcile-buffer-names--duplicates + #'erc-networks-tests--create-dead-proc)) + + (ert-info ("Process dead, given ID") + (erc-tests--prep-erc-networks--reconcile-buffer-names--dupes-given + #'erc-networks-tests--create-dead-proc))) + +(defun erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf (check) + (let ((foonet-proc (with-temp-buffer + (erc-networks-tests--create-dead-proc)))) + (with-current-buffer (get-buffer-create "barnet") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create nil) + erc-server-process (erc-networks-tests--create-dead-proc))) + + ;; Different proc and not "qual-equal" (different elts) + (with-current-buffer (get-buffer-create "#chan") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create nil) + erc--target (erc--target-from-string "#chan") + erc-server-process foonet-proc)) + (funcall check) + (erc-networks-tests--clean-bufs))) + +(ert-deftest erc-networks--reconcile-buffer-names--no-server-buf () + (ert-info ("Existing #chan buffer respected") + (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf + (lambda () + (with-current-buffer "barnet" + (should (string= (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id) + "#chan@barnet"))) + (ert-info ("Existing #chan buffer found and renamed") + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@foonet"))))))) + + (ert-info ("Existing #chan buffer") + (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf + (lambda () + (with-current-buffer (get-buffer-create "foonet") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create nil) + erc-server-process (erc-networks-tests--create-dead-proc)) + (should (string= (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id) + "#chan"))) + (ert-info ("Nothing renamed") + (should (equal (erc-networks-tests--bufnames "#chan") '("#chan"))))))) + + (ert-info ("Existing #chan@foonet and #chan@barnet buffers") + (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf + (lambda () + (with-current-buffer "#chan" + (rename-buffer "#chan@foonet")) + (should-not (get-buffer "#chan@barnet")) + (with-current-buffer (get-buffer-create "#chan@barnet") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan") + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "barnet")) + erc-networks--id (erc-networks--id-create nil))) + (with-current-buffer (get-buffer-create "foonet") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-server-process (erc-networks-tests--create-live-proc) + erc-networks--id (erc-networks--id-create nil)) + (set-process-query-on-exit-flag erc-server-process nil) + (should (string= (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id) + "#chan@foonet"))) + (ert-info ("Nothing renamed") + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@barnet" "#chan@foonet")))))))) + +(defun erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf-given + (check) + (let ((oofnet-proc (with-temp-buffer + (erc-networks-tests--create-dead-proc)))) + + (with-current-buffer (get-buffer-create "rabnet") + (erc-mode) + ;; Again, given name preempts network lookup (unrealistic but + ;; highlights priorities) + (setq erc-networks--id (erc-networks--id-create 'rabnet) + erc-network 'barnet + erc-server-current-nick "tester" + erc-server-process (erc-networks-tests--create-dead-proc))) + + ;; Identity is not "qual-equal" to above + (with-current-buffer (get-buffer-create "#chan") + (erc-mode) + (setq erc-networks--id (erc-networks--id-create 'oofnet) + erc-network 'foonet + erc--target (erc--target-from-string "#chan") + erc-server-process oofnet-proc)) + (funcall check) + (erc-networks-tests--clean-bufs))) + +(ert-deftest erc-networks--reconcile-buffer-names--no-server-buf-given () + + (ert-info ("Existing #chan buffer respected") + (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf-given + (lambda () + (with-current-buffer "rabnet" + (should (string= (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id) + "#chan@rabnet"))) + + (ert-info ("Existing #chan buffer found and renamed") + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@oofnet"))))))) + + (ert-info ("Existing #chan@oofnet and #chan@rabnet buffers") + (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf-given + (lambda () + ;; #chan has already been uniquified (but not grown) + (with-current-buffer "#chan" (rename-buffer "#chan@oofnet")) + (should-not (get-buffer "#chan@rabnet")) + + (with-current-buffer (get-buffer-create "#chan@rabnet") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan") + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "rabnet")) + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "rabnet")))) + + (with-current-buffer (get-buffer-create "oofnet") + (erc-mode) + (setq erc-network 'oofnet + erc-server-current-nick "tester" + erc-server-process (erc-networks-tests--create-live-proc) + erc-networks--id (erc-networks--id-create 'oofnet)) ; given + (set-process-query-on-exit-flag erc-server-process nil) + (should (string= (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id) + "#chan@oofnet"))) + + (ert-info ("Nothing renamed") + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@oofnet" "#chan@rabnet")))))))) + +;; This shows a corner case where a user explicitly assigns a "given" +;; ID via `erc-tls' but later connects again without one. It would +;; actually probably be better if the given identity were to win and +;; the derived one got an <n>-suffix. +;; +;; If we just compared net identities, the two would match, but they +;; don't here because one has a given name and the other a +;; discovered/assembled one; so they are *not* qual-equal. +(ert-deftest erc-networks--reconcile-buffer-names--no-srv-buf-given-mismatch () + ;; Existing #chan buffer *not* respected + (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf-given + (lambda () + (with-current-buffer (get-buffer-create "oofnet") + (erc-mode) + (setq erc-network 'oofnet + erc-server-current-nick "tester" + erc-server-process (erc-networks-tests--create-dead-proc) + erc-networks--id (erc-networks--id-create nil)) ; derived + (should (string= (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id) + "#chan@oofnet"))) + + (ert-info ("Collision renamed but not grown (because it's a given)") + ;; Original chan uniquified and moved out of the way + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@oofnet<2>"))))))) + +(defun erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net (check) + + (with-current-buffer (get-buffer-create "foonet") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-server-process (erc-networks-tests--create-dead-proc) + erc-networks--id (erc-networks--id-create nil))) ; derived + + (with-current-buffer (get-buffer-create "barnet") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-server-process (erc-networks-tests--create-dead-proc) + erc-networks--id (erc-networks--id-create nil))) ; derived + + (with-current-buffer + (get-buffer-create (elt ["#chan" "#chan@foonet"] (random 2))) + (erc-mode) + (setq erc--target (erc--target-from-string "#chan")) + (cl-multiple-value-setq (erc-server-process erc-networks--id) + (with-current-buffer "foonet" + (list erc-server-process erc-networks--id)))) + + (with-current-buffer (get-buffer-create "#chan@barnet") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan")) + (cl-multiple-value-setq (erc-server-process erc-networks--id) + (with-current-buffer "barnet" + (list erc-server-process erc-networks--id)))) + + (funcall check) + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--reconcile-buffer-names--multi-net () + (ert-info ("Same network rename") + (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net + (lambda () + (with-current-buffer "foonet" + (let ((result (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id))) + (should (string= result "#chan@foonet")))) + + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@barnet" "#chan@foonet")))))) + + (ert-info ("Same network keep name") + (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net + (lambda () + (with-current-buffer "barnet" + (let ((result (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id))) + (should (string= result "#chan@barnet")))) + + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@barnet" "#chan@foonet"))))))) + +(defun erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-given + (check) + + (with-current-buffer (get-buffer-create "oofnet") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create 'oofnet) ; one given + erc-server-process (erc-networks-tests--create-dead-proc))) + + (with-current-buffer (get-buffer-create "rabnet") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create 'rabnet) ; another given + erc-server-process (erc-networks-tests--create-dead-proc))) + + (with-current-buffer (get-buffer-create (elt ["chan" "#chan@oofnet"] + (random 2))) + (erc-mode) + (setq erc--target (erc--target-from-string "#chan")) + (cl-multiple-value-setq (erc-server-process erc-networks--id) + (with-current-buffer "oofnet" + (list erc-server-process erc-networks--id)))) + + (with-current-buffer (get-buffer-create "#chan@barnet") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan")) + (cl-multiple-value-setq (erc-server-process erc-networks--id) + (with-current-buffer "rabnet" + (list erc-server-process erc-networks--id)))) + + (funcall check) + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--reconcile-buffer-names--multi-net-given () + (ert-info ("Same network rename") + (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-given + (lambda () + (with-current-buffer "oofnet" + (let ((result (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id))) + (should (string= result "#chan@oofnet")))) + + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@oofnet" "#chan@rabnet")))))) + + (ert-info ("Same network keep name") + (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-given + (lambda () + (with-current-buffer "rabnet" + (let ((result (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id))) + (should (string= result "#chan@rabnet")))) + + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@oofnet" "#chan@rabnet"))))))) + +(defun erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-mixed + (check) + + (with-current-buffer (get-buffer-create "foonet") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create nil) ; one derived + erc-server-process (erc-networks-tests--create-dead-proc))) + + (with-current-buffer (get-buffer-create "my-conn") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create 'my-conn) ; one given + erc-server-process (erc-networks-tests--create-dead-proc))) + + (with-current-buffer (get-buffer-create (elt ["#chan" "#chan@foonet"] + (random 2))) + (erc-mode) + (setq erc--target (erc--target-from-string "#chan")) + (cl-multiple-value-setq (erc-server-process erc-networks--id) + (with-current-buffer "foonet" + (list erc-server-process erc-networks--id)))) + + (with-current-buffer (get-buffer-create "#chan@my-conn") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan")) + (cl-multiple-value-setq (erc-server-process erc-networks--id) + (with-current-buffer "my-conn" + (list erc-server-process erc-networks--id)))) + + (funcall check) + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--reconcile-buffer-names--multi-net-existing () + + (ert-info ("Buf name derived from network") + (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-mixed + (lambda () + (with-current-buffer "foonet" + (let ((result (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id))) + (should (string= result "#chan@foonet")))) + + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@foonet" "#chan@my-conn")))))) + + (ert-info ("Buf name given") + (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-mixed + (lambda () + (with-current-buffer "my-conn" + (let ((result (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id))) + (should (string= result "#chan@my-conn")))) + + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@foonet" "#chan@my-conn"))))))) + +(ert-deftest erc-networks--reconcile-buffer-names--multi-net-suffixed () + ;; Two networks, same channel. One network has two connections. + ;; When the same channel is joined on the latter under a different + ;; nick, all buffer names involving that network are suffixed with + ;; the network identity. + + (with-current-buffer (get-buffer-create "foonet/bob") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "bob" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/bob + :parts [foonet "bob"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer (get-buffer-create + (elt ["#chan@foonet" "#chan@foonet/bob"] (random 2))) + (erc-mode) + (setq erc--target (erc--target-from-string "#chan") + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "foonet/bob")) + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "foonet/bob")))) + + (with-current-buffer (get-buffer-create "barnet") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick (elt ["alice" "bob"] (random 2)) + erc-networks--id (erc-networks--id-create 'barnet) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer (get-buffer-create "#chan@barnet") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan") + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "barnet")) + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "barnet")))) + + (with-current-buffer (get-buffer-create "foonet/alice") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "alice" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/alice + :parts [foonet "alice"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer "foonet/alice" + (let ((result (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id))) + (should (string= result "#chan@foonet/alice")))) + + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@barnet" "#chan@foonet/bob"))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--reconcile-buffer-names--local () + (with-current-buffer (get-buffer-create "DALnet") + (erc-mode) + (setq erc-network 'DALnet + erc-server-announced-name "elysium.ga.us.dal.net" + erc-server-process (erc-networks-tests--create-dead-proc) + erc--isupport-params (make-hash-table) + erc-networks--id (erc-networks--id-create nil)) + (puthash 'CHANTYPES '("&#") erc--isupport-params)) + + (ert-info ("Local chan buffer from older, disconnected identity") + (with-current-buffer (get-buffer-create "&chan") + (erc-mode) + ;; Cheat here because localp is determined on identity init + (setq erc--target (with-current-buffer "DALnet" + (erc--target-from-string "&chan")) + erc-network 'DALnet + erc-server-announced-name "twisted.ma.us.dal.net" + erc-server-process (erc-networks-tests--create-dead-proc) + erc-networks--id (erc-networks--id-create nil)))) + + (ert-info ("Local channels renamed using network server names") + (with-current-buffer "DALnet" + (let ((result (erc-networks--reconcile-buffer-names + (erc--target-from-string "&chan") erc-networks--id))) + (should (string= result "&chan@elysium.ga.us.dal.net"))))) + + (should (get-buffer "&chan@twisted.ma.us.dal.net")) + (should-not (get-buffer "&chan")) + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--set-name () + (with-current-buffer (get-buffer-create "localhost:6667") + (let (erc-server-announced-name + (erc--isupport-params (make-hash-table)) + erc-network + calls) + (erc-mode) + + (cl-letf (((symbol-function 'erc-display-line) + (lambda (&rest r) (push r calls)))) + + (ert-info ("Signals when `erc-server-announced-name' unset") + (should-error (erc-networks--set-name nil (make-erc-response))) + (should-not calls)) + + (ert-info ("Signals when table empty and NETWORK param unset") + (setq erc-server-announced-name "irc.fake.gnu.org") + (let ((err (should-error (erc-networks--set-name + nil (make-erc-response))))) + (should (string-match-p "failed" (cadr err))) + (should (eq (car err) 'error))) + (should (string-match-p "*** Failed" (car (pop calls))))))) + + (erc-networks-tests--clean-bufs))) + +(ert-deftest erc-networks--ensure-announced () + (with-current-buffer (get-buffer-create "localhost:6667") + (should (local-variable-if-set-p 'erc-server-announced-name)) + (let (erc-insert-modify-hook + (erc-server-process (erc-networks-tests--create-live-proc)) + (parsed (make-erc-response + :unparsed ":irc.barnet.org 422 tester :MOTD File is missing" + :sender "irc.barnet.org" + :command "422" + :command-args '("tester" "MOTD File is missing") + :contents "MOTD File is missing"))) + + (erc-mode) ; boilerplate displayable start (needs `erc-server-process') + (insert "\n\n") + (setq erc-input-marker (make-marker) erc-insert-marker (make-marker)) + (set-marker erc-insert-marker (point-max)) + (erc-display-prompt) ; boilerplate displayable end + + (erc-networks--ensure-announced erc-server-process parsed) + (goto-char (point-min)) + (search-forward "Failed") + (should (string= erc-server-announced-name "irc.barnet.org"))) + (when noninteractive (kill-buffer)))) + +(ert-deftest erc-networks--rename-server-buffer--no-existing--orphan () + (with-current-buffer (get-buffer-create "#chan") + (erc-mode) + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc--target (erc--target-from-string "#chan") + erc-networks--id (erc-networks--id-create nil))) + + (with-current-buffer (get-buffer-create "irc.foonet.org") + (erc-mode) + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-server-process (erc-networks-tests--create-live-proc) + erc-networks--id (erc-networks--id-create nil)) + (should-not (erc-networks--rename-server-buffer erc-server-process)) + (should (string= (buffer-name) "FooNet"))) + + (ert-info ("Channel buffer reassociated") + (erc-server-process-alive "#chan") + (with-current-buffer "#chan" + (should erc-server-connected) + (erc-with-server-buffer + (should (string= (buffer-name) "FooNet"))))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--rename-server-buffer--existing--reuse () + (let* ((old-buf (get-buffer-create "FooNet")) + (old-proc (erc-networks-tests--create-dead-proc old-buf))) + + (with-current-buffer old-buf + (erc-mode) + (insert "*** Old buf") + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-insert-marker (set-marker (make-marker) (point-max)) + erc-server-process old-proc + erc-networks--id (erc-networks--id-create nil))) + + (with-current-buffer (get-buffer-create "#chan") + (erc-mode) + (setq erc-network 'FooNet + erc-server-process old-proc + erc-networks--id (erc-networks--id-create nil) + erc--target (erc--target-from-string "#chan"))) + + (ert-info ("New buffer steals name, content") + (with-current-buffer (get-buffer-create "irc.foonet.org") + (erc-mode) + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-server-process (erc-networks-tests--create-live-proc) + erc-networks--id (erc-networks--id-create nil)) + (should-not (erc-networks--rename-server-buffer erc-server-process)) + (should (string= (buffer-name) "FooNet")) + (goto-char (point-min)) + (should (search-forward "Old buf")))) + + (ert-info ("Channel buffer reassociated") + (erc-server-process-alive "#chan") + (with-current-buffer "#chan" + (should erc-server-connected) + (should-not (eq erc-server-process old-proc)) + (erc-with-server-buffer + (should (string= (buffer-name) "FooNet"))))) + + (ert-info ("Original buffer killed off") + (should-not (buffer-live-p old-buf)))) + + (erc-networks-tests--clean-bufs)) + +;; This is for compatibility with pre-28.1 behavior. Basically, we're +;; trying to match the behavior bug for bug. All buffers were always +;; suffixed and never reassociated. 28.1 introduced a regression that +;; reversed the latter, but we've reverted that. + +(ert-deftest erc-networks--rename-server-buffer--existing--noreuse () + (with-suppressed-warnings ((obsolete erc-reuse-buffers)) + (should erc-reuse-buffers) ; default + (let* ((old-buf (get-buffer-create "irc.foonet.org:6697/irc.foonet.org")) + (old-proc (erc-networks-tests--create-dead-proc old-buf)) + erc-reuse-buffers) + (with-current-buffer old-buf + (erc-mode) + (insert "*** Old buf") + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-insert-marker (set-marker (make-marker) (point-max)) + erc-server-process old-proc + erc-networks--id (erc-networks--id-create nil))) + (with-current-buffer (get-buffer-create "#chan") + (erc-mode) + (setq erc-network 'FooNet + erc-server-process old-proc + erc-networks--id (buffer-local-value 'erc-networks--id old-buf) + erc--target (erc--target-from-string "#chan")) + (rename-buffer (erc-networks--construct-target-buffer-name erc--target))) + + (ert-info ("Server buffer uniquely renamed") + (with-current-buffer + (get-buffer-create "irc.foonet.org:6697/irc.foonet.org<2>") + (erc-mode) + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-server-process (erc-networks-tests--create-live-proc) + erc-networks--id (erc-networks--id-create nil)) + (should-not (erc-networks--rename-server-buffer erc-server-process)) + (should (string= (buffer-name) + "irc.foonet.org:6697/irc.foonet.org<2>")) + (goto-char (point-min)) + (should-not (search-forward "Old buf" nil t)))) + + (ert-info ("Channel buffer not reassociated") + (should-not + (erc-server-process-alive + (should (get-buffer "#chan/irc.foonet.org")))) + (with-current-buffer (get-buffer "#chan/irc.foonet.org") + (should-not erc-server-connected) + (should (eq erc-server-process old-proc)) + (erc-with-server-buffer + (should (string= (buffer-name) + "irc.foonet.org:6697/irc.foonet.org"))))) + + (ert-info ("Old buffer still around") + (should (buffer-live-p old-buf))))) + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--rename-server-buffer--reconnecting () + (let* ((old-buf (get-buffer-create "FooNet")) + (old-proc (erc-networks-tests--create-dead-proc old-buf))) + + (with-current-buffer old-buf + (erc-mode) + (insert "*** Old buf") + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-insert-marker (set-marker (make-marker) (point-max)) + erc-server-process old-proc + erc-networks--id (erc-networks--id-create nil))) + + (with-current-buffer (get-buffer-create "#chan") + (erc-mode) + (setq erc-network 'FooNet + erc-server-process old-proc + erc--target (erc--target-from-string "#chan") + erc-networks--id (erc-networks--id-create nil))) + + (ert-info ("No new buffer") + (with-current-buffer old-buf + (setq erc-server-process (erc-networks-tests--create-live-proc)) + (should-not (erc-networks--rename-server-buffer erc-server-process)) + (should (string= (buffer-name) "FooNet")) + (goto-char (point-min)) + (should (search-forward "Old buf")))) + + (ert-info ("Channel buffer updated with live proc") + (erc-server-process-alive "#chan") + (with-current-buffer "#chan" + (should erc-server-connected) + (should-not (eq erc-server-process old-proc)) + (erc-with-server-buffer + (should (string= (buffer-name) "FooNet")))))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--rename-server-buffer--id () + (let* ((old-buf (get-buffer-create "MySession")) + (old-proc (erc-networks-tests--create-dead-proc old-buf))) + + (with-current-buffer old-buf + (erc-mode) + (insert "*** Old buf") + (setq erc-network 'FooNet + erc-networks--id (erc-networks--id-create 'MySession) + erc-insert-marker (set-marker (make-marker) (point-max)) + erc-server-process old-proc)) + + (with-current-buffer (get-buffer-create "#chan") + (erc-mode) + (setq erc-network 'FooNet + erc-networks--id (erc-networks--id-create 'MySession) + erc-server-process old-proc + erc--target (erc--target-from-string "#chan"))) + + (ert-info ("No new buffer") + (with-current-buffer old-buf + (setq erc-server-process (erc-networks-tests--create-live-proc)) + (should-not (erc-networks--rename-server-buffer erc-server-process)) + (should (string= (buffer-name) "MySession")) + (goto-char (point-min)) + (should (search-forward "Old buf")))) + + (ert-info ("Channel buffer updated with live proc") + (erc-server-process-alive "#chan") + (with-current-buffer "#chan" + (should erc-server-connected) + (should-not (eq erc-server-process old-proc)) + (erc-with-server-buffer + (should (string= (buffer-name) "MySession")))))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--rename-server-buffer--existing--live () + (let* (erc-kill-server-hook + erc-insert-modify-hook + (old-buf (get-buffer-create "FooNet")) + (old-proc (erc-networks-tests--create-live-proc old-buf))) ; live + + (with-current-buffer old-buf + (erc-mode) + (insert "*** Old buf") + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-insert-marker (set-marker (make-marker) (point-max)) + erc-server-process old-proc + erc-networks--id (erc-networks--id-create nil)) + (should (erc-server-process-alive))) + + (with-current-buffer (get-buffer-create "#chan") + (erc-mode) + (setq erc-network 'FooNet + erc-server-process old-proc + erc-networks--id (erc-networks--id-create nil) + erc-server-connected t + erc--target (erc--target-from-string "#chan"))) + + (ert-info ("New buffer rejected, abandoned, not killed") + (with-current-buffer (get-buffer-create "irc.foonet.org") + (erc-mode) + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-insert-marker (set-marker (make-marker) (point-max)) + erc-server-process (erc-networks-tests--create-live-proc) + erc-networks--id (erc-networks--id-create nil)) + (should-not (erc-networks--rename-server-buffer erc-server-process)) + (should (eq erc-active-buffer old-buf)) + (should-not (erc-server-process-alive)) + (should (string= (buffer-name) "irc.foonet.org")) + (goto-char (point-min)) + (search-forward "still connected"))) + + (ert-info ("Channel buffer updated with live proc") + (should (erc-server-process-alive "#chan")) + (with-current-buffer "#chan" + (should erc-server-connected) + (should (erc-server-buffer-live-p)) + (should (eq erc-server-process old-proc)) + (should (buffer-live-p (process-buffer erc-server-process))) + (with-current-buffer (process-buffer erc-server-process) + (should (eq (current-buffer) (get-buffer "FooNet"))) + (should (eq (current-buffer) old-buf)))))) + + (should (get-buffer "FooNet")) + (should (get-buffer "irc.foonet.org")) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--rename-server-buffer--local-match () + (let* ((old-buf (get-buffer-create "FooNet")) + (old-proc (erc-networks-tests--create-dead-proc old-buf))) + + (with-current-buffer old-buf + (erc-mode) + (insert "*** Old buf") + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-server-announced-name "us-east.foonet.org" + erc-insert-marker (set-marker (make-marker) (point-max)) + erc-server-process old-proc + erc--isupport-params (make-hash-table) + erc-networks--id (erc-networks--id-create nil)) + (puthash 'CHANTYPES '("&#") erc--isupport-params)) + + (with-current-buffer (get-buffer-create "&chan") + (erc-mode) + (setq erc-network 'FooNet + erc-server-process old-proc + erc-server-announced-name "us-east.foonet.org" + erc--target (erc--target-from-string "&chan") + erc-networks--id (erc-networks--id-create nil))) + + (ert-info ("New server buffer steals name, content") + (with-current-buffer (get-buffer-create "irc.foonet.org") + (erc-mode) + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-server-announced-name "us-east.foonet.org" + erc-server-process (erc-networks-tests--create-live-proc) + erc--isupport-params (make-hash-table) + erc-networks--id (erc-networks--id-create nil)) + (puthash 'CHANTYPES '("&#") erc--isupport-params) + (should-not (erc-networks--rename-server-buffer erc-server-process)) + (should (string= (buffer-name) "FooNet")) + (goto-char (point-min)) + (should (search-forward "Old buf")))) + + (ert-info ("Channel buffer reassociated when &local server matches") + (should (erc-server-process-alive "&chan")) + (with-current-buffer "&chan" + (should erc-server-connected) + (should-not (eq erc-server-process old-proc)) + (erc-with-server-buffer + (should (string= (buffer-name) "FooNet"))))) + + (ert-info ("Original buffer killed off") + (should-not (buffer-live-p old-buf))) + + (erc-networks-tests--clean-bufs))) + +(ert-deftest erc-networks--rename-server-buffer--local-nomatch () + (let* ((old-buf (get-buffer-create "FooNet")) + (old-proc (erc-networks-tests--create-dead-proc old-buf))) + + (with-current-buffer old-buf + (erc-mode) + (insert "*** Old buf") + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-server-announced-name "us-west.foonet.org" + erc-insert-marker (set-marker (make-marker) (point-max)) + erc-server-process old-proc + erc--isupport-params (make-hash-table) + erc-networks--id (erc-networks--id-create nil)) + (puthash 'CHANTYPES '("&#") erc--isupport-params)) + + (with-current-buffer (get-buffer-create "&chan") + (erc-mode) + (setq erc-network 'FooNet + erc-server-process old-proc + erc-server-announced-name "us-west.foonet.org" ; west + erc--target (erc--target-from-string "&chan") + erc-networks--id (erc-networks--id-create nil))) + + (ert-info ("New server buffer steals name, content") + (with-current-buffer (get-buffer-create "irc.foonet.org") + (erc-mode) + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-server-announced-name "us-east.foonet.org" ; east + erc-server-process (erc-networks-tests--create-live-proc) + erc--isupport-params (make-hash-table) + erc-networks--id (erc-networks--id-create nil)) + + (puthash 'CHANTYPES '("&#") erc--isupport-params) + (should-not (erc-networks--rename-server-buffer erc-server-process)) + (should (string= (buffer-name) "FooNet")) + (goto-char (point-min)) + (should (search-forward "Old buf")))) + + (ert-info ("Channel buffer now orphaned even though network matches") + (should-not (erc-server-process-alive "&chan")) + (with-current-buffer "&chan" + (should-not erc-server-connected) + (should (eq erc-server-process old-proc)) + (erc-with-server-buffer + (should (string= (buffer-name) "FooNet"))))) + + (ert-info ("Original buffer killed off") + (should-not (buffer-live-p old-buf))) + + (erc-networks-tests--clean-bufs))) + +(ert-deftest erc-networks--update-server-identity--double-existing () + (with-temp-buffer + (erc-mode) + (setq erc-networks--id (make-erc-networks--id-qualifying + :parts [foonet "bob"] :len 1)) + + (with-current-buffer (get-buffer-create "#chan@foonet/bob") + (erc-mode) + (setq erc-networks--id (make-erc-networks--id-qualifying + :parts [foonet "bob"] :len 2))) + (with-current-buffer (get-buffer-create "foonet/alice") + (erc-mode) + (setq erc-networks--id + (make-erc-networks--id-qualifying :parts [foonet "alice"] :len 2))) + + (ert-info ("Adopt equivalent identity") + (should (eq (erc-networks--update-server-identity) + (buffer-local-value 'erc-networks--id + (get-buffer "#chan@foonet/bob"))))) + + (ert-info ("Ignore non-matches") + (should-not (erc-networks--update-server-identity)) + (should (eq erc-networks--id + (buffer-local-value 'erc-networks--id + (get-buffer "#chan@foonet/bob")))))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--update-server-identity--double-new () + (with-temp-buffer + (erc-mode) + (setq erc-networks--id (make-erc-networks--id-qualifying + :parts [foonet "bob"] :len 1)) + + (with-current-buffer (get-buffer-create "foonet/alice") + (erc-mode) + (setq erc-networks--id + (make-erc-networks--id-qualifying :parts [foonet "alice"] :len 2))) + (with-current-buffer (get-buffer-create "#chan@foonet/alice") + (erc-mode) + (setq erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "foonet/alice")))) + + (ert-info ("Evolve identity to prevent ambiguity") + (should-not (erc-networks--update-server-identity)) + (should (= (erc-networks--id-qualifying-len erc-networks--id) 2)) + (should (eq (erc-networks--id-symbol erc-networks--id) 'foonet/bob)))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--update-server-identity--double-bounded () + (with-temp-buffer + (erc-mode) + (setq erc-networks--id (make-erc-networks--id-qualifying + :parts [foonet "bob"] :len 1)) + + (with-current-buffer (get-buffer-create "foonet/alice/home") + (erc-mode) + (setq erc-networks--id (make-erc-networks--id-qualifying + :parts [foonet "alice" home] :len 3))) + (with-current-buffer (get-buffer-create "#chan@foonet/alice/home") + (erc-mode) + (setq erc-networks--id + (buffer-local-value 'erc-networks--id + (get-buffer "foonet/alice/home")))) + + (ert-info ("Evolve identity to prevent ambiguity") + (should-not (erc-networks--update-server-identity)) + (should (= (erc-networks--id-qualifying-len erc-networks--id) 2)) + (should (eq (erc-networks--id-symbol erc-networks--id) 'foonet/bob)))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--update-server-identity--double-even () + (with-temp-buffer + (erc-mode) + (setq erc-networks--id + (make-erc-networks--id-qualifying :parts [foonet "bob"] :len 1)) + + (with-current-buffer (get-buffer-create "foonet") + (erc-mode) + (setq erc-networks--id + (make-erc-networks--id-qualifying :parts [foonet "alice"] :len 1))) + (with-current-buffer (get-buffer-create "#chan") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan") + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "foonet")))) + + (ert-info ("Evolve identity to prevent ambiguity") + (should-not (erc-networks--update-server-identity)) + (should (= (erc-networks--id-qualifying-len erc-networks--id) 2)) + (should (eq (erc-networks--id-symbol erc-networks--id) 'foonet/bob))) + + (ert-info ("Collision renamed") + (with-current-buffer "foonet/alice" + (should (eq (erc-networks--id-symbol erc-networks--id) 'foonet/alice))) + + (with-current-buffer "#chan@foonet/alice" + (should (eq (erc-networks--id-symbol erc-networks--id) + 'foonet/alice))))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--update-server-identity--triple-new () + (with-temp-buffer + (erc-mode) + (setq erc-networks--id + (make-erc-networks--id-qualifying :parts [foonet "bob" home] :len 1)) + + (with-current-buffer (get-buffer-create "foonet/bob/office") + (erc-mode) + (setq erc-networks--id + (make-erc-networks--id-qualifying :parts [foonet "bob" office] + :len 3))) + (with-current-buffer (get-buffer-create "#chan@foonet/bob/office") + (erc-mode) + (setq erc-networks--id + (buffer-local-value 'erc-networks--id + (get-buffer "foonet/bob/office")))) + + (ert-info ("Extend our identity's canonical ID so that it's unique") + (should-not (erc-networks--update-server-identity)) + (should (= (erc-networks--id-qualifying-len erc-networks--id) 3)))) + + (erc-networks-tests--clean-bufs)) + +;;; erc-networks-tests.el ends here diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 5b04bff617b..618d7eeea02 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -566,8 +566,9 @@ (erc-log-irc-protocol ":irc.gnu.org 001 tester :Welcome") (erc-log-irc-protocol ":irc.gnu.org 002 tester :Your host is irc.gnu.org") (setq erc-network 'FooNet) + (setq erc-networks--id (erc-networks--id-create nil)) (erc-log-irc-protocol ":irc.gnu.org 422 tester :MOTD missing") - (setq erc-network 'BarNet) + (setq erc-networks--id (erc-networks--id-create 'BarNet)) (erc-log-irc-protocol ":irc.gnu.org 221 tester +i") (set-process-query-on-exit-flag erc-server-process nil))) (with-current-buffer "*erc-protocol*" |