rocket-server 0.0.1

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.
@@ -0,0 +1,257 @@
1
+ require File.expand_path("../spec_helper", __FILE__)
2
+
3
+ class Rocket::Server::Connection
4
+ def send(*args); end
5
+ end
6
+
7
+ describe Rocket::Server::Connection do
8
+ subject do
9
+ Rocket::Server::Connection
10
+ end
11
+
12
+ before do
13
+ Rocket::Server.instance_variable_set("@apps", {"test-app" => {"secret" => "my-secret"}})
14
+ end
15
+
16
+ describe "#initialize" do
17
+ it "should set all callbacks" do
18
+ conn = subject.new({})
19
+ conn.instance_variable_get("@onopen").should == conn.method(:onopen)
20
+ conn.instance_variable_get("@onclose").should == conn.method(:onclose)
21
+ conn.instance_variable_get("@onerror").should == conn.method(:onerror)
22
+ conn.instance_variable_get("@onmessage").should == conn.method(:onmessage)
23
+ end
24
+ end
25
+
26
+ describe "#onopen" do
27
+ context "when valid app specified in request" do
28
+ before do
29
+ @conn = subject.new(1)
30
+ @conn.request.expects(:"[]").with("Path").returns("/app/test-app")
31
+ @conn.request.stubs(:"[]").with("Query").returns({})
32
+ end
33
+
34
+ it "should start new session for it" do
35
+ @conn.stubs(:send)
36
+ @conn.onopen
37
+ session = @conn.session
38
+ session.should be_kind_of(Rocket::Server::Session)
39
+ session.app_id.should == "test-app"
40
+ end
41
+
42
+ it "should send message to connected client" do
43
+ @conn.expects(:send).with({:event => "rocket:connected", :data => { :session_id => 1 }}.to_json)
44
+ @conn.onopen.should == true
45
+ end
46
+ end
47
+
48
+ context "when invalid app specified in request" do
49
+ it "should close connection with client" do
50
+ conn = subject.new(1)
51
+ conn.request.expects(:"[]").with("Path").returns("/app/non-existing-app")
52
+ conn.request.stubs(:"[]").with("Query").returns({})
53
+ conn.expects(:close_connection)
54
+ conn.onopen
55
+ end
56
+ end
57
+
58
+ context "when valid secret given in request query" do
59
+ it "should start new session and authenticate it" do
60
+ conn = subject.new(1)
61
+ conn.request.expects(:"[]").with("Path").returns("/app/test-app")
62
+ conn.request.stubs(:"[]").with("Query").returns("secret" => "my-secret")
63
+ conn.expects(:send).with({:event => "rocket:connected", :data => { :session_id => 1 }}.to_json)
64
+ conn.onopen
65
+ session = conn.session
66
+ session.should be_authenticated
67
+ end
68
+ end
69
+
70
+ context "when invalid or no secret given" do
71
+ it "shouldn't authenticate session" do
72
+ conn = subject.new(1)
73
+ conn.request.expects(:"[]").with("Path").returns("/app/test-app")
74
+ conn.request.stubs(:"[]").with("Query").returns("secret" => "fooobar")
75
+ conn.onopen
76
+ session = conn.session
77
+ session.should_not be_authenticated
78
+ end
79
+ end
80
+ end
81
+
82
+ describe "#onclose" do
83
+ context "when session is active" do
84
+ it "should close it" do
85
+ conn = subject.new(1)
86
+ conn.request.expects(:"[]").with("Path").returns("/app/test-app")
87
+ conn.request.stubs(:"[]").with("Query").returns({})
88
+ conn.onopen
89
+ conn.session.expects(:close)
90
+ conn.onclose
91
+ end
92
+ end
93
+
94
+ context "when session is not active" do
95
+ it "should do nothing" do
96
+ conn = subject.new(1)
97
+ conn.onclose.should be_nil
98
+ end
99
+ end
100
+ end
101
+
102
+ describe "#onerror" do
103
+ it "should log given error" do
104
+ conn = Rocket::Server::Connection.new(1)
105
+ conn.request.expects(:"[]").with("Path").returns("/app/test-app")
106
+ conn.request.stubs(:"[]").with("Query").returns({})
107
+ conn.onopen
108
+ conn.onerror("test error here")
109
+ end
110
+ end
111
+
112
+ describe "#onmessage" do
113
+ subject do
114
+ conn = Rocket::Server::Connection.new(1)
115
+ conn.request.expects(:"[]").with("Path").returns("/app/test-app")
116
+ conn.request.stubs(:"[]").with("Query").returns({})
117
+ conn.onopen
118
+ conn
119
+ end
120
+
121
+ context "when given message is valid JSON" do
122
+ context "for rocket:subscribe message" do
123
+ it "should process it" do
124
+ conn = subject
125
+ message = {"event" => "rocket:subscribe", "channel" => "my-test-one"}
126
+ conn.expects(:subscribe!).with(instance_of(Hash))
127
+ conn.onmessage(message.to_json)
128
+ end
129
+ end
130
+
131
+ context "for rocket:unsubscribe message" do
132
+ it "should process it" do
133
+ conn = subject
134
+ message = {"event" => "rocket:unsubscribe", "channel" => "my-test-one"}
135
+ conn.expects(:unsubscribe!).with(instance_of(Hash))
136
+ conn.onmessage(message.to_json)
137
+ end
138
+ end
139
+
140
+ context "for other message" do
141
+ it "should process it" do
142
+ conn = subject
143
+ message = {"channel" => "my-test-chan", "event" => "my-test-even", "data" => {"foo" => "bar"}}
144
+ conn.expects(:trigger!).with(instance_of(Hash))
145
+ conn.onmessage(message.to_json)
146
+ end
147
+ end
148
+ end
149
+
150
+ context "when given message is invalid JSON" do
151
+ it "should log proper error" do
152
+ conn = subject
153
+ conn.onmessage("{invalid JSON here}")
154
+ end
155
+ end
156
+ end
157
+
158
+ describe "#session?" do
159
+ context "when current session exists" do
160
+ it "should be true" do
161
+ conn = subject.new(1)
162
+ conn.request.expects(:"[]").with("Path").returns("/app/test-app")
163
+ conn.request.stubs(:"[]").with("Query").returns({})
164
+ conn.onopen
165
+ conn.should be_session
166
+ end
167
+ end
168
+
169
+ context "when there is no session" do
170
+ it "should be false" do
171
+ conn = subject.new(1)
172
+ conn.should_not be_session
173
+ end
174
+ end
175
+ end
176
+
177
+ describe "#subscribe!" do
178
+ before do
179
+ @conn = subject.new(1)
180
+ @conn.request.expects(:"[]").with("Path").returns("/app/test-app")
181
+ @conn.request.stubs(:"[]").with("Query").returns({})
182
+ @conn.onopen
183
+ end
184
+
185
+ context "when given valid event data" do
186
+ it "should subscribe channel" do
187
+ @conn.subscribe!({"channel" => "test-channel"}).should be
188
+ @conn.session.subscriptions.should have(1).item
189
+ end
190
+ end
191
+
192
+ context "when no valid event data given" do
193
+ it "should return false" do
194
+ @conn.subscribe!({"channello" => "test-channel"}).should be_false
195
+ end
196
+ end
197
+ end
198
+
199
+ describe "#unsubscribe!" do
200
+ before do
201
+ @conn = subject.new(1)
202
+ @conn.request.expects(:"[]").with("Path").returns("/app/test-app")
203
+ @conn.request.stubs(:"[]").with("Query").returns({})
204
+ @conn.onopen
205
+ end
206
+
207
+ context "when given valid event data" do
208
+ it "should unsubscribe channel" do
209
+ @conn.unsubscribe!({"channel" => "test-channel"})
210
+ end
211
+ end
212
+
213
+ context "when no valid event data given" do
214
+ it "should return false" do
215
+ @conn.unsubscribe!({"channello" => "test-channel"}).should be_false
216
+ end
217
+ end
218
+ end
219
+
220
+ describe "#trigger!" do
221
+ before do
222
+ @conn = subject.new(1)
223
+ @conn.request.expects(:"[]").with("Path").returns("/app/test-app")
224
+ @conn.request.stubs(:"[]").with("Query").returns({})
225
+ @conn.onopen
226
+ end
227
+
228
+ context "when session is not authenticated" do
229
+ it "should log proper error" do
230
+ data = {"event" => "test", "channel" => "testing"}
231
+ @conn.trigger!(data)
232
+ end
233
+ end
234
+
235
+ context "when session is authenticated" do
236
+ before do
237
+ @conn.session.authenticate!("my-secret")
238
+ end
239
+
240
+ context "when event data is valid" do
241
+ it "should broadcast it on given channel" do
242
+ data = {"event" => "test", "channel" => "testing"}
243
+ Rocket::Server::Channel["test-app" => "testing"].expects(:push).with(data.to_json)
244
+ @conn.trigger!(data)
245
+ end
246
+ end
247
+
248
+ context "when event data is invalid" do
249
+ it "should log proper error" do
250
+ data = {"evento" => "test", "channello" => "testing"}
251
+ @conn.trigger!(data)
252
+ end
253
+ end
254
+ end
255
+
256
+ end
257
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path("../spec_helper", __FILE__)
2
+
3
+ class HelpersPoweredClass
4
+ include Rocket::Server::Helpers
5
+ end
6
+
7
+ describe Rocket::Server::Helpers do
8
+ subject do
9
+ HelpersPoweredClass.new
10
+ end
11
+
12
+ it "#log should be proxy to Rocket::Server.logger" do
13
+ subject.log.should == Rocket::Server.logger
14
+ end
15
+
16
+ it "should respond to all log level-specific methods" do
17
+ subject.should respond_to(:log_info)
18
+ subject.should respond_to(:log_debug)
19
+ subject.should respond_to(:log_warn)
20
+ subject.should respond_to(:log_error)
21
+ subject.should respond_to(:log_fatal)
22
+ end
23
+ end
@@ -0,0 +1,31 @@
1
+ require File.expand_path("../spec_helper", __FILE__)
2
+
3
+ describe Rocket::Server::Misc do
4
+ subject do
5
+ Rocket::Server::Misc
6
+ end
7
+
8
+ describe ".generate_config_file" do
9
+ context "when everything's ok" do
10
+ it "should create default config under given path" do
11
+ begin
12
+ subject.generate_config_file(fname = File.expand_path("../rocket.yml", __FILE__))
13
+ File.should be_exist(fname)
14
+ expect { YAML.load_file(fname) }.to_not raise_error
15
+ ensure
16
+ FileUtils.rm_rf(fname)
17
+ end
18
+ end
19
+ end
20
+
21
+ context "when error raised" do
22
+ it "should rescue it and display, and exit program" do
23
+ out, err = capture_output {
24
+ File.expects(:open).raises(Errno::EACCES)
25
+ expect { subject.generate_config_file("rocket.yml") }.to raise_error(SystemExit)
26
+ }
27
+ out.should == "Permission denied\n"
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,138 @@
1
+ require File.expand_path("../spec_helper", __FILE__)
2
+
3
+ describe Rocket::Server::Runner do
4
+ subject do
5
+ Rocket::Server::Runner
6
+ end
7
+
8
+ describe "#initialize" do
9
+ it "should set options" do
10
+ subject.new(1=>2).options.should == {1=>2}
11
+ end
12
+
13
+ context "when host and port given" do
14
+ it "should set it properly" do
15
+ serv = subject.new(:host => 'test.host', :port => 999)
16
+ serv.host.should == 'test.host'
17
+ serv.port.should == 999
18
+ end
19
+ end
20
+
21
+ context "when no host or port given" do
22
+ it "should set default values for it" do
23
+ serv = subject.new
24
+ serv.host.should == 'localhost'
25
+ serv.port.should == 9772
26
+ end
27
+ end
28
+
29
+ it "should remove unnecessary options" do
30
+ serv = subject.new(:verbose => true, :quiet => false, :log => 1, :apps => [], :plugins => [])
31
+ serv.options.values.should be_empty
32
+ end
33
+
34
+ context "when :pid option given" do
35
+ it "should set it" do
36
+ serv = subject.new(:pid => "test.pid")
37
+ serv.pidfile.should == "test.pid"
38
+ end
39
+ end
40
+
41
+ context "when :daemon option given" do
42
+ it "should set it" do
43
+ serv = subject.new(:daemon => true)
44
+ serv.daemon.should == true
45
+ end
46
+ end
47
+ end
48
+
49
+ describe "#stop!" do
50
+ it "should stop EventMachine reactor" do
51
+ EM.expects(:stop)
52
+ subject.new.stop!
53
+ end
54
+ end
55
+
56
+ describe "#start!" do
57
+ context "when daemon mode disabled" do
58
+ it "should start server on given host and port" do
59
+ EM.expects(:start_server).with("test.host", 9992, Rocket::Server::Connection, instance_of(Hash))
60
+ t = Thread.new { subject.new(:host => "test.host", :port => 9992).start! }
61
+ t.kill
62
+ end
63
+ end
64
+
65
+ context "when daemon mode enabled" do
66
+ it "should daemonize server" do
67
+ serv = subject.new(:host => "test.host", :port => 9992, :daemon => true)
68
+ serv.expects(:daemonize!).returns(:test)
69
+ serv.start!.should == :test
70
+ end
71
+ end
72
+ end
73
+
74
+ describe "#save_pid" do
75
+ context "when pid file given" do
76
+ subject do
77
+ Rocket::Server::Runner.new(:pid => "test.pid")
78
+ end
79
+
80
+ context "and everything's ok" do
81
+ it "should save process id to this file" do
82
+ mock_file = mock
83
+ mock_file.expects(:write).with("#{Process.pid}\n")
84
+ File.expects(:open).with("test.pid", "w+").yields(mock_file)
85
+ subject.save_pid
86
+ end
87
+ end
88
+
89
+ context "and some errors raises" do
90
+ it "should display error and quit" do
91
+ out, err = capture_output {
92
+ FileUtils.expects(:mkdir_p).with(".").raises(Errno::EACCES)
93
+ expect { subject.save_pid }.to raise_error(SystemExit)
94
+ }
95
+ out.should == "Permission denied\n"
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ describe "#kill!" do
102
+ context "when pid file given" do
103
+ subject do
104
+ Rocket::Server::Runner.new(:pid => "test.pid")
105
+ end
106
+
107
+ context "and it doesn't exist" do
108
+ it "should do nothing" do
109
+ File.expects(:exists?).with("test.pid").returns(false)
110
+ subject.kill!.should_not be
111
+ end
112
+ end
113
+
114
+ context "and it exists" do
115
+ it "should remove it and kill given process" do
116
+ File.expects(:exists?).with("test.pid").returns(true)
117
+ File.expects(:read).with("test.pid").returns("123\n")
118
+ FileUtils.expects(:rm).with("test.pid")
119
+ Process.expects(:kill).with(9, 123)
120
+ subject.kill!.should == 123
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ describe "#daemonize!" do
127
+ subject do
128
+ Rocket::Server::Runner.new(:pid => "test.pid")
129
+ end
130
+
131
+ it "should switch to deamon mode and start server" do
132
+ serv = subject
133
+ serv.expects(:daemonize)
134
+ serv.expects(:start!)
135
+ serv.daemonize!
136
+ end
137
+ end
138
+ end