lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb in ably-rest-0.8.5 vs lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb in ably-rest-0.8.6

- old
+ new

@@ -6,11 +6,11 @@ let(:default_options) { { environment: environment, protocol: protocol } } let(:client_options) { default_options } let(:client) { Ably::Rest::Client.new(client_options) } - connection_retry = Ably::Rest::Client::CONNECTION_RETRY + http_defaults = Ably::Rest::Client::HTTP_DEFAULTS def encode64(text) Base64.encode64(text).gsub("\n", '') end @@ -48,10 +48,16 @@ it 'uses token authentication' do expect(client.auth).to be_using_token_auth end end + context 'with an invalid wildcard "*" :client_id' do + it 'raises an exception' do + expect { Ably::Rest::Client.new(client_options.merge(key: api_key, client_id: '*')) }.to raise_error ArgumentError + end + end + context 'with an :auth_callback Proc' do let(:client) { Ably::Rest::Client.new(client_options.merge(auth_callback: Proc.new { token_request })) } it 'calls the auth Proc to get a new token' do expect { client.channel('channel_name').publish('event', 'message') }.to change { client.auth.current_token_details } @@ -81,11 +87,11 @@ expect(client.auth).to be_using_token_auth end context 'before any REST request' do before do - expect(client.auth).to receive(:token_request_from_auth_url).with(token_request_url, hash_including(:auth_method => :get)).once do + expect(client.auth).to receive(:token_request_from_auth_url).with(token_request_url, hash_including(:auth_method => :get), anything).once do client.auth.create_token_request(client_id: client_id) end end it 'sends an HTTP request to the provided auth URL to get a new token' do @@ -152,12 +158,14 @@ @request_index ||= 0 @request_index += 1 send("token_request_#{@request_index > 2 ? 'next' : @request_index}") end)) end - let(:token_request_1) { client.auth.create_token_request({}, token_request_options.merge(client_id: random_str)) } - let(:token_request_2) { client.auth.create_token_request({}, token_request_options.merge(client_id: random_str)) } + let(:client_id) { random_str } + let(:client_id_2) { client_id } + let(:token_request_1) { client.auth.create_token_request({}, token_request_options.merge(client_id: client_id)) } + let(:token_request_2) { client.auth.create_token_request({}, token_request_options.merge(client_id: client_id_2)) } # If token expires against whilst runnig tests in a slower CI environment then use this token let(:token_request_next) { client.auth.create_token_request({}, token_request_options.merge(client_id: random_str)) } context 'when expired' do @@ -175,10 +183,20 @@ sleep 1 expect { client.channel('channel_name').publish('event', 'message') }.to change { client.auth.current_token_details } expect(client.auth.current_token_details.client_id).to eql(token_request_2.client_id) end + + context 'with a different client_id in the subsequent token' do + let(:client_id_2) { random_str } + + it 'fails to authenticate and raises an exception' do + client.channel('channel_name').publish('event', 'message') + sleep 1 + expect { client.channel('channel_name').publish('event', 'message') }.to raise_error(Ably::Exceptions::IncompatibleClientId) + end + end end context 'when token has not expired' do let(:token_request_options) { { key_name: key_name, key_secret: key_secret, ttl: 3600 } } @@ -193,29 +211,57 @@ end end end context 'connection transport' do - let(:client_options) { default_options.merge(key: api_key) } + context 'defaults' do + let(:client_options) { default_options.merge(key: api_key) } - context 'for default host' do - it "is configured to timeout connection opening in #{connection_retry.fetch(:single_request_open_timeout)} seconds" do - expect(client.connection.options.open_timeout).to eql(connection_retry.fetch(:single_request_open_timeout)) + context 'for default host' do + it "is configured to timeout connection opening in #{http_defaults.fetch(:open_timeout)} seconds" do + expect(client.connection.options.open_timeout).to eql(http_defaults.fetch(:open_timeout)) + end + + it "is configured to timeout connection requests in #{http_defaults.fetch(:request_timeout)} seconds" do + expect(client.connection.options.timeout).to eql(http_defaults.fetch(:request_timeout)) + end end - it "is configured to timeout connection requests in #{connection_retry.fetch(:single_request_timeout)} seconds" do - expect(client.connection.options.timeout).to eql(connection_retry.fetch(:single_request_timeout)) + context 'for the fallback hosts' do + it "is configured to timeout connection opening in #{http_defaults.fetch(:open_timeout)} seconds" do + expect(client.fallback_connection.options.open_timeout).to eql(http_defaults.fetch(:open_timeout)) + end + + it "is configured to timeout connection requests in #{http_defaults.fetch(:request_timeout)} seconds" do + expect(client.fallback_connection.options.timeout).to eql(http_defaults.fetch(:request_timeout)) + end end end - context 'for the fallback hosts' do - it "is configured to timeout connection opening in #{connection_retry.fetch(:single_request_open_timeout)} seconds" do - expect(client.fallback_connection.options.open_timeout).to eql(connection_retry.fetch(:single_request_open_timeout)) + context 'with custom http_open_timeout and http_request_timeout options' do + let(:http_open_timeout) { 999 } + let(:http_request_timeout) { 666 } + let(:client_options) { default_options.merge(key: api_key, http_open_timeout: http_open_timeout, http_request_timeout: http_request_timeout) } + + context 'for default host' do + it 'is configured to use custom open timeout' do + expect(client.connection.options.open_timeout).to eql(http_open_timeout) + end + + it 'is configured to use custom request timeout' do + expect(client.connection.options.timeout).to eql(http_request_timeout) + end end - it "is configured to timeout connection requests in #{connection_retry.fetch(:single_request_timeout)} seconds" do - expect(client.fallback_connection.options.timeout).to eql(connection_retry.fetch(:single_request_timeout)) + context 'for the fallback hosts' do + it "is configured to timeout connection opening in #{http_defaults.fetch(:open_timeout)} seconds" do + expect(client.fallback_connection.options.open_timeout).to eql(http_open_timeout) + end + + it "is configured to timeout connection requests in #{http_defaults.fetch(:request_timeout)} seconds" do + expect(client.fallback_connection.options.timeout).to eql(http_request_timeout) + end end end end context 'fallback hosts', :webmock do @@ -247,23 +293,24 @@ end end context 'when environment is production' do let(:custom_hosts) { %w(A.ably-realtime.com B.ably-realtime.com) } - let(:max_attempts) { 2 } - let(:cumulative_timeout) { 0.5 } - let(:client_options) { default_options.merge(environment: nil, key: api_key) } + let(:max_retry_count) { 2 } + let(:max_retry_duration) { 0.5 } let(:fallback_block) { Proc.new { raise Faraday::SSLError.new('ssl error message') } } + let(:client_options) do + default_options.merge( + environment: nil, + key: api_key, + http_max_retry_duration: max_retry_duration, + http_max_retry_count: max_retry_count + ) + end before do stub_const 'Ably::FALLBACK_HOSTS', custom_hosts - stub_const 'Ably::Rest::Client::CONNECTION_RETRY', { - single_request_open_timeout: 4, - single_request_timeout: 15, - cumulative_request_open_timeout: cumulative_timeout, - max_retry_attempts: max_attempts - } end let!(:first_fallback_request_stub) do stub_request(:post, "https://#{api_key}@#{custom_hosts[0]}#{path}").to_return(&fallback_block) end @@ -277,21 +324,21 @@ stub_request(:post, "https://#{api_key}@#{Ably::Rest::Client::DOMAIN}#{path}").to_return do raise Faraday::TimeoutError.new('timeout error message') end end - it "tries fallback hosts #{connection_retry[:max_retry_attempts]} times" do + it "tries fallback hosts #{http_defaults.fetch(:max_retry_count)} times" do expect { publish_block.call }.to raise_error Ably::Exceptions::ConnectionError, /ssl error message/ expect(default_host_request_stub).to have_been_requested expect(first_fallback_request_stub).to have_been_requested expect(second_fallback_request_stub).to have_been_requested end - context "and the total request time exeeds #{connection_retry[:cumulative_request_open_timeout]} seconds" do + context "and the total request time exeeds #{http_defaults.fetch(:max_retry_duration)} seconds" do let!(:default_host_request_stub) do stub_request(:post, "https://#{api_key}@#{Ably::Rest::Client::DOMAIN}#{path}").to_return do - sleep cumulative_timeout * 1.5 + sleep max_retry_duration * 1.5 raise Faraday::TimeoutError.new('timeout error message') end end it 'makes no further attempts to any fallback hosts' do @@ -308,11 +355,11 @@ stub_request(:post, "https://#{api_key}@#{Ably::Rest::Client::DOMAIN}#{path}").to_return do raise Faraday::ConnectionFailed.new('connection failure error message') end end - it "tries fallback hosts #{connection_retry[:max_retry_attempts]} times" do + it "tries fallback hosts #{http_defaults.fetch(:max_retry_count)} times" do expect { publish_block.call }.to raise_error Ably::Exceptions::ConnectionError, /ssl error message/ expect(default_host_request_stub).to have_been_requested expect(first_fallback_request_stub).to have_been_requested expect(second_fallback_request_stub).to have_been_requested end @@ -424,9 +471,63 @@ specify 'are never used' do expect { client.auth.request_token }.to raise_error Ably::Exceptions::ConnectionTimeout expect(custom_host_request_stub).to have_been_requested end end + end + end + + context 'HTTP configuration options' do + let(:client_options) { default_options.merge(key: api_key) } + + context 'defaults' do + specify '#http_open_timeout is 4s' do + expect(client.http_defaults[:open_timeout]).to eql(4) + end + + specify '#http_request_timeout is 15s' do + expect(client.http_defaults[:request_timeout]).to eql(15) + end + + specify '#http_max_retry_count is 3' do + expect(client.http_defaults[:max_retry_count]).to eql(3) + end + + specify '#http_max_retry_duration is 10s' do + expect(client.http_defaults[:max_retry_duration]).to eql(10) + end + end + + context 'configured' do + let(:client_options) do + default_options.merge( + key: api_key, + http_open_timeout: 1, + http_request_timeout: 2, + http_max_retry_count: 33, + http_max_retry_duration: 4 + ) + end + + specify '#http_open_timeout uses provided value' do + expect(client.http_defaults[:open_timeout]).to eql(1) + end + + specify '#http_request_timeout uses provided value' do + expect(client.http_defaults[:request_timeout]).to eql(2) + end + + specify '#http_max_retry_count uses provided value' do + expect(client.http_defaults[:max_retry_count]).to eql(33) + end + + specify '#http_max_retry_duration uses provided value' do + expect(client.http_defaults[:max_retry_duration]).to eql(4) + end + end + + it 'is frozen' do + expect(client.http_defaults).to be_frozen end end context '#auth' do let(:dummy_auth_url) { 'http://dummy.url' }