├── irctestframework ├── __init__.py ├── defaults.py └── wrapper ├── .gitignore ├── serverconfig ├── unrealircd │ ├── ircd.rules │ ├── ircd.motd │ ├── oper.motd │ ├── db_crypted.conf │ ├── irc3.conf │ ├── irc2.conf │ ├── irc1.conf │ ├── modules │ │ └── fakereputation.c │ └── common.conf ├── anope │ ├── config.cache │ └── install_anope └── atheme │ ├── install_atheme │ └── services.db ├── tests ├── serial │ ├── README │ ├── time_extban_expiry │ ├── netsplit_simple │ └── netsplit_merge ├── usercommands │ ├── admin │ ├── credits │ ├── license │ ├── info │ ├── time │ ├── ison │ ├── map │ ├── setident │ ├── rules │ ├── links │ ├── motd │ ├── version │ ├── part │ ├── nick │ ├── lusers │ ├── cycle │ ├── module │ ├── setname │ ├── userhost │ ├── quit │ ├── userip │ ├── join │ ├── notice │ ├── list │ ├── privmsg │ ├── vhost │ ├── names │ ├── knock │ ├── whowas │ ├── silence │ ├── away │ ├── topic │ ├── monitor │ ├── dccallow │ ├── watch │ ├── tagmsg │ ├── who │ ├── invite │ ├── whois │ ├── kick │ ├── mode │ └── history ├── basic ├── db │ ├── writing │ │ ├── reputation │ │ ├── permanent │ │ ├── tkl │ │ └── history │ └── reading │ │ ├── reputation │ │ ├── permanent │ │ ├── tkl │ │ └── history ├── opercommands │ ├── module │ ├── wallops │ ├── globops │ ├── tsctl │ ├── mkpasswd │ ├── chgident │ ├── sapart │ ├── sethost │ ├── chgname │ ├── chghost │ ├── opermotd │ ├── locops │ ├── dns │ ├── kill │ ├── tempshun │ ├── dccdeny │ ├── sajoin │ ├── oper │ ├── samode │ └── tkl ├── usermodes │ ├── bot │ ├── showwhois │ ├── nokick │ ├── privacy │ ├── noctcp │ ├── regonlymsg │ └── censor ├── extensions │ ├── userhost-in-names │ ├── cap-chghost │ ├── bot-tag │ ├── extended-join │ ├── multi-prefix │ ├── away-notify │ ├── cap │ └── labeled-response ├── chanmodes │ ├── nokick │ ├── noknock │ ├── noexternal │ ├── nonickchange │ ├── regonlyspeak │ ├── regonlyjoin │ ├── nonotice │ ├── noinvite │ ├── exempt │ ├── noctcp │ ├── censor │ ├── inviteonly │ ├── operonly │ ├── permanent │ ├── stripcolor │ ├── nocolor │ ├── link │ ├── ban │ ├── vhoaq │ ├── history │ ├── delayjoin │ └── flood ├── services │ ├── identify │ ├── account-notify │ ├── sasl │ ├── account-tag │ ├── sasl_pre-registration_client1 │ ├── sasl_pre-registration_client2 │ └── account_extban ├── extbans │ ├── quiet │ ├── realname │ ├── inchannel │ ├── nickchange │ ├── join │ ├── forward │ ├── text │ ├── msgbypass │ └── securitygroup └── _pre_test ├── check_missing_tests └── runwin /irctestframework/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *~ 3 | logs/ 4 | -------------------------------------------------------------------------------- /irctestframework/defaults.py: -------------------------------------------------------------------------------- 1 | print 'hello' 2 | -------------------------------------------------------------------------------- /serverconfig/unrealircd/ircd.rules: -------------------------------------------------------------------------------- 1 | This are the rules 2 | -------------------------------------------------------------------------------- /serverconfig/unrealircd/ircd.motd: -------------------------------------------------------------------------------- 1 | This is a test server 2 | -------------------------------------------------------------------------------- /serverconfig/unrealircd/oper.motd: -------------------------------------------------------------------------------- 1 | This is the oper MOTD 2 | last line of OPERMOTD 3 | -------------------------------------------------------------------------------- /serverconfig/anope/config.cache: -------------------------------------------------------------------------------- 1 | INSTDIR="$HOME/anope" 2 | RUNGROUP="" 3 | UMASK=077 4 | DEBUG="yes" 5 | USE_PCH="no" 6 | EXTRA_INCLUDE_DIRS="" 7 | EXTRA_LIB_DIRS="" 8 | EXTRA_CONFIG_ARGS="" 9 | -------------------------------------------------------------------------------- /tests/serial/README: -------------------------------------------------------------------------------- 1 | All the tests in this directory are run in series, 2 | so not in parallel. 3 | 4 | Please only put tests here that really need it, 5 | such as netsplit, as it hurts performance. 6 | -------------------------------------------------------------------------------- /tests/usercommands/admin: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | m.connect() 7 | 8 | m.send(c1a, "ADMIN") 9 | m.expect(c1a, "ADMIN output", ":.+ 256 $me :Administrative info about.*") 10 | m.clearlog() 11 | print 12 | -------------------------------------------------------------------------------- /tests/usercommands/credits: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | m.connect() 7 | 8 | m.send(c1a, "CREDITS") 9 | m.expect(c1a, "CREDITS output", ":.+ 371 $me :.*UnrealIRCd.*redits.*") 10 | m.clearlog() 11 | print 12 | -------------------------------------------------------------------------------- /tests/usercommands/license: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | m.connect() 7 | 8 | m.send(c1a, "LICENSE") 9 | m.expect(c1a, "LICENSE output", ":.+ 371 $me :.*UnrealIRCd License.*") 10 | m.clearlog() 11 | print 12 | -------------------------------------------------------------------------------- /tests/basic: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | print 14 | -------------------------------------------------------------------------------- /tests/usercommands/info: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | m.connect() 7 | 8 | m.send(c1a, "INFO") 9 | m.expect(c1a, "INFO output", ":.+ 371 $me :.*This release was brought to you by.*") 10 | m.clearlog() 11 | print 12 | -------------------------------------------------------------------------------- /tests/usercommands/time: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | m.connect() 7 | 8 | m.send(c1a, "TIME") 9 | m.expect(c1a, "TIME response", ":.+ 391 $me irc1\.test\.net :.* .* [0-9]+ [0-9]+ .*:.*") 10 | m.clearlog() 11 | print 12 | -------------------------------------------------------------------------------- /tests/db/writing/reputation: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | m.connect() 7 | 8 | m.send(c1a, "FAKEREPUTATION 127.0.0.1 500") 9 | m.expect(c1a, "Confirm setting reputation", "Reputation for.*127.0.0.1.*500"); 10 | m.clearlog() 11 | print 12 | -------------------------------------------------------------------------------- /tests/usercommands/ison: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send_all("ISON :$c1a thisnickdoesnotexist $c2a irc1.test.net $c3a") 11 | m.expect_all("ISON response", "$c1a $c2a $c3a") 12 | m.clearlog() 13 | print 14 | -------------------------------------------------------------------------------- /serverconfig/atheme/install_atheme: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | VERSION="7.2.10-r2" 3 | DIRECTORY="atheme-v${VERSION}" 4 | 5 | set -e 6 | set -x 7 | 8 | mkdir -p ~/tmp 9 | cd ~/tmp 10 | wget "https://github.com/atheme/atheme/releases/download/v${VERSION}/$DIRECTORY.tar.xz" -O "$DIRECTORY.tar.xz" 11 | tar xJvf $DIRECTORY.tar.xz 12 | cd $DIRECTORY 13 | ./configure --disable-nls 14 | make 15 | make install 16 | -------------------------------------------------------------------------------- /tests/usercommands/map: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | m.connect() 7 | 8 | m.send(c1a, "MAP") 9 | m.expect(c1a, "IRC1", ":.+ 006 $me :irc1\.test\.net") 10 | m.expect(c1a, "IRC2", ":.+ 006 $me :`-irc2\.test\.net") 11 | m.expect(c1a, "IRC3", ":.+ 006 $me : `-irc3\.test\.net") 12 | m.clearlog() 13 | print 14 | -------------------------------------------------------------------------------- /tests/opercommands/module: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | m.connect() 7 | 8 | m.send(c1a, "OPER netadmin test") 9 | m.send(c1a, "MODULE -all") 10 | m.expect(c1a, "MODULE reply with version information", ":irc.+ 304 $me :\*\*\* oper 5[^ ]+ - command \/oper - by UnrealIRCd Team") 11 | m.clearlog() 12 | print 13 | -------------------------------------------------------------------------------- /tests/usercommands/setident: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c1a, 'SETIDENT :newident') 11 | m.clearlog() 12 | 13 | m.send_all('WHOIS $c1a') 14 | m.expect_all("New ident in WHOIS", ":.* 311 $me $c1a newident .*") 15 | m.clearlog() 16 | print 17 | -------------------------------------------------------------------------------- /tests/usermodes/bot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | 11 | m.send(c1a, "MODE $c1a +B") 12 | m.send_all("WHOIS $c1a") 13 | m.expect(c1a, "MODE set", "MODE $c1a :\+B") 14 | m.expect(c1a, "Receive BOTMOTD", "BOTMOTD") 15 | m.expect_all("Show bot status in /WHOIS", "is a.*Bot.*on") 16 | print 17 | -------------------------------------------------------------------------------- /tests/db/reading/reputation: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | m.connect() 7 | 8 | m.send(c1a, "OPER netadmin test") 9 | m.send(c1a, "REPUTATION 127.0.0.1") 10 | # Allow for some wiggle room, we set 500 before but a score of 500-505 is considered OK. 11 | m.expect(c1a, "Confirm reputation was set to value from before (500)", "Score: 50[012345]"); 12 | m.clearlog() 13 | print 14 | -------------------------------------------------------------------------------- /tests/usercommands/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | m.connect() 7 | 8 | m.send(c1a, "RULES") 9 | m.expect(c1a, "RULES output 308 (header)", ":.+ 308 $me :- irc.* Server Rules") 10 | m.expect(c1a, "RULES output 232 (text)", ":.+ 232 $me :- This are the rules") 11 | m.expect(c1a, "RULES output 309 (end)", ":.+ 309 $me :End of RULES command") 12 | m.clearlog() 13 | print 14 | -------------------------------------------------------------------------------- /serverconfig/anope/install_anope: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | VERSION="2.0.7" 3 | DIRECTORY="anope-${VERSION}-source" 4 | SCRIPTDIR="$( cd "$(dirname "$0")" ; pwd -P )" 5 | 6 | set -e 7 | set -x 8 | 9 | mkdir -p ~/tmp 10 | cd ~/tmp 11 | wget "https://github.com/anope/anope/releases/download/${VERSION}/${DIRECTORY}.tar.gz" -O "$DIRECTORY.tar.gz" 12 | rm -rf "$DIRECTORY" 13 | tar xzvf $DIRECTORY.tar.gz 14 | cd $DIRECTORY 15 | cp -av "$SCRIPTDIR/config.cache" . 16 | ./Config -quick 17 | cd build 18 | make 19 | make install 20 | -------------------------------------------------------------------------------- /tests/usercommands/links: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | m.connect() 7 | 8 | m.send(c1a, "LINKS") 9 | m.expect(c1a, "Server 2 hops away", ":.+ 364 $me irc3\.test\.net irc2\.test\.net :2 Secondary test") 10 | m.expect(c1a, "Server 1 hop away", ":.+ 364 $me irc2\.test\.net irc1\.test\.net :1 Hub") 11 | m.expect(c1a, "Ourselves", ":.+ 364 $me irc1\.test\.net irc1\.test\.net :0 Primary test server") 12 | m.clearlog() 13 | print 14 | -------------------------------------------------------------------------------- /tests/usercommands/motd: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | m.connect() 7 | 8 | m.send(c1a, "MOTD") 9 | m.expect(c1a, "MOTD output 375 (header)", ":.+ 375 $me :- irc.* Message of the Day") 10 | m.expect(c1a, "MOTD output 372 (date)", ":.+ 372 $me :.*[0-9]+:[0-9]+") 11 | m.expect(c1a, "MOTD output 372 (text)", ":.+ 372 $me :- This is a test server") 12 | m.expect(c1a, "MOTD output 376 (end)", ":.+ 376 $me :End of /MOTD command") 13 | m.clearlog() 14 | print 15 | -------------------------------------------------------------------------------- /tests/usercommands/version: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | m.connect() 7 | 8 | m.send(c1a, "VERSION") 9 | m.expect(c1a, "VERSION response (351)", ":.+ 351 $me UnrealIRCd-.* irc1\.test\.net :0 ") 10 | m.expect(c1a, "VERSION response (005, part 1)", ":.+ 005 $me .*CASEMAPPING") 11 | m.expect(c1a, "VERSION response (005, part 2)", ":.+ 005 $me .*MAXLIST") 12 | m.expect(c1a, "VERSION response (005, part 3)", ":.+ 005 $me .*WHOX") 13 | m.clearlog() 14 | print 15 | -------------------------------------------------------------------------------- /serverconfig/unrealircd/db_crypted.conf: -------------------------------------------------------------------------------- 1 | secret channeldb { 2 | password "thisisATEST111!"; 3 | } 4 | set { 5 | channeldb { 6 | db-secret channeldb; 7 | } 8 | } 9 | 10 | secret reputationdb { 11 | password "thisisATEST222!"; 12 | } 13 | set { 14 | reputation { 15 | db-secret reputationdb; 16 | } 17 | } 18 | 19 | secret sharedsecret { 20 | password "thisisATEST333!"; 21 | } 22 | set { 23 | tkldb { 24 | db-secret sharedsecret; 25 | } 26 | } 27 | set { 28 | history { 29 | channel { 30 | persist yes; 31 | db-secret sharedsecret; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/usermodes/showwhois: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c1a, "OPER netadmin test") 11 | m.send(c1a, "MODE $c1a +W") 12 | m.expect(c1a, "MODE set", "MODE $c1a :\+W") 13 | print 14 | 15 | m.send_all("WHOIS $c1a", skip = c1a) 16 | m.expect(c1a, "Should see a NOTICE on /WHOIS (1 of 2)", "c2a.*did a \/whois on you") 17 | m.expect(c1a, "Should see a NOTICE on /WHOIS (2 of 2)", "c3a.*did a \/whois on you") 18 | print 19 | -------------------------------------------------------------------------------- /tests/opercommands/wallops: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c1a, "WALLOPS this is a wallops test") 11 | m.expect(c1a, "Command not permitted as non-ircop", ":.+ 481 $me :Permission Denied") 12 | m.clearlog() 13 | print 14 | 15 | m.send(c1a, "OPER netadmin test") 16 | m.send(c1a, "WALLOPS this is a wallops test") 17 | m.expect_all("Everyone should see wallops", ":$c1a.* WALLOPS :this is a wallops test", skip=c1a) 18 | print 19 | -------------------------------------------------------------------------------- /tests/usercommands/part: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c1a) 12 | m.expect(c1a, "user in channel", "JOIN") 13 | print 14 | 15 | m.send(c3a, "PART " + chan) 16 | m.expect_all("Everyone should see user leaving", ":c3a.*PART.*") 17 | m.clearlog() 18 | print 19 | 20 | m.send_all("NAMES " + chan) 21 | m.not_expect_all("Parted user should no longer be in channel", "353.*" + chan + " :.*$c3a") 22 | print 23 | -------------------------------------------------------------------------------- /tests/extensions/userhost-in-names: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, skip = c1a) 12 | m.expect(c3a, "two users in channel", "JOIN") 13 | print 14 | 15 | m.send(c1a, "CAP REQ userhost-in-names") 16 | m.send(c1a, "JOIN " + chan) 17 | m.expect(c1a, "userhost in NAMES w/UHNAMES", "353.*$c3a!~?username@") 18 | print 19 | 20 | m.send(c3a, "NAMES " + chan) 21 | m.expect(c3a, "userhost NOT in NAMES wo/UHNAMES", "353.*$c1a([^!]+|$)") 22 | -------------------------------------------------------------------------------- /tests/chanmodes/nokick: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c2a) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | print 14 | 15 | m.send(c2a, "MODE " + chan + " +Q") 16 | m.expect(c1a, "MODE +Q", ":c2a.*MODE.*\+Q") 17 | print 18 | 19 | m.send(c2a, "KICK " + chan + " $c3a") 20 | m.expect(c2a, "Expect 972 error numeric on /KICK", " 972.*channel is") 21 | m.not_expect(c1a, "Should be no KICK event", ":c2a.*KICK") 22 | print 23 | -------------------------------------------------------------------------------- /tests/chanmodes/noknock: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c2a, skip = c3a) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | print 14 | 15 | m.send(c2a, "MODE " + chan + " +iK") 16 | m.expect(c1a, "MODE +iK", ":c2a.*MODE.*\+iK") 17 | print 18 | 19 | m.send(c3a, "KNOCK " + chan) 20 | m.expect(c3a, "Should get an error (numeric 480)", "480.*No knock") 21 | m.not_expect(c1a, "Should not see a knock in channel", "Knock") 22 | print 23 | -------------------------------------------------------------------------------- /tests/extensions/cap-chghost: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c3a, "MODE $c3a +x") 11 | 12 | chan = m.randchan() 13 | m.join_all(chan) 14 | m.expect(c1a, "users in channel", "JOIN") 15 | print 16 | 17 | m.send(c1a, "CAP REQ chghost") 18 | m.send(c3a, "MODE $c3a -x") 19 | m.expect(c1a, "with CAP chghost a CHGHOST notification should be generated", ":c3a.* CHGHOST") 20 | m.not_expect(c2a, "without CAP chghost no CHGHOST notification should be generated", ":c3a.* CHGHOST") 21 | print 22 | -------------------------------------------------------------------------------- /tests/usercommands/nick: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c2a) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | print 14 | 15 | # Need to disable the auto-syncer here due to the nick change 16 | m.sync = 0 17 | m.send(c3a, "NICK nickcmdtest") 18 | m.expect_all("All users should see the NICK event", ":c3a.*NICK :nickcmdtest", timeout = 10) 19 | m.not_expect(c3a, "No 447 error numeric on /NICK", " 447.*not change nickname") 20 | print 21 | -------------------------------------------------------------------------------- /tests/db/reading/permanent: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | m.connect() 7 | 8 | chan = "#permanent_test" 9 | m.join_all(chan, creator=c1a) 10 | m.send_all("MODE " + chan) 11 | m.send_all("MODE " + chan + " b") 12 | m.send_all("MODE " + chan + " e") 13 | m.send_all("MODE " + chan + " I") 14 | m.expect_all("MODE +PT should be set after rejoin", "324.*\+PT") 15 | m.expect_all("ban should be set after rejoin", "367.*ban!") 16 | m.expect_all("exempts should be set after rejoin", "348.*exempt!") 17 | m.expect_all("invexes should be set after rejoin", "346.*invex!") 18 | -------------------------------------------------------------------------------- /tests/usercommands/lusers: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | m.connect() 7 | 8 | m.send(c1a, "LUSERS") 9 | m.expect(c1a, "LUSERS output 251 (text)", ":.+ 251 $me :There are .* users and .* invisible on .* servers") 10 | m.expect(c1a, "LUSERS output 255 (text)", ":.+ 255 $me :I have .* clients and .* servers") 11 | m.expect(c1a, "LUSERS output 265 (local counts)", ":.+ 265 $me [0-9]+ [0-9]+ :Current local users .*, max .*") 12 | m.expect(c1a, "LUSERS output 266 (global counts)", ":.+ 266 $me [0-9]+ [0-9]+ :Current global users .*, max .*") 13 | m.clearlog() 14 | print 15 | -------------------------------------------------------------------------------- /tests/usermodes/nokick: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c3a) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | print 14 | 15 | m.send(c1a, "OPER netadmin test") 16 | m.send(c1a, "MODE $c1a +q") 17 | m.expect(c1a, "MODE set", "MODE $c1a :\+q") 18 | print 19 | 20 | m.send(c3a, "KICK " + chan + " $c1a") 21 | m.expect(c3a, "Expect 972 error numeric on /KICK", "972.*user is unkickable") 22 | m.not_expect_all("Should be no KICK event", ":c2a.*KICK") 23 | print 24 | -------------------------------------------------------------------------------- /tests/usercommands/cycle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c1a) 12 | m.expect(c1a, "user in channel", "JOIN") 13 | print 14 | 15 | m.send(c3a, "CYCLE " + chan) 16 | m.expect_all("Everyone should see user leaving", ":c3a.*PART.*") 17 | m.expect_all("Everyone should see user joining", ":c3a.*JOIN.*") 18 | m.clearlog() 19 | print 20 | 21 | m.send_all("NAMES " + chan) 22 | m.expect_all("Cycled user should still be in channel", "353.*" + chan + " :.*$c3a") 23 | print 24 | -------------------------------------------------------------------------------- /tests/chanmodes/noexternal: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c2a, skip = c1a) 12 | m.expect(c2a, "users in channel", "JOIN") 13 | m.send(c2a, "MODE " + chan + " +n") 14 | print 15 | 16 | m.send(c1a, "PRIVMSG " + chan + " :external message") 17 | m.not_expect_all("Message should not be delivered if +n", "external message") 18 | m.expect(c1a, "Error message on external message attempt", ":irc.+ 404 $me " + chan + " :No external channel messages") 19 | m.clearlog() 20 | print 21 | -------------------------------------------------------------------------------- /tests/usercommands/module: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | m.connect() 7 | 8 | m.send(c1a, "MODULE") 9 | m.expect(c1a, "Regular MODULE output", ":.+ 304 $me :Showing loaded 3rd party modules.*") 10 | m.expect(c1a, "End of MODULE output", ":.+ 304 $me :End of module list") 11 | m.not_expect(c1a, "There should be no listed (3rd party) modules", ":.+ 304 $me :\*\*\*") 12 | m.clearlog() 13 | print 14 | 15 | m.send(c1a, "MODULE -all") 16 | m.expect(c1a, "Full MODULE output", ":.+ 304 $me :Showing ALL loaded modules") 17 | m.expect(c1a, "End of MODULE output", ":.+ 304 $me :End of module list") 18 | m.clearlog() 19 | print 20 | -------------------------------------------------------------------------------- /tests/opercommands/globops: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c1a, "GLOBOPS this is a globops test") 11 | m.expect(c1a, "Command not permitted as non-ircop", ":.+ 481 $me :Permission Denied") 12 | m.clearlog() 13 | print 14 | 15 | m.send(c1a, "OPER netadmin test") 16 | m.send(c2a, "OPER netadmin test") 17 | m.send(c1a, "GLOBOPS this is a globops test") 18 | m.expect_all("Opers should see globops", ":irc.+ NOTICE $me :from $c1a: this is a globops test", skip = c3a) 19 | m.not_expect(c3a, "Non-opers should not see globops", "this is a globops test") 20 | print 21 | -------------------------------------------------------------------------------- /tests/usercommands/setname: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan) 12 | m.send(c2a, 'CAP REQ :setname') 13 | m.send(c1a, 'SETNAME :my new realname') 14 | m.not_expect(c3a, "setname notification should not be received (no capability)", ":$c1a.* SETNAME") 15 | m.expect(c2a, "setname notification received", ":$c1a.* SETNAME :my new realname") 16 | m.clearlog() 17 | print 18 | 19 | m.send_all('WHOIS $c1a') 20 | m.expect_all("New realname in WHOIS", ":.* 311 $me $c1a username Clk.* \* :my new realname") 21 | m.clearlog() 22 | print 23 | 24 | -------------------------------------------------------------------------------- /tests/chanmodes/nonickchange: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c2a) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | print 14 | 15 | m.send(c2a, "MODE " + chan + " +N") 16 | m.expect(c1a, "MODE +N", ":c2a.*MODE.*\+N") 17 | print 18 | 19 | # Need to disable the auto-syncer here due to the nick change 20 | m.sync = 0 21 | m.send(c3a, "NICK zzz") 22 | m.expect(c3a, "Expect 447 error numeric on /NICK", " 447.*not change nickname", timeout = 10) 23 | m.not_expect(c1a, "Should be no NICK event", ":c3a.*NICK") 24 | print 25 | -------------------------------------------------------------------------------- /tests/services/identify: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c1a, "IDENTIFY client1 test") 11 | m.expect(c1a, "Identified to account", ":irc.* 900 ", timeout = 10) 12 | m.clearlog() 13 | print 14 | 15 | # Lazy way to make sure the SASL propagated completely 16 | m.send(c1a, "VERSION services.test.net") 17 | m.expect(c1a, "Services version response", ":services\.test\.net 351 $c1a .*", timeout = 10) 18 | m.clearlog() 19 | print 20 | 21 | m.send_all("WHOIS $c1a") 22 | m.expect_all("Show account in WHOIS", ":.+ 330 $me $c1a client1 :is logged in as") 23 | m.clearlog() 24 | print 25 | 26 | -------------------------------------------------------------------------------- /tests/usermodes/privacy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.send(c1a, "JOIN " + chan) 12 | m.expect(c1a, "user in channel", "JOIN") 13 | print 14 | 15 | m.send_all("WHOIS $c1a", skip = c1a) 16 | m.expect_all("Channel should be visible with umode -p", "319.*" + chan, skip = c1a) 17 | print 18 | 19 | m.send(c1a, "MODE $c1a +p") 20 | m.expect(c1a, "MODE set", "MODE $c1a :\+p") 21 | m.clearlog() 22 | print 23 | 24 | m.send_all("WHOIS $c1a", skip = c1a) 25 | m.not_expect_all("Channel should not be visible with umode +p", "319.*" + chan, skip = c1a) 26 | print 27 | 28 | -------------------------------------------------------------------------------- /tests/opercommands/tsctl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | import time 4 | 5 | m = irctestframework.irctest.IrcTest() 6 | c1a = m.new('c1a') 7 | m.connect() 8 | 9 | m.send(c1a, "TSCTL") 10 | m.expect(c1a, "Command not permitted as non-ircop", ":.+ 481 $me :Permission Denied") 11 | m.clearlog() 12 | print 13 | 14 | m.send(c1a, "OPER netadmin test") 15 | m.send(c1a, "TSCTL") 16 | m.expect(c1a, "See time on irc1", ":irc1.+ NOTICE $c1a :\*\*\* Server=irc1\.test\.net TStime=[0-9]+") 17 | m.expect(c1a, "See time on irc2", ":irc2.+ NOTICE $c1a :\*\*\* Server=irc2\.test\.net TStime=[0-9]+", timeout=5) 18 | m.expect(c1a, "See time on irc3", ":irc3.+ NOTICE $c1a :\*\*\* Server=irc3\.test\.net TStime=[0-9]+", timeout=5) 19 | m.clearlog() 20 | print 21 | -------------------------------------------------------------------------------- /tests/usercommands/userhost: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send_all("USERHOST :$c1a thisnickdoesnotexist $c2a irc1.test.net $c3a") 11 | m.expect(c1a, "USERHOST response on client 1", ":.+ 302 $me :$c1a=.*username@localhost $c2a=.*username@Clk-8608861 $c3a=.*username@Clk-8608861") 12 | m.expect(c2a, "USERHOST response on client 2", ":.+ 302 $me :$c1a=.*username@Clk-8608861 $c2a=.*username@localhost $c3a=.*username@Clk-8608861") 13 | m.expect(c3a, "USERHOST response on client 3", ":.+ 302 $me :$c1a=.*username@Clk-8608861 $c2a=.*username@Clk-8608861 $c3a=.*username@localhost") 14 | m.clearlog() 15 | print 16 | -------------------------------------------------------------------------------- /serverconfig/unrealircd/irc3.conf: -------------------------------------------------------------------------------- 1 | me { 2 | name irc3.test.net; 3 | info "Secondary test server (leaf)"; 4 | sid 002; 5 | }; 6 | 7 | listen { 8 | ip 127.0.0.1; 9 | port 5663; 10 | }; 11 | 12 | listen { 13 | ip 127.0.0.1; 14 | port 5903; 15 | options { ssl; }; 16 | }; 17 | 18 | link irc2.test.net { 19 | incoming { 20 | mask 127.0.0.1; 21 | }; 22 | outgoing { 23 | hostname 127.0.0.1; 24 | port 5902; 25 | options { 26 | /* no autoconnect due to interference 27 | * with some of the linking tests 28 | */ 29 | ssl; 30 | }; 31 | }; 32 | password "test"; 33 | class servers; 34 | }; 35 | 36 | log { 37 | source { 38 | all; 39 | } 40 | destination { 41 | file "irc3.log" { maxsize 250M; } 42 | } 43 | }; 44 | 45 | include "common.conf"; 46 | -------------------------------------------------------------------------------- /tests/opercommands/mkpasswd: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | m.connect() 7 | 8 | m.send(c1a, "MKPASSWD argon2 test") 9 | m.expect(c1a, "Command not permitted as non-ircop", ":.+ 481 $me :Permission Denied") 10 | m.clearlog() 11 | print 12 | 13 | m.send(c1a, "OPER netadmin test") 14 | m.send(c1a, "MKPASSWD argon2 test") 15 | m.expect(c1a, "MKPASSWD reply", ":irc.+ NOTICE $me :\*\*\* Authentication phrase \(method=argon2, para=test\) is: \$argon2id\$v=") 16 | m.clearlog() 17 | print 18 | 19 | m.send(c1a, "MKPASSWD bcrypt test") 20 | m.expect(c1a, "MKPASSWD reply", ":irc.+ NOTICE $me :\*\*\* Authentication phrase \(method=bcrypt, para=test\) is: \$2y\$") 21 | m.clearlog() 22 | print 23 | -------------------------------------------------------------------------------- /tests/opercommands/chgident: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c3a, "CHGIDENT $c1a newident") 11 | m.expect(c3a, "Should get permission denied if not IRCOp", ":.* 481 $me :Permission Denied.*") 12 | m.clearlog() 13 | 14 | m.send_all("WHOIS $c1a") 15 | m.not_expect_all("Should not see new ident in WHOIS", ":.* 311 $me $c1a newident .*") 16 | m.clearlog() 17 | print 18 | 19 | m.send(c3a, "OPER netadmin test") 20 | m.send(c3a, "CHGIDENT $c1a newident") 21 | m.clearlog() 22 | 23 | m.send_all("WHOIS $c1a") 24 | m.expect_all("Should see new ident in WHOIS", ":.* 311 $me $c1a newident .*") 25 | m.clearlog() 26 | print 27 | -------------------------------------------------------------------------------- /tests/services/account-notify: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c3a, "CAP REQ account-notify") 11 | m.clearlog() 12 | print 13 | 14 | chan = m.randchan() 15 | m.join_all(chan, skip = c2a, creator=c1a) 16 | m.expect(c1a, "users in channel", "JOIN") 17 | m.clearlog() 18 | print 19 | 20 | m.send(c1a, "NS IDENTIFY client1 test") 21 | m.expect(c1a, "Identified to account", ":irc.* 900 ", timeout = 10) 22 | m.expect(c3a, "ACCOUNT message in channel upon account login", ":c1a.* ACCOUNT client1", timeout = 5) 23 | m.not_expect(c2a, "no ACCOUNT message if no CAP account-notify", ":c1a.* ACCOUNT client1") 24 | m.clearlog() 25 | print 26 | -------------------------------------------------------------------------------- /serverconfig/unrealircd/irc2.conf: -------------------------------------------------------------------------------- 1 | me { 2 | name irc2.test.net; 3 | info "Hub"; 4 | sid 010; 5 | }; 6 | 7 | listen { 8 | ip 127.0.0.1; 9 | port 5662; 10 | }; 11 | 12 | listen { 13 | ip 127.0.0.1; 14 | port 5902; 15 | options { ssl; }; 16 | }; 17 | 18 | link irc1.test.net { 19 | incoming { 20 | mask 127.0.0.1; 21 | }; 22 | password "test"; 23 | class servers; 24 | }; 25 | 26 | link irc3.test.net { 27 | incoming { 28 | mask 127.0.0.1; 29 | }; 30 | password "test"; 31 | class servers; 32 | }; 33 | 34 | link services.test.net { 35 | incoming { 36 | mask 127.0.0.1; 37 | }; 38 | password "test"; 39 | class servers; 40 | }; 41 | 42 | log { 43 | source { 44 | all; 45 | } 46 | destination { 47 | file "irc2.log" { maxsize 250M; } 48 | } 49 | }; 50 | 51 | include "common.conf"; 52 | -------------------------------------------------------------------------------- /tests/chanmodes/regonlyspeak: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c2a) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | m.clearlog() 14 | 15 | m.send(c2a, "MODE " + chan + " +M") 16 | m.expect(c1a, "MODE +M", ":c2a.*MODE.*\+M") 17 | m.clearlog() 18 | 19 | m.send(c1a, "PRIVMSG " + chan + " :hello") 20 | m.expect(c1a, "should show a 404 numeric if not identified, with cmode +M", "404 .*You must have a registered nick") 21 | m.not_expect(c3a, "should block messages if not identified, with cmode +M", ":c1a.*PRIVMSG.*this is red") 22 | m.clearlog() 23 | 24 | print('TODO: test with registered and +M') 25 | -------------------------------------------------------------------------------- /tests/opercommands/sapart: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c1a) 12 | m.expect(c1a, "see others joining", ":c2a.*JOIN") 13 | m.clearlog() 14 | print 15 | 16 | m.send(c1a, "SAPART $c3a " + chan) 17 | m.expect(c1a, "Command not permitted as non-ircop", ":.+ 481 $me :Permission Denied") 18 | m.clearlog() 19 | print 20 | 21 | m.send(c1a, "OPER netadmin test") 22 | m.send(c1a, "SAPART $c3a " + chan) 23 | m.expect(c3a, "See that you are forced parted", ":irc.+ NOTICE $me :\*\*\* You were forced to part " + chan) 24 | m.expect_all("See c3a parting", ":c3a.*PART", timeout = 5) 25 | m.clearlog() 26 | print 27 | -------------------------------------------------------------------------------- /tests/chanmodes/regonlyjoin: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c1a, skip = c3a) 12 | m.expect(c1a, "first user in channel", ":c1a.*JOIN") 13 | m.expect(c2a, "second user in channel", ":c2a.*JOIN") 14 | m.clearlog() 15 | 16 | m.send(c1a, "MODE " + chan + " +R") 17 | m.expect(c2a, "MODE +R", ":c1a.*MODE.*\+R") 18 | m.clearlog() 19 | 20 | m.send(c3a, "JOIN " + chan) 21 | m.expect(c3a, "unable to join with +R (numeric 477)", "477.*need.*registered") 22 | m.not_expect(c1a, "should not see JOIN for user if +R", ":c3a.*JOIN") 23 | m.clearlog() 24 | 25 | print('TODO: test JOIN with registered user (should pass)') 26 | -------------------------------------------------------------------------------- /tests/opercommands/sethost: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c1a, "SETHOST this.is.my.new.hostname") 11 | m.expect(c1a, "Should get permission denied if not IRCOp", ":.* 481 $me :Permission Denied.*") 12 | m.clearlog() 13 | 14 | m.send_all("WHOIS $c1a") 15 | m.not_expect_all("Should not see new hostname in WHOIS", ":.* 311 $me $c1a .* this\.is\.my\.new\.hostname") 16 | m.clearlog() 17 | print 18 | 19 | m.send(c1a, "OPER netadmin test") 20 | m.send(c1a, "SETHOST this.is.my.new.hostname") 21 | m.clearlog() 22 | 23 | m.send_all("WHOIS $c1a") 24 | m.expect_all("Should see new hostname in WHOIS", ":.* 311 $me $c1a .* this\.is\.my\.new\.hostname") 25 | m.clearlog() 26 | print 27 | -------------------------------------------------------------------------------- /check_missing_tests: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ ! -f ~/unrealircd/data/cmds.txt ]; then 3 | echo "File ~/unrealircd/data/cmds.txt not found" 4 | echo "This means the 'third/dumpcmds' module was not loaded" 5 | echo "or the ircd is not running." 6 | exit 1 7 | fi 8 | 9 | cat ~/unrealircd/data/cmds.txt|\ 10 | grep 'USER'|\ 11 | grep -v 'ALIAS'|\ 12 | awk '{ print $1 }'|\ 13 | tr '[A-Z]' '[a-z]'|\ 14 | while read cmd 15 | do 16 | if [ ! -f "tests/usercommands/$cmd" -a ! -f "tests/opercommands/$cmd" ]; then 17 | echo "MISSING: tests/usercommands/$cmd" 18 | fi 19 | done 20 | 21 | cat ~/unrealircd/data/cmds.txt|\ 22 | grep 'OPER'|\ 23 | grep -v 'ALIAS'|\ 24 | awk '{ print $1 }'|\ 25 | tr '[A-Z]' '[a-z]'|\ 26 | while read cmd 27 | do 28 | if [ ! -f "tests/opercommands/$cmd" ]; then 29 | echo "MISSING: tests/opercommands/$cmd" 30 | fi 31 | done 32 | -------------------------------------------------------------------------------- /tests/opercommands/chgname: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c3a, "CHGNAME $c1a :my new realname") 11 | m.expect(c3a, "Should get permission denied if not IRCOp", ":.* 481 $me :Permission Denied.*") 12 | m.clearlog() 13 | 14 | m.send_all("WHOIS $c1a") 15 | m.not_expect_all("Should not see new realname in WHOIS", ":.* 311 $me $c1a username Clk.* \* :my new realname") 16 | m.clearlog() 17 | print 18 | 19 | m.send(c3a, "OPER netadmin test") 20 | m.send(c3a, "CHGNAME $c1a :my new realname") 21 | m.clearlog() 22 | 23 | m.send_all("WHOIS $c1a") 24 | m.expect_all("Should see new realname in WHOIS", ":.* 311 $me $c1a username Clk.* \* :my new realname") 25 | m.clearlog() 26 | print 27 | -------------------------------------------------------------------------------- /tests/opercommands/chghost: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c3a, "CHGHOST $c1a this.is.my.new.hostname") 11 | m.expect(c3a, "Should get permission denied if not IRCOp", ":.* 481 $me :Permission Denied.*") 12 | m.clearlog() 13 | 14 | m.send_all("WHOIS $c1a") 15 | m.not_expect_all("Should not see new hostname in WHOIS", ":.* 311 $me $c1a .* this\.is\.my\.new\.hostname") 16 | m.clearlog() 17 | print 18 | 19 | m.send(c3a, "OPER netadmin test") 20 | m.send(c3a, "CHGHOST $c1a this.is.my.new.hostname") 21 | m.clearlog() 22 | 23 | m.send_all("WHOIS $c1a") 24 | m.expect_all("Should see new hostname in WHOIS", ":.* 311 $me $c1a .* this\.is\.my\.new\.hostname") 25 | m.clearlog() 26 | print 27 | -------------------------------------------------------------------------------- /tests/opercommands/opermotd: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | m.connect() 7 | 8 | m.send(c1a, "OPERMOTD") 9 | m.expect(c1a, "Command not permitted as non-ircop", ":.+ 481 $me :Permission Denied") 10 | m.clearlog() 11 | print 12 | 13 | m.send(c1a, "OPER netadmin test") 14 | m.send(c1a, "OPERMOTD") 15 | m.expect(c1a, "OPERMOTD output 375 (header)", ":.+ 375 $me :- irc.* Message of the Day") 16 | m.expect(c1a, "OPERMOTD output 372 (date)", ":.+ 372 $me :.*IRC Operator Message of the Day") 17 | m.expect(c1a, "OPERMOTD output 372 (text)", ":.+ 372 $me :- This is the oper MOTD") 18 | m.expect(c1a, "OPERMOTD output 372 (text)", ":.+ 372 $me :- last line of OPERMOTD") 19 | m.expect(c1a, "OPERMOTD output 376 (end)", ":.+ 376 $me :End of /OPERMOTD command") 20 | m.clearlog() 21 | print 22 | -------------------------------------------------------------------------------- /tests/usercommands/quit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c1a) 12 | m.expect(c1a, "user in channel", "JOIN") 13 | print 14 | 15 | # Need to disable the auto-syncer here due to 1 client disappearing. 16 | m.sync = 0 17 | 18 | m.send(c3a, "QUIT :goodbye") 19 | m.expect(c3a, "Quiting user should see a closing link message", "ERROR :Closing Link.*Quit", timeout = 10) 20 | m.expect_all("Other clients should see user leaving", ":c3a.* QUIT :", timeout = 10, skip = c3a) 21 | m.clearlog() 22 | print 23 | 24 | m.send_all("NAMES " + chan, skip = c1a) 25 | m.not_expect_all("Parted user should no longer be in channel", "353.*" + chan + " :.*$c3a", skip = c1a) 26 | print 27 | -------------------------------------------------------------------------------- /tests/chanmodes/nonotice: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c2a) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | print 14 | 15 | m.send(c1a, "NOTICE " + chan + " :this is a notice") 16 | m.not_expect(c1a, "should allow NOTICE (no 404 numeric) with -T", " 404 .*NOTICEs are not permitted") 17 | m.expect(c3a, "should allow NOTICE with -T", ":c1a.*NOTICE.*:this is a notice") 18 | print 19 | m.clearlog() 20 | 21 | m.send(c2a, "MODE " + chan + " +T") 22 | m.expect(c1a, "MODE +T", ":c2a.*MODE.*\+T") 23 | print 24 | 25 | m.send(c1a, "NOTICE " + chan + " :this is a notice") 26 | m.not_expect(c3a, "should block NOTICE with +T", ":c1a.*NOTICE.*:this is a notice") 27 | print 28 | -------------------------------------------------------------------------------- /tests/usercommands/userip: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send_all("USERIP :$c1a thisnickdoesnotexist $c2a irc1.test.net $c3a") 11 | m.expect(c1a, "USERIP response on client 1", ":.+ 340 $me :$c1a=.*username@127\.0\.0\.1 $c2a=.*username@C9BC54D4\.CCE2A095\.73B42A24\.IP $c3a=.*username@C9BC54D4\.CCE2A095\.73B42A24\.IP") 12 | m.expect(c2a, "USERIP response on client 2", ":.+ 340 $me :$c1a=.*username@C9BC54D4\.CCE2A095\.73B42A24\.IP $c2a=.*username@127\.0\.0\.1 $c3a=.*username@C9BC54D4\.CCE2A095\.73B42A24\.IP") 13 | m.expect(c3a, "USERIP response on client 3", ":.+ 340 $me :$c1a=.*username@C9BC54D4\.CCE2A095\.73B42A24\.IP $c2a=.*username@C9BC54D4\.CCE2A095\.73B42A24\.IP $c3a=.*username@127\.0\.0\.1") 14 | m.clearlog() 15 | print 16 | -------------------------------------------------------------------------------- /tests/chanmodes/noinvite: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c2a, skip = c3a) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | print 14 | 15 | m.send(c2a, "MODE " + chan + " +iV") 16 | m.expect(c1a, "MODE +iV", ":c2a.*MODE.*\+iV") 17 | print 18 | 19 | m.send(c1a, "INVITE $c3a " + chan) 20 | m.expect(c1a, "Expect 518 error numeric on /INVITE for non-ops", " 518.*Cannot invite") 21 | print 22 | 23 | m.send(c2a, "INVITE $c3a " + chan) 24 | m.expect(c1a, "Expect 518 error numeric on /INVITE for ops too", " 518.*Cannot invite") 25 | print 26 | 27 | m.send(c3a, "JOIN " + chan) 28 | m.not_expect(c1a, "User should be unable to join since he was never invited", ":c3a.*JOIN") 29 | print 30 | -------------------------------------------------------------------------------- /tests/chanmodes/exempt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, skip = c3a, creator=c1a) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | print 14 | 15 | m.send(c1a, "MODE " + chan + " +b c3a*!*@*") 16 | m.send(c3a, "JOIN " + chan) 17 | m.expect(c3a, "unable to join if banned (474 error)", "474.*Cannot join") 18 | m.not_expect(c1a, "unable to join if banned (no JOIN)", ":c3a.*JOIN") 19 | m.clearlog() 20 | print 21 | 22 | m.send(c1a, "MODE " + chan + " +e c3a*!*@*") 23 | m.expect(c2a, "MODE +e", ":c1a.*MODE") 24 | print 25 | 26 | m.send(c3a, "JOIN " + chan) 27 | m.not_expect(c3a, "can join if exempt (should be no 474 error)", "474.*Cannot join") 28 | m.expect(c1a, "can join if exempt (JOIN)", ":c3a.*JOIN") 29 | print 30 | -------------------------------------------------------------------------------- /tests/usercommands/join: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c1a) 12 | m.expect(c1a, "see others joining (1 of 2)", ":c2a.*JOIN") 13 | m.expect(c1a, "see others joining (2 of 2)", ":c3a.*JOIN") 14 | m.clearlog() 15 | print 16 | 17 | m.send_all("NAMES " + chan) 18 | m.expect_all("Creator should have ops", "353.*@$c1a") 19 | m.expect_all("2nd user should not have ops", "353.*[^@]$c2a") 20 | m.expect_all("3rd user should not have ops", "353.*[^@]$c3a") 21 | print 22 | 23 | # Need to disable the auto-syncer here due to 1 client parting all channels, 24 | # including the auto syncer channel. 25 | m.sync = 0 26 | 27 | m.send(c3a, "JOIN 0") 28 | m.expect_all("See c3a leaving", ":c3a.*PART", timeout = 5) 29 | m.clearlog() 30 | print 31 | -------------------------------------------------------------------------------- /tests/extbans/quiet: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, skip = c3a, creator=c1a) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | m.clearlog() 14 | print 15 | 16 | m.send(c1a, "MODE " + chan + " +b ~quiet:$c3a!*@*") 17 | m.expect(c1a, "expect ban to be set", ":.+ MODE " + chan + " \+b") 18 | m.clearlog() 19 | print 20 | 21 | m.send(c3a, "JOIN " + chan) 22 | m.expect_all("Client should be able to join with +b ~quiet", ":c3a.* JOIN ") 23 | m.clearlog() 24 | print 25 | 26 | m.send(c3a, "PRIVMSG " + chan + " :this should be blocked") 27 | m.expect(c3a, "Message should be blocked with +b ~quiet", ":irc.+ 404 $c3a " + chan + " :You are banned") 28 | m.not_expect_all("Message should not go through", "this should be blocked") 29 | m.clearlog() 30 | print 31 | -------------------------------------------------------------------------------- /tests/usercommands/notice: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c1a) 12 | m.expect_all("all in channel", "NAMES") 13 | m.clearlog() 14 | print 15 | 16 | m.send(c1a, "NOTICE " + chan + " :this is a channel notice") 17 | m.expect_all("Recieve channel NOTICE", ":$c1a.* NOTICE " + chan + " :this is a channel notice", skip = c1a) 18 | m.clearlog() 19 | print 20 | 21 | m.send_all("NOTICE $c1a :this is a private notice") 22 | m.expect(c1a, "Private notice from client 1 (myself)", ":$c1a.* NOTICE $c1a :this is a private notice") 23 | m.expect(c1a, "Private notice from client 2", ":$c2a.* NOTICE $c1a :this is a private notice") 24 | m.expect(c1a, "Private notice from client 3", ":$c3a.* NOTICE $c1a :this is a private notice") 25 | m.clearlog() 26 | print 27 | -------------------------------------------------------------------------------- /tests/chanmodes/noctcp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c2a) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | print 14 | 15 | m.send(c1a, "PRIVMSG " + chan + " :\001VERSION\001") 16 | m.not_expect(c1a, "should not block CTCP (no 404 numeric) with -C", " 404 .*CTCPs are not permitted") 17 | m.expect(c3a, "should not block CTCP with -C", ":c1a.*PRIVMSG.*VERSION") 18 | m.clearlog() 19 | print 20 | 21 | m.send(c2a, "MODE " + chan + " +C") 22 | m.expect(c1a, "MODE +c", ":c2a.*MODE.*\+C") 23 | print 24 | 25 | m.send(c1a, "PRIVMSG " + chan + " :\001VERSION\001") 26 | m.expect(c1a, "should block CTCP (expect 404 numeric) with +C", " 404 .*CTCPs are not permitted") 27 | m.not_expect(c3a, "should block CTCP with +C", ":c1a.*PRIVMSG.*VERSION") 28 | print 29 | -------------------------------------------------------------------------------- /tests/usercommands/list: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c1a) 12 | m.expect(c1a, "user in channel", "JOIN") 13 | print 14 | 15 | m.send(c1a, "MODE " + chan + " +nt") 16 | m.expect_all("MODE change on channel", ":$c1a.* MODE " + chan) 17 | m.clearlog() 18 | print 19 | 20 | m.send(c1a, "TOPIC " + chan + " :this is a nice topic") 21 | m.expect_all("TOPIC change on channel", ":$c1a.* TOPIC " + chan) 22 | m.clearlog() 23 | print 24 | 25 | m.send_all("LIST") 26 | m.expect_all("LIST head (numeric 321)", ":.+ 321 $me Channel :Users Name") 27 | m.expect_all("LIST channel entry (numeric 322)", ":.+ 322 $me " + chan + " [0-9]+ :\[\+nt\] this is a nice topic") 28 | m.expect_all("LIST end (numeric 323)", ":.+ 323 $me :End of /LIST") 29 | m.clearlog() 30 | print 31 | -------------------------------------------------------------------------------- /tests/opercommands/locops: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c1b = m.new('c1b') 7 | c2a = m.new('c2a') 8 | c3a = m.new('c3a') 9 | m.connect() 10 | 11 | m.send(c1a, "LOCOPS this is a locops test") 12 | m.expect(c1a, "Command not permitted as non-ircop", ":.+ 481 $me :Permission Denied") 13 | m.clearlog() 14 | print 15 | 16 | m.send(c1a, "OPER netadmin test") 17 | m.send(c1b, "OPER netadmin test") 18 | m.send(c2a, "OPER netadmin test") 19 | m.send(c1a, "LOCOPS this is a locops test") 20 | m.expect(c1a, "Local opers should see locops", ":irc.+ NOTICE $me :from $c1a: this is a locops test") 21 | m.expect(c1b, "Local opers should see locops", ":irc.+ NOTICE $me :from $c1a: this is a locops test") 22 | m.not_expect(c3a, "Non-opers should not see locops", "this is a locops test") 23 | m.not_expect(c2a, "Opers on other servers should not see locops", "this is a locops test") 24 | print 25 | -------------------------------------------------------------------------------- /tests/usercommands/privmsg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c1a) 12 | m.expect_all("all in channel", "NAMES") 13 | m.clearlog() 14 | print 15 | 16 | m.send(c1a, "PRIVMSG " + chan + " :this is a channel message") 17 | m.expect_all("Recieve channel PRIVMSG", ":$c1a.* PRIVMSG " + chan + " :this is a channel message", skip = c1a) 18 | m.clearlog() 19 | print 20 | 21 | m.send_all("PRIVMSG $c1a :this is a private message") 22 | m.expect(c1a, "Private message from client 1 (myself)", ":$c1a.* PRIVMSG $c1a :this is a private message") 23 | m.expect(c1a, "Private message from client 2", ":$c2a.* PRIVMSG $c1a :this is a private message") 24 | m.expect(c1a, "Private message from client 3", ":$c3a.* PRIVMSG $c1a :this is a private message") 25 | m.clearlog() 26 | print 27 | -------------------------------------------------------------------------------- /tests/usercommands/vhost: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c1a, "VHOST wrong wrong") 11 | m.expect(c1a, "NOTICE about failed VHOST attempt (username)", "Login for wrong failed") 12 | m.clearlog() 13 | print 14 | 15 | m.send(c1a, "VHOST test wrong") 16 | m.expect(c1a, "NOTICE about failed VHOST attempt (password)", "Login for test failed") 17 | m.send(c1a, "WHOIS $c1a") 18 | m.not_expect(c1a, "VHOST NOT shown in WHOIS on failed attempt", "this\.is\.a\.test") 19 | m.clearlog() 20 | print 21 | 22 | m.send(c1a, "VHOST test test") 23 | m.expect(c1a, "New displayed host (396)", ":.+ 396 $me this\.is\.a\.test :is now your displayed host") 24 | m.clearlog() 25 | print 26 | 27 | m.send_all("WHOIS $c1a") 28 | m.expect_all("VHOST shown in WHOIS", ":.+ 311 $me $c1a username this\.is\.a\.test .*") 29 | m.clearlog() 30 | print 31 | -------------------------------------------------------------------------------- /tests/extensions/bot-tag: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c2b = m.new('c2b') 8 | c3a = m.new('c3a') 9 | m.connect() 10 | 11 | # c2b will be the bot 12 | m.send(c2b, "MODE $c2b +B") 13 | m.expect(c2b, "MODE set", "MODE $c2b :\+B") 14 | m.clearlog() 15 | print 16 | 17 | chan = m.randchan() 18 | m.join_all(chan, creator = c1a, skip = c2b) 19 | m.expect(c1a, "first user in channel", ":c1a.*JOIN") 20 | m.expect(c2a, "second user in channel", ":c2a.*JOIN") 21 | m.clearlog() 22 | print 23 | 24 | m.send(c2b, "JOIN " + chan) 25 | m.expect_all("JOIN with bot message tag", ".*bot") 26 | m.clearlog() 27 | print 28 | 29 | m.send(c2b, "PRIVMSG " + chan + " :hello everyone!") 30 | m.expect_all("PRIVMSG with bot message tag", ".*bot.*hello everyone", skip = c2b) 31 | print 32 | 33 | m.send(c2b, "PART " + chan) 34 | m.expect_all("PART with bot message tag", ".*bot") 35 | m.clearlog() 36 | print 37 | 38 | -------------------------------------------------------------------------------- /irctestframework/wrapper: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ "$TIMEOUT" = "" ]; then 3 | TIMEOUT=50 4 | fi 5 | 6 | echo Executing: $1 7 | if [ ! -d logs ]; then 8 | echo "ERROR: Directory logs/ does not exist" 9 | exit 1 10 | fi 11 | if [ ! -d logs/failure ]; then 12 | echo "ERROR: Directory logs/failure does not exist" 13 | exit 1 14 | fi 15 | if [ ! -d logs/success ]; then 16 | echo "ERROR: Directory logs/success does not exist" 17 | exit 1 18 | fi 19 | 20 | # strip ./, convert . to _, strip .py, and add .log suffix: 21 | LOGFILE="logs/`echo "$1"|sed 's/\.\///g'|sed 's/\//__/g'|sed 's/\.py//g'`.log" 22 | export PYTHONIOENCODING=utf-8 23 | timeout --kill-after=5 --signal=INT $TIMEOUT $* 1>$LOGFILE 2>&1 24 | wait 25 | EXCODE="$?" 26 | # FIXME: this is too fragile 27 | cat $LOGFILE|egrep -q 'Traceback.*most recent call|python exception|failed to run|File.*, line' 28 | GREPCODE="$?" 29 | 30 | if [ "$EXCODE" -eq 0 -a "$GREPCODE" != 0 ]; then 31 | mv $LOGFILE logs/success 32 | else 33 | mv $LOGFILE logs/failure 34 | fi 35 | -------------------------------------------------------------------------------- /serverconfig/unrealircd/irc1.conf: -------------------------------------------------------------------------------- 1 | me { 2 | name irc1.test.net; 3 | info "Primary test server (leaf)"; 4 | sid 001; 5 | }; 6 | 7 | listen { 8 | ip 127.0.0.1; 9 | port 5661; 10 | }; 11 | 12 | listen { 13 | ip 127.0.0.1; 14 | port 5901; 15 | options { ssl; }; 16 | }; 17 | 18 | link irc2.test.net { 19 | incoming { 20 | mask 127.0.0.1; 21 | }; 22 | outgoing { 23 | hostname 127.0.0.1; 24 | port 5902; 25 | options { 26 | /* no autoconnect due to interference 27 | * with some of the linking tests 28 | */ 29 | ssl; 30 | }; 31 | }; 32 | password "test"; 33 | class servers; 34 | }; 35 | 36 | log { 37 | source { 38 | all; 39 | } 40 | destination { 41 | file "irc1.log" { maxsize 250M; } 42 | } 43 | }; 44 | 45 | /* Because irc1 is used for DB tests it needs to use 46 | * different files for all the databases: 47 | */ 48 | set { 49 | channeldb { 50 | database "channel.irc1.db"; 51 | } 52 | reputation { 53 | database "reputation.irc1.db"; 54 | } 55 | tkldb { 56 | database "tkl.irc1.db"; 57 | } 58 | } 59 | 60 | include "common.conf"; 61 | -------------------------------------------------------------------------------- /tests/extensions/extended-join: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.send(c1a, "CAP REQ extended-join") 12 | m.join_all(chan, skip = c1a, creator=c1a) 13 | m.expect(c1a, "users in channel", "JOIN") 14 | m.expect(c1a, "CAP extended-join should result in extended join (1-hop)", ":c2a.*JOIN.*:Test framework") 15 | m.expect(c1a, "CAP extended-join should result in extended join (2-hops)", ":c3a.*JOIN.*:Test framework") 16 | m.not_expect(c2a, "without CAP extended-join no extended join should be generated", ":c1a.*JOIN.*:Test framework") 17 | m.not_expect(c2a, "without CAP extended-join no extended join should be generated", ":c3a.*JOIN.*:Test framework") 18 | m.not_expect(c3a, "without CAP extended-join no extended join should be generated", ":c1a.*JOIN.*:Test framework") 19 | m.not_expect(c3a, "without CAP extended-join no extended join should be generated", ":c2a.*JOIN.*:Test framework") 20 | 21 | print 22 | -------------------------------------------------------------------------------- /tests/usercommands/names: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c1a) 12 | m.expect_all("users in channel", "JOIN") 13 | m.send(c1a, "MODE " + chan + " +vv $c1a $c2a") 14 | m.clearlog() 15 | print 16 | 17 | m.send_all("NAMES " + chan) 18 | m.expect_all("NAMES should list client 1", ":.* 353 $me = " + chan + " :.*@$c1a") 19 | m.expect_all("NAMES should list client 2", ":.* 353 $me = " + chan + " :.*\+$c2a") 20 | m.expect_all("NAMES should list client 3", ":.* 353 $me = " + chan + " :.*$c3a") 21 | m.clearlog() 22 | print 23 | 24 | m.send(c3a, "PART " + chan) 25 | m.clearlog() 26 | print 27 | 28 | m.send(c3a, "NAMES " + chan) 29 | m.expect(c3a, "NAMES should list nobody if not in channel and no permissions", ":.* 353 $me = " + chan + " :$") 30 | m.not_expect(c3a, "Should not see client 1", ".*353.*$c1a") 31 | m.not_expect(c3a, "Should not see client 2", ".*353.*$c2a") 32 | m.clearlog() 33 | print 34 | -------------------------------------------------------------------------------- /tests/extensions/multi-prefix: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c1a, skip = c3a) 12 | m.expect(c2a, "users in channel", "JOIN") 13 | m.expect(c2a, "c1a has ops", "353.*@c1a") 14 | print 15 | 16 | m.send(c1a, "MODE " + chan + " +hv $c1a $c1a") 17 | m.expect(c1a, "c1a now has +vho", "MODE.*\+hv") 18 | print 19 | 20 | m.send(c3a, "CAP REQ multi-prefix") 21 | m.expect(c3a, "CAP ACK for multi-prefix", "CAP.*ACK.*multi-prefix") 22 | print 23 | 24 | m.send(c3a, "JOIN " + chan) 25 | m.expect(c3a, "with CAP multi-prefix NAMES should show all prefixes", "353.*@%\+c1a") 26 | m.expect(c2a, "without CAP multi-prefix NAMES should only show the highest prefix", "353.*@c1a") 27 | print 28 | 29 | m.send_all("WHO " + chan) 30 | m.expect(c3a, "with CAP multi-prefix WHO should show all prefixes", "352.*c1a.* H@%\+ :") 31 | m.expect(c2a, "without CAP multi-prefix WHO should only show the highest prefix", "352.*c1a.* H@ :") 32 | print 33 | -------------------------------------------------------------------------------- /tests/services/sasl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c1a, "CAP REQ :sasl") 11 | m.expect(c1a, "SASL CAP available and enabled", ":.+ CAP $c1a ACK :sasl") 12 | m.clearlog() 13 | print 14 | 15 | m.send(c1a, "AUTHENTICATE PLAIN") 16 | m.expect(c1a, "AUTHENTICATE plain go ahead", "AUTHENTICATE \+", timeout = 10) 17 | m.clearlog() 18 | print 19 | 20 | # client1 \000 client1 \000 test 21 | m.send(c1a, "AUTHENTICATE Y2xpZW50MQBjbGllbnQxAHRlc3Q=") 22 | m.expect(c1a, "SASL authentication successful", ":.+ 903 $c1a :SASL authentication successful", timeout = 10) 23 | m.clearlog() 24 | print 25 | 26 | # Lazy way to make sure the SASL propagated completely 27 | m.send(c1a, "VERSION services.test.net") 28 | m.expect(c1a, "Services version response", ":services\.test\.net 351 $c1a .*", timeout = 10) 29 | m.clearlog() 30 | print 31 | 32 | m.send_all("WHOIS $c1a") 33 | m.expect_all("Show account in WHOIS", ":.+ 330 $me $c1a client1 :is logged in as") 34 | m.clearlog() 35 | print 36 | -------------------------------------------------------------------------------- /tests/opercommands/dns: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | m.connect() 7 | 8 | m.send(c1a, "DNS") 9 | m.expect(c1a, "Command not permitted as non-ircop", ":.+ 481 $me :Permission Denied") 10 | m.clearlog() 11 | print 12 | 13 | m.send(c1a, "OPER netadmin test") 14 | m.send(c1a, "DNS") 15 | m.expect(c1a, "DNS Statistics (header)", ":.+ 304 $me :DNS CACHE Stats") 16 | m.expect(c1a, "DNS Statistics (hits)", ":.+ 304 $me : hits: [0-9]+") 17 | m.expect(c1a, "DNS Statistics (misses)", ":.+ 304 $me : misses: [0-9]+") 18 | m.clearlog() 19 | print 20 | 21 | m.send(c1a, "DNS l") 22 | m.expect(c1a, "DNS Cache list (header)", ":.+ 304 $me :DNS CACHE List") 23 | # should be safe to check for this: 24 | # nope, not anymore: https://github.com/c-ares/c-ares/pull/430 25 | # too bad. now we can't check this anymore. 26 | #m.expect(c1a, "DNS Statistics (hits)", ":.+ 304 $me : localhost \[127\.0\.0\.1\]") 27 | m.clearlog() 28 | print 29 | 30 | m.send(c1a, "DNS c") 31 | m.expect(c1a, "DNS Cache clear", ":.+ NOTICE $me :.*DNS cache cleared") 32 | m.clearlog() 33 | print 34 | -------------------------------------------------------------------------------- /tests/usermodes/noctcp: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c1a, "MODE $c1a +T") 11 | m.expect(c1a, "MODE set", "MODE $c1a :\+T") 12 | print 13 | 14 | m.send_all("PRIVMSG $c1a :\001CTCPTEST\001", skip = c1a) 15 | m.expect_all("Error indicating CTCP was blocked (numeric 531)", "531.*does not accept CTCP", skip = c1a) 16 | print 17 | 18 | m.send_all("PRIVMSG $c1a :aa sunshine bb", skip = c1a) 19 | m.expect(c1a, "should not block regular text with +T (1 of 2)", ":c2a.*PRIVMSG.*aa sunshine bb") 20 | m.expect(c1a, "should not block regular text with +T (2 of 2)", ":c3a.*PRIVMSG.*aa sunshine bb") 21 | print 22 | 23 | m.send(c1a, "MODE $c1a -T") 24 | m.expect(c1a, "MODE unset", "MODE $c1a :-T") 25 | print 26 | m.clearlog() 27 | 28 | m.send_all("PRIVMSG $c1a :\001CTCPTEST\001", skip = c1a) 29 | m.expect(c1a, "should not block CTCPs with -T (1 of 2)", ":c2a.*PRIVMSG.*\001CTCPTEST\001") 30 | m.expect(c1a, "should not block CTCPs with -T (2 of 2)", ":c3a.*PRIVMSG.*\001CTCPTEST\001") 31 | print 32 | -------------------------------------------------------------------------------- /tests/extensions/away-notify: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | print 14 | 15 | m.send(c1a, "CAP REQ away-notify") 16 | m.send(c3a, "AWAY :I am away") 17 | m.expect(c1a, "away-notify should show user going AWAY", ":c3a.* AWAY :I am away") 18 | m.not_expect(c2a, "without away-notify it should not show user going AWAY", ":c3a.* AWAY :I am away") 19 | m.clearlog() 20 | print 21 | 22 | m.send(c3a, "AWAY :I am still away") 23 | m.expect(c1a, "away-notify should show user going AWAY", ":c3a.* AWAY :I am still away") 24 | m.not_expect(c2a, "without away-notify it should not show user going AWAY", ":c3a.* AWAY :I am still away") 25 | m.clearlog() 26 | print 27 | 28 | m.send(c3a, "AWAY") 29 | m.expect(c1a, "away-notify should show user coming back from AWAY", ":c3a.* AWAY$") 30 | m.not_expect(c2a, "without away-notify it should not show user combing back from AWAY", ":c3a.* AWAY$") 31 | m.clearlog() 32 | print 33 | -------------------------------------------------------------------------------- /tests/usercommands/knock: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c1a, skip = c3a) 12 | m.expect(c1a, "first user in channel", ":c1a.*JOIN") 13 | m.expect(c2a, "second user in channel", ":c2a.*JOIN") 14 | m.clearlog() 15 | print 16 | 17 | m.send(c1a, "MODE " + chan + " +i") 18 | m.expect(c2a, "MODE +i", ":c1a.*MODE.*\+i") 19 | m.clearlog() 20 | print 21 | 22 | m.send(c3a, "KNOCK " + chan) 23 | m.expect(c3a, "knocked response", "Knocked on " + chan) 24 | m.expect(c1a, "Knock notice to ops", ".*Knock.*by $c3a.*no reason") 25 | m.not_expect(c2a, "No knock notice to non-ops", ".*Knock.*by") # no ops = no knock noticem 26 | m.clearlog() 27 | print 28 | 29 | m.send(c3a, "KNOCK " + chan + " :hi there!") 30 | m.expect(c3a, "knocked response", "Knocked on " + chan) 31 | m.expect(c1a, "Knock notice to ops", ".*Knock.*by $c3a.*hi there") 32 | m.not_expect(c2a, "No knock notice to non-ops", ".*Knock.*by") # no ops = no knock noticem 33 | m.clearlog() 34 | print 35 | -------------------------------------------------------------------------------- /tests/extbans/realname: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, skip = c3a, creator=c1a) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | m.clearlog() 14 | print 15 | 16 | m.send(c3a, "SETNAME bannedrealname") 17 | m.send(c1a, "MODE " + chan + " +b ~realname:bannedreal*") 18 | m.expect(c1a, "expect ban to be set", ":.+ MODE " + chan + " \+b") 19 | m.clearlog() 20 | print 21 | 22 | m.send(c3a, "JOIN " + chan) 23 | m.expect(c3a, "Client should receive error on JOIN attempt", ":irc.+ 474 $c3a " + chan + " :Cannot join channel \(\+b\)") 24 | m.not_expect_all("Client should NOT be able to join with +b ~realname", ":c3a.* JOIN ") 25 | m.clearlog() 26 | print 27 | 28 | m.send(c3a, "SETNAME allowedrealname") 29 | m.send(c3a, "JOIN " + chan) 30 | m.not_expect(c3a, "Client should NOT receive error on JOIN attempt", ":irc.+ 474 $c3a " + chan + " :Cannot join channel \(\+b\)") 31 | m.expect_all("Client should be able to join now", ":c3a.* JOIN ") 32 | m.clearlog() 33 | print 34 | -------------------------------------------------------------------------------- /tests/extensions/cap: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c1a, "CAP LS") 11 | m.expect(c1a, "versionless CAP LS should not show capability values", " CAP .* LS :.*unrealircd.org/link-security( |$)") 12 | m.clearlog() 13 | print 14 | 15 | m.send(c1a, "CAP LIST") 16 | m.expect(c1a, "CAP LIST should only show the 2 caps requested by irctestframework", " CAP .* LIST :message-tags account-tag") 17 | m.clearlog() 18 | print 19 | 20 | m.send(c2a, "CAP LS 300") 21 | m.expect(c2a, "CAP LS 300 should not show capability values", " CAP .* LS :.*unrealircd.org/link-security( |$)") 22 | m.clearlog() 23 | print 24 | 25 | m.send(c3a, "CAP LS 302") 26 | m.expect(c3a, "CAP LS 302 should show capability values", " CAP .* LS :.*unrealircd.org/link-security=[0-9]+") 27 | m.clearlog() 28 | print 29 | 30 | m.send(c1a, "CAP LS 302") 31 | m.send(c1a, "CAP REQ chghost") 32 | m.send(c1a, "CAP LIST") 33 | m.expect(c1a, "CAP LIST should show cap-notify and chghost", " CAP .* LIST :cap-notify chghost message-tags account-tag") 34 | -------------------------------------------------------------------------------- /tests/chanmodes/censor: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c2a) 12 | m.send(c2a, "MODE " + chan + " +G") 13 | m.expect(c1a, "users in channel", "JOIN") 14 | m.expect(c1a, "MODE +G", "MODE.*\+G") 15 | print 16 | 17 | m.send(c1a, "PRIVMSG " + chan + " :aa fucked bb") 18 | m.expect(c3a, "should censor badwords with +G", ":c1a.*PRIVMSG.*aa bb") 19 | print 20 | 21 | m.send(c1a, "PRIVMSG " + chan + " :aa sunshine bb") 22 | m.expect(c3a, "should not censor non-badwords with +G", ":c1a.*PRIVMSG.*aa sunshine bb") 23 | print 24 | 25 | m.send(c2a, "MODE " + chan + " -G") 26 | m.expect(c1a, "MODE -G", "MODE.*\-G") 27 | print 28 | m.clearlog() 29 | 30 | m.send(c1a, "PRIVMSG " + chan + " :aa fucked bb") 31 | m.expect(c3a, "should not censor badwords without +G", ":c1a.*PRIVMSG.*aa fucked bb") 32 | print 33 | 34 | m.send(c1a, "PRIVMSG " + chan + " :aa sunshine bb") 35 | m.expect(c3a, "should not censor non-badwords without +G", ":c1a.*PRIVMSG.*aa sunshine bb") 36 | print 37 | -------------------------------------------------------------------------------- /tests/extbans/inchannel: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, skip = c3a, creator=c1a) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | m.clearlog() 14 | print 15 | 16 | bannedchan = m.randchan() 17 | m.send(c3a, "JOIN " + bannedchan) 18 | m.send(c1a, "MODE " + chan + " +b ~channel:" + bannedchan) 19 | m.expect(c1a, "expect ban to be set", ":.+ MODE " + chan + " \+b") 20 | m.clearlog() 21 | print 22 | 23 | m.send(c3a, "JOIN " + chan) 24 | m.expect(c3a, "Client should receive error on JOIN attempt", ":irc.+ 474 $c3a " + chan + " :Cannot join channel \(\+b\)") 25 | m.not_expect_all("Client should NOT be able to join with +b ~channel", ":c3a.* JOIN ") 26 | m.clearlog() 27 | print 28 | 29 | m.send(c3a, "PART " + bannedchan) 30 | m.send(c3a, "JOIN " + chan) 31 | m.not_expect(c3a, "Client should NOT receive error on JOIN attempt", ":irc.+ 474 $c3a " + chan + " :Cannot join channel \(\+b\)") 32 | m.expect_all("Client should be able to join now", ":c3a.* JOIN ") 33 | m.clearlog() 34 | print 35 | -------------------------------------------------------------------------------- /tests/usercommands/whowas: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | import time 4 | 5 | m = irctestframework.irctest.IrcTest() 6 | c1a = m.new('c1a') 7 | c2a = m.new('c2a') 8 | c3a = m.new('c3a') 9 | m.connect() 10 | 11 | # Should return no results if user is online 12 | m.send(c1a, "WHOWAS $c3a") 13 | m.expect(c1a, "Nickname not found (expected)", ":.+ 406 $me $c3a :There was no such nickname") 14 | m.expect(c1a, "End of WHOWAS", ":.+ 369 $me $c3a :End of WHOWAS") 15 | 16 | # Need to disable the auto-syncer since one client will go off-line 17 | m.sync = 0 18 | 19 | # Test quit 20 | m.send(c3a, "QUIT :poof!") 21 | time.sleep(5) # <- we must be sure the user is offline... 22 | m.clearlog() 23 | print 24 | 25 | # And now we should have a WHOWAS entry 26 | m.send(c1a, "WHOWAS $c3a") 27 | m.expect(c1a, "WHOWAS reply (314, nuhr)", ":.+ 314 $me $c3a username Clk-.* \* :Test framework", timeout = 10) 28 | m.expect(c1a, "WHOWAS reply (312, server and time)", ":.+ 312 $me $c3a irc3\.test\.net :.*", timeout = 10) 29 | m.expect(c1a, "End of WHOWAS", ":.+ 369 $me $c3a :End of WHOWAS", timeout = 10) 30 | m.not_expect(c1a, "No nickname not found", ":.+ 406 $me $c3a") 31 | m.clearlog() 32 | print 33 | -------------------------------------------------------------------------------- /tests/usermodes/regonlymsg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | # Need to disable the auto-syncer here due to the +R 11 | m.sync = 0 12 | 13 | m.send(c1a, "MODE $c1a +R") 14 | m.expect(c1a, "MODE set", "MODE $c1a :\+R", timeout = 10) 15 | m.clearlog() 16 | print 17 | 18 | m.send_all("PRIVMSG $c1a :test 123", skip = c1a) 19 | m.expect_all("should error on unregistered msg to +R user", "531.*You must identify", skip = c1a, timeout = 15) 20 | m.not_expect(c1a, "No message from unregistered users", "test 123") 21 | m.clearlog() 22 | print 23 | 24 | # Syncer can be re-enabled, yay: 25 | m.sync = 1 26 | m.send(c1a, "MODE $c1a -R") 27 | m.expect(c1a, "MODE unset", "MODE $c1a :-R") 28 | m.clearlog() 29 | print 30 | 31 | m.send_all("PRIVMSG $c1a :test 456", skip = c1a) 32 | m.expect(c1a, "Message from unregistered users with -R", ":c2a.*test 456") 33 | m.expect(c1a, "Message from unregistered users with -R", ":c3a.*test 456") 34 | m.not_expect_all("should NOT error on unregistered msg to +R user", "531.*You must identify", skip = c1a) 35 | print 36 | 37 | -------------------------------------------------------------------------------- /tests/opercommands/kill: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c1a) 12 | m.expect(c1a, "user in channel", "JOIN") 13 | print 14 | 15 | m.send(c1a, "KILL $c3a :please die") 16 | m.expect(c1a, "Command not permitted as non-ircop", ":.+ 481 $me :Permission Denied") 17 | m.clearlog() 18 | print 19 | 20 | m.send(c1a, "OPER netadmin test") 21 | m.send(c2a, "OPER netadmin test") 22 | # Disable syncer since one of the clients is going to die 23 | m.sync = 0 24 | m.send(c1a, "KILL $c3a :please die") 25 | m.expect_all("KILL Notice to opers", ":.+ NOTICE $me :.*Client killed.* $c3a.*\[by: $c1a\] \(please die\)", timeout = 5, skip = c3a) 26 | m.expect(c3a, "Killed client should see KILL notification", ":$c1a.+ KILL $c3a :please die", timeout = 5) 27 | m.expect(c3a, "Killed client should receive ERROR Closing link", "ERROR :Closing Link: $c3a.*\(Killed by $c1a \(please die\)\)", timeout = 5) 28 | m.expect_all("See QUIT in channel", ":$c3a.+ QUIT :Killed by $c1a \(please die\)", timeout = 5, skip = c3a) 29 | print 30 | -------------------------------------------------------------------------------- /tests/chanmodes/inviteonly: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c1a, skip = c3a) 12 | m.expect(c1a, "first user in channel", ":c1a.*JOIN") 13 | m.expect(c2a, "second user in channel", ":c2a.*JOIN") 14 | m.clearlog() 15 | print 16 | 17 | m.send(c1a, "MODE " + chan + " +i") 18 | m.expect(c2a, "MODE +i", ":c1a.*MODE.*\+i") 19 | m.clearlog() 20 | print 21 | 22 | m.send_all("MODE " + chan) 23 | m.expect_all("See channel as currently +i", ":.* 324 $me " + chan + " \+i") 24 | m.clearlog() 25 | print 26 | m.send(c3a, "JOIN " + chan) 27 | m.expect(c3a, "unable to join with +i (numeric 473)", "473.*Cannot join channel.*\+i") 28 | m.not_expect(c1a, "should not see JOIN for user if +i", ":c3a.*JOIN") 29 | print 30 | m.clearlog() 31 | 32 | m.send(c1a, "MODE " + chan + " +I c3a*!*@*") 33 | m.send(c3a, "JOIN " + chan) 34 | m.not_expect(c3a, "no unable to join (numeric 473) with matching invex (+I)", "473.*Cannot join channel.*\+i") 35 | m.expect(c1a, "should see JOIN for user if +i with matching invex (+I)", ":c3a.*JOIN") 36 | print 37 | -------------------------------------------------------------------------------- /tests/extbans/nickchange: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, skip = c3a, creator=c1a) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | m.clearlog() 14 | print 15 | 16 | m.send(c1a, "MODE " + chan + " +b ~nickchange:$c3a!*@*") 17 | m.expect(c1a, "expect ban to be set", ":.+ MODE " + chan + " \+b") 18 | m.clearlog() 19 | print 20 | 21 | m.send(c3a, "JOIN " + chan) 22 | m.expect_all("Client should be able to join with +b ~nickchange", ":c3a.* JOIN ") 23 | m.clearlog() 24 | print 25 | 26 | m.send(c3a, "PRIVMSG " + chan + " :this should not be blocked") 27 | m.not_expect(c3a, "Message should NOT be blocked with +b ~nickchange", ":irc.+ 404 $c3a " + chan + " :You are banned") 28 | m.expect_all("Message should go through", "this should not be blocked", skip = c3a) 29 | m.clearlog() 30 | print 31 | 32 | # Disable syncer due to nick change 33 | m.sync = 0 34 | m.send(c3a, "NICK hfdhsfdfsdh") 35 | m.expect(c3a, "Nick change should be blocked", ":irc.+ 437 .* " + chan + " :Cannot change nick", timeout = 5) 36 | m.clearlog() 37 | print 38 | -------------------------------------------------------------------------------- /tests/opercommands/tempshun: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | import time 4 | 5 | m = irctestframework.irctest.IrcTest() 6 | c1a = m.new('c1a') 7 | c2a = m.new('c2a') 8 | c3a = m.new('c3a') 9 | m.connect() 10 | 11 | chan = m.randchan() 12 | m.join_all(chan, creator = c1a, skip = c3a) 13 | m.expect(c1a, "see others joining", ":c2a.*JOIN") 14 | m.clearlog() 15 | print 16 | 17 | m.send(c1a, "TEMPSHUN $c3a please shut up") 18 | m.expect(c1a, "Command not permitted as non-ircop", ":.+ 481 $me :Permission Denied") 19 | m.clearlog() 20 | print 21 | 22 | m.send(c1a, "OPER netadmin test") 23 | m.sync = 0 24 | # Disable syncer, since one of the clients can no longer msg. 25 | m.send(c1a, "TEMPSHUN $c3a please shut up") 26 | m.expect(c1a, "Temporary shun added notice", ":irc3.+ NOTICE $c1a :.*Temporary shun added on user $c3a.* \[reason: please shut up\] \[by: $c1a\]", timeout = 5) 27 | m.clearlog() 28 | print 29 | 30 | m.send(c3a, "PRIVMSG " + chan + " :this message should not be delivered") 31 | time.sleep(5) # yeah, I don't like it either, but it's necessary.. 32 | m.not_expect_all("TEMPSHUNed user should not be able to PRIVMSG (should not error, but no delivery either)", ":$c3a.*PRIVMSG") 33 | m.clearlog() 34 | print 35 | -------------------------------------------------------------------------------- /tests/chanmodes/operonly: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c1a, skip = c3a) 12 | m.expect(c1a, "first user in channel", ":c1a.*JOIN") 13 | m.expect(c2a, "second user in channel", ":c2a.*JOIN") 14 | print 15 | 16 | m.send(c1a, "MODE " + chan + " +O") 17 | m.expect(c1a, "cannot set +O if not IRCOp", "974.*You are not an IRC operator") 18 | m.not_expect(c2a, "no MODE +O if not IRCOp", ":c1a.*MODE.*\+O") 19 | m.clearlog() 20 | print 21 | 22 | m.send(c1a, "OPER netadmin test") 23 | m.send(c1a, "MODE " + chan + " +O") 24 | m.expect(c2a, "MODE +O set", ":c1a.*MODE.*\+O") 25 | print 26 | 27 | m.send(c3a, "JOIN " + chan) 28 | m.expect(c3a, "unable to join with +O (numeric 520)", "520.*IRCops only") 29 | m.not_expect(c1a, "should not see JOIN for user if +O", ":c3a.*JOIN") 30 | m.clearlog() 31 | print 32 | 33 | m.send(c3a, "OPER netadmin test") 34 | m.send(c3a, "JOIN " + chan) 35 | m.not_expect(c3a, "able to join with +O if oper (nonumeric 520)", "520.*IRCops only") 36 | m.expect(c1a, "should see JOIN for user if +O and IRCOp", ":c3a.*JOIN") 37 | print 38 | -------------------------------------------------------------------------------- /tests/usercommands/silence: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c1a, "SILENCE +$c2a") 11 | m.expect(c1a, "Added message", ":$c1a.* SILENCE \+$c2a\!\*@\*") 12 | m.clearlog() 13 | print 14 | 15 | m.send(c1a, "SILENCE") 16 | m.expect(c1a, "Silence list shows added item", ":.+ 271 $me $c2a\!\*@\*") 17 | m.expect(c1a, "Silence list end", ":.+ 272 $me :End of Silence List") 18 | m.clearlog() 19 | print 20 | 21 | # blocked via SILENCE: 22 | m.send(c2a, "PRIVMSG $c1a :test message") 23 | m.not_expect(c1a, "should not receive test message (silenced)", "test message") 24 | m.clearlog() 25 | print 26 | 27 | # NOT silenced: 28 | m.send(c3a, "PRIVMSG $c1a :test message") 29 | m.expect(c1a, "should receive test message (not silenced)", "test message") 30 | m.clearlog() 31 | print 32 | 33 | m.send(c1a, "SILENCE -$c2a") 34 | m.expect(c1a, "Remove message", ":$c1a.* SILENCE -$c2a\!\*@\*") 35 | m.clearlog() 36 | print 37 | 38 | # No longer blocked via SILENCE: 39 | m.send(c2a, "PRIVMSG $c1a :test message") 40 | m.expect(c1a, "should receive test message (no longer silenced)", "test message") 41 | m.clearlog() 42 | print 43 | -------------------------------------------------------------------------------- /tests/usermodes/censor: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c1a, "MODE $c1a +G") 11 | m.expect(c1a, "MODE set", "MODE $c1a :\+G") 12 | print 13 | 14 | m.send(c2a, "PRIVMSG $c1a :aa fucked bb") 15 | m.send(c3a, "PRIVMSG $c1a :aa fucked bb") 16 | m.expect(c1a, "should censor badwords with +G", ":c2a.*PRIVMSG.*aa bb") 17 | m.expect(c1a, "should censor badwords with +G", ":c3a.*PRIVMSG.*aa bb") 18 | print 19 | 20 | m.send(c2a, "PRIVMSG $c1a :aa sunshine bb") 21 | m.send(c3a, "PRIVMSG $c1a :aa sunshine bb") 22 | m.expect(c1a, "should not censor non-badwords with +G", ":c2a.*PRIVMSG.*aa sunshine bb") 23 | m.expect(c1a, "should not censor non-badwords with +G", ":c3a.*PRIVMSG.*aa sunshine bb") 24 | print 25 | 26 | m.send(c1a, "MODE $c1a -G") 27 | m.expect(c1a, "MODE unset", "MODE $c1a :-G") 28 | print 29 | m.clearlog() 30 | 31 | m.send(c2a, "PRIVMSG $c1a :aa fucked bb") 32 | m.send(c3a, "PRIVMSG $c1a :aa fucked bb") 33 | m.expect(c1a, "should not censor badwords with -G", ":c2a.*PRIVMSG.*aa fucked bb") 34 | m.expect(c1a, "should not censor badwords with -G", ":c3a.*PRIVMSG.*aa fucked bb") 35 | print 36 | -------------------------------------------------------------------------------- /tests/usercommands/away: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c1a, "AWAY :I am away") 11 | m.expect(c1a, "receive AWAY numeric 306", ":.+ 306 $me :You have been marked as being away") 12 | m.clearlog() 13 | print 14 | 15 | m.send(c1a, "AWAY :I am away. Yes, really.") 16 | m.expect(c1a, "receive AWAY numeric 306 (again)", ":.+ 306 $me :You have been marked as being away") 17 | m.clearlog() 18 | print 19 | 20 | m.send_all("WHOIS $c1a $c1a") 21 | m.expect_all("End of WHOIS", ":.+ 318", timeout = 5) 22 | m.expect_all("show AWAY in WHOIS", ":.+ 301 $me $c1a :I am away") 23 | m.clearlog() 24 | print 25 | 26 | m.send_all("PRIVMSG $c1a :test") 27 | m.expect_all("see AWAY message on PRIVMSG", ":.+ 301 $me $c1a :I am away") 28 | m.clearlog() 29 | print 30 | 31 | m.send(c1a, "AWAY") 32 | m.expect(c1a, "receive no longer AWAY (numeric 305)", ":.+ 305 $me :You are no longer marked as being away") 33 | m.clearlog() 34 | print 35 | 36 | m.send_all("WHOIS $c1a $c1a") 37 | m.expect_all("End of WHOIS", ":.+ 318", timeout = 5) 38 | m.not_expect_all("Don't show AWAY in WHOIS", ":.+ 301 $me $c1a :I am away") 39 | m.clearlog() 40 | print 41 | -------------------------------------------------------------------------------- /tests/opercommands/dccdeny: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c1b = m.new('c1b') 7 | c1c = m.new('c1c') 8 | m.connect() 9 | 10 | m.send(c1c, "PRIVMSG $c1b :\001DCC SEND some.forbidden 12345 1024 65535\001") 11 | m.expect(c1b, "Expect DCC to go through", "\001DCC SEND some\.forbidden") 12 | m.clearlog() 13 | print 14 | 15 | m.send(c1a, "DCCDENY *.forbidden this is not allowed") 16 | m.expect(c1a, "Command not permitted as non-ircop", ":.+ 481 $me :Permission Denied") 17 | m.clearlog() 18 | print 19 | 20 | m.send(c1a, "OPER netadmin test") 21 | m.send(c1a, "DCCDENY *.forbidden this is not allowed") 22 | m.expect(c1a, "Added DCCDENY notice", "$c1a added a temporary DCCDENY for \*\.forbidden \(this is not allowed\)") 23 | m.clearlog() 24 | print 25 | 26 | m.send(c1c, "PRIVMSG $c1b :\001DCC SEND some.forbidden 12345 1024 65535\001") 27 | m.not_expect(c1b, "DCC should not go through", "\001DCC SEND some\.forbidden") 28 | m.expect(c1c, "Blocked message", ":.+ 531 $me $c1b :Cannot DCC SEND file: this is not allowed") 29 | m.clearlog() 30 | print 31 | 32 | m.send(c1a, "UNDCCDENY *.forbidden") 33 | m.expect(c1a, "Removed DCCDENY notice", "$c1a removed a temporary DCCDENY for \*\.forbidden") 34 | m.clearlog() 35 | print 36 | 37 | -------------------------------------------------------------------------------- /tests/chanmodes/permanent: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.send(c1a, "JOIN " + chan) 12 | m.expect(c1a, "user in channel", ":c1a.*JOIN") 13 | print 14 | 15 | m.send(c1a, "MODE " + chan + " +P") 16 | m.expect(c1a, "cannot set +P if not IRCOp", "481.*IRC operator") 17 | m.not_expect(c2a, "no MODE +P if not IRCOp", ":c1a.*MODE.*\+P") 18 | m.clearlog() 19 | print 20 | 21 | m.send(c1a, "OPER netadmin test") 22 | m.send(c1a, "MODE " + chan + " +PT") 23 | m.send(c1a, "MODE " + chan + " +beI ban!*@* exempt!*@* invex!*@*") 24 | m.expect(c1a, "MODE +PT", "MODE.*\+PT") 25 | m.expect(c1a, "MODE +beI", "MODE.*\+beI") 26 | m.clearlog() 27 | print 28 | 29 | m.send(c1a, "PART " + chan) 30 | m.join_all(chan, creator=c2a) 31 | m.send_all("MODE " + chan) 32 | m.send_all("MODE " + chan + " b") 33 | m.send_all("MODE " + chan + " e") 34 | m.send_all("MODE " + chan + " I") 35 | m.expect_all("MODE +PT should be set after rejoin", "324.*\+PT") 36 | m.expect_all("ban should be set after rejoin", "367.*ban!") 37 | m.expect_all("exempts should be set after rejoin", "348.*exempt!") 38 | m.expect_all("invexes should be set after rejoin", "346.*invex!") 39 | -------------------------------------------------------------------------------- /tests/db/writing/permanent: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = "#permanent_test" 11 | m.send(c1a, "JOIN " + chan) 12 | m.expect(c1a, "user in channel", ":c1a.*JOIN") 13 | print 14 | 15 | m.send(c1a, "MODE " + chan + " +P") 16 | m.expect(c1a, "cannot set +P if not IRCOp", "481.*IRC operator") 17 | m.not_expect(c2a, "no MODE +P if not IRCOp", ":c1a.*MODE.*\+P") 18 | m.clearlog() 19 | print 20 | 21 | m.send(c1a, "OPER netadmin test") 22 | m.send(c1a, "MODE " + chan + " +PT") 23 | m.send(c1a, "MODE " + chan + " +beI ban!*@* exempt!*@* invex!*@*") 24 | m.expect(c1a, "MODE +PT", "MODE.*\+PT") 25 | m.expect(c1a, "MODE +beI", "MODE.*\+beI") 26 | m.clearlog() 27 | print 28 | 29 | m.send(c1a, "PART " + chan) 30 | m.join_all(chan, creator=c2a) 31 | m.send_all("MODE " + chan) 32 | m.send_all("MODE " + chan + " b") 33 | m.send_all("MODE " + chan + " e") 34 | m.send_all("MODE " + chan + " I") 35 | m.expect_all("MODE +TP should be set after rejoin", "324.*\+PT") 36 | m.expect_all("ban should be set after rejoin", "367.*ban!") 37 | m.expect_all("exempts should be set after rejoin", "348.*exempt!") 38 | m.expect_all("invexes should be set after rejoin", "346.*invex!") 39 | -------------------------------------------------------------------------------- /tests/extbans/join: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, skip = c3a, creator=c1a) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | m.clearlog() 14 | print 15 | 16 | m.send(c1a, "MODE " + chan + " +b ~join:$c3a!*@*") 17 | m.expect(c1a, "expect ban to be set", ":.+ MODE " + chan + " \+b") 18 | m.clearlog() 19 | print 20 | 21 | m.send(c3a, "JOIN " + chan) 22 | m.expect(c3a, "Client should receive error on JOIN attempt", ":irc.+ 474 $c3a " + chan + " :Cannot join channel \(\+b\)") 23 | m.not_expect_all("Client should NOT be able to join with +b ~join", ":c3a.* JOIN ") 24 | m.clearlog() 25 | print 26 | 27 | m.send(c1a, "INVITE $c3a " + chan) 28 | m.expect(c3a, "INVITE", ":c1a.* INVITE $me :" + chan) 29 | m.send(c3a, "JOIN " + chan) 30 | m.expect_all("Client should be able to join after INVITE from chanop", ":c3a.* JOIN ") 31 | m.clearlog() 32 | print 33 | 34 | m.send(c3a, "PRIVMSG " + chan + " :this should not be blocked") 35 | m.not_expect(c3a, "Message should NOT be blocked with +b ~join", ":irc.+ 404 $c3a " + chan + " :You are banned") 36 | m.expect_all("Message should go through", "this should not be blocked", skip = c3a) 37 | m.clearlog() 38 | print 39 | -------------------------------------------------------------------------------- /tests/usercommands/topic: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c1a) 12 | m.expect(c1a, "user in channel", "JOIN") 13 | print 14 | 15 | m.send(c1a, "TOPIC " + chan + " :this is a nice new topic") 16 | m.expect_all("Everyone should see TOPIC change", ":$c1a.* TOPIC " + chan + " :this is a nice new topic") 17 | m.clearlog() 18 | print 19 | 20 | m.send_all("TOPIC " + chan) 21 | m.expect_all("After querying for topic, see the topic text via numeric 332", " 332 .* " + chan + " :this is a nice new topic") 22 | m.expect_all("After querying for topic, see the topic setter and time via numeric 333", " 333 .* " + chan + " $c1a!.*@.* [0-9]{10}") 23 | m.clearlog() 24 | print 25 | 26 | m.send(c1a, "TOPIC " + chan + " :") 27 | m.expect_all("Everyone should see TOPIC change when set to empty", ":$c1a.* TOPIC " + chan + " :") 28 | m.clearlog() 29 | print 30 | 31 | m.send_all("TOPIC " + chan) 32 | m.expect_all("After querying for topic, see the (empty) topic text via numeric 332", " 332 .* " + chan + " :") 33 | m.expect_all("After querying for topic, see the topic setter and time via numeric 333", " 333 .* " + chan + " $c1a!.*@.* [0-9]{10}") 34 | m.clearlog() 35 | print 36 | -------------------------------------------------------------------------------- /tests/services/account-tag: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c2a, "NS IDENTIFY client2 test") 11 | m.expect(c2a, "Identified to account", ":irc.* 900 ", timeout = 10) 12 | m.clearlog() 13 | print 14 | 15 | # For PRIVMSG test later.. 16 | m.send(c2a, "CAP REQ echo-message") 17 | m.clearlog() 18 | print 19 | 20 | chan = m.randchan() 21 | m.join_all(chan, skip = c2a, creator=c1a) 22 | m.expect(c1a, "users in channel", "JOIN") 23 | m.clearlog() 24 | print 25 | 26 | m.send(c2a, "JOIN " + chan) 27 | m.expect_all("Account tag in JOIN", "account=client2") 28 | m.clearlog() 29 | print 30 | 31 | m.send(c2a, "PRIVMSG " + chan + " :hello!") 32 | m.expect_all("Account tag in PRIVMSG", "account=client2") 33 | m.clearlog() 34 | print 35 | 36 | m.send(c2a, "PART " + chan) 37 | m.expect_all("Account tag in PART", "account=client2") 38 | m.clearlog() 39 | print 40 | 41 | m.send(c2a, "JOIN " + chan) 42 | m.expect_all("Account tag in JOIN (again)", "account=client2") 43 | m.clearlog() 44 | print 45 | 46 | # Need to disable the auto-syncer here due to 1 client disappearing. 47 | m.sync = 0 48 | 49 | m.send(c2a, "QUIT :goodbye") 50 | m.expect_all("Account tag in QUIT", "account=client2", timeout = 5, skip = c2a) 51 | m.clearlog() 52 | print 53 | -------------------------------------------------------------------------------- /tests/chanmodes/stripcolor: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c2a) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | print 14 | 15 | m.send(c1a, "PRIVMSG " + chan + " :\0034this is red\003") 16 | m.not_expect(c1a, "should not strip color in messages (no 404 numeric) with -S", " 404 .*Color is not permitted") 17 | m.expect(c3a, "should not strip color in messages with -S", ":c1a.*PRIVMSG.*\0034this is red") 18 | m.clearlog() 19 | print 20 | 21 | m.send(c1a, "PRIVMSG " + chan + " :\0026this is reverse\003") 22 | m.not_expect(c1a, "should not strip reverse in messages (no 404 numeric) with -S", " 404 .*Color is not permitted") 23 | m.expect(c3a, "should not strip reverse in messages with -S", ":c1a.*PRIVMSG.*\0026this is reverse") 24 | m.clearlog() 25 | print 26 | 27 | m.send(c2a, "MODE " + chan + " +S") 28 | m.expect(c1a, "MODE +S", ":c2a.*MODE.*\+S") 29 | print 30 | 31 | m.send(c1a, "PRIVMSG " + chan + " :\0034this is red\003") 32 | m.expect(c3a, "should strip color in messages with +S", ":c1a.*PRIVMSG.*:this is red") 33 | print 34 | 35 | m.send(c1a, "PRIVMSG " + chan + " :\026this is reverse\026") 36 | m.expect(c3a, "should strip reverse in messages with +S", ":c1a.*PRIVMSG.*:this is reverse") 37 | print 38 | -------------------------------------------------------------------------------- /tests/usercommands/monitor: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c1a, "MONITOR + $c3a") 11 | m.expect(c1a, "730 numeric for user that is online", ":.+ 730 $me :$c3a!username@Clk.*") 12 | m.clearlog() 13 | print 14 | 15 | m.send(c1a, "MONITOR + somenick-m") 16 | m.expect(c1a, "731 numeric for user that is offline", ":.+ 731 $me :somenick-m") 17 | m.clearlog() 18 | print 19 | 20 | m.send(c1a, "MONITOR S") 21 | m.expect(c1a, "730 numeric for user that is online", ":.+ 730 $me :$c3a!username@Clk.*") 22 | m.expect(c1a, "731 numeric for user that is offline", ":.+ 731 $me :somenick-m") 23 | m.clearlog() 24 | print 25 | 26 | # Need to disable the auto-syncer here due to the nick change 27 | m.sync = 0 28 | 29 | # Test nick change 30 | c3a_original_nick = c3a.nick 31 | m.send(c3a, "NICK somenick-m") 32 | m.expect(c1a, "731 numeric for user that went offline (nick change)", ":.+ 731 $me :" + c3a_original_nick, timeout = 10) 33 | m.expect(c1a, "730 numeric for user that got online (nick change)", ":.+ 730 $me :somenick-m!username@Clk-.*", timeout = 10) 34 | m.clearlog() 35 | print 36 | 37 | # Test quit 38 | m.send(c3a, "QUIT :poof!") 39 | m.expect(c1a, "731 numeric for user that went offline (quit)", ":.+ 731 $me :somenick-m", timeout = 10) 40 | m.clearlog() 41 | print 42 | -------------------------------------------------------------------------------- /tests/usercommands/dccallow: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c1a, "DCCALLOW +$c2a") 11 | m.clearlog() 12 | print 13 | 14 | m.send(c1a, "DCCALLOW LIST") 15 | m.expect(c1a, "DCCALLOW LIST shows added item", ":.+ 620 $me :The following users are on your") 16 | m.expect(c1a, "DCCALLOW LIST item", ":.+ 618 $me :$c2a \(.*@Clk-.*") 17 | m.expect(c1a, "DCCALLOW LIST end", ":.+ 619 $me :End of DCCALLOW LIST") 18 | m.clearlog() 19 | print 20 | 21 | # not in DCCALLOW - should be blocked: 22 | m.send(c3a, "PRIVMSG $c1a :\001DCC SEND some.exe 12345 1024 65535\001") 23 | m.not_expect(c1a, "DCC SEND should be blocked from this user", ".*PRIVMSG.*DCC SEND") 24 | m.clearlog() 25 | print 26 | 27 | # on DCCALLOW - should be allowed: 28 | m.send(c2a, "PRIVMSG $c1a :\001DCC SEND some.exe 12345 1024 65535\001") 29 | m.expect(c1a, "DCC SEND should be accepted from this user", ":$c2a.*PRIVMSG.*DCC SEND") 30 | m.clearlog() 31 | print 32 | 33 | m.send(c1a, "DCCALLOW -$c2a") 34 | m.clearlog() 35 | print 36 | 37 | # previously but no longer on DCCALLOW - should now be blocked: 38 | m.send(c2a, "PRIVMSG $c1a :\001DCC SEND some.exe 12345 1024 65535\001") 39 | m.not_expect(c1a, "DCC SEND should no longer be accepted from this user", ".*PRIVMSG.*DCC SEND") 40 | m.clearlog() 41 | print 42 | 43 | -------------------------------------------------------------------------------- /tests/_pre_test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # 3 | # NOTE: This test is special, do not use it as a template 4 | # if you are adding new tests. Pick some other test instead. 5 | # 6 | # This test is special in the sense that multisync is not 7 | # available since not all servers are linked yet, so we 8 | # only connect 1 instance at a time and recreate the IrcTest() 9 | # m object. This is not regular procedure. 10 | # 11 | 12 | import irctestframework.irctest 13 | import time 14 | 15 | m = irctestframework.irctest.IrcTest() 16 | c1a = m.new('c1a') 17 | m.connect() 18 | m.send(c1a, "VERSION") 19 | m.expect(c1a, "FAKEREPUTATION module is correctly loaded", ":.+ 005 .*FAKEREPUTATION"); 20 | m.send(c1a, "OPER netadmin test") 21 | m.send(c1a, "CONNECT irc2.test.net") 22 | m.expect(c1a, "irc1<->irc2 should be linked", "Link irc1.test.net -> irc2.test.net is now synced", timeout=15) 23 | 24 | m = irctestframework.irctest.IrcTest() 25 | c3a = m.new('c3a') 26 | m.connect() 27 | m.send(c3a, "VERSION") 28 | m.expect(c3a, "FAKEREPUTATION module is correctly loaded", ":.+ 005 .*FAKEREPUTATION"); 29 | m.send(c3a, "OPER netadmin test") 30 | m.send(c3a, "CONNECT irc2.test.net") 31 | m.expect(c3a, "irc3<->irc2 should be linked", "Link irc3.test.net -> irc2.test.net is now synced", timeout=15) 32 | 33 | c2a = m.new('c2a') 34 | m.connect() 35 | m.send(c2a, "VERSION") 36 | m.expect(c2a, "FAKEREPUTATION module is correctly loaded", ":.+ 005 .*FAKEREPUTATION"); 37 | -------------------------------------------------------------------------------- /tests/services/sasl_pre-registration_client1: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | import base64 4 | 5 | m = irctestframework.irctest.IrcTest() 6 | c1a = m.new('c1a') 7 | c1a.disable_registration = 1 8 | m.sync = 0 9 | m.connect() 10 | 11 | m.send(c1a, "CAP LS 302") 12 | m.send(c1a, "USER username x x :Test framework") 13 | m.send(c1a, "NICK client1") 14 | m.send(c1a, "CAP REQ :message-tags account-tag") 15 | m.send(c1a, "CAP REQ :sasl") 16 | m.expect(c1a, "SASL CAP available and enabled", ":.+ CAP .* ACK :sasl", timeout = 10) 17 | m.clearlog() 18 | print 19 | 20 | m.send(c1a, "AUTHENTICATE PLAIN") 21 | m.expect(c1a, "AUTHENTICATE plain go ahead", "AUTHENTICATE \+", timeout = 10) 22 | m.clearlog() 23 | print 24 | 25 | # Now, authenticate 26 | auth_string = base64.b64encode(b'client1\000client1\000test').decode() 27 | m.send(c1a, "AUTHENTICATE " + auth_string) 28 | m.expect(c1a, "SASL authentication successful", ":.+ 903 .* :SASL authentication successful", timeout = 10) 29 | m.clearlog() 30 | print 31 | 32 | m.send(c1a, "CAP END") 33 | m.expect(c1a, "Numeric 001 RPL_WELCOME", ":irc.* 001 client1 .*", timeout=10) 34 | m.expect(c1a, "Client should receive modes", ":client1 MODE client1 .*", timeout=10) 35 | m.expect(c1a, "NickServ sets +r", ":NickServ MODE client1 :\+r", timeout=5) 36 | m.not_expect(c1a, "", "This nickname is registered") 37 | m.clearlog() 38 | 39 | m.sync = 1 40 | m.send(c1a, "WHOIS client1") 41 | m.expect(c1a, "Show account in WHOIS", ":.+ 330 client1 client1 client1 :is logged in as") 42 | m.clearlog() 43 | print 44 | -------------------------------------------------------------------------------- /tests/services/sasl_pre-registration_client2: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | import base64 4 | 5 | m = irctestframework.irctest.IrcTest() 6 | c2a = m.new('c2a') 7 | c2a.disable_registration = 1 8 | m.sync = 0 9 | m.connect() 10 | 11 | m.send(c2a, "CAP LS 302") 12 | m.send(c2a, "USER username x x :Test framework") 13 | m.send(c2a, "NICK client2") 14 | m.send(c2a, "CAP REQ :message-tags account-tag") 15 | m.send(c2a, "CAP REQ :sasl") 16 | m.expect(c2a, "SASL CAP available and enabled", ":.+ CAP .* ACK :sasl", timeout = 10) 17 | m.clearlog() 18 | print 19 | 20 | m.send(c2a, "AUTHENTICATE PLAIN") 21 | m.expect(c2a, "AUTHENTICATE plain go ahead", "AUTHENTICATE \+", timeout = 10) 22 | m.clearlog() 23 | print 24 | 25 | # Now, authenticate 26 | auth_string = base64.b64encode(b'client2\000client2\000test').decode() 27 | m.send(c2a, "AUTHENTICATE " + auth_string) 28 | m.expect(c2a, "SASL authentication successful", ":.+ 903 .* :SASL authentication successful", timeout = 10) 29 | m.clearlog() 30 | print 31 | 32 | m.send(c2a, "CAP END") 33 | m.expect(c2a, "Numeric 001 RPL_WELCOME", ":irc.* 001 client2 .*", timeout=10) 34 | m.expect(c2a, "Client should receive modes", ":client2 MODE client2 .*", timeout=10) 35 | m.expect(c2a, "NickServ sets +r", ":NickServ MODE client2 :\+r", timeout=5) 36 | m.not_expect(c2a, "", "This nickname is registered") 37 | m.clearlog() 38 | 39 | m.sync = 1 40 | m.send(c2a, "WHOIS client2") 41 | m.expect(c2a, "Show account in WHOIS", ":.+ 330 client2 client2 client2 :is logged in as") 42 | m.clearlog() 43 | print 44 | -------------------------------------------------------------------------------- /tests/opercommands/sajoin: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c1a, skip = c3a) 12 | m.expect(c1a, "see others joining", ":c2a.*JOIN") 13 | m.clearlog() 14 | print 15 | 16 | m.send(c1a, "SAJOIN $c3a " + chan) 17 | m.expect(c1a, "Command not permitted as non-ircop", ":.+ 481 $me :Permission Denied") 18 | m.clearlog() 19 | print 20 | 21 | m.send(c1a, "OPER netadmin test") 22 | m.send(c1a, "SAJOIN $c3a " + chan) 23 | m.expect_all("See c3a joining", ":c3a.*JOIN", timeout = 5) 24 | m.expect(c3a, "See that you are forced joined", ":irc.+ NOTICE $me :\*\*\* You were forced to join " + chan) 25 | m.clearlog() 26 | print 27 | 28 | # Need to disable the auto-syncer here due to 1 client parting all channels, 29 | # including the auto syncer channel. 30 | m.sync = 0 31 | 32 | m.send(c1a, "SAJOIN $c3a 0") 33 | m.expect_all("See c3a leaving", ":c3a.*PART", timeout = 5) 34 | m.expect(c3a, "See that you are forced to part all channels", ":irc.+ NOTICE $me :\*\*\* You were forced to join 0", timeout = 5) 35 | m.clearlog() 36 | print 37 | 38 | m.send(c1a, "SAJOIN $c3a @" + chan) 39 | m.expect_all("See c3a joining", ":c3a.*JOIN", timeout = 5) 40 | m.expect_all("See c3a receiving ops", ":.*MODE " + chan + " \+o $c3a", timeout = 5) 41 | m.expect(c3a, "See that you are forced joined", ":irc.+ NOTICE $me :\*\*\* You were forced to join " + chan) 42 | m.clearlog() 43 | print 44 | -------------------------------------------------------------------------------- /tests/usercommands/watch: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | m.send(c1a, "WATCH +$c3a") 11 | m.expect(c1a, "604 numeric for user that is online", ":.+ 604 $me $c3a username Clk.* [0-9]+ :is online") 12 | m.clearlog() 13 | print 14 | 15 | m.send(c1a, "WATCH +somenick-w") 16 | m.expect(c1a, "605 numeric for user that is offline", ":.+ 605 $me somenick-w \* \* 0 :is offline") 17 | m.clearlog() 18 | print 19 | 20 | m.send(c1a, "WATCH L") 21 | m.expect(c1a, "604 numeric for user that is online", ":.+ 604 $me $c3a username Clk.* [0-9]+ :is online") 22 | m.expect(c1a, "605 numeric for user that is offline", ":.+ 605 $me somenick-w \* \* [0-9]+ :is offline") 23 | m.clearlog() 24 | print 25 | 26 | # Need to disable the auto-syncer here due to the nick change 27 | m.sync = 0 28 | 29 | # Test nick change 30 | c3a_original_nick = c3a.nick 31 | m.send(c3a, "NICK somenick-w") 32 | m.expect(c1a, "601 numeric for user that went offline (nick change)", ":.+ 601 $me " + c3a_original_nick + " username Clk-.* [0-9]+ :logged offline", timeout = 10) 33 | m.expect(c1a, "600 numeric for user that got online (nick change)", ":.+ 600 $me somenick-w username Clk-.* [0-9]+ :logged online", timeout = 10) 34 | m.clearlog() 35 | print 36 | 37 | # Test quit 38 | m.send(c3a, "QUIT :poof!") 39 | m.expect(c1a, "601 numeric for user that went offline (quit)", ":.+ 601 $me somenick-w username Clk-.* [0-9]+ :logged offline", timeout = 10) 40 | m.clearlog() 41 | print 42 | -------------------------------------------------------------------------------- /tests/opercommands/oper: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | # The following is spread over the 3 clients: first c1a, then c2a, then c3a 11 | # this to speed up the tests since fake lag is applied heavily on failed attempts. 12 | 13 | m.send(c1a, "OPER") 14 | m.expect(c1a, "OPER without parameters should give error", ":.+ 461 $me OPER :Not enough parameters") 15 | m.clearlog() 16 | print 17 | 18 | m.send(c1a, "OPER wrongusername") 19 | m.expect(c1a, "OPER with invalid username should give error", ":.+ 491 $me :No O-lines for your host") 20 | m.clearlog() 21 | print 22 | 23 | m.send(c2a, "OPER wrongusername xyz") 24 | m.expect(c2a, "OPER with invalid username/password should give error", ":.+ 491 $me :No O-lines for your host") 25 | m.clearlog() 26 | print 27 | 28 | m.send(c2a, "OPER netadmin") 29 | m.expect(c2a, "OPER with only username should give error if password is required", ":.+ 464 $me :Password Incorrect") 30 | m.clearlog() 31 | print 32 | 33 | m.send(c3a, "OPER netadmin wrong") 34 | m.expect(c3a, "OPER with invalid password should give error", ":.+ 464 $me :Password Incorrect") 35 | m.clearlog() 36 | print 37 | 38 | m.send(c3a, "OPER netadmin test") 39 | m.expect(c3a, "OPER should give you +o user mode", ":$c3a MODE $c3a :\+o") 40 | m.expect(c3a, "OPER should give you snomasks", ":.+ 008 $me \+.* :Server notice mask") 41 | m.expect(c3a, "OPER up notification", ":.+ 381 $me :You are now an IRC Operator") 42 | m.clearlog() 43 | print 44 | -------------------------------------------------------------------------------- /tests/chanmodes/nocolor: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c2a) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | print 14 | 15 | m.send(c1a, "PRIVMSG " + chan + " :\0034this is red\003") 16 | m.not_expect(c1a, "should not block color in messages (no 404 numeric) with -c", " 404 .*Color is not permitted") 17 | m.expect(c3a, "should not block color in messages with -c", ":c1a.*PRIVMSG.*\0034this is red") 18 | m.clearlog() 19 | print 20 | 21 | m.send(c1a, "PRIVMSG " + chan + " :\0026this is reverse\003") 22 | m.not_expect(c1a, "should not block reverse in messages (no 404 numeric) with -c", " 404 .*Color is not permitted") 23 | m.expect(c3a, "should not block reverse in messages with -c", ":c1a.*PRIVMSG.*\0026this is reverse") 24 | m.clearlog() 25 | print 26 | 27 | m.send(c2a, "MODE " + chan + " +c") 28 | m.expect(c1a, "MODE +c", ":c2a.*MODE.*\+c") 29 | print 30 | 31 | m.send(c1a, "PRIVMSG " + chan + " :\0034this is red\003") 32 | m.expect(c1a, "should block color in messages (404 numeric) with +c", " 404 .*Color is not permitted") 33 | m.not_expect(c3a, "should block color in messages with +c", ":c1a.*PRIVMSG.*this is red") 34 | print 35 | 36 | m.send(c1a, "PRIVMSG " + chan + " :\026this is reverse\026") 37 | m.expect(c1a, "should block reverse in messages (404 numeric) with +c", " 404 .*Color is not permitted") 38 | m.not_expect(c3a, "should block reverse in messages with +c", ":c1a.*PRIVMSG.*:this is reverse") 39 | print 40 | -------------------------------------------------------------------------------- /tests/serial/time_extban_expiry: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | import time 4 | 5 | m = irctestframework.irctest.IrcTest() 6 | c1a = m.new('c1a') 7 | c2a = m.new('c2a') 8 | c3a = m.new('c3a') 9 | m.connect() 10 | 11 | chan = m.randchan() 12 | m.join_all(chan, creator = c2a) 13 | 14 | # - extban 15 | m.send(c2a, "MODE " + chan + " +b ~time:1:~text:block:*bantimetest*") 16 | m.send(c2a, "MODE " + chan + " +b ~time:5:~text:block:*secondary*") 17 | m.expect_all("MODE +b set", ".*MODE.*\+b.*") 18 | m.clearlog() 19 | print 20 | 21 | m.send(c1a, "PRIVMSG " + chan + " :aa bantimetest bb") 22 | m.not_expect(c3a, "text should not be seen with extban in place", ":c1a.*PRIVMSG.*") 23 | m.expect(c1a, "expect block message", ":.+ 404 .*") 24 | m.clearlog() 25 | print 26 | 27 | time.sleep(30) 28 | 29 | m.not_expect_all("extban should NOT be removed after 30 seconds already (too soon)", ".*MODE.*-b.*") 30 | m.clearlog() 31 | print 32 | 33 | # Give it another 60 seconds now. Since we already passed 30 seconds, 34 | # ideally this would hit after 30 seconds, but give it another 30 seconds extra just in case (90s total). 35 | m.expect_all("Ban automatically unset after 1 minute expiry time", ".*MODE.*-b ~time:1:~text:block:\*bantimetest\*.*", timeout=60) 36 | time.sleep(5) 37 | m.not_expect_all("Second longer extban should not expire yet", ".*MODE.*-b ~time:5.*") 38 | m.clearlog() 39 | print 40 | 41 | # Should no longer be blocking 42 | m.send(c1a, "PRIVMSG " + chan + " :aa bantimetest bb") 43 | m.expect(c3a, "text should be seen after extban removal", ":c1a.*PRIVMSG.*") 44 | m.not_expect(c1a, "don't expect block message", ":.+ 404 .*") 45 | m.clearlog() 46 | print 47 | -------------------------------------------------------------------------------- /tests/extbans/forward: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.send(c1a, "JOIN " + chan) 12 | m.send(c1a, "MODE " + chan + " +b ~forward:#redirect:c3a*!*@*") 13 | m.expect(c1a, "user in channel", "JOIN") 14 | m.clearlog() 15 | print 16 | 17 | m.send(c2a, "JOIN " + chan) 18 | m.send(c3a, "JOIN " + chan) 19 | m.expect(c1a, "Unbanned client should be able to JOIN", ":c2a.* JOIN") 20 | m.not_expect(c1a, "Banned client should be unable to JOIN", ":c3a.* JOIN") 21 | m.expect(c3a, "Server informing about redirect", ":irc.* 470 $me " + chan + " #redirect :\[Link\] Cannot join channel " + chan + " \(you are banned\) -- transferring you to \#redirect") 22 | m.expect(c3a, "Join the redirected channel", ":$me.* JOIN :\#redirect") 23 | m.clearlog() 24 | print 25 | 26 | m.send(c2a, "PART " + chan) 27 | m.send(c3a, "PART #redirect") 28 | m.send(c1a, "MODE " + chan + " -b ~forward:#redirect:c3a*!*@*") 29 | m.send(c1a, "MODE " + chan + " +b ~time:100:~forward:#redirect:c3a*!*@*") 30 | m.expect(c1a, "Unban", "MODE.*-b ~forward:#redirect:c3a*!*@*") 31 | m.expect(c1a, "Ban", "MODE.*\+b ~time:100:~forward:#redirect:c3a*!*@*") 32 | m.clearlog() 33 | print 34 | 35 | m.send(c2a, "JOIN " + chan) 36 | m.send(c3a, "JOIN " + chan) 37 | m.expect(c1a, "Unbanned client should be able to JOIN", ":c2a.* JOIN") 38 | m.not_expect(c1a, "Banned client should be unable to JOIN", ":c3a.* JOIN") 39 | m.expect(c3a, "Server informing about redirect", ":irc.* 470 $me " + chan + " #redirect :\[Link\] Cannot join channel " + chan + " \(you are banned\) -- transferring you to \#redirect") 40 | m.expect(c3a, "Join the redirected channel", ":$me.* JOIN :\#redirect") 41 | m.clearlog() 42 | print 43 | -------------------------------------------------------------------------------- /tests/usercommands/tagmsg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | # Need to disable this so we can test this case: 11 | m.disable_message_tags_check = 1 12 | c2a.disable_message_tags_check = 1 13 | m.send(c2a, "CAP REQ :-message-tags") 14 | m.clearlog() 15 | print 16 | 17 | chan = m.randchan() 18 | m.join_all(chan, creator = c1a) 19 | m.expect_all("all in channel", "NAMES") 20 | m.clearlog() 21 | print 22 | 23 | # A correct TAGMSG to a channel 24 | m.send(c1a, "@+draft/typing=active TAGMSG " + chan) 25 | m.not_expect(c2a, "Not receive TAGMSG if no message-tags CAP", ":$c1a.* TAGMSG " + chan) 26 | m.expect(c3a, "Recieve channel TAGMSG", ":$c1a.* TAGMSG " + chan) 27 | m.clearlog() 28 | print 29 | 30 | # An incorrect TAGMSG to a channel 31 | m.send(c1a, "@+draft/typing=invalidmsg TAGMSG " + chan) 32 | m.not_expect_all("Not receive TAGMSG if not containing valid client tag", ":$c1a.* TAGMSG " + chan, skip = c1a) 33 | m.clearlog() 34 | print 35 | 36 | # An empty TAGMSG to a channel 37 | m.send(c1a, "TAGMSG " + chan) 38 | m.not_expect_all("Not receive TAGMSG if not containing any client tags", ":$c1a.* TAGMSG " + chan, skip = c1a) 39 | m.clearlog() 40 | print 41 | 42 | # A correct TAGMSG to a user 43 | m.send(c1a, "@+draft/typing=active TAGMSG $c3a") 44 | m.expect(c3a, "Recieve user TAGMSG", ":$c1a.* TAGMSG $c3a") 45 | m.clearlog() 46 | print 47 | 48 | # An incorrect TAGMSG to a channel 49 | m.send(c1a, "@+draft/typing=invalidmsg TAGMSG $c3a") 50 | m.not_expect(c3a, "Not receive TAGMSG if not containing valid client tag", ":$c1a.* TAGMSG $c3a") 51 | m.clearlog() 52 | print 53 | 54 | # An empty TAGMSG to a user 55 | m.send(c1a, "TAGMSG $c3a") 56 | m.not_expect(c3a, "Not receive TAGMSG if not containing any client tags", ":$c1a.* TAGMSG " + chan) 57 | m.clearlog() 58 | print 59 | 60 | -------------------------------------------------------------------------------- /tests/db/reading/tkl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # 3 | # This tests TKLs such as: KLINE, ZLINE, GLINE, GZLINE, SPAMFILTER 4 | # 5 | import irctestframework.irctest 6 | 7 | m = irctestframework.irctest.IrcTest() 8 | c1a = m.new('c1a') 9 | c2a = m.new('c2a') 10 | c3a = m.new('c3a') 11 | m.connect() 12 | 13 | m.send_all("OPER netadmin test") 14 | 15 | ##### LOCAL TKLS ###### 16 | 17 | ### KLINE on host 18 | m.send_all("STATS kline") 19 | regex = "223.*K user@some\.host666 3[0-9][0-9][0-9] [0-9]+ c1a.* :This is a kline test" 20 | m.expect(c1a, "K-Line shown in /STATS kline locally", regex) 21 | m.not_expect_all("K-Line NOT shown in /STATS kline on remote servers", regex, skip=c1a) 22 | m.clearlog() 23 | print 24 | 25 | ### ZLINE on host 26 | m.send_all("STATS kline") 27 | regex = "223.*z \*@192\.0\.2\.2 3[0-9][0-9][0-9] [0-9]+ c1a.* :This is a zline test" 28 | m.expect(c1a, "Z-Line shown in /STATS zline locally", regex) 29 | m.not_expect_all("Z-Line NOT shown in /STATS zline on remote servers", regex, skip=c1a) 30 | m.clearlog() 31 | print 32 | 33 | ##### GLOBAL TKLS ###### 34 | 35 | ### GLINE on host 36 | m.send_all("STATS gline") 37 | m.expect_all("G-Line shown in /STATS gline", 38 | "223.*G user@some\.host777 3[0-9][0-9][0-9] [0-9]+ c1a.* :This is a gline test") 39 | m.clearlog() 40 | print 41 | 42 | ### GLINE on ip 43 | m.send_all("STATS gline") 44 | m.expect_all("G-Line shown in /STATS gline", 45 | "223.*G user@192\.0\.2\.3 3[0-9][0-9][0-9] [0-9]+ c1a.* :This is a gline test on IP") 46 | m.clearlog() 47 | print 48 | 49 | ### GZLINE on ip 50 | m.send_all("STATS gline") 51 | m.expect_all("GZ-Line shown in /STATS gline", 52 | "223.*Z \*@192\.0\.2\.4 3[0-9][0-9][0-9] [0-9]+ c1a.* :This is a gzline test on IP") 53 | m.clearlog() 54 | print 55 | 56 | ### Spamfilter 57 | m.send_all("STATS spamfilter") 58 | m.expect_all("Spamfilter shown in /STATS spamfilter", 59 | "229.* F simple p gzline 0 [0-9]* 0 this_is_a_test c1a[^ ]+ [0-9]+ [0-9]+ :Please gzline me immediately") 60 | m.clearlog() 61 | print 62 | 63 | -------------------------------------------------------------------------------- /tests/usercommands/who: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | print 14 | 15 | m.send(c1a, "WHO " + chan) 16 | m.expect(c1a, "simple WHO #channel output (1 of 3)", "352 $c1a " + chan + " username Clk-8608861 irc1\.test\.net $c1a H.*:0 Test framework") 17 | m.expect(c1a, "simple WHO #channel output (2 of 3)", "352 $c1a " + chan + " username Clk-8608861 irc2\.test\.net $c2a H.*:[0-9] Test framework") 18 | m.expect(c1a, "simple WHO #channel output (3 of 3)", "352 $c1a " + chan + " username Clk-8608861 irc3\.test\.net $c3a H.*:[0-9] Test framework") 19 | m.clearlog() 20 | print 21 | 22 | m.send(c1a, "WHO " + chan + " %tcuihsnfmdlaor") 23 | m.expect(c1a, "complex WHO #channel output (WHOX) (1 of 3)", "354 $c1a 0 " + chan + " username 127.0.0.1 Clk-8608861 irc1\.test\.net $c1a H.* \* 0 [0-9]+ 0 (999|n\/a) :Test framework") 24 | m.expect(c1a, "complex WHO #channel output (WHOX) (2 of 3)", "354 $c1a 0 " + chan + " username 255.255.255.255 Clk-8608861 irc2\.test\.net $c2a H.* \* 0 [0-9]+ 0 (999|n\/a) :Test framework") 25 | m.expect(c1a, "complex WHO #channel output (WHOX) (3 of 3)", "354 $c1a 0 " + chan + " username 255.255.255.255 Clk-8608861 irc3\.test\.net $c3a H.* \* 0 [0-9]+ 0 (999|n\/a) :Test framework") 26 | m.clearlog() 27 | print 28 | 29 | m.send(c1a, "OPER netadmin test") 30 | m.send(c1a, "WHO " + chan + " %tcuiHsnfmdlaor") 31 | m.expect(c1a, "complex WHOX output for opers (1 of 3)", "354 $c1a 0 " + chan + " username 127.0.0.1 localhost irc1\.test\.net $c1a H.* iostwx 0 [0-9]+ 0 (999|n\/a) :Test framework") 32 | m.expect(c1a, "complex WHOX output for opers (2 of 3)", "354 $c1a 0 " + chan + " username 127.0.0.1 localhost irc2\.test\.net $c2a H.* iwx 0 [0-9]+ 0 (999|n\/a) :Test framework") 33 | m.expect(c1a, "complex WHOX output for opers (3 of 3)", "354 $c1a 0 " + chan + " username 127.0.0.1 localhost irc3\.test\.net $c3a H.* iwx 0 [0-9]+ 0 (999|n\/a) :Test framework") 34 | -------------------------------------------------------------------------------- /tests/usercommands/invite: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | # Yeah there's some overlap between this and the chanmode +i test. 11 | # This one actually tests the INVITE command, in different ways too. 12 | 13 | chan = m.randchan() 14 | m.join_all(chan, creator = c1a, skip = c3a) 15 | m.expect(c1a, "first user in channel", ":c1a.*JOIN") 16 | m.expect(c2a, "second user in channel", ":c2a.*JOIN") 17 | print 18 | 19 | m.send(c2a, "INVITE $c3a " + chan) 20 | m.expect(c2a, "Should receive 341 numeric about succesful invite (non-op-invite)", " 341 $c2a $c3a " + chan) 21 | m.expect(c3a, "Recipient should see the INVITE (non-op-invite)", ":$c2a.* INVITE $c3a :" + chan) 22 | m.clearlog() 23 | print 24 | 25 | m.send(c1a, "MODE " + chan + " +i") 26 | m.expect(c2a, "MODE +i", ":c1a.*MODE.*\+i") 27 | print 28 | 29 | m.send(c3a, "JOIN " + chan) 30 | m.expect(c3a, "unable to join with +i (numeric 473)", "473.*Cannot join channel.*\+i") 31 | m.not_expect(c1a, "should not see JOIN for user if +i", ":c3a.*JOIN") 32 | print 33 | m.clearlog() 34 | 35 | m.send(c1a, "INVITE $c3a " + chan) 36 | m.expect(c1a, "Should receive 341 numeric about succesful invite", " 341 $c1a $c3a " + chan) 37 | m.expect(c3a, "Recipient should see the INVITE", ":$c1a.* INVITE $c3a :" + chan) 38 | m.clearlog() 39 | print 40 | 41 | m.send(c3a, "JOIN " + chan) 42 | m.not_expect(c3a, "no numeric 473", "473.*Cannot join channel.*\+i") 43 | m.expect_all("should see JOIN for /INVITE'd user", ":c3a.*JOIN") 44 | print 45 | m.clearlog() 46 | 47 | m.send(c2a, "PART " + chan) 48 | m.send(c1a, "CAP REQ :invite-notify") 49 | m.send(c1a, "MODE " + chan + " +o $c3a") 50 | m.expect(c3a, "MODE +o", ":$c1a.* MODE .* \+o $c3a") 51 | m.send(c3a, "INVITE $c2a " + chan) 52 | m.expect(c1a, "should see INVITE notification", ":$c3a.* INVITE $c2a " + chan) 53 | m.not_expect(c3a, "should not see INVITE notification", ":$c3a.* INVITE $c2a " + chan) 54 | m.expect(c3a, "should see NOTICE notification", ":.* NOTICE @" + chan + " :.*$c3a.*$c2a") 55 | print 56 | m.clearlog() 57 | 58 | -------------------------------------------------------------------------------- /tests/usercommands/whois: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | print 14 | 15 | ### FIRST A NORMAL WHOIS ### 16 | m.send_all("WHOIS $c1a") 17 | # 311 for all: 18 | m.expect_all("numeric 311", ":.* 311 $me $c1a username Clk.* \* :Test framework") 19 | # 379 only for self: 20 | m.expect(c1a, "numeric 379 (local)", ":.* 379 $me $c1a :is using modes \+iwx") 21 | # 378 only for self: 22 | m.expect(c1a, "numeric 378 (local)", ":.* 378 $me $c1a :is connecting from \*@localhost 127\.0\.0\.1") 23 | # 319 for all: 24 | m.expect_all("numeric 319", ":.* 319 $me $c1a :.*" + chan + ".*") 25 | m.expect_all("numeric 312", ":.* 312 $me $c1a irc1\.test\.net :Primary test server") 26 | # 317 only for local: 27 | m.expect(c1a, "numeric 317 (local)", ":.* 317 $me $c1a [0-9]+ [0-9]+ :seconds idle, signon time") 28 | # 318 for all: 29 | m.expect_all("numeric 318", ":.* 318 $me $c1a :End of /WHOIS list") 30 | m.clearlog() 31 | print 32 | 33 | ### NOW A REMOTE WHOIS ### 34 | # This requires special handling of expect_all with timeout. 35 | # Normally we don't need this, these type of commands are very rare 36 | # and take 2*latency rather than 1*latency. 37 | m.send_all("WHOIS $c1a $c1a") 38 | # 311 for all: 39 | m.expect_all("numeric 311", ":.* 311 $me $c1a username Clk.* \* :Test framework", timeout=10) 40 | # 379 only for self: 41 | m.expect(c1a, "numeric 379 (local)", ":.* 379 $me $c1a :is using modes \+iwx") 42 | # 378 only for self: 43 | m.expect(c1a, "numeric 378 (local)", ":.* 378 $me $c1a :is connecting from \*@localhost 127\.0\.0\.1") 44 | # 319 for all: 45 | m.expect_all("numeric 319", ":.* 319 $me $c1a :.*" + chan + ".*", timeout=10) 46 | m.expect_all("numeric 312", ":.* 312 $me $c1a irc1\.test\.net :Primary test server", timeout=10) 47 | # 317 for all: 48 | m.expect_all("numeric 317", ":.* 317 $me $c1a [0-9]+ [0-9]+ :seconds idle, signon time", timeout=10) 49 | # 318 for all: 50 | m.expect_all("numeric 318", ":.* 318 $me $c1a :End of /WHOIS list", timeout=10) 51 | m.clearlog() 52 | print 53 | -------------------------------------------------------------------------------- /tests/serial/netsplit_simple: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | clones_per_server = 75 5 | servers = { 'c1', 'c2', 'c3' } 6 | clones = {} 7 | 8 | m = irctestframework.irctest.IrcTest() 9 | 10 | c1o = m.new('c1o') 11 | c3o = m.new('c3o') 12 | 13 | for s in servers: 14 | for i in range(1, clones_per_server+1): 15 | name = s + '-' + str(i) 16 | clones[name] = m.new(name) 17 | 18 | m.connect() 19 | m.send(c1o, "OPER netadmin test") 20 | m.send(c3o, "OPER netadmin test") 21 | m.clearlog() 22 | 23 | chan = m.randchan() 24 | m.send(c1o, "JOIN " + chan) 25 | m.send(c1o, "MODE " + chan + " +F off") 26 | m.join_all(chan, skip = c1o) 27 | m.expect_all("see join", ":$me.*JOIN.*") 28 | m.clearlog() 29 | print 30 | 31 | # Put channel -F so we can check that join-flood protection 32 | # isn't triggered by netmerge later 33 | m.send(c1o, "MODE " + chan + " -F") 34 | m.clearlog() 35 | 36 | m.send_all("NAMES " + chan) 37 | for src in clones: 38 | for dst in clones: 39 | m.expect(clones[src], "see all other clones in channel: " + clones[dst].nick + " is not seen by " + clones[src].nick, clones[dst].nick) 40 | m.clearlog() 41 | print 42 | 43 | # SQUIT servers 44 | m.sync = 0 45 | m.disable_message_tags_check = True 46 | for s in [c1o, c3o]: 47 | m.send(s, "SQUIT irc2.test.net") 48 | m.send(s, "MAP") 49 | m.expect(s, "End of /MAP", "007.*End of", timeout = 10) 50 | m.not_expect(s, "Server gone, should not show up in MAP", " 006 .*irc2\.test\.net") 51 | m.clearlog() 52 | 53 | # TODO: verify that all users on other servers disappeared (a proper QUIT was sent) 54 | 55 | # CONNECT servers 56 | for s in [c1o, c3o]: 57 | m.send(s, "CONNECT irc2.test.net") 58 | m.expect(c1o, "ircX<->irc2 should be linked", "Link irc[0-9].test.net -> irc2.test.net is now synced", timeout=15) 59 | m.send(s, "MAP") 60 | m.expect(s, "End of /MAP", "007.*End of", timeout = 10) 61 | m.expect(s, "Server connected, should show up in MAP", " 006 .*irc2\.test\.net") 62 | m.clearlog() 63 | 64 | # Restore syncing 65 | m.sync = 1 66 | m.disable_message_tags_check = False 67 | 68 | m.send_all("NAMES " + chan) 69 | for src in clones: 70 | for dst in clones: 71 | m.expect(clones[src], "see all other clones in channel: " + clones[dst].nick + " is not seen by " + clones[src].nick, clones[dst].nick) 72 | m.clearlog() 73 | print 74 | 75 | -------------------------------------------------------------------------------- /tests/extbans/text: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator = c2a) 12 | m.send(c2a, "MODE " + chan + " +b ~text:censor:*fuck*") 13 | m.expect(c1a, "users in channel", "JOIN") 14 | print 15 | 16 | m.send(c1a, "PRIVMSG " + chan + " :aa fucked bb") 17 | m.expect(c3a, "should censor badwords with text extban", ":c1a.*PRIVMSG.*aa bb") 18 | m.clearlog() 19 | print 20 | 21 | m.send(c1a, "PRIVMSG " + chan + " :aa sunshine bb") 22 | m.expect(c3a, "should not censor non-badwords with text extban", ":c1a.*PRIVMSG.*aa sunshine bb") 23 | m.clearlog() 24 | print 25 | 26 | m.send(c2a, "MODE " + chan + " -b ~text:censor:*fuck*") 27 | m.clearlog() 28 | print 29 | 30 | m.send(c1a, "PRIVMSG " + chan + " :aa fucked bb") 31 | m.expect(c3a, "should not censor badwords without text extban", ":c1a.*PRIVMSG.*aa fucked bb") 32 | m.clearlog() 33 | print 34 | 35 | m.send(c1a, "PRIVMSG " + chan + " :aa sunshine bb") 36 | m.expect(c3a, "should not censor non-badwords without text extban", ":c1a.*PRIVMSG.*aa sunshine bb") 37 | m.clearlog() 38 | print 39 | 40 | m.send(c2a, "MODE " + chan + " +b ~text:block:*fuck*") 41 | m.clearlog() 42 | print 43 | 44 | m.send(c1a, "PRIVMSG " + chan + " :aa fucked bb") 45 | m.not_expect(c3a, "text should not be seen with extban in place", ":c1a.*PRIVMSG.*") 46 | m.expect(c1a, "expect block message", ":.+ 404 .*") 47 | m.clearlog() 48 | print 49 | 50 | m.send(c1a, "PRIVMSG " + chan + " :aa sunshine bb") 51 | m.expect(c3a, "should not censor non-badwords with text extban", ":c1a.*PRIVMSG.*aa sunshine bb") 52 | m.not_expect(c1a, "expect block message", ":.+ 404 .*") 53 | m.clearlog() 54 | print 55 | 56 | m.send(c2a, "MODE " + chan + " -b ~text:block:*fuck*") 57 | m.expect_all("unban", ".*MODE.*-b.*") 58 | m.send(c2a, "MODE " + chan + " +b ~time:1:~text:block:*fuck*") 59 | m.clearlog() 60 | print 61 | 62 | m.send(c1a, "PRIVMSG " + chan + " :aa fucked bb") 63 | m.not_expect(c3a, "text should not be seen with extban in place", ":c1a.*PRIVMSG.*") 64 | m.expect(c1a, "expect block message", ":.+ 404 .*") 65 | m.clearlog() 66 | print 67 | 68 | m.send(c1a, "PRIVMSG " + chan + " :aa sunshine bb") 69 | m.expect(c3a, "should not censor non-badwords with text extban", ":c1a.*PRIVMSG.*aa sunshine bb") 70 | m.not_expect(c1a, "expect block message", ":.+ 404 .*") 71 | m.clearlog() 72 | print 73 | 74 | -------------------------------------------------------------------------------- /serverconfig/unrealircd/modules/fakereputation.c: -------------------------------------------------------------------------------- 1 | /* Fake reputation 2 | * DO NOT USE THIS ON A LIVE SERVER. IT IS FOR THE TESTING SUITE *ONLY*. 3 | * If you use it on a server accessible by other users then they can 4 | * set any reputation value they choose which has a major negative 5 | * impact on security. Also, this module only works well the first few 6 | * minutes after booting, along with some other caveats. AGAIN, 7 | * IT IS ONLY FOR THE TEST SUITE!! 8 | * 9 | * (C) Copyright 2020 Bram Matthys and The UnrealIRCd Team 10 | * License: GPLv2 11 | */ 12 | 13 | #include "unrealircd.h" 14 | 15 | CMD_FUNC(cmd_fakereputation); 16 | 17 | ModuleHeader MOD_HEADER 18 | = { 19 | "third/fakereputation", 20 | "5.0", 21 | "/FAKEREPUTATION command for testing", 22 | "UnrealIRCd Team", 23 | #if UNREAL_VERSION < 0x05000000 24 | "unrealircd-5", 25 | #else 26 | "unrealircd-6", 27 | #endif 28 | }; 29 | 30 | MOD_INIT() 31 | { 32 | CommandAdd(modinfo->handle, "FAKEREPUTATION", cmd_fakereputation, MAXPARA, CMD_USER); 33 | ISupportAdd(modinfo->handle, "FAKEREPUTATION", NULL); 34 | MARK_AS_OFFICIAL_MODULE(modinfo); 35 | return MOD_SUCCESS; 36 | } 37 | 38 | MOD_LOAD() 39 | { 40 | return MOD_SUCCESS; 41 | } 42 | 43 | MOD_UNLOAD() 44 | { 45 | return MOD_SUCCESS; 46 | } 47 | 48 | CMD_FUNC(cmd_fakereputation) 49 | { 50 | int v; 51 | char buf[64]; 52 | 53 | if ((parc < 2) || BadPtr(parv[1]) || (atoi(parv[1]) < 1)) 54 | { 55 | sendnotice(client, "Syntax 1 is: /FAKEREPUTATION "); 56 | sendnotice(client, " Example 1: /FAKEREPUTATION 5"); 57 | sendnotice(client, "Syntax 2 is: /FAKEREPUTATION "); 58 | sendnotice(client, " Example 2: /FAKEREPUTATION 127.0.0.1 5"); 59 | return; 60 | } 61 | 62 | if ((strchr(parv[1], '.') || strchr(parv[1], ':')) && !BadPtr(parv[2])) 63 | { 64 | /* FAKEREPUTATION */ 65 | const char *parx[4]; 66 | parx[0] = NULL; 67 | parx[1] = parv[1]; 68 | parx[2] = parv[2]; 69 | parx[3] = NULL; 70 | sendnotice(client, "Reputation for '%s' set to '%s'", parv[1], parv[2]); 71 | do_cmd(&me, NULL, "REPUTATION", 3, parx); 72 | return; 73 | } 74 | 75 | v = atoi(parv[1]); 76 | if (v > 10000) 77 | { 78 | sendnotice(client, "ERROR: Requested reputation value out of range, max is 10000"); 79 | return; 80 | } 81 | /* And make it a number again. Yes we do it this way so nobody sets '1ab' or something */ 82 | snprintf(buf, sizeof(buf), "%d", v); 83 | moddata_client_set(client, "reputation", buf); 84 | broadcast_md_client_cmd(NULL, &me, client, "reputation", buf); 85 | sendnotice(client, "Reputation set to %s", buf); 86 | } 87 | -------------------------------------------------------------------------------- /tests/services/account_extban: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | # Because services are only tested on Windows, 5 | # the account extban needed to be placed here. 6 | 7 | m = irctestframework.irctest.IrcTest() 8 | c1a = m.new('c1a') 9 | c2a = m.new('c2a') 10 | c3a = m.new('c3a') 11 | m.connect() 12 | 13 | chan = m.randchan() 14 | m.join_all(chan, skip = c3a, creator=c1a) 15 | m.expect(c1a, "users in channel", "JOIN") 16 | m.clearlog() 17 | print 18 | 19 | m.send(c1a, "MODE " + chan + " +iI ~a:*") 20 | m.expect(c1a, "expect ban to be set", ":.+ MODE " + chan + " \+iI") 21 | m.clearlog() 22 | print 23 | 24 | m.send(c3a, "JOIN " + chan) 25 | m.expect(c3a, "Client should receive error on JOIN attempt", ":irc.+ 473 $c3a " + chan + " :Cannot join channel \(\+i\)") 26 | m.not_expect_all("Client should NOT be able to join with +b ~a:* when not logged in", ":c3a.* JOIN ") 27 | m.clearlog() 28 | print 29 | 30 | m.send(c1a, "MODE " + chan + " -I+I ~a:* ~a:client3") 31 | m.expect(c1a, "expect ban to be set", ":.+ MODE " + chan + " -I\+I") 32 | m.clearlog() 33 | print 34 | 35 | m.send(c3a, "JOIN " + chan) 36 | m.expect(c3a, "Client should receive error on JOIN attempt", ":irc.+ 473 $c3a " + chan + " :Cannot join channel \(\+i\)") 37 | m.not_expect_all("Client should NOT be able to join with +b ~a:client3 when not logged in", ":c3a.* JOIN ") 38 | m.clearlog() 39 | print 40 | 41 | m.send(c3a, "NS IDENTIFY client3 test") 42 | m.expect(c3a, "Identified to account", ":irc.* 900 ", timeout = 10) 43 | m.clearlog() 44 | print 45 | 46 | m.send(c3a, "JOIN " + chan) 47 | m.not_expect(c3a, "Client should NOT receive error on JOIN attempt", ":irc.+ 473") 48 | m.expect_all("Client should be able to join now that it is logged in", ":c3a.* JOIN ") 49 | m.clearlog() 50 | print 51 | 52 | m.send(c3a, "PART " + chan) 53 | m.send(c1a, "MODE " + chan + " -I+I ~a:client3 ~a:0") 54 | m.expect(c1a, "expect ban to be set", ":.+ MODE " + chan + " -I\+I") 55 | print 56 | 57 | m.send(c3a, "JOIN " + chan) 58 | m.expect(c3a, "Client should receive error on JOIN attempt", ":irc.+ 473 $c3a " + chan + " :Cannot join channel \(\+i\)") 59 | m.not_expect_all("Client should NOT be able to join with +b ~a:0 when logged in", ":c3a.* JOIN ") 60 | m.clearlog() 61 | print 62 | 63 | m.send(c3a, "NS LOGOUT") 64 | m.send(c3a, "PART " + chan) 65 | m.expect(c3a, "NS LOGOUT succesful", "been logged out", timeout=10) 66 | m.clearlog() 67 | print 68 | 69 | m.send(c3a, "JOIN " + chan) 70 | m.not_expect(c3a, "Client should NOT receive error on JOIN attempt", ":irc.+ 473") 71 | m.expect_all("Client should be able to join now when logged out and with +I ~a:0", ":c3a.* JOIN ") 72 | m.clearlog() 73 | print 74 | -------------------------------------------------------------------------------- /tests/extensions/labeled-response: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, skip = c1a) 12 | m.expect(c2a, "users in channel", "JOIN") 13 | print 14 | 15 | m.send(c1a, "CAP REQ :labeled-response batch server-time") 16 | m.expect(c1a, "CAP ACK for labeled-response and other capabilities", ":.* CAP c1a.* ACK :labeled-response batch server-time"); 17 | m.clearlog() 18 | print 19 | 20 | m.send(c1a, "@label=aaa NOTICE " + chan + " :hello") 21 | m.expect(c1a, "ACK message for zero response", "@label=aaa.* :.* ACK") 22 | m.not_expect(c1a, "No BATCH start or end for zero response", " BATCH ") 23 | m.clearlog() 24 | print 25 | 26 | m.send(c1a, "@label=bbb ISON $c1a") 27 | m.expect(c1a, "Single line response with label", "@label=bbb.*303.*c1a.* :c1a.*") 28 | m.not_expect(c1a, "No BATCH start or end for single response", " BATCH ") 29 | m.clearlog() 30 | print 31 | 32 | m.send(c1a, "@label=ccc JOIN " + chan) 33 | m.expect(c1a, "BATCH start for multiline response", "@label=ccc.*BATCH \+.*labeled-response") 34 | m.expect(c1a, "Multiple lines within the match", "@batch=") 35 | m.expect(c1a, "BATCH end", "BATCH -.*") 36 | m.clearlog() 37 | print 38 | 39 | m.send(c1a, "@label=whoisss WHOIS $c3a $c3a") 40 | m.expect(c1a, "Far WHOIS should result in batch start for multiline response", "@label=whoisss.*BATCH \+.*labeled-response", timeout = 10) 41 | m.expect(c1a, "Multiple lines within the match", "@batch=", timeout = 10) 42 | m.expect(c1a, "BATCH end", "BATCH -.*", timeout = 10) 43 | m.clearlog() 44 | print 45 | 46 | # This sends the JOIN again. Since we are already in the channel 47 | # the IRC server should not send any reply and not do any action. 48 | # We do expect an ACK back though, due to labeled-response... 49 | # 50 | # We need this additional test in addition to the 1st one because 51 | # PRIVMSG was slightly special, so best to test with JOIN too.. 52 | m.send(c1a, "@label=ddd JOIN " + chan) 53 | m.expect(c1a, "ACK message for zero response", "@label=ddd.* :.* ACK") 54 | m.not_expect(c1a, "No BATCH start or end for zero response", " BATCH ") 55 | m.clearlog() 56 | print 57 | 58 | # Finally, we should obey not to do labeled-response for the echo-message stuff. 59 | m.send(c1a, "CAP REQ :echo-message") 60 | m.send(c1a, "@label=eee NOTICE $c1a :hello") 61 | m.expect(c1a, "One PRIVMSG with the label", "@label=eee.* :.* NOTICE.* :hello") 62 | m.expect(c1a, "The other PRIVMSG without the label", ":.* NOTICE.* :hello") 63 | m.not_expect(c1a, "No BATCH start or end for single response", " BATCH ") 64 | m.clearlog() 65 | print 66 | -------------------------------------------------------------------------------- /tests/chanmodes/link: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan1 = m.randchan() 11 | chan2 = m.randchan() 12 | 13 | m.send(c1a, "JOIN " + chan1) 14 | m.expect(c1a, "first user in channel", ":c1a.*JOIN") 15 | print 16 | 17 | # Test with +l (limit) 18 | m.send(c1a, "MODE " + chan1 + " +l 2") 19 | m.expect(c1a, "MODE +l 2", ":c1a.*MODE.*\+l 2") 20 | m.send(c1a, "MODE " + chan1 + " +L " + chan2) 21 | m.expect(c1a, "MODE +L ...", ":c1a.*MODE.*\+L " + chan2) 22 | print 23 | m.send(c2a, "JOIN " + chan1) 24 | m.expect(c2a, "can join channel if +l is not reached", ":c2a.*JOIN.*" + chan1) 25 | print 26 | m.send(c3a, "JOIN " + chan1) 27 | m.expect(c3a, "Server informing about redirect", ":irc.* 470 $me " + chan1 + " " + chan2 + " :\[Link\] Cannot join channel " + chan1 + " \(channel has become full\) -- transferring you to " + chan2) 28 | m.expect(c3a, "JOIN to 2nd channel", ":c3a.*JOIN.*" + chan2) 29 | m.not_expect(c1a, "should not see any JOIN in primary channel", ":c3a.*JOIN") 30 | print 31 | m.clearlog() 32 | 33 | # Test with +i (invite only) 34 | m.send(c3a, "PART " + chan2) 35 | m.send(c1a, "MODE " + chan1 + " -l+i") 36 | m.expect(c1a, "MODE", "MODE.*\+i") 37 | m.send(c3a, "JOIN " + chan1) 38 | m.expect(c3a, "Server informing about redirect", ":irc.* 470 $me " + chan1 + " " + chan2 + " :\[Link\] Cannot join channel " + chan1 + " \(channel is invite only\) -- transferring you to " + chan2) 39 | m.expect(c3a, "JOIN to 2nd channel", ":c3a.*JOIN.*" + chan2) 40 | m.not_expect(c1a, "should not see any JOIN in primary channel", ":c3a.*JOIN") 41 | print 42 | m.clearlog() 43 | 44 | # Test with +b (affected by some other ban) 45 | m.send(c3a, "PART " + chan2) 46 | m.send(c1a, "MODE " + chan1 + " -i+b c3a*!*@*") 47 | m.expect(c1a, "MODE", "MODE.*\+b") 48 | m.send(c3a, "JOIN " + chan1) 49 | m.expect(c3a, "Server informing about redirect", ":irc.* 470 $me " + chan1 + " " + chan2 + " :\[Link\] Cannot join channel " + chan1 + " \(you are banned\) -- transferring you to " + chan2) 50 | m.expect(c3a, "JOIN to 2nd channel", ":c3a.*JOIN.*" + chan2) 51 | m.not_expect(c1a, "should not see any JOIN in primary channel", ":c3a.*JOIN") 52 | print 53 | m.clearlog() 54 | 55 | # Test with +k (channel key) 56 | m.send(c3a, "PART " + chan2) 57 | m.send(c1a, "MODE " + chan1 + " -b+k c3a*!*@* secret") 58 | m.expect(c1a, "MODE", "MODE.*\+k") 59 | m.send(c3a, "JOIN " + chan1) 60 | m.expect(c3a, "Server informing about redirect", ":irc.* 470 $me " + chan1 + " " + chan2 + " :\[Link\] Cannot join channel " + chan1 + " \(invalid channel key\) -- transferring you to " + chan2) 61 | m.expect(c3a, "JOIN to 2nd channel", ":c3a.*JOIN.*" + chan2) 62 | m.not_expect(c1a, "should not see any JOIN in primary channel", ":c3a.*JOIN") 63 | print 64 | m.clearlog() 65 | -------------------------------------------------------------------------------- /tests/chanmodes/ban: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, skip = c3a, creator=c1a) 12 | m.expect(c1a, "users in channel", "JOIN") 13 | print 14 | 15 | # Since we have so many ban test types we use 16 | # some abstraction so you can easily add stuff: 17 | 18 | bantests = [ 19 | { "matchban":"c3a*!*@*", 20 | "nomatchban":"c3aNOMATCH*!*@*", 21 | "bantype":"by nick", 22 | }, 23 | { "matchban":"*!*username@*", 24 | "nomatchban":"*!*nomatch@*", 25 | "bantype":"by username", 26 | }, 27 | { "matchban":"*!*@Clk-8608861", 28 | "nomatchban":"*!*@Clk-6C400E99", 29 | "bantype":"by cloaked hostname", 30 | }, 31 | # { "matchban":"*!*@C9BC54D4.CCE2A095.73B42A24.IP", 32 | # "nomatchban":"*!*@231FD6C8.9CC7FEA8.9999999.IP", 33 | # "bantype":"by cloaked IP", 34 | # }, 35 | { "matchban":"*!*@localhost", 36 | "nomatchban":"*!*@nomatchhost", 37 | "bantype":"by real hostname", 38 | }, 39 | { "matchban":"*!*@127.0.0.1", 40 | "nomatchban":"*!*@127.0.0.91", 41 | "bantype":"by real IP", 42 | }, 43 | { "matchban":"*!*@127.0.0.1/16", 44 | "nomatchban":"*!*@127.5.0.1/16", 45 | "bantype":"by real IP with CIDR", 46 | }, 47 | { "matchban":"*!*@this.is.a.test", 48 | "nomatchban":"*!*@not.a.match", 49 | "bantype":"by vhost", 50 | "specialcmd":"VHOST test test" 51 | }, 52 | # A ban on a cloakedhost should still work if using a vhost: 53 | { "matchban":"*!*@Clk-8608861", 54 | "nomatchban":"*!*@Clk-9999999", 55 | "bantype":"by cloakedhost when using vhost", 56 | "specialcmd":"VHOST test test" 57 | }, 58 | ] 59 | 60 | for t in bantests: 61 | if t.get('specialcmd'): 62 | m.send(c3a, t['specialcmd']) 63 | print 64 | 65 | m.send(c1a, "MODE " + chan + " +b " + t['matchban']) 66 | m.send(c3a, "JOIN " + chan) 67 | m.expect(c3a, "unable to join if banned by " + t['bantype'] + " (474 error)", "474.*Cannot join") 68 | m.not_expect(c1a, "unable to join if banned by " + t['bantype'] + " (no JOIN)", ":c3a.*JOIN") 69 | print 70 | 71 | m.send(c1a, "MODE " + chan + " -b+b " + t['matchban'] + ' ' + t['nomatchban']) 72 | m.clearlog() 73 | print 74 | 75 | m.send(c3a, "JOIN " + chan) 76 | m.not_expect(c3a, "can join if not banned " + t['bantype'] + " (should be no 474 error)", "474.*Cannot join") 77 | m.expect(c1a, "can join if not banned " + t['bantype'] + " (JOIN)", ":c3a.*JOIN") 78 | print 79 | 80 | m.send(c3a, "PART " + chan) 81 | m.send(c3a, "MODE $c3a -x+x") 82 | m.send(c1a, "MODE " + chan + " -b " + t['nomatchban']) 83 | m.clearlog() 84 | print 85 | -------------------------------------------------------------------------------- /tests/usercommands/kick: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | kick_allowed_matrix = [ 5 | { "q":"q" }, { "q":"a" }, { "q":"o" }, { "q":"h" }, { "q":"v" }, 6 | { "a":"o" }, { "a":"h" }, { "a":"v" }, 7 | { "o":"o" }, { "o":"h" }, { "o":"v" }, 8 | { "h":"v" }, 9 | ] 10 | 11 | kick_not_allowed_matrix = [ 12 | # q may do anything, so skipped here... 13 | { "a":"q" }, { "a":"a" }, 14 | { "o":"q" }, { "o":"a" }, 15 | { "h":"q" }, { "h":"a" }, { "h":"o" }, { "h":"h" }, 16 | { "v":"v" }, 17 | ] 18 | 19 | m = irctestframework.irctest.IrcTest() 20 | c1a = m.new('c1a') 21 | c1o = m.new('c1o') 22 | c2a = m.new('c2a') 23 | c3a = m.new('c3a') 24 | m.connect() 25 | 26 | m.send(c1o, "OPER netadmin test") 27 | m.clearlog() 28 | print 29 | 30 | chan = m.randchan() 31 | m.join_all(chan, creator = c1a) 32 | m.expect(c1a, "user in channel", "JOIN") 33 | print 34 | 35 | for e in kick_allowed_matrix: 36 | for kicker_level,victim_level in e.items(): 37 | m.send(c1o, "MODE " + chan + " -vhoaq $c1a $c1a $c1a $c1a $c1a") 38 | m.send(c1o, "MODE " + chan + " +" + kicker_level + " $c1a") 39 | m.send(c1o, "MODE " + chan + " -vhoaq $c3a $c3a $c3a $c3a $c3a") 40 | m.send(c1o, "MODE " + chan + " +" + victim_level + " $c3a") 41 | m.clearlog() 42 | print 43 | m.send(c1a, "KICK " + chan + " $c3a :go away plz") 44 | m.expect_all("User should be kicked if a +" + kicker_level + " tries to kick a +" + victim_level, ":$c1a.*KICK.*" + chan + ".*$c3a :go away plz") 45 | m.clearlog() 46 | print 47 | m.send_all("NAMES " + chan) 48 | m.not_expect_all("Kicked user should no longer be in channel", "353.*" + chan + " :.*$c3a") 49 | m.clearlog() 50 | print 51 | m.send(c3a, "JOIN " + chan) 52 | m.expect(c1a, "user back in channel", ":c3a.*JOIN") 53 | m.clearlog() 54 | print 55 | 56 | for e in kick_not_allowed_matrix: 57 | for kicker_level,victim_level in e.items(): 58 | m.send(c1o, "MODE " + chan + " -vhoaq $c1a $c1a $c1a $c1a $c1a") 59 | m.send(c1o, "MODE " + chan + " +" + kicker_level + " $c1a") 60 | m.send(c1o, "MODE " + chan + " -vhoaq $c3a $c3a $c3a $c3a $c3a") 61 | m.send(c1o, "MODE " + chan + " +" + victim_level + " $c3a") 62 | m.clearlog() 63 | print 64 | m.send(c1a, "KICK " + chan + " $c3a :go away plz") 65 | m.not_expect_all("User should NOT be kicked if a +" + kicker_level + " tries to kick a +" + victim_level, ":$c1a.*KICK.*" + chan + ".*$c3a :go away plz") 66 | m.clearlog() 67 | print 68 | m.send_all("NAMES " + chan) 69 | m.expect_all("User should still be in channel", "353.*" + chan + " :.*$c3a") 70 | m.clearlog() 71 | print 72 | m.send(c3a, "JOIN " + chan) 73 | m.clearlog() 74 | print 75 | -------------------------------------------------------------------------------- /tests/opercommands/samode: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | # Contrary to the channel mode specific mode tests, this tests the MODE 11 | # command itself, if it eats the correct parameter, broadcasts it corectly, etc. 12 | 13 | chan = m.randchan() 14 | m.join_all(chan, creator = c1a) 15 | m.expect(c1a, "user in channel", "JOIN") 16 | print 17 | 18 | m.send(c1a, "SAMODE " + chan + " +slk 11 22") 19 | m.expect(c1a, "Command not permitted as non-ircop", ":.+ 481 $me :Permission Denied") 20 | m.clearlog() 21 | print 22 | 23 | m.send(c1a, "OPER netadmin test") 24 | m.send(c1a, "SAMODE " + chan + " +slk 11 22") 25 | m.expect_all("Everyone should see MODE change #1", ":irc1.test.net MODE " + chan + " \+slk 11 22") 26 | m.expect(c1a, "SAMODE notice", ":.+ NOTICE $me :.*Client $c1a used SAMODE " + chan + " \(\+slk 11 22\)") 27 | m.clearlog() 28 | print 29 | 30 | m.send_all("MODE " + chan) 31 | m.expect_all("Verify modes set, via MODE #chan, after #1", " 324 .* " + chan + " \+kls 22 11") 32 | m.clearlog() 33 | print 34 | 35 | m.send(c1a, "SAMODE " + chan + " -l") 36 | m.expect_all("Everyone should see MODE change #2", ":irc1.test.net MODE " + chan + " \-l") 37 | m.clearlog() 38 | print 39 | 40 | m.send_all("MODE " + chan) 41 | m.expect_all("Verify modes set, via MODE #chan, after #2", " 324 .* " + chan + " \+ks 22") 42 | m.clearlog() 43 | print 44 | 45 | m.send(c1a, "SAMODE " + chan + " -k+f dummy [5t]:10") 46 | m.expect_all("Everyone should see MODE change #3", ":irc1.test.net MODE " + chan + " \-k\+f 22 \[5t\]:10") 47 | m.clearlog() 48 | print 49 | 50 | m.send_all("MODE " + chan) 51 | m.expect_all("Verify modes set, via MODE #chan, after #3", " 324 .* " + chan + " \+fs \[5t\]:10") 52 | m.clearlog() 53 | print 54 | 55 | # Collapsed will only process the first parameter (set in this case) and ignore the other changes 56 | m.send(c1a, "SAMODE " + chan + " +k-k+k one two three") 57 | m.expect_all("Everyone should see collapsed MODE change #4", ":irc1.test.net MODE " + chan + " \+k one") 58 | m.clearlog() 59 | print 60 | 61 | m.send_all("MODE " + chan) 62 | m.expect_all("Verify modes set, via MODE #chan, after #4", " 324 .* " + chan + " \+fks \[5t\]:10 one") 63 | m.clearlog() 64 | print 65 | 66 | # Collapased will only process the first parameter (unset in this case) and ignore the other changes 67 | m.send(c1a, "SAMODE " + chan + " -f+f-f+f [1t]:10 [2t]:10 [3t]:10 [4t]:10") 68 | m.expect_all("Everyone should see collapsed MODE change #5", ":irc1.test.net MODE " + chan + " -f \[5t\]:10") 69 | m.clearlog() 70 | print 71 | 72 | m.send_all("MODE " + chan) 73 | m.expect_all("Verify modes set, via MODE #chan, after #5", " 324 .* " + chan + " \+ks one") 74 | m.clearlog() 75 | print 76 | 77 | m.send(c1a, "SAMODE #nonexistant +k key") 78 | m.expect(c1a, "MODE set request for non-existant channel should return 403 numeric", "403.*No such channel") 79 | m.clearlog() 80 | print 81 | -------------------------------------------------------------------------------- /tests/db/reading/history: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | import time 4 | 5 | m = irctestframework.irctest.IrcTest() 6 | c1a = m.new('c1a') 7 | c1b = m.new('c1b') 8 | c1c = m.new('c1c') 9 | c1d = m.new('c1d') 10 | m.connect() 11 | 12 | m.send_all("CAP REQ server-time") 13 | m.send(c1d, "CAP REQ batch") 14 | print 15 | 16 | chan = "#history_test" 17 | m.send(c1c, "JOIN " + chan) # first user with ops 18 | m.send(c1a, "JOIN " + chan) 19 | m.expect(c1a, "users in channel", "JOIN") 20 | m.clearlog() 21 | print 22 | 23 | m.send(c1b, "JOIN " + chan) 24 | m.expect(c1b, "new user joining channel (same server)", "JOIN") 25 | m.expect(c1b, "history playback: 1st message", ":c1a.* PRIVMSG .* :one") 26 | m.expect(c1b, "history playback: 2nd message should have colors stripped", ":c1a.* PRIVMSG .* :red two") 27 | m.expect(c1b, "history playback: 9th message is altered", ":c2a.* PRIVMSG.*nine ") 28 | m.expect(c1b, "history playback: 10th message", ":c2a.* PRIVMSG .* :ten") 29 | m.not_expect(c1b, "history playback: should not see wrapped message (message zero)", "PRIVMSG.*should be wrapped") 30 | m.not_expect(c1b, "playback should not see a BATCH if not supported", ".*BATCH.*") 31 | # do not clear here, so we can see any potential inconsistency with the other playback.. 32 | print 33 | 34 | m.send(c1d, "JOIN " + chan) 35 | m.expect(c1d, "new user joining channel (far server)", "JOIN") 36 | m.expect(c1d, "should start a BATCH", " BATCH \+[^ ]+ chathistory " + chan) 37 | m.expect(c1d, "history playback: 1st message", ":c1a.* PRIVMSG .* :one") 38 | m.expect(c1d, "history playback: 2nd message should have colors stripped", ":c1a.* PRIVMSG .* :red two") 39 | m.expect(c1d, "history playback: 9th message is altered", ":c2a.* PRIVMSG.*nine ") 40 | m.expect(c1d, "history playback: 10th message", ":c2a.* PRIVMSG .* :ten") 41 | m.expect(c1d, "all playback should be wrapped in a batch (1 of 10)", ".*batch=.+ PRIVMSG .* :one") 42 | m.expect(c1d, "all playback should be wrapped in a batch (2 of 10)", ".*batch=.+ PRIVMSG .* :red two") 43 | m.expect(c1d, "all playback should be wrapped in a batch (3 of 10)", ".*batch=.+ PRIVMSG .* :three") 44 | m.expect(c1d, "all playback should be wrapped in a batch (4 of 10)", ".*batch=.+ PRIVMSG .* :four") 45 | m.expect(c1d, "all playback should be wrapped in a batch (5 of 10)", ".*batch=.+ PRIVMSG .* :five") 46 | m.expect(c1d, "all playback should be wrapped in a batch (6 of 10)", ".*batch=.+ PRIVMSG .* :six") 47 | m.expect(c1d, "all playback should be wrapped in a batch (7 of 10)", ".*batch=.+ PRIVMSG .* :seven") 48 | m.expect(c1d, "all playback should be wrapped in a batch (8 of 10)", ".*batch=.+ PRIVMSG .* :eight") 49 | m.expect(c1d, "all playback should be wrapped in a batch (9 of 10)", ".*batch=.+ PRIVMSG .* :nine ") 50 | m.expect(c1d, "all playback should be wrapped in a batch (10 of 10)", ".*batch=.+ PRIVMSG .* :ten") 51 | m.not_expect(c1d, "history playback: should not see wrapped message (message zero)", "PRIVMSG.*should be wrapped") 52 | m.expect(c1d, "should end the BATCH", " BATCH -[^ ]+") 53 | m.clearlog() 54 | print 55 | -------------------------------------------------------------------------------- /tests/extbans/msgbypass: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.join_all(chan, creator=c1a, skip = c3a) 12 | m.send(c1a, "MODE " + chan + " +n") 13 | m.expect(c1a, "users in channel", "JOIN") 14 | m.clearlog() 15 | print 16 | 17 | # external message 18 | m.send(c3a, "PRIVMSG " + chan + " :external message") 19 | m.expect(c3a, "Can normally not send if +n", ":irc.+ 404 $me " + chan) 20 | m.not_expect_all("Message should not be delivered", "external message") 21 | m.clearlog() 22 | print 23 | 24 | m.send(c1a, "MODE " + chan + " +e ~msgbypass:external:$c3a!*@*") 25 | m.send(c3a, "PRIVMSG " + chan + " :external message") 26 | m.not_expect(c3a, "No error message now even if +n", ":irc.+ 404 $me " + chan) 27 | m.expect_all("Message should be delivered", "external message", skip = c3a) 28 | m.clearlog() 29 | print 30 | 31 | m.send(c1a, "MODE " + chan + " -e ~msgbypass:external:$c3a!*@*") 32 | m.send(c3a, "JOIN " + chan) 33 | m.expect(c1a, "Client 3 joins channel", ":$c3a.* JOIN ") 34 | m.clearlog() 35 | print 36 | 37 | # moderated message 38 | m.send(c1a, "MODE " + chan + " +m") 39 | m.send(c3a, "PRIVMSG " + chan + " :moderated message") 40 | m.expect(c3a, "Can normally not send if +m", ":irc.+ 404 $me " + chan) 41 | m.not_expect_all("Message should not be delivered", "moderated message") 42 | m.clearlog() 43 | print 44 | 45 | m.send(c1a, "MODE " + chan + " +e ~msgbypass:moderated:$c3a!*@*") 46 | m.send(c3a, "PRIVMSG " + chan + " :moderated message") 47 | m.not_expect(c3a, "No error message now even if +m", ":irc.+ 404 $me " + chan) 48 | m.expect_all("Message should be delivered", "moderated message", skip = c3a) 49 | m.clearlog() 50 | print 51 | 52 | # censor 53 | m.send(c1a, "MODE " + chan + " -e ~msgbypass:moderated:$c3a!*@*") 54 | m.send(c1a, "MODE " + chan + " -m+G") 55 | m.send(c3a, "PRIVMSG " + chan + " :fuck") 56 | m.expect_all("Message should be censored", "", skip = c3a) 57 | m.not_expect_all("Message should not be delivered", "fuck") 58 | m.clearlog() 59 | print 60 | 61 | m.send(c1a, "MODE " + chan + " +e ~msgbypass:censor:$c3a!*@*") 62 | m.send(c3a, "PRIVMSG " + chan + " :fuck") 63 | m.expect_all("Message should be delivered", "fuck", skip = c3a) 64 | m.clearlog() 65 | print 66 | 67 | # color 68 | m.send(c1a, "MODE " + chan + " -e ~msgbypass:censor:$c3a!*@*") 69 | m.send(c1a, "MODE " + chan + " -G+c") 70 | m.send(c3a, "PRIVMSG " + chan + " :\00312color") 71 | m.expect(c3a, "Can normally not send if +c", ":irc.+ 404 $me " + chan) 72 | m.not_expect_all("Message should not be delivered", "12color") 73 | m.clearlog() 74 | print 75 | 76 | m.send(c1a, "MODE " + chan + " +e ~msgbypass:color:$c3a!*@*") 77 | m.send(c3a, "PRIVMSG " + chan + " :\00312color") 78 | m.not_expect(c3a, "No error message now even if +c", ":irc.+ 404 $me " + chan) 79 | m.expect_all("Message should be delivered", "\00312color", skip = c3a) 80 | m.clearlog() 81 | print 82 | 83 | # notice 84 | m.send(c1a, "MODE " + chan + " -e ~msgbypass:color:$c3a!*@*") 85 | m.send(c1a, "MODE " + chan + " -c+T") 86 | m.send(c3a, "NOTICE " + chan + " :this is a notice") 87 | # no 404 numeric error beause NOTICEs should not generate errors (RFC) 88 | m.not_expect_all("Message should not be delivered", "this is a notice") 89 | m.clearlog() 90 | print 91 | 92 | m.send(c1a, "MODE " + chan + " +e ~msgbypass:notice:$c3a!*@*") 93 | m.send(c3a, "NOTICE " + chan + " :this is a notice") 94 | m.expect_all("Message should be delivered", "this is a notice", skip = c3a) 95 | m.clearlog() 96 | print 97 | -------------------------------------------------------------------------------- /tests/db/writing/tkl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # 3 | # This tests TKLs such as: KLINE, ZLINE, GLINE, GZLINE, SPAMFILTER 4 | # 5 | import irctestframework.irctest 6 | 7 | m = irctestframework.irctest.IrcTest() 8 | c1a = m.new('c1a') 9 | c2a = m.new('c2a') 10 | c3a = m.new('c3a') 11 | m.connect() 12 | 13 | m.send_all("OPER netadmin test") 14 | 15 | ##### LOCAL TKLS ###### 16 | 17 | ### KLINE on host 18 | m.send(c1a, "KLINE user@some.host666 3600 This is a kline test") 19 | regex = "K-Line added: 'user@some\.host666'.*This is a kline test" 20 | m.expect(c1a, "K-Line added notice to local IRCOps", regex) 21 | m.not_expect_all("K-Line added notice NOT to remote IRCOps", regex, skip=c1a) 22 | m.clearlog() 23 | print 24 | 25 | m.send_all("STATS kline") 26 | regex = "223.*K user@some\.host666 3[0-9][0-9][0-9] [0-9] c1a.* :This is a kline test" 27 | m.expect(c1a, "K-Line shown in /STATS kline locally", regex) 28 | m.not_expect_all("K-Line NOT shown in /STATS kline on remote servers", regex, skip=c1a) 29 | m.clearlog() 30 | print 31 | 32 | ### ZLINE on host 33 | m.send(c1a, "ZLINE *@192.0.2.2 3600 This is a zline test") 34 | regex = "Z-Line added: '\*@192\.0\.2\.2'.*This is a zline test" 35 | m.expect(c1a, "Z-Line added notice to local IRCOps", regex) 36 | m.not_expect_all("Z-Line added notice NOT to remote IRCOps", regex, skip=c1a) 37 | m.clearlog() 38 | print 39 | 40 | m.send_all("STATS kline") 41 | regex = "223.*z \*@192\.0\.2\.2 3[0-9][0-9][0-9] [0-9] c1a.* :This is a zline test" 42 | m.expect(c1a, "Z-Line shown in /STATS zline locally", regex) 43 | m.not_expect_all("Z-Line NOT shown in /STATS zline on remote servers", regex, skip=c1a) 44 | m.clearlog() 45 | print 46 | 47 | ##### GLOBAL TKLS ###### 48 | 49 | ### GLINE on host 50 | m.send(c1a, "GLINE user@some.host777 3600 This is a gline test") 51 | m.expect_all("G-Line added notice to IRCOps", 52 | "G-Line added: 'user@some\.host777'.*This is a gline test") 53 | m.clearlog() 54 | print 55 | 56 | m.send_all("STATS gline") 57 | m.expect_all("G-Line shown in /STATS gline", 58 | "223.*G user@some\.host777 3[0-9][0-9][0-9] [0-9] c1a.* :This is a gline test") 59 | m.clearlog() 60 | print 61 | 62 | ### GLINE on ip 63 | m.send(c1a, "GLINE user@192.0.2.3 3600 This is a gline test on IP") 64 | m.expect_all("G-Line added notice to IRCOps", 65 | "G-Line added: 'user@192\.0\.2\.3'.*This is a gline test on IP") 66 | m.clearlog() 67 | print 68 | 69 | m.send_all("STATS gline") 70 | m.expect_all("G-Line shown in /STATS gline", 71 | "223.*G user@192\.0\.2\.3 3[0-9][0-9][0-9] [0-9] c1a.* :This is a gline test on IP") 72 | m.clearlog() 73 | print 74 | 75 | ### GZLINE on ip 76 | m.send(c1a, "GZLINE *@192.0.2.4 3600 This is a gzline test on IP") 77 | m.expect_all("GZ-Line added notice to IRCOps", 78 | "Global Z-Line added: '\*@192\.0\.2\.4'.*This is a gzline test on IP") 79 | m.clearlog() 80 | print 81 | 82 | m.send_all("STATS gline") 83 | m.expect_all("GZ-Line shown in /STATS gline", 84 | "223.*Z \*@192\.0\.2\.4 3[0-9][0-9][0-9] [0-9] c1a.* :This is a gzline test on IP") 85 | m.clearlog() 86 | print 87 | 88 | ### Spamfilter 89 | m.send(c1a, "SPAMFILTER add -simple p gzline 0 this_is_a_test Please gzline me immediately") 90 | m.expect_all("Spamfilter added notice to IRCOps", 91 | "Spamfilter added: 'Please gzline me immediately' \[type: simple\] \[targets: p\] \[action: gzline\] \[reason: this is a test\].*") 92 | m.clearlog() 93 | print 94 | 95 | m.send_all("STATS spamfilter") 96 | m.expect_all("Spamfilter shown in /STATS spamfilter", 97 | "229.* F simple p gzline 0 [0-9]* 0 this_is_a_test c1a[^ ]+ [0-9]+ [0-9]+ :Please gzline me immediately") 98 | m.clearlog() 99 | print 100 | 101 | -------------------------------------------------------------------------------- /tests/chanmodes/vhoaq: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | mode_allowed_matrix = [ 5 | { "q":"q" }, { "q":"a" }, { "q":"o" }, { "q":"h" }, { "q":"v" }, 6 | { "a":"o" }, { "a":"h" }, { "a":"v" }, 7 | { "o":"o" }, { "o":"h" }, { "o":"v" }, 8 | { "h":"v" }, 9 | ] 10 | 11 | mode_not_allowed_matrix = [ 12 | # q may do anything, so skipped here... 13 | { "a":"q" }, { "a":"a" }, 14 | { "o":"q" }, { "o":"a" }, 15 | { "h":"q" }, { "h":"a" }, { "h":"o" }, { "h":"h" }, 16 | { "v":"v" }, 17 | ] 18 | 19 | m = irctestframework.irctest.IrcTest() 20 | c1a = m.new('c1a') 21 | c1o = m.new('c1o') 22 | c2a = m.new('c2a') 23 | c3a = m.new('c3a') 24 | m.connect() 25 | 26 | m.send(c1o, "OPER netadmin test") 27 | m.clearlog() 28 | print 29 | 30 | chan = m.randchan() 31 | m.join_all(chan, creator = c1a) 32 | m.expect(c1a, "user in channel", "JOIN") 33 | print 34 | 35 | # Verify what should be allowed 36 | for e in mode_allowed_matrix: 37 | for op_level,victim_level in e.items(): 38 | m.send(c1o, "MODE " + chan + " -vhoaq $c1a $c1a $c1a $c1a $c1a") 39 | m.send(c1o, "MODE " + chan + " +" + op_level + " $c1a") 40 | m.send(c1o, "MODE " + chan + " -vhoaq $c3a $c3a $c3a $c3a $c3a") 41 | m.send(c1o, "MODE " + chan + " +" + victim_level + " $c3a") 42 | m.clearlog() 43 | print 44 | m.send(c1a, "MODE " + chan + " -" + victim_level + " $c3a") 45 | m.expect_all("User with +" + op_level + " should be able to -" + victim_level, ":$c1a.*MODE.*" + chan + " -" + victim_level + " $c3a") 46 | m.clearlog() 47 | print 48 | m.send(c1a, "MODE " + chan + " +" + victim_level + " $c3a") 49 | m.expect_all("User with +" + op_level + " should be able to +" + victim_level, ":$c1a.*MODE.*" + chan + " \\+" + victim_level + " $c3a") 50 | m.clearlog() 51 | print 52 | 53 | # Verify what should NOT be allowed 54 | for e in mode_not_allowed_matrix: 55 | for op_level,victim_level in e.items(): 56 | m.send(c1o, "MODE " + chan + " -vhoaq $c1a $c1a $c1a $c1a $c1a") 57 | m.send(c1o, "MODE " + chan + " +" + op_level + " $c1a") 58 | m.send(c1o, "MODE " + chan + " -vhoaq $c3a $c3a $c3a $c3a $c3a") 59 | m.send(c1o, "MODE " + chan + " +" + victim_level + " $c3a") 60 | m.clearlog() 61 | print 62 | m.send(c1a, "MODE " + chan + " -" + victim_level + " $c3a") 63 | m.not_expect_all("User with +" + op_level + " should NOT be able to -" + victim_level, ":$c1a.*MODE.*" + chan) 64 | m.clearlog() 65 | print 66 | m.send(c1a, "MODE " + chan + " +" + victim_level + " $c3a") 67 | m.not_expect_all("User with +" + op_level + " should NOT be able to +" + victim_level, ":$c1a.*MODE.*" + chan) 68 | m.clearlog() 69 | print 70 | 71 | # And finally verify -hoaq removal on self (special case) and 72 | # also verify that you cannot +hoaq yourself magically :D 73 | for op_level in { "h", "o", "a", "q" }: 74 | m.send(c1o, "MODE " + chan + " -vhoaq $c1a $c1a $c1a $c1a $c1a") 75 | m.send(c1o, "MODE " + chan + " +" + op_level + " $c1a") 76 | m.clearlog() 77 | print 78 | # Should be able to remove themselves 79 | m.send(c1a, "MODE " + chan + " -" + op_level + " $c1a") 80 | m.expect_all("User with +" + op_level + " should be able to -" + op_level, ":$c1a.*MODE.*" + chan + " -" + op_level + " $c1a") 81 | m.clearlog() 82 | print 83 | # Should now be opless with no MODE changes allowed 84 | m.send(c1a, "MODE " + chan + " +" + op_level + " $c1a") 85 | m.not_expect_all("User with no chanop rights should not be able to set themselves +" + victim_level, ":$c1a.*MODE.*" + chan) 86 | m.clearlog() 87 | print 88 | -------------------------------------------------------------------------------- /tests/usercommands/mode: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | # Contrary to the channel mode specific mode tests, this tests the MODE 11 | # command itself, if it eats the correct parameter, broadcasts it corectly, etc. 12 | 13 | chan = m.randchan() 14 | m.join_all(chan, creator = c1a) 15 | m.expect(c1a, "user in channel", "JOIN") 16 | print 17 | 18 | m.send(c2a, "MODE " + chan + " +slk 666 key") 19 | m.send(c2a, "MODE " + chan + " +b ban") 20 | m.expect(c2a, "Want 482 / not chanop error", " 482 .* " + chan) 21 | m.not_expect_all("Nobody should see this unauthorized MODE change", ":$c2a.* MODE " + chan) 22 | m.clearlog() 23 | print 24 | 25 | m.send(c1a, "MODE " + chan + " +slk 11 22") 26 | m.expect_all("Everyone should see MODE change #1", ":$c1a.* MODE " + chan + " \+slk 11 22") 27 | m.clearlog() 28 | print 29 | 30 | m.send_all("MODE " + chan) 31 | m.expect_all("Verify modes set, via MODE #chan, after #1", " 324 .* " + chan + " \+kls 22 11") 32 | m.clearlog() 33 | print 34 | 35 | m.send(c1a, "MODE " + chan + " -l") 36 | m.expect_all("Everyone should see MODE change #2", ":$c1a.* MODE " + chan + " \-l") 37 | m.clearlog() 38 | print 39 | 40 | m.send_all("MODE " + chan) 41 | m.expect_all("Verify modes set, via MODE #chan, after #2", " 324 .* " + chan + " \+ks 22") 42 | m.clearlog() 43 | print 44 | 45 | m.send(c1a, "MODE " + chan + " -k+f dummy [5t]:10") 46 | m.expect_all("Everyone should see MODE change #3", ":$c1a.* MODE " + chan + " \-k\+f 22 \[5t\]:10") 47 | m.clearlog() 48 | print 49 | 50 | m.send_all("MODE " + chan) 51 | m.expect_all("Verify modes set, via MODE #chan, after #3", " 324 .* " + chan + " \+fs \[5t\]:10") 52 | m.clearlog() 53 | print 54 | 55 | # Collapsed will only process the first parameter (set in this case) and ignore the other changes 56 | m.send(c1a, "MODE " + chan + " +k-k+k one two three") 57 | m.expect_all("Everyone should see collapsed MODE change #4", ":$c1a.* MODE " + chan + " \+k one") 58 | m.clearlog() 59 | print 60 | 61 | m.send_all("MODE " + chan) 62 | m.expect_all("Verify modes set, via MODE #chan, after #4", " 324 .* " + chan + " \+fks \[5t\]:10 one") 63 | m.clearlog() 64 | print 65 | 66 | # Collapased will only process the first parameter (unset in this case) and ignore the other changes 67 | m.send(c1a, "MODE " + chan + " -f+f-f+f [1t]:10 [2t]:10 [3t]:10 [4t]:10") 68 | m.expect_all("Everyone should see collapsed MODE change #5", ":$c1a.* MODE " + chan + " -f \[5t\]:10") 69 | m.clearlog() 70 | print 71 | 72 | m.send_all("MODE " + chan) 73 | m.expect_all("Verify modes set, via MODE #chan, after #5", " 324 .* " + chan + " \+ks one") 74 | m.clearlog() 75 | print 76 | 77 | m.send(c1a, "MODE #nonexistant") 78 | m.expect(c1a, "MODE query request for non-existant channel should return 403 numeric", "403.*No such channel") 79 | m.clearlog() 80 | print 81 | 82 | m.send(c1a, "MODE #nonexistant +k key") 83 | m.expect(c1a, "MODE set request for non-existant channel should return 403 numeric", "403.*No such channel") 84 | m.clearlog() 85 | print 86 | 87 | m.send(c1a, "MODE $c1a +r") 88 | m.not_expect(c1a, "Shouldn't be able to set +r on yourself", "MODE.*\+r") 89 | m.clearlog() 90 | print 91 | 92 | m.send(c1a, "MODE $c1a +z") 93 | m.not_expect(c1a, "Shouldn't be able to set +z on yourself", "MODE.*\+z") 94 | m.clearlog() 95 | print 96 | 97 | m.send(c1a, "MODE $c1a +t") 98 | m.not_expect(c1a, "Shouldn't be able to set +t on yourself", "MODE.*\+t") 99 | m.clearlog() 100 | print 101 | 102 | m.send(c1a, "MODE $c1a +o") 103 | m.not_expect(c1a, "Shouldn't be able to set +o on yourself", "MODE.*\+o") 104 | m.clearlog() 105 | print 106 | 107 | m.send(c1a, "MODE $c1a +S") 108 | m.not_expect(c1a, "Shouldn't be able to set +S on yourself", "MODE.*\+S") 109 | m.clearlog() 110 | print 111 | 112 | m.send(c1a, "MODE $c1a +p") 113 | m.expect(c1a, "Should be able to set +p on yourself", "MODE.*\+p") 114 | m.clearlog() 115 | print 116 | 117 | m.send(c1a, "MODE $c1a +GT") 118 | m.expect(c1a, "Should be able to set multiple modes on yourself (+GT)", "MODE.*\+GT") 119 | m.clearlog() 120 | print 121 | 122 | -------------------------------------------------------------------------------- /tests/usercommands/history: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | import time 4 | 5 | # Here we test the HISTORY command 6 | # Note that these are tests are more loose, as we do more proper 7 | # testing of things in tests/chanmodes/history 8 | 9 | m = irctestframework.irctest.IrcTest() 10 | c1a = m.new('c1a') 11 | c1b = m.new('c1b') 12 | c2a = m.new('c2a') 13 | c3a = m.new('c3a') 14 | c3b = m.new('c3b') 15 | m.connect() 16 | 17 | m.send_all("CAP REQ server-time") 18 | m.send(c3a, "CAP REQ batch") 19 | print 20 | 21 | chan = m.randchan() 22 | m.send(c2a, "JOIN " + chan) # first user with ops 23 | m.send(c1a, "JOIN " + chan) 24 | m.expect(c1a, "users in channel", "JOIN") 25 | m.clearlog() 26 | print 27 | 28 | # Set history channel mode: save 20 lines for 5 minutes 29 | m.send(c2a, "MODE " + chan + " +SGH 20:5") 30 | m.expect(c1a, "MODE +H", ":c2a.*MODE.*\+GSH 20:5") 31 | m.clearlog() 32 | print 33 | 34 | # Send 1+15 messages, the last one is normally wrapped in on-join playback 35 | # but is still visible via the HISTORY command playback. 36 | m.send(c1a, "PRIVMSG " + chan + " :should be wrapped in on-join playback") 37 | m.send(c1a, "PRIVMSG " + chan + " :one") 38 | m.send(c1a, "PRIVMSG " + chan + " :\0034red two\003") # will be stripped 39 | m.send(c1a, "PRIVMSG " + chan + " :three") 40 | m.send(c1a, "PRIVMSG " + chan + " :four") 41 | m.send(c1a, "PRIVMSG " + chan + " :five") 42 | m.send(c2a, "PRIVMSG " + chan + " :six") 43 | m.send(c2a, "PRIVMSG " + chan + " :seven") 44 | m.send(c2a, "PRIVMSG " + chan + " :eight") 45 | m.send(c2a, "PRIVMSG " + chan + " :nine fuck") # will be stripped 46 | m.send(c2a, "PRIVMSG " + chan + " :ten") 47 | m.send(c2a, "PRIVMSG " + chan + " :eleven") 48 | m.send(c2a, "PRIVMSG " + chan + " :twelve") 49 | m.send(c2a, "PRIVMSG " + chan + " :thirteen") 50 | m.send(c2a, "PRIVMSG " + chan + " :fourteen") 51 | m.send(c2a, "PRIVMSG " + chan + " :fifteen") 52 | m.expect(c2a, "Message with stripped color", "PRIVMSG .*:red two") 53 | m.not_expect(c1a, "Message with censored message", "PRIVMSG.*nine fuck") 54 | m.clearlog() 55 | print 56 | 57 | # Expect a parameter: 58 | m.send(c1b, "HISTORY") 59 | m.expect(c1b, "Usage information if no parameter provided", "Use:") 60 | m.clearlog() 61 | print 62 | 63 | # Should not be able to retrieve history without joining: 64 | m.send(c1b, "HISTORY " + chan) 65 | m.expect(c1b, "History not allowed if not in channel", ":.* 442 $me " + chan) 66 | m.clearlog() 67 | print 68 | 69 | m.send(c1b, "JOIN " + chan) 70 | # this one should not show up in on-join (15 line limit), only in HISTORY #chan request 71 | m.not_expect(c1b, "history playback: should NOT see on-join-wrapped message (message zero)", "PRIVMSG.*should be wrapped") 72 | m.clearlog() 73 | print 74 | 75 | m.send(c1b, "HISTORY " + chan) 76 | m.expect(c1b, "history playback: 1st message", ":c1a.* PRIVMSG .* :one") 77 | m.expect(c1b, "history playback: 2nd message should have colors stripped", ":c1a.* PRIVMSG .* :red two") 78 | m.expect(c1b, "history playback: 9th message is altered", ":c2a.* PRIVMSG.*nine ") 79 | m.expect(c1b, "history playback: 10th message", ":c2a.* PRIVMSG .* :ten") 80 | m.expect(c1b, "history playback: should see on-join-wrapped message (message zero)", "PRIVMSG.*should be wrapped") 81 | m.not_expect(c1b, "playback should not see a BATCH if not supported", ".*BATCH.*") 82 | m.clearlog() 83 | print 84 | 85 | m.send(c2a, "PRIVMSG " + chan + " :sixteen") 86 | m.send(c2a, "PRIVMSG " + chan + " :seventeen") 87 | m.send(c2a, "PRIVMSG " + chan + " :eighteen") 88 | m.send(c2a, "PRIVMSG " + chan + " :nineteen") 89 | m.send(c2a, "PRIVMSG " + chan + " :twenty") 90 | m.clearlog() 91 | print 92 | 93 | m.send(c1b, "HISTORY " + chan) 94 | m.expect(c1b, "history playback: 1st message", ":c1a.* PRIVMSG .* :one") 95 | m.expect(c1b, "history playback: 2nd message should have colors stripped", ":c1a.* PRIVMSG .* :red two") 96 | m.expect(c1b, "history playback: 9th message is altered", ":c2a.* PRIVMSG.*nine ") 97 | m.expect(c1b, "history playback: 10th message", ":c2a.* PRIVMSG .* :ten") 98 | m.not_expect(c1b, "history playback: should NOT see now wrapped message (message zero)", "PRIVMSG.*should be wrapped") 99 | m.clearlog() 100 | print 101 | -------------------------------------------------------------------------------- /tests/extbans/securitygroup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | m.connect() 9 | 10 | chan = m.randchan() 11 | m.send(c1a, "JOIN " + chan) 12 | m.expect(c1a, "user in channel", "JOIN") 13 | m.clearlog() 14 | print 15 | 16 | #### Some syntax and invalid group checks 17 | m.send(c1a, "MODE " + chan + " +b ~security-group") 18 | m.not_expect(c1a, "no ban should be set that is invalid", ":.+ MODE " + chan + " \+b") 19 | m.clearlog() 20 | print 21 | 22 | m.send(c1a, "MODE " + chan + " +b ~security-group:abcdef") 23 | m.not_expect(c1a, "no ban should be set for non-existant security group", ":.+ MODE " + chan + " \+b") 24 | m.clearlog() 25 | print 26 | 27 | #### +b ~security-group:unknown-users 28 | m.send(c1a, "MODE " + chan + " +b ~security-group:unknown-users") 29 | m.expect(c1a, "expect ban to be set", ":.+ MODE " + chan + " \+b ~security-group:unknown-users") 30 | m.clearlog() 31 | print 32 | 33 | m.send(c2a, "FAKEREPUTATION 1") 34 | m.send(c2a, "JOIN " + chan) 35 | m.expect(c2a, "Client should receive error on JOIN attempt", ":irc.+ 474 $c2a " + chan + " :Cannot join channel \(\+b\)") 36 | m.not_expect(c1a, "Client with low reputation should NOT be able to join with +b ~security-group:unknown-users", ":c2a.* JOIN ") 37 | m.clearlog() 38 | print 39 | 40 | m.send(c3a, "FAKEREPUTATION 25") 41 | m.send(c3a, "JOIN " + chan) 42 | m.not_expect(c3a, "Client should NOT receive error on JOIN attempt", ":irc.+ 474 $c3a " + chan + " :Cannot join channel \(\+b\)") 43 | m.expect(c1a, "Client with high reputation should be able to join with +b ~security-group:unknown-users", ":c3a.* JOIN ") 44 | m.clearlog() 45 | print 46 | 47 | m.send(c1a, "MODE " + chan + " -b ~security-group:unknown-users") 48 | m.expect(c1a, "expect ban to be unset", ":.+ MODE " + chan + " -b ~security-group:unknown-users") 49 | m.send(c3a, "PART " + chan) 50 | m.clearlog() 51 | print 52 | 53 | #### +b ~security-group:!known-users 54 | m.send(c1a, "MODE " + chan + " +b ~security-group:!known-users") 55 | m.expect(c1a, "expect ban to be set", ":.+ MODE " + chan + " \+b ~security-group:!known-users") 56 | m.clearlog() 57 | print 58 | 59 | m.send(c2a, "FAKEREPUTATION 1") 60 | m.send(c2a, "JOIN " + chan) 61 | m.expect(c2a, "Client should receive error on JOIN attempt", ":irc.+ 474 $c2a " + chan + " :Cannot join channel \(\+b\)") 62 | m.not_expect(c1a, "Client with low reputation should NOT be able to join with +b ~security-group:!known-users", ":c2a.* JOIN ") 63 | m.clearlog() 64 | print 65 | 66 | m.send(c3a, "FAKEREPUTATION 25") 67 | m.send(c3a, "JOIN " + chan) 68 | m.not_expect(c3a, "Client should NOT receive error on JOIN attempt", ":irc.+ 474 $c3a " + chan + " :Cannot join channel \(\+b\)") 69 | m.expect(c1a, "Client with high reputation should be able to join with +b ~security-group:!known-users", ":c3a.* JOIN ") 70 | m.clearlog() 71 | print 72 | 73 | m.send(c1a, "MODE " + chan + " -b ~security-group:!known-users") 74 | m.expect(c1a, "expect ban to be unset", ":.+ MODE " + chan + " -b ~security-group:!known-users") 75 | m.send(c3a, "PART " + chan) 76 | m.clearlog() 77 | print 78 | 79 | #### +b ~security-group:known-users 80 | m.send(c1a, "MODE " + chan + " +b ~security-group:known-users") 81 | m.expect(c1a, "expect ban to be set", ":.+ MODE " + chan + " \+b ~security-group:known-users") 82 | m.clearlog() 83 | print 84 | 85 | m.send(c2a, "FAKEREPUTATION 1") 86 | m.send(c2a, "JOIN " + chan) 87 | m.not_expect(c2a, "Client should NOT receive error on JOIN attempt", ":irc.+ 474 $c2a " + chan + " :Cannot join channel \(\+b\)") 88 | m.expect(c1a, "Client with low reputation should be able to join with +b ~security-group:known-users", ":c2a.* JOIN ") 89 | m.clearlog() 90 | print 91 | 92 | m.send(c3a, "FAKEREPUTATION 25") 93 | m.send(c3a, "JOIN " + chan) 94 | m.expect(c3a, "Client should receive error on JOIN attempt", ":irc.+ 474 $c3a " + chan + " :Cannot join channel \(\+b\)") 95 | m.not_expect(c1a, "Client with high reputation should NOT be able to join with +b ~security-group:known-users", ":c3a.* JOIN ") 96 | m.clearlog() 97 | print 98 | 99 | m.send(c1a, "MODE " + chan + " -b ~security-group:known-users") 100 | m.expect(c1a, "expect ban to be unset", ":.+ MODE " + chan + " -b ~security-group:known-users") 101 | m.send(c2a, "PART " + chan) 102 | m.clearlog() 103 | print 104 | -------------------------------------------------------------------------------- /tests/chanmodes/history: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | import time 4 | 5 | m = irctestframework.irctest.IrcTest() 6 | c1a = m.new('c1a') 7 | c1b = m.new('c1b') 8 | c2a = m.new('c2a') 9 | c3a = m.new('c3a') 10 | c3b = m.new('c3b') 11 | m.connect() 12 | 13 | m.send_all("CAP REQ server-time") 14 | m.send(c3a, "CAP REQ batch") 15 | print 16 | 17 | chan = m.randchan() 18 | m.send(c2a, "JOIN " + chan) # first user with ops 19 | m.send(c1a, "JOIN " + chan) 20 | m.expect(c1a, "users in channel", "JOIN") 21 | m.clearlog() 22 | print 23 | 24 | # Set history channel mode: save 10 lines for 5 minutes 25 | m.send(c2a, "MODE " + chan + " +SGH 10:5") 26 | m.expect(c1a, "MODE +H", ":c2a.*MODE.*\+GSH 10:5") 27 | m.clearlog() 28 | print 29 | 30 | m.send(c1a, "PRIVMSG " + chan + " :should be wrapped") 31 | m.send(c1a, "PRIVMSG " + chan + " :one") 32 | m.send(c1a, "PRIVMSG " + chan + " :\0034red two\003") # will be stripped 33 | m.send(c1a, "PRIVMSG " + chan + " :three") 34 | m.send(c1a, "PRIVMSG " + chan + " :four") 35 | m.send(c1a, "PRIVMSG " + chan + " :five") 36 | m.send(c2a, "PRIVMSG " + chan + " :six") 37 | m.send(c2a, "PRIVMSG " + chan + " :seven") 38 | m.send(c2a, "PRIVMSG " + chan + " :eight") 39 | m.send(c2a, "PRIVMSG " + chan + " :nine fuck") # will be stripped 40 | m.send(c2a, "PRIVMSG " + chan + " :ten") 41 | m.expect(c2a, "Message with stripped color", "PRIVMSG .*:red two") 42 | m.not_expect(c1a, "Message with censored message", "PRIVMSG.*nine fuck") 43 | m.clearlog() 44 | print 45 | 46 | m.send(c1b, "JOIN " + chan) 47 | m.expect(c1b, "new user joining channel (same server)", "JOIN") 48 | m.expect(c1b, "history playback: 1st message", ":c1a.* PRIVMSG .* :one") 49 | m.expect(c1b, "history playback: 2nd message should have colors stripped", ":c1a.* PRIVMSG .* :red two") 50 | m.expect(c1b, "history playback: 9th message is altered", ":c2a.* PRIVMSG.*nine ") 51 | m.expect(c1b, "history playback: 10th message", ":c2a.* PRIVMSG .* :ten") 52 | m.not_expect(c1b, "history playback: should not see wrapped message (message zero)", "PRIVMSG.*should be wrapped") 53 | m.not_expect(c1b, "playback should not see a BATCH if not supported", ".*BATCH.*") 54 | # do not clear here, so we can see any potential inconsistency with the other playback.. 55 | print 56 | 57 | m.send(c3a, "JOIN " + chan) 58 | m.expect(c3a, "new user joining channel (far server)", "JOIN") 59 | m.expect(c3a, "should start a BATCH", " BATCH \+[^ ]+ chathistory " + chan) 60 | m.expect(c3a, "history playback: 1st message", ":c1a.* PRIVMSG .* :one") 61 | m.expect(c3a, "history playback: 2nd message should have colors stripped", ":c1a.* PRIVMSG .* :red two") 62 | m.expect(c3a, "history playback: 9th message is altered", ":c2a.* PRIVMSG.*nine ") 63 | m.expect(c3a, "history playback: 10th message", ":c2a.* PRIVMSG .* :ten") 64 | m.expect(c3a, "all playback should be wrapped in a batch (1 of 10)", ".*batch=.+ PRIVMSG .* :one") 65 | m.expect(c3a, "all playback should be wrapped in a batch (2 of 10)", ".*batch=.+ PRIVMSG .* :red two") 66 | m.expect(c3a, "all playback should be wrapped in a batch (3 of 10)", ".*batch=.+ PRIVMSG .* :three") 67 | m.expect(c3a, "all playback should be wrapped in a batch (4 of 10)", ".*batch=.+ PRIVMSG .* :four") 68 | m.expect(c3a, "all playback should be wrapped in a batch (5 of 10)", ".*batch=.+ PRIVMSG .* :five") 69 | m.expect(c3a, "all playback should be wrapped in a batch (6 of 10)", ".*batch=.+ PRIVMSG .* :six") 70 | m.expect(c3a, "all playback should be wrapped in a batch (7 of 10)", ".*batch=.+ PRIVMSG .* :seven") 71 | m.expect(c3a, "all playback should be wrapped in a batch (8 of 10)", ".*batch=.+ PRIVMSG .* :eight") 72 | m.expect(c3a, "all playback should be wrapped in a batch (9 of 10)", ".*batch=.+ PRIVMSG .* :nine ") 73 | m.expect(c3a, "all playback should be wrapped in a batch (10 of 10)", ".*batch=.+ PRIVMSG .* :ten") 74 | m.not_expect(c3a, "history playback: should not see wrapped message (message zero)", "PRIVMSG.*should be wrapped") 75 | m.expect(c3a, "should end the BATCH", " BATCH -[^ ]+") 76 | m.clearlog() 77 | print 78 | 79 | ### We can't test this anymore now that the time unit is in minutes, 80 | ### otherwise the entire test framework would have to wait a full minute which is not acceptable. 81 | #time.sleep(8) 82 | #m.send(c3b, "JOIN " + chan) 83 | #m.expect(c3b, "new user joining channel (far server, after history expire)", "JOIN") 84 | #m.not_expect(c3b, "should not see any history (expired)", ".*PRIVMSG.*") 85 | #print 86 | -------------------------------------------------------------------------------- /tests/db/writing/history: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | import time 4 | 5 | m = irctestframework.irctest.IrcTest() 6 | c1a = m.new('c1a') 7 | c1b = m.new('c1b') 8 | c2a = m.new('c2a') 9 | c3a = m.new('c3a') 10 | c3b = m.new('c3b') 11 | m.connect() 12 | 13 | m.send_all("CAP REQ server-time") 14 | m.send(c3a, "CAP REQ batch") 15 | print 16 | 17 | chan = "#history_test" 18 | m.send(c2a, "JOIN " + chan) # first user with ops 19 | m.send(c1a, "JOIN " + chan) 20 | m.expect(c1a, "users in channel", "JOIN") 21 | m.clearlog() 22 | print 23 | 24 | # Set history channel mode: save 10 lines for 600 minutes 25 | m.send(c2a, "MODE " + chan + " +SGH 10:600") 26 | m.expect(c1a, "MODE +H", ":c2a.*MODE.*\+GSH 10:10h") 27 | m.send(c2a, "OPER netadmin test") 28 | m.send(c2a, "MODE " + chan + " +P") 29 | m.expect(c1a, "MODE +P", ":c2a.*MODE.*\+P") 30 | m.clearlog() 31 | print 32 | 33 | m.send(c1a, "PRIVMSG " + chan + " :should be wrapped") 34 | m.send(c1a, "PRIVMSG " + chan + " :one") 35 | m.send(c1a, "PRIVMSG " + chan + " :\0034red two\003") # will be stripped 36 | m.send(c1a, "PRIVMSG " + chan + " :three") 37 | m.send(c1a, "PRIVMSG " + chan + " :four") 38 | m.send(c1a, "PRIVMSG " + chan + " :five") 39 | m.send(c2a, "PRIVMSG " + chan + " :six") 40 | m.send(c2a, "PRIVMSG " + chan + " :seven") 41 | m.send(c2a, "PRIVMSG " + chan + " :eight") 42 | m.send(c2a, "PRIVMSG " + chan + " :nine fuck") # will be stripped 43 | m.send(c2a, "PRIVMSG " + chan + " :ten") 44 | m.expect(c2a, "Message with stripped color", "PRIVMSG .*:red two") 45 | m.not_expect(c1a, "Message with censored message", "PRIVMSG.*nine fuck") 46 | m.clearlog() 47 | print 48 | 49 | m.send(c1b, "JOIN " + chan) 50 | m.expect(c1b, "new user joining channel (same server)", "JOIN") 51 | m.expect(c1b, "history playback: 1st message", ":c1a.* PRIVMSG .* :one") 52 | m.expect(c1b, "history playback: 2nd message should have colors stripped", ":c1a.* PRIVMSG .* :red two") 53 | m.expect(c1b, "history playback: 9th message is altered", ":c2a.* PRIVMSG.*nine ") 54 | m.expect(c1b, "history playback: 10th message", ":c2a.* PRIVMSG .* :ten") 55 | m.not_expect(c1b, "history playback: should not see wrapped message (message zero)", "PRIVMSG.*should be wrapped") 56 | m.not_expect(c1b, "playback should not see a BATCH if not supported", ".*BATCH.*") 57 | # do not clear here, so we can see any potential inconsistency with the other playback.. 58 | print 59 | 60 | m.send(c3a, "JOIN " + chan) 61 | m.expect(c3a, "new user joining channel (far server)", "JOIN") 62 | m.expect(c3a, "should start a BATCH", " BATCH \+[^ ]+ chathistory " + chan) 63 | m.expect(c3a, "history playback: 1st message", ":c1a.* PRIVMSG .* :one") 64 | m.expect(c3a, "history playback: 2nd message should have colors stripped", ":c1a.* PRIVMSG .* :red two") 65 | m.expect(c3a, "history playback: 9th message is altered", ":c2a.* PRIVMSG.*nine ") 66 | m.expect(c3a, "history playback: 10th message", ":c2a.* PRIVMSG .* :ten") 67 | m.expect(c3a, "all playback should be wrapped in a batch (1 of 10)", ".*batch=.+ PRIVMSG .* :one") 68 | m.expect(c3a, "all playback should be wrapped in a batch (2 of 10)", ".*batch=.+ PRIVMSG .* :red two") 69 | m.expect(c3a, "all playback should be wrapped in a batch (3 of 10)", ".*batch=.+ PRIVMSG .* :three") 70 | m.expect(c3a, "all playback should be wrapped in a batch (4 of 10)", ".*batch=.+ PRIVMSG .* :four") 71 | m.expect(c3a, "all playback should be wrapped in a batch (5 of 10)", ".*batch=.+ PRIVMSG .* :five") 72 | m.expect(c3a, "all playback should be wrapped in a batch (6 of 10)", ".*batch=.+ PRIVMSG .* :six") 73 | m.expect(c3a, "all playback should be wrapped in a batch (7 of 10)", ".*batch=.+ PRIVMSG .* :seven") 74 | m.expect(c3a, "all playback should be wrapped in a batch (8 of 10)", ".*batch=.+ PRIVMSG .* :eight") 75 | m.expect(c3a, "all playback should be wrapped in a batch (9 of 10)", ".*batch=.+ PRIVMSG .* :nine ") 76 | m.expect(c3a, "all playback should be wrapped in a batch (10 of 10)", ".*batch=.+ PRIVMSG .* :ten") 77 | m.not_expect(c3a, "history playback: should not see wrapped message (message zero)", "PRIVMSG.*should be wrapped") 78 | m.expect(c3a, "should end the BATCH", " BATCH -[^ ]+") 79 | m.clearlog() 80 | print 81 | 82 | ### We can't test this anymore now that the time unit is in minutes, 83 | ### otherwise the entire test framework would have to wait a full minute which is not acceptable. 84 | #time.sleep(8) 85 | #m.send(c3b, "JOIN " + chan) 86 | #m.expect(c3b, "new user joining channel (far server, after history expire)", "JOIN") 87 | #m.not_expect(c3b, "should not see any history (expired)", ".*PRIVMSG.*") 88 | #print 89 | -------------------------------------------------------------------------------- /tests/chanmodes/delayjoin: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | m = irctestframework.irctest.IrcTest() 5 | c1a = m.new('c1a') 6 | c2a = m.new('c2a') 7 | c3a = m.new('c3a') 8 | c3b = m.new('c3b') 9 | m.connect() 10 | 11 | chan = m.randchan() 12 | m.send(c1a, "JOIN " + chan) 13 | m.send(c1a, "MODE " + chan + " +D") 14 | m.expect(c1a, "MODE +D", "MODE.*\+D") 15 | print 16 | 17 | # Now join the rest 18 | m.send(c2a, "JOIN " + chan) 19 | m.send(c3a, "JOIN " + chan) 20 | m.send(c3b, "JOIN " + chan) 21 | m.expect(c1a, "Chanop should see all joins (1 of 2)", ":c2a.*JOIN") 22 | m.expect(c1a, "Chanop should see all joins (2 of 2)", ":c3a.*JOIN") 23 | m.not_expect(c2a, "Non-chanop should not see joins", ":c3a.*JOIN") 24 | m.not_expect(c3a, "Non-chanop should not see joins", ":c3b.*JOIN") 25 | print 26 | m.clearlog() 27 | 28 | # Quick part test 29 | m.send(c3b, "PART " + chan) 30 | m.send(c3a, "PART " + chan) 31 | m.send(c2a, "PART " + chan) 32 | m.expect(c1a, "Chanop should see all parts (1 of 2)", ":c2a.*PART") 33 | m.expect(c1a, "Chanop should see all parts (2 of 2)", ":c3a.*PART") 34 | m.not_expect(c3a, "Non-chanop should not see parts", ":c3b.*PART") 35 | m.not_expect(c2a, "Non-chanop should not see parts", ":c3a.*PART") 36 | print 37 | m.clearlog() 38 | 39 | # Re-join them again (This identical to 'Now join the rest' from earlier) 40 | m.send(c2a, "JOIN " + chan) 41 | m.send(c3a, "JOIN " + chan) 42 | m.send(c3b, "JOIN " + chan) 43 | m.expect(c1a, "Chanop should see all joins (1 of 2)", ":c2a.*JOIN") 44 | m.expect(c1a, "Chanop should see all joins (2 of 2)", ":c3a.*JOIN") 45 | m.not_expect(c2a, "Non-chanop should not see joins", ":c3a.*JOIN") 46 | m.not_expect(c3a, "Non-chanop should not see joins", ":c3b.*JOIN") 47 | print 48 | m.clearlog() 49 | 50 | # Make one user visible... 51 | # For chanops this should result in a: PRIVMSG 52 | # For non-chansop this should result in a: JOIN, PRIVMSG 53 | m.send(c3b, "PRIVMSG " + chan + " :make me visible") 54 | m.not_expect(c1a, "When user msgs for the first time, chanop should not see duplicate joins", ":c3b.*JOIN") 55 | m.not_expect(c3b, "When we send a msg for the first time, we should not see a self-join", ":c3b.*JOIN") 56 | m.expect(c3a, "When user msgs for the first time, we should see the user joining (local)", ":c3b.*JOIN") 57 | m.expect(c2a, "When user msgs for the first time, we should see the user joining (remote)", ":c3b.*JOIN") 58 | print 59 | m.clearlog() 60 | 61 | # ... and make the user part. This should result in a PART to be shown to all channel members (ops & non-ops) 62 | m.send(c3b, "PART " + chan) 63 | m.expect_all("PART from visible channel member", ":c3b.*PART") 64 | print 65 | m.clearlog() 66 | 67 | # And make the user join again so we can continue tests... 68 | m.send(c3b, "JOIN " + chan) 69 | m.expect(c1a, "Chanop should see join", ":c3b.*JOIN") 70 | print 71 | m.clearlog() 72 | 73 | # Mode +v should expose the user 74 | m.send(c1a, "MODE " + chan + " +v $c2a") 75 | m.not_expect(c1a, "When doing +v on user, chanop should not see duplicate joins", ":c2a.*JOIN") 76 | m.not_expect(c2a, "When doing +v on user, and we are the affected user, we should not see a self-join", ":c2a.*JOIN") 77 | m.expect(c3a, "When doing +v on a user, we should see the user joining", ":c2a.*JOIN") 78 | print 79 | m.clearlog() 80 | 81 | # Message should expose the user 82 | m.send(c3b, "PRIVMSG " + chan + " :hello everyone") 83 | m.not_expect(c1a, "When user msgs for the first time, chanop should not see duplicate joins", ":c3b.*JOIN") 84 | m.not_expect(c3b, "When we send a msg for the first time, we should not see a self-join", ":c3b.*JOIN") 85 | m.expect(c3a, "When user msgs for the first time, we should see the user joining (local)", ":c3b.*JOIN") 86 | m.expect(c2a, "When user msgs for the first time, we should see the user joining (remote)", ":c3b.*JOIN") 87 | print 88 | m.clearlog() 89 | 90 | # Another message should not do anything special 91 | m.send(c3b, "PRIVMSG " + chan + " :second message") 92 | m.not_expect_all("On second message there should not be any (duplicate) JOIN", ":c3b.*JOIN") 93 | print 94 | m.clearlog() 95 | 96 | #### Below we test unsetting of the mode #### 97 | 98 | m.send(c1a, "MODE " + chan + " -D") 99 | m.expect(c1a, "MODE -D", "MODE.*\-D") 100 | m.expect_all("MODE +d when there are invisible users", "MODE.*\+d") 101 | print 102 | m.clearlog() 103 | 104 | m.send(c3a, "PRIVMSG " + chan + " :i am the last invisible client") 105 | m.not_expect(c1a, "When user msgs for the first time (even if chan is -D+d) chanop should not see duplicate joins", ":c3a.*JOIN") 106 | m.not_expect(c3a, "When we send a msg for the first time (even if chan is -D+d) we should not see a self-join", ":c3a.*JOIN") 107 | m.expect(c3b, "When user msgs for the first time (even if chan is -D+d) we should see the user joining (local)", ":c3a.*JOIN") 108 | m.expect(c2a, "When user msgs for the first time (even if chan is -D+d) we should see the user joining (remote)", ":c3a.*JOIN") 109 | m.expect_all("MODE -d now that there are no remaining invisible users", "MODE.*\-d") 110 | print 111 | -------------------------------------------------------------------------------- /tests/serial/netsplit_merge: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | 4 | clones_per_server = 75 5 | bans_per_server = 40 6 | servers = { 'c1', 'c2', 'c3' } 7 | clones = {} 8 | 9 | m = irctestframework.irctest.IrcTest() 10 | 11 | c1o = m.new('c1o') 12 | c2o = m.new('c2o') 13 | c3o = m.new('c3o') 14 | 15 | for s in servers: 16 | for i in range(1, clones_per_server+1): 17 | name = s + '-' + str(i) 18 | clones[name] = m.new(name) 19 | 20 | m.connect() 21 | m.send(c1o, "OPER netadmin test") 22 | m.send(c2o, "OPER netadmin test") 23 | m.send(c3o, "OPER netadmin test") 24 | m.clearlog() 25 | 26 | chan = m.randchan() 27 | m.send(c1o, "JOIN " + chan) 28 | m.send(c1o, "MODE " + chan + " +F off") 29 | m.join_all(chan, skip = c1o) 30 | m.expect_all("see join", ":$me.*JOIN.*") 31 | m.clearlog() 32 | print 33 | 34 | # Put channel -F so we can check that join-flood protection 35 | # isn't triggered by netmerge later 36 | m.send(c1o, "MODE " + chan + " -F") 37 | m.clearlog() 38 | 39 | m.send_all("NAMES " + chan) 40 | for src in clones: 41 | for dst in clones: 42 | m.expect(clones[src], "see all other clones in channel", clones[dst].nick) 43 | m.clearlog() 44 | print 45 | 46 | # SQUIT servers 47 | m.sync = 0 48 | m.disable_message_tags_check = True 49 | for s in [c1o, c3o]: 50 | m.send(s, "SQUIT irc2.test.net") 51 | m.send(s, "MAP") 52 | m.expect(s, "End of /MAP", "007.*End of", timeout = 10) 53 | m.not_expect(s, "Server gone, should not show up in MAP", " 006 .*irc2\.test\.net") 54 | 55 | # Verify that all users on other servers disappeared (a proper QUIT was sent) 56 | for s in servers: 57 | for i in range(1, clones_per_server+1): 58 | s_name = s + '-' + str(i) 59 | for d in servers: 60 | if s == d: 61 | continue 62 | for j in range(1, clones_per_server+1): 63 | d_name = d + '-' + str(j) 64 | m.expect(clones[s_name], "QUIT", ":" + d_name + ".*QUIT :irc", timeout=15) 65 | m.clearlog() 66 | print 67 | 68 | for i in range(1, bans_per_server+1): 69 | banid = "ban"+str(i)+"!" 70 | m.send(c1o, "MODE " + chan + " +b " + banid + "*@c1.test.net") 71 | m.send(c2o, "MODE " + chan + " +b " + banid + "*@c2.test.net") 72 | m.send(c3o, "MODE " + chan + " +b " + banid + "*@c3.test.net") 73 | m.expect(c1o, "MODE", "MODE.*"+banid, timeout=10) 74 | m.expect(c2o, "MODE", "MODE.*"+banid, timeout=10) 75 | m.expect(c3o, "MODE", "MODE.*"+banid, timeout=10) 76 | m.clearlog() 77 | 78 | m.clearlog() 79 | 80 | # CONNECT servers 81 | for s in [c1o, c3o]: 82 | m.send(s, "CONNECT irc2.test.net") 83 | m.expect(s, "ircX<->irc2 should be linked", "Link irc[0-9].test.net -> irc2.test.net is now synced", timeout=30) 84 | m.send(s, "MAP") 85 | m.expect(s, "End of /MAP", "007.*End of", timeout = 10) 86 | m.expect(s, "Server connected, should show up in MAP", " 006 .*irc2\.test\.net") 87 | 88 | # Verify that all users on other servers appeared again (a proper JOIN was sent) 89 | for s in servers: 90 | for i in range(1, clones_per_server+1): 91 | s_name = s + '-' + str(i) 92 | for d in servers: 93 | if s == d: 94 | continue 95 | for j in range(1, clones_per_server+1): 96 | d_name = d + '-' + str(j) 97 | m.expect(clones[s_name], "JOIN on netsync: check for " + d_name, ":" + d_name + ".*JOIN", timeout=15) 98 | 99 | # Verify all MODEs for bans were seen too 100 | for s in servers: 101 | for i in range(1, clones_per_server+1): 102 | s_name = s + '-' + str(i) 103 | for d in servers: 104 | if s == d: 105 | continue 106 | for j in range(1, bans_per_server+1): 107 | banid = "ban"+str(j)+"!\\*@" + d + ".test.net" 108 | # ^ nice.. need to escape the * there to \\* since we are feeding it to regex: 109 | m.expect(clones[s_name], "MODE +b on netsync: "+banid, "MODE.*"+banid, timeout=15) 110 | m.clearlog() 111 | print 112 | 113 | # Restore syncing 114 | m.sync = 1 115 | m.disable_message_tags_check = False 116 | 117 | # Check if NAMES verifies that everyone is in the channel 118 | m.send_all("NAMES " + chan) 119 | for src in clones: 120 | for dst in clones: 121 | m.expect(clones[src], "see all other clones in channel after synced", clones[dst].nick) 122 | m.clearlog() 123 | print 124 | 125 | # Check if banlist shows all bans are set as well (with correct "set by" field) 126 | # - the three opers on the servers can handle this, no need to query all XYZ clones again. 127 | for name in [c1o, c2o, c3o]: 128 | m.send(name, "MODE " + chan + " b") 129 | for d in servers: 130 | for j in range(1, bans_per_server+1): 131 | banid = "ban"+str(j)+"!\\*@" + d + ".test.net" 132 | # ^ nice.. need to escape the * there to \\* since we are feeding it to regex: 133 | m.expect(name, "Banlist shows ban " +banid, " 367 .*"+banid) 134 | m.clearlog() 135 | print 136 | -------------------------------------------------------------------------------- /tests/opercommands/tkl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # 3 | # This tests TKLs such as: KLINE, ZLINE, GLINE, GZLINE, SPAMFILTER 4 | # 5 | import irctestframework.irctest 6 | 7 | m = irctestframework.irctest.IrcTest() 8 | c1a = m.new('c1a') 9 | c2a = m.new('c2a') 10 | c3a = m.new('c3a') 11 | m.connect() 12 | 13 | m.send_all("OPER netadmin test") 14 | 15 | ##### LOCAL TKLS ###### 16 | 17 | ### KLINE on host 18 | m.send(c1a, "KLINE user@some.host 60 This is a kline test") 19 | regex = "K-Line added: 'user@some\.host' \[reason: This is a kline test\] \[by: $c1a.*\]" 20 | m.expect(c1a, "K-Line added notice to local IRCOps", regex) 21 | m.not_expect_all("K-Line added notice NOT to remote IRCOps", regex, skip=c1a) 22 | m.clearlog() 23 | print 24 | 25 | m.send_all("STATS kline") 26 | regex = "223.*K user@some\.host [0-9][0-9] [0-9] c1a.* :This is a kline test" 27 | m.expect(c1a, "K-Line shown in /STATS kline locally", regex) 28 | m.not_expect_all("K-Line NOT shown in /STATS kline on remote servers", regex, skip=c1a) 29 | m.clearlog() 30 | print 31 | 32 | m.send(c1a, "KLINE -user@some.host") 33 | regex = "K-Line removed: 'user@some\.host' \[reason: This is a kline test\] \[by: $c1a.*\]" 34 | m.expect(c1a, "K-Line removed notice shown to local IRCOps", regex) 35 | m.not_expect_all("K-Line removed notice NOT shown to IRCOps on remote servers", regex, skip=c1a) 36 | m.clearlog() 37 | print 38 | 39 | ### ZLINE on host 40 | m.send(c1a, "ZLINE *@4.3.2.1 60 This is a zline test") 41 | regex = "Z-Line added: '\*@4\.3\.2\.1' \[reason: This is a zline test\] \[by: $c1a.*\]" 42 | m.expect(c1a, "Z-Line added notice to local IRCOps", regex) 43 | m.not_expect_all("Z-Line added notice NOT to remote IRCOps", regex, skip=c1a) 44 | m.clearlog() 45 | print 46 | 47 | m.send_all("STATS kline") 48 | regex = "223.*z \*@4\.3\.2\.1 [0-9][0-9] [0-9] c1a.* :This is a zline test" 49 | m.expect(c1a, "Z-Line shown in /STATS zline locally", regex) 50 | m.not_expect_all("Z-Line NOT shown in /STATS zline on remote servers", regex, skip=c1a) 51 | m.clearlog() 52 | print 53 | 54 | m.send(c1a, "ZLINE -*@4.3.2.1") 55 | regex = "Z-Line removed: '\*@4\.3\.2\.1' \[reason: This is a zline test\] \[by: $c1a.*\]" 56 | m.expect(c1a, "Z-Line removed notice shown to local IRCOps", regex) 57 | m.not_expect_all("Z-Line removed notice NOT shown to IRCOps on remote servers", regex, skip=c1a) 58 | m.clearlog() 59 | print 60 | 61 | ##### GLOBAL TKLS ###### 62 | 63 | ### GLINE on host 64 | m.send(c1a, "GLINE user@some.host 60 This is a gline test") 65 | m.expect_all("G-Line added notice to IRCOps", 66 | "G-Line added: 'user@some\.host' \[reason: This is a gline test\] \[by: $c1a.*\]") 67 | m.clearlog() 68 | print 69 | 70 | m.send_all("STATS gline") 71 | m.expect_all("G-Line shown in /STATS gline", 72 | "223.*G user@some\.host [0-9][0-9] [0-9] c1a.* :This is a gline test") 73 | m.clearlog() 74 | print 75 | 76 | m.send(c1a, "GLINE -user@some.host") 77 | m.expect_all("G-Line removed notice to IRCOps", 78 | "G-Line removed: 'user@some\.host' \[reason: This is a gline test\] \[by: $c1a.*\]") 79 | m.clearlog() 80 | print 81 | 82 | ### GLINE on ip 83 | m.send(c1a, "GLINE user@4.3.2.1 60 This is a gline test on IP") 84 | m.expect_all("G-Line added notice to IRCOps", 85 | "G-Line added: 'user@4\.3\.2\.1' \[reason: This is a gline test on IP\] \[by: $c1a.*\]") 86 | m.clearlog() 87 | print 88 | 89 | m.send_all("STATS gline") 90 | m.expect_all("G-Line shown in /STATS gline", 91 | "223.*G user@4\.3\.2\.1 [0-9][0-9] [0-9] c1a.* :This is a gline test on IP") 92 | m.clearlog() 93 | print 94 | 95 | m.send(c1a, "GLINE -user@4.3.2.1") 96 | m.expect_all("G-Line removed notice to IRCOps", 97 | "G-Line removed: 'user@4\.3\.2\.1' \[reason: This is a gline test on IP\] \[by: $c1a.*\]") 98 | m.clearlog() 99 | print 100 | 101 | ### GZLINE on ip 102 | m.send(c1a, "GZLINE *@4.3.2.1 60 This is a gzline test on IP") 103 | m.expect_all("GZ-Line added notice to IRCOps", 104 | "Global Z-Line added: '\*@4\.3\.2\.1' \[reason: This is a gzline test on IP\] \[by: $c1a.*\]") 105 | m.clearlog() 106 | print 107 | 108 | m.send_all("STATS gline") 109 | m.expect_all("GZ-Line shown in /STATS gline", 110 | "223.*Z \*@4\.3\.2\.1 [0-9][0-9] [0-9] c1a.* :This is a gzline test on IP") 111 | m.clearlog() 112 | print 113 | 114 | m.send(c1a, "GZLINE -*@4.3.2.1") 115 | m.expect_all("GZ-Line removed notice to IRCOps", 116 | "Global Z-Line removed: '\*@4\.3\.2\.1' \[reason: This is a gzline test on IP\] \[by: $c1a.*\]") 117 | m.clearlog() 118 | print 119 | 120 | ### Spamfilter 121 | m.send(c1a, "SPAMFILTER add -simple p gzline 0 this_is_a_test Please gzline me") 122 | m.expect_all("Spamfilter added notice to IRCOps", 123 | "Spamfilter added: 'Please gzline me' \[type: simple\] \[targets: p\] \[action: gzline\] \[reason: this is a test\] \[by: $c1a.*\]") 124 | m.clearlog() 125 | print 126 | 127 | m.send_all("STATS spamfilter") 128 | m.expect_all("Spamfilter shown in /STATS spamfilter", 129 | "229.* F simple p gzline 0 [0-9]* 0 this_is_a_test c1a[^ ]+ [0-9]+ [0-9]+ :Please gzline me") 130 | m.clearlog() 131 | print 132 | 133 | m.send(c1a, "SPAMFILTER del -simple p gzline - - Please gzline me") 134 | m.expect_all("Spamfilter removed notice to IRCOps", 135 | "Spamfilter removed: 'Please gzline me' \[type: simple\] \[targets: p\] \[action: gzline\] \[reason: this is a test\] \[by: $c1a.*\]") 136 | m.clearlog() 137 | print 138 | 139 | -------------------------------------------------------------------------------- /serverconfig/unrealircd/common.conf: -------------------------------------------------------------------------------- 1 | /*** Common configuration file for test suite ***/ 2 | /*** This is NOT suitable for production!!! ***/ 3 | 4 | include "modules.default.conf"; 5 | include "modules.optional.conf"; 6 | include "snomasks.default.conf"; 7 | include "help/help.conf"; 8 | include "badwords.conf"; 9 | include "spamfilter.conf"; 10 | include "operclass.default.conf"; 11 | 12 | loadmodule "cloak_sha256"; 13 | 14 | admin { 15 | "Test Network"; 16 | "!NOT FOR PRODUCTION!"; 17 | }; 18 | 19 | class clients { 20 | pingfreq 90; 21 | maxclients 2048; 22 | sendq 100000; 23 | options { nofakelag; }; 24 | }; 25 | 26 | class opers 27 | { 28 | pingfreq 90; 29 | maxclients 50; 30 | sendq 1M; 31 | recvq 8000; 32 | }; 33 | 34 | class servers 35 | { 36 | pingfreq 60; 37 | connfreq 15; /* try to connect every 15 seconds */ 38 | maxclients 10; /* max servers */ 39 | sendq 5M; 40 | }; 41 | 42 | allow { 43 | mask "*@*"; 44 | class clients; 45 | maxperip 2048; 46 | }; 47 | 48 | oper test { 49 | class opers; 50 | mask *@*; 51 | password "test"; 52 | operclass netadmin-with-override; 53 | swhois "is a Network Administrator"; 54 | vhost netadmin.test.net; 55 | }; 56 | 57 | oper netadmin { 58 | mask *@127.0.0.1; 59 | password "test"; 60 | class clients; 61 | operclass netadmin-with-override; 62 | vhost "netadmin.test.net"; 63 | swhois "is a Network Administrator"; 64 | }; 65 | 66 | oper netadmin-badhost { 67 | mask *@127.0.0.5; 68 | password "test"; 69 | class clients; 70 | operclass netadmin-with-override; 71 | vhost "netadmin.test.net"; 72 | swhois "is a Network Administrator"; 73 | }; 74 | 75 | oper globop { 76 | mask *@127.0.0.1; 77 | password "test"; 78 | class clients; 79 | operclass globop-with-override; 80 | vhost "globop.test.net"; 81 | }; 82 | 83 | oper locop { 84 | mask *@127.0.0.1; 85 | password "test"; 86 | class clients; 87 | operclass locop; 88 | vhost "locop.test.net"; 89 | }; 90 | 91 | link services.test.net 92 | { 93 | incoming { 94 | mask 127.0.0.1; 95 | }; 96 | 97 | password "test"; 98 | 99 | class servers; 100 | }; 101 | 102 | ulines { 103 | services.test.net; 104 | }; 105 | 106 | drpass { 107 | restart "restart"; 108 | die "die"; 109 | }; 110 | 111 | include "aliases/anope.conf"; 112 | 113 | ban nick { 114 | mask "*C*h*a*n*S*e*r*v*"; 115 | reason "Reserved for Services"; 116 | }; 117 | 118 | ban ip { 119 | mask 195.86.232.81; 120 | reason "Hate you"; 121 | }; 122 | 123 | ban server { 124 | mask eris.berkeley.edu; 125 | reason "Get out of here."; 126 | }; 127 | 128 | ban user { 129 | mask *tirc@*.saturn.bbn.com; 130 | reason "Idiot"; 131 | }; 132 | 133 | ban realname { 134 | mask "Swat Team"; 135 | reason "mIRKFORCE"; 136 | }; 137 | 138 | except ban { 139 | mask *@127.0.0.1; 140 | }; 141 | 142 | deny dcc { 143 | filename "*sub7*"; 144 | reason "Possible Sub7 Virus"; 145 | }; 146 | 147 | deny dcc { 148 | filename "*.exe"; 149 | soft yes; 150 | reason "Executable files may be dangerous"; 151 | }; 152 | 153 | deny channel { 154 | channel "*warez*"; 155 | reason "Warez is illegal"; 156 | class "clients"; 157 | }; 158 | 159 | vhost { 160 | vhost this.is.a.test; 161 | mask *@127.0.0.1; 162 | login test; 163 | password test; 164 | swhois "likes to test things"; 165 | }; 166 | 167 | set { 168 | network-name "TestNet"; 169 | default-server "irc.test.net"; 170 | services-server "services.test.net"; 171 | sasl-server "services.test.net"; 172 | stats-server "stats.test.net"; 173 | help-channel "#Help"; 174 | hiddenhost-prefix "Clk"; 175 | prefix-quit "Quit"; 176 | cloak-keys { 177 | /* Only use this for this test network. Don't copy these! */ 178 | "Q71kCDAqmT1FqNl3hsQAskLksBd5HiHP3OG3ai077MpVEn2whUQeTThxD3T8lw1XjwWDjQ1W8U1t2uCP"; 179 | "obr42bf4H6h68784hg2JI6qePVl40D3oMedr02aj3a64d251NKgrl1icdr0q4fQVbRJf11224GoMGySd"; 180 | "Xudc2KqmsPMc43X7Ddx826Qn0l346Ax0d67h6G38js1pIhM0n5XT0u8m1T62wS66DTt461uBU4Q56P0N"; 181 | }; 182 | kline-address "test@example.org"; 183 | modes-on-connect "+ixw"; 184 | modes-on-oper "+xwgs"; 185 | modes-on-join "+"; /* for easy testing */ 186 | options { 187 | hide-ulines; 188 | }; 189 | 190 | maxchannelsperuser 10; 191 | 192 | anti-spam-quit-message-time 5s; 193 | 194 | /* These flood protection features need to be disabled for the tests: */ 195 | anti-flood { 196 | everyone { 197 | connect-flood 250:1; 198 | target-flood { 199 | channel-privmsg 1000:1; 200 | channel-notice 30:2; 201 | channel-tagmsg 20:2; 202 | private-privmsg 1000:1; 203 | private-notice 30:4; 204 | private-tagmsg 20:2; 205 | }; 206 | } 207 | known-users { 208 | join-flood 250:10; 209 | } 210 | unknown-users { 211 | join-flood 250:10; 212 | } 213 | channel { 214 | boot-delay 0; /* this interfers with our tests */ 215 | split-delay 0; /* same */ 216 | } 217 | }; 218 | handshake-delay 0; 219 | max-unknown-connections-per-ip 99; 220 | 221 | spamfilter { 222 | ban-time 1d; 223 | ban-reason "Spam/Advertising"; 224 | virus-help-channel "#help"; 225 | }; 226 | 227 | ping-cookie no; /* annoying with debugging */ 228 | 229 | }; 230 | 231 | /* These interfer with the 'inconsistent message tags' detection (FIXME!!) */ 232 | blacklist-module "userip-tag"; 233 | blacklist-module "userhost-tag"; 234 | blacklist-module "issued-by-tag"; 235 | 236 | /* This one really needs to be blacklisted since we 237 | * connect a large number of 'new connections' 238 | */ 239 | blacklist-module "connthrottle"; 240 | 241 | /* And this allows setting fake reputation by any unprivileged user. 242 | * Again, don't use this on a live network, it is only for the test suite. 243 | */ 244 | loadmodule "third/fakereputation"; 245 | -------------------------------------------------------------------------------- /tests/chanmodes/flood: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import irctestframework.irctest 3 | import time 4 | 5 | # TODO: more +f sub-tests 6 | 7 | m = irctestframework.irctest.IrcTest() 8 | c1a = m.new('c1a') 9 | c2a = m.new('c2a') 10 | c3a = m.new('c3a') 11 | m.connect() 12 | 13 | # This forces the clients as 'known-users'... 14 | # TODO: also test 'unknown-users' style bans 15 | m.send(c1a, "FAKEREPUTATION 25") 16 | m.send(c2a, "FAKEREPUTATION 25") 17 | m.send(c3a, "FAKEREPUTATION 25") 18 | 19 | 20 | chan = m.randchan() 21 | m.send(c1a, "JOIN " + chan) 22 | m.expect(c1a, "users in channel", "JOIN") 23 | m.clearlog() 24 | print 25 | 26 | # knock-flood: +f [1k]:15 27 | m.send(c1a, "MODE " + chan + " +fi [1k]:15") 28 | m.expect(c1a, "MODE set", ":c1a.*MODE.*f.*\[1k\]:15") 29 | m.clearlog() 30 | print 31 | m.send(c2a, "KNOCK " + chan) 32 | m.send(c3a, "KNOCK " + chan) 33 | m.expect(c1a, "should send warning on flood", ":irc.* NOTICE %" + chan + " :\*\*\* Channel knockflood detected \(limit is 1 per 15 seconds\), setting mode \+K") 34 | m.expect(c1a, "should set MODE on flood", ":irc.* MODE " + chan + " \+K") 35 | m.clearlog() 36 | print 37 | 38 | # join-flood: +f [1j]:15 39 | m.send(c1a, "MODE " + chan + " -iK+f [1j]:15") 40 | m.expect(c1a, "MODE set", ":c1a.*MODE.*f.*\[1j\]:15") 41 | m.clearlog() 42 | print 43 | m.send(c2a, "JOIN " + chan) 44 | m.send(c3a, "JOIN " + chan) 45 | m.expect(c1a, "should send warning on flood", ":irc.* NOTICE %" + chan + " :\*\*\* Channel joinflood detected \(limit is 1 per 15 seconds\), setting mode \+i", timeout = 5) 46 | m.expect(c1a, "should set MODE on flood", ":irc.* MODE " + chan + " \+i", timeout = 5) 47 | m.clearlog() 48 | print 49 | 50 | # message-flood: +f [2m]:15 51 | m.send(c1a, "MODE " + chan + " -i+f [2m]:15") 52 | m.expect_all("MODE set", ":c1a.*MODE.*f.*\[2m\]:15") 53 | m.clearlog() 54 | print 55 | m.send(c2a, "PRIVMSG " + chan + " :message one") 56 | m.send(c3a, "PRIVMSG " + chan + " :message two") 57 | m.not_expect_all("no warning if limit not reached yet", "flood detected"); 58 | m.send(c2a, "PRIVMSG " + chan + " :message three") 59 | m.expect(c1a, "should send warning on flood", ":irc.* NOTICE %" + chan + " :\*\*\* Channel msg/noticeflood detected \(limit is 2 per 15 seconds\), setting mode \+m", timeout = 5) 60 | m.expect(c1a, "should set MODE on flood", ":irc.* MODE " + chan + " \+m", timeout = 5) 61 | m.clearlog() 62 | print 63 | 64 | # ctcp-flood: +f [2c]:15 65 | m.send(c1a, "MODE " + chan + " -m+f [2c]:15") 66 | m.expect_all("MODE set", ":c1a.*MODE.*f.*\[2c\]:15") 67 | m.clearlog() 68 | print 69 | m.send(c2a, "PRIVMSG " + chan + " :message one") 70 | m.send(c3a, "PRIVMSG " + chan + " :message two") 71 | m.send(c2a, "PRIVMSG " + chan + " :message three") 72 | m.not_expect_all("no warning on non-CTCP", "flood detected"); 73 | m.clearlog() 74 | print 75 | m.send(c2a, "PRIVMSG " + chan + " :\001PING\001") 76 | m.send(c3a, "PRIVMSG " + chan + " :\001PING\001") 77 | m.not_expect_all("no warning if limit not reached yet", "flood detected"); 78 | m.send(c2a, "PRIVMSG " + chan + " :\001PING\001") 79 | m.expect(c1a, "should send warning on flood", ":irc.* NOTICE %" + chan + " :\*\*\* Channel CTCPflood detected \(limit is 2 per 15 seconds\), setting mode \+C", timeout = 5) 80 | m.expect(c1a, "should set MODE on flood", ":irc.* MODE " + chan + " \+C", timeout = 5) 81 | m.clearlog() 82 | print 83 | 84 | # nick-flood: +f [1n]:15 85 | m.send(c1a, "MODE " + chan + " -C+f [1n]:15") 86 | m.expect_all("MODE set", ":c1a.*MODE.*f.*\[1n\]:15") 87 | m.clearlog() 88 | print 89 | m.send(c2a, "NICK c2achmodef") 90 | m.send(c3a, "NICK c3achmodef") 91 | m.expect(c1a, "should send warning on flood", ":irc.* NOTICE %" + chan + " :\*\*\* Channel nickflood detected \(limit is 1 per 15 seconds\), setting mode \+N", timeout = 5) 92 | m.expect(c1a, "should set MODE on flood", ":irc.* MODE " + chan + " \+N", timeout = 5) 93 | m.clearlog() 94 | print 95 | 96 | # nick-flood: +f [1t]:15 97 | m.send(c1a, "MODE " + chan + " -C+f [1t]:15") 98 | m.expect_all("MODE set", ":c1a.*MODE.*f.*\[1t\]:15") 99 | m.clearlog() 100 | print 101 | m.send(c2a, "PRIVMSG " + chan + " :message one") 102 | m.send(c3a, "PRIVMSG " + chan + " :message one for me too") 103 | m.send(c2a, "PRIVMSG " + chan + " :message two I should be kicked") 104 | m.expect_all("should KICK user on flood", ":irc.* KICK " + chan + " $c2a :Flooding \(Limit is 1 lines per 15 seconds\)", timeout = 5) 105 | m.clearlog() 106 | print 107 | 108 | # rejoin 109 | m.send(c2a, "JOIN " + chan) 110 | m.clearlog() 111 | print 112 | 113 | # repeat-flood: +f [1r]:15 114 | m.send(c1a, "MODE " + chan + " +f [1r#d]:15") 115 | m.expect_all("MODE set", ":c1a.*MODE.*f.*\[1r\#d\]:15") 116 | m.clearlog() 117 | print 118 | m.send(c2a, "PRIVMSG " + chan + " :message one") 119 | m.expect_all("Expect first message to be delivered", ":$c2a.* PRIVMSG.*message one", skip = c2a) 120 | m.clearlog() 121 | print 122 | # now test a direct repeat: 123 | m.send(c2a, "PRIVMSG " + chan + " :message one") 124 | m.expect(c2a, "Repeated message should error", ":ir.* 404 $me " + chan + " :Flooding \(Your last message is too similar to previous ones\)") 125 | m.not_expect_all("Don't deliver repeated message", ":$c2a.* PRIVMSG.*message one", skip = c2a) 126 | m.clearlog() 127 | print 128 | 129 | # repeat-flood: +f [1r2]:15 130 | m.send(c1a, "MODE " + chan + " +f [1r#d2]:15") 131 | m.expect_all("MODE set", ":c1a.*MODE.*f.*\[1r\#d2\]:15") 132 | m.clearlog() 133 | print 134 | m.send(c2a, "PRIVMSG " + chan + " :alpha") 135 | m.expect_all("Expect first message to be delivered", ":$c2a.* PRIVMSG.*alpha", skip = c2a) 136 | m.clearlog() 137 | print 138 | m.send(c2a, "PRIVMSG " + chan + " :beta") 139 | m.expect_all("Expect second message to be delivered", ":$c2a.* PRIVMSG.*beta", skip = c2a) 140 | m.clearlog() 141 | print 142 | # now test a repeat of the before-last-message: 143 | m.send(c2a, "PRIVMSG " + chan + " :alpha") 144 | m.expect(c2a, "Repeated message should error", ":ir.* 404 $me " + chan + " :Flooding \(Your last message is too similar to previous ones\)") 145 | m.not_expect_all("Don't deliver repeated message", ":$c2a.* PRIVMSG.*alpha", skip = c2a) 146 | m.clearlog() 147 | print 148 | -------------------------------------------------------------------------------- /runwin: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function stopunreal { 4 | # Ask gracefully first 5 | taskkill -im unrealircd.exe -t 6 | taskkill -im timeout.exe -t 7 | # Wait 8 | sleep 5 9 | # Terminate with force 10 | taskkill -im unrealircd.exe -f -t 11 | taskkill -im timeout.exe -f -t 12 | sleep 2 13 | } 14 | 15 | function show_core_files { 16 | echo "UnrealIRCd has CRASHED!!" 17 | for f in "$UNREALIRCDDIR/"*.core 18 | do 19 | echo "*** $f ***" 20 | cat "$f" 21 | done 22 | } 23 | 24 | function fail { 25 | echo "FATAL ERROR: $1" 26 | sleep 5 27 | if ls "$UNREALIRCDDIR/"*mdmp 1>/dev/null 2>&1; then 28 | show_core_files 29 | CRASHED=1 30 | fi 31 | echo "Cleaning up..." 32 | stopunreal 33 | if [ "$CRASHED" = 1 ]; then 34 | echo "Tests failed / UnrealIRCd has CRASHED!! See errors above." 35 | else 36 | if ls "$UNREALIRCDDIR/"*mdmp 1>/dev/null 2>&1; then 37 | show_core_files 38 | echo "Tests failed AND UnrealIRCd crashed while terminating." 39 | else 40 | echo "Tests failed. See errors above." 41 | fi 42 | fi 43 | exit 1 44 | } 45 | 46 | if [ "$MAXPARALLEL" = "" ]; then 47 | MAXPARALLEL="25" 48 | fi 49 | TIMEOUT="40" 50 | KEEPDBS="0" 51 | CRASHED="0" 52 | INCLUDEFILE="" 53 | 54 | UNREALIRCDDIR="/c/Program Files/UnrealIRCd 6" 55 | 56 | # Stupid? Yes! 57 | find tests/ -type f -exec sed -i -e 's/\#\!\/usr\/bin\/python3/\#\!\/c\/Python39\/python/g' {} \; 58 | 59 | export PYTHONPATH="`pwd`" 60 | export PYTHONIOENCODING=utf-8 61 | export TIMEOUT 62 | 63 | rm -rf logs 64 | mkdir logs 65 | mkdir logs/success 66 | mkdir logs/failure 67 | 68 | if [ "$1" = "-include" ]; then 69 | shift 70 | INCLUDEFILE="$1" 71 | shift 72 | fi 73 | 74 | if [ "$1" = "-single" ]; then 75 | MAXPARALLEL=1 76 | shift 77 | fi 78 | 79 | if [ "$1" = "-keepdbs" ]; then 80 | KEEPDBS=1 81 | shift 82 | fi 83 | 84 | if [ "$1" = "-boot" -o "$1" = "" ]; then 85 | shift 86 | 87 | # Boot the ircd 88 | echo "Booting IRC server..." 89 | stopunreal 90 | 91 | # Move old core files and minidumps to oldcores\ (don't print and ignore errors) 92 | mkdir "$UNREALIRCDDIR/oldcores" 1>/dev/null 2>&1 93 | mv "$UNREALIRCDDIR/"*.core "$UNREALIRCDDIR/oldcores" 1>/dev/null 2>&1 94 | mv "$UNREALIRCDDIR/"*.mdmp "$UNREALIRCDDIR/oldcores" 1>/dev/null 2>&1 95 | 96 | cp -av serverconfig/unrealircd/* "$UNREALIRCDDIR/conf/" || fail "Could not copy configuration files" 97 | cd "$UNREALIRCDDIR/bin" || fail "Could not change to UnrealIRCd directory" 98 | echo "Now in:" 99 | pwd 100 | 101 | if [ "$KEEPDBS" -eq 0 ]; then 102 | # Delete databases 103 | echo Deleting old databases... 104 | mkdir "$UNREALIRCDDIR/data/old" 105 | mv "$UNREALIRCDDIR"/data/*.db "$UNREALIRCDDIR/data/old/" 106 | rm -rf "$UNREALIRCDDIR/data/history.old" 107 | mv "$UNREALIRCDDIR/data/history" "$UNREALIRCDDIR/data/history.old" 108 | fi 109 | 110 | if [ "$INCLUDEFILE" != "" ]; then 111 | echo Adding include... 112 | # Add include to irc1.conf (only) 113 | echo 'include "'$INCLUDEFILE'";' >>"$UNREALIRCDDIR/conf/irc1.conf" 114 | fi 115 | 116 | ./unrealircd -f irc2.conf& 117 | sleep 15 118 | ./unrealircd -f irc1.conf& 119 | sleep 15 120 | ./unrealircd -f irc3.conf& 121 | sleep 20 122 | cd - 123 | 124 | COUNTPROCS="`tasklist.exe|grep -i unrealircd|wc -l`" 125 | if [ "$COUNTPROCS" -lt 3 ]; then 126 | fatal "UnrealIRCd failed to boot" 127 | fi 128 | 129 | echo "Linking servers..." 130 | (timeout --kill-after=5 --signal=INT 30 tests/_pre_test) || fail "UnrealIRCd servers did not link" 131 | echo 132 | fi 133 | 134 | if [ "$1" = "" ]; then 135 | # Run all tests: 136 | echo "Running all tests in parallel..." 137 | # NOTE: we skip services tests on Windows! Too much hassle ;) 138 | find tests -type f|grep -vF '~'|grep -vF _pre_test|grep -v services/|grep -vF /db/|grep -vF /serial/|xargs -L1 -P$MAXPARALLEL irctestframework/wrapper 139 | #wait 140 | #^ this is annoying: 'wait' will also wait for unrealircd.exe to stop, 141 | # which hopefully will never happen, so we sleep instead: 142 | sleep 45 143 | echo "Running remaining tests in series..." 144 | find tests/serial/ -type f|grep -vF '~'|grep -vF README|xargs -L1 -P1 irctestframework/wrapper 145 | # And again, we sleep here too, what a joke... convert to some tasklist|find shit ? 146 | sleep 45 147 | stopunreal 148 | else 149 | # Run specific tests: 150 | echo "Running specific tests by user request..." 151 | for f in $* 152 | do 153 | # Skip backup files and such (blah~) 154 | if (echo "$f"|egrep -q '~$'); then 155 | continue 156 | fi 157 | if [ "$f" = "tests/db/writing/history" -o "$f" = "tests/db/reading/history" ]; then 158 | if ! (echo "$INCLUDEFILE"|grep -q 'crypt'); then 159 | echo "WARNING: Skipping $f -- not using encryption so can't test this" 160 | continue 161 | fi 162 | fi 163 | irctestframework/wrapper $f 164 | done 165 | fi 166 | 167 | cd logs/success 168 | echo 169 | echo "===================================================================================================" 170 | echo ">>> SUCCESFUL TESTS" 171 | for f in *.log 172 | do 173 | name="`echo $f|sed 's/__/\//g'|sed 's/\.log//g'`" 174 | if [ "$f" == "*.log" ]; then 175 | continue 176 | fi 177 | echo "✔ $name" 178 | done 179 | cd - 1>/dev/null 2>&1 180 | echo "===================================================================================================" 181 | 182 | failed=0 183 | cd logs/failure 184 | for f in *.log 185 | do 186 | name="`echo $f|sed 's/__/\//g'|sed 's/\.log//g'`" 187 | if [ "$f" == "*.log" ]; then 188 | continue 189 | fi 190 | echo 191 | echo "===================================================================================================" 192 | echo ">>> FAILED TEST: $name" 193 | cat $f 194 | echo "===================================================================================================" 195 | echo 196 | failed=1 197 | done 198 | 199 | if [ "$failed" = 1 ]; then 200 | echo 201 | echo "======[ SUMMARY ]======" 202 | for f in *.log 203 | do 204 | name="`echo $f|sed 's/__/\//g'|sed 's/\.log//g'`" 205 | if [ "$f" == "*.log" ]; then 206 | continue 207 | fi 208 | echo "TEST FAILED: $name" 209 | done 210 | fi 211 | 212 | cd - 1>/dev/null 2>&1 213 | 214 | stopunreal 215 | 216 | exit $failed 217 | -------------------------------------------------------------------------------- /serverconfig/atheme/services.db: -------------------------------------------------------------------------------- 1 | GRVER 1 2 | DBV 12 3 | MDEP transport/rfc1459 4 | MDEP protocol/base36uid 5 | MDEP protocol/unreal 6 | MDEP backend/corestorage 7 | MDEP backend/opensex 8 | MDEP crypto/pbkdf2v2 9 | MDEP crypto/posix 10 | MDEP nickserv/main 11 | MDEP nickserv/badmail 12 | MDEP nickserv/drop 13 | MDEP nickserv/ghost 14 | MDEP nickserv/group 15 | MDEP nickserv/help 16 | MDEP nickserv/list 17 | MDEP nickserv/hold 18 | MDEP nickserv/identify 19 | MDEP nickserv/info 20 | MDEP nickserv/listmail 21 | MDEP nickserv/logout 22 | MDEP nickserv/mark 23 | MDEP nickserv/freeze 24 | MDEP nickserv/listchans 25 | MDEP groupserv/main 26 | MDEP nickserv/listgroups 27 | MDEP nickserv/register 28 | MDEP nickserv/regnolimit 29 | MDEP nickserv/resetpass 30 | MDEP nickserv/restrict 31 | MDEP nickserv/return 32 | MDEP nickserv/setpass 33 | MDEP nickserv/sendpass_user 34 | MDEP nickserv/set_core 35 | MDEP nickserv/set_accountname 36 | MDEP nickserv/set_email 37 | MDEP nickserv/set_emailmemos 38 | MDEP nickserv/set_hidemail 39 | MDEP nickserv/set_nevergroup 40 | MDEP nickserv/set_neverop 41 | MDEP nickserv/set_nogreet 42 | MDEP nickserv/set_nomemo 43 | MDEP nickserv/set_noop 44 | MDEP nickserv/set_password 45 | MDEP nickserv/set_property 46 | MDEP nickserv/set_pubkey 47 | MDEP nickserv/set_quietchg 48 | MDEP nickserv/status 49 | MDEP nickserv/taxonomy 50 | MDEP nickserv/vacation 51 | MDEP nickserv/verify 52 | MDEP nickserv/vhost 53 | MDEP chanserv/main 54 | MDEP chanserv/access 55 | MDEP chanserv/akick 56 | MDEP chanserv/ban 57 | MDEP chanserv/clone 58 | MDEP chanserv/close 59 | MDEP chanserv/clear 60 | MDEP chanserv/clear_akicks 61 | MDEP chanserv/clear_bans 62 | MDEP chanserv/clear_flags 63 | MDEP chanserv/clear_users 64 | MDEP chanserv/count 65 | MDEP chanserv/drop 66 | MDEP chanserv/flags 67 | MDEP chanserv/ftransfer 68 | MDEP chanserv/getkey 69 | MDEP chanserv/help 70 | MDEP chanserv/hold 71 | MDEP chanserv/info 72 | MDEP chanserv/invite 73 | MDEP chanserv/kick 74 | MDEP chanserv/list 75 | MDEP chanserv/mark 76 | MDEP chanserv/op 77 | MDEP chanserv/recover 78 | MDEP chanserv/register 79 | MDEP chanserv/set_core 80 | MDEP chanserv/set_email 81 | MDEP chanserv/set_entrymsg 82 | MDEP chanserv/set_fantasy 83 | MDEP chanserv/set_guard 84 | MDEP chanserv/set_keeptopic 85 | MDEP chanserv/set_mlock 86 | MDEP chanserv/set_prefix 87 | MDEP chanserv/set_property 88 | MDEP chanserv/set_restricted 89 | MDEP chanserv/set_secure 90 | MDEP chanserv/set_topiclock 91 | MDEP chanserv/set_url 92 | MDEP chanserv/set_verbose 93 | MDEP chanserv/status 94 | MDEP chanserv/sync 95 | MDEP chanserv/taxonomy 96 | MDEP chanserv/template 97 | MDEP chanserv/topic 98 | MDEP chanserv/voice 99 | MDEP chanserv/why 100 | MDEP chanserv/quiet 101 | MDEP chanserv/antiflood 102 | MDEP operserv/main 103 | MDEP operserv/akill 104 | MDEP operserv/compare 105 | MDEP operserv/help 106 | MDEP operserv/identify 107 | MDEP operserv/ignore 108 | MDEP operserv/info 109 | MDEP operserv/jupe 110 | MDEP operserv/mode 111 | MDEP operserv/modinspect 112 | MDEP operserv/modlist 113 | MDEP operserv/modload 114 | MDEP operserv/modunload 115 | MDEP operserv/modreload 116 | MDEP operserv/noop 117 | MDEP operserv/readonly 118 | MDEP operserv/rehash 119 | MDEP operserv/restart 120 | MDEP operserv/rmatch 121 | MDEP operserv/rnc 122 | MDEP operserv/rwatch 123 | MDEP operserv/set 124 | MDEP operserv/sgline 125 | MDEP operserv/shutdown 126 | MDEP operserv/specs 127 | MDEP operserv/sqline 128 | MDEP operserv/update 129 | MDEP operserv/uptime 130 | MDEP memoserv/main 131 | MDEP memoserv/help 132 | MDEP memoserv/send 133 | MDEP memoserv/sendops 134 | MDEP memoserv/sendgroup 135 | MDEP memoserv/list 136 | MDEP memoserv/read 137 | MDEP memoserv/forward 138 | MDEP memoserv/delete 139 | MDEP memoserv/ignore 140 | MDEP global/main 141 | MDEP infoserv/main 142 | MDEP saslserv/main 143 | MDEP saslserv/plain 144 | MDEP saslserv/authcookie 145 | MDEP saslserv/external 146 | MDEP statserv/main 147 | MDEP statserv/netsplit 148 | MDEP statserv/server 149 | MDEP groupserv/acsnolimit 150 | MDEP groupserv/drop 151 | MDEP groupserv/fdrop 152 | MDEP groupserv/fflags 153 | MDEP groupserv/flags 154 | MDEP groupserv/help 155 | MDEP groupserv/info 156 | MDEP groupserv/join 157 | MDEP groupserv/list 158 | MDEP groupserv/listchans 159 | MDEP groupserv/register 160 | MDEP groupserv/regnolimit 161 | MDEP groupserv/set 162 | MDEP groupserv/set_channel 163 | MDEP groupserv/set_description 164 | MDEP groupserv/set_email 165 | MDEP groupserv/set_groupname 166 | MDEP groupserv/set_joinflags 167 | MDEP groupserv/set_open 168 | MDEP groupserv/set_public 169 | MDEP groupserv/set_url 170 | MDEP misc/httpd 171 | MDEP transport/xmlrpc 172 | LUID AAAAAAAAE 173 | CF +AFHORVabefhioqrstv 174 | MU AAAAAAAAC client1 $z$6$64000$PPyfxwYylBTzysFv$mx5ptqPr6a6exqioUO8fEAkMo3Fn24+AcuKtRm3sJhnRq3dg/Tac6Nm2zAyjBb30SdptY8l3Io6aVQWgLU54hA== noreply@unrealircd.org 1574064478 1679483612 +sC default 175 | MDU client1 private:host:actual username@localhost 176 | MDU client1 private:host:vhost username@Clk-8608861 177 | MN client1 client1 1574064478 1679483612 178 | MU AAAAAAAAD client2 $z$6$64000$w1E5a2ddt0bUfSSF$cgtCEUR/CTBKA/1grI9Xu9zR2/fsq2tDJJEbCPjBGNWRq8yR4KoAY88mW+bZ21b50jmO9lRZHJEhFBFAi3qr2w== noreply@unrealircd.org 1574064489 1679483612 +sC default 179 | MDU client2 private:host:actual username@localhost 180 | MDU client2 private:host:vhost username@Clk-8608861 181 | MN client2 client2 1574064489 1679483612 182 | MU AAAAAAAAE client3 $z$6$64000$bABwEn1QRtdq0LnP$YWhwxRR6sn7dXkg7HkOcU51KN3BbfZ/LtSjfGDX6OWM2tzHZA1U4ky625f5nncNkBThFI5ceI+ApdMTzQDiYzA== noreply@unrealircd.org 1574064494 1679483612 +sCb default 183 | MDU client3 private:host:actual username@localhost 184 | MDU client3 private:host:vhost username@Clk-8608861 185 | MN client3 client3 1574064494 1574064495 186 | MU AAAAAAAAB netadmin $1$muoatx$czAvH.o2toZo/cTLxh30n1 noreply@unrealircd.org 1574058981 1574061512 +sC default 187 | MDU netadmin private:host:actual x@localhost 188 | MDU netadmin private:host:vhost x@netadmin.test.net 189 | MN netadmin netadmin 1574058981 1574059914 190 | GDBV 4 191 | GFA +fscmviA 192 | KID 0 193 | XID 0 194 | QID 0 195 | --------------------------------------------------------------------------------