autumn 3.1.8

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.
Files changed (111) hide show
  1. data/AUTHORS +11 -0
  2. data/CHANGELOG +567 -0
  3. data/MANIFEST +110 -0
  4. data/README +1114 -0
  5. data/README.textile +1153 -0
  6. data/Rakefile +75 -0
  7. data/autumn.gemspec +44 -0
  8. data/bin/autumn +11 -0
  9. data/lib/autumn.rb +8 -0
  10. data/lib/autumn/authentication.rb +238 -0
  11. data/lib/autumn/channel_leaf.rb +107 -0
  12. data/lib/autumn/coder.rb +166 -0
  13. data/lib/autumn/console_boot.rb +10 -0
  14. data/lib/autumn/ctcp.rb +250 -0
  15. data/lib/autumn/daemon.rb +207 -0
  16. data/lib/autumn/datamapper_hacks.rb +290 -0
  17. data/lib/autumn/foliater.rb +231 -0
  18. data/lib/autumn/formatting.rb +236 -0
  19. data/lib/autumn/generator.rb +231 -0
  20. data/lib/autumn/genesis.rb +190 -0
  21. data/lib/autumn/inheritable_attributes.rb +162 -0
  22. data/lib/autumn/leaf.rb +738 -0
  23. data/lib/autumn/log_facade.rb +49 -0
  24. data/lib/autumn/misc.rb +87 -0
  25. data/lib/autumn/resources/daemons/Anothernet.yml +3 -0
  26. data/lib/autumn/resources/daemons/AustHex.yml +29 -0
  27. data/lib/autumn/resources/daemons/Bahamut.yml +67 -0
  28. data/lib/autumn/resources/daemons/Dancer.yml +3 -0
  29. data/lib/autumn/resources/daemons/GameSurge.yml +3 -0
  30. data/lib/autumn/resources/daemons/IRCnet.yml +3 -0
  31. data/lib/autumn/resources/daemons/Ithildin.yml +7 -0
  32. data/lib/autumn/resources/daemons/KineIRCd.yml +56 -0
  33. data/lib/autumn/resources/daemons/PTlink.yml +6 -0
  34. data/lib/autumn/resources/daemons/QuakeNet.yml +20 -0
  35. data/lib/autumn/resources/daemons/RFC1459.yml +158 -0
  36. data/lib/autumn/resources/daemons/RFC2811.yml +16 -0
  37. data/lib/autumn/resources/daemons/RFC2812.yml +36 -0
  38. data/lib/autumn/resources/daemons/RatBox.yml +25 -0
  39. data/lib/autumn/resources/daemons/Ultimate.yml +24 -0
  40. data/lib/autumn/resources/daemons/Undernet.yml +6 -0
  41. data/lib/autumn/resources/daemons/Unreal.yml +110 -0
  42. data/lib/autumn/resources/daemons/_Other.yml +7 -0
  43. data/lib/autumn/resources/daemons/aircd.yml +33 -0
  44. data/lib/autumn/resources/daemons/bdq-ircd.yml +3 -0
  45. data/lib/autumn/resources/daemons/hybrid.yml +38 -0
  46. data/lib/autumn/resources/daemons/ircu.yml +67 -0
  47. data/lib/autumn/resources/daemons/tr-ircd.yml +8 -0
  48. data/lib/autumn/script.rb +74 -0
  49. data/lib/autumn/speciator.rb +165 -0
  50. data/lib/autumn/stem.rb +919 -0
  51. data/lib/autumn/stem_facade.rb +176 -0
  52. data/lib/autumn/tool/bin.rb +301 -0
  53. data/lib/autumn/tool/create.rb +48 -0
  54. data/lib/autumn/tool/project_creator.rb +110 -0
  55. data/lib/autumn/version.rb +3 -0
  56. data/lib/skel/Rakefile +163 -0
  57. data/lib/skel/config/global.yml +2 -0
  58. data/lib/skel/config/seasons/testing/database.yml +4 -0
  59. data/lib/skel/config/seasons/testing/leaves.yml +9 -0
  60. data/lib/skel/config/seasons/testing/season.yml +2 -0
  61. data/lib/skel/config/seasons/testing/stems.yml +10 -0
  62. data/lib/skel/leaves/administrator/README +20 -0
  63. data/lib/skel/leaves/administrator/controller.rb +67 -0
  64. data/lib/skel/leaves/administrator/views/autumn.txt.erb +1 -0
  65. data/lib/skel/leaves/administrator/views/reload.txt.erb +11 -0
  66. data/lib/skel/leaves/insulter/README +17 -0
  67. data/lib/skel/leaves/insulter/controller.rb +65 -0
  68. data/lib/skel/leaves/insulter/views/about.txt.erb +1 -0
  69. data/lib/skel/leaves/insulter/views/help.txt.erb +1 -0
  70. data/lib/skel/leaves/insulter/views/insult.txt.erb +1 -0
  71. data/lib/skel/leaves/scorekeeper/README +34 -0
  72. data/lib/skel/leaves/scorekeeper/config.yml +2 -0
  73. data/lib/skel/leaves/scorekeeper/controller.rb +104 -0
  74. data/lib/skel/leaves/scorekeeper/helpers/general.rb +64 -0
  75. data/lib/skel/leaves/scorekeeper/models/channel.rb +12 -0
  76. data/lib/skel/leaves/scorekeeper/models/person.rb +14 -0
  77. data/lib/skel/leaves/scorekeeper/models/pseudonym.rb +11 -0
  78. data/lib/skel/leaves/scorekeeper/models/score.rb +14 -0
  79. data/lib/skel/leaves/scorekeeper/tasks/stats.rake +17 -0
  80. data/lib/skel/leaves/scorekeeper/views/about.txt.erb +1 -0
  81. data/lib/skel/leaves/scorekeeper/views/change.txt.erb +5 -0
  82. data/lib/skel/leaves/scorekeeper/views/history.txt.erb +11 -0
  83. data/lib/skel/leaves/scorekeeper/views/points.txt.erb +5 -0
  84. data/lib/skel/leaves/scorekeeper/views/usage.txt.erb +1 -0
  85. data/lib/skel/log/README +1 -0
  86. data/lib/skel/script/console +28 -0
  87. data/lib/skel/script/destroy +48 -0
  88. data/lib/skel/script/generate +48 -0
  89. data/lib/skel/shared/README +1 -0
  90. data/lib/skel/tmp/README +1 -0
  91. data/spec/authentication_spec.rb +328 -0
  92. data/spec/channel_leaf_spec.rb +142 -0
  93. data/spec/coder_spec.rb +146 -0
  94. data/spec/ctcp_spec.rb +222 -0
  95. data/spec/daemon_spec.rb +202 -0
  96. data/spec/datamapper_hacks_spec.rb +164 -0
  97. data/tasks/authors.rake +30 -0
  98. data/tasks/changelog.rake +18 -0
  99. data/tasks/copyright.rake +21 -0
  100. data/tasks/doc.rake +7 -0
  101. data/tasks/gem.rake +23 -0
  102. data/tasks/gem_installer.rake +76 -0
  103. data/tasks/install_dependencies.rake +6 -0
  104. data/tasks/manifest.rake +4 -0
  105. data/tasks/rcov.rake +23 -0
  106. data/tasks/release.rake +52 -0
  107. data/tasks/reversion.rake +8 -0
  108. data/tasks/setup.rake +24 -0
  109. data/tasks/spec.rake +7 -0
  110. data/tasks/yard.rake +4 -0
  111. metadata +188 -0
@@ -0,0 +1,146 @@
1
+ require 'rubygems'
2
+ require 'facets/array'
3
+ require 'facets/string'
4
+
5
+ require "autumn/coder"
6
+
7
+ describe Autumn::Coder do
8
+ before :each do
9
+ @coder = Autumn::Coder.new
10
+ end
11
+
12
+ it "should start with an indent of 0" do
13
+ @coder << "test string"
14
+ @coder.output.should eql("test string\n")
15
+ end
16
+
17
+ it "should indent by two spaces" do
18
+ @coder.indent!
19
+ @coder << "test string"
20
+ @coder.unindent!
21
+ @coder.output.should eql(" test string\n")
22
+ end
23
+
24
+ it "should indent each line of a multi-line string" do
25
+ @coder.indent!
26
+ @coder << "line 1\nline 2"
27
+ @coder.unindent!
28
+ @coder.output.should eql(" line 1\n line 2\n")
29
+ end
30
+
31
+ it "should insert a newline between consecutive calls to <<" do
32
+ @coder << "first string"
33
+ @coder << "second string"
34
+ @coder.output.should eql("first string\nsecond string\n")
35
+ end
36
+
37
+ it "should unindent by two spaces" do
38
+ @coder.indent!
39
+ @coder << "first string"
40
+ @coder.unindent!
41
+ @coder << "second string"
42
+ @coder.output.should eql(" first string\nsecond string\n")
43
+ end
44
+
45
+ it "should add newlines when given the newline! message" do
46
+ @coder << "first line"
47
+ @coder.newline!
48
+ @coder << "second line"
49
+ @coder.output.should eql("first line\n\nsecond line\n")
50
+ end
51
+
52
+ it "should generate a basic class template" do
53
+ @coder.klass('TestClass')
54
+ @coder.output.should eql("class TestClass\nend\n")
55
+ end
56
+
57
+ it "should generate a subclass template" do
58
+ @coder.klass('Subclass', 'Superclass')
59
+ @coder.output.should eql("class Subclass < Superclass\nend\n")
60
+ end
61
+
62
+ it "should indent the contents of a class" do
63
+ @coder.klass('TestClass') { |klass| klass << "content" }
64
+ @coder.output.should eql("class TestClass\n content\nend\n")
65
+ end
66
+
67
+ it "should generate a basic method template" do
68
+ @coder.method('test_method')
69
+ @coder.output.should eql("def test_method\nend\n")
70
+ end
71
+
72
+ it "should indent the contents of a method" do
73
+ @coder.method('test_method') { |meth| meth << "content" }
74
+ @coder.output.should eql("def test_method\n content\nend\n")
75
+ end
76
+
77
+ it "should properly generate a one-parameter method" do
78
+ @coder.method('test_method', :arg)
79
+ @coder.output.should eql("def test_method(arg)\nend\n")
80
+ end
81
+
82
+ it "should properly generate a multi-parameter method" do
83
+ @coder.method('test_method', :arg1, :arg2)
84
+ @coder.output.should eql("def test_method(arg1, arg2)\nend\n")
85
+ end
86
+
87
+ it "should properly generate optional parameters" do
88
+ @coder.method('test_method', { :arg => nil })
89
+ @coder.output.should eql("def test_method(arg=nil)\nend\n")
90
+ end
91
+
92
+ it "should properly generate multiple optional and required parameters" do
93
+ @coder.method('test_method', :req1, :req2, { :opt1 => '' }, { :opt2 => Array.new })
94
+ @coder.output.should eql(%{def test_method(req1, req2, opt1="", opt2=[])\nend\n})
95
+ end
96
+
97
+ it "should raise an exception for empty parameter names" do
98
+ lambda { @coder.method('test_method', '') }.should raise_error(ArgumentError)
99
+ end
100
+
101
+ it "should raise an exception for empty optional parameter names" do
102
+ lambda { @coder.method('test_method', { '' => nil }) }.should raise_error(ArgumentError)
103
+ end
104
+ end
105
+
106
+ describe Autumn::TemplateCoder do
107
+ before :each do
108
+ @coder = Autumn::TemplateCoder.new
109
+ end
110
+
111
+ it "should generate a proper leaf template" do
112
+ @coder.leaf('test_leaf')
113
+
114
+ # HACK extlib and facets both define String#margin to do different things;
115
+ # we need a way to un-require the dm-core gem once we've run the DM
116
+ # specs. For now, we're forced to redefine String#margin
117
+ String.class_eval do
118
+ def margin(n=0)
119
+ #d = /\A.*\n\s*(.)/.match( self )[1]
120
+ #d = /\A\s*(.)/.match( self)[1] unless d
121
+ d = ((/\A.*\n\s*(.)/.match(self)) ||
122
+ (/\A\s*(.)/.match(self)))[1]
123
+ return '' unless d
124
+ if n == 0
125
+ gsub(/\n\s*\Z/,'').gsub(/^\s*[#{d}]/, '')
126
+ else
127
+ gsub(/\n\s*\Z/,'').gsub(/^\s*[#{d}]/, ' ' * n)
128
+ end
129
+ end
130
+ end
131
+
132
+ @coder.output.should eql(%{
133
+ |# Controller for the TestLeaf leaf.
134
+ |
135
+ |class Controller < Autumn::Leaf
136
+ |
137
+ | # Typing "!about" displays some basic information about this leaf.
138
+ |
139
+ | def about_command(stem, sender, reply_to, msg)
140
+ | # This method renders the file "about.txt.erb"
141
+ | end
142
+ |end
143
+ |
144
+ }.margin)
145
+ end
146
+ end
@@ -0,0 +1,222 @@
1
+ require 'set'
2
+ require 'rubygems'
3
+ require 'facets/array'
4
+ require 'facets/enumerable'
5
+ require 'facets/kernel'
6
+ require 'facets/string'
7
+ require 'anise'
8
+
9
+ require 'autumn/misc'
10
+ require 'autumn/stem_facade'
11
+ require 'autumn/daemon'
12
+ require 'autumn/stem'
13
+ require 'autumn/ctcp'
14
+
15
+ describe Autumn::CTCP do
16
+ before :each do
17
+ @ctcp = Autumn::CTCP.new
18
+ @sender_hash = { :user => 'TestUser', :nick => 'TestNick', :host => 'ca.testhost.org' }
19
+ end
20
+
21
+ describe "with a mock stem" do
22
+ before :each do
23
+ @stem = mock('stem')
24
+ end
25
+
26
+ it "should parse CTCP requests in PRIVMSGs and broadcast two request-received methods" do
27
+ @stem.should_receive(:broadcast).once.with(:ctcp_test_request, @ctcp, @stem, @sender_hash, [])
28
+ @stem.should_receive(:broadcast).once.with(:ctcp_request_received, :test, @ctcp, @stem, @sender_hash, [])
29
+ @ctcp.irc_privmsg_event @stem, @sender_hash, :message => "\01TEST\01"
30
+ end
31
+
32
+ it "should parse unencoded arguments in CTCP requests" do
33
+ @stem.should_receive(:broadcast).once.with(:ctcp_test_request, @ctcp, @stem, @sender_hash, [ 'arg1', 'arg2' ])
34
+ @stem.should_receive(:broadcast).once.with(:ctcp_request_received, :test, @ctcp, @stem, @sender_hash, [ 'arg1', 'arg2' ])
35
+ @ctcp.irc_privmsg_event @stem, @sender_hash, :message => "\01TEST arg1 arg2\01"
36
+ end
37
+
38
+ it "should parse encoded arguments in CTCP requests" do
39
+ Autumn::CTCP::ENCODED_COMMANDS << 'TEST'
40
+ @stem.should_receive(:broadcast).once.with(:ctcp_test_request, @ctcp, @stem, @sender_hash, [ 'arg1', 'arg 2' ])
41
+ @stem.should_receive(:broadcast).once.with(:ctcp_request_received, :test, @ctcp, @stem, @sender_hash, [ 'arg1', 'arg 2' ])
42
+ @ctcp.irc_privmsg_event @stem, @sender_hash, :message => "\01TEST arg1 arg\\@2\01"
43
+ end
44
+
45
+ it "should correctly unescape all magic characters in its response" do
46
+ Autumn::CTCP::ENCODED_COMMANDS << 'TEST'
47
+ @stem.should_receive(:broadcast).once.with(:ctcp_test_request, @ctcp, @stem, @sender_hash, [ "\000\001\n\r \\" ])
48
+ @stem.should_receive(:broadcast).once.with(:ctcp_request_received, :test, @ctcp, @stem, @sender_hash, [ "\000\001\n\r \\" ])
49
+ @ctcp.irc_privmsg_event @stem, @sender_hash, :message => "\01TEST \\0\\1\\n\\r\\@\\\\\01"
50
+ end
51
+
52
+ it "should not parse space escapes in unencoded arguments in CTCP requests" do
53
+ @stem.should_receive(:broadcast).once.with(:ctcp_test_request, @ctcp, @stem, @sender_hash, [ 'arg1', 'arg\@2' ])
54
+ @stem.should_receive(:broadcast).once.with(:ctcp_request_received, :test, @ctcp, @stem, @sender_hash, [ 'arg1', 'arg\@2' ])
55
+ @ctcp.irc_privmsg_event @stem, @sender_hash, :message => "\01TEST arg1 arg\\@2\01"
56
+ end
57
+
58
+ it "should parse CTCP responses in NOTICEs and broadcast two response-received methods" do
59
+ @stem.should_receive(:broadcast).once.with(:ctcp_test_response, @ctcp, @stem, @sender_hash, [])
60
+ @stem.should_receive(:broadcast).once.with(:ctcp_response_received, :test, @ctcp, @stem, @sender_hash, [])
61
+ @ctcp.irc_notice_event @stem, @sender_hash, :message => "\01TEST\01"
62
+ end
63
+
64
+ it "should parse unencoded arguments in CTCP responses" do
65
+ @stem.should_receive(:broadcast).once.with(:ctcp_test_response, @ctcp, @stem, @sender_hash, [ 'arg1', 'arg2' ])
66
+ @stem.should_receive(:broadcast).once.with(:ctcp_response_received, :test, @ctcp, @stem, @sender_hash, [ 'arg1', 'arg2' ])
67
+ @ctcp.irc_notice_event @stem, @sender_hash, :message => "\01TEST arg1 arg2\01"
68
+ end
69
+
70
+ it "should parse encoded arguments in CTCP responses" do
71
+ Autumn::CTCP::ENCODED_COMMANDS << 'TEST'
72
+ @stem.should_receive(:broadcast).once.with(:ctcp_test_response, @ctcp, @stem, @sender_hash, [ 'arg1', 'arg 2' ])
73
+ @stem.should_receive(:broadcast).once.with(:ctcp_response_received, :test, @ctcp, @stem, @sender_hash, [ 'arg1', 'arg 2' ])
74
+ @ctcp.irc_notice_event @stem, @sender_hash, :message => "\01TEST arg1 arg\\@2\01"
75
+ end
76
+
77
+ it "should not parse space escapes in unencoded arguments in CTCP responses" do
78
+ @stem.should_receive(:broadcast).once.with(:ctcp_test_response, @ctcp, @stem, @sender_hash, [ 'arg1', 'arg\@2' ])
79
+ @stem.should_receive(:broadcast).once.with(:ctcp_response_received, :test, @ctcp, @stem, @sender_hash, [ 'arg1', 'arg\@2' ])
80
+ @ctcp.irc_notice_event @stem, @sender_hash, :message => "\01TEST arg1 arg\\@2\01"
81
+ end
82
+ end
83
+
84
+ describe "with an actual stem" do
85
+ before :each do
86
+ @ctcp.instance_variable_set(:@reply_queue, Hash.new { |h,k| h[k] = Array.new })
87
+
88
+ @stem = Autumn::Stem.new('irc.example.com', 'Example', :channel => '#example')
89
+ #TODO proper way to stub this?
90
+ @stem.instance_eval do
91
+ def privmsg(*args)
92
+ args
93
+ end
94
+ end
95
+ @stem.add_listener @ctcp
96
+ end
97
+
98
+ it "should set the @ctcp variable in a stem when it's added as a listener to that stem" do
99
+ @stem.instance_variable_get(:@ctcp).should eql(@ctcp)
100
+ end
101
+
102
+ it "should add a method of the form ctcp_* to the stem" do
103
+ lambda { @stem.ctcp_action("#example") }.should_not raise_error(NoMethodError)
104
+ end
105
+
106
+ it "... which replies with a CTCP message" do
107
+ @stem.ctcp_action("#example").should eql([ "#example", "\001ACTION\001" ])
108
+ end
109
+
110
+ it "... ... that properly encodes arguments when appropriate" do
111
+ @stem.ctcp_ping("#example", 'arg1', 'arg 2').should eql([ "#example", "\001PING arg1 arg\\@2\001" ])
112
+ end
113
+
114
+ it "... ... ... escaping all magic characters" do
115
+ @stem.ctcp_ping("#example", "\n\r \\\000\001").should eql([ "#example", "\001PING " + '\n\r\@\\\\\0\1' + "\001" ])
116
+ end
117
+
118
+ it "... ... that does not encode arguments when appropriate" do
119
+ @stem.ctcp_action("#example", "ABC 123").should eql([ "#example", "\001ACTION ABC 123\001" ])
120
+ end
121
+
122
+ it "should add a method of the form ctcp_reply_* to the stem" do
123
+ lambda { @stem.ctcp_reply_ping("Pinger") }.should_not raise_error(NoMethodError)
124
+ end
125
+
126
+ it "... which replies with a CTCP response" do
127
+ @stem.ctcp_reply_ping("Pinger")
128
+ reply_queue(@ctcp, @stem).shift.should == { :recipient => "Pinger", :message => "\001PING\001" }
129
+ end
130
+
131
+ it "... ... that properly encodes arguments when appropriate" do
132
+ @stem.ctcp_reply_ping("Pinger", 'arg1', 'arg 2')
133
+ reply_queue(@ctcp, @stem).shift.should == { :recipient => "Pinger", :message => "\001PING arg1 arg\\@2\001" }
134
+ end
135
+
136
+ it "... ... ... escaping all magic characters" do
137
+ @stem.ctcp_reply_ping("Pinger", "\n\r \\\000\001")
138
+ reply_queue(@ctcp, @stem).shift.should == { :recipient => "Pinger", :message => "\001PING " + '\n\r\@\\\\\0\1' + "\001" }
139
+ end
140
+
141
+ it "... ... that does not encode arguments when appropriate" do
142
+ @stem.ctcp_reply_example("Tester", "ABC 123")
143
+ reply_queue(@ctcp, @stem).shift.should == { :recipient => "Tester", :message => "\001EXAMPLE ABC 123\001" }
144
+ end
145
+ end
146
+
147
+ describe "with a mock stem that records message intervals" do
148
+ before :each do
149
+ @stem = Object.new
150
+ class << @stem
151
+ attr :received
152
+
153
+ def notice(*args)
154
+ @received ||= Array.new
155
+ @received << Time.now
156
+ end
157
+
158
+ def privmsg(*args)
159
+ end
160
+
161
+ def average_interval
162
+ times = Array.new
163
+ @received.each_by { |a, b| times << b - a if a and b }
164
+ return times.sum/times.size.to_f
165
+ end
166
+ end
167
+
168
+ @ctcp.added @stem
169
+ end
170
+
171
+ it "should queue replies and fire them at the default interval of 0.25 seconds" do
172
+ 10.times { @stem.ctcp_reply_ping "Pinger", "ABC123" }
173
+ sleep 3
174
+ @stem.average_interval.should be_close(0.25, 0.05)
175
+ end
176
+
177
+ it "should drop replies from the queue when the default maximum of 10 is exceeded" do
178
+ Thread.exclusive { 15.times { @stem.ctcp_reply_ping "Pinger", "ABC123" } }
179
+ sleep 4
180
+ @stem.received.size.should be_close(10, 1.5)
181
+ end
182
+
183
+ describe "with custom CTCP reply rate and queue length values" do
184
+ before :each do
185
+ @ctcp = Autumn::CTCP.new(:reply_rate => 0.5, :reply_queue_size => 5)
186
+ @ctcp.added @stem
187
+ end
188
+
189
+ it "should queue replies and fire them at a custom interval" do
190
+ 5.times { @stem.ctcp_reply_ping "Pinger", "ABC123" }
191
+ sleep 3
192
+ @stem.average_interval.should be_close(0.5, 0.05)
193
+ end
194
+
195
+ it "should drop replies from the queue when a custom maximum is exceeded" do
196
+ 15.times { @stem.ctcp_reply_ping "Pinger", "ABC123" }
197
+ sleep 4
198
+ @stem.received.size.should be_close(5, 1.5)
199
+ end
200
+ end
201
+ end
202
+
203
+ it "should respond to CTCP VERSION requests" do
204
+ @ctcp.should respond_to(:ctcp_version_request)
205
+ end
206
+
207
+ it "should respond to CTCP PING requests" do
208
+ @ctcp.should respond_to(:ctcp_ping_request)
209
+ end
210
+
211
+ it "should respond to CTCP TIME requests" do
212
+ @ctcp.should respond_to(:ctcp_time_request)
213
+ end
214
+
215
+ after :each do
216
+ Autumn::CTCP::ENCODED_COMMANDS.delete 'TEST'
217
+ end
218
+
219
+ def reply_queue(ctcp, stem)
220
+ ctcp.instance_variable_get(:@reply_queue)[stem]
221
+ end
222
+ end
@@ -0,0 +1,202 @@
1
+ require 'set'
2
+ require 'rubygems'
3
+ require 'facets/array'
4
+ require 'facets/string'
5
+
6
+ require 'autumn/misc'
7
+ require 'autumn/daemon'
8
+
9
+ describe Autumn::Daemon do
10
+ it "should not allow the creation of a default Daemon" do
11
+ lambda { Autumn::Daemon.new nil, nil }.should raise_error
12
+ end
13
+
14
+ describe "(the default daemon)" do
15
+ it "should exist" do
16
+ Autumn::Daemon.default.should_not be_nil
17
+ end
18
+
19
+ it "should parrot unknown properties" do
20
+ Autumn::Daemon.default.usermode['~'].should eql('~')
21
+ Autumn::Daemon.default.privilege['~'].should eql('~')
22
+ Autumn::Daemon.default.user_prefix['('].should eql('(')
23
+ Autumn::Daemon.default.channel_prefix['('].should eql('(')
24
+ Autumn::Daemon.default.channel_mode['~'].should eql('~')
25
+ Autumn::Daemon.default.server_mode['~'].should eql('~')
26
+ Autumn::Daemon.default.event[123].should eql(123)
27
+ end
28
+ end
29
+
30
+ describe "with some standard options" do
31
+ before :each do
32
+ @daemon = Autumn::Daemon.new 'daemon', {
33
+ 'usermode' => { 'f' => :first_usermode, 's' => :second_usermode },
34
+ 'privilege' => { 'f' => :first_priv, 's' => :second_priv },
35
+ 'user_prefix' => { '+' => :first_priv, '-' => :second_priv },
36
+ 'channel_prefix' => { '#' => :first_chantype, '&' => :second_chantype },
37
+ 'channel_mode' => { 'c' => :first_chanmode, 'd' => :second_chanmode },
38
+ 'server_mode' => { 'F' => :first_srvrmode, 'S' => :second_srvrmode },
39
+ 'event' => { 998 => :first_event, 997 => :second_event }
40
+ }
41
+ end
42
+
43
+ it "should associate a Daemon with its name" do
44
+ Autumn::Daemon['daemon'].should equal(@daemon)
45
+ end
46
+
47
+ it "should update the default Daemon with its properties" do
48
+ Autumn::Daemon.default.usermode['f'].should eql(:first_usermode)
49
+ Autumn::Daemon.default.privilege['f'].should eql(:first_priv)
50
+ Autumn::Daemon.default.user_prefix['+'].should eql(:first_priv)
51
+ Autumn::Daemon.default.channel_prefix['#'].should eql(:first_chantype)
52
+ Autumn::Daemon.default.channel_mode['c'].should eql(:first_chanmode)
53
+ Autumn::Daemon.default.server_mode['F'].should eql(:first_srvrmode)
54
+ Autumn::Daemon.default.event[998].should eql(:first_event)
55
+ end
56
+
57
+ it "should return hashes merged with the default" do
58
+ Autumn::Daemon.default.usermode['b'] = :new_usermode
59
+ Autumn::Daemon.default.privilege['b'] = :new_priv
60
+ Autumn::Daemon.default.user_prefix['$'] = :new_uprefix
61
+ Autumn::Daemon.default.channel_prefix['%'] = :new_cprefix
62
+ Autumn::Daemon.default.channel_mode['b'] = :new_chanmode
63
+ Autumn::Daemon.default.server_mode['B'] = :new_srvmode
64
+ Autumn::Daemon.default.event[100] = :new_event
65
+
66
+ @daemon.usermode['b'].should eql(:new_usermode)
67
+ @daemon.privilege['b'].should eql(:new_priv)
68
+ @daemon.user_prefix['$'].should eql(:new_uprefix)
69
+ @daemon.channel_prefix['%'].should eql(:new_cprefix)
70
+ @daemon.channel_mode['b'].should eql(:new_chanmode)
71
+ @daemon.server_mode['B'].should eql(:new_srvmode)
72
+ @daemon.event[100].should eql(:new_event)
73
+ end
74
+
75
+ it "should parrot unknown properties" do
76
+ @daemon.usermode['~'].should eql('~')
77
+ @daemon.privilege['~'].should eql('~')
78
+ @daemon.user_prefix['('].should eql('(')
79
+ @daemon.channel_prefix['('].should eql('(')
80
+ @daemon.channel_mode['~'].should eql('~')
81
+ @daemon.server_mode['~'].should eql('~')
82
+ @daemon.event[123].should eql(123)
83
+ end
84
+
85
+ it "should recognize a change in user privilege as such" do
86
+ @daemon.privilege_mode?('+f').should be_true
87
+ end
88
+
89
+ it "should recognize a change in channel mode as such" do
90
+ @daemon.privilege_mode?('+c').should be_false
91
+ end
92
+
93
+ it "should raise an exception when privilege_mode? is called with an invalid mode string" do
94
+ lambda { @daemon.privilege_mode?('invalid') }.should raise_error
95
+ end
96
+
97
+ it "should recognize when a nick is prefixed" do
98
+ @daemon.nick_prefixed?('+Nick').should be_true
99
+ end
100
+
101
+ it "should recognize when a nick is not prefixed" do
102
+ @daemon.nick_prefixed?('Nick').should be_false
103
+ end
104
+
105
+ it "should be able to strip a nick of prefix characters" do
106
+ @daemon.just_nick('+Nick').should eql('Nick')
107
+ end
108
+
109
+ it "should, when asked to strip a nick with no prefix characters, return that same nick" do
110
+ @daemon.just_nick('Nick').should eql('Nick')
111
+ end
112
+
113
+ it "should give the privilege of a nick with no prefixes as :unvoiced" do
114
+ @daemon.nick_privilege('Nick').should eql(:unvoiced)
115
+ end
116
+
117
+ it "should correctly give the privilege of a nick with one prefix" do
118
+ @daemon.nick_privilege('+Nick').should eql(:first_priv)
119
+ end
120
+
121
+ it "should correctly give the privileges of a nick with multiple prefixes" do
122
+ @daemon.nick_privilege('+-Nick').should == [ :first_priv, :second_priv ].to_set
123
+ end
124
+
125
+ it "should add predicate methods for each hash which return true for known values" do
126
+ @daemon.usermode?('f').should be_true
127
+ @daemon.privilege?('f').should be_true
128
+ @daemon.user_prefix?('+').should be_true
129
+ @daemon.channel_prefix?('#').should be_true
130
+ @daemon.channel_mode?('c').should be_true
131
+ @daemon.server_mode?('F').should be_true
132
+ @daemon.event?(998).should be_true
133
+ end
134
+
135
+ it "... and return false for unknown values" do
136
+ @daemon.usermode?('~').should be_false
137
+ @daemon.privilege?('~').should be_false
138
+ @daemon.user_prefix?('(').should be_false
139
+ @daemon.channel_prefix?('(').should be_false
140
+ @daemon.channel_mode?('~').should be_false
141
+ @daemon.server_mode?('~').should be_false
142
+ @daemon.event?(123).should be_false
143
+ end
144
+
145
+ it "... and should work with numeric prefix characters" do
146
+ @daemon.user_prefix?(?+).should be_true
147
+ @daemon.channel_prefix?(?#).should be_true
148
+ end
149
+
150
+ it "... and should return values in the default daemon as well" do
151
+ Autumn::Daemon.default.usermode['b'] = :new_usermode
152
+ Autumn::Daemon.default.privilege['b'] = :new_priv
153
+ Autumn::Daemon.default.user_prefix['$'] = :new_uprefix
154
+ Autumn::Daemon.default.channel_prefix['%'] = :new_cprefix
155
+ Autumn::Daemon.default.channel_mode['b'] = :new_chanmode
156
+ Autumn::Daemon.default.server_mode['B'] = :new_srvmode
157
+ Autumn::Daemon.default.event[100] = :new_event
158
+
159
+ @daemon.usermode?('b').should be_true
160
+ @daemon.privilege?('b').should be_true
161
+ @daemon.user_prefix?('$').should be_true
162
+ @daemon.channel_prefix?('%').should be_true
163
+ @daemon.channel_mode?('b').should be_true
164
+ @daemon.server_mode?('B').should be_true
165
+ @daemon.event?(100).should be_true
166
+ end
167
+
168
+ describe "initialized along with a second Daemon with some duplicate properties" do
169
+ before :each do
170
+ @daemon2 = Autumn::Daemon.new 'daemon2', {
171
+ 'usermode' => { 'f' => :first_usermode, 's' => :other_usermode },
172
+ 'privilege' => { 'f' => :first_priv, 's' => :other_priv },
173
+ 'user_prefix' => { '+' => :first_priv, '-' => :other_priv },
174
+ 'channel_prefix' => { '#' => :first_chantype, '&' => :other_chantype },
175
+ 'channel_mode' => { 'c' => :first_chanmode, 'd' => :other_chanmode },
176
+ 'server_mode' => { 'F' => :first_srvrmode, 'S' => :other_srvrmode },
177
+ 'event' => { 998 => :first_event, 997 => :other_event }
178
+ }
179
+ end
180
+
181
+ it "should not remove the duplicate properties with identical values from the default Daemon" do
182
+ Autumn::Daemon.default.usermode['f'].should eql(:first_usermode)
183
+ Autumn::Daemon.default.privilege['f'].should eql(:first_priv)
184
+ Autumn::Daemon.default.user_prefix['+'].should eql(:first_priv)
185
+ Autumn::Daemon.default.channel_prefix['#'].should eql(:first_chantype)
186
+ Autumn::Daemon.default.channel_mode['c'].should eql(:first_chanmode)
187
+ Autumn::Daemon.default.server_mode['F'].should eql(:first_srvrmode)
188
+ Autumn::Daemon.default.event[998].should eql(:first_event)
189
+ end
190
+
191
+ it "should remove the duplicate properties with different values from the default Daemon" do
192
+ Autumn::Daemon.default.usermode['s'].should eql('s')
193
+ Autumn::Daemon.default.privilege['s'].should eql('s')
194
+ Autumn::Daemon.default.user_prefix['-'].should eql('-')
195
+ Autumn::Daemon.default.channel_prefix['&'].should eql('&')
196
+ Autumn::Daemon.default.channel_mode['d'].should eql('d')
197
+ Autumn::Daemon.default.server_mode['S'].should eql('S')
198
+ Autumn::Daemon.default.event[997].should eql(997)
199
+ end
200
+ end
201
+ end
202
+ end