Sutto-marvin 0.1.20081120 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/README.textile +8 -0
  2. data/VERSION.yml +2 -2
  3. data/bin/marvin +88 -55
  4. data/config/settings.yml.sample +6 -1
  5. data/config/setup.rb +19 -4
  6. data/handlers/debug_handler.rb +2 -2
  7. data/handlers/hello_world.rb +1 -1
  8. data/lib/marvin.rb +14 -9
  9. data/lib/marvin/abstract_client.rb +10 -2
  10. data/lib/marvin/console.rb +54 -0
  11. data/lib/marvin/daemon.rb +71 -0
  12. data/lib/marvin/distributed.rb +14 -0
  13. data/lib/marvin/distributed/dispatch_handler.rb +82 -0
  14. data/lib/marvin/distributed/drb_client.rb +78 -0
  15. data/lib/marvin/distributed/ring_server.rb +41 -0
  16. data/lib/marvin/exception_tracker.rb +1 -1
  17. data/lib/marvin/irc.rb +4 -5
  18. data/lib/marvin/irc/client.rb +13 -2
  19. data/lib/marvin/irc/server.rb +57 -0
  20. data/lib/marvin/irc/server/abstract_connection.rb +79 -0
  21. data/lib/marvin/irc/server/base_connection.rb +66 -0
  22. data/lib/marvin/irc/server/channel.rb +111 -0
  23. data/lib/marvin/irc/server/named_store.rb +14 -0
  24. data/lib/marvin/irc/server/user.rb +5 -0
  25. data/lib/marvin/irc/server/user/handle_mixin.rb +138 -0
  26. data/lib/marvin/irc/server/user_connection.rb +127 -0
  27. data/lib/marvin/loader.rb +111 -36
  28. data/lib/marvin/logger.rb +2 -2
  29. data/lib/marvin/options.rb +11 -2
  30. data/lib/marvin/parsers/command.rb +43 -11
  31. data/lib/marvin/settings.rb +7 -6
  32. data/lib/marvin/status.rb +72 -0
  33. data/lib/marvin/test_client.rb +5 -1
  34. data/lib/marvin/util.rb +18 -1
  35. data/script/client +2 -18
  36. data/script/console +9 -0
  37. data/script/distributed_client +9 -0
  38. data/script/ring_server +12 -0
  39. data/script/server +12 -0
  40. data/script/status +11 -0
  41. data/test/parser_comparison.rb +27 -1
  42. data/test/parser_test.rb +254 -10
  43. data/test/test_helper.rb +1 -1
  44. metadata +62 -8
  45. data/lib/marvin/drb_handler.rb +0 -12
  46. data/lib/marvin/irc/abstract_server.rb +0 -4
  47. data/lib/marvin/irc/base_server.rb +0 -11
  48. data/script/daemon-runner +0 -12
data/lib/marvin/logger.rb CHANGED
@@ -6,7 +6,7 @@ module Marvin
6
6
  class << self
7
7
 
8
8
  def setup
9
- log_path = Marvin::Settings.root / "log/#{Marvin::Settings.environment}.log"
9
+ log_path = Marvin::Settings.root / "log/#{Marvin::Loader.type.to_s.dasherize}-#{Marvin::Settings.environment}.log"
10
10
  self.logger ||= new(log_path, Marvin::Settings.log_level, Marvin::Settings.verbose)
11
11
  end
12
12
 
@@ -17,7 +17,6 @@ module Marvin
17
17
 
18
18
  end
19
19
 
20
-
21
20
  LEVELS = {
22
21
  :fatal => 7,
23
22
  :error => 6,
@@ -74,6 +73,7 @@ module Marvin
74
73
 
75
74
  def write(message, level = self.level)
76
75
  self.file.puts message
76
+ self.file.flush
77
77
  STDOUT.puts colourize(message, level) if self.verbose
78
78
  end
79
79
 
@@ -6,7 +6,8 @@ module Marvin
6
6
  def self.parse!
7
7
  options = {
8
8
  :verbose => Marvin::Settings.verbose,
9
- :log_level => Marvin::Settings.log_level.to_s
9
+ :log_level => Marvin::Settings.log_level.to_s,
10
+ :daemon => false
10
11
  }
11
12
 
12
13
  ARGV.options do |o|
@@ -19,12 +20,20 @@ module Marvin
19
20
  o.on("-l", "--level=[level]", String, "The log level to use",
20
21
  "Default: #{options[:log_level]}") {|options[:log_level]|}
21
22
  o.on("-v", "--verbose", "Be verbose (print to stdout)") {|options[:verbose]|}
23
+ o.on("-d", "--daemon", "Run as a daemon (drop the PID)") {|options[:daemon]|}
24
+ o.on("-k", "--kill", "Kill all of the current type / the running instances") do |kill|
25
+ if kill
26
+ Marvin::Daemon.kill_all(Marvin::Loader.type)
27
+ exit
28
+ end
29
+ end
30
+
22
31
  o.separator ""
23
32
  o.on_tail("-h", "--help", "Show this message.") { puts o; exit }
24
-
25
33
  o.parse!
26
34
  end
27
35
 
36
+ Marvin::Settings.daemon = options[:daemon]
28
37
  Marvin::Settings.log_level = options[:log_level].to_sym
29
38
  Marvin::Settings.verbose = options[:verbose]
30
39
  end
@@ -51,17 +51,49 @@ module Marvin
51
51
  @@commands[command.to_sym] = Marvin::IRC::Event.new(name, *args)
52
52
  end
53
53
 
54
- register_event :nick, :NICK, :new_nick
55
- register_event :quit, :QUIT, :message
56
- register_event :ping, :PING, :data
57
- register_event :pong, :PONG, :data
58
- register_event :join, :JOIN, :target
59
- register_event :invite, :INVITE, :target, :channel
60
- register_event :message, :PRIVMSG, :target, :message
61
- register_event :part, :PART, :target, :message
62
- register_event :mode, :MODE, :target, :mode
63
- register_event :kick, :KICK, :target, :channel, :reason
64
- register_event :topic, :TOPIC, :target, :topic
54
+ register_event :pass, :PASS, :password
55
+ register_event :user, :USER, :user, :mode, :unused, :real_name
56
+ register_event :oper, :OPER, :name, :password
57
+ register_event :service, :SERVICE, :nick, :reserved, :distribution, :type, :reserved, :info
58
+ register_event :squit, :SQUIT, :server, :comment
59
+ register_event :nick, :NICK, :new_nick
60
+ register_event :quit, :QUIT, :message
61
+ register_event :ping, :PING, :data, :server
62
+ register_event :pong, :PONG, :data, :server
63
+ register_event :join, :JOIN, :target, :key
64
+ register_event :invite, :INVITE, :target, :channel
65
+ register_event :message, :PRIVMSG, :target, :message
66
+ register_event :part, :PART, :target, :message
67
+ register_event :mode, :MODE, :target, :mode, :mode_params
68
+ register_event :kick, :KICK, :target, :channel, :reason
69
+ register_event :notice, :NOTICE, :target, :message
70
+ register_event :topic, :TOPIC, :target, :topic
71
+ register_event :names, :NAMES, :channel, :target
72
+ register_event :list, :LIST, :channel, :target
73
+ register_event :motd, :MOTD, :target
74
+ register_event :lusers, :LUSERS, :mask, :target
75
+ register_event :version, :VERSION, :target
76
+ register_event :links, :LINKS, :remote, :mask
77
+ register_event :connect, :CONNECT, :target, :port, :remote
78
+ register_event :trace, :TRACE, :target
79
+ register_event :admin, :ADMIN, :target
80
+ register_event :info, :INFO, :target
81
+ register_event :servlist, :SERVLIST, :mask, :type
82
+ register_event :squery, :SQUERY, :service_name, :text
83
+ register_event :who, :WHO, :mask, :o
84
+ register_event :whois, :WHOIS, :target, :mask
85
+ register_event :whowas, :WHOWAS, :nick, :count, :target
86
+ register_event :kill, :KILL, :nick, :reason
87
+ register_event :error, :ERROR, :message
88
+ register_event :away, :AWAY, :reason
89
+ register_event :rehash, :REHASH
90
+ register_event :die, :DIE
91
+ register_event :restart, :RESTART
92
+ register_event :summon, :SUMMON, :user, :target, :channel
93
+ register_event :users, :USERS, :target
94
+ register_event :wallops, :WALLOPS, :message
95
+ register_event :userhost, :USERHOST, :nick
96
+ register_event :ison, :ISON, :nick
65
97
  # Add the default numeric event
66
98
  register_event :numeric, :numeric, :code, :data
67
99
  # And a few others reserved for special purposed
@@ -5,15 +5,20 @@ module Marvin
5
5
  class Settings
6
6
 
7
7
  cattr_accessor :environment, :configuration, :is_setup, :default_client,
8
- :handler_folder, :default_parser, :log_level, :verbose
8
+ :handler_folder, :default_parser, :log_level, :verbose, :daemon
9
9
 
10
10
  self.verbose = false
11
11
  self.log_level = :info
12
+ self.daemon = false
12
13
 
13
14
  class << self
14
15
 
16
+ def daemon?
17
+ self.daemon
18
+ end
19
+
15
20
  def root
16
- defined?(MARVIN_ROOT) ? MARVIN_ROOT : File.dirname(__FILE__) / "../.."
21
+ File.expand_path(defined?(MARVIN_ROOT) ? MARVIN_ROOT : File.dirname(__FILE__) / "../..")
17
22
  end
18
23
 
19
24
  def setup(options = {})
@@ -21,10 +26,6 @@ module Marvin
21
26
  self.setup!(options)
22
27
  end
23
28
 
24
- def daemon?
25
- defined?(IS_DAEMON) && IS_DAEMON
26
- end
27
-
28
29
  def setup!(options = {})
29
30
  self.environment ||= "development"
30
31
  self.configuration = {}
@@ -0,0 +1,72 @@
1
+ module Marvin
2
+ class Status
3
+ CONTROLLERS = {
4
+ :client => "IRC Client",
5
+ :server => "IRC Server",
6
+ :ring_server => "Ring Server",
7
+ :distributed_client => "Distributed Client",
8
+ }
9
+
10
+ class << self
11
+
12
+ def show!
13
+ STDOUT.puts ""
14
+ STDOUT.puts " Marvin Status"
15
+ STDOUT.puts " ============="
16
+ STDOUT.puts ""
17
+ if ARGV.include?("--help") || ARGV.include?("-h")
18
+ STDOUT.puts " Usage: script/status [options]\n\n"
19
+ STDOUT.puts " -h, --help Show this message"
20
+ STDOUT.puts " -f, --full Include distributed stats"
21
+ STDOUT.puts ""
22
+ exit
23
+ end
24
+ pids = {}
25
+ CONTROLLERS.each_key { |k| pids[k] = Marvin::Daemon.pids_for_type(k) }
26
+ CONTROLLERS.each do |k, v|
27
+ count = pids[k].size
28
+ postfix = count == 1 ? "" : "s"
29
+ STDOUT.puts " #{count} running instance#{postfix} of the #{CONTROLLERS[k]}"
30
+ STDOUT.puts " Pid#{postfix}: #{pids[k].join(", ")}" unless count == 0
31
+ STDOUT.puts ""
32
+ end
33
+
34
+ if (ARGV.include?("-f") || ARGV.include?("--full")) && !pids[:ring_server].empty?
35
+ require 'rinda/ring'
36
+ DRb.start_service
37
+ STDOUT.puts " Distributed Status"
38
+ STDOUT.puts " ------------------"
39
+ begin
40
+ rs = Rinda::RingFinger.finger.lookup_ring(3)
41
+ STDOUT.puts " Ring Server: #{rs.__drburi}"
42
+ items = rs.read_all([:marvin_event, nil, nil, nil])
43
+ STDOUT.puts " Unprocessed Items: #{items.size}"
44
+ STDOUT.puts ""
45
+ unless items.empty?
46
+ start_time = items.first[2][:dispatched_at]
47
+ STDOUT.puts " Earliest Item: #{start_time ? start_time.strftime("%I:%M%p %d/%m/%y") : "Never"}"
48
+ end_time = items.last[2][:dispatched_at]
49
+ STDOUT.puts " Latest Item: #{end_time ? end_time.strftime("%I:%M%p %d/%m/%y") : "Never"}"
50
+ mapping = {}
51
+ items.each do |i|
52
+ mapping[i[1].inspect] ||= 0
53
+ mapping[i[1].inspect] += 1
54
+ end
55
+ width = mapping.keys.map { |k| k.length }.max
56
+ STDOUT.puts ""
57
+ STDOUT.puts " Unprocessed Message Counts:"
58
+ STDOUT.puts " ---------------------------"
59
+ mapping.each { |k, v| STDOUT.puts " #{k.ljust width} => #{v}" }
60
+ STDOUT.puts ""
61
+ end
62
+ rescue
63
+ STDOUT.puts " Ring server not found."
64
+ STDOUT.puts ""
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+ end
72
+ end
@@ -12,7 +12,7 @@ module Marvin
12
12
 
13
13
  DispatchedEvents = Struct.new(:name, :options)
14
14
 
15
- def initialize
15
+ def initialize(opts = {})
16
16
  super
17
17
  self.incoming_commands = []
18
18
  self.outgoing_commands = []
@@ -56,5 +56,9 @@ module Marvin
56
56
  end
57
57
  end
58
58
 
59
+ def self.add_reconnect(opts = {})
60
+ Marvin::Logger.info "Added reconnect with options: #{opts.inspect}"
61
+ end
62
+
59
63
  end
60
64
  end
data/lib/marvin/util.rb CHANGED
@@ -1,6 +1,13 @@
1
1
  module Marvin
2
2
  module Util
3
3
 
4
+ GLOB_PATTERN_MAP = {
5
+ '*' => '.*',
6
+ '?' => '.',
7
+ '[' => '[',
8
+ ']' => ']'
9
+ }
10
+
4
11
  # Return the channel-name version of a string by
5
12
  # appending "#" to the front if it doesn't already
6
13
  # start with it.
@@ -20,9 +27,19 @@ module Marvin
20
27
  # specify parameters which have spaces etc (for example,
21
28
  # the actual message part of a response).
22
29
  def last_param(section)
23
- section && ":#{section.to_s.strip} "
30
+ section && ":#{section.to_s.strip}"
24
31
  end
25
32
  alias lp last_param
33
+
34
+ # Converts a glob-like pattern into a regular
35
+ # expression for easy / fast matching. Code is
36
+ # from PLEAC at http://pleac.sourceforge.net/pleac_ruby/patternmatching.html
37
+ def glob2pattern(glob_string)
38
+ inner_pattern = glob_string.gsub(/(.)/) do |c|
39
+ GLOB_PATTERN_MAP[c] || Regexp::escape(c)
40
+ end
41
+ return Regexp.new("^#{inner_pattern}$")
42
+ end
26
43
 
27
44
  extend self
28
45
 
data/script/client CHANGED
@@ -1,25 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'rubygems'
3
3
 
4
- if File.exist?(File.dirname(__FILE__) + "/../lib/marvin.rb")
5
- $:.unshift(File.dirname(__FILE__) + "/../lib/")
6
- end
7
-
4
+ $:.unshift(File.dirname(__FILE__) + "/../lib/") if File.exist?(File.dirname(__FILE__) + "/../lib/marvin.rb")
8
5
  MARVIN_ROOT = File.join(File.dirname(__FILE__), "..")
9
- IS_DAEMON = ARGV.include?("--is-daemon")
10
6
 
11
7
  # And Require Marvin.
12
8
  require 'marvin'
13
-
14
- ["INT", "TERM"].each do |sig|
15
-
16
- # Trap a given signal and run all
17
- # of our callbacks etc,
18
- trap sig do
19
- Marvin::Loader.stop!
20
- exit
21
- end
22
-
23
- end
24
-
25
- Marvin::Loader.run!
9
+ Marvin::Loader.run! :client
data/script/console ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ libs = ["-r irb/completion", "-r lib/marvin", "-r lib/marvin/console"]
4
+
5
+ cmd = "irb #{libs.join(" ")} --simple-prompt"
6
+
7
+ puts "Loading Marvin console..."
8
+
9
+ exec cmd
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+
4
+ $:.unshift(File.dirname(__FILE__) + "/../lib/") if File.exist?(File.dirname(__FILE__) + "/../lib/marvin.rb")
5
+ MARVIN_ROOT = File.join(File.dirname(__FILE__), "..")
6
+
7
+ # And Require Marvin.
8
+ require 'marvin'
9
+ Marvin::Loader.run! :distributed_client
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ #!/usr/bin/env ruby
4
+ require 'rubygems'
5
+
6
+ $:.unshift(File.dirname(__FILE__) + "/../lib/") if File.exist?(File.dirname(__FILE__) + "/../lib/marvin.rb")
7
+ MARVIN_ROOT = File.join(File.dirname(__FILE__), "..")
8
+
9
+ # And Require Marvin.
10
+ require 'marvin'
11
+ Marvin::Loader.run! :ring_server
12
+
data/script/server ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ #!/usr/bin/env ruby
4
+ require 'rubygems'
5
+
6
+ $:.unshift(File.dirname(__FILE__) + "/../lib/") if File.exist?(File.dirname(__FILE__) + "/../lib/marvin.rb")
7
+ MARVIN_ROOT = File.join(File.dirname(__FILE__), "..")
8
+
9
+ # And Require Marvin.
10
+ require 'marvin'
11
+ Marvin::Loader.run! :server
12
+
data/script/status ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ #!/usr/bin/env ruby
3
+ require 'rubygems'
4
+
5
+ $:.unshift(File.dirname(__FILE__) + "/../lib/") if File.exist?(File.dirname(__FILE__) + "/../lib/marvin.rb")
6
+ MARVIN_ROOT = File.join(File.dirname(__FILE__), "..")
7
+
8
+ # And Require Marvin.
9
+ require 'marvin'
10
+
11
+ Marvin::Status.show!
@@ -33,4 +33,30 @@ LINES.each do |line|
33
33
  end
34
34
  puts ""
35
35
 
36
- end
36
+ end
37
+
38
+ puts ""
39
+ puts ""
40
+ puts "==============="
41
+ puts "| SPEED TESTS |"
42
+ puts "==============="
43
+ puts ""
44
+
45
+ width = PARSERS.map { |p| p.name.length }.max + 2
46
+
47
+ ITERATIONS = 1000
48
+
49
+ Benchmark.bm(width) do |b|
50
+ PARSERS.each do |parser|
51
+ b.report("#{parser.name}: ") do
52
+ LINES.each do |l|
53
+ ITERATIONS.times do
54
+ e = parser.new(l).to_event
55
+ unless e.nil?
56
+ e.to_hash # Get a hash
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
data/test/parser_test.rb CHANGED
@@ -1,20 +1,264 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ # In reality this tests several different classes:
4
+ # 1) The parser itself
5
+ # 2) The Command class
6
+ # 3) The two different types of prefixes
7
+ # 4) The Event class
1
8
  class ParserTest < Test::Unit::TestCase
2
- @@parser = nil
3
- def self.parser_is(p)
4
- @@parser = p
5
- end
9
+ @@parser = Marvin::Parsers::SimpleParser
6
10
 
7
- context "When parsing a PONG" do
11
+ context "When parsing a LIST" do
12
+ setup { @parsed = @@parser.new("LIST #twilight_zone,#42") }
13
+
14
+ should "not be nil" do
15
+ assert !@parsed.nil?
16
+ end
17
+
18
+ should "have a command" do
19
+ assert !@parsed.command.nil?
20
+ end
21
+
22
+ should "have not a prefix" do
23
+ assert @parsed.command.prefix.nil?
24
+ end
25
+
26
+ should "have a code of LIST" do
27
+ assert_equal "LIST", @parsed.command.code
28
+ end
29
+
30
+ should "have the correct arguments" do
31
+ assert_equal ["#twilight_zone,#42"], @parsed.command.params
32
+ end
33
+
34
+ should "be able to convert to an event" do
35
+ assert !@parsed.to_event.nil?
36
+ end
37
+
38
+ should "have the correct incoming event name" do
39
+ assert_equal :incoming_list, @parsed.to_event.to_incoming_event_name
40
+ end
41
+
42
+ should "have the correct outgoing event name" do
43
+ assert_equal :outgoing_list, @parsed.to_event.to_outgoing_event_name
44
+ end
45
+
46
+ should "convert to the correct hash" do
47
+ assert_equal({:channel => "#twilight_zone,#42", :target => ""}, @parsed.to_event.to_hash)
48
+ end
49
+
8
50
  end
9
51
 
10
- context "When parsing a PING" do
52
+ context "When parsing a JOIN" do
53
+ setup { @parsed = @@parser.new(":RelayBot!n=MarvinBot@static.amnet.net.au JOIN :#relayrelay") }
54
+
55
+ should "not be nil" do
56
+ assert !@parsed.nil?
57
+ end
58
+
59
+ should "have a command" do
60
+ assert !@parsed.command.nil?
61
+ end
62
+
63
+ should "have a prefix" do
64
+ assert !@parsed.command.prefix.nil?
65
+ end
66
+
67
+ should "have a code of JOIN" do
68
+ assert_equal "JOIN", @parsed.command.code
69
+ end
70
+
71
+ should "have the correct arguments" do
72
+ assert_equal ["#relayrelay"], @parsed.command.params
73
+ end
74
+
75
+ should "have a host mask" do
76
+ assert @parsed.command.prefix.is_a?(Marvin::Parsers::Prefixes::HostMask)
77
+ end
78
+
79
+ should "have the correct nick" do
80
+ assert_equal "RelayBot", @parsed.command.prefix.nickname
81
+ end
82
+
83
+ should "have the correct user" do
84
+ assert_equal "n=MarvinBot", @parsed.command.prefix.user
85
+ end
86
+
87
+ should "have the correct host" do
88
+ assert_equal "static.amnet.net.au", @parsed.command.prefix.host
89
+ end
90
+
91
+ should "be able to convert to an event" do
92
+ assert !@parsed.to_event.nil?
93
+ end
94
+
95
+ should "have the correct incoming event name" do
96
+ assert_equal :incoming_join, @parsed.to_event.to_incoming_event_name
97
+ end
98
+
99
+ should "have the correct outgoing event name" do
100
+ assert_equal :outgoing_join, @parsed.to_event.to_outgoing_event_name
101
+ end
102
+
103
+ should "convert to the correct hash" do
104
+ assert_equal({:target => "#relayrelay", :key => ""}.merge(@parsed.command.prefix.to_hash), @parsed.to_event.to_hash)
105
+ end
106
+
11
107
  end
12
108
 
13
109
  context "When parsing a PRIVMSG" do
110
+ setup { @parsed = @@parser.new(":SuttoL!n=SuttoL@sutto.net PRIVMSG #relayrelay :testing...") }
111
+
112
+ should "not be nil" do
113
+ assert !@parsed.nil?
114
+ end
115
+
116
+ should "have a command" do
117
+ assert !@parsed.command.nil?
118
+ end
119
+
120
+ should "have a prefix" do
121
+ assert !@parsed.command.prefix.nil?
122
+ end
123
+
124
+ should "have a code of PRIVMSG" do
125
+ assert_equal "PRIVMSG", @parsed.command.code
126
+ end
127
+
128
+ should "have the correct arguments" do
129
+ assert_equal ["#relayrelay", "testing..."], @parsed.command.params
130
+ end
131
+
132
+ should "have a host mask" do
133
+ assert @parsed.command.prefix.is_a?(Marvin::Parsers::Prefixes::HostMask)
134
+ end
135
+
136
+ should "have the correct nick" do
137
+ assert_equal "SuttoL", @parsed.command.prefix.nickname
138
+ end
139
+
140
+ should "have the correct user" do
141
+ assert_equal "n=SuttoL", @parsed.command.prefix.user
142
+ end
143
+
144
+ should "have the correct host" do
145
+ assert_equal "sutto.net", @parsed.command.prefix.host
146
+ end
147
+
148
+ should "be able to convert to an event" do
149
+ assert !@parsed.to_event.nil?
150
+ end
151
+
152
+ should "have the correct incoming event name" do
153
+ assert_equal :incoming_message, @parsed.to_event.to_incoming_event_name
154
+ end
155
+
156
+ should "have the correct outgoing event name" do
157
+ assert_equal :outgoing_message, @parsed.to_event.to_outgoing_event_name
158
+ end
159
+
160
+ should "convert to the correct hash" do
161
+ assert_equal({:target => "#relayrelay", :message => "testing..."}.merge(@parsed.command.prefix.to_hash), @parsed.to_event.to_hash)
162
+ end
163
+
164
+ end
165
+
166
+ context "When parsing a numeric - 366" do
167
+ setup { @parsed = @@parser.new(":irc.darth.vpn.spork.in 366 testbot #testing :End of NAMES list") }
168
+
169
+ should "not be nil" do
170
+ assert !@parsed.nil?
171
+ end
172
+
173
+ should "have a command" do
174
+ assert !@parsed.command.nil?
175
+ end
176
+
177
+ should "have a prefix" do
178
+ assert !@parsed.command.prefix.nil?
179
+ end
180
+
181
+ should "have a code of 366" do
182
+ assert_equal "366", @parsed.command.code
183
+ end
184
+
185
+ should "have the correct arguments" do
186
+ assert_equal ["testbot", "#testing", "End of NAMES list"], @parsed.command.params
187
+ end
188
+
189
+ should "have a host mask" do
190
+ assert @parsed.command.prefix.is_a?(Marvin::Parsers::Prefixes::Server)
191
+ end
192
+
193
+ should "have the correct name" do
194
+ assert_equal "irc.darth.vpn.spork.in", @parsed.command.prefix.name
195
+ end
196
+
197
+ should "be able to convert to an event" do
198
+ assert !@parsed.to_event.nil?
199
+ end
200
+
201
+ should "have the correct incoming event name" do
202
+ assert_equal :incoming_numeric, @parsed.to_event.to_incoming_event_name
203
+ end
204
+
205
+ should "have the correct outgoing event name" do
206
+ assert_equal :outgoing_numeric, @parsed.to_event.to_outgoing_event_name
207
+ end
208
+
209
+ should "convert to the correct hash" do
210
+ assert_equal({:code => "366", :data => "testbot #testing :End of NAMES list"}.merge(@parsed.command.prefix.to_hash), @parsed.to_event.to_hash)
211
+ end
212
+
213
+ end
214
+
215
+ context "When parsing a numeric - 004" do
216
+ setup { @parsed = @@parser.new(":wolfe.freenode.net 004 MarvinBot3000 wolfe.freenode.net hyperion-1.0.2b aAbBcCdDeEfFGhHiIjkKlLmMnNopPQrRsStTuUvVwWxXyYzZ01234569*@ bcdefFhiIklmnoPqstv") }
217
+
218
+ should "not be nil" do
219
+ assert !@parsed.nil?
220
+ end
221
+
222
+ should "have a command" do
223
+ assert !@parsed.command.nil?
224
+ end
225
+
226
+ should "have a prefix" do
227
+ assert !@parsed.command.prefix.nil?
228
+ end
229
+
230
+ should "have a code of 366" do
231
+ assert_equal "004", @parsed.command.code
232
+ end
233
+
234
+ should "have the correct arguments" do
235
+ assert_equal ["MarvinBot3000" , "wolfe.freenode.net", "hyperion-1.0.2b", "aAbBcCdDeEfFGhHiIjkKlLmMnNopPQrRsStTuUvVwWxXyYzZ01234569*@", "bcdefFhiIklmnoPqstv"], @parsed.command.params
236
+ end
237
+
238
+ should "have a host mask" do
239
+ assert @parsed.command.prefix.is_a?(Marvin::Parsers::Prefixes::Server)
240
+ end
241
+
242
+ should "have the correct name" do
243
+ assert_equal "wolfe.freenode.net", @parsed.command.prefix.name
244
+ end
245
+
246
+ should "be able to convert to an event" do
247
+ assert !@parsed.to_event.nil?
248
+ end
249
+
250
+ should "have the correct incoming event name" do
251
+ assert_equal :incoming_numeric, @parsed.to_event.to_incoming_event_name
252
+ end
253
+
254
+ should "have the correct outgoing event name" do
255
+ assert_equal :outgoing_numeric, @parsed.to_event.to_outgoing_event_name
256
+ end
257
+
258
+ should "convert to the correct hash" do
259
+ assert_equal({:code => "004", :data => "MarvinBot3000 wolfe.freenode.net hyperion-1.0.2b aAbBcCdDeEfFGhHiIjkKlLmMnNopPQrRsStTuUvVwWxXyYzZ01234569*@ bcdefFhiIklmnoPqstv"}.merge(@parsed.command.prefix.to_hash), @parsed.to_event.to_hash)
260
+ end
261
+
14
262
  end
15
263
 
16
- end
17
-
18
- ["Regexp", "Simple"].each do |parser_name|
19
- eval("class #{parser_name}ParserTest < ParserTest; parser_is #{parser_is}Parser; end")
20
264
  end