lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb in ably-rest-1.0.6 vs lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb in ably-rest-1.1.0

- old
+ new

@@ -11,10 +11,13 @@ let(:channel_name) { random_str } let(:payload) { random_str } let(:channel) { client.channel(channel_name) } let(:messages) { [] } + let(:sub_client) { auto_close Ably::Realtime::Client.new(client_options) } + let(:sub_channel) { sub_client.channel(channel_name) } + def disconnect_transport connection.transport.unbind end describe 'initialization' do @@ -724,11 +727,11 @@ context '#publish' do let(:name) { random_str } let(:data) { random_str } - context 'when attached' do + context 'when channel is attached (#RTL6c1)' do it 'publishes messages' do channel.attach do 3.times { channel.publish('event', payload) } end channel.subscribe do |message| @@ -736,85 +739,177 @@ stop_reactor if messages.count == 3 end end end - context 'when not yet attached' do - it 'publishes queued messages once attached' do - 3.times { channel.publish('event', random_str) } - channel.subscribe do |message| - messages << message if message.name == 'event' - stop_reactor if messages.count == 3 + context 'when channel is not attached in state Initializing (#RTL6c1)' do + it 'publishes messages immediately and does not implicitly attach (#RTL6c1)' do + sub_channel.attach do + sub_channel.subscribe do |message| + messages << message if message.name == 'event' + if messages.count == 3 + EventMachine.add_timer(1) do + expect(channel.state).to eq(:initialized) + stop_reactor + end + end + end + 3.times { channel.publish('event', random_str) } end end + end - it 'publishes queued messages within a single protocol message' do - 3.times { channel.publish('event', random_str) } - channel.subscribe do |message| - messages << message if message.name == 'event' - next unless messages.length == 3 + context 'when channel is Attaching (#RTL6c1)' do + it 'publishes messages immediately (#RTL6c1)' do + sub_channel.attach do + channel.once(:attaching) do + outgoing_message_count = 0 + client.connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message| + if protocol_message.action == :message + raise "Expected channel state to be attaching when publishing messages, not #{channel.state}" unless channel.attaching? + outgoing_message_count += protocol_message.messages.count + end + end + sub_channel.subscribe do |message| + messages << message if message.name == 'event' + if messages.count == 3 + expect(outgoing_message_count).to eql(3) + stop_reactor + end + end + 3.times { channel.publish('event', random_str) } + end + channel.attach + end + end + end - # All 3 messages should be batched into a single Protocol Message by the client library - # message.id = "{protocol_message.id}:{protocol_message_index}" - # Check that all messages share the same protocol_message.id - message_id = messages.map { |msg| msg.id.split(':')[0...-1].join(':') } - expect(message_id.uniq.count).to eql(1) + context 'when channel is Detaching (#RTL6c1)' do + it 'publishes messages immediately (#RTL6c1)' do + sub_channel.attach do + channel.attach do + channel.once(:detaching) do + outgoing_message_count = 0 + client.connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message| + if protocol_message.action == :message + raise "Expected channel state to be attaching when publishing messages, not #{channel.state}" unless channel.detaching? + outgoing_message_count += protocol_message.messages.count + end + end + sub_channel.subscribe do |message| + messages << message if message.name == 'event' + if messages.count == 3 + expect(outgoing_message_count).to eql(3) + stop_reactor + end + end + 3.times { channel.publish('event', random_str) } + end + channel.detach + end + end + end + end - # Check that messages use index 0,1,2 in the ID - message_indexes = messages.map { |msg| msg.id.split(':').last } - expect(message_indexes).to include("0", "1", "2") - stop_reactor + context 'when channel is Detached (#RTL6c1)' do + it 'publishes messages immediately (#RTL6c1)' do + sub_channel.attach do + channel.attach + channel.once(:attached) do + channel.once(:detached) do + outgoing_message_count = 0 + client.connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message| + if protocol_message.action == :message + raise "Expected channel state to be attaching when publishing messages, not #{channel.state}" unless channel.detached? + outgoing_message_count += protocol_message.messages.count + end + end + sub_channel.subscribe do |message| + messages << message if message.name == 'event' + if messages.count == 3 + expect(outgoing_message_count).to eql(3) + stop_reactor + end + end + 3.times { channel.publish('event', random_str) } + end + channel.detach + end end end + end - context 'with :queue_messages client option set to false' do - let(:client_options) { default_options.merge(queue_messages: false) } + context 'with :queue_messages client option set to false (#RTL6c4)' do + let(:client_options) { default_options.merge(queue_messages: false) } - context 'and connection state initialized' do - it 'fails the deferrable' do - expect(client.connection).to be_initialized + context 'and connection state connected (#RTL6c4)' do + it 'publishes the message' do + client.connection.once(:connected) do + channel.publish('event') + stop_reactor + end + end + end + + context 'and connection state initialized (#RTL6c4)' do + it 'fails the deferrable' do + expect(client.connection).to be_initialized + channel.publish('event').errback do |error| + expect(error).to be_a(Ably::Exceptions::MessageQueueingDisabled) + stop_reactor + end + end + end + + context 'and connection state connecting (#RTL6c4)' do + it 'fails the deferrable' do + client.connect + EventMachine.next_tick do + expect(client.connection).to be_connecting channel.publish('event').errback do |error| expect(error).to be_a(Ably::Exceptions::MessageQueueingDisabled) stop_reactor end end end + end - context 'and connection state connecting' do - it 'fails the deferrable' do - client.connect - EventMachine.next_tick do - expect(client.connection).to be_connecting - channel.publish('event').errback do |error| - expect(error).to be_a(Ably::Exceptions::MessageQueueingDisabled) - stop_reactor - end - end - end - end - - context 'and connection state disconnected' do + [:disconnected, :suspended, :closing, :closed].each do |invalid_connection_state| + context "and connection state #{invalid_connection_state} (#RTL6c4)" do let(:client_options) { default_options.merge(queue_messages: false) } it 'fails the deferrable' do client.connection.once(:connected) do - client.connection.once(:disconnected) do - expect(client.connection).to be_disconnected + client.connection.once(invalid_connection_state) do + expect(client.connection.state).to eq(invalid_connection_state) channel.publish('event').errback do |error| expect(error).to be_a(Ably::Exceptions::MessageQueueingDisabled) stop_reactor end end - client.connection.transition_state_machine :disconnected + if invalid_connection_state == :closed + connection.close + else + client.connection.transition_state_machine invalid_connection_state + end end end end + end - context 'and connection state connected' do - it 'publishes the message' do - client.connection.once(:connected) do - channel.publish('event') - stop_reactor + context 'and the channel state is failed (#RTL6c4)' do + let(:client_options) { default_options.merge(queue_messages: false) } + it 'fails the deferrable' do + client.connection.once(:connected) do + channel.attach + channel.once(:attached) do + channel.once(:failed) do + channel.publish('event').errback do |error| + expect(error).to be_a(Ably::Exceptions::ChannelInactive) + stop_reactor + end + end + channel.transition_state_machine(:failed) end end end end end @@ -1072,10 +1167,25 @@ end end end end + context 'with more than allowed messages in a single publish' do + let(:channel_name) { random_str } + + it 'rejects the publish' do + messages = (Ably::Realtime::Connection::MAX_PROTOCOL_MESSAGE_BATCH_SIZE + 1).times.map do + { name: 'foo' } + end + + channel.publish(messages).errback do |error| + expect(error).to be_kind_of(Ably::Exceptions::InvalidRequest) + stop_reactor + end + end + end + context 'identified clients' do context 'when authenticated with a wildcard client_id' do let(:token) { Ably::Rest::Client.new(default_options).auth.request_token(client_id: '*') } let(:client_options) { default_options.merge(key: nil, token: token) } let(:client) { auto_close Ably::Realtime::Client.new(client_options) } @@ -1951,12 +2061,16 @@ end end end context 'moves to' do - %w(suspended detached failed).each do |channel_state| + %w(suspended failed).each do |channel_state| context(channel_state) do + let(:client) do + auto_close Ably::Realtime::Client.new(default_options.merge(log_level: :error)) + end + specify 'all queued messages fail with NACK (#RTL11)' do channel.attach do # Move to disconnected disconnect_transport_proc = lambda do if connection.transport @@ -1979,10 +2093,11 @@ end specify 'all published messages awaiting an ACK do nothing (#RTL11a)' do connection_been_disconnected = false - channel.attach do + channel.attach + channel.once(:attached) do deferrable = channel.publish("foo") deferrable.errback do |error| fail "Message publish should not fail" end deferrable.callback do |error|