net-yail 1.4.3 → 1.4.4

Sign up to get free protection for your applications and to get access to all the features.
data/lib/net/yail.rb CHANGED
@@ -277,6 +277,9 @@ class YAIL
277
277
  # * <tt>:username</tt>: Username reported to server
278
278
  # * <tt>:realname</tt>: Real name reported to server
279
279
  # * <tt>:nicknames</tt>: Array of nicknames to cycle through
280
+ # * <tt>:io</tt>: TCP replacement object to use, should already be connected and ready for sending
281
+ # the "connect" data (:outgoing_begin_connection handler does this)
282
+ # If this is passed, :address and :port are ignored.
280
283
  # * <tt>:silent</tt>: DEPRECATED - Sets Logger level to FATAL and silences most non-Logger
281
284
  # messages.
282
285
  # * <tt>:loud</tt>: DEPRECATED - Sets Logger level to DEBUG. Spits out too many messages for your own good,
@@ -298,6 +301,7 @@ class YAIL
298
301
  @username = options[:username]
299
302
  @realname = options[:realname]
300
303
  @address = options[:address]
304
+ @io = options[:io]
301
305
  @port = options[:port] || 6667
302
306
  @log_silent = options[:silent] || false
303
307
  @log_loud = options[:loud] || false
@@ -312,15 +316,15 @@ class YAIL
312
316
  @log = Logger.new(options[:log_io] || STDERR)
313
317
  @log.level = Logger::WARN
314
318
 
319
+ if (options[:silent] || options[:loud])
320
+ @log.warn '[DEPRECATED] - passing :silent and :loud options to constructor are deprecated as of 1.4.1'
321
+ end
322
+
315
323
  # Convert old-school options into logger stuff
316
324
  @log.level = Logger::DEBUG if @log_loud
317
325
  @log.level = Logger::FATAL if @log_silent
318
326
  end
319
327
 
320
- if (options[:silent] || options[:loud])
321
- @log.warn '[DEPRECATED] - passing :silent and :loud options to constructor are deprecated as of 1.4.1'
322
- end
323
-
324
328
  # Read in map of event numbers and names. Yes, I stole this event map
325
329
  # file from RubyIRC and made very minor changes.... They stole it from
326
330
  # somewhere else anyway, so it's okay.
@@ -331,13 +335,17 @@ class YAIL
331
335
  @dead_socket = false
332
336
 
333
337
  # Build our socket - if something goes wrong, it's immediately a dead socket.
334
- begin
335
- @socket = TCPSocket.new(@address, @port)
336
- setup_ssl if @ssl
337
- rescue StandardError => boom
338
- @log.fatal "+++ERROR: Unable to open socket connection in Net::YAIL.initialize: #{boom.inspect}"
339
- @dead_socket = true
340
- raise
338
+ if @io
339
+ @socket = @io
340
+ else
341
+ begin
342
+ @socket = TCPSocket.new(@address, @port)
343
+ setup_ssl if @ssl
344
+ rescue StandardError => boom
345
+ @log.fatal "+++ERROR: Unable to open socket connection in Net::YAIL.initialize: #{boom.inspect}"
346
+ @dead_socket = true
347
+ raise
348
+ end
341
349
  end
342
350
 
343
351
  # Shared resources for threads to try and coordinate.... I know very
@@ -350,7 +358,6 @@ class YAIL
350
358
 
351
359
  # Buffered output is allowed to go out right away.
352
360
  @next_message_time = Time.now
353
-
354
361
  # Setup handlers
355
362
  @handlers = Hash.new
356
363
  setup_default_handlers
@@ -476,8 +483,19 @@ class YAIL
476
483
  # forever for incoming data, and calling handlers due to this listening
477
484
  def io_loop
478
485
  loop do
479
- # if no data is coming in, don't block the socket!
480
- read_incoming_data if Kernel.select([@socket], nil, nil, 0)
486
+ # Possible fix for SSL one-message-behind issue from BP - thanks!
487
+ #
488
+ # If SSL, we just assume we're ready so we're always grabbing the latest message(s) from the
489
+ # socket. I don't know if this will have any side-effects, but it seems to work in at least
490
+ # one situation, sooo....
491
+ ready = true if @ssl
492
+ unless ready
493
+ # if no data is coming in, don't block the socket! To allow for mocked IO objects, allow
494
+ # a non-IO to let us know if it's ready
495
+ ready = @socket.kind_of?(IO) ? Kernel.select([@socket], nil, nil, 0) : @socket.ready?
496
+ end
497
+
498
+ read_incoming_data if ready
481
499
 
482
500
  # Check for dead socket
483
501
  @dead_socket = true if @socket.eof?
@@ -1,5 +1,5 @@
1
1
  module Net
2
2
  class YAIL
3
- VERSION = '1.4.3'
3
+ VERSION = '1.4.4'
4
4
  end
5
5
  end
data/tests/mock_irc.rb ADDED
@@ -0,0 +1,153 @@
1
+ # An IO-like class that does IRC-like magic for us
2
+ class MockIRC
3
+ SERVER = "fakeirc.org"
4
+ USERHOST = "fakey@nerdbucket.com"
5
+
6
+ # Init - just call super and set up a couple vars
7
+ def initialize(*args)
8
+ super
9
+ @connected = false
10
+ @logged_in = false
11
+ @closed = false
12
+ @server = ''
13
+ @output = []
14
+ @mutex = Mutex.new
15
+ end
16
+
17
+ # All output sent to the IO uses puts in YAIL. I hope.
18
+ def puts(*args)
19
+ @mutex.synchronize do
20
+ for string in args
21
+ handle_command(string.strip)
22
+ end
23
+ end
24
+ return nil
25
+ end
26
+
27
+ # Lets us know if we are an open "socket" or not - if the socket is closed *and* we're out of
28
+ # output, we are done
29
+ def eof
30
+ @mutex.synchronize do
31
+ return @output.empty? && @closed
32
+ end
33
+ end
34
+
35
+ alias_method :eof?, :eof
36
+
37
+ # Pulls the first element off of @output
38
+ def gets
39
+ output = nil
40
+ @mutex.synchronize do
41
+ output = @output.shift
42
+ end
43
+
44
+ puts "WTF NO DATA!" if !output
45
+
46
+ return output
47
+ end
48
+
49
+ # Hack to let YAIL know if we have data to read
50
+ def ready?
51
+ return @output.empty? ? nil : true
52
+ end
53
+
54
+ # All the magic goes here
55
+ def handle_command(cmd)
56
+ unless @connected
57
+ handle_connected(cmd)
58
+ return
59
+ end
60
+
61
+ unless @logged_in
62
+ handle_nick(cmd)
63
+ return
64
+ end
65
+
66
+ # TODO: Handle other commands
67
+ case cmd
68
+ when /^QUIT/
69
+ add_output ":#{SERVER} NOTICE #{@nick} :See ya, jerk"
70
+ @closed = true
71
+
72
+ when /^NICK/ then handle_nick(cmd)
73
+ when /^JOIN/ then handle_join(cmd)
74
+ end
75
+ end
76
+
77
+ # Handles a connection command (USER) or errors
78
+ def handle_connected(cmd)
79
+ if cmd =~ /^USER (\S+) (\S+) (\S+) :(.*)$/
80
+ add_output ":#{SERVER} NOTICE AUTH :*** Looking up your hostname..."
81
+ @connected = true
82
+ return
83
+ end
84
+
85
+ add_output ":#{SERVER} ERROR :You need to authenticate or something"
86
+ end
87
+
88
+ # Handles a NICK request, but no error if no nick set - not sure what a real server does here
89
+ def handle_nick(cmd)
90
+ unless cmd =~ /^NICK :(.*)$/
91
+ return
92
+ end
93
+
94
+ nick = $1
95
+
96
+ if "InUseNick" == nick
97
+ add_output ":#{SERVER} 433 * #{nick} :Nickname is already in use."
98
+ return
99
+ end
100
+
101
+ oldnick = @nick
102
+ @nick = nick
103
+
104
+ unless @logged_in
105
+ add_output ":#{SERVER} NOTICE #{@nick} :*** You are exempt from user limits. congrats.",
106
+ ":#{SERVER} 001 #{@nick} :Welcome to the Fakey-fake Internet Relay Chat Network #{@nick}",
107
+ ":#{SERVER} 002 #{@nick} :Your host is #{SERVER}[0.0.0.0/6667], running version mock-irc-1.7.7",
108
+ ":#{SERVER} 003 #{@nick} :This server was created Nov 21 2009 at 21:20:48",
109
+ ":#{SERVER} 004 #{@nick} #{SERVER} mock-irc-1.7.7 foobar barbaz bazfoo",
110
+ ":#{SERVER} 005 #{@nick} CALLERID CASEMAPPING=rfc1459 DEAF=D KICKLEN=160 MODES=4 NICKLEN=15 PREFIX=(ohv)@%+ STATUSMSG=@%+ TOPICLEN=350 NETWORK=Fakeyfake MAXLIST=beI:25 MAXTARGETS=4 CHANTYPES=#& :are supported by this server",
111
+ ":#{SERVER} 251 #{@nick} :There are 0 users and 24 invisible on 1 servers",
112
+ ":#{SERVER} 254 #{@nick} 3 :channels formed",
113
+ ":#{SERVER} 255 #{@nick} :I have 24 clients and 0 servers",
114
+ ":#{SERVER} 265 #{@nick} :Current local users: 24 Max: 30",
115
+ ":#{SERVER} 266 #{@nick} :Current global users: 24 Max: 33",
116
+ ":#{SERVER} 250 #{@nick} :Highest connection count: 30 (30 clients) (4215 connections received)",
117
+ ":#{SERVER} 375 #{@nick} :- #{SERVER} Message of the Day - ",
118
+ ":#{SERVER} 372 #{@nick} :- BOO!",
119
+ ":#{SERVER} 372 #{@nick} :- Did I scare you?",
120
+ ":#{SERVER} 372 #{@nick} :- BOO again!",
121
+ ":#{SERVER} 376 #{@nick} :End of /MOTD command."
122
+ @logged_in = true
123
+ return
124
+ end
125
+
126
+ # Hostmask is faked, but otherwise this is the message we send in response to a nick change
127
+ add_output ":#{oldnick}!#{USERHOST} NICK :#{@nick}"
128
+ end
129
+
130
+ def handle_join(cmd)
131
+ unless cmd =~ /^JOIN (\S*)( (\S*))?$/
132
+ return
133
+ end
134
+
135
+ channel = $1
136
+ pass = $2
137
+ if "#banned" == channel
138
+ add_output ":#{SERVER} 474 T-meister #{channel}:Cannot join channel (+b)"
139
+ return
140
+ end
141
+
142
+ add_output ":#{@nick}!#{USERHOST} JOIN :#{channel}",
143
+ ":#{SERVER} 332 #{@nick} #{channel} :This is a topic, y'all!",
144
+ ":#{SERVER} 333 #{@nick} #{channel} user!user@user.com 1291781166",
145
+ ":#{SERVER} 353 #{@nick} = #{channel} :#{@nick} @Nerdmaster another_bot",
146
+ ":#{SERVER} 366 #{@nick} #{channel} :End of /NAMES list."
147
+ end
148
+
149
+ # Sets up our internal string to add the given string arguments for a gets call to pull
150
+ def add_output(*args)
151
+ args.each {|arg| @output.push(arg + "\n")}
152
+ end
153
+ end
data/tests/tc_event.rb CHANGED
@@ -99,6 +99,22 @@ class MessageParserEventTest < Test::Unit::TestCase
99
99
 
100
100
  # First param in the message params list should still be nick
101
101
  assert_equal 'Towelie', event.msg.params.first
102
+
103
+ # This is a weird numeric causing errors for a user
104
+ event = Net::YAIL::IncomingEvent.parse(":irc.somehost.xx 322 user #CrAzY_MaNiCoMiCuM 12 :[+ntr] \253'\002\0033,3 \0030 I \0030,0 \0034T \0034,4 " +
105
+ "\0031A \0031,1\0038\273\0031,9 OrA NuOvO ErOtIcI Su FFTXL\0030,13 #CrAzY_MaNiCoMiCuM:\0032,4 QuI ReGnAnO PeR OrA I + PaZZi DeL WeB, " +
106
+ "\0031,8TuTTi AnCoRa In PRoVa..\0034M\00307w\00308a\00303H\00311u\0031 \0031,9PrEpArAtE Le RiChIeStE PeR Il RiCoVeRo a ViTa\0030,13PoStI " +
107
+ "LiBeRi!!\0031,4!PaZZi Da STaRe InSiEmE. :\336")
108
+ assert_equal 'irc.somehost.xx', event.from
109
+ assert_equal :incoming_322, event.type
110
+ assert_equal :incoming_numeric, event.parent.type
111
+ assert_equal 'user', event.target
112
+ assert_equal ['#CrAzY_MaNiCoMiCuM', '12'], event.parameters[0..1]
113
+ assert event.server?
114
+ assert_equal "#CrAzY_MaNiCoMiCuM 12 [+ntr] \253'\002\0033,3 \0030 I \0030,0 \0034T \0034,4 \0031A \0031,1\0038\273\0031,9 OrA NuOvO " +
115
+ "ErOtIcI Su FFTXL\0030,13 #CrAzY_MaNiCoMiCuM:\0032,4 QuI ReGnAnO PeR OrA I + PaZZi DeL WeB, \0031,8TuTTi AnCoRa In PRoVa..\0034M" +
116
+ "\00307w\00308a\00303H\00311u\0031 \0031,9PrEpArAtE Le RiChIeStE PeR Il RiCoVeRo a ViTa\0030,13PoStI LiBeRi!!\0031,4!PaZZi Da " +
117
+ "STaRe InSiEmE. :\336", event.text
102
118
  end
103
119
 
104
120
  # Test an invite
data/tests/tc_yail.rb ADDED
@@ -0,0 +1,182 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + "/net_yail"
3
+ require File.dirname(__FILE__) + "/mock_irc"
4
+ require "test/unit"
5
+
6
+ # This test suite is built as an attempt to validate basic functionality in YAIL. Due to the
7
+ # threading of the library, things are going to be... weird. Good luck, me.
8
+ class YailSessionTest < Test::Unit::TestCase
9
+ def setup
10
+ @mockirc = MockIRC.new
11
+ @log = Logger.new($stderr)
12
+ @log.level = Logger::WARN
13
+ @yail = Net::YAIL.new(
14
+ :io => @mockirc, :address => "fake-irc.nerdbucket.com", :log => @log,
15
+ :nicknames => ["Bot"], :realname => "Net::YAIL", :username => "Username"
16
+ )
17
+ end
18
+
19
+ # Sets up all our handlers the legacy way - allows testing that things work as they used to
20
+ def setup_legacy_handling
21
+ ###
22
+ # Simple counters for basic testing of successful handler registration
23
+ ###
24
+
25
+ @msg = Hash.new(0)
26
+ @yail.prepend_handler(:incoming_welcome) { |text, args| @msg[:welcome] += 1 }
27
+ @yail.prepend_handler(:incoming_endofmotd) { |text, args| @msg[:endofmotd] += 1 }
28
+ @yail.prepend_handler(:incoming_notice) { |f, actor, target, text| @msg[:notice] += 1 }
29
+ @yail.prepend_handler(:incoming_nick) { |f, actor, nick| @msg[:nick] += 1 }
30
+ @yail.prepend_handler(:incoming_bannedfromchan) { |text, args| @msg[:bannedfromchan] += 1 }
31
+ @yail.prepend_handler(:incoming_join) { |f, actor, target| @msg[:join] += 1 }
32
+ @yail.prepend_handler(:incoming_mode) { |f, actor, target, modes, objects| @msg[:mode] += 1 }
33
+ @yail.prepend_handler(:incoming_msg) { |f, actor, target, text| @msg[:msg] += 1 }
34
+ @yail.prepend_handler(:incoming_act) { |f, actor, target, text| @msg[:act] += 1 }
35
+ @yail.prepend_handler(:incoming_ctcp) { |f, actor, target, text| @msg[:ctcp] += 1 }
36
+ @yail.prepend_handler(:incoming_ping) { |text| @msg[:ping] += 1 }
37
+ @yail.prepend_handler(:incoming_quit) { |f, actor, text| @msg[:quit] += 1 }
38
+ @yail.prepend_handler(:outgoing_mode) { |target, modes, objects| @msg[:o_mode] += 1 }
39
+ @yail.prepend_handler(:outgoing_join) { |channel, pass| @msg[:o_join] += 1 }
40
+
41
+ ###
42
+ # More complex handlers to test parsing of messages
43
+ ###
44
+
45
+ # Channels list helps us test joins
46
+ @channels = []
47
+ @yail.prepend_handler(:incoming_join) do |fullactor, actor, target|
48
+ @channels.push(target) if @yail.me == actor
49
+ end
50
+
51
+ # Gotta store extra info on notices to test event parsing
52
+ @notices = []
53
+ @yail.prepend_handler(:incoming_notice) do |f, actor, target, text|
54
+ @notices.push({:server => f, :nick => actor, :target => target, :text => text})
55
+ end
56
+
57
+ @yail.prepend_handler(:incoming_ping) { |text| @ping_message = text }
58
+ @yail.prepend_handler(:incoming_quit) { |f, actor, text| @quit = {:full => f, :nick => actor, :text => text} }
59
+ @yail.prepend_handler(:outgoing_join) {|channel, pass| @out_join = {:channel => channel, :password => pass} }
60
+ @yail.prepend_handler(:incoming_msg) {|f, actor, channel, text| @privmsg = {:channel => channel, :nick => actor, :text => text} }
61
+ @yail.prepend_handler(:incoming_ctcp) {|f, actor, channel, text| @ctcp = {:channel => channel, :nick => actor, :text => text} }
62
+ @yail.prepend_handler(:incoming_act) {|f, actor, channel, text| @act = {:channel => channel, :nick => actor, :text => text} }
63
+ end
64
+
65
+ # Waits until the mock IRC reports it has no more output - i.e., we've read everything available
66
+ def wait_for_irc
67
+ while @mockirc.ready?
68
+ sleep 0.05
69
+ end
70
+
71
+ # For safety, we need to wait yet again to be sure YAIL has processed the data it read.
72
+ # This is hacky, but it decreases random failures quite a bit
73
+ sleep 0.1
74
+ end
75
+
76
+ # Log in to fake server, do stuff, see that basic handling and such are working. For simplicity,
77
+ # this will be the all-encompassing "everything" test for legacy handling
78
+ def test_legacy
79
+ # Set up legacy handlers
80
+ setup_legacy_handling
81
+
82
+ common_tests
83
+ end
84
+
85
+ # Resets the messages hash, mocks the IRC server to send string to us, waits for the response, yields to the block
86
+ def mock_message(string)
87
+ @msg = Hash.new(0)
88
+ @mockirc.add_output string
89
+ wait_for_irc
90
+ yield
91
+ end
92
+
93
+ # Runs basic tests, verifying that we get expected results from a mocked session. Handlers set
94
+ # via legacy prepend_handler should be just the same as new handler system.
95
+ def common_tests
96
+ @yail.start_listening
97
+
98
+ # Wait until all data has been read and check messages
99
+ wait_for_irc
100
+ assert_equal 1, @msg[:welcome]
101
+ assert_equal 1, @msg[:endofmotd]
102
+ assert_equal 2, @msg[:notice]
103
+
104
+ # Intense notice test - make sure all events were properly translated
105
+ assert_equal ['fakeirc.org', 'fakeirc.org'], @notices.collect {|n| n[:server]}
106
+ assert_equal ['', ''], @notices.collect {|n| n[:nick]}
107
+ assert_equal ['AUTH', 'Bot'], @notices.collect {|n| n[:target]}
108
+ assert_match %r|looking up your host|i, @notices.first[:text]
109
+ assert_match %r|you are exempt|i, @notices.last[:text]
110
+
111
+ # Test magic methods that set up the bot
112
+ assert_equal "Bot", @yail.me, "Should have set @yail.me automatically on welcome handler"
113
+ assert_equal 1, @msg[:o_mode], "Should have auto-sent mode +i"
114
+
115
+ # Make sure nick change works
116
+ @yail.nick "Foo"
117
+ wait_for_irc
118
+ assert_equal "Foo", @yail.me, "Should have set @yail.me on explicit nick change"
119
+
120
+ # Join a channel where we've been banned
121
+ @yail.join("#banned")
122
+ wait_for_irc
123
+ assert_equal 1, @msg[:bannedfromchan]
124
+ assert_equal "#banned", @out_join[:channel]
125
+ assert_equal "", @out_join[:password]
126
+ assert_equal [], @channels
127
+
128
+ # Join some other channel
129
+ @yail.join("#foosball", "pass")
130
+ wait_for_irc
131
+ assert_equal "#foosball", @out_join[:channel]
132
+ assert_equal "pass", @out_join[:password]
133
+ assert_equal ['#foosball'], @channels
134
+
135
+ # Mock some chatter to verify PRIVMSG info
136
+ mock_message ":Nerdmaster!nerd@nerdbucket.com PRIVMSG #foosball :#{@yail.me}: Welcome!" do
137
+ assert_equal 1, @msg[:msg]
138
+ assert_equal 0, @msg[:act]
139
+ assert_equal 0, @msg[:ctcp]
140
+
141
+ assert_equal "Nerdmaster", @privmsg[:nick]
142
+ assert_equal "#foosball", @privmsg[:channel]
143
+ assert_equal "#{@yail.me}: Welcome!", @privmsg[:text]
144
+ end
145
+
146
+ # CTCP
147
+ mock_message ":Nerdmaster!nerd@nerdbucket.com PRIVMSG #foosball :\001CTCP THING\001" do
148
+ assert_equal 0, @msg[:msg]
149
+ assert_equal 0, @msg[:act]
150
+ assert_equal 1, @msg[:ctcp]
151
+
152
+ assert_equal "Nerdmaster", @ctcp[:nick]
153
+ assert_equal "#foosball", @ctcp[:channel]
154
+ assert_equal "CTCP THING", @ctcp[:text]
155
+ end
156
+
157
+ # ACT
158
+ mock_message ":Nerdmaster!nerd@nerdbucket.com PRIVMSG #foosball :\001ACTION vomits on you\001" do
159
+ assert_equal 0, @msg[:msg]
160
+ assert_equal 1, @msg[:act]
161
+ assert_equal 0, @msg[:ctcp]
162
+
163
+ assert_equal "Nerdmaster", @act[:nick]
164
+ assert_equal "#foosball", @act[:channel]
165
+ assert_equal "vomits on you", @act[:text]
166
+ end
167
+
168
+ # PING
169
+ mock_message "PING boo" do
170
+ assert_equal 1, @msg[:ping]
171
+ assert_equal 'boo', @ping_message
172
+ end
173
+
174
+ # User quits
175
+ mock_message ":Nerdmaster!nerd@nerdbucket.com QUIT :Quit: Bye byes" do
176
+ assert_equal 1, @msg[:quit]
177
+ assert_equal 'Nerdmaster!nerd@nerdbucket.com', @quit[:full]
178
+ assert_equal 'Nerdmaster', @quit[:nick]
179
+ assert_equal 'Quit: Bye byes', @quit[:text]
180
+ end
181
+ end
182
+ end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: net-yail
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 15
4
5
  prerelease: false
5
6
  segments:
6
7
  - 1
7
8
  - 4
8
- - 3
9
- version: 1.4.3
9
+ - 4
10
+ version: 1.4.4
10
11
  platform: ruby
11
12
  authors:
12
13
  - Jeremy Echols
@@ -14,7 +15,7 @@ autorequire: net/yail
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-09-20 00:00:00 -04:00
18
+ date: 2011-03-22 00:00:00 -04:00
18
19
  default_executable:
19
20
  dependencies: []
20
21
 
@@ -44,6 +45,8 @@ files:
44
45
  - tests/net_yail.rb
45
46
  - tests/tc_message_parser.rb
46
47
  - tests/tc_event.rb
48
+ - tests/tc_yail.rb
49
+ - tests/mock_irc.rb
47
50
  - YAIL-RDOC
48
51
  has_rdoc: true
49
52
  homepage: http://ruby-irc-yail.nerdbucket.com/
@@ -60,6 +63,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
60
63
  requirements:
61
64
  - - ">="
62
65
  - !ruby/object:Gem::Version
66
+ hash: 3
63
67
  segments:
64
68
  - 0
65
69
  version: "0"
@@ -68,6 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
68
72
  requirements:
69
73
  - - ">="
70
74
  - !ruby/object:Gem::Version
75
+ hash: 3
71
76
  segments:
72
77
  - 0
73
78
  version: "0"
@@ -82,3 +87,5 @@ test_files:
82
87
  - tests/net_yail.rb
83
88
  - tests/tc_message_parser.rb
84
89
  - tests/tc_event.rb
90
+ - tests/tc_yail.rb
91
+ - tests/mock_irc.rb