993c5b830c7d0e34019a7949bbcaedbf8f61c4c7
[jelmer/ctrlproxy.git] / libirc / python / tests / test_irc.py
1 # Copyright (C) 2005-2008 Jelmer Vernooij <jelmer@samba.org>
2  
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.
7
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.
12
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/>.
15
16 import irc
17 import os
18 import unittest
19
20 class LineTestCase(unittest.TestCase):
21
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")
26
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")
35
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")
44
45     def test_create_other(self):
46         l = irc.Line(":origin PRIVMSG bla")
47         newl = irc.Line(l)
48         self.assertEquals(str(l), str(newl))
49
50     def test_create_inval(self):
51         self.assertRaises(TypeError, irc.Line, 1)
52
53     def test__str__(self):
54         l = irc.Line(":origin PRIVMSG bla")
55         self.assertEquals(str(l), ":origin PRIVMSG bla")
56
57     def test_repr(self):
58         l = irc.Line(":origin PRIVMSG bla")
59         self.assertEquals(repr(l), "Line(':origin PRIVMSG bla')")
60
61     def test_get_nick(self):
62         l = irc.Line(":origin PRIVMSG bla")
63         self.assertEquals(l.get_nick(), "origin")
64
65     def test_len(self):
66         l = irc.Line(":origin PRIVMSG bla")
67         self.assertEquals(len(l), 2)
68
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])
74
75
76 class ChannelStateTests(unittest.TestCase):
77
78     def test_create(self):
79         s = irc.ChannelState("#foo")
80         self.assertTrue(s is not None)
81         self.assertEquals("#foo", s.name)
82
83     def test_nicks(self):
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"])
88
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)
94
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"))
101
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'])
107
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'])
113
114     def test_get_modes(self):
115         s = irc.ChannelState("#foo")
116         self.assertEquals("", s.modes)
117
118     def test_set_modes(self):
119         s = irc.ChannelState("#foo")
120         s.modes = "+n"
121         self.assertEquals("+n", s.modes)
122
123     def test_get_topic(self):
124         s = irc.ChannelState("#foo")
125         self.assertEquals(None, s.topic)
126
127     def test_set_topic(self):
128         s = irc.ChannelState("#foo")
129         s.topic = None
130         s.topic = "BLA"
131         self.assertEquals("BLA", s.topic)
132
133     def test_get_topic_time(self):
134         s = irc.ChannelState("#foo")
135         self.assertEquals(0, s.topic_set_time)
136
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)
141
142     def test_creationtime(self):
143         s = irc.ChannelState("#foo")
144         self.assertEquals(0, s.creation_time)
145
146     def test_creationtime_set(self):
147         s = irc.ChannelState("#foo")
148         s.creation_time = 423423
149         self.assertEquals(423423, s.creation_time)
150
151
152
153 class BaseNetworkStateTests(unittest.TestCase):
154
155     def test_create(self):
156         s = irc.NetworkState("nick", "user", "host")
157         self.assertTrue(s is not None)
158
159     def test_info(self):
160         s = irc.NetworkState("nick", "user", "host")
161         self.assertTrue(s.info is not None)
162
163
164 class NetworkStateTestCase(unittest.TestCase):
165
166     def setUp(self):
167         super(NetworkStateTestCase, self).setUp()
168         self.state = irc.NetworkState("nick", "user", "host")
169
170     def test_add_channel(self):
171         c = irc.ChannelState("#foo")
172         self.state.add(c)
173         self.assertEquals(c.name, self.state["#foo"].name)
174
175     def test_add_nick(self):
176         n = irc.Nick("me!user@host")
177         self.state.add(n)
178         self.assertEquals(n.nick, self.state["me"].nick)
179
180     def test_handle_line(self):
181         self.state.handle_line(":nick!user@host JOIN #foo")
182
183     def test_channels_empty(self):
184         self.assertEquals([], list(self.state.channels))
185         
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)
192
193     def test_get_channel(self):
194         self.state.handle_line(":nick!user@host JOIN #foo")
195         self.assertEquals(self.state["#foo"].name, "#foo")
196
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")
203
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])
209
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"])
214
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"])
220
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)
225
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))
229
230
231 class NetworkInfoTests(unittest.TestCase):
232
233     def test_create(self):
234         s = irc.NetworkInfo()
235         self.assertTrue(s is not None)
236
237     def test_prefix_by_mode(self):
238         s = irc.NetworkInfo()
239         self.assertEquals("@", s.get_prefix_by_mode("o"))
240
241     def test_irccmp_samecase(self):
242         s = irc.NetworkInfo()
243         self.assertEquals(s.irccmp("bla", "bla"), 0)
244
245     def test_irccmp_diff(self):
246         s = irc.NetworkInfo()
247         self.assertNotEqual(s.irccmp("bla", "bloe"), 0)
248
249     def test_irccmp_diffcase(self):
250         s = irc.NetworkInfo()
251         self.assertEqual(s.irccmp("BlA", "bla"), 0)
252
253     def test_is_prefix(self):
254         s = irc.NetworkInfo()
255         self.assertTrue(s.is_prefix("@"))
256         self.assertFalse(s.is_prefix("a"))
257
258     def test_is_channelname(self):
259         s = irc.NetworkInfo()
260         self.assertTrue(s.is_channelname("#bla"))
261         self.assertFalse(s.is_channelname("nietchannel"))
262
263
264 class NetworkNickTests(unittest.TestCase):
265
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)
272
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)
280
281     def test_set_nick(self):
282         nick = irc.Nick("nick", "user", "host")
283         nick.nick = "my"
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)
288
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)
296
297     def test_default_mode(self):
298         nick = irc.Nick("nick", "user", "host")
299         self.assertEquals(None, nick.modes)
300
301     def test_set_mode(self):
302         nick = irc.Nick("nick", "user", "host")
303         nick.modes = "+o"
304         self.assertEquals("+o", nick.modes)
305
306     def test_remove_mode(self):
307         nick = irc.Nick("nick", "user", "host")
308         nick.modes = ""
309         self.assertEquals(None, nick.modes)
310
311
312 class QueryStackTests(unittest.TestCase):
313
314     def setUp(self):
315         self.stack = irc.QueryStack()
316
317     def test_empty(self):
318         self.assertEquals([], list(self.stack))
319
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])
326
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])
336
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))
346
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))
357
358
359 class TransportTests(unittest.TestCase):
360
361     def test_create(self):
362         t = irc.Transport()
363
364
365 class DummyTransport(object):
366     """Trivial Transport."""
367
368     def __init__(self):
369         self._sent_lines = []
370
371     def str_lines(self):
372         return [str(l) for l in self._sent_lines]
373
374     def send_line(self, line):
375         self._sent_lines.append(line)
376
377     def is_connected(self):
378         return True
379
380
381 class ClientTests(unittest.TestCase):
382
383     def test_create(self):
384         c = irc.Client(DummyTransport(), "myorigin", "description")
385
386     def test_transport(self):
387         t = DummyTransport()
388         c = irc.Client(t, "myorigin", "description")
389         self.assertEquals(t, c.transport)
390
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)
398
399     def test_authenticated(self):
400         c = irc.Client(DummyTransport(), "myorigin", "description")
401         self.assertEquals(False, c.authenticated)
402
403     def test_state(self):
404         c = irc.Client(DummyTransport(), "myorigin", "description")
405         self.assertEquals(None, c.state)
406
407     def test_send_line(self):
408         t = DummyTransport()
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]))
413
414     def test_default_target(self):
415         c = irc.Client(DummyTransport(), "myorigin", "description")
416         self.assertEquals("*", c.default_target)
417
418     def test_default_origin(self):
419         c = irc.Client(DummyTransport(), "myorigin", "description")
420         self.assertEquals("myorigin", c.default_origin)
421
422     def test_own_hostmask_not_known(self):
423         c = irc.Client(DummyTransport(), "myorigin", "description")
424         self.assertEquals(None, c.own_hostmask)
425
426     def test_send_motd(self):
427         t = DummyTransport()
428         c = irc.Client(t, "myorigin", "description")
429         c.send_motd(["bla", "blie bloe"])
430         self.assertEquals([
431             ':myorigin 375 * :Start of MOTD',
432             ':myorigin 372 * :bla',
433             ':myorigin 372 * :blie bloe',
434             ':myorigin 376 * :End of MOTD'], t.str_lines())
435
436     def test_send_luserchannels(self):
437         t = DummyTransport()
438         c = irc.Client(t, "myorigin", "description")
439         c.send_luserchannels(42)
440         self.assertEquals([':myorigin 254 * 42 :channels formed'],
441                 t.str_lines())
442
443     def test_send_netsplit_none(self):
444         t = DummyTransport()
445         c = irc.Client(t, "myorigin", "description")
446         c.send_netsplit("us", "myserver")
447         self.assertEquals([], t.str_lines())
448
449     def test_send_channel_mode_none(self):
450         t = DummyTransport()
451         c = irc.Client(t, "myorigin", "description")
452         ch = irc.ChannelState("#ch")
453         c.send_channel_mode(ch)
454         self.assertEquals([], t.str_lines())
455
456     def test_send_banlist(self):
457         t = DummyTransport()
458         c = irc.Client(t, "myorigin", "description")
459         ch = irc.ChannelState("#ch")
460         c.send_banlist(ch)
461         self.assertEquals([':myorigin 368 * #ch :End of channel ban list'],
462             t.str_lines())
463
464     def test_send_nameslist(self):
465         t = DummyTransport()
466         c = irc.Client(t, "myorigin", "description")
467         ch = irc.ChannelState("#ch")
468         c.send_nameslist(ch)
469         self.assertEquals([':myorigin 366 * #ch :End of /NAMES list'],
470             t.str_lines())
471
472     def test_send_channel_state(self):
473         t = DummyTransport()
474         c = irc.Client(t, "myorigin", "description")
475         ch = irc.ChannelState("#ch")
476         c.send_channel_state(ch)
477         self.assertEquals([
478             'JOIN #ch', 
479             ':myorigin 366 * #ch :End of /NAMES list'],
480             t.str_lines())
481
482     def test_send_channel_state_diff(self):
483         t = DummyTransport()
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())
489
490     def test_send_topic(self):
491         t = DummyTransport()
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())
498         t._sent_lines = []
499         ch.topic = "LALALA"
500         ch.topic_set_time = 4324324L
501         c.send_topic(ch)
502         self.assertEquals([':myorigin 332 * #ch :LALALA'], t.str_lines())
503
504     def test_last_ping(self):
505         t = DummyTransport()
506         c = irc.Client(t, "myorigin", "description")
507         self.assertEquals(0, c.last_ping)
508
509     def test_last_pong(self):
510         t = DummyTransport()
511         c = irc.Client(t, "myorigin", "description")
512         self.assertEquals(0, c.last_pong)
513
514     def test_description(self):
515         t = DummyTransport()
516         c = irc.Client(t, "myorigin", "description")
517         self.assertEquals("description", c.description)
518
519
520 class ClientSendStateTests(unittest.TestCase):
521
522     def setUp(self):
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")
527
528     def assertLines(self, lines):
529         self.assertEquals(lines, self.transport.str_lines())
530
531     def test_empty(self):
532         self.client.send_state(self.state)
533         self.assertLines([])
534
535     def test_with_channel(self):
536         ch = irc.ChannelState("#foo")
537         ch.topic = "bla la"
538         self.state.add(ch)
539         self.client.send_state(self.state)
540         self.assertLines([
541             'JOIN #foo', 
542             ':myorigin 332 * #foo :bla la', 
543             ':myorigin 366 * #foo :End of /NAMES list'])
544
545     def test_empty_diff(self):
546         self.client.send_state_diff(self.state, self.state)
547         self.assertLines([])
548
549
550 class NetworkStateDiffTests(unittest.TestCase):
551
552     def setUp(self):
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")
558
559     def assertLines(self, lines):
560         self.assertEquals(lines, self.transport.str_lines())
561
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'])
567
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'])
572
573
574 class ChannelStateDiffTests(unittest.TestCase):
575
576     def setUp(self):
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)
586
587     def assertLines(self, lines):
588         self.assertEquals(lines, self.transport.str_lines())
589
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'])
594
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'])
599
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'])
605
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'])
611
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'])
617
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'])
622
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'])
628
629
630 class NetsplitTests(unittest.TestCase):
631
632     def setUp(self):
633         super(NetsplitTests, self).setUp()
634         self.transport = DummyTransport()
635         self.client = irc.Client(self.transport, "myserverorigin", 
636                 "description")
637         self.client.inject_line("NICK mynick")
638         self.client.inject_line("USER a a a a")
639         self.assertEquals(True, self.client.authenticated)
640
641     def assertLines(self, lines):
642         self.client.send_netsplit("us", "upstream")
643         self.assertEquals(lines, self.transport.str_lines())
644
645     def test_no_channels(self):
646         self.assertLines([])
647
648     def test_channel_no_nicks(self):
649         self.client.state.add(irc.ChannelState("#foo"))
650         self.assertLines([])
651
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"])
657
658     def test_channel_lots_of_nicks(self):
659         c = irc.ChannelState("#foo")
660         for i in range(10):
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)])
664
665
666 class LinestackTests(unittest.TestCase):
667
668     def get_path(self, name):
669         return os.path.join("/tmp", name)
670
671     def get_state(self):
672         return irc.NetworkState("nick", "user", "host")
673
674     def test_create(self):
675         ls = irc.Linestack(self.get_path("network"), True, self.get_state())
676         self.assertTrue(ls is not None)
677
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)
683
684     def test_replay_simple(self):
685         state1 = self.get_state()
686         ls = irc.Linestack(self.get_path("insert_line"), True, state1)
687         m = ls.get_marker()
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())
692
693     def test_traverse(self):
694         state = self.get_state()
695         ls = irc.Linestack(self.get_path("insert_line"), True, state)
696         m1 = ls.get_marker()
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)
700         m2 = ls.get_marker()
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)])