bougyman-autumn 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. data/AUTHORS +11 -0
  2. data/CHANGELOG +511 -0
  3. data/MANIFEST +109 -0
  4. data/README +1141 -0
  5. data/README.textile +1175 -0
  6. data/Rakefile +75 -0
  7. data/autumn.gemspec +43 -0
  8. data/bin/autumn +11 -0
  9. data/lib/autumn/authentication.rb +238 -0
  10. data/lib/autumn/channel_leaf.rb +107 -0
  11. data/lib/autumn/coder.rb +166 -0
  12. data/lib/autumn/console_boot.rb +10 -0
  13. data/lib/autumn/ctcp.rb +250 -0
  14. data/lib/autumn/daemon.rb +207 -0
  15. data/lib/autumn/datamapper_hacks.rb +290 -0
  16. data/lib/autumn/foliater.rb +231 -0
  17. data/lib/autumn/formatting.rb +236 -0
  18. data/lib/autumn/generator.rb +231 -0
  19. data/lib/autumn/genesis.rb +190 -0
  20. data/lib/autumn/inheritable_attributes.rb +162 -0
  21. data/lib/autumn/leaf.rb +738 -0
  22. data/lib/autumn/log_facade.rb +49 -0
  23. data/lib/autumn/misc.rb +87 -0
  24. data/lib/autumn/resources/daemons/Anothernet.yml +3 -0
  25. data/lib/autumn/resources/daemons/AustHex.yml +29 -0
  26. data/lib/autumn/resources/daemons/Bahamut.yml +67 -0
  27. data/lib/autumn/resources/daemons/Dancer.yml +3 -0
  28. data/lib/autumn/resources/daemons/GameSurge.yml +3 -0
  29. data/lib/autumn/resources/daemons/IRCnet.yml +3 -0
  30. data/lib/autumn/resources/daemons/Ithildin.yml +7 -0
  31. data/lib/autumn/resources/daemons/KineIRCd.yml +56 -0
  32. data/lib/autumn/resources/daemons/PTlink.yml +6 -0
  33. data/lib/autumn/resources/daemons/QuakeNet.yml +20 -0
  34. data/lib/autumn/resources/daemons/RFC1459.yml +158 -0
  35. data/lib/autumn/resources/daemons/RFC2811.yml +16 -0
  36. data/lib/autumn/resources/daemons/RFC2812.yml +36 -0
  37. data/lib/autumn/resources/daemons/RatBox.yml +25 -0
  38. data/lib/autumn/resources/daemons/Ultimate.yml +24 -0
  39. data/lib/autumn/resources/daemons/Undernet.yml +6 -0
  40. data/lib/autumn/resources/daemons/Unreal.yml +110 -0
  41. data/lib/autumn/resources/daemons/_Other.yml +7 -0
  42. data/lib/autumn/resources/daemons/aircd.yml +33 -0
  43. data/lib/autumn/resources/daemons/bdq-ircd.yml +3 -0
  44. data/lib/autumn/resources/daemons/hybrid.yml +38 -0
  45. data/lib/autumn/resources/daemons/ircu.yml +67 -0
  46. data/lib/autumn/resources/daemons/tr-ircd.yml +8 -0
  47. data/lib/autumn/script.rb +74 -0
  48. data/lib/autumn/speciator.rb +165 -0
  49. data/lib/autumn/stem.rb +919 -0
  50. data/lib/autumn/stem_facade.rb +176 -0
  51. data/lib/autumn/tool/bin.rb +302 -0
  52. data/lib/autumn/tool/create.rb +48 -0
  53. data/lib/autumn/tool/project_creator.rb +110 -0
  54. data/lib/autumn/version.rb +3 -0
  55. data/lib/autumn.rb +6 -0
  56. data/lib/skel/Rakefile +135 -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 +141 -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/bacon.rake +66 -0
  99. data/tasks/changelog.rake +18 -0
  100. data/tasks/copyright.rake +21 -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/yard.rake +4 -0
  110. metadata +187 -0
@@ -0,0 +1,146 @@
1
+ require 'rubygems'
2
+ require 'facets/array'
3
+ require 'facets/string'
4
+
5
+ require "libs/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
data/spec/ctcp_spec.rb ADDED
@@ -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 'libs/misc'
10
+ require 'libs/stem_facade'
11
+ require 'libs/daemon'
12
+ require 'libs/stem'
13
+ require 'libs/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 'libs/misc'
7
+ require 'libs/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