PROTON-1059: ruby binding broken in 0.11 release and on master Re-organized swig binding to avoid use of the pre-processor in %inline sections. Now works with ccache and non-ccache swig.
NOTE: According to ccache-swig man page: "Known problems are using preprocessor directives within %inline blocks and the use of â#pragma SWIGâ." This includes using macros in an %inline section. Added automatic example test, needs extension to cover all examples. Updated option and error handling in some examples to support auto-testing. Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/eb63824f Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/eb63824f Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/eb63824f Branch: refs/heads/go1 Commit: eb63824fd9eb6d3b516ae68065bf05c222b49d95 Parents: 8117f18 Author: Alan Conway <[email protected]> Authored: Mon Nov 23 17:13:12 2015 -0500 Committer: Alan Conway <[email protected]> Committed: Tue Dec 1 18:06:12 2015 -0500 ---------------------------------------------------------------------- examples/ruby/example_test.rb | 90 ++++++++++++++++++++++++++++++++ examples/ruby/reactor/broker.rb | 2 +- examples/ruby/reactor/client.rb | 16 +++++- examples/ruby/reactor/helloworld.rb | 4 ++ examples/ruby/reactor/server.rb | 24 ++++++--- proton-c/CMakeLists.txt | 26 +++++---- proton-c/bindings/python/cproton.i | 4 +- proton-c/bindings/ruby/ruby.i | 87 ++++++++++++++++-------------- 8 files changed, 195 insertions(+), 58 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/eb63824f/examples/ruby/example_test.rb ---------------------------------------------------------------------- diff --git a/examples/ruby/example_test.rb b/examples/ruby/example_test.rb new file mode 100755 index 0000000..9a01964 --- /dev/null +++ b/examples/ruby/example_test.rb @@ -0,0 +1,90 @@ +#!/usr/bin/enc ruby +# +# 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 'test/unit' +require 'qpid_proton' +require 'socket' + +$port = Random.new.rand(10000) + 10000 + +class ExampleTest < Test::Unit::TestCase + + def run_script(script, port) + assert File.exist? script + cmd = [RbConfig.ruby, script] + cmd += ["-a", ":#{port}/examples"] if port + return IO.popen(cmd) + end + + + def assert_output(script, want, port=nil) + out = run_script(script, port) + assert_equal want, out.read.strip + end + + def test_helloworld + assert_output("reactor/helloworld.rb", "Hello world!", $port) + end + + def test_send_recv + assert_output("reactor/simple_send.rb", "All 100 messages confirmed!", $port) + want = (0..99).reduce("") { |x,y| x << "Received: sequence #{y}\n" } + assert_output("reactor/simple_recv.rb", want.strip, $port) + end + + def test_client_server + want = <<EOS +-> Twas brillig, and the slithy toves +<- TWAS BRILLIG, AND THE SLITHY TOVES +-> Did gire and gymble in the wabe. +<- DID GIRE AND GYMBLE IN THE WABE. +-> All mimsy were the borogroves, +<- ALL MIMSY WERE THE BOROGROVES, +-> And the mome raths outgrabe. +<- AND THE MOME RATHS OUTGRABE. +EOS + srv = run_script("reactor/server.rb", $port) + assert_output("reactor/client.rb", want.strip, $port) + + ensure + Process.kill :TERM, srv.pid if srv + end +end + +begin + broker = spawn("#{RbConfig.ruby} reactor/broker.rb -a :#{$port}") + # Wait for the broker to be listening. + while true + begin + s = TCPSocket.open "", $port + puts "Broker ready at #{$port}" + s.close + break + rescue Errno::ECONNREFUSED + puts "Retry connection to #{$port}" + sleep(0.1) + end + end + + Test::Unit::AutoRunner.run + +ensure + Process.kill :TERM, broker if broker +end http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/eb63824f/examples/ruby/reactor/broker.rb ---------------------------------------------------------------------- diff --git a/examples/ruby/reactor/broker.rb b/examples/ruby/reactor/broker.rb index 9d7e5be..7882d9a 100644 --- a/examples/ruby/reactor/broker.rb +++ b/examples/ruby/reactor/broker.rb @@ -117,7 +117,7 @@ class Broker < Qpid::Proton::Handler::MessagingHandler debug("link is#{event.link.sender? ? '' : ' not'} a sender") if $options[:debug] if event.link.sender? if event.link.remote_source.dynamic? - address = generate_uuid + address = SecureRandom.uuid event.link.source.address = address q = Exchange.new(true) @queues[address] = q http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/eb63824f/examples/ruby/reactor/client.rb ---------------------------------------------------------------------- diff --git a/examples/ruby/reactor/client.rb b/examples/ruby/reactor/client.rb index 8bb58da..8c38f38 100644 --- a/examples/ruby/reactor/client.rb +++ b/examples/ruby/reactor/client.rb @@ -18,6 +18,7 @@ #++ require 'qpid_proton' +require 'optparse' class Client < Qpid::Proton::Handler::MessagingHandler @@ -58,6 +59,10 @@ class Client < Qpid::Proton::Handler::MessagingHandler end end + def on_transport_error(event) + raise "Connection error: #{event.transport.condition}" + end + end REQUESTS = ["Twas brillig, and the slithy toves", @@ -65,4 +70,13 @@ REQUESTS = ["Twas brillig, and the slithy toves", "All mimsy were the borogroves,", "And the mome raths outgrabe."] -Qpid::Proton::Reactor::Container.new(Client.new("0.0.0.0:5672/examples", REQUESTS)).run +options = { + :address => "localhost:5672/examples", +} + +OptionParser.new do |opts| + opts.banner = "Usage: client.rb [options]" + opts.on("-a", "--address=ADDRESS", "Send messages to ADDRESS (def. #{options[:address]}).") { |address| options[:address] = address } +end.parse! + +Qpid::Proton::Reactor::Container.new(Client.new(options[:address], REQUESTS)).run http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/eb63824f/examples/ruby/reactor/helloworld.rb ---------------------------------------------------------------------- diff --git a/examples/ruby/reactor/helloworld.rb b/examples/ruby/reactor/helloworld.rb index 03eb561..9b02e8a 100644 --- a/examples/ruby/reactor/helloworld.rb +++ b/examples/ruby/reactor/helloworld.rb @@ -45,6 +45,10 @@ class HelloWorld < Qpid::Proton::Handler::MessagingHandler puts event.message.body event.connection.close end + + def on_transport_error(event) + raise "Connection error: #{event.transport.condition}" + end end options = { http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/eb63824f/examples/ruby/reactor/server.rb ---------------------------------------------------------------------- diff --git a/examples/ruby/reactor/server.rb b/examples/ruby/reactor/server.rb index e149dba..9373272 100644 --- a/examples/ruby/reactor/server.rb +++ b/examples/ruby/reactor/server.rb @@ -18,20 +18,20 @@ #++ require 'qpid_proton' +require 'optparse' class Server < Qpid::Proton::Handler::MessagingHandler - def initialize(url, address) + def initialize(url) super() - @url = url - @address = address + @url = Qpid::Proton::URL.new url + @address = @url.path @senders = {} end def on_start(event) - puts "Listening on #{@url}" @container = event.container - @conn = @container.connect(:address => @url) + @conn = @container.connect(:url => @url) @receiver = @container.create_receiver(@conn, :source => @address) @relay = nil end @@ -59,6 +59,18 @@ class Server < Qpid::Proton::Handler::MessagingHandler sender.send(reply) end + def on_transport_error(event) + raise "Connection error: #{event.transport.condition}" + end end -Qpid::Proton::Reactor::Container.new(Server.new("0.0.0.0:5672", "examples")).run() +options = { + :address => "localhost:5672/examples", +} + +OptionParser.new do |opts| + opts.banner = "Usage: server.rb [options]" + opts.on("-a", "--address=ADDRESS", "Send messages to ADDRESS (def. #{options[:address]}).") { |address| options[:address] = address } +end.parse! + +Qpid::Proton::Reactor::Container.new(Server.new(options[:address])).run() http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/eb63824f/proton-c/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/proton-c/CMakeLists.txt b/proton-c/CMakeLists.txt index d80d60a..d897951 100644 --- a/proton-c/CMakeLists.txt +++ b/proton-c/CMakeLists.txt @@ -586,19 +586,25 @@ endif (BUILD_PYTHON) find_program(RUBY_EXE "ruby") if (RUBY_EXE AND BUILD_RUBY) + set (rb_root "${pn_test_root}/ruby") + set (rb_src "${CMAKE_CURRENT_SOURCE_DIR}/bindings/ruby") + set (rb_lib "${CMAKE_CURRENT_SOURCE_DIR}/bindings/ruby/lib") + set (rb_bin "${CMAKE_CURRENT_BINARY_DIR}/bindings/ruby") + set (rb_bld "$<TARGET_FILE_DIR:qpid-proton>") + set (rb_path $ENV{PATH} ${rb_bin} ${rb_bld}) + set (rb_rubylib ${rb_root} ${rb_src} ${rb_bin} ${rb_bld} ${rb_lib}) + to_native_path("${rb_path}" rb_path) + to_native_path("${rb_rubylib}" rb_rubylib) + + # ruby example tests have no dependencies other than standard ruby. + add_test(NAME ruby-example-test + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/examples/ruby + COMMAND ${env_py} -- "PATH=${rb_path}" "RUBYLIB=${rb_rubylib}" + ${RUBY_EXE} example_test.rb -v) + # ruby unit tests: tests/ruby/proton-test # only enable the tests if the Ruby gem dependencies were found if (DEFAULT_RUBY_TESTING) - set (rb_root "${pn_test_root}/ruby") - set (rb_src "${CMAKE_CURRENT_SOURCE_DIR}/bindings/ruby") - set (rb_lib "${CMAKE_CURRENT_SOURCE_DIR}/bindings/ruby/lib") - set (rb_bin "${CMAKE_CURRENT_BINARY_DIR}/bindings/ruby") - set (rb_bld "$<TARGET_FILE_DIR:qpid-proton>") - set (rb_path $ENV{PATH} ${rb_bin} ${rb_bld}) - set (rb_rubylib ${rb_root} ${rb_src} ${rb_bin} ${rb_bld} ${rb_lib}) - to_native_path("${rb_path}" rb_path) - to_native_path("${rb_rubylib}" rb_rubylib) - add_test (NAME ruby-unit-test COMMAND ${env_py} "PATH=${rb_path}" "RUBYLIB=${rb_rubylib}" "${rb_root}/proton-test") http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/eb63824f/proton-c/bindings/python/cproton.i ---------------------------------------------------------------------- diff --git a/proton-c/bindings/python/cproton.i b/proton-c/bindings/python/cproton.i index f7f56e3..1485801 100644 --- a/proton-c/bindings/python/cproton.i +++ b/proton-c/bindings/python/cproton.i @@ -37,10 +37,10 @@ NOTE: According to ccache-swig man page: "Known problems are using preprocessor directives within %inline blocks and the use of â#pragma SWIGâ." This includes using macros in an %inline section. -Do any preprocessor work or macro expansions here before we get into the %inline sections. +Keep preprocessor directives and macro expansions in the normal header section. */ -PN_HANDLE(PNI_PYTRACER); +PN_HANDLE(PNI_PYTRACER); %} %include <cstring.i> http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/eb63824f/proton-c/bindings/ruby/ruby.i ---------------------------------------------------------------------- diff --git a/proton-c/bindings/ruby/ruby.i b/proton-c/bindings/ruby/ruby.i index eddd529..9edbdb2 100644 --- a/proton-c/bindings/ruby/ruby.i +++ b/proton-c/bindings/ruby/ruby.i @@ -28,49 +28,16 @@ #include <proton/url.h> #include <proton/reactor.h> #include <proton/handlers.h> - +%} /* NOTE: According to ccache-swig man page: "Known problems are using preprocessor directives within %inline blocks and the use of â#pragma SWIGâ." -This includes using any macros in an %inline section. +This includes using macros in an %inline section. -Do any preprocessor work or macro expansions here before we get into the %inline sections. +Keep preprocessor directives and macro expansions in the normal header section. */ -#define CID_Pn_rbkey CID_pn_void - -typedef struct { - void *registry; - char *method; - char *key_value; -} Pn_rbkey_t; - -void Pn_rbkey_initialize(Pn_rbkey_t *rbkey) { - assert(rbkey); - rbkey->registry = NULL; - rbkey->method = NULL; - rbkey->key_value = NULL; -} - -void Pn_rbkey_finalize(Pn_rbkey_t *rbkey) { - if(rbkey && rbkey->registry && rbkey->method && rbkey->key_value) { - rb_funcall((VALUE )rbkey->registry, rb_intern(rbkey->method), 1, rb_str_new2(rbkey->key_value)); - } - if(rbkey->key_value) { - free(rbkey->key_value); - rbkey->key_value = NULL; - } -} - -#define Pn_rbkey_inspect NULL -#define Pn_rbkey_compare NULL -#define Pn_rbkey_hashcode NULL - -PN_CLASSDEF(Pn_rbkey) - -%} - %include <cstring.i> %cstring_output_withsize(char *OUTPUT, size_t *OUTPUT_SIZE) @@ -504,8 +471,53 @@ bool pn_ssl_get_protocol_name(pn_ssl_t *ssl, char *OUTPUT, size_t MAX_OUTPUT_SIZ %ignore pn_messenger_recv; %ignore pn_messenger_work; +%{ +typedef struct Pn_rbkey_t { + void *registry; + char *method; + char *key_value; +} Pn_rbkey_t; + +void Pn_rbkey_initialize(Pn_rbkey_t *rbkey) { + assert(rbkey); + rbkey->registry = NULL; + rbkey->method = NULL; + rbkey->key_value = NULL; +} + +void Pn_rbkey_finalize(Pn_rbkey_t *rbkey) { + if(rbkey && rbkey->registry && rbkey->method && rbkey->key_value) { + rb_funcall((VALUE )rbkey->registry, rb_intern(rbkey->method), 1, rb_str_new2(rbkey->key_value)); + } + if(rbkey->key_value) { + free(rbkey->key_value); + rbkey->key_value = NULL; + } +} + +/* NOTE: no macro or preprocessor definitions in %inline sections */ +#define CID_Pn_rbkey CID_pn_void +#define Pn_rbkey_inspect NULL +#define Pn_rbkey_compare NULL +#define Pn_rbkey_hashcode NULL + +pn_class_t* Pn_rbkey__class(void) { + static pn_class_t clazz = PN_CLASS(Pn_rbkey); + return &clazz; +} + +Pn_rbkey_t *Pn_rbkey_new(void) { + return (Pn_rbkey_t *) pn_class_new(Pn_rbkey__class(), sizeof(Pn_rbkey_t)); +} +%} + +pn_class_t* Pn_rbkey__class(void); +Pn_rbkey_t *Pn_rbkey_new(void); + %inline %{ +Pn_rbkey_t *Pn_rbkey_new(void); + void Pn_rbkey_set_registry(Pn_rbkey_t *rbkey, void *registry) { assert(rbkey); rbkey->registry = registry; @@ -579,8 +591,7 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *ssl, char *OUTPUT, size_t *OUTPUT_SIZE); } VALUE pni_ruby_get_from_registry(VALUE key) { - - return rb_funcall(pni_ruby_get_proton_module(), rb_intern("get_from_registry"), 1, key); + rb_funcall(pni_ruby_get_proton_module(), rb_intern("get_from_registry"), 1, key); } void pni_ruby_delete_from_registry(VALUE stored_key) { --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
