ably 1.1.1 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 26f56201f9faae28b9b74ef9223e8d50c049a25d065f80d8612ce0013da46783
4
- data.tar.gz: f74af9b0f0178576e41094fccf80821983da0b896e6bd7667fe534abe0d096bb
3
+ metadata.gz: 372821f0df3a03b36e29d0c2ce4141e08b7467c794aa28c542e38b10d658a0f5
4
+ data.tar.gz: 7015ce6030cf75b97474cab9dfb809d671d4178efd34aff777514502a3a74d83
5
5
  SHA512:
6
- metadata.gz: 2a4c6c4006a176c01eacd9f38d9f11a61fb7f64880a764a663eca26e2ed2b7806203f972edf7cb5f0dec1034e6776d6b6dac459766ba920cc09ea156022640a9
7
- data.tar.gz: 59d33ebc03521cf47449140715b5506dca17ac6b3708b914b6b0987d038c56667231086c8ff81c8d740d8a62c4474ac78c9839360b795e2d5c8f779ad972e3a5
6
+ metadata.gz: d92e931347421a955f3a318fca505cbb9f2271417a804a4e5a2e310c155abf4f42d2d89beca434e372a4b5777d931d278019a10b77d4b151d4e154a8a06d8064
7
+ data.tar.gz: 7e1d96e9b49558bdd010fa63e155ca291921e910212cb38ec00eafe7a6e7b58038150a1e24308d109ac59814bc5f181d2d653734c12c901ce11d7757410a4b28
@@ -1,7 +1,7 @@
1
1
  sudo: false
2
2
  env:
3
- - RSPEC_RETRY=true PARALLEL_TEST_PROCESSORS=4 PROTOCOL=json
4
- - RSPEC_RETRY=true PARALLEL_TEST_PROCESSORS=4 PROTOCOL=msgpack
3
+ - RSPEC_RETRY=true PARALLEL_TEST_PROCESSORS=2 PROTOCOL=json
4
+ - RSPEC_RETRY=true PARALLEL_TEST_PROCESSORS=2 PROTOCOL=msgpack
5
5
  language: ruby
6
6
  rvm:
7
7
  - 1.9.3
@@ -1,7 +1,14 @@
1
1
  # Change Log
2
2
 
3
- ## [v1.1.1](https://github.com/ably/ably-ruby/tree/v1.1.1)
3
+ ## [v1.1.2](https://github.com/ably/ably-ruby/tree/v1.1.2)
4
4
 
5
+ [Full Changelog](https://github.com/ably/ably-ruby/compare/v1.1.1...v1.1.2)
6
+
7
+ **Merged pull requests:**
8
+
9
+ - Remove legacy skipped tests and upgrade MsgPack [\#184](https://github.com/ably/ably-ruby/pull/184) ([mattheworiordan](https://github.com/mattheworiordan))
10
+
11
+ ## [v1.1.1](https://github.com/ably/ably-ruby/tree/v1.1.1) (2019-05-06)
5
12
  [Full Changelog](https://github.com/ably/ably-ruby/compare/v1.1.0...v1.1.1)
6
13
 
7
14
  **Implemented enhancements:**
@@ -67,7 +74,6 @@
67
74
  **Closed issues:**
68
75
 
69
76
  - Passing a frozen channel name or name gives an error on the REST client \[Reopen\] [\#145](https://github.com/ably/ably-ruby/issues/145)
70
- - Passing a frozen channel name or name gives an error on the REST client [\#132](https://github.com/ably/ably-ruby/issues/132)
71
77
 
72
78
  **Merged pull requests:**
73
79
 
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
30
30
  spec.add_runtime_dependency 'json'
31
31
  end
32
32
  spec.add_runtime_dependency 'websocket-driver', '~> 0.7'
33
- spec.add_runtime_dependency 'msgpack', '>= 0.6.2'
33
+ spec.add_runtime_dependency 'msgpack', '>= 1.3.0'
34
34
  spec.add_runtime_dependency 'addressable', '>= 2.0.0'
35
35
 
36
36
  spec.add_development_dependency 'rake', '~> 11.3'
@@ -20,6 +20,8 @@ module Ably
20
20
  ensure_logger_interface_is_valid
21
21
 
22
22
  @logger.level = log_level
23
+
24
+ @log_mutex = Mutex.new
23
25
  end
24
26
 
25
27
  # The logger used by this class, defaults to {http://www.ruby-doc.org/stdlib-1.9.3/libdoc/logger/rdoc/Logger.html Ruby Logger}
@@ -38,7 +40,9 @@ module Ably
38
40
  %w(fatal error warn info debug).each do |method_name|
39
41
  define_method(method_name) do |*args, &block|
40
42
  begin
41
- logger.public_send(method_name, *args, &block)
43
+ log_mutex.synchronize do
44
+ logger.public_send(method_name, *args, &block)
45
+ end
42
46
  rescue StandardError => e
43
47
  logger.error "Logger: Failed to log #{method_name} block - #{e.class}: #{e.message}\n#{e.backtrace.join("\n")}"
44
48
  end
@@ -46,6 +50,8 @@ module Ably
46
50
  end
47
51
 
48
52
  private
53
+ attr_reader :log_mutex
54
+
49
55
  def client
50
56
  @client
51
57
  end
@@ -23,7 +23,7 @@ module Ably::Modules
23
23
  def transition_state(state, *args)
24
24
  unless result = transition_to(state.to_sym, *args)
25
25
  exception = exception_for_state_change_to(state)
26
- logger.fatal { "#{self.class}: #{exception.message}" }
26
+ logger.fatal { "#{self.class}: #{exception.message}\n#{caller[0..20].join("\n")}" }
27
27
  end
28
28
  result
29
29
  end
@@ -161,6 +161,8 @@ module Ably
161
161
  @state_machine = ConnectionStateMachine.new(self)
162
162
  @state = STATE(state_machine.current_state)
163
163
  @manager = ConnectionManager.new(self)
164
+
165
+ @current_host = client.endpoint.host
164
166
  end
165
167
 
166
168
  # Causes the connection to close, entering the closed state, from any state except
@@ -49,18 +49,31 @@ module Ably::Realtime
49
49
 
50
50
  logger.debug { 'ConnectionManager: Opening a websocket transport connection' }
51
51
 
52
+ # The socket attempt can fail at the same time as a timer firing so ensure
53
+ # only one outcome is processed from this setup attempt
54
+ setup_attempt_status = {}
55
+ setup_failed = lambda do
56
+ return true if setup_attempt_status[:failed]
57
+ setup_attempt_status[:failed] = true
58
+ false
59
+ end
60
+
52
61
  connection.create_websocket_transport.tap do |socket_deferrable|
53
62
  socket_deferrable.callback do |websocket_transport|
54
63
  subscribe_to_transport_events websocket_transport
55
64
  yield websocket_transport if block_given?
56
65
  end
57
66
  socket_deferrable.errback do |error|
67
+ next if setup_failed.call
58
68
  connection_opening_failed error
59
69
  end
60
70
  end
61
71
 
72
+ # The connection request timeout must be marginally higher than the REST request timeout to ensure
73
+ # any HTTP auth request failure due to timeout triggers before the connection timer kicks in
62
74
  logger.debug { "ConnectionManager: Setting up automatic connection timeout timer for #{realtime_request_timeout}s" }
63
75
  create_timeout_timer_whilst_in_state(:connecting, realtime_request_timeout) do
76
+ next if setup_failed.call
64
77
  connection_opening_failed Ably::Exceptions::ConnectionTimeout.new("Connection to Ably timed out after #{realtime_request_timeout}s", nil, Ably::Exceptions::Codes::CONNECTION_TIMED_OUT)
65
78
  end
66
79
  end
@@ -80,7 +93,12 @@ module Ably::Realtime
80
93
 
81
94
  logger.warn { "ConnectionManager: Connection to #{connection.current_host}:#{connection.port} failed; #{error.message}" }
82
95
  next_state = get_next_retry_state_info
83
- connection.transition_state_machine next_state.fetch(:state), retry_in: next_state.fetch(:pause), reason: Ably::Exceptions::ConnectionError.new("Connection failed: #{error.message}", nil, Ably::Exceptions::Codes::CONNECTION_FAILED, error)
96
+
97
+ if connection.state == next_state.fetch(:state)
98
+ logger.error { "ConnectionManager: Skipping next retry state after connection opening failed as already in state #{next_state}\n#{caller[0..20].join("\n")}" }
99
+ else
100
+ connection.transition_state_machine next_state.fetch(:state), retry_in: next_state.fetch(:pause), reason: Ably::Exceptions::ConnectionError.new("Connection failed: #{error.message}", nil, Ably::Exceptions::Codes::CONNECTION_FAILED, error)
101
+ end
84
102
  end
85
103
 
86
104
  # Called whenever a new connection is made
@@ -471,11 +471,13 @@ module Ably
471
471
 
472
472
  # Allowable duration for an external auth request
473
473
  # For REST client this defaults to request_timeout
474
- # For Realtime clients this defaults to realtime_request_timeout
474
+ # For Realtime clients this defaults to 250ms less than the realtime_request_timeout
475
+ # ensuring an auth failure will be triggered before the realtime request timeout fires
476
+ # which would lead to a misleading error message (connection timeout as opposed to auth request timeout)
475
477
  # @api private
476
478
  def auth_request_timeout
477
479
  if @realtime_client
478
- @realtime_client.connection.defaults.fetch(:realtime_request_timeout)
480
+ @realtime_client.connection.defaults.fetch(:realtime_request_timeout) - 0.25
479
481
  else
480
482
  http_defaults.fetch(:request_timeout)
481
483
  end
@@ -1,5 +1,5 @@
1
1
  module Ably
2
- VERSION = '1.1.1'
2
+ VERSION = '1.1.2'
3
3
  PROTOCOL_VERSION = '1.1'
4
4
 
5
5
  # Allow a variant to be configured for all instances of this client library
@@ -1139,6 +1139,7 @@ describe Ably::Realtime::Auth, :event_machine do
1139
1139
  context 'when credentials are invalid' do
1140
1140
  let(:key_secret) { 'invalid' }
1141
1141
  let(:token) { Faraday.get("#{auth_url}?keyName=#{key_name}&keySecret=#{key_secret}").body }
1142
+ let(:client_options) { { token: token, environment: environment, protocol: protocol, log_level: :none } }
1142
1143
 
1143
1144
  it 'fails with an invalid signature error' do
1144
1145
  client.connection.once(:disconnected) do |state_change|
@@ -1239,7 +1240,7 @@ describe Ably::Realtime::Auth, :event_machine do
1239
1240
  Faraday.get("#{auth_url}?keyName=#{key_name}&keySecret=#{key_secret}&capability=#{URI.escape(basic_capability)}").body
1240
1241
  end
1241
1242
  end
1242
- let(:client_options) { default_options.merge(auth_callback: auth_callback) }
1243
+ let(:client_options) { default_options.merge(auth_callback: auth_callback, log_level: :error) }
1243
1244
 
1244
1245
  it 'client fails to publish to a channel with subscribe-only capability and publishes successfully on a channel with permissions' do
1245
1246
  client.connection.once(:connected) do
@@ -279,8 +279,7 @@ describe Ably::Realtime::Channel, :event_machine do
279
279
  key: restricted_api_key,
280
280
  log_level: :fatal,
281
281
  use_token_auth: true,
282
- # TODO: Use wildcard / default when intersection issue resolved, realtime#780
283
- default_token_params: { capability: { "canpublish:foo" => ["publish"] } }
282
+ default_token_params: { capability: { "canpublish:foo" => ["*"] } }
284
283
  )
285
284
  end
286
285
  let(:restricted_client) do
@@ -1009,9 +1008,6 @@ describe Ably::Realtime::Channel, :event_machine do
1009
1008
 
1010
1009
  it 'publishes the message without a name attribute in the payload' do
1011
1010
  published = false
1012
- channel.publish(nil, data) do
1013
- published = true
1014
- end
1015
1011
 
1016
1012
  channel.subscribe do |message|
1017
1013
  expect(message.name).to be_nil
@@ -1024,6 +1020,10 @@ describe Ably::Realtime::Channel, :event_machine do
1024
1020
  end
1025
1021
  end
1026
1022
  end
1023
+
1024
+ channel.publish(nil, data) do
1025
+ published = true
1026
+ end
1027
1027
  end
1028
1028
  end
1029
1029
 
@@ -1032,9 +1032,6 @@ describe Ably::Realtime::Channel, :event_machine do
1032
1032
 
1033
1033
  it 'publishes the message without a data attribute in the payload' do
1034
1034
  published = false
1035
- channel.publish(name, nil) do
1036
- published = true
1037
- end
1038
1035
 
1039
1036
  channel.subscribe do |message|
1040
1037
  expect(message.data).to be_nil
@@ -1047,6 +1044,10 @@ describe Ably::Realtime::Channel, :event_machine do
1047
1044
  end
1048
1045
  end
1049
1046
  end
1047
+
1048
+ channel.publish(name, nil) do
1049
+ published = true
1050
+ end
1050
1051
  end
1051
1052
  end
1052
1053
 
@@ -1997,6 +1998,8 @@ describe Ably::Realtime::Channel, :event_machine do
1997
1998
  end
1998
1999
 
1999
2000
  context '#resume (#RTL2f)' do
2001
+ let(:client_options) { default_options.merge(log_level: :fatal) }
2002
+
2000
2003
  it 'is false when a channel first attaches' do
2001
2004
  channel.attach
2002
2005
  channel.on(:attached) do |channel_state_change|
@@ -315,8 +315,9 @@ describe Ably::Realtime::Client, :event_machine do
315
315
  expect(msg.data).to eql(data)
316
316
  stop_reactor
317
317
  end
318
+
319
+ subject.publish channel_name, event_name, data
318
320
  end
319
- subject.publish channel_name, event_name, data
320
321
  end
321
322
 
322
323
  specify 'publishing does not result in a channel being created' do
@@ -341,8 +342,9 @@ describe Ably::Realtime::Client, :event_machine do
341
342
  expect(msg.extras).to eql(extras)
342
343
  stop_reactor
343
344
  end
345
+
346
+ subject.publish channel_name, event_name, {}, extras: extras
344
347
  end
345
- subject.publish channel_name, event_name, {}, extras: extras
346
348
  end
347
349
  end
348
350
 
@@ -353,8 +355,9 @@ describe Ably::Realtime::Client, :event_machine do
353
355
  expect(msg.data).to eql(data)
354
356
  stop_reactor
355
357
  end
358
+
359
+ subject.publish channel_name, [message]
356
360
  end
357
- subject.publish channel_name, [message]
358
361
  end
359
362
 
360
363
  specify 'publishing supports an array of Hash objects' do
@@ -364,8 +367,9 @@ describe Ably::Realtime::Client, :event_machine do
364
367
  expect(msg.data).to eql(data)
365
368
  stop_reactor
366
369
  end
370
+
371
+ subject.publish channel_name, [name: event_name, data: data]
367
372
  end
368
- subject.publish channel_name, [name: event_name, data: data]
369
373
  end
370
374
 
371
375
  specify 'publishing on a closed connection fails' do
@@ -45,7 +45,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
45
45
  connection.on(:failed) do |connection_state_change|
46
46
  error = connection_state_change.reason
47
47
  expect(connection.state).to eq(:failed)
48
- # TODO: Check error type is a TokenNotFOund exception
48
+ # TODO: Check error type is a TokenNotFound exception
49
49
  expect(error.status).to eq(401)
50
50
  expect(error.code).to eq(40400) # not found
51
51
  stop_reactor
@@ -110,6 +110,72 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
110
110
  end
111
111
  end
112
112
  end
113
+
114
+ context 'request fails due to slow response and subsequent timeout', :webmock, em_timeout: (Ably::Rest::Client::HTTP_DEFAULTS.fetch(:request_timeout) + 5) * 2 do
115
+ let(:auth_url) { "http://#{random_str}.domain.will.be.stubbed/path" }
116
+ let(:client_options) { default_options.reject { |k, v| k == :key }.merge(auth_url: auth_url, log_level: :fatal) }
117
+
118
+ # Timeout +5 seconds, beyond default allowed timeout
119
+ before do
120
+ stub_request(:get, auth_url).
121
+ to_return do |request|
122
+ sleep Ably::Rest::Client::HTTP_DEFAULTS.fetch(:request_timeout) + 5
123
+ { status: [500, "Internal Server Error"] }
124
+ end
125
+ end
126
+
127
+ specify 'the connection moves to the disconnected state and tries again, returning again to the disconnected state (#RSA4c, #RSA4c1, #RSA4c2)' do
128
+ states = Hash.new { |hash, key| hash[key] = [] }
129
+
130
+ connection.once(:connected) { raise "Connection can never move to connected because of auth failures" }
131
+
132
+ connection.on do |connection_state|
133
+ states[connection_state.current.to_sym] << Time.now
134
+ if states[:disconnected].count == 2 && connection_state.current == :disconnected
135
+ expect(connection.error_reason).to be_a(Ably::Exceptions::ConnectionError)
136
+ expect(connection.error_reason.message).to match(/auth_url/)
137
+ EventMachine.add_timer(2) do
138
+ expect(states.keys).to include(:connecting, :disconnected)
139
+ expect(states[:connecting].count).to eql(2)
140
+ expect(states[:connected].count).to eql(0)
141
+ stop_reactor
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+
148
+ context 'request fails once due to slow response but succeeds the second time' do
149
+ let(:auth_url) { "http://#{random_str}.domain.will.be.stubbed/path" }
150
+ let(:client_options) { default_options.reject { |k, v| k == :key }.merge(auth_url: auth_url, log_level: :fatal) }
151
+
152
+ # Timeout +5 seconds, beyond default allowed timeout
153
+ before do
154
+ token_response = Ably::Rest::Client.new(default_options).auth.request_token
155
+ WebMock.enable!
156
+
157
+ stub_request(:get, auth_url).
158
+ to_return do |request|
159
+ sleep Ably::Rest::Client::HTTP_DEFAULTS.fetch(:request_timeout)
160
+ { status: [500, "Internal Server Error"] }
161
+ end.then.
162
+ to_return(:status => 201, :body => token_response.to_json, :headers => { 'Content-Type' => 'application/json' })
163
+ end
164
+
165
+ specify 'the connection moves to the disconnected state and tries again, returning again to the disconnected state (#RSA4c, #RSA4c1, #RSA4c2)' do
166
+ states = Hash.new { |hash, key| hash[key] = [] }
167
+
168
+ connection.once(:connected) do
169
+ expect(states[:disconnected].count).to eql(1)
170
+ expect(states[:connecting].count).to eql(2)
171
+ stop_reactor
172
+ end
173
+
174
+ connection.on do |connection_state|
175
+ states[connection_state.current.to_sym] << Time.now
176
+ end
177
+ end
178
+ end
113
179
  end
114
180
 
115
181
  context 'existing CONNECTED connection' do
@@ -425,7 +491,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
425
491
  let(:client_options) do
426
492
  default_options.merge(
427
493
  log_level: :none,
428
- realtime_request_timeout: timeout
494
+ realtime_request_timeout: timeout,
429
495
  )
430
496
  end
431
497
 
@@ -27,6 +27,13 @@ describe Ably::Realtime::Connection, :event_machine do
27
27
  end
28
28
  end
29
29
 
30
+ context 'current_host' do
31
+ it 'is available immediately after the client is instanced' do
32
+ expect(connection.current_host.to_s).to match(/\.ably\.io$/)
33
+ stop_reactor
34
+ end
35
+ end
36
+
30
37
  context 'with :auto_connect option set to false' do
31
38
  let(:client) do
32
39
  auto_close Ably::Realtime::Client.new(default_options.merge(auto_connect: false))
@@ -1307,12 +1314,14 @@ describe Ably::Realtime::Connection, :event_machine do
1307
1314
  expect(connection.send(:client_msg_serial)).to eql(-1) # no messages published yet
1308
1315
  connection_id = client.connection.id
1309
1316
  connection.transport.__incoming_protocol_msgbus__
1310
- channel.publish('event', 'message-1') do
1317
+ channel.subscribe('event') do |message|
1318
+ expect(message.data).to eql('message-1')
1311
1319
  msg_serial = connection.send(:client_msg_serial)
1312
1320
  expect(msg_serial).to eql(0)
1313
1321
  recovery_key = client.connection.recovery_key
1314
1322
  connection.transition_state_machine! :failed
1315
1323
  end
1324
+ channel.publish('event', 'message-1')
1316
1325
  end
1317
1326
 
1318
1327
  connection.on(:failed) do
@@ -1329,7 +1338,7 @@ describe Ably::Realtime::Connection, :event_machine do
1329
1338
  expect(recover_client.connection.id).to eql(connection_id)
1330
1339
 
1331
1340
  recover_client_channel.subscribe do |message|
1332
- raise "Unexpected message #{message}" if message.data != 'message-2'
1341
+ expect(message.data).to eql('message-2')
1333
1342
  EventMachine.add_timer(2) do
1334
1343
  stop_reactor
1335
1344
  end
@@ -96,8 +96,7 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
96
96
  end
97
97
 
98
98
  context 'JSON Array' do
99
- # TODO: Add nil type back in
100
- let(:data) { { 'push' => { 'data' => { 'key' => [ true, false, 55, 'string', { 'Hash' => true }, ['array'] ] } } } }
99
+ let(:data) { { 'push' => { 'data' => { 'key' => [ true, false, 55, nil, 'string', { 'Hash' => true }, ['array'] ] } } } }
101
100
 
102
101
  it 'is encoded and decoded to the same Array' do
103
102
  publish_and_check_extras data
@@ -658,8 +657,7 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
658
657
  expect(message_state).to be_empty
659
658
  EventMachine.add_timer(2) do
660
659
  expect(message_state).to contain_exactly(:delivered)
661
- # TODO: Uncomment once issue realtime#42 is resolved
662
- # expect(msgs_received.length).to eql(1)
660
+ expect(msgs_received.length).to eql(1)
663
661
  stop_reactor
664
662
  end
665
663
  end
@@ -217,6 +217,12 @@ describe Ably::Realtime::Push::Admin, :event_machine do
217
217
  let(:client_id) { random_str }
218
218
  let(:fixture_count) { 6 }
219
219
 
220
+ before(:all) do
221
+ # As push tests often use the global scope (devices),
222
+ # we need to ensure tests cannot conflict
223
+ reload_test_app
224
+ end
225
+
220
226
  before do
221
227
  fixture_count.times.map do |index|
222
228
  Thread.new do # Parallelise the setup
@@ -274,6 +280,12 @@ describe Ably::Realtime::Push::Admin, :event_machine do
274
280
  let(:fixture_count) { 2 }
275
281
  let(:client_id) { random_str }
276
282
 
283
+ before(:all) do
284
+ # As push tests often use the global scope (devices),
285
+ # we need to ensure tests cannot conflict
286
+ reload_test_app
287
+ end
288
+
277
289
  before do
278
290
  fixture_count.times.map do |index|
279
291
  Thread.new do # Parallelise the setup
@@ -353,6 +365,12 @@ describe Ably::Realtime::Push::Admin, :event_machine do
353
365
  }
354
366
  end
355
367
 
368
+ before(:all) do
369
+ # As push tests often use the global scope (devices),
370
+ # we need to ensure tests cannot conflict
371
+ reload_test_app
372
+ end
373
+
356
374
  after do
357
375
  rest_device_registrations.remove_where client_id: client_id
358
376
  end
@@ -388,6 +406,12 @@ describe Ably::Realtime::Push::Admin, :event_machine do
388
406
  let(:device_id) { random_str }
389
407
  let(:client_id) { random_str }
390
408
 
409
+ before(:all) do
410
+ # As push tests often use the global scope (devices),
411
+ # we need to ensure tests cannot conflict
412
+ reload_test_app
413
+ end
414
+
391
415
  before do
392
416
  rest_device_registrations.save({
393
417
  id: "device-#{client_id}-0",
@@ -421,6 +445,12 @@ describe Ably::Realtime::Push::Admin, :event_machine do
421
445
  let(:device_id) { random_str }
422
446
  let(:client_id) { random_str }
423
447
 
448
+ before(:all) do
449
+ # As push tests often use the global scope (devices),
450
+ # we need to ensure tests cannot conflict
451
+ reload_test_app
452
+ end
453
+
424
454
  before do
425
455
  rest_device_registrations.save({
426
456
  id: "device-#{client_id}-0",
@@ -481,6 +511,12 @@ describe Ably::Realtime::Push::Admin, :event_machine do
481
511
  client.push.admin.channel_subscriptions
482
512
  }
483
513
 
514
+ before(:all) do
515
+ # As push tests often use the global scope (devices),
516
+ # we need to ensure tests cannot conflict
517
+ reload_test_app
518
+ end
519
+
484
520
  # Set up 2 devices with the same client_id
485
521
  # and two device with the unique device_id and no client_id
486
522
  before do
@@ -543,8 +579,10 @@ describe Ably::Realtime::Push::Admin, :event_machine do
543
579
  describe '#list_channels' do
544
580
  let(:fixture_count) { 6 }
545
581
 
546
- before(:context) do
547
- reload_test_app # TODO: Review if necessary later, currently other tests may affect list_channels
582
+ before(:all) do
583
+ # As push tests often use the global scope (devices),
584
+ # we need to ensure tests cannot conflict
585
+ reload_test_app
548
586
  end
549
587
 
550
588
  before do
@@ -75,8 +75,7 @@ describe Ably::Rest::Channel, 'messages' do
75
75
  end
76
76
 
77
77
  context 'JSON Array' do
78
- # TODO: Add nil type back in
79
- let(:data) { { 'push' => { 'data' => { 'key' => [ true, false, 55, 'string', { 'Hash' => true }, ['array'] ] } } } }
78
+ let(:data) { { 'push' => { 'data' => { 'key' => [ true, false, 55, nil, 'string', { 'Hash' => true }, ['array'] ] } } } }
80
79
 
81
80
  it 'is encoded and decoded to the same deep multi-type object' do
82
81
  channel.publish 'event', {}, extras: data
@@ -181,6 +181,12 @@ describe Ably::Rest::Push::Admin do
181
181
  let(:client_id) { random_str }
182
182
  let(:fixture_count) { 6 }
183
183
 
184
+ before(:all) do
185
+ # As push tests often use the global scope (devices),
186
+ # we need to ensure tests cannot conflict
187
+ reload_test_app
188
+ end
189
+
184
190
  before do
185
191
  fixture_count.times.map do |index|
186
192
  Thread.new do
@@ -244,6 +250,12 @@ describe Ably::Rest::Push::Admin do
244
250
  let(:fixture_count) { 2 }
245
251
  let(:client_id) { random_str }
246
252
 
253
+ before(:all) do
254
+ # As push tests often use the global scope (devices),
255
+ # we need to ensure tests cannot conflict
256
+ reload_test_app
257
+ end
258
+
247
259
  before do
248
260
  fixture_count.times.map do |index|
249
261
  Thread.new do
@@ -318,6 +330,12 @@ describe Ably::Rest::Push::Admin do
318
330
  }
319
331
  end
320
332
 
333
+ before(:all) do
334
+ # As push tests often use the global scope (devices),
335
+ # we need to ensure tests cannot conflict
336
+ reload_test_app
337
+ end
338
+
321
339
  after do
322
340
  subject.remove_where client_id: client_id, full_wait: true
323
341
  end
@@ -444,6 +462,12 @@ describe Ably::Rest::Push::Admin do
444
462
  let(:device_id) { random_str }
445
463
  let(:client_id) { random_str }
446
464
 
465
+ before(:all) do
466
+ # As push tests often use the global scope (devices),
467
+ # we need to ensure tests cannot conflict
468
+ reload_test_app
469
+ end
470
+
447
471
  before do
448
472
  [
449
473
  Thread.new do
@@ -501,6 +525,12 @@ describe Ably::Rest::Push::Admin do
501
525
  let(:device_id) { random_str }
502
526
  let(:client_id) { random_str }
503
527
 
528
+ before(:all) do
529
+ # As push tests often use the global scope (devices),
530
+ # we need to ensure tests cannot conflict
531
+ reload_test_app
532
+ end
533
+
504
534
  before do
505
535
  [
506
536
  Thread.new do
@@ -585,8 +615,8 @@ describe Ably::Rest::Push::Admin do
585
615
  # and two device with the unique device_id and no client_id
586
616
  before do
587
617
  [
588
- lambda { device_registrations.save(default_device_attr.merge(id: device_id)) },
589
- lambda { device_registrations.save(default_device_attr.merge(id: device_id_2)) },
618
+ lambda { device_registrations.save(default_device_attr.merge(id: device_id, client_id: nil)) },
619
+ lambda { device_registrations.save(default_device_attr.merge(id: device_id_2, client_id: nil)) },
590
620
  lambda { device_registrations.save(default_device_attr.merge(client_id: client_id, id: random_str)) },
591
621
  lambda { device_registrations.save(default_device_attr.merge(client_id: client_id, id: random_str)) }
592
622
  ].map do |proc|
@@ -602,6 +632,12 @@ describe Ably::Rest::Push::Admin do
602
632
  describe '#list (#RSH1c1)' do
603
633
  let(:fixture_count) { 6 }
604
634
 
635
+ before(:all) do
636
+ # As push tests often use the global scope (devices),
637
+ # we need to ensure tests cannot conflict
638
+ reload_test_app
639
+ end
640
+
605
641
  before do
606
642
  fixture_count.times.map do |index|
607
643
  Thread.new { subject.save(channel: "pushenabled:#{random_str}", client_id: client_id) }
@@ -670,11 +706,14 @@ describe Ably::Rest::Push::Admin do
670
706
  describe '#list_channels (#RSH1c2)' do
671
707
  let(:fixture_count) { 6 }
672
708
 
673
- before(:context) do
674
- reload_test_app # TODO: Review if necessary late, currently other tests may affect list_channels
709
+ before(:all) do
710
+ # As push tests often use the global scope (devices),
711
+ # we need to ensure tests cannot conflict
712
+ reload_test_app
675
713
  end
676
714
 
677
715
  before do
716
+ # Create 6 channel subscriptions to the client ID for this test
678
717
  fixture_count.times.map do |index|
679
718
  Thread.new do
680
719
  subject.save(channel: "pushenabled:#{index}:#{random_str}", client_id: client_id)
@@ -694,9 +733,6 @@ describe Ably::Rest::Push::Admin do
694
733
  end
695
734
 
696
735
  it 'supports paging' do
697
- skip 'Channel lists with limits is not reliable immediately after fixture creation'
698
- # TODO: Remove this once list channels with limits is reliable immediately after fixtures created
699
- # See https://github.com/ably/realtime/issues/1882
700
736
  subject.list_channels
701
737
  page = subject.list_channels(limit: 3)
702
738
  expect(page).to be_a(Ably::Models::PaginatedResult)
@@ -730,6 +766,12 @@ describe Ably::Rest::Push::Admin do
730
766
  let(:client_id) { random_str }
731
767
  let(:device_id) { random_str }
732
768
 
769
+ before(:all) do
770
+ # As push tests often use the global scope (devices),
771
+ # we need to ensure tests cannot conflict
772
+ reload_test_app
773
+ end
774
+
733
775
  it 'saves the new client_id PushChannelSubscription Hash object' do
734
776
  subject.save(channel: channel, client_id: client_id)
735
777
 
@@ -802,6 +844,12 @@ describe Ably::Rest::Push::Admin do
802
844
 
803
845
  let(:fixture_count) { 6 }
804
846
 
847
+ before(:all) do
848
+ # As push tests often use the global scope (devices),
849
+ # we need to ensure tests cannot conflict
850
+ reload_test_app
851
+ end
852
+
805
853
  before do
806
854
  fixture_count.times.map do |index|
807
855
  [
@@ -814,8 +862,10 @@ describe Ably::Rest::Push::Admin do
814
862
  end.each(&:join) # Wait for all threads to complete
815
863
  end
816
864
 
865
+ # TODO: Reinstate once delete subscriptions by channel is possible
866
+ # See https://github.com/ably/realtime/issues/1359
817
867
  it 'removes matching channels' do
818
- skip 'Delete by channel is not yet supported'
868
+ skip 'deleting subscriptions is not yet supported realtime#1359'
819
869
  subject.remove_where channel: fixed_channel, full_wait: true
820
870
  expect(subject.list(channel: fixed_channel).items.count).to eql(0)
821
871
  expect(subject.list(client_id: client_id).items.count).to eql(0)
@@ -852,6 +902,12 @@ describe Ably::Rest::Push::Admin do
852
902
  let(:client_id) { random_str }
853
903
  let(:device_id) { random_str }
854
904
 
905
+ before(:all) do
906
+ # As push tests often use the global scope (devices),
907
+ # we need to ensure tests cannot conflict
908
+ reload_test_app
909
+ end
910
+
855
911
  before do
856
912
  [
857
913
  lambda { subject.save(channel: channel, client_id: client_id) },
@@ -2,6 +2,8 @@ RSpec.configure do |config|
2
2
  config.before(:example) do |example|
3
3
  next if example.metadata[:prevent_log_stubbing]
4
4
 
5
+ log_mutex = Mutex.new
6
+
5
7
  @log_output = []
6
8
  %w(fatal error warn info debug).each do |method_name|
7
9
  allow_any_instance_of(Ably::Logger).to receive(method_name.to_sym).and_wrap_original do |method, *args, &block|
@@ -10,11 +12,13 @@ RSpec.configure do |config|
10
12
 
11
13
  prefix = "#{Time.now.strftime('%H:%M:%S.%L')} [\e[33m#{method_name}\e[0m] "
12
14
 
13
- begin
14
- args << block.call unless block.nil?
15
- @log_output << "#{prefix}#{args.compact.join(' ')}"
16
- rescue StandardError => e
17
- @log_output << "#{prefix}Failed to log block - #{e.class}: #{e.message}\n#{e.backtrace.join("\n")}}"
15
+ log_mutex.synchronize do
16
+ begin
17
+ args << block.call unless block.nil?
18
+ @log_output << "#{prefix}#{args.compact.join(' ')}"
19
+ rescue StandardError => e
20
+ @log_output << "#{prefix}Failed to log block - #{e.class}: #{e.message}\n#{e.backtrace.join("\n")}}"
21
+ end
18
22
  end
19
23
 
20
24
  # Call original
@@ -53,7 +53,7 @@ describe Ably::Modules::Enum, :api_private do
53
53
  end
54
54
 
55
55
  it 'allows different type comparison 2' do
56
- skip 'Unless we monkeypath Symbols, the == operator is never invoked'
56
+ skip 'Unless we monkeypatch Symbols, the == operator is never invoked'
57
57
  expect([:value_zero].include?(subject.ValueZero)).to eql(true)
58
58
  end
59
59
 
@@ -13,7 +13,7 @@ describe Ably::Realtime::Client do
13
13
  let(:client_options) { { key: 'appid.keyuid:keysecret', auto_connect: false } }
14
14
 
15
15
  it 'passes on the options to the initializer' do
16
- rest_client = instance_double('Ably::Rest::Client', auth: instance_double('Ably::Auth'), options: client_options)
16
+ rest_client = instance_double('Ably::Rest::Client', auth: instance_double('Ably::Auth'), options: client_options, environment: 'production', use_tls?: true, custom_tls_port: nil)
17
17
  expect(Ably::Rest::Client).to receive(:new).with(hash_including(client_options)).and_return(rest_client)
18
18
  subject
19
19
  end
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
  require 'shared/protocol_msgbus_behaviour'
3
3
 
4
4
  describe Ably::Realtime::Connection do
5
- let(:client) { instance_double('Ably::Realtime::Client', logger: double('logger').as_null_object, recover: nil) }
5
+ let(:client) { instance_double('Ably::Realtime::Client', logger: double('logger').as_null_object, recover: nil, endpoint: double('endpoint', host: 'realtime.ably.io')) }
6
6
 
7
7
  subject do
8
8
  Ably::Realtime::Connection.new(client, {}).tap do |connection|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ably
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lewis Marshall
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-05-06 00:00:00.000000000 Z
12
+ date: 2019-08-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine
@@ -115,14 +115,14 @@ dependencies:
115
115
  requirements:
116
116
  - - ">="
117
117
  - !ruby/object:Gem::Version
118
- version: 0.6.2
118
+ version: 1.3.0
119
119
  type: :runtime
120
120
  prerelease: false
121
121
  version_requirements: !ruby/object:Gem::Requirement
122
122
  requirements:
123
123
  - - ">="
124
124
  - !ruby/object:Gem::Version
125
- version: 0.6.2
125
+ version: 1.3.0
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: addressable
128
128
  requirement: !ruby/object:Gem::Requirement