ϪfdZddlZddlZddlZddlmZmZddlmZm Z ddl m Z ddl m Z ddlmZddlmZmZGd d e ZGd d eZGd deZGddeZGddeZddj3ej4dj3ej6ej8dej:ej<dzgZGddeZ GddejBZ"GddeZ#Gd d!eZ$Gd"d#ej"Z%Gd$d%eZ&Gd&d'e%Z'd(Z(Gd)d*eZ)Gd+d,eZ*Gd-d.ej"Z+Gd/d0eZ,Gd1d2eZ-Gd3d4eZ.Gd5d6ej"Z/Gd7d8eZ0Gd9d:eZ1Gd;deZ3Gd?d@eZ4GdAdBeZ5y)Cz+ Tests for L{twisted.words.protocols.irc}. N)protocoltask)StringIOWithoutClosingStringTransport)FilePath)TestCase)irc) IRCClient attributesceZdZdZy) IRCTestCasec|}t|tr|jd}t|tr1t|dtr|Dcgc]}|jd}}|j ||ycc}w)a$ A buffer is always bytes, but sometimes we need to compare it to a utf-8 unicode string @param buf: the buffer @type buf: L{bytes} or L{unicode} or L{list} @param val: the value to compare @type val: L{bytes} or L{unicode} or L{list} utf-8rutf8N) isinstancestrdecodelist assertEqual)selfbufval bufferValuebs =/usr/lib/python3/dist-packages/twisted/words/test/test_irc.pyassertEqualBufferValuez"IRCTestCase.assertEqualBufferValuesm c3 %,,W5K k4 (#a&#&9DEAqxx/E E c*Fs A8N)__name__ __module__ __qualname__rrr r s+r!r cPeZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zy )ModeParsingTestsz> Tests for L{twisted.words.protocols.irc.parseModes}. )klbrcd|jtjtjdgy)zI Parsing an empty mode string raises L{irc.IRCBadModes}. N assertRaisesr IRCBadModes parseModesrs rtest_emptyModesz ModeParsingTests.test_emptyModes0s  #//3>>2rBr!c|jtjtjdg|jtjtjdg|jtjtjdg|jtjtjdgy)z Parsing a mode string that contains an empty sequence (either a C{+} or C{-} followed directly by another C{+} or C{-}, or not followed by anything at all) raises L{irc.IRCBadModes}. z++kz-+k+-Nr'r+s rtest_emptyModeSequencez'ModeParsingTests.test_emptyModeSequence6st #//3>>5"E #//3>>5"E #//3>>3C #//3>>3Cr!c|jtjtjdg|jtjtjdgy)zp Parsing a mode string that does not start with C{+} or C{-} raises L{irc.IRCBadModes}. foo%Nr'r+s rtest_malformedModesz$ModeParsingTests.test_malformedModesAs< #//3>>5"E #//3>>3Cr!c|jtjtjdg|jtjtjdgy)zk Parsing a mode string that contains no mode characters raises L{irc.IRCBadModes}. r.r/Nr'r+s rtest_nullModeszModeParsingTests.test_nullModesIs< #//3>>3C #//3>>3Cr!ctjdg\}}|j|dg|j|gtjdg\}}|j|g|j|dgy)z Parsing a single mode setting with no parameters results in that mode, with no parameters, in the "added" direction and no modes in the "removed" direction. +ssN-sNr r*rraddedremoveds rtest_singleModez ModeParsingTests.test_singleModeQsp b1w  . "%b1w # ;-0r!ctjdg\}}|j|gd|j|gtjdg\}}|j|g|j|ddgy)z Parsing a single-direction mode setting with multiple modes and no parameters, results in all modes falling into the same direction group. z+stn)r9tNnNz-ntrDrBNr<r=s rtest_singleDirectionz%ModeParsingTests.test_singleDirection_sr 3w  GH "%r2w # ; "<=r!ctjdg\}}|j|gd|j|dgy)zL Parsing a multi-direction mode setting with no parameters. z+s-n+ti)r9rBiNrDNr<r=s rtest_multiDirectionz$ModeParsingTests.test_multiDirectionls; 26w  GH ;-0r!ctjdg\}}|j|gd|j|gy)z Parsing a multi-direction mode setting containing two consecutive mode sequences with the same direction results in the same result as if there were only one mode sequence in the same direction. z+sn+ti)r9rDrBrHNr<r=s rtest_consecutiveDirectionz*ModeParsingTests.test_consecutiveDirectionts9 "5w  TU "%r!c|jtjtjdg|j|jtjtjdgd|jy)z If the number of mode parameters does not match the number of modes expecting parameters, L{irc.IRCBadModes} is raised. z+kz+kl)r210lulz_extra_paramN)r(r r)r* paramModesr+s rtest_mismatchedParamsz&ModeParsingTests.test_mismatchedParams~sO #//3>>4T__U  OO NN  - OO  r!ctjdgd|j\}}|j|gd|j|gtjdddg|j\}}|j|g|j|gdtjdgd |j\}}|j|gd |j|gy ) z Modes which require parameters are parsed and paired with their relevant parameter, modes which do not require parameters do not consume any of the parameters. z+klbb)somekey42nick!user@host other!*@*)krS)lrTrrUrrVz-klbbrUrV))rXN)rYNrZr[z+knbb)rSrUrV)rWrDrZr[N)r r*rPrr=s rtest_parametersz ModeParsingTests.test_parameterss  Et w     "% & 4doo w #   S  ? w     "%r!N)rrr__doc__rPr,r0r4r6r@rFrJrLrQr\r r!rr#r#)sDJC DDD 1 >1&  *&r!r#ceZdZdZdZy) MiscTestsz, Tests for miscellaneous functions. c |jtjtjdgddd}|jtj|gdgdgdgdgggdgdgdgdgy ) z Apply a function of two arguments cumulatively to the items of a sequence, from right to left, so as to reduce the sequence to a single value. r)c*|jd||S)Nr)insert)rYxs r insertTopz'MiscTests.test_foldr..insertTops HHQNHr!rarbrcrdN)rr _foldroperatorsub)rris r test_foldrzMiscTests.test_foldrsp HLL!\BBG   JJy"sQC!qc&: ;Q|Q>OQR=S r!N)rrrr]rmr r!rr_r_s  r!r_c|eZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZdZdZy)FormattedTextTestsz> Tests for parsing and assembling formatted IRC text. cRtj|}|j||y)a+ Assert that C{text} is parsed and assembled to the same value as what C{expectedFormatted} is assembled to. This provides a way to ignore meaningless differences in the formatting structure that would be difficult to detect without rendering the structures. N)r parseFormattedTextassertAssemblesTo)rtextexpectedFormatted formatteds rassertAssembledEquallyz)FormattedTextTests.assertAssembledEquallys%**40  y*; Kr!cp|jtjtjddy)zi A I{normal} string assembles to a string prefixed with the I{off} control code. hellozhelloN)rr ryr|r}r+s rtest_assembleNormalz&FormattedTextTests.test_assembleNormals( 22188G3DE{Sr!cp|jtjtjddy)zt A I{bold} string assembles to a string prefixed with the I{off} and I{bold} control codes. rzhelloN)rr ryr|rr+s rtest_assembleBoldz$FormattedTextTests.test_assembleBolds' 22166'?C_Ur!cp|jtjtjddy)z An I{underline} string assembles to a string prefixed with the I{off} and I{underline} control codes. rzhelloN)rr ryr| underliner+s rtest_assembleUnderlinez)FormattedTextTests.test_assembleUnderline s+   % %akk'&: ;_ r!cp|jtjtjddy)z A I{reverse video} string assembles to a string prefixed with the I{off} and I{reverse video} control codes. rzhelloN)rr ryr| reverseVideor+s rtest_assembleReverseVideoz,FormattedTextTests.test_assembleReverseVideos+   % %annW&= > r!c|jtjtjj ddy)z A I{foreground color} string assembles to a string prefixed with the I{off} and I{color} (followed by the relevant foreground color code) control codes. rz 02helloN)rr ryr|fgbluer+s rtest_assembleForegroundColorz/FormattedTextTests.test_assembleForegroundColors0   % %addii&8 9;L r!c|jtjtjj ddy)a A I{background color} string assembles to a string prefixed with the I{off} and I{color} (followed by a I{,} to indicate the absence of a foreground color, followed by the relevant background color code) control codes. rz ,02helloN)rr ryr|bgrr+s rtest_assembleBackgroundColorz/FormattedTextTests.test_assembleBackgroundColor(s0   % %addii&8 9;M r!c|jtjtjj tj jddy)z A I{foreground} and I{background} color string assembles to a string prefixed with the I{off} and I{color} (followed by the relevant foreground color, I{,} and the relevant background color code) control codes. rz 05,02helloN)rr ryr|rredrrr+s rtest_assembleColorz%FormattedTextTests.test_assembleColor3s=   % %addhhqttyy/A&B C  r!c|jtjtjdtj dfd|jtjtj tjjtjjddftjdfdy)zK Nested attributes retain the attributes of their parents. r worldzhello worldz yayz05,03hello05 world yayN) rr ryr|rrr}rrrgreenrr+s rtest_assembleNestedz&FormattedTextTests.test_assembleNested?s   % %affWakk(6K-K&L M -   % %DDHHQTTZZ0(:;Q^^F=SS  =  r!cp|jtjdtjdy)zk Parsing unformatted text results in text with attributes that constitute a no-op. rN)rr rqr|r}r+s rtest_parseUnformattedTextz,FormattedTextTests.test_parseUnformattedTextQs( //8!((7:KLr!c|jtjdtjj d|jtjdtjj tj jd|jtjdtjj dtjjdfy)z Correctly formatted text with colors uses 2 digits to specify foreground and (optionally) background. z01yayyayz 01,02yayz01yay02yipeeyipeeN)rr rqr|rblackrrr+s rtest_colorFormattingz'FormattedTextTests.test_colorFormattingXs //@!$$**UBST   " "#5 6 14499UCS8T    " "#= > DDJJuaddii00 1 r!c|jdtjjd|jdtjjd|jdtjjtj j d|jdtjjtj jd|jdtjjtj jd |jd tjd |jd tjd |jdtjjd|jdtjy)a Formatted text with colors can use 1 digit for both foreground and background, as long as the text part does not begin with a digit. Foreground and background colors are only processed to a maximum of 2 digits per component, anything else is treated as text. Color sequences must begin with a digit, otherwise processing falls back to unformatted text. z 1kinda validz kinda validz999,999kinda validz9,999kinda validz1,2kinda validz1,999kinda validz 9kinda validz1,242 is a special numberz2 is a special numberz ,02oopsz,02oopszwrongwrongz1,hellorzN) rvr|rrrrryellowr}r+s rtest_weirdColorFormattingz,FormattedTextTests.test_weirdColorFormattingfs8 ##$6 =8QR ## $addjj1C&D  ## !$$**QTTYY}-E"F  ## "ADDJJqttzz./I$J  ## + DDJJqtt{{#:; <  ##$5qxx 7JK ##K'1BC ##M144::g3FG ##J9r!c:|jdtjtjjddf|jdtjtjjtj j ddfy)zb An empty color format specifier clears foreground and background colors. z 01yayresetrresetz01,02yayresetN)rvr|r}rrrrr+s rtest_clearColorFormattingz,FormattedTextTests.test_clearColorFormattingso ## !((144::e+ *k>Br!cntjjgd}|j|gdy)z L{ServerSupportedFeatures._splitParamArgs} splits ISUPPORT parameter arguments into key and value. Arguments without a separator are split into a key and an empty string. )A:1B:2zC:D))r|r)Br)Cr&)rr&N)r r_splitParamArgsrrrs rtest_splitParamArgsz/ServerSupportedFeatureTests.test_splitParamArgsPs, ))99:ST LMr!ctjjgdtj}|j |gdy)z L{ServerSupportedFeatures._splitParamArgs} uses the argument processor passed to convert ISUPPORT argument values to some more suitable form. )rrr))r|ra)rrb)rNN)r rrrrrs rtest_splitParamArgsProcessorz8ServerSupportedFeatureTests.test_splitParamArgsProcessorYs8 ))99 !2!2  ?@r!ctjj}|j|dd|j t |d|j|ddddy)a  L{ServerSupportedFeatures._parsePrefixParam} parses the ISUPPORT PREFIX parameter into a mapping from modes to prefix symbols, returns L{None} if there is no parseable prefix parameter or raises C{ValueError} if the prefix parameter is malformed. r&Nrz(ov)@+@r)r.ra)ov)r r_parsePrefixParamrr(r)rrs rtest_parsePrefixParamz1ServerSupportedFeatureTests.test_parsePrefixParamdsZ 77II *2.5 *&7A *84H86TUr!c$tjj}|j|gdddddd|j|gdddddd|j|gd ddddd|j t |gd y ) aO L{ServerSupportedFeatures._parseChanModesParam} parses the ISUPPORT CHANMODES parameter into a mapping from mode categories to mode characters. Passing fewer than 4 parameters results in the empty string for the relevant categories. Passing more than 4 parameters raises C{ValueError}. )r&r&r&r&r& addressModesrsetParamnoParam)rrXrYimnpstrrXrYr)rrXrYr&)rrcdeN)r r_parseChanModesParamrr(r)rrs rtest_parseChanModesParamz4ServerSupportedFeatureTests.test_parseChanModesParamps #::OO  !1 2"" L  !: ; 3CH U  !4 5 3CB O *&: --i8/J  ,,W56 # --g67 #r!c tj}|Dcgc]\}}dj||xsd}}}|j||Scc}}w)z Parse all specified features according to the ISUPPORT specifications. @type features: C{list} of C{(featureName, value)} @param features: Feature names and values to parse @rtype: L{irc.ServerSupportedFeatures} z{}={}r&)r rformatr")rfeaturesr'rvalues r_parsez"ServerSupportedFeatureTests._parsesP//1 IQR+$GNN4"5RR!Ss ANcL|j||fg}|j|S)z Parse a feature, with the given name and value, according to the ISUPPORT specifications and return the parsed value. )r-r#)rrr,r's r _parseFeaturez)ServerSupportedFeatureTests._parseFeatures) KK$0 ##D))r!c|j|j|d||j|j|d||j|j|ddy)zW Perform some common tests on a feature known to use L{_intOrDefault}. NnotanintrT*rr/)rrdefaults r_testIntOrDefaultFeaturez4ServerSupportedFeatureTests._testIntOrDefaultFeatures[ ++D$7A ++D*=wG ++D$7r!cH|j|jdddy)z The STATUSMSG support parameter is parsed into a string of channel status that support the exclusive channel notice method. STATUSMSGz@+Nr3r+s rtest_support_STATUSMSGz2ServerSupportedFeatureTests.test_support_STATUSMSGs! ++K>Er!c|j|jddddd|j|jdddddd|j|jdd ddddy) z The TARGMAX support parameter is parsed into a dictionary, mapping strings to integers, of the maximum number of targets for a particular command. TARGMAXzPRIVMSG:4,NOTICE:3rdrc)PRIVMSGNOTICEzPRIVMSG:4,NOTICE:3,KICK:3.1415N)r[r\KICKz PRIVMSG:4,NOTICE:3,KICK:notanintr3r+s rtest_support_TARGMAXz0ServerSupportedFeatureTests.test_support_TARGMAXs    y*> ?Q '    y*J KQ 5     y*L MQ 5 r!cjtjjd}|jd|y)a The NICKLEN support parameter is parsed into an integer value indicating the maximum length of a nickname the client may use, otherwise, if the parameter is missing or invalid, the default value (as specified by RFC 1459) is used. NICKLENNr rr9r5rr4s rtest_support_NICKLENz0ServerSupportedFeatureTests.test_support_NICKLEN*s---/99)D %%i9r!cjtjjd}|jd|y)z The CHANNELLEN support parameter is parsed into an integer value indicating the maximum channel name length, otherwise, if the parameter is missing or invalid, the default value (as specified by RFC 1459) is used. CHANNELLENNrarbs rtest_support_CHANNELLENz3ServerSupportedFeatureTests.test_support_CHANNELLEN4s---/99,G %%lGs/   - ++K?Qr!c&|jdy)z The KICKLEN support parameter is parsed into an integer value indicating the maximum length of a kick message a client may use. KICKLENNr5r+s rtest_support_KICKLENz0ServerSupportedFeatureTests.test_support_KICKLENGs %%i0r!c(|jd|jddg|j|jddd|j|jdddddd|j|jdd ddddy) z The PREFIX support parameter is parsed into a dictionary mapping modes to two-tuples of status symbol and priority. PREFIX)rorNz(ohv)@%+r)r3ra)r.rb)rhrz(hov)@%+r@r+s rtest_support_PREFIXz/ServerSupportedFeatureTests.test_support_PREFIXNs   *   ,?+@A ++Hd;TB    x 4 9     x 4 9 r!c&|jdy)z The TOPICLEN support parameter is parsed into an integer value indicating the maximum length of a topic a client may set. TOPICLENNrlr+s rtest_support_TOPICLENz1ServerSupportedFeatureTests.test_support_TOPICLEN`s %%j1r!c&|jdy)a_ The MODES support parameter is parsed into an integer value indicating the maximum number of "variable" modes (defined as being modes from C{addressModes}, C{param} or C{setParam} categories for the C{CHANMODES} ISUPPORT parameter) which may by set on a channel by a single MODE command from a client. rNrlr+s rtest_support_MODESz.ServerSupportedFeatureTests.test_support_MODESgs %%g.r!c|j|jddd|j|jddy)z The EXCEPTS support parameter is parsed into the mode character to be used for "ban exception" modes. If no parameter is specified then the character C{e} is assumed. rr rNr3r+s rtest_support_EXCEPTSz0ServerSupportedFeatureTests.test_support_EXCEPTSqs< ++Is;SA ++I6 2L $L?F (:=R1 $2/=;r!rceZdZdZy)IRCClientWithoutLoginrN)rrr performLoginr r!rr}r}sLr!r}c4eZdZdZdZdZdZdZdZdZ y) CTCPTestszK Tests for L{twisted.words.protocols.irc.IRCClient} CTCP handling. cht|_tj|j|_t |_|j j|j|j|jj|j|j jdyr{) rfiler FileWrapper transportr}clientmakeConnection addCleanuploseConnectionconnectionLostr+s rsetUpzCTCPTests.setUpsp*, !--dii8+-  ""4>>2 556  22D9r!cfdtjtjtjzdz}dtjtjtjzdz}|jj ||j j}|j||y)zTesting CTCP query ERRMSG. Not because this is this is an especially important case in the field, but it does go through the entire dispatch/decode/encode process. z@:nick!guy@over.there PRIVMSG #theChan :%(X)cERRMSG t%(X)c%(EOL)srEOLz>NOTICE nick :%(X)cERRMSG t :No error has occurred.%(X)c%(EOL)sN) r X_DELIMrLFr dataReceivedrgetvaluer)rerrQueryerrReplyreplys r test_ERRMSGzCTCPTests.test_ERRMSGs (03 CFFSVVO*T U   1KK8 9    * ""$ ##E84r!cLd|j_|jjddddtjtj tj z|jjdz}|jj}|j||y)z If attributes for version information on L{IRCClient} are set to L{None}, the parts of the CTCP VERSION response they correspond to are omitted. FrobozzIRCnick!guy@over.there#theChanNz1NOTICE nick :%(X)cVERSION %(vname)s::%(X)c%(EOL)s)rrvname) r versionNamectcpQuery_VERSIONr rrrrrrr versionReplyrs rtest_noNumbersVERSIONzCTCPTests.test_noNumbersVERSIONs~ #/  %%&;ZNM66CFF?[[,,Q   ""$ ##E<8r!cd|j_d|j_d|j_|jj ddddt j t jt jz|jj|jj|jjdz}|jj}|j||y) z The response to a CTCP VERSION query includes the version number and environment information, as specified by L{IRCClient.versionNum} and L{IRCClient.versionEnv}. rz1.2gZorkOSrrNzANOTICE nick :%(X)cVERSION %(vname)s:%(vnum)s:%(venv)s%(X)c%(EOL)s)rrrvnumvenv) rr versionNum versionEnvrr rrrrrrrs rtest_fullVERSIONzCTCPTests.test_fullVERSIONs #/ !' !)  %%&;ZN [[vv00 .. ..    ""$ ##E<8r!cDfd}d_|j_jjdddj t j gjjjdjjdy ) zL Duplicated CTCP messages are ignored and no reply is made. c0xjdz c_yNra)called)userchanneldatars rtestCTCPz8CTCPTests.test_noDuplicateCTCPDispatch..testCTCPs KK1 Kr!rfoo!bar@baz.quux#chanz{X}TESTTHIS{X}foo{X}TESTTHIS{X}rr&raN) rrctcpQuery_TESTTHIS irc_PRIVMSGr*r rrrrr)rrs` rtest_noDuplicateCTCPDispatchz&CTCPTests.test_noDuplicateCTCPDispatchs   )1 &   7>>>M N  ##DII$6$6$8"= a(r!cDfd}d_jjd|jjdddj t j gjjjdjjd jjd jjddd j t j gjjd y )zQ The fallback handler is invoked for unrecognized CTCP messages. cF||||f_xjdz c_yr) calledWithr)rrtagrrs r unknownQueryz6CTCPTests.test_noDefaultDispatch..unknownQuerys!#Wc48DO KK1 Kr!rctcpUnknownQueryrrz {X}NOTREAL{X}rr&)rrNOTREALNraz{X}NOTREAL{X}foo{X}NOTREAL{X}rbN) rpatchrrr*r rrrrrr)rrs` rtest_noDefaultDispatchz CTCPTests.test_noDefaultDispatchs    4;; 2LA  /*@*@3;;*@*O P  ##DII$6$6$8"=  OOK  a(   5<.method5s1vD !!$)3t9c!f#=> #4| % e2:#7 JJ  ubk *r!r )rrrrs``` rrzNoticingClient.makeMethod4s +* r!)rrrrrrr __classcell__)rs@rrrs9I ? y  )  L   8 9   1 ,   1 B  !" B#$7 )'>-7-3G8/r!rc: ||}||=|S#t$r|cYSwxYwr{)r)dictkeyr4r,s rpopr Ms4S  I s  ceZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZdZd dZd!dZd!dZdZdZdZdZdZdZdZdZdZ y)"ClientImplementationTestsc t|_t|_|jj |j|j |jj |j |jjdyr{)rrrrrrrrr+s rrzClientImplementationTests.setUpXsZ(*$&  ""4>>2 556  22D9r!c t|dd}t|dd}t|dd}d|zdz|zdz|zdz|zd z|zd z}|jj||j|jj||fgy) Nhost server.hostrnicknamerr&:  : r rrrr) rcodemsgfuncrrrrrs r_serverTestImplz)ClientImplementationTests._serverTestImpl`s2v}-2vz*2vr" $J t #c )D 03 6 = Ds JV S    ) **dBZL9r!c2d}|jd|d|y)NzHYour host is some.host[blah.blah/6667], running version server-version-3002rrrrrs r testYourHostz&ClientImplementationTests.testYourHostlsX UC#>r!c2d}|jd|d|y)Nz=This server was cobbled together Fri Aug 13 18:00:25 UTC 2004003rrrrs r testCreatedz%ClientImplementationTests.testCreatedpsM UC=r!c 8d}|jd|dddddy) Nz(server.host server-version abcDEF bcdEHI004rrzserver-versionabcDEFbcdEHIrrrs r testMyInfoz$ClientImplementationTests.testMyInfots/8    $$  r!c2d}|jd|d|y)Nz4There are 9227 victims and 9542 hiding on 24 servers251rrrrs rtestLuserClientz)ClientImplementationTests.testLuserClientsD UCSAr!c<d}d}|jd|d|gdy)NzMODES=4 CHANLIMIT=#:20 NICKLEN=16 USERLEN=10 HOSTLEN=63 TOPICLEN=450 KICKLEN=450 CHANNELLEN=30 KEYLEN=23 CHANTYPES=# PREFIX=(ov)@+ CASEMAPPING=ascii CAPAB IRCD=dancerare available on this server005r)rzCHANLIMIT=#:20z NICKLEN=16z USERLEN=10z HOSTLEN=63z TOPICLEN=450z KICKLEN=450z CHANNELLEN=30z KEYLEN=23z CHANTYPES=#z PREFIX=(ov)@+zCASEMAPPING=asciiCAPABz IRCD=dancerrrrrrrs r _sendISUPPORTz'ClientImplementationTests._sendISUPPORTs8 @ -      r!c$|jy)zq The client parses ISUPPORT messages sent by the server and calls L{IRCClient.isupport}. N)r2r+s r test_ISUPPORTz'ClientImplementationTests.test_ISUPPORTs r!c2d}|jd|d|y)NzTry server some.host, port 321010rrrrs r testBouncez$ClientImplementationTests.testBounces. UC <   1A KK $ $QZ 0 1  KK  &;Q:R1S TU r!c 2t|dd}t|dd}|dz|zdz|z} d| zdz|zdz|zdz|zdz} |jj| |j|jj||fgg|j_y) NidentrrDrrrrrr) rsendergrouptyperrrrQr wholeUserrs r_clientTestImplz)ClientImplementationTests._clientTestImplsB)2vv&SL5(3.5  /C'$.4u.removeFeature s]:D0C  ZdTF S  !6!6!A!A$!G N "DKK r!r<)rprrroN) mapsortedrgetChannelModeParamsrr2assertNotIdenticalr'r#)raddremover\s` rtest_getChannelModeParamsz3ClientImplementationTests.test_getChannelModeParamss  &$++"B"B"DE V <= !56 # k"&$++"B"B"DE V o. 1 h&$++"B"B"DE V b! $   5 5 @ @ JDQr!ctt|jj\}}|j |g|j |gy)z L{IRCClient.getUserModeParams} returns a list of user modes (modes that the user sets on themself, outside of channel modes) that require parameters when added and removed, respectively. N)r]r^rgetUserModeParamsr)rrarbs rtest_getUserModeParamsz0ClientImplementationTests.test_getUserModeParams8sA &$++"?"?"AB V b! $r!NcZ|d}d|d|d|d}|jj|y)z@ Build a MODE string and send it to the client. Nrz:Wolf!~wolf@yok.utu.fi MODE rr)rr)rrrtargetrs r_sendModeChangez)ClientImplementationTests._sendModeChangeBs: >F0#avTJ   )r!c|d}t|D]]\}}|\}|j|d|jdd|jd|tfddD||<_|S)zO Parse the results, do some test and return the data to check. rrrWolf!~wolf@yok.utu.firc3(K|] }| ywr{r ).0r rs r z=ClientImplementationTests._parseModeChange..WsMStCyMs)rrr) enumeratertuple)rresultsrhrEresultrrs @r_parseModeChangez*ClientImplementationTests._parseModeChangeKs >F"7+ NIAv!LFD   V] 3   T&\+B C   T)_f 5M4LMMGAJ  N r!c|j|jj|}|j||g|j_y)zR Compare the expected result with the one returned by the client. N)rsrrr)rrrhrrs r_checkModeChangez*ClientImplementationTests._checkModeChangeZs<&&t{{'8'8&A * r!cJ|jd|jdgy)z Mode strings that do not begin with a directional character, C{'+'} or C{'-'}, have C{'+'} automatically prepended. r:)Tr:r{Nrirur+s rtest_modeMissingDirectionz3ClientImplementationTests.test_modeMissingDirectionbs$ S! 345r!c|jd|jdg|jd|jdgy)zx No parameters are passed to L{IRCClient.modeChanged} for modes that don't take any parameters. r;)Fr:r{z+n)TrEr{Nrwr+s rtest_noModeParametersz/ClientImplementationTests.test_noModeParametersjsD T" 456 T" 345r!c|jdd|jdg|jdd|jdgy)zk Parameters are passed to L{IRCClient.modeChanged} for modes that take parameters. +oa_user)Trr}z-o)Frr~Nrwr+s rtest_oneModeParameterz/ClientImplementationTests.test_oneModeParametertsH T8, 789 T8, 89:r!c|jdd|jdg|jdd|jddgy)z Mixing adding and removing modes that do and don't take parameters invokes L{IRCClient.modeChanged} with mode characters and parameters that match up. z+osvza_user another_user)Tosv)r}N another_userz+v-os)Trr~)Fos)rNNrwr+s rtest_mixedModesz)ClientImplementationTests.test_mixedModes~sO V%:; NOP W&;<  %'L M r!c|jdd|jg|jtj}|j t |d|jd|djy)z Passing an argument to modes that take no parameters results in L{IRCClient.modeChanged} not being called and an error being logged. r8rrazToo many parametersrN riruflushLoggedErrorsr r)rrassertSubstringgetErrorMessagererrorss rtest_tooManyModeParametersz4ClientImplementationTests.test_tooManyModeParameterssh T7+ b!''8 Va( 2F1I4M4M4OPr!c|jd|jg|jtj}|j t |d|jd|djy)z Passing no arguments to modes that do take parameters results in L{IRCClient.modeChange} not being called and an error being logged. r|razNot enough parametersrNrrs rtest_tooFewModeParametersz3ClientImplementationTests.test_tooFewModeParameterssf T" b!''8 Va( 4fQi6O6O6QRr!c|jj}|jd||jdg|d}|j |jd||jdd||jdg|y ) z A C{MODE} message whose target is our user (the nickname of our user, to be precise), as opposed to a channel, will be parsed according to the modes specified by L{IRCClient.getUserModeParams}. r|)rh)Trr{c ddgS)Nr r&r r r!rrezBClientImplementationTests.test_userMode..getUserModeParamss 9 r!rez+Zan_arg)Tr )rN)rrrirur)rrhres r test_userModez'ClientImplementationTests.test_userModes %% T&1 34VD  4;; 35FG T8F; 78Hr!cfd}tj_jj_j jd|jjjdjjdgjjjdjjjdjjjdjj!jj"jjjdjj%jj'djt)jj+djjjdy)a When the I{RPL_WELCOME} message is received a heartbeat is started that will send a I{PING} message to the IRC server every L{irc.IRCClient.heartbeatInterval} seconds. When the transport is closed the heartbeat looping call is stopped too. cJj}j|_|Sr{)_originalCreateHeartbeatclock) heartbeatrs r_createHeartbeatzBClientImplementationTests.test_heartbeat.._createHeartbeats"557I"jjIO r!rNr2r&z PING foo r)rClockrrrrrrI _heartbeatirc_RPL_WELCOMEr`rhostnamerrr,advanceheartbeatIntervalrrrgetDelayedCalls)rrs` rtest_heartbeatz(ClientImplementationTests.test_heartbeatsY  ZZ\ (, (D(D% 4;; 24DE T[[33T: ##E2.  6 6= --u5 ##DNN$8$8$:B? 4;;889 ##DNN$8$8$:NK %%' ""4( TZZ779:A> T[[33T:r!c|j|jjdd|j_|jj dg|j|jjdy)zo If L{irc.IRCClient.heartbeatInterval} is set to L{None} then no heartbeat is created. Nr2)rIrrrrr+s rtest_heartbeatDisabledz0ClientImplementationTests.test_heartbeatDisabledsX T[[33T:(, % ##E2. T[[33T:r!)r&Nr{)!rrrrrr r#r(r+r2r4r7r=rArDrMrOrVrYrcrfrirsrurxrzrrrrrrrr r!rr r Ws: :?>  B <=Y N >5B $ < RD%* 66;   Q SI*;B;r!r ceZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZdZdZdZdZdZdZy)BasicServerFunctionalityTestsct|_tj|j|_t j |_|jj|jyr{) rfrrrCr IRCprr+s rrz#BasicServerFunctionalityTests.setUpsE')%%dff- dff%r!c|jj}t|tr|j d}|j ||y)z Make sure that the internal buffer equals a specified value. @param s: the value to compare against buffer @type s: L{bytes} or L{unicode} rN)rrrrrr)rr:rs rcheckz#BasicServerFunctionalityTests.checks>ffoo' a %,,W5K a(r!c`|jjddd|jdy)z Passing a command and parameters to L{IRC.sendMessage} results in a query string that consists of the command and parameters, separated by a space, ending with ' '. CMDparam1param2CMD param1 param2 N)r sendMessagerr+s rtest_sendMessagez.BasicServerFunctionalityTests.test_sendMessages' 5(H5 *+r!c^|jjdd|jdy)aF Passing a command and parameters to L{IRC.sendCommand} results in a query string that consists of the command and parameters, separated by a space, ending with ' '. The format is described in more detail in U{RFC 1459 }. rrrrNr sendCommandrr+s rtest_sendCommandz.BasicServerFunctionalityTests.test_sendCommands& 5"67 *+r!c^|jjdd|jdy)zk Passing unicode parameters to L{IRC.sendCommand} encodes the parameters in UTF-8. r)uparam¹uparam²sCMD param¹ param² Nrr+s rtest_sendUnicodeCommandz5BasicServerFunctionalityTests.test_sendUnicodeCommand s& 5"@A 9:r!c|jt|jjddd}|j t |dy)zf Passing L{None} as the command to L{IRC.sendMessage} raises a C{ValueError}. NrrIRC message requires a command.r(rrrrrrerrors rtest_sendMessageNoCommandz7BasicServerFunctionalityTests.test_sendMessageNoCommands@ !! **D(H  U%FGr!c|jt|jjdd}|j |j ddy)zf Passing L{None} as the command to L{IRC.sendCommand} raises a C{ValueError}. Nrrrr(rrrrrrs rtest_sendCommandNoCommandz7BasicServerFunctionalityTests.test_sendCommandNoCommandsC !! **D2F  A(IJr!c|jt|jjddd}|j t |dy)zi Passing an invalid string command to L{IRC.sendMessage} raises a C{ValueError}. rrrzCSomebody screwed up, 'cuz this doesn't look like a command to me: Nrrs rtest_sendMessageInvalidCommandz?r!c`|jjddd|jdy)z Passing a command and parameters with a specified prefix to L{IRC.sendCommand} results in a proper query string including the specified line prefix. rrirc.example.com$:irc.example.com CMD param1 param2 Nrr+s rtest_sendCommandWithPrefixz8BasicServerFunctionalityTests.test_sendCommandWithPrefix=s) 5"68IJ <=r!cBdddd}d}|jjddd||jj}|j d d \}}|d dj d }|j |d |j t |t |y) aM Passing a command and parameters with a specified prefix and tags to L{IRC.sendCommand} results in a proper query string including the specified line prefix and appropriate tags syntax. The query string should be output as follows: @tags :prefix COMMAND param1 param2 The tags are a string of IRCv3 tags, preceded by '@'. The rest of the string is as described in test_sendMessage. For more on the message tag format, see U{the IRCv3 specification }. bbbNeee)aaaccczexample.com/ddd)aaa=bbbscccsexample.com/ddd=eeerrr ra;rrrrrsplitrr^rsendTags expectedTagsoutMsg outTagStroutLineoutTagss rtest_sendCommandWithTagsz6BasicServerFunctionalityTests.test_sendCommandWithTagsFs!%HC  5"68I8T"#\\$2 7AB-%%d+ "KL  -vg?r!cdddd}|jt|jjddd|}|j |j dd y) zW Passing empty tag names to L{IRC.sendCommand} raises a C{ValueError}. rNr&)rrr&rrrrA tag name is required.rrrrs r!test_sendCommandValidateEmptyTagsz?BasicServerFunctionalityTests.test_sendCommandValidateEmptyTags_sW!26!!  FF        A(ABr!cdddd}|jt|jjddd|}|j |j dd y) zb Passing None as a tag name to L{IRC.sendCommand} raises a C{ValueError}. rNbeep)rrNrrrrrrrs r test_sendCommandValidateNoneTagsz>BasicServerFunctionalityTests.test_sendCommandValidateNoneTagsnsW !V<!!  FF        A(ABr!cddi}|jt|jjddd|}|j |j ddy) zl Passing a tag name containing spaces to L{IRC.sendCommand} raises a C{ValueError}. zaaa bbbrrrrr Tag contains invalid characters.Nrrs r&test_sendCommandValidateTagsWithSpaceszDBasicServerFunctionalityTests.test_sendCommandValidateTagsWithSpaces~U u%!!  FF        A(JKr!cddi}|jt|jjddd|}|j |j ddy) zx Passing a tag name containing invalid characters to L{IRC.sendCommand} raises a C{ValueError}. zaaa_b^@rrrrrrNrrs r,test_sendCommandValidateTagsWithInvalidCharszJBasicServerFunctionalityTests.test_sendCommandValidateTagsWithInvalidCharsrr!cddd}d}|jjddd||jj}|j dd \}}|d d j d }|j t |t |y ) zr Tags with values containing invalid characters passed to L{IRC.sendCommand} are escaped. rz test \;;)rr)rsccc=test\r\n\s\\\:\:rrrrraNrrrs r(test_sendCommandValidateTagValueEscapingzFBasicServerFunctionalityTests.test_sendCommandValidateTagValueEscapings !9C  5"68I8T"#\\$2 7AB-%%d+ &*>?r!c`|jjddd|jdy)Nthis-is-sender this-is-recipzthis is messagez8:this-is-sender PRIVMSG this-is-recip :this is message )rrrr+s rrYz)BasicServerFunctionalityTests.testPrivmsgs% ':KL OPr!c`|jjddd|jdy)Nrrzthis is noticez6:this-is-sender NOTICE this-is-recip :this is notice )rnoticerr+s r testNoticez(BasicServerFunctionalityTests.testNotice%  &9IJ MNr!c`|jjddd|jdy)Nrrzthis is actionz6:this-is-sender ACTION this-is-recip :this is action )rrrr+s r testActionz(BasicServerFunctionalityTests.testActionrr!c^|jjdd|jdy)N this-personz #this-channelz!:this-person JOIN #this-channel )rjoinrr+s rtestJoinz&BasicServerFunctionalityTests.testJoin!  M?3 89r!c^|jjdd|jdy)Nrz #that-channelz!:this-person PART #that-channel )rpartrr+s rtestPartz&BasicServerFunctionalityTests.testPartrr!c2ttjdz }|jj}d}d}|jj ||dddddd d |d d g gd }dj |t ||||z}|j|y)zp Verify that a whois by the client receives the right protocol actions from the server. dzrequesting-nickz target-nickrhzhost.comz Target Userz irc.host.comz A fake serverF z #fakeusersz #fakemisc)zA:%(hostname)s 311 %(req)s %(targ)s target host.com * :Target Userz>:%(hostname)s 312 %(req)s %(targ)s irc.host.com :A fake serverzN:%(hostname)s 317 %(req)s %(targ)s 12 %(timestamp)s :seconds idle, signon timez8:%(hostname)s 319 %(req)s %(targ)s :#fakeusers #fakemiscz6:%(hostname)s 318 %(req)s %(targ)s :End of WHOIS list.r&r)r timestampreqtargN)r<timerrwhoisrr r)rrrrrrKrs r testWhoisz'BasicServerFunctionalityTests.testWhoiss  c)* 66??            ; '  ;;u%$)   8r!N)rrrrrrrrrrrrrrrrrrrrYrrrrrr r!rrrs|& ), ,;HK  @>@2 CC L L @"QOO::!r!rc.eZdZdZdZdZdZdZdZy) DummyClientz{ A L{twisted.words.protocols.irc.IRCClient} that stores sent lines in a C{list} rather than transmitting them. cg|_yr{)rKr+s rrzDummyClient.__init__s  r!cPtjj|g|_yr{)r r connectionMaderKr+s rr zDummyClient.connectionMades $$T* r!cT|dtjt|jz S)zE Truncate an IRC line to the maximum allowed length. N)r MAX_COMMAND_LENGTHr delimiterrlines r _truncateLinezDummyClient._truncateLines&Bc,,s4>>/BBCCr!cd|j|}tjj||Sr{)rr r lineReceivedr s rrzDummyClient.lineReceiveds)!!$'}}))$55r!cX|jj|j|yr{)rKrr)rms rsendLinezDummyClient.sendLines $,,Q/0r!N) rrrr]rr rrrr r!rrrs! D 6 1r!rc"eZdZdZdZdZdZy)ClientInviteTestsz( Tests for L{IRCClient.invite}. c"t|_y)zO Create a L{DummyClient} to call C{invite} on in test methods. N)rrr+s rrzClientInviteTests.setUps "m r!c|jjdd|j|jjdgy)z If the channel name passed to L{IRCClient.invite} does not begin with a channel prefix character, one is prepended to it. r2rINVITE foo #barNrinviterrKr+s rtest_channelCorrectionz(ClientInviteTests.test_channelCorrections6 5%( **->,?@r!c|jjdd|j|jjdgy)zs L{IRCClient.invite} sends an I{INVITE} message with the specified username and a channel. r2#barrNrr+s r test_invitezClientInviteTests.test_invites6 5&) **->,?@r!N)rrrr]rrrr r!rrrs$ AAr!rceZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZddZ ddZdZdZdZdZdZdZdZdZdZdZy)ClientMsgTestszP Tests for messages sent with L{twisted.words.protocols.irc.IRCClient}. cVt|_|jjyr{)rrr r+s rrzClientMsgTests.setUp$s!m  ""$r!c|jjdd|j|jjdgy)zO A message containing no newlines is sent in a single command. r2rPRIVMSG foo :barN)rrrrKr+s rtest_singleLinezClientMsgTests.test_singleLine(s4 u% **-?,@Ar!c|jt|jjddd|jt|jjdddy)z Specifying a C{length} value to L{IRCClient.msg} that is too short to contain the protocol command to send a message raises C{ValueError}. r2rrrcN)r(rrrr+s rtest_invalidMaxLengthz$ClientMsgTests.test_invalidMaxLength/s@ *dkkooueQG *dkkooueQGr!ctddzdz}|jjdd||j|jjgdy)z Messages longer than the C{length} parameter to L{IRCClient.msg} will be split and sent in multiple commands. PRIVMSG foo :rcrbr2barbazbo)r$PRIVMSG foo :bazzPRIVMSG foo :boNrrrrrK)r maxLen_msgs rtest_multipleLine_msgz$ClientMsgTests.test_multipleLine_msg7sJ )A-1  z:6  KK   G r!ctddzdz}|jjdd||j|jjgdy)z Messages longer than the C{length} parameter to L{IRCClient.notice} will be split and sent in multiple commands. NOTICE foo :rcrbr2r*)NOTICE foo :barNOTICE foo :bazzNOTICE foo :boNrrrrrK)r maxLen_notices rtest_multipleLine_noticez'ClientMsgTests.test_multipleLine_noticeCsL N+a/!3  5*m<  KK   D r!c8d}td|dz}|jjd|||j|jjd|gg|j_|jjd||dz |jdt|jjg|j_|jjd||dz|jdt|jjy)z Messages exactly equal in length to the C{length} parameter to L{IRCClient.msg} are sent in a single command. r*r)rbr2raNr,rrmaxLens rtest_sufficientWidth_msgz'ClientMsgTests.test_sufficientWidth_msgOs }SE*+a/ sF+ **}SE-B,CD  sFQJ/ C 1 123  sFQJ/ C 1 123r!c8d}td|dz}|jjd|||j|jjd|gg|j_|jjd||dz |jdt|jjg|j_|jjd||dz|jdt|jjy)z Messages exactly equal in length to the C{length} parameter to L{IRCClient.notice} are sent in a single command. r*r0rbr2raNr3r7s rtest_sufficientWidth_noticez*ClientMsgTests.test_sufficientWidth_notice_s |C5)*Q. 5#v. **|C5-A,BC  5#vz2 C 1 123  5#vz2 C 1 123r!cg|j_|jjdd|j|jjdgy)zC An LF at the beginning of the message is ignored. r2 barr$NrrKrrr+s rtest_newlinesAtStart_msgz'ClientMsgTests.test_newlinesAtStart_msgo@  w' **-?,@Ar!cg|j_|jjdd|j|jjdgy)zB An LF at the beginning of the notice is ignored. r2r=r1NrrKrrr+s rtest_newlinesAtStart_noticez*ClientMsgTests.test_newlinesAtStart_noticewB  5'* **->,?@r!cg|j_|jjdd|j|jjdgy)z= An LF at the end of the message is ignored. r2bar r$Nr>r+s rtest_newlinesAtEnd_msgz%ClientMsgTests.test_newlinesAtEnd_msgr@r!cg|j_|jjdd|j|jjdgy)z< An LF at the end of the notice is ignored. r2rFr1NrBr+s rtest_newlinesAtEnd_noticez(ClientMsgTests.test_newlinesAtEnd_noticerDr!cg|j_|jjdd|j|jjddgy)z; An LF within a message causes a new line. r2bar bazr$r+Nr>r+s rtest_newlinesWithinMessage_msgz-ClientMsgTests.test_newlinesWithinMessage_msgsC  z* **-?AS,TUr!cg|j_|jjdd|j|jjddgy)z: An LF within a notice causes a new line. r2rKr1r2NrBr+s r!test_newlinesWithinMessage_noticez0ClientMsgTests.test_newlinesWithinMessage_noticesE  5*- **->@Q,RSr!cg|j_|jjdd|j|jjddgy)zH Consecutive LFs in messages do not cause a blank line. r2bar bazr$r+Nr>r+s rtest_consecutiveNewlines_msgz+ClientMsgTests.test_consecutiveNewlines_msgsC  |, **-?AS,TUr!cg|j_|jjdd|j|jjddgy)zG Consecutive LFs in notices do not cause a blank line. r2rPr1r2NrBr+s rtest_consecutiveNewlines_noticez.ClientMsgTests.test_consecutiveNewlines_noticesE  5,/ **->@Q,RSr!Nc dj|jj|jj|jj}|jj d||g|j |jdfd|jjD] }|jj||z"|jt|djdD}|j||y) z Assert that messages sent by L{IRCClient.msg} are split into an expected number of commands and the original message is transmitted in its entirety over those commands. :{}!{}@{} r2lengthrc&j|Sr{r)rrs rz?ClientMsgTests.assertLongMessageSplitting_msg..sgnnQ6Gr!r&c3(K|] \}}}| ywr{r rmrrhrs rrnz@ClientMsgTests.assertLongMessageSplitting_msg..s!O.CdFG'!ON) r*rrrealnamerrrrKrrrr)rrexpectedNumCommandsrWresponsePrefixrreceivedMessagers @rassertLongMessageSplitting_msgz-ClientMsgTests.assertLongMessageSplitting_msgs &,, KK KK KK   wv6 4;; +GHKK%% .sfmmA6Fr!r&c3(K|] \}}}| ywr{r r\s rrnzCClientMsgTests.assertLongMessageSplitting_notice..s!N.CdFG'!Nr]N) r*rrr^rrrrKrrrr)rrr_rWr`rrars @r!assertLongMessageSplitting_noticez0ClientMsgTests.assertLongMessageSplitting_notices&,, KK KK KK   5'&9 4;; +FGKK%% //!34 ++ Qs55: , r!czdtjdz z}|j|dtjdzy)a The maximum message length can be specified to L{IRCClient.notice}, messages longer than this are split into multiple commands with the intent of delivering long messages without losing data due to message truncation when the server relays them. rrbrcrVNrlris r)test_splitLongMessagesWithOverride_noticez8ClientMsgTests.test_splitLongMessagesWithOverride_notices>//!34 .. Qs55: / r!cdtjdzz}|jjd|dz|z|j |jj d|zd|zgy)zK IRCClient breaks on newlines before it breaks long lines. rrbr2 r)Nr r rrrrKrlonglines rtest_newlinesBeforeLineBreakingz.ClientMsgTests.test_newlinesBeforeLineBreakings` #00A56 x$9:  KK  ( :OhH: :t}}/E/E G    ##DNN$8$8$:$@$@$I8Tr!c d}d}d}d|j_d|j_|jj|||d|jjd|d|d |d |d |jjd g}|j |j j jd |y )z If the C{password} attribute of L{IRCClient} is not L{None}, the C{register} method also sends a PASS command with it as the argument. rrrrtestpasszPASS rrrrr&rNrrs rtest_registerWithPasswordz%ClientTests.test_registerWithPasswords ! !+ !+  x:>DMM**+ ,H: :t}}/E/E G    ##DNN$8$8$:$@$@$I8Tr!cd}d}d}d|j_d|j_|jj||||jj ddg|j |j }|j|d||jj ddg|j |j }|j|d j|d zy ) z Verify that the client repeats the L{IRCClient.setNick} method with a new value when presented with an C{ERR_NICKNAMEINUSE} while trying to register. rrrrrrrrNICK {}rN) rr^rrirc_ERR_NICKNAMEINUSErrrrr*)rrrrlastLines rtest_registerWithTakenNickz&ClientTests.test_registerWithTakenNicks ! !+ !+  x:> ++Hwi@##DNN3 HhZ&89 ++Hwi@##DNN3 9#3#3HtO#DEr!cd}d|j_|jj||jjddg|j |j }|j |dj|dzy)z L{IRCClient.alterCollidedNick} determines how a nickname is altered upon collision while a user is trying to change to that nickname. r2c |dzS)N***r rs rrZz.s te|r!rrrrN)ralterCollidedNickrrrrrr*)rrrs rtest_overrideAlterCollidedNickz*ClientTests.test_overrideAlterCollidedNicksp *C ' t$ ++Hwi@##DNN3 9#3#3D5L#ABr!cd}d}|jj||jjddg|jj||j |jj ||jj |d|g|j |jj |y)z When a NICK command is sent after signon, C{IRCClient.nickname} is set to the new nickname I{after} the server sends an acknowledgement. r2rrrz !quux@quxN)rrrsetNickrrirc_NICK)roldnicknewnicks rtest_nickChangezClientTests.test_nickChanges  w' %%h : g& //9 ')4wi@ //9r!cd}|j|jjd|jj||jj ddg|j |j }|j|d|jj|jjddg|j|jjd|jj|jj|j|jj|jj|jj}|jj||jj ddg|j |j }|j|d||j|jj|y)z Trying to register an illegal nickname results in the default legal nickname being set, and trying to change a nickname to an illegal nickname results in the old nickname being kept. r2FrrrTN) rr _registeredrirc_ERR_ERRONEUSNICKNAMErrerroneousNickFallbackrrr)rbadnickrrs rtest_erroneousNickzClientTests.test_erroneousNickso 22E: w' ..x'C##DNN3 U4==+N+N*O#PQ %%h : 22D9 dmmAAB //1T1TU--(( g& ..x'C##DNN3 U7)#45 //9r!cd}d}d}|jj|||jj||d|d|dd|d|ddg}|j|jj j d|y ) zd L{IRCClient.desrcibe} sends a CTCP ACTION message to the target specified. r2rwaveszPRIVMSG z :ACTION r&rN)rdescriberrr,r)rrhrrrs r test_describezClientTests.test_describe s  vv. w/vhl6(# 6wi|F83 7   ##DNN$8$8$:$@$@$I8Tr!cnfd}|j_jjdddgy)zh The default implementation of L{IRCClient.noticed} doesn't invoke C{privmsg()} c(jdy)Nz%privmsg() should not have been called)fail)rrrrs rrz6ClientTests.test_noticedDoesntPrivmsg..privmsg( s II= >r!spamz#greasyspooncafezI don't want any spam!N)rr irc_NOTICE)rrs` rtest_noticedDoesntPrivmsgz%ClientTests.test_noticedDoesntPrivmsg" s1  ?!(    *<>V)WXr!c|jjd|j|jj j d|jj |jjdd|j|jj d|jj i|j_t|jjdzD];}tj|z|jjdt|f<=|jt|jj|jjdz|jjdd|jt|jj|jj|j|jj dy) z# L{IRCClient.ping} otherusersPRIVMSG otheruser :PINGz are you theres)PRIVMSG otheruser :PING are you there rczI sent a lot of pingss1PRIVMSG otheruser :PING I sent a lot of pings N)rpingr$rr,rclearr_pingsrange _MAX_PINGRINGrrr)rpingNums r test_pingzClientTests.test_ping. s ;'  NN " - -.L M   ;8  NN "$X   " T]]881<= XGBF))+PWBWDMM +W!> ? X T]]112DMM4O4ORS4ST ;(?@ T]]112DMM4O4OP  NN " H r!N)rrrr]rrrrrrrrrrrrrrrr r!rrrVsZ < & U U  U&U*F* C ::6U" Y r!rceZdZdZdZy)CollectorClientzQ A client that saves in a list the names of the methods that got called. cbg_d_|D]}|ffd }t||y)zx @param methodsList: list of methods' names that should be replaced. @type methodsList: C{list} Wolfcfd}|S)z6 Collects C{method}s. c@jj|fyr{)rr)rrrs rinnerz.fake_method..innerd sLL''7r!r )rrrs` r fake_methodz-CollectorClient.__init__..fake_method_ s 8 r!N)rrsetattr)r methodsListrrs` rrzCollectorClient.__init__U s:   ! 1F#)  D&+- 0 1r!N)rrrr]rr r!rrrP s 1r!rc^eZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZy)DccTestsz% Tests for C{dcc_*} methods. cHgd}d|_d|_t||_y)N) dccDoSenddccDoAcceptResume dccDoResume dccDoChatrk#twistedrrrrrrs rrzDccTests.setUpq s!P+ ! %g. r!c |jj|j|jd|j |jj d|jddddgdffgy) zO L{irc.IRCClient.dcc_SEND} invokes L{irc.IRCClient.dccDoSend}. foo.txt 127.0.0.1 1025r 127.0.0.1foo.txtr{rr1025N)rdcc_SENDrrrrr+s r test_dccSendzDccTests.test_dccSendw sh TYY 6NO  KK    #!8    r!cptj}|jt|jddy)zM L{irc.IRCClient.dccDoSend} is raises C{NotImplementedError} rN)r r r(NotImplementedErrordccSend)rrs rtest_dccSendNotImplementedz#DccTests.test_dccSendNotImplemented s( -v~~z4Pr!c|jtj|jj|j |j d}|jt|dy)z{ L{irc.IRCClient.dcc_SEND} raises L{irc.IRCBadMessage} when it is passed a malformed query string. r2z#malformed DCC SEND request: ['foo']N r(r IRCBadMessagerrrrrrrrrs rtest_dccSendMalformedRequestz%DccTests.test_dccSendMalformedRequest N ""   t{{33TYY e  V&KLr!c|jtj|jj|j |j d}|jt|dy)z L{irc.IRCClient.dcc_SEND} raises L{irc.IRCBadMessage} when it is passed a query string that doesn't contain a valid address. zfoo.txt #23 sd@dzIndecipherable address '#23'Nrrs r!test_dccSendIndecipherableAddressz*DccTests.test_dccSendIndecipherableAddress sR ""    KK II LL    V&DEr!c|jtj|jj|j |j d}|jt|dy)z L{irc.IRCClient.dcc_SEND} raises L{irc.IRCBadMessage} when it is passed a query string that doesn't contain a valid port number. foo.txt 127.0.0.1 sd@dIndecipherable port 'sd@d'Nrrs rtest_dccSendIndecipherablePortz'DccTests.test_dccSendIndecipherablePort R ""    KK II LL $   V&BCr!c|jj|j|jd|j |jj d|jdddffgy)zY L{irc.IRCClient.dcc_ACCEPT} invokes L{irc.IRCClient.dccDoAcceptResume}. foo.txt 1025 2rrrrbN)r dcc_ACCEPTrrrrr+s rtest_dccAcceptzDccTests.test_dccAccept sV tyy$,,8HI  KK  !DIIy$#B C D r!c|jtj|jj|j |j d}|jt|dy)z} L{irc.IRCClient.dcc_ACCEPT} raises L{irc.IRCBadMessage} when it is passed a malformed query string. r2z*malformed DCC SEND ACCEPT request: ['foo']N) r(r rrrrrrrrs rtest_dccAcceptMalformedRequestz'DccTests.test_dccAcceptMalformedRequest O ""   t{{55tyy$,,PU  V&RSr!c|jj|j|jd|j |jj d|jdddffgy)zS L{irc.IRCClient.dcc_RESUME} invokes L{irc.IRCClient.dccDoResume}. rrrrrbN)r dcc_RESUMErrrrr+s rtest_dccResumezDccTests.test_dccResume sU tyy$,,8HI  KK  =499iq2Q"R!S r!c|jtj|jj|j |j d}|jt|dy)z} L{irc.IRCClient.dcc_RESUME} raises L{irc.IRCBadMessage} when it is passed a malformed query string. r2z*malformed DCC SEND RESUME request: ['foo']N) r(r rrr rrrrrs rtest_dccResumeMalformedRequestz'DccTests.test_dccResumeMalformedRequest r r!c |jj|j|jd|j |jj d|j|jddgdffgy)zO L{irc.IRCClient.dcc_CHAT} invokes L{irc.IRCClient.dccDoChat}. rrrrrN)rdcc_CHATrrrrr+s r test_dccChatzDccTests.test_dccChat si TYY 6NO  KK     #8    r!c|jtj|jj|j |j d}|jt|dy)z{ L{irc.IRCClient.dcc_CHAT} raises L{irc.IRCBadMessage} when it is passed a malformed query string. r2z#malformed DCC CHAT request: ['foo']N r(r rrrrrrrrs rtest_dccChatMalformedRequestz%DccTests.test_dccChatMalformedRequest rr!c|jtj|jj|j |j d}|jt|dy)z L{irc.IRCClient.dcc_CHAT} raises L{irc.IRCBadMessage} when it is passed a query string that doesn't contain a valid port number. rrNrrs rtest_dccChatIndecipherablePortz'DccTests.test_dccChatIndecipherablePort rr!N)rrrr]rrrrrrrr rrrrrr r!rrrl sP/  ,QM F D T T *M Dr!rcFeZdZdZdZdZdZdZdZdZ dZ d Z d Z y ) ServerToClientTestszL Tests for the C{irc_*} methods sent from the server to the client. cHd|_d|_gd}t||_y)Nrkr) rrrruserQuitrrrrrrs rrzServerToClientTests.setUp s%+ !   &g. r!c |jj|j|jg|jjddg|j |jj d|jffdgy)z L{IRCClient.joined} is called when I join a channel; L{IRCClient.userJoined} is called when someone else joins. Svadilfari!~svadi@yok.utu.fi#pythonr)r SvadilfarirN)rirc_JOINrrrrr+s r test_irc_JOINz!ServerToClientTests.test_irc_JOIN$ sh TYY7 ;i[I  KK   (*S T r!c |jj|j|jg|jjddg|j |jj d|jffdgy)z L{IRCClient.left} is called when I part the channel; L{IRCClient.userLeft} is called when someone else parts. rrr)rr N)rirc_PARTrrrrr+s r test_irc_PARTz!ServerToClientTests.test_irc_PART0 sh TYY7 ;i[I  KK  t||o &(O P r!c|jjddg|jj|jdg|j|jjddgy)zo L{IRCClient.userQuit} is called whenever someone quits the channel (myself included). rAdios. Farewell.)r)r!r()r)rr)N)rirc_QUITrrrr+s r test_irc_QUITz!ServerToClientTests.test_irc_QUIT< s[ ;hZH TYY 6  KK  63  r!c>dtjtjtjzdz}|jj |j |j|g|j|jjd|j ddffgy)zK L{IRCClient.noticed} is called when a notice is received. z:%(X)cextended%(X)cdata1%(X)cextended%(X)cdata2%(X)c%(EOL)srrrz data1 data2N) r rrrrrrrrrrs rtest_irc_NOTICEz#ServerToClientTests.test_irc_NOTICEK s~K66CFF?N   tyy4<<*=>  KK  9tyy*m.T"U!V r!c |jjdgd|jj|j|jddg|j |jj ddd|jddffgy) z L{IRCClient.kickedFrom} is called when I get kicked from the channel; L{IRCClient.userKicked} is called when someone else gets kicked. r)rWOLF shoryuken!r!z hadouken!)r)rr!r0rrN)rirc_KICKrrrrr+s r test_irc_KICKz!ServerToClientTests.test_irc_KICKX sy  *,M  TYY|[(QR  KK  G dllFKPQ  r!c|jj|j|jdg|j |jj dd|jdffgy)zR L{IRCClient.topicUpdated} is called when someone sets the topic. new topic is newrrN)r irc_TOPICrrrrr+s rtest_irc_TOPICz"ServerToClientTests.test_irc_TOPICj sX dii$,,8J)KL  KK  vt||5GH I J r!c|jj|jd|jdg|j |jj dd|jdffgy)zc L{IRCClient.topicUpdated} is called when the topic is initially reported. ?r4rrN)r irc_RPL_TOPICrrrrr+s rtest_irc_RPL_TOPICz&ServerToClientTests.test_irc_RPL_TOPICt sZ !!$))c4<FDLL"3M"N!O r!N) rrrr]rr#r&r+r-r2r6r:r=r r!rrr s4/         $    r!rc@eZdZdZdZdZdZdZdZdZ dZ d Z y ) CTCPQueryTestsz/ Tests for the C{ctcpQuery_*} methods. cBd|_d|_tdg|_y)Nrkr ctcpMakeReplyrr+s rrzCTCPQueryTests.setUp s+ ! %&78 r!c|jj|j|jd|j |jj dddgffgy)zm L{IRCClient.ctcpQuery_PING} calls L{IRCClient.ctcpMakeReply} with the correct args. rrAr)PINGrN)rctcpQuery_PINGrrrrr+s rtest_ctcpQuery_PINGz"CTCPQueryTests.test_ctcpQuery_PING sP ""499dllFC  KK  ?V>N=O4P"Q!R r!cd|j_|jj|j|jd|j |jj dddgffgy)zo L{IRCClient.ctcpQuery_FINGER} calls L{IRCClient.ctcpMakeReply} with the correct args. rrrAr)FINGERrN)r fingerReplyctcpQuery_FINGERrrrrr+s rtest_ctcpQuery_FINGERz$CTCPQueryTests.test_ctcpQuery_FINGER s\ #*  $$TYY fE  KK  ?V>Q=R4S"T!U r!cd|j_|jj|j|jd|j |jj ddddgffgy)zo L{IRCClient.ctcpQuery_SOURCE} calls L{IRCClient.ctcpMakeReply} with the correct args. urlrrAr)SOURCErL)rMNN)r sourceURLctcpQuery_SOURCErrrrr+s rtest_ctcpQuery_SOURCEz$CTCPQueryTests.test_ctcpQuery_SOURCE s` !&  $$TYY fE  KK  ):R=S4T"U!V r!c4|jj|j|jd|jj|j|jdd}|j |jj ddd|fgffdddgffgy) zs L{IRCClient.ctcpQuery_CLIENTINFO} calls L{IRCClient.ctcpMakeReply} with the correct args. r&z PING PONGzEACTION CLIENTINFO DCC ERRMSG FINGER PING SOURCE TIME USERINFO VERSIONrAr CLIENTINFO)rWNN)rctcpQuery_CLIENTINFOrrrr)rrs rtest_ctcpQuery_CLIENTINFOz(CTCPQueryTests.test_ctcpQuery_CLIENTINFO s ((DLL"E ((DLL+N V   KK   6\4,@+A"BC 6,@+A"BC  r!c|jj|j|jd|j |jj ddddy)zm L{IRCClient.ctcpQuery_TIME} calls L{IRCClient.ctcpMakeReply} with the correct args. rrrarN)rctcpQuery_TIMErrrrr+s rtest_ctcpQuery_TIMEz"CTCPQueryTests.test_ctcpQuery_TIME sK ""499dllFC ,,Q/215v>r!c|jj|j|jd|j |jj dddgffgy)zl L{IRCClient.ctcpQuery_DCC} calls L{IRCClient.ctcpMakeReply} with the correct args. rrAr)ERRMSGz!DCC data :Unknown DCC type 'DATA'N)r ctcpQuery_DCCrrrrr+s rtest_ctcpQuery_DCCz!CTCPQueryTests.test_ctcpQuery_DCC sX !!$))T\\6B  KK  $MNO  r!N) rrrr]rrErJrPrUrYr\r`r r!rr?r? s/9         $? r!r?ceZdZdZdZy)DccChatFactoryTestsz& Tests for L{DccChatFactory}. cd}tjd|}|jd}|j|tj|j |j |y)z An instance of the L{irc.DccChat} protocol is returned, which has the factory property set to the factory which created it. )fromUserNNNr)r DccChatFactory buildProtocolassertIsInstanceDccChatrfactory)r queryDatarirs rtest_buildProtocolz&DccChatFactoryTests.test_buildProtocol sU - $$T95((5 h 4 ))73r!N)rrrr]rkr r!rrbrb s  4r!rbceZdZdZdZy)DccDescribeTestsz# Tests for L{dccDescribe}. cRtjd}|j|dy)z@ L{irc.dccDescribe} supports long IP addresses. zCHAT arg 3232235522 6666z$CHAT for host 192.168.0.2, port 6666N)r dccDescriberrs r test_addresszDccDescribeTests.test_address s$!;< !GHr!N)rrrr]rpr r!rrmrm s Ir!rmcHeZdZdZd dZdZdZdZdZdZ d Z d Z d Z y) DccFileReceiveTestsz& Tests for L{DccFileReceive}. Nctj||}|r|jdt}|j||S)a Factory helper that returns a L{DccFileReceive} instance for a specific test case. @param filename: Path to the local file where received data is stored. @type filename: L{str} @param resumeOffset: An integer representing the amount of bytes from where the transfer of data should be resumed. @type resumeOffset: L{int} @param overwrite: A boolean specifying whether the file to write to should be overwritten by calling L{DccFileReceive.set_overwrite} or not. @type overwrite: L{bool} @return: An instance of L{DccFileReceive}. @rtype: L{DccFileReceive}  resumeOffsetT)r DccFileReceive set_overwriterr)rfilenameru overwriterrs rmakeConnectedDccFileReceivez/DccFileReceiveTests.makeConnectedDccFileReceive sF(%%h\J  "H " "4 (#%  *r!cL|j||jdy)z Arrange the protocol so that it received all data. @param protocol: The protocol which will receive the data. @type: L{DccFileReceive} @param data: The received data. @type data: L{bytest} N)rr)rrrs rallDataReceivedForProtocolz.DccFileReceiveTests.allDataReceivedForProtocol( s$ d#%r!ct|j}|jd|j|jd}|j |d|j |jdy)z If given a resumeOffset argument, L{DccFileReceive} will attempt to resume from that number of bytes if the file exists. sTwisted is awesome! rtsamazing!Twisted is amazing!Nrmktemp setContentrzpathr|r getContentrfprs rtest_resumeFromResumeOffsetz/DccFileReceiveTests.test_resumeFromResumeOffset5 sa dkkm $ ,-33BGG"3M ''+> *@Ar!ct|j}|jd|j|jd}|j |d|j |jdy)aG When resuming from an offset somewhere in the middle of the file, for example, if there are 50 bytes in a file, and L{DccFileReceive} is given a resumeOffset of 25, and after that 15 more bytes are written to the file, then the resultant file should have just 40 bytes of data. rr~rtscool!sTwisted is cool!Nrrs r:test_resumeFromResumeOffsetInTheMiddleOfAlreadyWrittenDatazNDccFileReceiveTests.test_resumeFromResumeOffsetInTheMiddleOfAlreadyWrittenDataB sadkkm $ ,-33BGG"3M ''(; *=>r!ct|j}|jd|j|jd}|j |d|j |jdy)z When local file already exists it can be overwritten using the L{DccFileReceive.set_overwrite} method. sI love contributing to Twisted!T)rysTwisted rocks!Nrrs rtest_setOverwritez%DccFileReceiveTests.test_setOverwriteR sb dkkm $ 8933BGGt3L ''2CD *;rs  +L,+'B+(+*M&{M&`  ,\ \ ~" K" L:'..377.;(//366cff/E2 KKckk*+  C; C ,,(FkFD_;+_;D CMMz) z)zE*EPH; H;V BKBJ1#--18A A8tR[tRn w +w t1cmm18`D{`DFw +w t^ [^ B4+4" I{ I@N+@Nr!