""" The NAMES command (`RFC 1459 `__, `RFC 2812 `__, `Modern `__) """ from irctest import cases, runner from irctest.numerics import RPL_ENDOFNAMES, RPL_NAMREPLY from irctest.patma import ANYSTR, StrRe class NamesTestCase(cases.BaseServerTestCase): def _testNames(self, symbol): self.connectClient("nick1") self.sendLine(1, "JOIN #chan") self.getMessages(1) self.connectClient("nick2") self.sendLine(2, "JOIN #chan") self.getMessages(2) self.getMessages(1) self.sendLine(1, "NAMES #chan") # TODO: It is technically allowed to have one line for each; # but noone does that. self.assertMessageMatch( self.getMessage(1), command=RPL_NAMREPLY, params=[ "nick1", *(["="] if symbol else []), "#chan", StrRe("(nick2 @nick1|@nick1 nick2)"), ], ) self.assertMessageMatch( self.getMessage(1), command=RPL_ENDOFNAMES, params=["nick1", "#chan", ANYSTR], ) @cases.mark_specifications("RFC1459", deprecated=True) def testNames1459(self): """ https://modern.ircdocs.horse/#names-message https://datatracker.ietf.org/doc/html/rfc1459#section-4.2.5 https://datatracker.ietf.org/doc/html/rfc2812#section-3.2.5 """ self._testNames(symbol=False) @cases.mark_specifications("RFC1459", "RFC2812", "Modern") def testNames2812(self): """ https://modern.ircdocs.horse/#names-message https://datatracker.ietf.org/doc/html/rfc1459#section-4.2.5 https://datatracker.ietf.org/doc/html/rfc2812#section-3.2.5 """ self._testNames(symbol=True) def _testNamesMultipleChannels(self, symbol): self.connectClient("nick1") if self.targmax.get("NAMES", "1") == "1": raise runner.OptionalExtensionNotSupported("Multi-target NAMES") self.sendLine(1, "JOIN #chan1") self.sendLine(1, "JOIN #chan2") self.getMessages(1) self.sendLine(1, "NAMES #chan1,#chan2") # TODO: order is unspecified self.assertMessageMatch( self.getMessage(1), command=RPL_NAMREPLY, params=["nick1", *(["="] if symbol else []), "#chan1", "@nick1"], ) self.assertMessageMatch( self.getMessage(1), command=RPL_NAMREPLY, params=["nick1", *(["="] if symbol else []), "#chan2", "@nick1"], ) self.assertMessageMatch( self.getMessage(1), command=RPL_ENDOFNAMES, params=["nick1", "#chan1,#chan2", ANYSTR], ) @cases.mark_isupport("TARGMAX") @cases.mark_specifications("RFC1459", deprecated=True) def testNamesMultipleChannels1459(self): """ https://modern.ircdocs.horse/#names-message https://datatracker.ietf.org/doc/html/rfc1459#section-4.2.5 https://datatracker.ietf.org/doc/html/rfc2812#section-3.2.5 """ self._testNamesMultipleChannels(symbol=False) @cases.mark_isupport("TARGMAX") @cases.mark_specifications("RFC1459", "RFC2812", "Modern") def testNamesMultipleChannels2812(self): """ https://modern.ircdocs.horse/#names-message https://datatracker.ietf.org/doc/html/rfc1459#section-4.2.5 https://datatracker.ietf.org/doc/html/rfc2812#section-3.2.5 """ self._testNamesMultipleChannels(symbol=True) @cases.mark_specifications("RFC1459", "RFC2812", "Modern") def testNamesInvalidChannel(self): """ "There is no error reply for bad channel names." -- https://datatracker.ietf.org/doc/html/rfc1459#section-4.2.5 -- https://datatracker.ietf.org/doc/html/rfc2812#section-3.2.5 "If the channel name is invalid or the channel does not exist, one `RPL_ENDOFNAMES` numeric containing the given channel name should be returned." -- https://modern.ircdocs.horse/#names-message """ self.connectClient("foo") self.getMessages(1) self.sendLine(1, "NAMES invalid") self.assertMessageMatch( self.getMessage(1), command=RPL_ENDOFNAMES, params=["foo", "invalid", ANYSTR], ) @cases.mark_specifications("RFC1459", "RFC2812", "Modern") def testNamesNonexistingChannel(self): """ "There is no error reply for bad channel names." -- https://datatracker.ietf.org/doc/html/rfc1459#section-4.2.5 -- https://datatracker.ietf.org/doc/html/rfc2812#section-3.2.5 "If the channel name is invalid or the channel does not exist, one `RPL_ENDOFNAMES` numeric containing the given channel name should be returned." -- https://modern.ircdocs.horse/#names-message """ self.connectClient("foo") self.getMessages(1) self.sendLine(1, "NAMES #nonexisting") self.assertMessageMatch( self.getMessage(1), command=RPL_ENDOFNAMES, params=["foo", "#nonexisting", ANYSTR], ) def _testNamesNoArgumentPublic(self, symbol): self.connectClient("nick1") self.getMessages(1) self.sendLine(1, "JOIN #chan1") self.connectClient("nick2") self.sendLine(2, "JOIN #chan2") self.sendLine(2, "MODE #chan2 -sp") self.getMessages(1) self.getMessages(2) self.sendLine(1, "NAMES") # TODO: order is unspecified self.assertMessageMatch( self.getMessage(1), command=RPL_NAMREPLY, params=["nick1", *(["="] if symbol else []), "#chan1", "@nick1"], ) self.assertMessageMatch( self.getMessage(1), command=RPL_NAMREPLY, params=["nick1", *(["="] if symbol else []), "#chan2", "@nick2"], ) self.assertMessageMatch( self.getMessage(1), command=RPL_ENDOFNAMES, params=["nick1", ANYSTR, ANYSTR], ) @cases.mark_specifications("RFC1459", deprecated=True) def testNamesNoArgumentPublic1459(self): """ "If no parameter is given, a list of all channels and their occupants is returned." -- https://datatracker.ietf.org/doc/html/rfc1459#section-4.2.5 -- https://datatracker.ietf.org/doc/html/rfc2812#section-3.2.5 """ self._testNamesNoArgumentPublic(symbol=False) @cases.mark_specifications("RFC2812", deprecated=True) def testNamesNoArgumentPublic2812(self): """ "If no parameter is given, a list of all channels and their occupants is returned." -- https://datatracker.ietf.org/doc/html/rfc1459#section-4.2.5 -- https://datatracker.ietf.org/doc/html/rfc2812#section-3.2.5 """ self._testNamesNoArgumentPublic(symbol=True) def _testNamesNoArgumentPrivate(self, symbol): self.connectClient("nick1") self.getMessages(1) self.sendLine(1, "JOIN #chan1") self.connectClient("nick2") self.sendLine(2, "JOIN #chan2") self.sendLine(2, "MODE #chan2 +sp") self.getMessages(1) self.getMessages(2) self.sendLine(1, "NAMES") self.assertMessageMatch( self.getMessage(1), command=RPL_NAMREPLY, params=["nick1", *(["="] if symbol else []), "#chan1", "@nick1"], ) self.assertMessageMatch( self.getMessage(1), command=RPL_ENDOFNAMES, params=["nick1", ANYSTR, ANYSTR], ) @cases.mark_specifications("RFC1459", deprecated=True) def testNamesNoArgumentPrivate1459(self): """ "If no parameter is given, a list of all channels and their occupants is returned. At the end of this list, a list of users who are visible but either not on any channel or not on a visible channel are listed as being on `channel' "*"." -- https://datatracker.ietf.org/doc/html/rfc1459#section-4.2.5 -- https://datatracker.ietf.org/doc/html/rfc2812#section-3.2.5 """ self._testNamesNoArgumentPrivate(symbol=False) @cases.mark_specifications("RFC2812", deprecated=True) def testNamesNoArgumentPrivate2812(self): """ "If no parameter is given, a list of all channels and their occupants is returned. At the end of this list, a list of users who are visible but either not on any channel or not on a visible channel are listed as being on `channel' "*"." -- https://datatracker.ietf.org/doc/html/rfc1459#section-4.2.5 -- https://datatracker.ietf.org/doc/html/rfc2812#section-3.2.5 """ self._testNamesNoArgumentPrivate(symbol=True)