You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

IRCParserTest.java 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. /*
  2. * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. * SOFTWARE.
  21. */
  22. package com.dmdirc.parser.irc;
  23. import com.dmdirc.parser.common.MyInfo;
  24. import com.dmdirc.parser.common.ChannelListModeItem;
  25. import com.dmdirc.parser.common.ParserError;
  26. import com.dmdirc.harness.parser.TestIPrivateCTCP;
  27. import com.dmdirc.harness.parser.TestParser;
  28. import com.dmdirc.harness.parser.TestIConnectError;
  29. import com.dmdirc.harness.parser.TestINoticeAuth;
  30. import com.dmdirc.harness.parser.TestINumeric;
  31. import com.dmdirc.harness.parser.TestIServerError;
  32. import com.dmdirc.harness.parser.TestIPost005;
  33. import com.dmdirc.harness.parser.TestIPrivateMessage;
  34. import com.dmdirc.harness.parser.TestIPrivateAction;
  35. import com.dmdirc.parser.interfaces.callbacks.AuthNoticeListener;
  36. import com.dmdirc.parser.common.CallbackNotFoundException;
  37. import com.dmdirc.parser.interfaces.callbacks.AwayStateListener;
  38. import com.dmdirc.parser.interfaces.callbacks.CallbackInterface;
  39. import com.dmdirc.parser.interfaces.callbacks.ChannelKickListener;
  40. import com.dmdirc.parser.interfaces.callbacks.ConnectErrorListener;
  41. import com.dmdirc.parser.interfaces.callbacks.ErrorInfoListener;
  42. import com.dmdirc.parser.interfaces.callbacks.NumericListener;
  43. import com.dmdirc.parser.interfaces.callbacks.Post005Listener;
  44. import com.dmdirc.parser.interfaces.callbacks.PrivateActionListener;
  45. import com.dmdirc.parser.interfaces.callbacks.PrivateCtcpListener;
  46. import com.dmdirc.parser.interfaces.callbacks.PrivateMessageListener;
  47. import com.dmdirc.parser.interfaces.callbacks.ServerErrorListener;
  48. import java.util.Arrays;
  49. import java.util.Collection;
  50. import javax.net.ssl.TrustManager;
  51. import org.junit.Ignore;
  52. import org.junit.Test;
  53. import static org.junit.Assert.*;
  54. import static org.mockito.Mockito.*;
  55. public class IRCParserTest {
  56. private static interface TestCallback extends CallbackInterface { }
  57. @Test
  58. public void testIssue42() {
  59. // Invalid callback names are silently ignored instead of raising exceptions
  60. boolean res = false;
  61. try {
  62. final IRCParser myParser = new IRCParser();
  63. myParser.getCallbackManager().addCallback(TestCallback.class, mock(TestCallback.class));
  64. } catch (CallbackNotFoundException ex) {
  65. res = true;
  66. }
  67. assertTrue("addCallback() should throw exception for non-existant callbacks", res);
  68. }
  69. @Test
  70. public void testIssue1674() {
  71. // parser nick change error with dual 001
  72. final ErrorInfoListener error = mock(ErrorInfoListener.class);
  73. final TestParser myParser = new TestParser();
  74. myParser.getCallbackManager().addCallback(ErrorInfoListener.class, error);
  75. myParser.injectConnectionStrings();
  76. myParser.nick = "nick2";
  77. myParser.injectConnectionStrings();
  78. myParser.injectLine(":nick2!ident@host NICK :nick");
  79. verify(error, never()).onErrorInfo((IRCParser) anyObject(), (ParserError) anyObject());
  80. }
  81. @Test
  82. public void testProxyPortWithBindIP() {
  83. final TestIConnectError tice = new TestIConnectError();
  84. final ServerInfo si = new ServerInfo();
  85. si.setProxyPort(155555);
  86. si.setUseSocks(true);
  87. final IRCParser myParser = new IRCParser(si);
  88. myParser.getCallbackManager().addCallback(ConnectErrorListener.class, tice);
  89. myParser.setBindIP("0.0.0.0");
  90. myParser.run();
  91. assertTrue("Using an invalid socks proxy port should raise a connect error event",
  92. tice.error);
  93. }
  94. @Test
  95. public void testTokeniser() {
  96. final String line1 = "a b c d e";
  97. final String line2 = "a b c :d e";
  98. final String line3 = ":a b:c :d e";
  99. final String line4 = null;
  100. final String[] res1 = IRCParser.tokeniseLine(line1);
  101. final String[] res2 = IRCParser.tokeniseLine(line2);
  102. final String[] res3 = IRCParser.tokeniseLine(line3);
  103. final String[] res4 = IRCParser.tokeniseLine(line4);
  104. assertTrue(Arrays.equals(res1, new String[]{"a", "b", "c", "d", "e"}));
  105. assertTrue(Arrays.equals(res2, new String[]{"a", "b", "c", "d e"}));
  106. assertTrue(Arrays.equals(res3, new String[]{":a", "b:c", "d e"}));
  107. assertTrue(Arrays.equals(res4, new String[]{""}));
  108. }
  109. @Test
  110. public void testSendConnectionStrings1() {
  111. final ServerInfo serverInfo = new ServerInfo("irc.testing.dmdirc", 6667, "");
  112. final MyInfo myInfo = new MyInfo();
  113. myInfo.setNickname("Nickname");
  114. myInfo.setRealname("Real name");
  115. myInfo.setUsername("Username");
  116. final TestParser parser = new TestParser(myInfo, serverInfo);
  117. parser.sendConnectionStrings();
  118. assertEquals(2, parser.sentLines.size());
  119. assertTrue("Should send nickname line",
  120. Arrays.equals(parser.getLine(0), new String[]{"NICK", "Nickname"}));
  121. final String[] userParts = parser.getLine(1);
  122. assertEquals("First token should be USER", "USER", userParts[0]);
  123. assertEquals("USER should contain username", myInfo.getUsername().toLowerCase(),
  124. userParts[1].toLowerCase());
  125. assertEquals("USER should contain server name", serverInfo.getHost(), userParts[3]);
  126. assertEquals("USER should contain real name", "Real name", userParts[4]);
  127. }
  128. @Test
  129. public void testSendConnectionStrings2() {
  130. final ServerInfo serverInfo = new ServerInfo("irc.testing.dmdirc", 6667, "password");
  131. final MyInfo myInfo = new MyInfo();
  132. myInfo.setNickname("Nickname");
  133. myInfo.setRealname("Real name");
  134. myInfo.setUsername("Username");
  135. final TestParser parser = new TestParser(myInfo, serverInfo);
  136. parser.sendConnectionStrings();
  137. assertEquals(3, parser.sentLines.size());
  138. assertTrue("Should send password line",
  139. Arrays.equals(parser.getLine(0), new String[]{"PASS", "password"}));
  140. }
  141. @Test
  142. public void testPingPong() {
  143. final TestParser parser = new TestParser();
  144. parser.injectLine("PING :flubadee7291");
  145. assertTrue("Should reply to PINGs with PONGs",
  146. Arrays.equals(parser.getLine(0), new String[]{"PONG", "flubadee7291"}));
  147. }
  148. @Test
  149. public void testError() throws CallbackNotFoundException {
  150. final TestIServerError test = new TestIServerError();
  151. final TestParser parser = new TestParser();
  152. parser.getCallbackManager().addCallback(ServerErrorListener.class, test);
  153. parser.injectLine("ERROR :You smell of cheese");
  154. assertNotNull(test.message);
  155. assertEquals("ERROR message should be passed to callback",
  156. "You smell of cheese", test.message);
  157. }
  158. @Test
  159. public void testAuthNotices() throws CallbackNotFoundException {
  160. final TestINoticeAuth test = new TestINoticeAuth();
  161. final TestParser parser = new TestParser();
  162. parser.getCallbackManager().addCallback(AuthNoticeListener.class, test);
  163. parser.sendConnectionStrings();
  164. parser.injectLine("NOTICE AUTH :Random auth notice?");
  165. assertNotNull(test.message);
  166. assertEquals("Random auth notice?", test.message);
  167. test.message = null;
  168. parser.injectLine(":us.ircnet.org 020 * :Stupid notice");
  169. assertNotNull(test.message);
  170. assertEquals("Stupid notice", test.message);
  171. }
  172. @Test
  173. public void testPre001NickChange() throws CallbackNotFoundException {
  174. final TestINoticeAuth test = new TestINoticeAuth();
  175. final TestParser parser = new TestParser();
  176. parser.getCallbackManager().addCallback(AuthNoticeListener.class, test);
  177. parser.sendConnectionStrings();
  178. parser.injectLine(":chris!@ NICK :user2");
  179. assertNull(test.message);
  180. }
  181. @Test
  182. public void testNumeric() throws CallbackNotFoundException {
  183. final TestINumeric test = new TestINumeric();
  184. final TestParser parser = new TestParser();
  185. parser.getCallbackManager().addCallback(NumericListener.class, test);
  186. parser.injectLine(":server 001 nick :Hi there, nick");
  187. assertEquals(1, test.numeric);
  188. assertTrue(Arrays.equals(new String[]{":server", "001", "nick", "Hi there, nick"},
  189. test.data));
  190. }
  191. @Test
  192. public void testPost005() throws CallbackNotFoundException {
  193. final TestIPost005 test = new TestIPost005();
  194. final TestParser parser = new TestParser();
  195. parser.getCallbackManager().addCallback(Post005Listener.class, test);
  196. final String[] strings = {
  197. "NOTICE AUTH :Blah, blah",
  198. ":server 020 * :Blah! Blah!",
  199. ":server 001 nick :Welcome to the Testing IRC Network, nick",
  200. ":server 002 nick :Your host is server.net, running version foo",
  201. "NOTICE AUTH :I'm a retarded server",
  202. ":server 003 nick :This server was created Sun Jan 6 2008 at 17:34:54 CET",
  203. ":server 004 nick server.net foo dioswkgxRXInP biklmnopstvrDcCNuMT bklov",
  204. ":server 005 nick WHOX WALLCHOPS WALLVOICES USERIP :are supported by this server",
  205. ":server 005 nick MAXNICKLEN=15 TOPICLEN=250 AWAYLEN=160 :are supported " +
  206. "by this server",
  207. ":server 375 nick :zomg, motd!",
  208. };
  209. for (String string : strings) {
  210. assertFalse("OnPost005 fired too early", test.done);
  211. parser.injectLine(string);
  212. }
  213. assertTrue("OnPost005 not fired", test.done);
  214. }
  215. @Test
  216. public void test005Parsing() {
  217. final TestParser parser = new TestParser();
  218. final String[] strings = {
  219. ":server 001 nick :Welcome to the Testing IRC Network, nick",
  220. ":server 002 nick :Your host is server.net, running version foo",
  221. ":server 003 nick :This server was created Sun Jan 6 2008 at 17:34:54 CET",
  222. ":server 004 nick server.net foo dioswkgxRXInP biklmnopstvrDcCNuMT bklov",
  223. ":server 005 nick WHOX WALLCHOPS WALLVOICES NETWORK=moo :are supported by" +
  224. " this server",
  225. ":server 005 nick MAXNICKLEN=15 MAXLIST=b:10,e:22,I:45 :are supported by" +
  226. " this server",
  227. ":server 375 nick :zomg, motd!",
  228. };
  229. for (String string : strings) {
  230. parser.injectLine(string);
  231. }
  232. assertEquals(10, parser.getMaxListModes('b'));
  233. assertEquals(22, parser.getMaxListModes('e'));
  234. assertEquals(45, parser.getMaxListModes('I'));
  235. assertEquals("getMaxListModes should return 0 for unknowns;", 0,
  236. parser.getMaxListModes('z'));
  237. assertEquals("moo", parser.getNetworkName());
  238. assertEquals("server", parser.getServerName());
  239. }
  240. @Test
  241. public void testBindIP() {
  242. final TestParser parser = new TestParser();
  243. parser.setBindIP("abc.def.ghi.123");
  244. assertEquals("abc.def.ghi.123", parser.getBindIP());
  245. }
  246. @Test
  247. public void testCreateFake() {
  248. final TestParser parser = new TestParser();
  249. parser.setCreateFake(false);
  250. assertFalse(parser.getCreateFake());
  251. parser.setCreateFake(true);
  252. assertTrue(parser.getCreateFake());
  253. }
  254. @Test
  255. public void testAutoListMode() {
  256. final TestParser parser = new TestParser();
  257. parser.setAutoListMode(false);
  258. assertFalse(parser.getAutoListMode());
  259. parser.setAutoListMode(true);
  260. assertTrue(parser.getAutoListMode());
  261. }
  262. @Test
  263. public void testRemoveAfterCallback() {
  264. final TestParser parser = new TestParser();
  265. parser.setRemoveAfterCallback(false);
  266. assertFalse(parser.getRemoveAfterCallback());
  267. parser.setRemoveAfterCallback(true);
  268. assertTrue(parser.getRemoveAfterCallback());
  269. }
  270. @Test
  271. public void testAddLastLine() {
  272. final TestParser parser = new TestParser();
  273. parser.setAddLastLine(false);
  274. assertFalse(parser.getAddLastLine());
  275. parser.setAddLastLine(true);
  276. assertTrue(parser.getAddLastLine());
  277. }
  278. @Test
  279. public void testDisconnectOnFatal() {
  280. final TestParser parser = new TestParser();
  281. parser.setDisconnectOnFatal(false);
  282. assertFalse(parser.getDisconnectOnFatal());
  283. parser.setDisconnectOnFatal(true);
  284. assertTrue(parser.getDisconnectOnFatal());
  285. }
  286. @Test
  287. public void testTrustManager() {
  288. final TestParser parser = new TestParser();
  289. assertTrue(Arrays.equals(parser.getDefaultTrustManager(), parser.getTrustManager()));
  290. parser.setTrustManagers(new TrustManager[0]);
  291. assertTrue(Arrays.equals(new TrustManager[0], parser.getTrustManager()));
  292. }
  293. @Test
  294. public void testPrivateMessages() throws CallbackNotFoundException {
  295. final TestParser parser = new TestParser();
  296. final TestIPrivateMessage ipmtest = new TestIPrivateMessage();
  297. final TestIPrivateAction ipatest = new TestIPrivateAction();
  298. final TestIPrivateCTCP ipctest = new TestIPrivateCTCP();
  299. parser.injectConnectionStrings();
  300. parser.getCallbackManager().addCallback(PrivateMessageListener.class, ipmtest);
  301. parser.getCallbackManager().addCallback(PrivateActionListener.class, ipatest);
  302. parser.getCallbackManager().addCallback(PrivateCtcpListener.class, ipctest);
  303. parser.injectLine(":a!b@c PRIVMSG nick :Hello!");
  304. assertNotNull(ipmtest.host);
  305. assertNull(ipatest.host);
  306. assertNull(ipctest.host);
  307. assertEquals("a!b@c", ipmtest.host);
  308. assertEquals("Hello!", ipmtest.message);
  309. ipmtest.host = null;
  310. ipmtest.message = null;
  311. parser.injectLine(":a!b@c PRIVMSG nick :" + ((char) 1) + "ACTION meep" + ((char) 1));
  312. assertNull(ipmtest.host);
  313. assertNotNull(ipatest.host);
  314. assertNull(ipctest.host);
  315. assertEquals("a!b@c", ipatest.host);
  316. assertEquals("meep", ipatest.message);
  317. ipatest.host = null;
  318. ipatest.message = null;
  319. parser.injectLine(":a!b@c PRIVMSG nick :" + ((char) 1) + "FOO meep" + ((char) 1));
  320. assertNull(ipmtest.host);
  321. assertNull(ipatest.host);
  322. assertNotNull(ipctest.host);
  323. assertEquals("a!b@c", ipctest.host);
  324. assertEquals("FOO", ipctest.type);
  325. assertEquals("meep", ipctest.message);
  326. }
  327. private void testListModes(String numeric1, String numeric2, char mode) {
  328. final TestParser parser = new TestParser();
  329. parser.injectConnectionStrings();
  330. parser.injectLine(":nick JOIN #D");
  331. parser.injectLine(":server " + numeric1 + " nick #D ban1!ident@.host bansetter1 1001");
  332. parser.injectLine(":server " + numeric1 + " nick #D ban2!*@.host bansetter2 1002");
  333. parser.injectLine(":server " + numeric1 + " nick #D ban3!ident@* bansetter3 1003");
  334. parser.injectLine(":server " + numeric2 + " nick #D :End of Channel Something List");
  335. final Collection<ChannelListModeItem> items
  336. = parser.getChannel("#D").getListMode(mode);
  337. assertEquals(3, items.size());
  338. boolean gotOne = false, gotTwo = false, gotThree = false;
  339. for (ChannelListModeItem item : items) {
  340. if (item.getItem().equals("ban1!ident@.host")) {
  341. assertEquals("bansetter1", item.getOwner());
  342. assertEquals(1001l, item.getTime());
  343. assertFalse(gotOne);
  344. gotOne = true;
  345. } else if (item.getItem().equals("ban2!*@.host")) {
  346. assertEquals("bansetter2", item.getOwner());
  347. assertEquals(1002l, item.getTime());
  348. assertFalse(gotTwo);
  349. gotTwo = true;
  350. } else if (item.toString().equals("ban3!ident@*")) {
  351. assertEquals("bansetter3", item.getOwner());
  352. assertEquals(1003l, item.getTime());
  353. assertFalse(gotThree);
  354. gotThree = true;
  355. }
  356. }
  357. assertTrue(gotOne);
  358. assertTrue(gotTwo);
  359. assertTrue(gotThree);
  360. }
  361. @Test
  362. public void testNormalBans() {
  363. testListModes("367", "368", 'b');
  364. }
  365. @Test
  366. public void testInvexList() {
  367. testListModes("346", "347", 'I');
  368. }
  369. @Test
  370. public void testExemptList() {
  371. testListModes("348", "349", 'e');
  372. }
  373. @Test
  374. public void testReopList() {
  375. testListModes("344", "345", 'R');
  376. }
  377. @Test
  378. public void testGetParam() {
  379. assertEquals("abc def", TestParser.getParam("foo :abc def"));
  380. assertEquals("bar :abc def", TestParser.getParam("foo :bar :abc def"));
  381. assertEquals("abc def", TestParser.getParam("abc def"));
  382. }
  383. @Test
  384. public void testKick() throws CallbackNotFoundException {
  385. final TestParser parser = new TestParser();
  386. final ChannelKickListener ick = mock(ChannelKickListener.class);
  387. parser.injectConnectionStrings();
  388. parser.injectLine(":nick JOIN #D");
  389. parser.getCallbackManager().addCallback(ChannelKickListener.class, ick, "#D");
  390. parser.injectLine(":bar!me@moo KICK #D nick :Bye!");
  391. verify(ick).onChannelKick(same(parser), (IRCChannelInfo) anyObject(),
  392. (IRCChannelClientInfo) anyObject(), (IRCChannelClientInfo) anyObject(),
  393. anyString(), anyString());
  394. }
  395. @Test
  396. public void testIRCds() {
  397. doIRCdTest("u2.10.12.10+snircd(1.3.4)", "snircd");
  398. doIRCdTest("u2.10.12.12", "ircu");
  399. doIRCdTest("hyperion-1.0.2b", "hyperion");
  400. doIRCdTest("hybrid-7.2.3", "hybrid");
  401. doIRCdTest("Unreal3.2.6", "unreal");
  402. doIRCdTest("bahamut-1.8(04)", "bahamut");
  403. }
  404. @Test
  405. public void testIllegalPort1() {
  406. final TestParser tp = new TestParser(new MyInfo(), new ServerInfo("127.0.0.1", 0, ""));
  407. final TestIConnectError tiei = new TestIConnectError();
  408. tp.getCallbackManager().addCallback(ConnectErrorListener.class, tiei);
  409. tp.runSuper();
  410. assertTrue(tiei.error);
  411. }
  412. @Test
  413. public void testIllegalPort2() {
  414. final TestParser tp = new TestParser(new MyInfo(), new ServerInfo("127.0.0.1", 1, ""));
  415. final TestIConnectError tiei = new TestIConnectError();
  416. tp.getCallbackManager().addCallback(ConnectErrorListener.class, tiei);
  417. tp.runSuper();
  418. assertTrue(tiei.error);
  419. }
  420. @Test
  421. public void testIllegalPort3() {
  422. final TestParser tp = new TestParser(new MyInfo(), new ServerInfo("127.0.0.1", 65570, ""));
  423. final TestIConnectError tiei = new TestIConnectError();
  424. tp.getCallbackManager().addCallback(ConnectErrorListener.class, tiei);
  425. tp.runSuper();
  426. assertTrue(tiei.error);
  427. }
  428. private void doIRCdTest(final String ircd, final String expected) {
  429. final TestParser parser = new TestParser();
  430. String[] strings = {
  431. ":server 001 nick :Welcome to the Testing IRC Network, nick",
  432. ":server 002 nick :Your host is server.net, running version %s",
  433. ":server 003 nick :This server was created Sun Jan 6 2008 at 17:34:54 CET",
  434. ":server 004 nick server.net %s dioswkgxRXInP biklmnopstvrDcCNuMT bklov"
  435. };
  436. for (String line : strings) {
  437. parser.injectLine(String.format(line, ircd));
  438. }
  439. assertEquals(ircd, parser.getServerSoftware());
  440. assertEquals(expected.toLowerCase(), parser.getServerSoftwareType().toLowerCase());
  441. }
  442. }