|
14 | 14 | NotImplementedByController,
|
15 | 15 | )
|
16 | 16 | from irctest.cases import BaseServerTestCase
|
| 17 | +from irctest.client_mock import ClientMock |
17 | 18 | from irctest.exceptions import NoMessageException
|
18 | 19 | from irctest.patma import ANYSTR
|
19 | 20 |
|
@@ -496,6 +497,53 @@ def kill_proc(self) -> None:
|
496 | 497 | os.killpg(self.pgroup_id, signal.SIGKILL)
|
497 | 498 | super().kill_proc()
|
498 | 499 |
|
| 500 | + def wait_for_services(self) -> None: |
| 501 | + # by default, wait_for_services() connects a user that sends a HELP command |
| 502 | + # to NickServ and assumes services are up when it receives a non-ERR_NOSUCHNICK |
| 503 | + # reply. |
| 504 | + # However, with Sable, NickServ is always up, even when services are not linked, |
| 505 | + # so we need to check a different way. We check presence of a non-EXTERNAL |
| 506 | + # value to the sasl capability, but LINKS would |
| 507 | + if self.services_up: |
| 508 | + # Don't check again if they are already available |
| 509 | + return |
| 510 | + self.server_controller.wait_for_port() |
| 511 | + |
| 512 | + c = ClientMock(name="chkSvs", show_io=True) |
| 513 | + c.connect(self.server_controller.hostname, self.server_controller.port) |
| 514 | + c.sendLine("NICK chkSvs") |
| 515 | + c.sendLine("USER chk chk chk chk") |
| 516 | + time.sleep(self.server_controller.sync_sleep_time) |
| 517 | + got_end_of_motd = False |
| 518 | + while not got_end_of_motd: |
| 519 | + for msg in c.getMessages(synchronize=False): |
| 520 | + if msg.command == "PING": |
| 521 | + # Hi Unreal |
| 522 | + c.sendLine("PONG :" + msg.params[0]) |
| 523 | + if msg.command in ("376", "422"): # RPL_ENDOFMOTD / ERR_NOMOTD |
| 524 | + got_end_of_motd = True |
| 525 | + |
| 526 | + timeout = time.time() + 10 |
| 527 | + while not self.services_up: |
| 528 | + if time.time() > timeout: |
| 529 | + raise Exception("Timeout while waiting for services") |
| 530 | + c.sendLine("CAP LS 302") |
| 531 | + |
| 532 | + msgs = self.getNickServResponse(c, timeout=1) |
| 533 | + for msg in msgs: |
| 534 | + if msg.command == "CAP": |
| 535 | + pass |
| 536 | + for token in msg.params[-1].split(): |
| 537 | + if token.startswith("sasl="): |
| 538 | + if "PLAIN" in token.removeprefix("sasl=").split(","): |
| 539 | + # SASL PLAIN is available, so services are linked. |
| 540 | + self.services_up = True |
| 541 | + break |
| 542 | + |
| 543 | + c.sendLine("QUIT") |
| 544 | + c.getMessages() |
| 545 | + c.disconnect() |
| 546 | + |
499 | 547 |
|
500 | 548 | def get_irctest_controller_class() -> Type[SableController]:
|
501 | 549 | return SableController
|
0 commit comments