ably 1.1.1 → 1.1.2

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.
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