rocket-server 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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