faye 0.5.5 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of faye might be problematic. Click here for more details.
- data/History.txt +14 -0
- data/README.rdoc +98 -0
- data/Rakefile +17 -15
- data/lib/faye-browser-min.js +1 -1
- data/lib/faye.rb +14 -5
- data/lib/faye/adapters/rack_adapter.rb +12 -5
- data/lib/faye/engines/base.rb +62 -0
- data/lib/faye/engines/connection.rb +63 -0
- data/lib/faye/engines/memory.rb +89 -0
- data/lib/faye/engines/redis.rb +141 -0
- data/lib/faye/error.rb +16 -4
- data/lib/faye/mixins/publisher.rb +6 -0
- data/lib/faye/protocol/channel.rb +34 -86
- data/lib/faye/protocol/client.rb +36 -52
- data/lib/faye/protocol/extensible.rb +3 -0
- data/lib/faye/protocol/server.rb +119 -169
- data/lib/faye/transport/http.rb +45 -0
- data/lib/faye/transport/local.rb +15 -0
- data/lib/faye/{network → transport}/transport.rb +36 -49
- data/spec/browser.html +35 -0
- data/spec/install.sh +48 -0
- data/spec/javascript/channel_spec.js +15 -0
- data/spec/javascript/client_spec.js +610 -0
- data/spec/javascript/engine_spec.js +319 -0
- data/spec/javascript/faye_spec.js +15 -0
- data/spec/javascript/grammar_spec.js +66 -0
- data/spec/javascript/node_adapter_spec.js +276 -0
- data/spec/javascript/server/connect_spec.js +168 -0
- data/spec/javascript/server/disconnect_spec.js +121 -0
- data/spec/javascript/server/extensions_spec.js +60 -0
- data/spec/javascript/server/handshake_spec.js +153 -0
- data/spec/javascript/server/subscribe_spec.js +245 -0
- data/spec/javascript/server/unsubscribe_spec.js +245 -0
- data/spec/javascript/server_spec.js +146 -0
- data/spec/javascript/transport_spec.js +130 -0
- data/spec/node.js +34 -0
- data/spec/ruby/channel_spec.rb +17 -0
- data/spec/ruby/client_spec.rb +615 -0
- data/spec/ruby/engine_spec.rb +312 -0
- data/spec/ruby/faye_spec.rb +14 -0
- data/spec/ruby/grammar_spec.rb +68 -0
- data/spec/ruby/rack_adapter_spec.rb +209 -0
- data/spec/ruby/server/connect_spec.rb +170 -0
- data/spec/ruby/server/disconnect_spec.rb +120 -0
- data/spec/ruby/server/extensions_spec.rb +69 -0
- data/spec/ruby/server/handshake_spec.rb +151 -0
- data/spec/ruby/server/subscribe_spec.rb +247 -0
- data/spec/ruby/server/unsubscribe_spec.rb +247 -0
- data/spec/ruby/server_spec.rb +138 -0
- data/spec/ruby/transport_spec.rb +128 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/testswarm.pl +200 -0
- data/spec/thin_proxy.rb +36 -0
- metadata +119 -84
- data/Manifest.txt +0 -27
- data/README.txt +0 -98
- data/lib/faye/protocol/connection.rb +0 -111
- data/test/scenario.rb +0 -172
- data/test/test_channel.rb +0 -54
- data/test/test_clients.rb +0 -381
- data/test/test_grammar.rb +0 -86
- data/test/test_server.rb +0 -488
@@ -0,0 +1,170 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "server connect" do
|
4
|
+
let(:engine) { mock "engine" }
|
5
|
+
let(:server) { Faye::Server.new }
|
6
|
+
|
7
|
+
before do
|
8
|
+
Faye::Engine.stub(:get).and_return engine
|
9
|
+
end
|
10
|
+
|
11
|
+
describe :connect do
|
12
|
+
let(:client_id) { "fakeclientid" }
|
13
|
+
let(:message) {{"channel" => "/meta/connect",
|
14
|
+
"clientId" => "fakeclientid",
|
15
|
+
"connectionType" => "long-polling"
|
16
|
+
}}
|
17
|
+
|
18
|
+
describe "with valid paramters" do
|
19
|
+
before do
|
20
|
+
message["advice"] = {"timeout" => 60}
|
21
|
+
engine.should_receive(:client_exists).with(client_id).and_yield true
|
22
|
+
end
|
23
|
+
|
24
|
+
it "connects to the engine to wait for new messages" do
|
25
|
+
engine.should_receive(:connect).with(client_id, {"timeout" => 60})
|
26
|
+
server.connect(message) {}
|
27
|
+
end
|
28
|
+
|
29
|
+
it "returns a successful response and any queued messages" do
|
30
|
+
engine.stub(:connect).and_yield([{"channel" => "/x", "data" => "hello"}])
|
31
|
+
server.connect(message) do |response|
|
32
|
+
response.should == [
|
33
|
+
{ "channel" => "/meta/connect",
|
34
|
+
"successful" => true,
|
35
|
+
"clientId" => client_id
|
36
|
+
}, {
|
37
|
+
"channel" => "/x",
|
38
|
+
"data" => "hello"
|
39
|
+
}
|
40
|
+
]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "with a message id" do
|
45
|
+
before { message["id"] = "foo" }
|
46
|
+
|
47
|
+
it "returns the same id" do
|
48
|
+
engine.stub(:connect)
|
49
|
+
server.connect(message) do |response|
|
50
|
+
response.should == {
|
51
|
+
"channel" => "/meta/connect",
|
52
|
+
"successful" => true,
|
53
|
+
"clientId" => client_id,
|
54
|
+
"id" => "foo"
|
55
|
+
}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "with an unknown client" do
|
62
|
+
before do
|
63
|
+
engine.should_receive(:client_exists).with(client_id).and_yield false
|
64
|
+
end
|
65
|
+
|
66
|
+
it "does not connect to the engine" do
|
67
|
+
engine.should_not_receive(:connect)
|
68
|
+
server.connect(message) {}
|
69
|
+
end
|
70
|
+
|
71
|
+
it "returns an unsuccessful response" do
|
72
|
+
server.connect(message) do |response|
|
73
|
+
response.should == {
|
74
|
+
"channel" => "/meta/connect",
|
75
|
+
"successful" => false,
|
76
|
+
"error" => "401:fakeclientid:Unknown client"
|
77
|
+
}
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "missing clientId" do
|
83
|
+
before do
|
84
|
+
message.delete("clientId")
|
85
|
+
engine.should_receive(:client_exists).with(nil).and_yield false
|
86
|
+
end
|
87
|
+
|
88
|
+
it "does not connect to the engine" do
|
89
|
+
engine.should_not_receive(:connect)
|
90
|
+
server.connect(message) {}
|
91
|
+
end
|
92
|
+
|
93
|
+
it "returns an unsuccessful response" do
|
94
|
+
server.connect(message) do |response|
|
95
|
+
response.should == {
|
96
|
+
"channel" => "/meta/connect",
|
97
|
+
"successful" => false,
|
98
|
+
"error" => "402:clientId:Missing required parameter"
|
99
|
+
}
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "missing connectionType" do
|
105
|
+
before do
|
106
|
+
message.delete("connectionType")
|
107
|
+
engine.should_receive(:client_exists).with(client_id).and_yield true
|
108
|
+
end
|
109
|
+
|
110
|
+
it "does not connect to the engine" do
|
111
|
+
engine.should_not_receive(:connect)
|
112
|
+
server.connect(message) {}
|
113
|
+
end
|
114
|
+
|
115
|
+
it "returns an unsuccessful response" do
|
116
|
+
server.connect(message) do |response|
|
117
|
+
response.should == {
|
118
|
+
"channel" => "/meta/connect",
|
119
|
+
"successful" => false,
|
120
|
+
"error" => "402:connectionType:Missing required parameter"
|
121
|
+
}
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "with an unknown connectionType" do
|
127
|
+
before do
|
128
|
+
message["connectionType"] = "flash"
|
129
|
+
engine.should_receive(:client_exists).with(client_id).and_yield true
|
130
|
+
end
|
131
|
+
|
132
|
+
it "does not connect to the engine" do
|
133
|
+
engine.should_not_receive(:connect)
|
134
|
+
server.connect(message) {}
|
135
|
+
end
|
136
|
+
|
137
|
+
it "returns an unsuccessful response" do
|
138
|
+
server.connect(message) do |response|
|
139
|
+
response.should == {
|
140
|
+
"channel" => "/meta/connect",
|
141
|
+
"successful" => false,
|
142
|
+
"error" => "301:flash:Connection types not supported"
|
143
|
+
}
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "with an error" do
|
149
|
+
before do
|
150
|
+
message["error"] = "invalid"
|
151
|
+
engine.should_receive(:client_exists).with(client_id).and_yield true
|
152
|
+
end
|
153
|
+
|
154
|
+
it "does not connect to the engine" do
|
155
|
+
engine.should_not_receive(:connect)
|
156
|
+
server.connect(message) {}
|
157
|
+
end
|
158
|
+
|
159
|
+
it "returns an unsuccessful response" do
|
160
|
+
server.connect(message) do |response|
|
161
|
+
response.should == {
|
162
|
+
"channel" => "/meta/connect",
|
163
|
+
"successful" => false,
|
164
|
+
"error" => "invalid"
|
165
|
+
}
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "server disconnect" do
|
4
|
+
let(:engine) { mock "engine" }
|
5
|
+
let(:server) { Faye::Server.new }
|
6
|
+
|
7
|
+
before do
|
8
|
+
Faye::Engine.stub(:get).and_return engine
|
9
|
+
end
|
10
|
+
|
11
|
+
describe :disconnect do
|
12
|
+
let(:client_id) { "fakeclientid" }
|
13
|
+
let(:message) {{"channel" => "/meta/disconnect",
|
14
|
+
"clientId" => "fakeclientid"
|
15
|
+
}}
|
16
|
+
|
17
|
+
describe "with valid parameters" do
|
18
|
+
before do
|
19
|
+
engine.should_receive(:client_exists).with(client_id).and_yield true
|
20
|
+
end
|
21
|
+
|
22
|
+
it "destroys the client" do
|
23
|
+
engine.should_receive(:destroy_client).with(client_id)
|
24
|
+
server.disconnect(message) {}
|
25
|
+
end
|
26
|
+
|
27
|
+
it "returns a successful response" do
|
28
|
+
engine.stub(:destroy_client)
|
29
|
+
server.disconnect(message) do |response|
|
30
|
+
response.should == {
|
31
|
+
"channel" => "/meta/disconnect",
|
32
|
+
"successful" => true,
|
33
|
+
"clientId" => client_id
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "with a message id" do
|
39
|
+
before { message["id"] = "foo" }
|
40
|
+
|
41
|
+
it "returns the same id" do
|
42
|
+
engine.stub(:destroy_client)
|
43
|
+
server.disconnect(message) do |response|
|
44
|
+
response.should == {
|
45
|
+
"channel" => "/meta/disconnect",
|
46
|
+
"successful" => true,
|
47
|
+
"clientId" => client_id,
|
48
|
+
"id" => "foo"
|
49
|
+
}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "with an unknown client" do
|
56
|
+
before do
|
57
|
+
engine.should_receive(:client_exists).with(client_id).and_yield false
|
58
|
+
end
|
59
|
+
|
60
|
+
it "does not destroy the client" do
|
61
|
+
engine.should_not_receive(:destroy_client)
|
62
|
+
server.disconnect(message) {}
|
63
|
+
end
|
64
|
+
|
65
|
+
it "returns an unsuccessful response" do
|
66
|
+
server.disconnect(message) do |response|
|
67
|
+
response.should == {
|
68
|
+
"channel" => "/meta/disconnect",
|
69
|
+
"successful" => false,
|
70
|
+
"error" => "401:fakeclientid:Unknown client"
|
71
|
+
}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "missing clientId" do
|
77
|
+
before do
|
78
|
+
message.delete("clientId")
|
79
|
+
engine.should_receive(:client_exists).with(nil).and_yield false
|
80
|
+
end
|
81
|
+
|
82
|
+
it "does not destroy the client" do
|
83
|
+
engine.should_not_receive(:destroy_client)
|
84
|
+
server.disconnect(message) {}
|
85
|
+
end
|
86
|
+
|
87
|
+
it "returns an unsuccessful response" do
|
88
|
+
server.disconnect(message) do |response|
|
89
|
+
response.should == {
|
90
|
+
"channel" => "/meta/disconnect",
|
91
|
+
"successful" => false,
|
92
|
+
"error" => "402:clientId:Missing required parameter"
|
93
|
+
}
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "with an error" do
|
99
|
+
before do
|
100
|
+
message["error"] = "invalid"
|
101
|
+
engine.should_receive(:client_exists).with(client_id).and_yield true
|
102
|
+
end
|
103
|
+
|
104
|
+
it "does not destroy the client" do
|
105
|
+
engine.should_not_receive(:destroy_client)
|
106
|
+
server.disconnect(message) {}
|
107
|
+
end
|
108
|
+
|
109
|
+
it "returns an unsuccessful response" do
|
110
|
+
server.disconnect(message) do |response|
|
111
|
+
response.should == {
|
112
|
+
"channel" => "/meta/disconnect",
|
113
|
+
"successful" => false,
|
114
|
+
"error" => "invalid"
|
115
|
+
}
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "server extensions" do
|
4
|
+
let(:engine) do
|
5
|
+
engine = mock "engine"
|
6
|
+
engine.stub(:interval).and_return(0)
|
7
|
+
engine.stub(:timeout).and_return(60)
|
8
|
+
engine
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:server) { Faye::Server.new }
|
12
|
+
let(:message) { {"channel" => "/foo", "data" => "hello"} }
|
13
|
+
let(:advice) { {"reconnect"=>"retry", "interval"=>0, "timeout"=>60000} }
|
14
|
+
|
15
|
+
before do
|
16
|
+
Faye::Engine.stub(:get).and_return engine
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "with an incoming extension installed" do
|
20
|
+
before do
|
21
|
+
extension = Class.new do
|
22
|
+
def incoming(message, callback)
|
23
|
+
message["ext"] = {"auth" => "password"}
|
24
|
+
callback.call(message)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
server.add_extension(extension.new)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "passes incoming messages through the extension" do
|
31
|
+
engine.should_receive(:publish).with({"channel" => "/foo", "data" => "hello", "ext" => {"auth" => "password"}})
|
32
|
+
server.process(message, false) {}
|
33
|
+
end
|
34
|
+
|
35
|
+
it "does not pass outgoing messages through the extension" do
|
36
|
+
server.stub(:handshake).and_yield(message)
|
37
|
+
engine.stub(:publish)
|
38
|
+
response = nil
|
39
|
+
server.process({"channel" => "/meta/handshake"}, false) { |r| response = r }
|
40
|
+
response.should == [{"channel" => "/foo", "data" => "hello", "advice" => advice}]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "with an outgoing extension installed" do
|
45
|
+
before do
|
46
|
+
extension = Class.new do
|
47
|
+
def outgoing(message, callback)
|
48
|
+
message["ext"] = {"auth" => "password"}
|
49
|
+
callback.call(message)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
server.add_extension(extension.new)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "does not pass incoming messages through the extension" do
|
56
|
+
engine.should_receive(:publish).with({"channel" => "/foo", "data" => "hello"})
|
57
|
+
server.process(message, false) {}
|
58
|
+
end
|
59
|
+
|
60
|
+
it "passes outgoing messages through the extension" do
|
61
|
+
server.stub(:handshake).and_yield(message)
|
62
|
+
engine.stub(:publish)
|
63
|
+
response = nil
|
64
|
+
server.process({"channel" => "/meta/handshake"}, false) { |r| response = r }
|
65
|
+
response.should == [{"channel" => "/foo", "data" => "hello", "advice" => advice, "ext" => {"auth" => "password"}}]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
@@ -0,0 +1,151 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "server handshake" do
|
4
|
+
let(:engine) { mock "engine" }
|
5
|
+
let(:server) { Faye::Server.new }
|
6
|
+
|
7
|
+
before do
|
8
|
+
Faye::Engine.stub(:get).and_return engine
|
9
|
+
end
|
10
|
+
|
11
|
+
describe :handshake do
|
12
|
+
let(:message) {{"channel" => "/meta/handshake",
|
13
|
+
"version" => "1.0",
|
14
|
+
"supportedConnectionTypes" => ["long-polling"]
|
15
|
+
}}
|
16
|
+
|
17
|
+
describe "with valid parameters" do
|
18
|
+
it "creates a client" do
|
19
|
+
engine.should_receive(:create_client)
|
20
|
+
server.handshake(message) {}
|
21
|
+
end
|
22
|
+
|
23
|
+
it "returns a successful response" do
|
24
|
+
engine.stub(:create_client).and_yield "clientid"
|
25
|
+
server.handshake(message) do |response|
|
26
|
+
response.should == {
|
27
|
+
"channel" => "/meta/handshake",
|
28
|
+
"successful" => true,
|
29
|
+
"version" => "1.0",
|
30
|
+
"supportedConnectionTypes" => ["long-polling","cross-origin-long-polling","callback-polling","websocket"],
|
31
|
+
"clientId" => "clientid"
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "with a message id" do
|
37
|
+
before { message["id"] = "foo" }
|
38
|
+
|
39
|
+
it "returns the same id" do
|
40
|
+
engine.stub(:create_client).and_yield "clientid"
|
41
|
+
server.handshake(message) do |response|
|
42
|
+
response.should == {
|
43
|
+
"channel" => "/meta/handshake",
|
44
|
+
"successful" => true,
|
45
|
+
"version" => "1.0",
|
46
|
+
"supportedConnectionTypes" => ["long-polling","cross-origin-long-polling","callback-polling","websocket"],
|
47
|
+
"clientId" => "clientid",
|
48
|
+
"id" => "foo"
|
49
|
+
}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "missing version" do
|
56
|
+
before { message.delete "version" }
|
57
|
+
|
58
|
+
it "does not create a client" do
|
59
|
+
engine.should_not_receive(:create_client)
|
60
|
+
server.handshake(message) {}
|
61
|
+
end
|
62
|
+
|
63
|
+
it "returns an unsuccessful response" do
|
64
|
+
server.handshake(message) do |response|
|
65
|
+
response.should == {
|
66
|
+
"channel" => "/meta/handshake",
|
67
|
+
"successful" => false,
|
68
|
+
"error" => "402:version:Missing required parameter",
|
69
|
+
"version" => "1.0",
|
70
|
+
"supportedConnectionTypes" => ["long-polling","cross-origin-long-polling","callback-polling","websocket"]
|
71
|
+
}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "missing supportedConnectionTypes" do
|
77
|
+
before { message.delete "supportedConnectionTypes" }
|
78
|
+
|
79
|
+
it "does not create a client" do
|
80
|
+
engine.should_not_receive(:create_client)
|
81
|
+
server.handshake(message) {}
|
82
|
+
end
|
83
|
+
|
84
|
+
it "returns an unsuccessful response" do
|
85
|
+
server.handshake(message) do |response|
|
86
|
+
response.should == {
|
87
|
+
"channel" => "/meta/handshake",
|
88
|
+
"successful" => false,
|
89
|
+
"error" => "402:supportedConnectionTypes:Missing required parameter",
|
90
|
+
"version" => "1.0",
|
91
|
+
"supportedConnectionTypes" => ["long-polling","cross-origin-long-polling","callback-polling","websocket"]
|
92
|
+
}
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
it "returns a successful response for local clients" do
|
97
|
+
engine.stub(:create_client).and_yield "clientid"
|
98
|
+
server.handshake(message, true) do |response|
|
99
|
+
response.should == {
|
100
|
+
"channel" => "/meta/handshake",
|
101
|
+
"successful" => true,
|
102
|
+
"version" => "1.0",
|
103
|
+
"clientId" => "clientid"
|
104
|
+
}
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "with no matching supportedConnectionTypes" do
|
110
|
+
before { message["supportedConnectionTypes"] = ["iframe", "flash"] }
|
111
|
+
|
112
|
+
it "does not create a client" do
|
113
|
+
engine.should_not_receive(:create_client)
|
114
|
+
server.handshake(message) {}
|
115
|
+
end
|
116
|
+
|
117
|
+
it "returns an unsuccessful response" do
|
118
|
+
server.handshake(message) do |response|
|
119
|
+
response.should == {
|
120
|
+
"channel" => "/meta/handshake",
|
121
|
+
"successful" => false,
|
122
|
+
"error" => "301:iframe,flash:Connection types not supported",
|
123
|
+
"version" => "1.0",
|
124
|
+
"supportedConnectionTypes" => ["long-polling","cross-origin-long-polling","callback-polling","websocket"]
|
125
|
+
}
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "with an error" do
|
131
|
+
before { message["error"] = "invalid" }
|
132
|
+
|
133
|
+
it "does not createa a client" do
|
134
|
+
engine.should_not_receive(:create_client)
|
135
|
+
server.handshake(message) {}
|
136
|
+
end
|
137
|
+
|
138
|
+
it "returns an unsuccessful response" do
|
139
|
+
server.handshake(message) do |response|
|
140
|
+
response.should == {
|
141
|
+
"channel" => "/meta/handshake",
|
142
|
+
"successful" => false,
|
143
|
+
"error" => "invalid",
|
144
|
+
"version" => "1.0",
|
145
|
+
"supportedConnectionTypes" => ["long-polling","cross-origin-long-polling","callback-polling","websocket"]
|
146
|
+
}
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|