net-irc 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,30 @@
1
+ class Net::IRC::Message::ServerConfig
2
+ attr_reader :mode_parser
3
+
4
+ def initialize
5
+ @config = {}
6
+ @mode_parser = Net::IRC::Message::ModeParser.new
7
+ end
8
+
9
+ def set(arg)
10
+ params = arg.kind_of?(Net::IRC::Message) ? arg.to_a : arg.split(/\s+/)
11
+
12
+ params[1..-1].each do |s|
13
+ case s
14
+ when /^:?are supported by this server$/
15
+ # Ignore
16
+ when /^([^=]+)=(.*)$/
17
+ key = Regexp.last_match[1].to_sym
18
+ value = Regexp.last_match[2]
19
+ @config[key] = value
20
+ @mode_parser.set(key, value) if key == :CHANMODES || key == :PREFIX
21
+ else
22
+ @config[s] = true
23
+ end
24
+ end
25
+ end
26
+
27
+ def [](key)
28
+ @config[key]
29
+ end
30
+ end
@@ -0,0 +1,176 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH << "lib"
4
+ $LOAD_PATH << "../lib"
5
+
6
+ require "net/irc"
7
+ require "net/irc/client/channel_manager"
8
+ include Net::IRC
9
+ include Constants
10
+
11
+ class ChannelManagerTestServerSession < Net::IRC::Server::Session
12
+ @@testq = SizedQueue.new(1)
13
+ @@instance = nil
14
+
15
+ def self.testq
16
+ @@testq
17
+ end
18
+
19
+ def self.instance
20
+ @@instance
21
+ end
22
+
23
+ def initialize(*args)
24
+ super
25
+ @@instance = self
26
+ end
27
+
28
+ def on_message(m)
29
+ @@testq << m
30
+ end
31
+ end
32
+
33
+ class ChannelManagerTestClient < Net::IRC::Client
34
+ include Net::IRC::Client::ChannelManager
35
+ @@testq = SizedQueue.new(1)
36
+
37
+ def self.testq
38
+ @@testq
39
+ end
40
+
41
+ def on_message(m)
42
+ @@testq << m
43
+ end
44
+ end
45
+
46
+ describe Net::IRC, "server and client" do
47
+ before :all do
48
+ @port = nil
49
+ @server, @client = nil, nil
50
+
51
+ Thread.abort_on_exception = true
52
+ Thread.start do
53
+ @server = Net::IRC::Server.new("localhost", @port, ChannelManagerTestServerSession, {
54
+ :logger => Logger.new(nil),
55
+ })
56
+ @server.start
57
+ end
58
+
59
+ true until @server.instance_variable_get(:@serv)
60
+
61
+ @port = @server.instance_variable_get(:@serv).addr[1]
62
+
63
+ Thread.start do
64
+ @client = ChannelManagerTestClient.new("localhost", @port, {
65
+ :nick => "foonick",
66
+ :user => "foouser",
67
+ :real => "foo real name",
68
+ :pass => "foopass",
69
+ :logger => Logger.new(nil),
70
+ })
71
+ @client.start
72
+ end
73
+ end
74
+
75
+ server_q = ChannelManagerTestServerSession.testq
76
+ client_q = ChannelManagerTestClient.testq
77
+
78
+ it "client should manage channel mode/users correctly" do
79
+ client = @client
80
+ client.instance_variable_set(:@prefix, Prefix.new("foonick!foouser@localhost"))
81
+
82
+ ChannelManagerTestServerSession.instance.instance_eval do
83
+ Thread.exclusive do
84
+ post client.prefix, JOIN, "#test"
85
+ post nil, NOTICE, "#test", "sep1"
86
+ end
87
+ end
88
+
89
+ true until client_q.pop.to_s == "NOTICE #test sep1\r\n"
90
+
91
+ c = @client.instance_variable_get(:@channels)
92
+ c.synchronize do
93
+ c.should be_a_kind_of(Hash)
94
+ c["#test"].should be_a_kind_of(Hash)
95
+ c["#test"][:modes].should be_a_kind_of(Array)
96
+ c["#test"][:users].should be_a_kind_of(Array)
97
+ c["#test"][:users].should == ["foonick"]
98
+ end
99
+
100
+ ChannelManagerTestServerSession.instance.instance_eval do
101
+ Thread.exclusive do
102
+ post "test1!test@localhost", JOIN, "#test"
103
+ post "test2!test@localhost", JOIN, "#test"
104
+ post nil, NOTICE, "#test", "sep2"
105
+ end
106
+ end
107
+
108
+ true until client_q.pop.to_s == "NOTICE #test sep2\r\n"
109
+ c.synchronize do
110
+ c["#test"][:users].should == ["foonick", "test1", "test2"]
111
+ end
112
+
113
+ ChannelManagerTestServerSession.instance.instance_eval do
114
+ Thread.exclusive do
115
+ post nil, RPL_NAMREPLY, client.prefix.nick, "@", "#test", "foo1 foo2 foo3 @foo4 +foo5"
116
+ post nil, NOTICE, "#test", "sep3"
117
+ end
118
+ end
119
+
120
+ true until client_q.pop.to_s == "NOTICE #test sep3\r\n"
121
+ c.synchronize do
122
+ c["#test"][:users].should == ["foonick", "test1", "test2", "foo1", "foo2", "foo3", "foo4", "foo5"]
123
+ c["#test"][:modes].should include([:s, nil])
124
+ c["#test"][:modes].should include([:o, "foo4"])
125
+ c["#test"][:modes].should include([:v, "foo5"])
126
+ end
127
+
128
+ ChannelManagerTestServerSession.instance.instance_eval do
129
+ Thread.exclusive do
130
+ post nil, RPL_NAMREPLY, client.prefix.nick, "@", "#test1", "foo1 foo2 foo3 @foo4 +foo5"
131
+ post "foo4!foo@localhost", QUIT, "message"
132
+ post "foo5!foo@localhost", PART, "#test1", "message"
133
+ post client.prefix, KICK, "#test", "foo1", "message"
134
+ post client.prefix, MODE, "#test", "+o", "foo2"
135
+ post nil, NOTICE, "#test", "sep4"
136
+ end
137
+ end
138
+
139
+ true until client_q.pop.to_s == "NOTICE #test sep4\r\n"
140
+ c.synchronize do
141
+ c["#test"][:users].should == ["foonick", "test1", "test2", "foo2", "foo3", "foo5"]
142
+ c["#test1"][:users].should == ["foo1", "foo2", "foo3"]
143
+ c["#test"][:modes].should_not include([:o, "foo4"])
144
+ c["#test"][:modes].should include([:v, "foo5"])
145
+ c["#test1"][:modes].should_not include([:v, "foo5"])
146
+ c["#test"][:modes].should include([:o, "foo2"])
147
+ end
148
+
149
+ ChannelManagerTestServerSession.instance.instance_eval do
150
+ Thread.exclusive do
151
+ post "foonick!test@localhost", NICK, "foonick2"
152
+ post "foonick2!test@localhost", NICK, "foonick"
153
+ post "foo2!test@localhost", NICK, "bar2"
154
+ post "foo3!test@localhost", NICK, "bar3"
155
+ post nil, NOTICE, "#test", "sep5"
156
+ end
157
+ end
158
+
159
+ true until client_q.pop.to_s == "NOTICE #test sep5\r\n"
160
+ c.synchronize do
161
+ c["#test"][:users].should == ["foonick", "test1", "test2", "bar2", "bar3", "foo5"]
162
+ c["#test1"][:users].should == ["foo1", "bar2", "bar3"]
163
+ c["#test"][:modes].should_not include([:o, "foo4"])
164
+ c["#test"][:modes].should include([:v, "foo5"])
165
+ c["#test1"][:modes].should_not include([:v, "foo5"])
166
+ c["#test"][:modes].should_not include([:o, "foo2"])
167
+ c["#test"][:modes].should include([:o, "bar2"])
168
+ end
169
+ end
170
+
171
+ after :all do
172
+ @server.finish
173
+ @client.finish
174
+ end
175
+ end
176
+
@@ -6,38 +6,160 @@ require "net/irc"
6
6
  include Net::IRC
7
7
  include Constants
8
8
 
9
-
10
9
  describe Message::ModeParser do
11
- it "should parse RFC1459 correctly" do
12
- Message::ModeParser::RFC1459::Channel.parse("#Finish +im")[:positive].should == [[:i, nil], [:m, nil]]
13
- Message::ModeParser::RFC1459::Channel.parse("#Finish +o Kilroy")[:positive].should == [[:o, "Kilroy"]]
14
- Message::ModeParser::RFC1459::Channel.parse("#Finish +v Kilroy")[:positive].should == [[:v, "Kilroy"]]
15
- Message::ModeParser::RFC1459::Channel.parse("#Fins -s")[:negative].should == [[:s, nil]]
16
- Message::ModeParser::RFC1459::Channel.parse("#42 +k oulu")[:positive].should == [[:k, "oulu"]]
17
- Message::ModeParser::RFC1459::Channel.parse("#eu-opers +l 10")[:positive].should == [[:l, "10"]]
18
- Message::ModeParser::RFC1459::Channel.parse("&oulu +b")[:positive].should == [[:b, nil]]
19
- Message::ModeParser::RFC1459::Channel.parse("&oulu +b *!*@*")[:positive].should == [[:b, "*!*@*"]]
20
- Message::ModeParser::RFC1459::Channel.parse("&oulu +b *!*@*.edu")[:positive].should == [[:b, "*!*@*.edu"]]
21
-
22
- Message::ModeParser::RFC1459::Channel.parse("#foo +ooo foo bar baz").should == {
10
+ it "should parse RFC2812+ correctly" do
11
+ parser = Message::ModeParser.new
12
+
13
+ parser.parse("#Finish +im")[:positive].should == [[:i, nil], [:m, nil]]
14
+ parser.parse("#Finish +o Kilroy")[:positive].should == [[:o, "Kilroy"]]
15
+ parser.parse("#Finish +v Kilroy")[:positive].should == [[:v, "Kilroy"]]
16
+ parser.parse("#Fins -s")[:negative].should == [[:s, nil]]
17
+ parser.parse("#42 +k oulu")[:positive].should == [[:k, "oulu"]]
18
+ parser.parse("#eu-opers +l 10")[:positive].should == [[:l, "10"]]
19
+ parser.parse("&oulu +b")[:positive].should == [[:b, nil]]
20
+ parser.parse("&oulu +b *!*@*")[:positive].should == [[:b, "*!*@*"]]
21
+
22
+ parser.parse("&oulu +b *!*@*.edu")[:positive].should == [[:b, "*!*@*.edu"]]
23
+ parser.parse("#oulu +e")[:positive].should == [[:e, nil]]
24
+ parser.parse("#oulu +e *!*@*.edu")[:positive].should == [[:e, "*!*@*.edu"]]
25
+ parser.parse("#oulu +I")[:positive].should == [[:I, nil]]
26
+ parser.parse("#oulu +I *!*@*.edu")[:positive].should == [[:I, "*!*@*.edu"]]
27
+ parser.parse("#oulu +R")[:positive].should == [[:R, nil]]
28
+ parser.parse("#oulu +R *!*@*.edu")[:positive].should == [[:R, "*!*@*.edu"]]
29
+
30
+ parser.parse("#foo +ooo foo bar baz").should == {
23
31
  :positive => [[:o, "foo"], [:o, "bar"], [:o, "baz"]],
24
32
  :negative => [],
25
33
  }
26
- Message::ModeParser::RFC1459::Channel.parse("#foo +oo-o foo bar baz").should == {
34
+ parser.parse("#foo +oo-o foo bar baz").should == {
27
35
  :positive => [[:o, "foo"], [:o, "bar"]],
28
36
  :negative => [[:o, "baz"]],
29
37
  }
30
- Message::ModeParser::RFC1459::Channel.parse("#foo -oo+o foo bar baz").should == {
38
+ parser.parse("#foo -oo+o foo bar baz").should == {
31
39
  :positive => [[:o, "baz"]],
32
40
  :negative => [[:o, "foo"], [:o, "bar"]],
33
41
  }
34
- Message::ModeParser::RFC1459::Channel.parse("#foo +imv foo").should == {
42
+ parser.parse("#foo +imv foo").should == {
35
43
  :positive => [[:i, nil], [:m, nil], [:v, "foo"]],
36
44
  :negative => [],
37
45
  }
46
+
47
+ parser.parse("#foo +lk 10 foo").should == {
48
+ :positive => [[:l, "10"], [:k, "foo"]],
49
+ :negative => [],
50
+ }
51
+ parser.parse("#foo -l+k foo").should == {
52
+ :positive => [[:k, "foo"]],
53
+ :negative => [[:l, nil]],
54
+ }
55
+ parser.parse("#foo +ao foo").should == {
56
+ :positive => [[:a, nil], [:o, "foo"]],
57
+ :negative => [],
58
+ }
59
+ end
60
+
61
+ it "should parse modes of Hyperion ircd correctly" do
62
+ parser = Message::ModeParser.new
63
+ parser.set(:CHANMODES, 'bdeIq,k,lfJD,cgijLmnPQrRstz')
64
+
65
+ parser.parse("#Finish +im")[:positive].should == [[:i, nil], [:m, nil]]
66
+ parser.parse("#Finish +o Kilroy")[:positive].should == [[:o, "Kilroy"]]
67
+ parser.parse("#Finish +v Kilroy")[:positive].should == [[:v, "Kilroy"]]
68
+ parser.parse("#Fins -s")[:negative].should == [[:s, nil]]
69
+ parser.parse("#42 +k oulu")[:positive].should == [[:k, "oulu"]]
70
+ parser.parse("#eu-opers +l 10")[:positive].should == [[:l, "10"]]
71
+ parser.parse("&oulu +b")[:positive].should == [[:b, nil]]
72
+ parser.parse("&oulu +b *!*@*")[:positive].should == [[:b, "*!*@*"]]
73
+ parser.parse("&oulu +b *!*@*.edu")[:positive].should == [[:b, "*!*@*.edu"]]
74
+
75
+ parser.parse("#oulu +e")[:positive].should == [[:e, nil]]
76
+ parser.parse("#oulu +e *!*@*.edu")[:positive].should == [[:e, "*!*@*.edu"]]
77
+ parser.parse("#oulu +I")[:positive].should == [[:I, nil]]
78
+ parser.parse("#oulu +I *!*@*.edu")[:positive].should == [[:I, "*!*@*.edu"]]
38
79
 
39
- Message::ModeParser::RFC1459::User.parse("WIZ -w")[:negative].should == [[:w, nil]]
40
- Message::ModeParser::RFC1459::User.parse("ANGEL +i")[:positive].should == [[:i, nil]]
41
- Message::ModeParser::RFC1459::User.parse("WIZ -o")[:negative].should == [[:o, nil]]
80
+ parser.parse("#foo +ooo foo bar baz").should == {
81
+ :positive => [[:o, "foo"], [:o, "bar"], [:o, "baz"]],
82
+ :negative => [],
83
+ }
84
+ parser.parse("#foo +oo-o foo bar baz").should == {
85
+ :positive => [[:o, "foo"], [:o, "bar"]],
86
+ :negative => [[:o, "baz"]],
87
+ }
88
+ parser.parse("#foo -oo+o foo bar baz").should == {
89
+ :positive => [[:o, "baz"]],
90
+ :negative => [[:o, "foo"], [:o, "bar"]],
91
+ }
92
+ parser.parse("#foo +imv foo").should == {
93
+ :positive => [[:i, nil], [:m, nil], [:v, "foo"]],
94
+ :negative => [],
95
+ }
96
+
97
+ parser.parse("#foo +lk 10 foo").should == {
98
+ :positive => [[:l, "10"], [:k, "foo"]],
99
+ :negative => [],
100
+ }
101
+ parser.parse("#foo -l+k foo").should == {
102
+ :positive => [[:k, "foo"]],
103
+ :negative => [[:l, nil]],
104
+ }
105
+ parser.parse("#foo +cv foo").should == {
106
+ :positive => [[:c, nil], [:v, "foo"]],
107
+ :negative => [],
108
+ }
109
+ end
110
+
111
+ it "should parse modes of Unreal ircd correctly" do
112
+ parser = Message::ModeParser.new
113
+ parser.set(:PREFIX, '(qaohv)~&@%+')
114
+ parser.set(:CHANMODES, 'beI,kfL,lj,psmntirRcOAQKVCuzNSMTG')
115
+
116
+ parser.parse("#Finish +im")[:positive].should == [[:i, nil], [:m, nil]]
117
+ parser.parse("#Finish +o Kilroy")[:positive].should == [[:o, "Kilroy"]]
118
+ parser.parse("#Finish +v Kilroy")[:positive].should == [[:v, "Kilroy"]]
119
+ parser.parse("#Fins -s")[:negative].should == [[:s, nil]]
120
+ parser.parse("#42 +k oulu")[:positive].should == [[:k, "oulu"]]
121
+ parser.parse("#eu-opers +l 10")[:positive].should == [[:l, "10"]]
122
+ parser.parse("&oulu +b")[:positive].should == [[:b, nil]]
123
+ parser.parse("&oulu +b *!*@*")[:positive].should == [[:b, "*!*@*"]]
124
+ parser.parse("&oulu +b *!*@*.edu")[:positive].should == [[:b, "*!*@*.edu"]]
125
+
126
+ parser.parse("#oulu +e")[:positive].should == [[:e, nil]]
127
+ parser.parse("#oulu +e *!*@*.edu")[:positive].should == [[:e, "*!*@*.edu"]]
128
+ parser.parse("#oulu +I")[:positive].should == [[:I, nil]]
129
+ parser.parse("#oulu +I *!*@*.edu")[:positive].should == [[:I, "*!*@*.edu"]]
130
+
131
+ parser.parse("#foo +ooo foo bar baz").should == {
132
+ :positive => [[:o, "foo"], [:o, "bar"], [:o, "baz"]],
133
+ :negative => [],
134
+ }
135
+ parser.parse("#foo +oo-o foo bar baz").should == {
136
+ :positive => [[:o, "foo"], [:o, "bar"]],
137
+ :negative => [[:o, "baz"]],
138
+ }
139
+ parser.parse("#foo -oo+o foo bar baz").should == {
140
+ :positive => [[:o, "baz"]],
141
+ :negative => [[:o, "foo"], [:o, "bar"]],
142
+ }
143
+ parser.parse("#foo +imv foo").should == {
144
+ :positive => [[:i, nil], [:m, nil], [:v, "foo"]],
145
+ :negative => [],
146
+ }
147
+
148
+ parser.parse("#foo +lk 10 foo").should == {
149
+ :positive => [[:l, "10"], [:k, "foo"]],
150
+ :negative => [],
151
+ }
152
+ parser.parse("#foo -l+k foo").should == {
153
+ :positive => [[:k, "foo"]],
154
+ :negative => [[:l, nil]],
155
+ }
156
+ parser.parse("#foo -q+ah foo bar baz").should == {
157
+ :positive => [[:a, "bar"], [:h, "baz"]],
158
+ :negative => [[:q, "foo"]],
159
+ }
160
+ parser.parse("#foo +Av foo").should == {
161
+ :positive => [[:A, nil], [:v, "foo"]],
162
+ :negative => [],
163
+ }
42
164
  end
43
165
  end
@@ -53,6 +53,15 @@ describe Net::IRC::Message, "construct" do
53
53
  channel.should == "#channel"
54
54
  message.should == "message"
55
55
  end
56
+
57
+ it "#to_a should return duplicated array" do
58
+ m = Message.new("foo", "PRIVMSG", ["#channel", "message"])
59
+ m[0].should == m.params[0]
60
+ m[1].should == m.params[1]
61
+ m.to_a.should == ["#channel", "message"]
62
+ m.to_a.clear
63
+ m.to_a.should == ["#channel", "message"]
64
+ end
56
65
  end
57
66
 
58
67
  describe Net::IRC::Message, "parse" do
@@ -268,75 +277,6 @@ describe Net::IRC, "server and client" do
268
277
  message.to_s.should == "PRIVMSG #channel :message a b c\r\n"
269
278
  end
270
279
 
271
- it "client should manage channel mode/users correctly" do
272
- client = @client
273
- c = @client.instance_variable_get(:@channels)
274
- TestServerSession.instance.instance_eval do
275
- Thread.exclusive do
276
- post client.prefix, JOIN, "#test"
277
- post nil, NOTICE, "#test", "sep1"
278
- end
279
- end
280
-
281
- true until client_q.pop.to_s == "NOTICE #test sep1\r\n"
282
- c.synchronize do
283
- c.should be_a_kind_of(Hash)
284
- c["#test"].should be_a_kind_of(Hash)
285
- c["#test"][:modes].should be_a_kind_of(Array)
286
- c["#test"][:users].should be_a_kind_of(Array)
287
- c["#test"][:users].should == ["foonick"]
288
- end
289
-
290
- TestServerSession.instance.instance_eval do
291
- Thread.exclusive do
292
- post "test1!test@localhost", JOIN, "#test"
293
- post "test2!test@localhost", JOIN, "#test"
294
- post nil, NOTICE, "#test", "sep2"
295
- end
296
- end
297
-
298
- true until client_q.pop.to_s == "NOTICE #test sep2\r\n"
299
- c.synchronize do
300
- c["#test"][:users].should == ["foonick", "test1", "test2"]
301
- end
302
-
303
- TestServerSession.instance.instance_eval do
304
- Thread.exclusive do
305
- post nil, RPL_NAMREPLY, client.prefix.nick, "@", "#test", "foo1 foo2 foo3 @foo4 +foo5"
306
- post nil, NOTICE, "#test", "sep3"
307
- end
308
- end
309
-
310
- true until client_q.pop.to_s == "NOTICE #test sep3\r\n"
311
- c.synchronize do
312
- c["#test"][:users].should == ["foonick", "test1", "test2", "foo1", "foo2", "foo3", "foo4", "foo5"]
313
- c["#test"][:modes].should include([:s, nil])
314
- c["#test"][:modes].should include([:o, "foo4"])
315
- c["#test"][:modes].should include([:v, "foo5"])
316
- end
317
-
318
- TestServerSession.instance.instance_eval do
319
- Thread.exclusive do
320
- post nil, RPL_NAMREPLY, client.prefix.nick, "@", "#test1", "foo1 foo2 foo3 @foo4 +foo5"
321
- post "foo4!foo@localhost", QUIT, "message"
322
- post "foo5!foo@localhost", PART, "#test1", "message"
323
- post client.prefix, KICK, "#test", "foo1", "message"
324
- post client.prefix, MODE, "#test", "+o", "foo2"
325
- post nil, NOTICE, "#test", "sep4"
326
- end
327
- end
328
-
329
- true until client_q.pop.to_s == "NOTICE #test sep4\r\n"
330
- c.synchronize do
331
- c["#test"][:users].should == ["foonick", "test1", "test2", "foo2", "foo3", "foo5"]
332
- c["#test1"][:users].should == ["foo1", "foo2", "foo3"]
333
- c["#test"][:modes].should_not include([:o, "foo4"])
334
- c["#test"][:modes].should include([:v, "foo5"])
335
- c["#test1"][:modes].should_not include([:v, "foo5"])
336
- c["#test"][:modes].should include([:o, "foo2"])
337
- end
338
- end
339
-
340
280
  it "should allow lame RPL_WELCOME (not prefix but nick)" do
341
281
  client = @client
342
282
  TestServerSession.instance.instance_eval do