http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a13bc2b9/proton-c/bindings/ruby/tests/test_delivery.rb ---------------------------------------------------------------------- diff --git a/proton-c/bindings/ruby/tests/test_delivery.rb b/proton-c/bindings/ruby/tests/test_delivery.rb index 334450a..db15321 100644 --- a/proton-c/bindings/ruby/tests/test_delivery.rb +++ b/proton-c/bindings/ruby/tests/test_delivery.rb @@ -24,8 +24,7 @@ include Qpid::Proton # Test Delivery and Tracker class TestDelivery < Minitest::Test - # Duck-typed handler - class NoAutoHandler + class NoAutoHandler < MessagingHandler @@options = {:auto_settle=>false, :auto_accept=>false} def options() @@options; end end @@ -35,32 +34,32 @@ class TestDelivery < Minitest::Test @unsent = to_send end - def on_connection_opened(event) + def on_connection_open(connection) @outcomes = [] - @sender = event.connection.open_sender("x") + @sender = connection.open_sender("x") @unsettled = {} # Awaiting remote settlement end attr_reader :outcomes, :unsent, :unsettled - def on_sendable(event) + def on_sendable(sender) return if @unsent.empty? m = Message.new(@unsent.shift) - tracker = event.sender.send(m) + tracker = sender.send(m) @unsettled[tracker] = m end - def outcome(event) - t = event.tracker + def outcome(method, tracker) + t = tracker m = @unsettled.delete(t) - @outcomes << [m.body, event.method, t.id, t.state, t.modifications] - event.connection.close if @unsettled.empty? + @outcomes << [m.body, method, t.id, t.state, t.modifications] + tracker.connection.close if @unsettled.empty? end - def on_accepted(event) outcome(event); end - def on_rejected(event) outcome(event); end - def on_released(event) outcome(event); end - def on_modified(event) outcome(event); end + def on_tracker_accept(tracker) outcome(__method__, tracker); end + def on_tracker_reject(tracker) outcome(__method__, tracker); end + def on_tracker_release(tracker) outcome(__method__, tracker); end + def on_tracker_modify(tracker) outcome(__method__, tracker); end end class ReceiveHandler < NoAutoHandler @@ -70,17 +69,17 @@ class TestDelivery < Minitest::Test attr_reader :received - def on_message(event) - @received << event.message.body - case event.message.body - when "accept" then event.delivery.accept - when "reject" then event.delivery.reject - when "release-really" then event.delivery.release({:failed=>false}) # AMQP RELEASED - when "release" then event.delivery.release # AMQP MODIFIED{ :failed => true } - when "modify" then event.delivery.release({:undeliverable => true, :annotations => {:x => 42 }}) - when "modify-empty" then event.delivery.release({:failed => false, :undeliverable => false, :annotations => {}}) - when "modify-nil" then event.delivery.release({:failed => false, :undeliverable => false, :annotations => nil}) - else raise event.inspect + def on_message(delivery, message) + @received << message.body + case message.body + when "accept" then delivery.accept + when "reject" then delivery.reject + when "release-really" then delivery.release({:failed=>false}) # AMQP RELEASED + when "release" then delivery.release # AMQP MODIFIED{ :failed => true } + when "modify" then delivery.release({:undeliverable => true, :annotations => {:x => 42 }}) + when "modify-empty" then delivery.release({:failed => false, :undeliverable => false, :annotations => {}}) + when "modify-nil" then delivery.release({:failed => false, :undeliverable => false, :annotations => nil}) + else raise inspect end end end @@ -88,17 +87,18 @@ class TestDelivery < Minitest::Test def test_outcomes rh = ReceiveHandler.new sh = SendHandler.new(["accept", "reject", "release-really", "release", "modify", "modify-empty", "modify-nil"]) - c = TestContainer.new(nil, { :handler => rh }, __method__) - c.connect(c.url, {:handler => sh}) + c = Container.new(nil, __method__) + l = c.listen_io(TCPServer.new(0), ListenOnceHandler.new({ :handler => rh })) + c.connect(l.url, {:handler => sh}) c.run o = sh.outcomes - assert_equal ["accept", :on_accepted, "1", Transfer::ACCEPTED, nil], o.shift - assert_equal ["reject", :on_rejected, "2", Transfer::REJECTED, nil], o.shift - assert_equal ["release-really", :on_released, "3", Transfer::RELEASED, nil], o.shift - assert_equal ["release", :on_modified, "4", Transfer::MODIFIED, {:failed=>true, :undeliverable=>false, :annotations=>nil}], o.shift - assert_equal ["modify", :on_modified, "5", Transfer::MODIFIED, {:failed=>true, :undeliverable=>true, :annotations=>{:x => 42}}], o.shift - assert_equal ["modify-empty", :on_released, "6", Transfer::RELEASED, nil], o.shift - assert_equal ["modify-nil", :on_released, "7", Transfer::RELEASED, nil], o.shift + assert_equal ["accept", :on_tracker_accept, "1", Transfer::ACCEPTED, nil], o.shift + assert_equal ["reject", :on_tracker_reject, "2", Transfer::REJECTED, nil], o.shift + assert_equal ["release-really", :on_tracker_release, "3", Transfer::RELEASED, nil], o.shift + assert_equal ["release", :on_tracker_modify, "4", Transfer::MODIFIED, {:failed=>true, :undeliverable=>false, :annotations=>nil}], o.shift + assert_equal ["modify", :on_tracker_modify, "5", Transfer::MODIFIED, {:failed=>true, :undeliverable=>true, :annotations=>{:x => 42}}], o.shift + assert_equal ["modify-empty", :on_tracker_release, "6", Transfer::RELEASED, nil], o.shift + assert_equal ["modify-nil", :on_tracker_release, "7", Transfer::RELEASED, nil], o.shift assert_empty o assert_equal ["accept", "reject", "release-really", "release", "modify", "modify-empty", "modify-nil"], rh.received assert_empty sh.unsettled
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a13bc2b9/proton-c/bindings/ruby/tests/test_messaging_adapter.rb ---------------------------------------------------------------------- diff --git a/proton-c/bindings/ruby/tests/test_messaging_adapter.rb b/proton-c/bindings/ruby/tests/test_messaging_adapter.rb new file mode 100644 index 0000000..200b68c --- /dev/null +++ b/proton-c/bindings/ruby/tests/test_messaging_adapter.rb @@ -0,0 +1,232 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + + +require 'minitest/autorun' +require 'qpid_proton' +require 'test_tools' +include Qpid::Proton + +# Records every call, never provokes "on_unhandled" +class RecordingHandler < Qpid::Proton::MessagingHandler + + def initialize(*args) super(*args); @calls = []; end + + attr_accessor :calls + + def names() @calls.collect { |c| c[0] }; end + + def clear() @calls.clear; end + + def method_missing(name, *args) + respond_to_missing?(name) ? (@calls << [name, *args]) : super; + end + def respond_to_missing?(name, private=false); (/^on_/ =~ name); end + def respond_to?(name, all=false) super || respond_to_missing?(name); end # For ruby < 1.9.2 +end + +# Extra methods for driver pairs of RecordingHandler +class DriverPair + def names() collect { |x| x.handler.names }; end + def clear() each { |x| x.handler.clear; } end +end + +class TestMessagingHandler < Minitest::Test + + def test_handler_defaults + d = DriverPair.new(RecordingHandler.new, RecordingHandler.new) + want = { :prefetch => 10, :auto_settle => true, :auto_accept => true, :auto_open => true, :auto_close => true } + assert_equal want, d.client.handler.options + assert_equal want, d.server.handler.options + end + + def test_auto_open_close + d = DriverPair.new(RecordingHandler.new, RecordingHandler.new) + d.client.connection.open; d.client.connection.open_sender; d.run + assert_equal [:on_connection_open, :on_session_open, :on_link_open, :on_sendable], d.client.handler.names + assert_equal [:on_connection_open, :on_session_open, :on_link_open], d.server.handler.names + d.clear + d.client.connection.close; d.run + assert_equal [:on_connection_close, :on_transport_close], d.server.handler.names + assert_equal [:on_connection_close, :on_transport_close], d.client.handler.names + end + + def test_no_auto_open_close + opts = { :auto_close => false, :auto_open => false } + d = DriverPair.new(RecordingHandler.new(opts), RecordingHandler.new(opts)) + + d.client.connection.open; d.run + assert_equal [:on_connection_open], d.server.handler.names + assert_equal [], d.client.handler.names + d.server.connection.open; d.run + assert_equal [:on_connection_open], d.client.handler.names + assert_equal [:on_connection_open], d.server.handler.names + d.clear + d.client.connection.session.open; d.run + assert_equal [:on_session_open], d.server.handler.names + assert_equal [], d.client.handler.names + d.clear + d.client.connection.close; + 3.times { d.process } + assert_equal [:on_connection_close], d.server.handler.names + assert_equal [], d.client.handler.names + d.server.connection.close; d.run + assert_equal [:on_connection_close, :on_transport_close], d.client.handler.names + assert_equal [:on_connection_close, :on_transport_close], d.server.handler.names + end + + def test_transport_error + d = DriverPair.new(RecordingHandler.new, RecordingHandler.new) + d.client.connection.open; d.run + d.clear + d.client.close "stop that"; d.run + assert_equal [:on_transport_close], d.client.handler.names + assert_equal [:on_transport_error, :on_transport_close], d.server.handler.names + assert_equal Condition.new("proton:io", "stop that (connection aborted)"), d.client.transport.condition + assert_equal Condition.new("amqp:connection:framing-error", "connection aborted"), d.server.transport.condition + end + + # Close on half-open + def test_connection_error + opts = { :auto_open => false } + d = DriverPair.new(RecordingHandler.new(opts), RecordingHandler.new(opts)) + d.client.connection.open; d.run + d.server.connection.close "bad dog"; d.run + assert_equal [:on_connection_open, :on_connection_error, :on_connection_close, :on_transport_close], d.client.handler.names + assert_equal "bad dog", d.client.handler.calls[1][1].condition.description + assert_equal [:on_connection_open, :on_connection_error, :on_connection_close, :on_transport_close], d.server.handler.names + end + + def test_session_error + d = DriverPair.new(RecordingHandler.new, RecordingHandler.new) + d.client.connection.open + s = d.client.connection.session; s.open; d.run + assert_equal [:on_connection_open, :on_session_open], d.client.handler.names + assert_equal [:on_connection_open, :on_session_open], d.server.handler.names + d.clear + s.close "bad dog"; d.run + assert_equal [:on_session_error, :on_session_close], d.client.handler.names + assert_equal [:on_session_error, :on_session_close], d.server.handler.names + assert_equal "bad dog", d.server.handler.calls[0][1].condition.description + end + + def test_link_error + d = DriverPair.new(RecordingHandler.new, RecordingHandler.new) + d.client.connection.open + s = d.client.connection.open_sender; d.run + assert_equal [:on_connection_open, :on_session_open, :on_link_open, :on_sendable], d.client.handler.names + assert_equal [:on_connection_open, :on_session_open, :on_link_open], d.server.handler.names + d.clear + s.close "bad dog"; d.run + assert_equal [:on_link_error, :on_link_close], d.client.handler.names + assert_equal [:on_link_error, :on_link_close], d.server.handler.names + assert_equal "bad dog", d.server.handler.calls[0][1].condition.description + end + + def test_options_off + handler_class = Class.new(RecordingHandler) do + def on_link_open(l) super; @link = l; end + def on_session_open(s) super; @session = s; end + attr_reader :link, :session + end + + off = {:prefetch => nil, :auto_settle => false, :auto_accept => false, :auto_open => false, :auto_close => false} + d = DriverPair.new(handler_class.new(off), handler_class.new(off)) + d.client.connection.open; d.run + assert_equal [[], [:on_connection_open]], d.names + d.server.connection.open; d.run + assert_equal [[:on_connection_open], [:on_connection_open]], d.names + d.clear + s = d.client.connection.open_sender; d.run + assert_equal [[], [:on_session_open, :on_link_open]], d.names + d.server.handler.session.open + d.server.handler.link.open # Return the opens + d.run + assert_equal [[:on_session_open, :on_link_open], [:on_session_open, :on_link_open]], d.names + d.clear + d.server.handler.link.flow(1); d.run + assert_equal [[:on_sendable], []], d.names + assert_equal 1, s.credit + d.clear + s.send Message.new("foo"); d.run + assert_equal [[], [:on_message]], d.names + end + + + def test_message + handler_class = Class.new(MessagingHandler) do + def on_message(delivery, message) @message = message; end + def on_tracker_accept(event) @accepted = true; end + attr_accessor :message, :accepted + end + d = DriverPair.new(handler_class.new, handler_class.new) + d.client.connection.open; + s = d.client.connection.open_sender; d.run + assert_equal 10, s.credit # Default prefetch + s.send(Message.new("foo")); d.run + assert_equal "foo", d.server.handler.message.body + assert d.client.handler.accepted + end + + # Verify on_unhandled is called + def test_unhandled + handler_class = Class.new(MessagingHandler) do + def initialize() super; @unhandled = []; end + def on_unhandled(method, *args) @unhandled << method; end + attr_accessor :unhandled + end + d = DriverPair.new(handler_class.new, handler_class.new) + d.client.connection.open; d.run + assert_equal [:on_connection_open], d.client.handler.unhandled + assert_equal [:on_connection_open], d.server.handler.unhandled + end + + # Verify on_error is called + def test_on_error + handler_class = Class.new(MessagingHandler) do + def initialize() super; @error = []; @unhandled = []; end + def on_error(condition) @error << condition; end + def on_unhandled(method, *args) @unhandled << method; end + attr_accessor :error, :unhandled + end + d = DriverPair.new(handler_class.new, handler_class.new) + d.client.connection.open + r = d.client.connection.open_receiver; d.run + assert_equal [:on_connection_open, :on_session_open, :on_link_open], d.client.handler.unhandled + assert_equal [:on_connection_open, :on_session_open, :on_link_open, :on_sendable], d.server.handler.unhandled + r.close Condition.new("goof", "oops"); d.run + + assert_equal [Condition.new("goof", "oops")], d.client.handler.error + assert_equal [:on_connection_open, :on_session_open, :on_link_open, :on_sendable, :on_link_close], d.server.handler.unhandled + assert_equal [Condition.new("goof", "oops")], d.server.handler.error + + end + + # Verify on_unhandled is called for errors if there is no on_error + def test_unhandled_error + handler_class = Class.new(MessagingHandler) do + def on_unhandled(method, *args) + @error = args[0].condition if method == :on_connection_error; + end + attr_accessor :error + end + d = DriverPair.new(handler_class.new, handler_class.new) + d.client.connection.open; d.run + d.client.connection.close "oops"; d.run + assert_equal [Condition.new("error", "oops")]*2, d.collect { |x| x.handler.error } + end +end http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a13bc2b9/proton-c/bindings/ruby/tests/test_old_adapter.rb ---------------------------------------------------------------------- diff --git a/proton-c/bindings/ruby/tests/test_old_adapter.rb b/proton-c/bindings/ruby/tests/test_old_adapter.rb new file mode 100644 index 0000000..103efc1 --- /dev/null +++ b/proton-c/bindings/ruby/tests/test_old_adapter.rb @@ -0,0 +1,228 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + + +require 'minitest/autorun' +require 'qpid_proton' +require 'test_tools' +include Qpid::Proton + +OldMessagingHandler = Qpid::Proton::Handler::MessagingHandler #Use the old handler. + +# Records every call +class AllHandler < OldMessagingHandler + def initialize(*args) + super(*args) + @calls = [] + end + + attr_accessor :calls + + def names; @calls.map { |c| c[0] }; end + def events; @calls.map { |c| c[1] }; end + + def method_missing(name, *args) (/^on_/ =~ name) ? (@calls << [name] + args) : super; end + def respond_to_missing?(name, private=false); (/^on_/ =~ name); end + def respond_to?(name, all=false) super || respond_to_missing?(name); end # For ruby < 1.9.2 +end + +# Tests with Mock handler that handles all methods, expect both old and new calls +class TestOldHandler < Minitest::Test + def setup + @h = [AllHandler.new, AllHandler.new] + @ch, @sh = *@h + @d = DriverPair.new(*@h) + end + + def clear; @d.each { |d| h = d.handler; h.calls.clear }; end + + def test_handler_defaults + want = { :prefetch => 10, :auto_settle => true, :auto_accept => true, :auto_open => true, :auto_close => true, :peer_close_is_error => false } + assert_equal want, @ch.options + assert_equal want, @sh.options + end + + def test_auto_open_close + @d.client.connection.open; @d.client.connection.open_sender; @d.run + assert_equal [:on_connection_opened, :on_session_opened, :on_link_opened, :on_sendable], @ch.names + assert_equal [:on_connection_opening, :on_session_opening, :on_link_opening, :on_connection_opened, :on_session_opened, :on_link_opened], @sh.names + clear + @d.client.connection.close; @d.run + assert_equal [:on_connection_closed, :on_transport_closed], @ch.names + assert_equal [:on_connection_closing, :on_connection_closed, :on_transport_closed], @sh.names + end + + def test_no_auto_open_close + [:auto_close, :auto_open].each { |k| @ch.options[k] = @sh.options[k] = false } + @d.client.connection.open; @d.run + assert_equal [:on_connection_opening], @sh.names + assert_equal [], @ch.names + @d.server.connection.open; @d.run + assert_equal [:on_connection_opened], @ch.names + assert_equal [:on_connection_opening, :on_connection_opened], @sh.names + clear + @d.client.connection.session.open; @d.run + assert_equal [:on_session_opening], @sh.names + assert_equal [], @ch.names + clear + @d.client.connection.close; + 3.times { @d.process } + assert_equal [:on_connection_closing], @sh.names + assert_equal [], @ch.names + @d.server.connection.close; @d.run + assert_equal [:on_connection_closed, :on_transport_closed], @ch.names + assert_equal [:on_connection_closing, :on_connection_closed, :on_transport_closed], @sh.names + end + + def test_transport_error + @d.client.connection.open; @d.run + clear + @d.client.close "stop that"; @d.run + assert_equal [:on_transport_closed], @ch.names + assert_equal [:on_transport_error, :on_transport_closed], @sh.names + assert_equal Condition.new("proton:io", "stop that (connection aborted)"), @d.client.transport.condition + assert_equal Condition.new("amqp:connection:framing-error", "connection aborted"), @d.server.transport.condition + end + + def test_connection_error + @ch.options[:auto_open] = @sh.options[:auto_open] = false + @d.client.connection.open; @d.run + @d.server.connection.close "bad dog"; @d.run + assert_equal [:on_connection_opened, :on_connection_error, :on_connection_closed, :on_transport_closed], @ch.names + assert_equal "bad dog", @ch.calls[2][1].condition.description + assert_equal [:on_connection_opening, :on_connection_closed, :on_transport_closed], @sh.names + end + + def test_session_error + @d.client.connection.open + s = @d.client.connection.session; s.open; @d.run + s.close "bad dog"; @d.run + assert_equal [:on_connection_opened, :on_session_opened, :on_session_closed], @ch.names + assert_equal [:on_connection_opening, :on_session_opening, :on_connection_opened, :on_session_opened, :on_session_error, :on_session_closed], @sh.names + assert_equal "bad dog", @sh.calls[-3][1].condition.description + end + + def test_link_error + @d.client.connection.open + s = @d.client.connection.open_sender; @d.run + s.close "bad dog"; @d.run + assert_equal [:on_connection_opened, :on_session_opened, :on_link_opened, :on_sendable, :on_link_closed], @ch.names + assert_equal [:on_connection_opening, :on_session_opening, :on_link_opening, + :on_connection_opened, :on_session_opened, :on_link_opened, + :on_link_error, :on_link_closed], @sh.names + assert_equal "bad dog", @sh.calls[-3][1].condition.description + end + + def test_options_off + off = {:prefetch => 0, :auto_settle => false, :auto_accept => false, :auto_open => false, :auto_close => false} + @ch.options.replace(off) + @sh.options.replace(off) + @d.client.connection.open; @d.run + assert_equal [[], [:on_connection_opening]], [@ch.names, @sh.names] + @d.server.connection.open; @d.run + assert_equal [[:on_connection_opened], [:on_connection_opening, :on_connection_opened]], [@ch.names, @sh.names] + clear + s = @d.client.connection.open_sender; @d.run + assert_equal [[], [:on_session_opening, :on_link_opening]], [@ch.names, @sh.names] + @sh.events[1].session.open + r = @sh.events[1].link + r.open; @d.run + assert_equal [[:on_session_opened, :on_link_opened], [:on_session_opening, :on_link_opening, :on_session_opened, :on_link_opened]], [@ch.names, @sh.names] + clear + r.flow(1); @d.run + assert_equal [[:on_sendable], []], [@ch.names, @sh.names] + assert_equal 1, s.credit + clear + s.send Message.new("foo"); @d.run + assert_equal [[], [:on_message]], [@ch.names, @sh.names] + end + + def test_peer_close_is_error + @ch.options[:peer_close_is_error] = true + @d.client.connection.open; @d.run + @d.server.connection.close; @d.run + assert_equal [:on_connection_opened, :on_connection_error, :on_connection_closed, :on_transport_closed], @ch.names + assert_equal [:on_connection_opening, :on_connection_opened, :on_connection_closed, :on_transport_closed], @sh.names + end +end + +# Test with real handlers that implement a few methods +class TestOldUnhandled < Minitest::Test + + def test_message + handler_class = Class.new(OldMessagingHandler) do + def on_message(event) @message = event.message; end + def on_accepted(event) @accepted = true; end + attr_accessor :message, :accepted, :sender + end + d = DriverPair.new(handler_class.new, handler_class.new) + d.client.connection.open; + s = d.client.connection.open_sender; d.run + assert_equal 10, s.credit # Default prefetch + s.send(Message.new("foo")); d.run + assert_equal "foo", d.server.handler.message.body + assert d.client.handler.accepted + end + + # Verify on_unhandled is called + def test_unhandled + handler_class = Class.new(OldMessagingHandler) do + def initialize() super; @unhandled = []; end + def on_unhandled(event) @unhandled << event.method; end + attr_accessor :unhandled + end + d = DriverPair.new(handler_class.new, handler_class.new) + d.client.connection.open; d.run + assert_equal [:on_connection_opened], d.client.handler.unhandled + assert_equal [:on_connection_opening, :on_connection_opened], d.server.handler.unhandled + end + + # Verify on_error is called + def test_on_error + handler_class = Class.new(OldMessagingHandler) do + def initialize() super; @error = []; @unhandled = []; end + def on_error(event) @error << event.method; end + def on_unhandled(event) @unhandled << event.method; end + attr_accessor :error, :unhandled + end + d = DriverPair.new(handler_class.new, handler_class.new) + d.client.connection.open + r = d.client.connection.open_receiver; d.run + r.close "oops"; d.run + assert_equal [:on_connection_opened, :on_session_opened, :on_link_opened, + :on_link_closed], d.client.handler.unhandled + assert_equal [:on_connection_opening, :on_session_opening, :on_link_opening, + :on_connection_opened, :on_session_opened, :on_link_opened, :on_sendable, + :on_link_closed], d.server.handler.unhandled + assert_equal [:on_link_error], d.server.handler.error + + end + + # Verify on_unhandled is called even for errors if there is no on_error + def test_unhandled_error + handler_class = Class.new(OldMessagingHandler) do + def initialize() super; @unhandled = []; end + def on_unhandled(event) @unhandled << event.method; end + attr_accessor :unhandled + end + d = DriverPair.new(handler_class.new, handler_class.new) + d.client.connection.open; d.run + d.client.connection.close "oops"; d.run + assert_equal [:on_connection_opened, :on_connection_closed, :on_transport_closed], d.client.handler.unhandled + assert_equal [:on_connection_opening, :on_connection_opened, :on_connection_error, :on_connection_closed, :on_transport_closed], d.server.handler.unhandled + end +end http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a13bc2b9/proton-c/bindings/ruby/tests/test_tools.rb ---------------------------------------------------------------------- diff --git a/proton-c/bindings/ruby/tests/test_tools.rb b/proton-c/bindings/ruby/tests/test_tools.rb index ad4a7cb..a5b3b75 100644 --- a/proton-c/bindings/ruby/tests/test_tools.rb +++ b/proton-c/bindings/ruby/tests/test_tools.rb @@ -23,10 +23,6 @@ require 'qpid_proton' require 'thread' require 'socket' -Container = Qpid::Proton::Container -ListenHandler = Qpid::Proton::Listener::Handler -MessagingHandler = Qpid::Proton::Handler::MessagingHandler - class TestError < Exception; end def wait_port(port, timeout=5) @@ -43,7 +39,7 @@ def wait_port(port, timeout=5) end # Handler that records some common events that are checked by tests -class TestHandler < MessagingHandler +class TestHandler < Qpid::Proton::MessagingHandler attr_reader :errors, :connections, :sessions, :links, :messages # Pass optional extra handlers and options to the Container @@ -64,50 +60,54 @@ class TestHandler < MessagingHandler raise TestError.new("TestHandler has errors:\n #{text}") end - def on_error(event) - @errors.push "#{event.type}: #{event.condition.inspect}" + def on_error(condition) + @errors.push "#{condition}" raise_errors if @raise_errors end - def endpoint_opened(queue, endpoint) + def endpoint_open(queue, endpoint) queue.push(endpoint) end - def on_connection_opened(event) - endpoint_opened(@connections, event.connection) + def on_connection_open(c) + endpoint_open(@connections, c) end - def on_session_opened(event) - endpoint_opened(@sessions, event.session) + def on_session_open(s) + endpoint_open(@sessions, s) end - def on_link_opened(event) - endpoint_opened(@links, event.link) + def on_link_open(l) + endpoint_open(@links, l) end - def on_message(event) - @messages.push(event.message) + def on_message(d, m) + @messages.push(m) end end # ListenHandler that closes the Listener after first accept -class ListenOnceHandler < ListenHandler +class ListenOnceHandler < Qpid::Proton::Listener::Handler def on_error(l, e) raise TestError, e.inspect; end def on_accept(l) l.close; super; end end +# Add port/url to Listener, assuming a TCP socket +class Qpid::Proton::Listener + def port() to_io.addr[1]; end + def url() "amqp://:#{port}"; end +end + # A client/server pair of ConnectionDrivers linked by a socket pair -class DriverPair < Array +DriverPair = Struct.new(:client, :server) do def initialize(client_handler, server_handler) - handlers = [client_handler, server_handler] - self[0..-1] = Socket.pair(:LOCAL, :STREAM, 0).map { |s| HandlerDriver.new(s, handlers.shift) } + s = Socket.pair(:LOCAL, :STREAM, 0) + self.client = HandlerDriver.new(s[0], client_handler) + self.server = HandlerDriver.new(s[1], server_handler) server.transport.set_server end - alias client first - alias server last - # Process each driver once, return time of next timed event def process(now = Time.now, max_time=nil) t = collect { |d| d.process(now) }.compact.min @@ -115,40 +115,20 @@ class DriverPair < Array t end - # Run till there is no IO activity - does not handle waiting for timed events - # but does pass +now+ to process and returns the min returned timed event time - def run(now=Time.now) - t = process(now) # Generate initial IO activity and get initial next-time - t = process(now, t) while (IO.select(self, [], [], 0) rescue nil) - t = process(now, t) # Final gulp to finish off events + def active() + can_read = self.select { |d| d.can_read? } + can_write = self.select {|d| d.can_write? } + IO.select(can_read, can_write, [], 0) end -end - -# Container that listens on a random port for a single connection -class TestContainer < Container - def initialize(handler, lopts=nil, id=nil) - super handler, id - @server = TCPServer.open(0) - @listener = listen_io(@server, ListenOnceHandler.new(lopts)) + # Run till there is nothing else to do - not handle waiting for timed events + # but does pass +now+ to process and returns the min returned timed event time + def run(now=Time.now) + t = nil + begin + t = process(now, t) + end while active + t end - - def port() @server.addr[1]; end - def url() "amqp://:#{port}"; end end -# Raw handler to record on_xxx calls via on_unhandled. -# Handy as a base for raw test handlers -class UnhandledHandler - def initialize() @calls =[]; end - def on_unhandled(name, args) @calls << name; end - attr_reader :calls - - # Ruby mechanics to capture on_xxx calls - - def method_missing(name, *args) - if respond_to_missing?(name) then on_unhandled(name, *args) else super end; - end - def respond_to_missing?(name, private=false); (/^on_/ =~ name); end - def respond_to?(name, all=false) super || respond_to_missing?(name); end # For ruby < 1.9.2 -end --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
