1 # Copyright (C) 2005-2008 Jelmer Vernooij <jelmer@samba.org>
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 3 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 class LineTestCase(unittest.TestCase):
22 def test_create_str(self):
23 l = irc.Line(":origin PRIVMSG bla")
24 self.assertTrue(l is not None)
25 self.assertEquals(str(l), ":origin PRIVMSG bla")
27 def test_create_list_origin(self):
28 l = irc.Line([":origin", "PRIVMSG", "bla"])
29 self.assertTrue(l is not None)
30 self.assertEquals("origin", l.origin)
31 self.assertEquals(2, len(l))
32 self.assertEquals("PRIVMSG", l[0])
33 self.assertEquals("bla", l[1])
34 self.assertEqual(str(l), ":origin PRIVMSG :bla")
36 def test_create_list_no_origin(self):
37 l = irc.Line(["PRIVMSG", "bla"])
38 self.assertTrue(l is not None)
39 self.assertEquals(None, l.origin)
40 self.assertEquals(2, len(l))
41 self.assertEquals("PRIVMSG", l[0])
42 self.assertEquals("bla", l[1])
43 self.assertEqual(str(l), "PRIVMSG :bla")
45 def test_create_other(self):
46 l = irc.Line(":origin PRIVMSG bla")
48 self.assertEquals(str(l), str(newl))
50 def test_create_inval(self):
51 self.assertRaises(TypeError, irc.Line, 1)
53 def test__str__(self):
54 l = irc.Line(":origin PRIVMSG bla")
55 self.assertEquals(str(l), ":origin PRIVMSG bla")
58 l = irc.Line(":origin PRIVMSG bla")
59 self.assertEquals(repr(l), "Line(':origin PRIVMSG bla')")
61 def test_get_nick(self):
62 l = irc.Line(":origin PRIVMSG bla")
63 self.assertEquals(l.get_nick(), "origin")
66 l = irc.Line(":origin PRIVMSG bla")
67 self.assertEquals(len(l), 2)
69 def test_getitem(self):
70 l = irc.Line(":origin PRIVMSG bla")
71 self.assertEquals(l[0], "PRIVMSG")
72 self.assertEquals(l[1], "bla")
73 self.assertRaises(KeyError, lambda: l[2])
76 class ChannelStateTests(unittest.TestCase):
78 def test_create(self):
79 s = irc.ChannelState("#foo")
80 self.assertTrue(s is not None)
81 self.assertEquals("#foo", s.name)
84 s = irc.ChannelState("#foo")
85 self.assertTrue(s.nicks is not None)
86 self.assertEquals(0, len(s.nicks))
87 self.assertRaises(KeyError, lambda: s.nicks["nick"])
89 def test_add_nick(self):
90 s = irc.ChannelState("#foo")
91 s.nicks.add(irc.Nick("me!foo@bar"))
92 self.assertEquals(1, len(s.nicks))
93 self.assertEquals("me", s.nicks["me"].nick)
95 def test_add_nick_mode(self):
96 s = irc.ChannelState("#foo")
97 s.nicks.add(irc.Nick("me!foo@bar"), "+o")
98 self.assertEquals(1, len(s.nicks))
99 self.assertEquals("me", s.nicks["me"].nick)
100 self.assertEquals("+o", s.nicks.nick_mode("me"))
102 def test_set_key(self):
103 s = irc.ChannelState("#foo")
104 self.assertRaises(KeyError, lambda:s.mode_option['k'])
105 s.mode_option['k'] = "bar"
106 self.assertEquals("bar", s.mode_option['k'])
108 def test_limit(self):
109 s = irc.ChannelState("#foo")
110 self.assertRaises(KeyError, lambda:s.mode_option['l'])
111 s.mode_option['l'] = "42"
112 self.assertEquals("42", s.mode_option['l'])
114 def test_get_modes(self):
115 s = irc.ChannelState("#foo")
116 self.assertEquals("", s.modes)
118 def test_set_modes(self):
119 s = irc.ChannelState("#foo")
121 self.assertEquals("+n", s.modes)
123 def test_get_topic(self):
124 s = irc.ChannelState("#foo")
125 self.assertEquals(None, s.topic)
127 def test_set_topic(self):
128 s = irc.ChannelState("#foo")
131 self.assertEquals("BLA", s.topic)
133 def test_get_topic_time(self):
134 s = irc.ChannelState("#foo")
135 self.assertEquals(0, s.topic_set_time)
137 def test_get_topic_time_set(self):
138 s = irc.ChannelState("#foo")
139 s.topic_set_time = 42
140 self.assertEquals(42, s.topic_set_time)
142 def test_creationtime(self):
143 s = irc.ChannelState("#foo")
144 self.assertEquals(0, s.creation_time)
146 def test_creationtime_set(self):
147 s = irc.ChannelState("#foo")
148 s.creation_time = 423423
149 self.assertEquals(423423, s.creation_time)
153 class BaseNetworkStateTests(unittest.TestCase):
155 def test_create(self):
156 s = irc.NetworkState("nick", "user", "host")
157 self.assertTrue(s is not None)
160 s = irc.NetworkState("nick", "user", "host")
161 self.assertTrue(s.info is not None)
164 class NetworkStateTestCase(unittest.TestCase):
167 super(NetworkStateTestCase, self).setUp()
168 self.state = irc.NetworkState("nick", "user", "host")
170 def test_add_channel(self):
171 c = irc.ChannelState("#foo")
173 self.assertEquals(c.name, self.state["#foo"].name)
175 def test_add_nick(self):
176 n = irc.Nick("me!user@host")
178 self.assertEquals(n.nick, self.state["me"].nick)
180 def test_handle_line(self):
181 self.state.handle_line(":nick!user@host JOIN #foo")
183 def test_channels_empty(self):
184 self.assertEquals([], list(self.state.channels))
186 def test_channels(self):
187 self.state.handle_line(":nick!user@host JOIN #foo")
188 channels = self.state.channels
189 self.assertEquals(1, len(channels))
190 self.assertEquals("#foo", list(channels)[0].name)
191 self.assertEquals("#foo", channels["#foo"].name)
193 def test_get_channel(self):
194 self.state.handle_line(":nick!user@host JOIN #foo")
195 self.assertEquals(self.state["#foo"].name, "#foo")
197 def test_leave_channel(self):
198 self.state.handle_line(":nick!user@host JOIN #foo")
199 self.assertEquals(["#foo"], [c.name for c in self.state.channels])
200 self.state.handle_line(":nick!user@host PART #foo")
201 self.assertEquals([], [c.name for c in self.state.channels])
202 self.state.handle_line(":nick!user@host PART #ba")
204 def test_kicked_off_channel(self):
205 self.state.handle_line(":nick!user@host JOIN #foo")
206 self.assertEquals(["#foo"], [c.name for c in self.state.channels])
207 self.state.handle_line(":othernick!user@host KICK #foo :nick")
208 self.assertEquals([], [c.name for c in self.state.channels])
210 def test_channel_mode_option(self):
211 self.state.handle_line(":nick!user@host JOIN #foo")
212 self.state.handle_line(":somenick MODE #foo +l 42")
213 self.assertEquals("42", self.state["#foo"].mode_option["l"])
215 def test_channel_mode_two_options(self):
216 self.state.handle_line(":nick!user@host JOIN #foo")
217 self.state.handle_line(":somenick MODE #foo +kl bla 42")
218 self.assertEquals("42", self.state["#foo"].mode_option["l"])
219 self.assertEquals("bla", self.state["#foo"].mode_option["k"])
221 def test_channel_topic(self):
222 self.state.handle_line(":nick!user@host JOIN #foo")
223 self.state.handle_line(":someserver 332 nick #foo :The TOPIC")
224 self.assertEquals("The TOPIC", self.state["#foo"].topic)
226 def test_nick_channels(self):
227 self.state.handle_line(":nick!user@host JOIN #foo")
228 self.assertEquals(["#foo"], list(self.state["nick"].channels))
231 class NetworkInfoTests(unittest.TestCase):
233 def test_create(self):
234 s = irc.NetworkInfo()
235 self.assertTrue(s is not None)
237 def test_prefix_by_mode(self):
238 s = irc.NetworkInfo()
239 self.assertEquals("@", s.get_prefix_by_mode("o"))
241 def test_irccmp_samecase(self):
242 s = irc.NetworkInfo()
243 self.assertEquals(s.irccmp("bla", "bla"), 0)
245 def test_irccmp_diff(self):
246 s = irc.NetworkInfo()
247 self.assertNotEqual(s.irccmp("bla", "bloe"), 0)
249 def test_irccmp_diffcase(self):
250 s = irc.NetworkInfo()
251 self.assertEqual(s.irccmp("BlA", "bla"), 0)
253 def test_is_prefix(self):
254 s = irc.NetworkInfo()
255 self.assertTrue(s.is_prefix("@"))
256 self.assertFalse(s.is_prefix("a"))
258 def test_is_channelname(self):
259 s = irc.NetworkInfo()
260 self.assertTrue(s.is_channelname("#bla"))
261 self.assertFalse(s.is_channelname("nietchannel"))
264 class NetworkNickTests(unittest.TestCase):
266 def test_create(self):
267 nick = irc.Nick("nick", "user", "host")
268 self.assertEquals("nick", nick.nick)
269 self.assertEquals("user", nick.username)
270 self.assertEquals("host", nick.hostname)
271 self.assertEquals("nick!user@host", nick.hostmask)
273 def test_set_hostmask(self):
274 nick = irc.Nick("nick", "user", "host")
275 nick.hostmask = "my!new@mask"
276 self.assertEquals("my", nick.nick)
277 self.assertEquals("new", nick.username)
278 self.assertEquals("mask", nick.hostname)
279 self.assertEquals("my!new@mask", nick.hostmask)
281 def test_set_nick(self):
282 nick = irc.Nick("nick", "user", "host")
284 self.assertEquals("my", nick.nick)
285 self.assertEquals("user", nick.username)
286 self.assertEquals("host", nick.hostname)
287 self.assertEquals("my!user@host", nick.hostmask)
289 def test_set_username(self):
290 nick = irc.Nick("nick", "user", "host")
291 nick.username = "uname"
292 self.assertEquals("nick", nick.nick)
293 self.assertEquals("uname", nick.username)
294 self.assertEquals("host", nick.hostname)
295 self.assertEquals("nick!uname@host", nick.hostmask)
297 def test_default_mode(self):
298 nick = irc.Nick("nick", "user", "host")
299 self.assertEquals(None, nick.modes)
301 def test_set_mode(self):
302 nick = irc.Nick("nick", "user", "host")
304 self.assertEquals("+o", nick.modes)
306 def test_remove_mode(self):
307 nick = irc.Nick("nick", "user", "host")
309 self.assertEquals(None, nick.modes)
312 class QueryStackTests(unittest.TestCase):
315 self.stack = irc.QueryStack()
317 def test_empty(self):
318 self.assertEquals([], list(self.stack))
320 def test_privmsg(self):
321 self.stack.record("token", "PRIVMSG joe :bla")
322 entries = list(self.stack)
323 self.assertEquals(1, len(entries))
324 self.assertEquals("token", entries[0][0])
325 self.assertEquals("PRIVMSG", entries[0][1])
327 def test_privmsg2(self):
328 self.stack.record("token", "PRIVMSG joe :bla")
329 self.stack.record("token", "PRIVMSG bla :bar")
330 entries = list(self.stack)
331 self.assertEquals(2, len(entries))
332 self.assertEquals("token", entries[0][0])
333 self.assertEquals("PRIVMSG", entries[0][1])
334 self.assertEquals("token", entries[1][0])
335 self.assertEquals("PRIVMSG", entries[1][1])
337 def test_unknown_command(self):
338 self.stack.record("token", "IDONTKNOW joe :bla")
339 entries = list(self.stack)
340 self.assertEquals(1, len(entries))
341 self.assertEquals("token", entries[0][0])
342 self.assertEquals(None, entries[0][1])
343 self.assertEquals("token",
344 self.stack.response(":server 421 user :No such command"))
345 self.assertEquals([], list(self.stack))
347 def test_removes_old_unreplied(self):
348 self.stack.record("token1", "PRIVMSG joe :bla")
349 self.stack.record("token2", "UNKNOWN joe :bla")
350 entries = list(self.stack)
351 self.assertEquals(2, len(entries))
352 self.assertEquals("token1", entries[0][0])
353 self.assertEquals("token2", entries[1][0])
354 self.assertEquals("token2",
355 self.stack.response(":server 421 user :No such command"))
356 # FIXME: self.assertEquals([], list(self.stack))
359 class TransportTests(unittest.TestCase):
361 def test_create(self):
365 class DummyTransport(object):
366 """Trivial Transport."""
369 self._sent_lines = []
372 return [str(l) for l in self._sent_lines]
374 def send_line(self, line):
375 self._sent_lines.append(line)
377 def is_connected(self):
381 class ClientTests(unittest.TestCase):
383 def test_create(self):
384 c = irc.Client(DummyTransport(), "myorigin", "description")
386 def test_transport(self):
388 c = irc.Client(t, "myorigin", "description")
389 self.assertEquals(t, c.transport)
391 def test_authenticate(self):
392 c = irc.Client(DummyTransport(), "myorigin", "description")
393 self.assertEquals(False, c.authenticated)
394 c.inject_line("NICK mynick")
395 c.inject_line("USER a a a a")
396 self.assertTrue(c.state is not None)
397 self.assertEquals(True, c.authenticated)
399 def test_authenticated(self):
400 c = irc.Client(DummyTransport(), "myorigin", "description")
401 self.assertEquals(False, c.authenticated)
403 def test_state(self):
404 c = irc.Client(DummyTransport(), "myorigin", "description")
405 self.assertEquals(None, c.state)
407 def test_send_line(self):
409 c = irc.Client(t, "myorigin", "description")
410 c.send_line(":server NOTICE mynick :bla")
411 self.assertEquals(1, len(t._sent_lines))
412 self.assertEquals(":server NOTICE mynick :bla", str(t._sent_lines[0]))
414 def test_default_target(self):
415 c = irc.Client(DummyTransport(), "myorigin", "description")
416 self.assertEquals("*", c.default_target)
418 def test_default_origin(self):
419 c = irc.Client(DummyTransport(), "myorigin", "description")
420 self.assertEquals("myorigin", c.default_origin)
422 def test_own_hostmask_not_known(self):
423 c = irc.Client(DummyTransport(), "myorigin", "description")
424 self.assertEquals(None, c.own_hostmask)
426 def test_send_motd(self):
428 c = irc.Client(t, "myorigin", "description")
429 c.send_motd(["bla", "blie bloe"])
431 ':myorigin 375 * :Start of MOTD',
432 ':myorigin 372 * :bla',
433 ':myorigin 372 * :blie bloe',
434 ':myorigin 376 * :End of MOTD'], t.str_lines())
436 def test_send_luserchannels(self):
438 c = irc.Client(t, "myorigin", "description")
439 c.send_luserchannels(42)
440 self.assertEquals([':myorigin 254 * 42 :channels formed'],
443 def test_send_netsplit_none(self):
445 c = irc.Client(t, "myorigin", "description")
446 c.send_netsplit("us", "myserver")
447 self.assertEquals([], t.str_lines())
449 def test_send_channel_mode_none(self):
451 c = irc.Client(t, "myorigin", "description")
452 ch = irc.ChannelState("#ch")
453 c.send_channel_mode(ch)
454 self.assertEquals([], t.str_lines())
456 def test_send_banlist(self):
458 c = irc.Client(t, "myorigin", "description")
459 ch = irc.ChannelState("#ch")
461 self.assertEquals([':myorigin 368 * #ch :End of channel ban list'],
464 def test_send_nameslist(self):
466 c = irc.Client(t, "myorigin", "description")
467 ch = irc.ChannelState("#ch")
469 self.assertEquals([':myorigin 366 * #ch :End of /NAMES list'],
472 def test_send_channel_state(self):
474 c = irc.Client(t, "myorigin", "description")
475 ch = irc.ChannelState("#ch")
476 c.send_channel_state(ch)
479 ':myorigin 366 * #ch :End of /NAMES list'],
482 def test_send_channel_state_diff(self):
484 c = irc.Client(t, "myorigin", "description")
485 ch1 = irc.ChannelState("#ch")
486 ch2 = irc.ChannelState("#ch")
487 c.send_channel_state_diff(ch1, ch2)
488 self.assertEquals([], t.str_lines())
490 def test_send_topic(self):
492 c = irc.Client(t, "myorigin", "description")
493 ch = irc.ChannelState("#ch")
494 c.send_topic(ch, False)
495 self.assertEquals([], t.str_lines())
496 c.send_topic(ch, True)
497 self.assertEquals([':myorigin 331 * #ch :No topic set'], t.str_lines())
500 ch.topic_set_time = 4324324L
502 self.assertEquals([':myorigin 332 * #ch :LALALA'], t.str_lines())
504 def test_last_ping(self):
506 c = irc.Client(t, "myorigin", "description")
507 self.assertEquals(0, c.last_ping)
509 def test_last_pong(self):
511 c = irc.Client(t, "myorigin", "description")
512 self.assertEquals(0, c.last_pong)
514 def test_description(self):
516 c = irc.Client(t, "myorigin", "description")
517 self.assertEquals("description", c.description)
520 class ClientSendStateTests(unittest.TestCase):
523 super(ClientSendStateTests, self).setUp()
524 self.transport = DummyTransport()
525 self.client = irc.Client(self.transport, "myorigin", "description")
526 self.state = irc.NetworkState("nick", "user", "host")
528 def assertLines(self, lines):
529 self.assertEquals(lines, self.transport.str_lines())
531 def test_empty(self):
532 self.client.send_state(self.state)
535 def test_with_channel(self):
536 ch = irc.ChannelState("#foo")
539 self.client.send_state(self.state)
542 ':myorigin 332 * #foo :bla la',
543 ':myorigin 366 * #foo :End of /NAMES list'])
545 def test_empty_diff(self):
546 self.client.send_state_diff(self.state, self.state)
550 class NetworkStateDiffTests(unittest.TestCase):
553 super(NetworkStateDiffTests, self).setUp()
554 self.transport = DummyTransport()
555 self.client = irc.Client(self.transport, "myorigin", "description")
556 self.state1 = irc.NetworkState("nick", "user", "host")
557 self.state2 = irc.NetworkState("nick", "user", "host")
559 def assertLines(self, lines):
560 self.assertEquals(lines, self.transport.str_lines())
562 def test_new_channel(self):
563 self.state2.add(irc.ChannelState("#foo"))
564 self.client.send_state_diff(self.state1, self.state2)
565 self.assertLines(['JOIN #foo',
566 ':myorigin 366 * #foo :End of /NAMES list'])
568 def test_leave_channel(self):
569 self.state1.add(irc.ChannelState("#foo"))
570 self.client.send_state_diff(self.state1, self.state2)
571 self.assertLines(['PART #foo'])
574 class ChannelStateDiffTests(unittest.TestCase):
577 super(ChannelStateDiffTests, self).setUp()
578 self.transport = DummyTransport()
579 self.client = irc.Client(self.transport, "myorigin", "description")
580 self.state1 = irc.NetworkState("nick", "user", "host")
581 self.state2 = irc.NetworkState("nick", "user", "host")
582 self.channel1 = irc.ChannelState("#foo")
583 self.channel2 = irc.ChannelState("#foo")
584 self.state1.add(self.channel1)
585 self.state2.add(self.channel2)
587 def assertLines(self, lines):
588 self.assertEquals(lines, self.transport.str_lines())
590 def test_diff_topic_set(self):
591 self.channel2.topic = "bla la"
592 self.client.send_state_diff(self.state1, self.state2)
593 self.assertLines(['TOPIC #foo :bla la'])
595 def test_diff_topic_unset(self):
596 self.channel1.topic = "bla la"
597 self.client.send_state_diff(self.state1, self.state2)
598 self.assertLines(['TOPIC #foo'])
600 def test_diff_nicks_leave(self):
601 self.channel1.nicks.add(irc.Nick("me!foo@bar"))
602 self.channel1.nicks.add(irc.Nick("you!foo@bar"))
603 self.client.send_state_diff(self.state1, self.state2)
604 self.assertLines([':me!foo@bar PART #foo', ':you!foo@bar PART #foo'])
606 def test_diff_nicks_join(self):
607 self.channel2.nicks.add(irc.Nick("me!foo@bar"))
608 self.channel2.nicks.add(irc.Nick("you!foo@bar"))
609 self.client.send_state_diff(self.state1, self.state2)
610 self.assertLines([':me!foo@bar JOIN #foo', ':you!foo@bar JOIN #foo'])
612 def test_diff_nick_change(self):
613 self.channel1.nicks.add(irc.Nick("me!foo@bar"))
614 self.channel2.nicks.add(irc.Nick("you!foo@bar"))
615 self.client.send_state_diff(self.state1, self.state2)
616 # FIXME: self.assertLines([':me!foo@bar NICK you'])
618 def test_diff_mode(self):
619 self.channel2.modes = "+r"
620 self.client.send_state_diff(self.state1, self.state2)
621 self.assertLines([':myorigin MODE #foo +r'])
623 def test_diff_mode_remove(self):
624 self.channel1.modes = "+p"
625 self.channel2.modes = "+r"
626 self.client.send_state_diff(self.state1, self.state2)
627 #FIXME: self.assertLines([':myorigin MODE #foo -p+r'])
630 class NetsplitTests(unittest.TestCase):
633 super(NetsplitTests, self).setUp()
634 self.transport = DummyTransport()
635 self.client = irc.Client(self.transport, "myserverorigin",
637 self.client.inject_line("NICK mynick")
638 self.client.inject_line("USER a a a a")
639 self.assertEquals(True, self.client.authenticated)
641 def assertLines(self, lines):
642 self.client.send_netsplit("us", "upstream")
643 self.assertEquals(lines, self.transport.str_lines())
645 def test_no_channels(self):
648 def test_channel_no_nicks(self):
649 self.client.state.add(irc.ChannelState("#foo"))
652 def test_channel_one_nick(self):
653 c = irc.ChannelState("#foo")
654 c.nicks.add(irc.Nick("somebody!someuser@somehost"))
655 self.client.state.add(c)
656 self.assertLines([":somebody!someuser@somehost QUIT :us upstream"])
658 def test_channel_lots_of_nicks(self):
659 c = irc.ChannelState("#foo")
661 c.nicks.add(irc.Nick("some%d!someuser@somehost" % i))
662 self.client.state.add(c)
663 self.assertLines([":some%d!someuser@somehost QUIT :us upstream" % i for i in range(10)])
666 class LinestackTests(unittest.TestCase):
668 def get_path(self, name):
669 return os.path.join("/tmp", name)
672 return irc.NetworkState("nick", "user", "host")
674 def test_create(self):
675 ls = irc.Linestack(self.get_path("network"), True, self.get_state())
676 self.assertTrue(ls is not None)
678 def test_insert_line(self):
679 state = self.get_state()
680 ls = irc.Linestack(self.get_path("insert_line"), True, state)
681 ls.insert_line(":somebody!some@host PRIVMSG #bla :BAR!",
682 irc.TO_SERVER, state)
684 def test_replay_simple(self):
685 state1 = self.get_state()
686 ls = irc.Linestack(self.get_path("insert_line"), True, state1)
688 ls.insert_line(":somebody!some@host JOIN #bla", irc.FROM_SERVER, state1)
689 state2 = self.get_state()
690 ls.replay(state2, m, ls.get_marker())
691 self.assertEquals(["#bla"], state2.channels.keys())
693 def test_traverse(self):
694 state = self.get_state()
695 ls = irc.Linestack(self.get_path("insert_line"), True, state)
697 ls.insert_line(":somebody!some@host JOIN #bla", irc.FROM_SERVER, state)
698 ls.insert_line(":somebody!some@host PRIVMSG #bla :BAR!",
699 irc.FROM_SERVER, state)
701 self.assertEquals([irc.Line(":somebody!some@host JOIN #bla"), irc.Line(":somebody!some@host PRIVMSG #bla :BAR!")], [l for (l, t) in ls.traverse(m1, m2)])