You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2018/01/05 16:35:48 UTC

[24/50] [abbrv] qpid-proton git commit: PROTON-1537: [ruby] Update tests to new API, many fixes

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: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org