autumn 3.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +11 -0
- data/CHANGELOG +567 -0
- data/MANIFEST +110 -0
- data/README +1114 -0
- data/README.textile +1153 -0
- data/Rakefile +75 -0
- data/autumn.gemspec +44 -0
- data/bin/autumn +11 -0
- data/lib/autumn.rb +8 -0
- data/lib/autumn/authentication.rb +238 -0
- data/lib/autumn/channel_leaf.rb +107 -0
- data/lib/autumn/coder.rb +166 -0
- data/lib/autumn/console_boot.rb +10 -0
- data/lib/autumn/ctcp.rb +250 -0
- data/lib/autumn/daemon.rb +207 -0
- data/lib/autumn/datamapper_hacks.rb +290 -0
- data/lib/autumn/foliater.rb +231 -0
- data/lib/autumn/formatting.rb +236 -0
- data/lib/autumn/generator.rb +231 -0
- data/lib/autumn/genesis.rb +190 -0
- data/lib/autumn/inheritable_attributes.rb +162 -0
- data/lib/autumn/leaf.rb +738 -0
- data/lib/autumn/log_facade.rb +49 -0
- data/lib/autumn/misc.rb +87 -0
- data/lib/autumn/resources/daemons/Anothernet.yml +3 -0
- data/lib/autumn/resources/daemons/AustHex.yml +29 -0
- data/lib/autumn/resources/daemons/Bahamut.yml +67 -0
- data/lib/autumn/resources/daemons/Dancer.yml +3 -0
- data/lib/autumn/resources/daemons/GameSurge.yml +3 -0
- data/lib/autumn/resources/daemons/IRCnet.yml +3 -0
- data/lib/autumn/resources/daemons/Ithildin.yml +7 -0
- data/lib/autumn/resources/daemons/KineIRCd.yml +56 -0
- data/lib/autumn/resources/daemons/PTlink.yml +6 -0
- data/lib/autumn/resources/daemons/QuakeNet.yml +20 -0
- data/lib/autumn/resources/daemons/RFC1459.yml +158 -0
- data/lib/autumn/resources/daemons/RFC2811.yml +16 -0
- data/lib/autumn/resources/daemons/RFC2812.yml +36 -0
- data/lib/autumn/resources/daemons/RatBox.yml +25 -0
- data/lib/autumn/resources/daemons/Ultimate.yml +24 -0
- data/lib/autumn/resources/daemons/Undernet.yml +6 -0
- data/lib/autumn/resources/daemons/Unreal.yml +110 -0
- data/lib/autumn/resources/daemons/_Other.yml +7 -0
- data/lib/autumn/resources/daemons/aircd.yml +33 -0
- data/lib/autumn/resources/daemons/bdq-ircd.yml +3 -0
- data/lib/autumn/resources/daemons/hybrid.yml +38 -0
- data/lib/autumn/resources/daemons/ircu.yml +67 -0
- data/lib/autumn/resources/daemons/tr-ircd.yml +8 -0
- data/lib/autumn/script.rb +74 -0
- data/lib/autumn/speciator.rb +165 -0
- data/lib/autumn/stem.rb +919 -0
- data/lib/autumn/stem_facade.rb +176 -0
- data/lib/autumn/tool/bin.rb +301 -0
- data/lib/autumn/tool/create.rb +48 -0
- data/lib/autumn/tool/project_creator.rb +110 -0
- data/lib/autumn/version.rb +3 -0
- data/lib/skel/Rakefile +163 -0
- data/lib/skel/config/global.yml +2 -0
- data/lib/skel/config/seasons/testing/database.yml +4 -0
- data/lib/skel/config/seasons/testing/leaves.yml +9 -0
- data/lib/skel/config/seasons/testing/season.yml +2 -0
- data/lib/skel/config/seasons/testing/stems.yml +10 -0
- data/lib/skel/leaves/administrator/README +20 -0
- data/lib/skel/leaves/administrator/controller.rb +67 -0
- data/lib/skel/leaves/administrator/views/autumn.txt.erb +1 -0
- data/lib/skel/leaves/administrator/views/reload.txt.erb +11 -0
- data/lib/skel/leaves/insulter/README +17 -0
- data/lib/skel/leaves/insulter/controller.rb +65 -0
- data/lib/skel/leaves/insulter/views/about.txt.erb +1 -0
- data/lib/skel/leaves/insulter/views/help.txt.erb +1 -0
- data/lib/skel/leaves/insulter/views/insult.txt.erb +1 -0
- data/lib/skel/leaves/scorekeeper/README +34 -0
- data/lib/skel/leaves/scorekeeper/config.yml +2 -0
- data/lib/skel/leaves/scorekeeper/controller.rb +104 -0
- data/lib/skel/leaves/scorekeeper/helpers/general.rb +64 -0
- data/lib/skel/leaves/scorekeeper/models/channel.rb +12 -0
- data/lib/skel/leaves/scorekeeper/models/person.rb +14 -0
- data/lib/skel/leaves/scorekeeper/models/pseudonym.rb +11 -0
- data/lib/skel/leaves/scorekeeper/models/score.rb +14 -0
- data/lib/skel/leaves/scorekeeper/tasks/stats.rake +17 -0
- data/lib/skel/leaves/scorekeeper/views/about.txt.erb +1 -0
- data/lib/skel/leaves/scorekeeper/views/change.txt.erb +5 -0
- data/lib/skel/leaves/scorekeeper/views/history.txt.erb +11 -0
- data/lib/skel/leaves/scorekeeper/views/points.txt.erb +5 -0
- data/lib/skel/leaves/scorekeeper/views/usage.txt.erb +1 -0
- data/lib/skel/log/README +1 -0
- data/lib/skel/script/console +28 -0
- data/lib/skel/script/destroy +48 -0
- data/lib/skel/script/generate +48 -0
- data/lib/skel/shared/README +1 -0
- data/lib/skel/tmp/README +1 -0
- data/spec/authentication_spec.rb +328 -0
- data/spec/channel_leaf_spec.rb +142 -0
- data/spec/coder_spec.rb +146 -0
- data/spec/ctcp_spec.rb +222 -0
- data/spec/daemon_spec.rb +202 -0
- data/spec/datamapper_hacks_spec.rb +164 -0
- data/tasks/authors.rake +30 -0
- data/tasks/changelog.rake +18 -0
- data/tasks/copyright.rake +21 -0
- data/tasks/doc.rake +7 -0
- data/tasks/gem.rake +23 -0
- data/tasks/gem_installer.rake +76 -0
- data/tasks/install_dependencies.rake +6 -0
- data/tasks/manifest.rake +4 -0
- data/tasks/rcov.rake +23 -0
- data/tasks/release.rake +52 -0
- data/tasks/reversion.rake +8 -0
- data/tasks/setup.rake +24 -0
- data/tasks/spec.rake +7 -0
- data/tasks/yard.rake +4 -0
- metadata +188 -0
data/spec/coder_spec.rb
ADDED
@@ -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
|
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 '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
|
data/spec/daemon_spec.rb
ADDED
@@ -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
|