net-irc 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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