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.

Files changed (62) hide show
  1. data/History.txt +14 -0
  2. data/README.rdoc +98 -0
  3. data/Rakefile +17 -15
  4. data/lib/faye-browser-min.js +1 -1
  5. data/lib/faye.rb +14 -5
  6. data/lib/faye/adapters/rack_adapter.rb +12 -5
  7. data/lib/faye/engines/base.rb +62 -0
  8. data/lib/faye/engines/connection.rb +63 -0
  9. data/lib/faye/engines/memory.rb +89 -0
  10. data/lib/faye/engines/redis.rb +141 -0
  11. data/lib/faye/error.rb +16 -4
  12. data/lib/faye/mixins/publisher.rb +6 -0
  13. data/lib/faye/protocol/channel.rb +34 -86
  14. data/lib/faye/protocol/client.rb +36 -52
  15. data/lib/faye/protocol/extensible.rb +3 -0
  16. data/lib/faye/protocol/server.rb +119 -169
  17. data/lib/faye/transport/http.rb +45 -0
  18. data/lib/faye/transport/local.rb +15 -0
  19. data/lib/faye/{network → transport}/transport.rb +36 -49
  20. data/spec/browser.html +35 -0
  21. data/spec/install.sh +48 -0
  22. data/spec/javascript/channel_spec.js +15 -0
  23. data/spec/javascript/client_spec.js +610 -0
  24. data/spec/javascript/engine_spec.js +319 -0
  25. data/spec/javascript/faye_spec.js +15 -0
  26. data/spec/javascript/grammar_spec.js +66 -0
  27. data/spec/javascript/node_adapter_spec.js +276 -0
  28. data/spec/javascript/server/connect_spec.js +168 -0
  29. data/spec/javascript/server/disconnect_spec.js +121 -0
  30. data/spec/javascript/server/extensions_spec.js +60 -0
  31. data/spec/javascript/server/handshake_spec.js +153 -0
  32. data/spec/javascript/server/subscribe_spec.js +245 -0
  33. data/spec/javascript/server/unsubscribe_spec.js +245 -0
  34. data/spec/javascript/server_spec.js +146 -0
  35. data/spec/javascript/transport_spec.js +130 -0
  36. data/spec/node.js +34 -0
  37. data/spec/ruby/channel_spec.rb +17 -0
  38. data/spec/ruby/client_spec.rb +615 -0
  39. data/spec/ruby/engine_spec.rb +312 -0
  40. data/spec/ruby/faye_spec.rb +14 -0
  41. data/spec/ruby/grammar_spec.rb +68 -0
  42. data/spec/ruby/rack_adapter_spec.rb +209 -0
  43. data/spec/ruby/server/connect_spec.rb +170 -0
  44. data/spec/ruby/server/disconnect_spec.rb +120 -0
  45. data/spec/ruby/server/extensions_spec.rb +69 -0
  46. data/spec/ruby/server/handshake_spec.rb +151 -0
  47. data/spec/ruby/server/subscribe_spec.rb +247 -0
  48. data/spec/ruby/server/unsubscribe_spec.rb +247 -0
  49. data/spec/ruby/server_spec.rb +138 -0
  50. data/spec/ruby/transport_spec.rb +128 -0
  51. data/spec/spec_helper.rb +5 -0
  52. data/spec/testswarm.pl +200 -0
  53. data/spec/thin_proxy.rb +36 -0
  54. metadata +119 -84
  55. data/Manifest.txt +0 -27
  56. data/README.txt +0 -98
  57. data/lib/faye/protocol/connection.rb +0 -111
  58. data/test/scenario.rb +0 -172
  59. data/test/test_channel.rb +0 -54
  60. data/test/test_clients.rb +0 -381
  61. data/test/test_grammar.rb +0 -86
  62. data/test/test_server.rb +0 -488
@@ -1,111 +0,0 @@
1
- module Faye
2
- class Connection
3
- include EventMachine::Deferrable
4
- include Publisher
5
- include Timeouts
6
-
7
- MAX_DELAY = 0.001
8
- INTERVAL = 0.0
9
- TIMEOUT = 60.0
10
-
11
- attr_reader :id, :interval, :timeout
12
-
13
- def initialize(id, options = {})
14
- @id = id
15
- @options = options
16
- @interval = @options[:interval] || INTERVAL
17
- @timeout = @options[:timeout] || TIMEOUT
18
- @channels = Set.new
19
- @inbox = Set.new
20
- @connected = false
21
-
22
- begin_deletion_timeout
23
- end
24
-
25
- def socket=(socket)
26
- @connected = true
27
- @socket = socket
28
- end
29
-
30
- def on_message(event)
31
- return unless @inbox.add?(event)
32
- @socket.send(JSON.unparse(event)) if @socket
33
- begin_delivery_timeout
34
- end
35
-
36
- def subscribe(channel)
37
- return unless @channels.add?(channel)
38
- channel.add_subscriber(:message, method(:on_message))
39
- end
40
-
41
- def unsubscribe(channel)
42
- return @channels.each(&method(:unsubscribe)) if channel == :all
43
- return unless @channels.member?(channel)
44
- @channels.delete(channel)
45
- channel.remove_subscriber(:message, method(:on_message))
46
- end
47
-
48
- def connect(options, &block)
49
- options = options || {}
50
- timeout = options['timeout'] ? options['timeout'] / 1000.0 : @timeout
51
-
52
- set_deferred_status(:deferred)
53
-
54
- callback(&block)
55
- return if @connected
56
-
57
- @connected = true
58
- remove_timeout(:deletion)
59
-
60
- begin_delivery_timeout
61
- begin_connection_timeout(timeout)
62
- end
63
-
64
- def flush!
65
- return unless @connected
66
- release_connection!
67
-
68
- events = @inbox.entries
69
- @inbox = Set.new
70
-
71
- set_deferred_status(:succeeded, events)
72
- set_deferred_status(:deferred)
73
- end
74
-
75
- def disconnect!
76
- unsubscribe(:all)
77
- flush!
78
- end
79
-
80
- private
81
-
82
- def release_connection!
83
- return if @socket
84
-
85
- remove_timeout(:connection)
86
- remove_timeout(:delivery)
87
- @connected = false
88
-
89
- begin_deletion_timeout
90
- end
91
-
92
- def begin_delivery_timeout
93
- return unless @connected and not @inbox.empty?
94
- add_timeout(:delivery, MAX_DELAY) { flush! }
95
- end
96
-
97
- def begin_connection_timeout(timeout)
98
- return unless @connected
99
- add_timeout(:connection, timeout) { flush! }
100
- end
101
-
102
- def begin_deletion_timeout
103
- return if @connected
104
- add_timeout(:deletion, TIMEOUT + 10 * @timeout) do
105
- publish_event(:stale_connection, self)
106
- end
107
- end
108
-
109
- end
110
- end
111
-
data/test/scenario.rb DELETED
@@ -1,172 +0,0 @@
1
- $VERBOSE = false
2
-
3
- module Scenario
4
- module ClassMethods
5
- def scenario(name, &block)
6
- define_method("test: #{name}", &block)
7
- end
8
- end
9
-
10
- def self.included(klass)
11
- klass.extend ClassMethods
12
- end
13
-
14
- def setup
15
- Thread.new { EM.run }
16
- while not EM.reactor_running?; end
17
- @scenario = AsyncScenario.new
18
- @commands = []
19
- @started = false
20
- end
21
-
22
- def teardown
23
- while EM.reactor_running?; end
24
- end
25
-
26
- def run(runner)
27
- @runner = runner
28
- super
29
- end
30
-
31
- def method_missing(sym, *args)
32
- @commands << [sym, args]
33
- EM.next_tick { run_next_command unless @started }
34
- end
35
-
36
- def run_next_command
37
- @started = true
38
- command = @commands.shift
39
- return finish if command.nil?
40
- begin
41
- @scenario.__send__(command.first, *command.last) do
42
- run_next_command
43
- end
44
- rescue Object => e
45
- @passed = false
46
- add_failure(e.message, e.backtrace)
47
- @runner.puke(self.class, self.name, e) if @runner.respond_to?(:puke)
48
- block.call
49
- end
50
- end
51
-
52
- def finish
53
- @scenario.finish { EM.stop }
54
- end
55
-
56
- class AsyncScenario
57
- include Test::Unit::Assertions
58
-
59
- def initialize
60
- @clients = {}
61
- @inbox = {}
62
- @errors = {}
63
- @pool = 0
64
- end
65
-
66
- def wait(time, &block)
67
- EM.add_timer(time, &block)
68
- end
69
-
70
- def server(port, &block)
71
- @endpoint = "http://0.0.0.0:#{port}/bayeux"
72
- @bayeux = Faye::RackAdapter.new(:mount => '/bayeux', :timeout => 30)
73
- Rack::Handler.get('thin').run(@bayeux, :Port => port) do |server|
74
- @server = server
75
- EM.next_tick(&block)
76
- end
77
- end
78
-
79
- def http_client(name, channels = nil, &block)
80
- setup_client(Faye::Client.new(@endpoint), name, channels, &block)
81
- end
82
-
83
- def local_client(name, channels = nil, &block)
84
- setup_client(@bayeux.get_client, name, channels, &block)
85
- end
86
-
87
- def extend_server(stage, extension, &block)
88
- object = Object.new
89
- def object.added
90
- @active = true
91
- end
92
- (class << object; self; end).send(:define_method, stage) do |*args|
93
- extension.call(*args) if @active
94
- end
95
- @bayeux.add_extension(object)
96
- block.call
97
- end
98
-
99
- def extend_client(name, stage, extension, &block)
100
- object = Object.new
101
- (class << object; self; end).send(:define_method, stage, &extension)
102
- @clients[name].add_extension(object)
103
- block.call
104
- end
105
-
106
- def listen_for_errors(name, &block)
107
- @errors[name] = []
108
- errors = @errors
109
-
110
- extend_client(name, :incoming, lambda { |message, callback|
111
- if message['successful'] == false
112
- errors[name] << message['error']
113
- end
114
- callback.call(message)
115
- }, &block)
116
- end
117
-
118
- def setup_client(client, name, channels, &block)
119
- @clients[name] = client
120
- @inbox[name] = {}
121
- @pool += 1
122
-
123
- return block.call if channels.nil?
124
-
125
- channels.each { |channel| subscribe(name, channel) }
126
- EM.add_timer(0.5 * channels.size, &block)
127
- end
128
-
129
- def subscribe(name, channel, &block)
130
- client = @clients[name]
131
-
132
- @last_sub = client.subscribe(channel) do |message|
133
- box = @inbox[name]
134
- box[channel] ||= []
135
- box[channel] << message
136
- end
137
-
138
- @last_sub.callback(&block)
139
- end
140
-
141
- def cancel_last_subscription(&block)
142
- @last_sub.cancel
143
- EM.add_timer(0.5, &block)
144
- end
145
-
146
- def publish(from, channel, messages, &block)
147
- messages = [messages].flatten
148
- messages.each { |msg| @clients[from].publish(channel, msg) }
149
- EM.add_timer(2, &block)
150
- end
151
-
152
- def check_inbox(expected_inbox, &block)
153
- assert_equal expected_inbox, @inbox
154
- EM.next_tick(&block)
155
- end
156
-
157
- def check_errors(name, expected_errors, &block)
158
- assert_equal expected_errors, @errors[name]
159
- EM.next_tick(&block)
160
- end
161
-
162
- def finish(&block)
163
- @clients.each { |id,c| c.disconnect }
164
- EM.add_timer(1) do
165
- @server.stop!
166
- block.call
167
- end
168
- end
169
- end
170
-
171
- end
172
-
data/test/test_channel.rb DELETED
@@ -1,54 +0,0 @@
1
- require "test/unit"
2
- require File.dirname(__FILE__) + "/../lib/faye"
3
-
4
- class TestChannel < Test::Unit::TestCase
5
- include Faye
6
-
7
- def test_channel_storage
8
- tree = Channel::Tree.new
9
- tree['invalid/name'] = 1
10
- tree['/valid/name'] = 2
11
- tree['/va()$$lid/name'] = 3
12
-
13
- assert_equal nil, tree['invalid/name']
14
- assert_equal 2, tree['/valid/name']
15
- assert_equal 3, tree['/va()$$lid/name']
16
- end
17
-
18
- def test_keys
19
- tree = Channel::Tree.new
20
- tree['/foo'] = tree['/bar'] = tree['/foo/bar'] = true
21
- assert_equal %w[/bar /foo /foo/bar], tree.keys.sort
22
- end
23
-
24
- def test_removal
25
- tree = Channel::Tree.new
26
- tree['/foo'] = tree['/bar'] = tree['/foo/bar'] = true
27
-
28
- tree.remove('/foo/bar')
29
- assert_equal %w[/bar /foo], tree.keys.sort
30
- end
31
-
32
- def test_globbing
33
- tree = Channel::Tree.new
34
- tree['/foo/bar'] = 1
35
- tree['/foo/boo'] = 2
36
- tree['/foo'] = 3
37
- tree['/foobar'] = 4
38
- tree['/foo/bar/boo'] = 5
39
- tree['/foobar/boo'] = 6
40
- tree['/foo/*'] = 7
41
- tree['/foo/**'] = 8
42
-
43
- assert_equal [1,2,7,8], tree.glob('/foo/*').sort
44
- assert_equal [1,7,8], tree.glob('/foo/bar').sort
45
- assert_equal [1,2,5,7,8], tree.glob('/foo/**').sort
46
- assert_equal [5,8], tree.glob('/foo/bar/boo').sort
47
-
48
- tree['/channels/hello'] = 'A'
49
- tree['/channels/name'] = 'B'
50
- tree['/channels/nested/hello'] = 'C'
51
-
52
- assert_equal %w[A B C], tree.glob('/channels/**').sort
53
- end
54
- end
data/test/test_clients.rb DELETED
@@ -1,381 +0,0 @@
1
- require "test/unit"
2
- require File.dirname(__FILE__) + "/../lib/faye"
3
- require "test/scenario"
4
-
5
- class TestClients < Test::Unit::TestCase
6
- include Faye
7
- include Scenario
8
-
9
- scenario "Client modifies incoming messages" do
10
- server 8000
11
- http_client :A, ['/channels/a']
12
- http_client :B, ['/channels/b']
13
-
14
- extend_client :A, :incoming, lambda { |message, callback|
15
- if message['data']
16
- message['data']['modified'] = 'hi'
17
- end
18
- callback.call(message)
19
- }
20
-
21
- publish :B, '/channels/a', 'welcome' => 'message'
22
- check_inbox(
23
- :A => {
24
- '/channels/a' => ['welcome' => 'message', 'modified' => 'hi']
25
- },
26
- :B => {}
27
- )
28
- end
29
-
30
- scenario "Client blocks incoming messages" do
31
- server 8000
32
- http_client :A, ['/channels/a']
33
- http_client :B, ['/channels/b']
34
-
35
- extend_client :A, :incoming, lambda { |message, callback|
36
- callback.call(nil)
37
- }
38
-
39
- publish :B, '/channels/a', 'welcome' => 'message'
40
- check_inbox( :A => {}, :B => {} )
41
- end
42
-
43
- scenario "Server requires authentication" do
44
- server 8000
45
- http_client :A, ['/channels/a']
46
- http_client :B, ['/channels/b']
47
-
48
- extend_server :incoming, lambda { |message, callback|
49
- if message['ext'] and message['ext']['password']
50
- callback.call(message)
51
- end
52
- }
53
-
54
- extend_client :B, :outgoing, lambda { |message, callback|
55
- message['ext'] = {'password' => true}
56
- callback.call(message)
57
- }
58
-
59
- publish :A, '/channels/b', 'message_for' => 'B'
60
- check_inbox( :A => {}, :B => {} )
61
-
62
- publish :B, '/channels/a', 'message_for' => 'A'
63
- check_inbox(
64
- :A => {
65
- '/channels/a' => ['message_for' => 'A']
66
- },
67
- :B => {}
68
- )
69
- end
70
-
71
- scenario "Server blocks a message by setting an error" do
72
- server 8000
73
- http_client :A, ['/channels/a']
74
- http_client :B, ['/channels/b']
75
-
76
- extend_server :incoming, lambda { |message, callback|
77
- if message['data']
78
- message['error'] = Faye::Error.ext_mismatch
79
- end
80
- callback.call(message)
81
- }
82
-
83
- listen_for_errors :A
84
-
85
- publish :A, '/channels/b', 'message_for' => 'B'
86
- check_inbox( :A => {}, :B => {} )
87
- check_errors :A, ['302::Extension mismatch']
88
- end
89
-
90
- scenario "Server modifies outgoing message" do
91
- server 8000
92
- http_client :A, []
93
- http_client :B, ['/channels/b']
94
-
95
- extend_server :outgoing, lambda { |message, callback|
96
- message['data']['addition'] = 56 if message['data']
97
- callback.call(message)
98
- }
99
-
100
- publish :A, '/channels/b', 'message_for' => 'B'
101
- check_inbox(
102
- :A => {},
103
- :B => {
104
- '/channels/b' => ['message_for' => 'B', 'addition' => 56]
105
- }
106
- )
107
- end
108
-
109
- [:incoming, :outgoing].each do |direction|
110
- scenario "Server delays #{ direction } message" do
111
- server 8000
112
- http_client :A, []
113
- http_client :B, ['/channels/b']
114
-
115
- extend_server direction, lambda { |message, callback|
116
- timeout = message['data'] ? 5 : 0
117
- EM.add_timer(timeout) { callback.call(message) }
118
- }
119
-
120
- publish :A, '/channels/b', 'message_for' => 'B'
121
- check_inbox( :A => {}, :B => {} )
122
-
123
- wait 3
124
- check_inbox( :A => {}, :B => {} )
125
-
126
- wait 1
127
-
128
- check_inbox(
129
- :A => {},
130
- :B => {
131
- '/channels/b' => ['message_for' => 'B']
132
- }
133
- )
134
- end
135
- end
136
-
137
- scenario "Server blocks outgoing message" do
138
- server 8000
139
- http_client :A, []
140
- http_client :B, ['/channels/b']
141
-
142
- extend_server :outgoing, lambda { |message, callback|
143
- if !message['data'] or message['data']['deliver'] == 'yes'
144
- callback.call(message)
145
- else
146
- callback.call(nil)
147
- end
148
- }
149
-
150
- publish :A, '/channels/b', [{'deliver' => 'no'}, {'deliver' => 'yes'}]
151
-
152
- check_inbox(
153
- :A => {},
154
- :B => {
155
- '/channels/b' => ['deliver' => 'yes']
156
- }
157
- )
158
- end
159
-
160
- scenario "Two HTTP clients, no messages delivered" do
161
- server 8000
162
- http_client :A, ['/channels/a']
163
- http_client :B, []
164
- publish :B, '/channels/b', 'hello' => 'world'
165
- check_inbox(
166
- :A => {},
167
- :B => {}
168
- )
169
- end
170
-
171
- scenario "Two HTTP clients, single subscription" do
172
- server 8000
173
- http_client :A, ['/channels/a']
174
- http_client :B, []
175
- publish :B, '/channels/a', 'hello' => 'world'
176
- check_inbox(
177
- :A => {
178
- '/channels/a' => ['hello' => 'world']
179
- },
180
- :B => {}
181
- )
182
- end
183
-
184
- scenario "Two HTTP clients, two identical messages sent together" do
185
- server 8000
186
- http_client :A, ['/channels/a']
187
- http_client :B, []
188
- publish :B, '/channels/a', [{'hello' => 'world'}, {'hello' => 'world'}]
189
- check_inbox(
190
- :A => {
191
- '/channels/a' => [{'hello' => 'world'}, {'hello' => 'world'}]
192
- },
193
- :B => {}
194
- )
195
- end
196
-
197
- scenario "Two HTTP clients, two message deliveries" do
198
- server 8000
199
- http_client :A, ['/channels/a']
200
- http_client :B, []
201
- publish :B, '/channels/a', 'hello' => 'world'
202
- check_inbox(
203
- :A => {
204
- '/channels/a' => ['hello' => 'world']
205
- },
206
- :B => {}
207
- )
208
- wait 1
209
- publish :B, '/channels/a', 'hello' => 'world'
210
- check_inbox(
211
- :A => {
212
- '/channels/a' => [{'hello' => 'world'}, {'hello' => 'world'}]
213
- },
214
- :B => {}
215
- )
216
- end
217
-
218
- scenario "Two HTTP clients, multiple subscriptions" do
219
- server 8000
220
- http_client :A, ['/channels/a', '/channels/*']
221
- http_client :B, []
222
- publish :B, '/channels/a', 'hello' => 'world'
223
- check_inbox(
224
- :A => {
225
- '/channels/a' => ['hello' => 'world'],
226
- '/channels/*' => ['hello' => 'world']
227
- },
228
- :B => {}
229
- )
230
- end
231
-
232
- scenario "One HTTP client, one local with no subscriptions" do
233
- server 8000
234
- http_client :A, ['/channels/a']
235
- local_client :B
236
- publish :B, '/channels/a', 'hello' => 'world'
237
-
238
- check_inbox(
239
- :A => {
240
- '/channels/a' => ['hello' => 'world']
241
- },
242
- :B => {}
243
- )
244
- end
245
-
246
- scenario "Two HTTP clients, two subscriptions on the same channel" do
247
- server 8000
248
- http_client :A, ['/channels/a']
249
- http_client :B, []
250
- subscribe :A, '/channels/a'
251
- publish :B, '/channels/a', 'hello' => 'world'
252
- check_inbox(
253
- :A => {
254
- '/channels/a' => [{'hello' => 'world'}, {'hello' => 'world'}]
255
- },
256
- :B => {}
257
- )
258
- end
259
-
260
- scenario "Two HTTP clients, two subscriptions and one unsubscription" do
261
- server 8000
262
- http_client :A, ['/channels/a']
263
- http_client :B, []
264
- subscribe :A, '/channels/a'
265
- cancel_last_subscription
266
- publish :B, '/channels/a', 'another' => 'message'
267
- check_inbox(
268
- :A => {
269
- '/channels/a' => [{'another' => 'message'}]
270
- },
271
- :B => {}
272
- )
273
- end
274
-
275
- scenario "Three HTTP clients, single receiver" do
276
- server 8000
277
- http_client :A, ['/channels/a']
278
- http_client :B, []
279
- http_client :C, ['/channels/c']
280
- publish :B, '/channels/a', 'chunky' => 'bacon'
281
- check_inbox(
282
- :A => {
283
- '/channels/a' => ['chunky' => 'bacon']
284
- },
285
- :B => {},
286
- :C => {}
287
- )
288
- end
289
-
290
- scenario "Three HTTP clients, multiple receivers" do
291
- server 8000
292
- http_client :A, ['/channels/shared']
293
- http_client :B, []
294
- http_client :C, ['/channels/shared']
295
- publish :B, '/channels/shared', 'chunky' => 'bacon'
296
- check_inbox(
297
- :A => {
298
- '/channels/shared' => ['chunky' => 'bacon']
299
- },
300
- :B => {},
301
- :C => {
302
- '/channels/shared' => ['chunky' => 'bacon']
303
- }
304
- )
305
- end
306
-
307
- scenario "Two HTTP clients, single wildcard on receiver" do
308
- server 8000
309
- http_client :A, ['/channels/*']
310
- http_client :B, []
311
- publish :B, '/channels/anything', 'msg' => 'hey'
312
- check_inbox(
313
- :A => {
314
- '/channels/*' => ['msg' => 'hey']
315
- },
316
- :B => {}
317
- )
318
- end
319
-
320
- scenario "Two HTTP clients, single wildcard on sender" do
321
- server 8000
322
- http_client :A, ['/channels/name', '/channels/hello', '/channels/nested/hello']
323
- http_client :B, []
324
- publish :B, '/channels/*', 'msg' => 'hey'
325
- check_inbox(
326
- :A => {
327
- '/channels/name' => ['msg' => 'hey'],
328
- '/channels/hello' => ['msg' => 'hey']
329
- },
330
- :B => {}
331
- )
332
- end
333
-
334
- scenario "Two HTTP clients, single wildcard on both" do
335
- server 8000
336
- http_client :A, ['/channels/*']
337
- http_client :B, []
338
- publish :B, '/channels/*', 'msg' => 'hey'
339
- check_inbox(
340
- :A => {
341
- '/channels/*' => ['msg' => 'hey']
342
- },
343
- :B => {}
344
- )
345
- end
346
-
347
- scenario "Two local clients, double wildcard on sender" do
348
- server 8000
349
- local_client :A, ['/channels/name', '/channels/hello', '/channels/nested/hello']
350
- local_client :B, []
351
- publish :B, '/channels/**', 'msg' => 'hey'
352
- check_inbox(
353
- :A => {
354
- '/channels/name' => ['msg' => 'hey'],
355
- '/channels/hello' => ['msg' => 'hey'],
356
- '/channels/nested/hello' => ['msg' => 'hey']
357
- },
358
- :B => {}
359
- )
360
- end
361
-
362
- scenario "Two local clients, one HTTP, double wildcard on sender and one subscription" do
363
- server 8000
364
- local_client :A, ['/channels/hello', '/channels/nested/hello']
365
- local_client :B, []
366
- http_client :C, ['/channels/name', '/channels/foo/**']
367
- publish :B, '/channels/**', 'msg' => 'hey'
368
- check_inbox(
369
- :A => {
370
- '/channels/hello' => ['msg' => 'hey'],
371
- '/channels/nested/hello' => ['msg' => 'hey']
372
- },
373
- :B => {},
374
- :C => {
375
- '/channels/name' => ['msg' => 'hey'],
376
- '/channels/foo/**' => ['msg' => 'hey']
377
- }
378
- )
379
- end
380
- end
381
-