diff options
Diffstat (limited to 'qpid/cpp/bindings')
-rw-r--r-- | qpid/cpp/bindings/qmf/python/Makefile.am | 2 | ||||
-rw-r--r-- | qpid/cpp/bindings/qmf/python/qmf.py | 4 | ||||
-rw-r--r-- | qpid/cpp/bindings/qmf/qmfengine.i | 35 | ||||
-rw-r--r-- | qpid/cpp/bindings/qmf/ruby/Makefile.am | 7 | ||||
-rw-r--r-- | qpid/cpp/bindings/qmf/ruby/qmf.rb | 321 | ||||
-rwxr-xr-x | qpid/cpp/bindings/qmf/tests/agent_ruby.rb | 103 | ||||
-rwxr-xr-x | qpid/cpp/bindings/qmf/tests/ruby_console.rb | 76 | ||||
-rwxr-xr-x | qpid/cpp/bindings/qmf/tests/ruby_console_test.rb | 194 | ||||
-rwxr-xr-x | qpid/cpp/bindings/qmf/tests/run_interop_tests | 10 | ||||
-rw-r--r-- | qpid/cpp/bindings/qmf/tests/test_base.rb | 73 |
10 files changed, 711 insertions, 114 deletions
diff --git a/qpid/cpp/bindings/qmf/python/Makefile.am b/qpid/cpp/bindings/qmf/python/Makefile.am index 55d9079fb7..53303c7be9 100644 --- a/qpid/cpp/bindings/qmf/python/Makefile.am +++ b/qpid/cpp/bindings/qmf/python/Makefile.am @@ -38,7 +38,7 @@ lib_LTLIBRARIES = _qmfengine.la #_qmfengine_la_LDFLAGS = -avoid-version -module -shrext "$(PYTHON_SO)" #_qmfengine_la_LDFLAGS = -avoid-version -module -shrext ".so" _qmfengine_la_LDFLAGS = -avoid-version -module -shared -_qmfengine_la_LIBADD = $(PYTHON_LIBS) -L$(top_builddir)/src/.libs -lqpidclient $(top_builddir)/src/libqmfagent.la +_qmfengine_la_LIBADD = $(PYTHON_LIBS) -L$(top_builddir)/src/.libs -lqpidclient $(top_builddir)/src/libqmf.la _qmfengine_la_CXXFLAGS = $(INCLUDES) -I$(srcdir)/qmf -I$(PYTHON_INC) nodist__qmfengine_la_SOURCES = qmfengine.cpp diff --git a/qpid/cpp/bindings/qmf/python/qmf.py b/qpid/cpp/bindings/qmf/python/qmf.py index 4800b327f1..383baad0e3 100644 --- a/qpid/cpp/bindings/qmf/python/qmf.py +++ b/qpid/cpp/bindings/qmf/python/qmf.py @@ -566,7 +566,7 @@ class Console: # attr_reader :impl def initialize(handler=None, kwargs={}): self._handler = handler - self.impl = qmfengine.ConsoleEngine() + self.impl = qmfengine.Console() self._event = qmfengine.ConsoleEvent() self._broker_list = [] @@ -741,7 +741,7 @@ class Agent(ConnectionHandler): self._agentLabel = label self._conn = None self._handler = handler - self.impl = qmfengine.AgentEngine(self._agentLabel) + self.impl = qmfengine.Agent(self._agentLabel) self._event = qmfengine.AgentEvent() self._xmtMessage = qmfengine.Message() diff --git a/qpid/cpp/bindings/qmf/qmfengine.i b/qpid/cpp/bindings/qmf/qmfengine.i index d3500c9b8f..3477215254 100644 --- a/qpid/cpp/bindings/qmf/qmfengine.i +++ b/qpid/cpp/bindings/qmf/qmfengine.i @@ -19,34 +19,35 @@ %{ -#include "qmf/AgentEngine.h" -#include "qmf/ConsoleEngine.h" -#include "qmf/ResilientConnection.h" +#include "qmf/engine/Agent.h" +#include "qmf/engine/Console.h" +#include "qmf/engine/ResilientConnection.h" %} -%include <qmf/QmfImportExport.h> -%include <qmf/Query.h> -%include <qmf/Message.h> -%include <qmf/AgentEngine.h> -%include <qmf/ConsoleEngine.h> -%include <qmf/ConnectionSettings.h> -%include <qmf/ResilientConnection.h> -%include <qmf/Typecode.h> -%include <qmf/Schema.h> -%include <qmf/Value.h> -%include <qmf/ObjectId.h> -%include <qmf/Object.h> +%include <qmf/engine/QmfEngineImportExport.h> +%include <qmf/engine/Query.h> +%include <qmf/engine/Message.h> +%include <qmf/engine/Agent.h> +%include <qmf/engine/Console.h> +%include <qmf/engine/ConnectionSettings.h> +%include <qmf/engine/ResilientConnection.h> +%include <qmf/engine/Typecode.h> +%include <qmf/engine/Schema.h> +%include <qmf/engine/Value.h> +%include <qmf/engine/ObjectId.h> +%include <qmf/engine/Object.h> %inline { using namespace std; -using namespace qmf; +using namespace qmf::engine; namespace qmf { +namespace engine { - +} } } diff --git a/qpid/cpp/bindings/qmf/ruby/Makefile.am b/qpid/cpp/bindings/qmf/ruby/Makefile.am index 0537dd1cd8..34096da9ee 100644 --- a/qpid/cpp/bindings/qmf/ruby/Makefile.am +++ b/qpid/cpp/bindings/qmf/ruby/Makefile.am @@ -23,23 +23,22 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/src EXTRA_DIST = ruby.i BUILT_SOURCES = qmfengine.cpp -generated_file_list = qmfengine.cpp rubylibdir = $(RUBY_LIB) dist_rubylib_DATA = qmf.rb -$(generated_file_list): $(srcdir)/ruby.i $(srcdir)/../qmfengine.i +qmfengine.cpp: $(srcdir)/ruby.i $(srcdir)/../qmfengine.i $(SWIG) -ruby -c++ -Wall -I/usr/include $(INCLUDES) $(QPID_CXXFLAGS) -o qmfengine.cpp $(srcdir)/ruby.i rubylibarchdir = $(RUBY_LIB_ARCH) rubylibarch_LTLIBRARIES = qmfengine.la qmfengine_la_LDFLAGS = -avoid-version -module -shrext ".$(RUBY_DLEXT)" -qmfengine_la_LIBADD = $(RUBY_LIBS) -L$(top_builddir)/src/.libs -lqpidclient $(top_builddir)/src/libqmfagent.la +qmfengine_la_LIBADD = $(RUBY_LIBS) -L$(top_builddir)/src/.libs -lqpidclient $(top_builddir)/src/libqmfengine.la qmfengine_la_CXXFLAGS = $(INCLUDES) -I$(RUBY_INC) -I$(RUBY_INC_ARCH) nodist_qmfengine_la_SOURCES = qmfengine.cpp -CLEANFILES = $(generated_file_list) +CLEANFILES = qmfengine.cpp endif # HAVE_RUBY_DEVEL diff --git a/qpid/cpp/bindings/qmf/ruby/qmf.rb b/qpid/cpp/bindings/qmf/ruby/qmf.rb index 16f1058f4a..fbf95215fd 100644 --- a/qpid/cpp/bindings/qmf/ruby/qmf.rb +++ b/qpid/cpp/bindings/qmf/ruby/qmf.rb @@ -60,7 +60,19 @@ module Qmf raise ArgumentError, "Value for attribute '#{key}' has unsupported type: #{val.class}" end - @impl.setAttr(key, v) + good = @impl.setAttr(key, v) + raise "Invalid attribute '#{key}'" unless good + end + + def method_missing(name_in, *args) + name = name_in.to_s + if name[name.length - 1] == 61 + attr = name[0..name.length - 2] + set_attr(attr, args[0]) + return + end + + super.method_missing(name_in, args) end end @@ -85,12 +97,17 @@ module Qmf @new_conn_handlers = [] @conn_handlers_to_delete = [] @conn_handlers = [] + @connected = nil @thread = Thread.new do run end end + def connected? + @connected + end + def kick @sockEngine.write(".") @sockEngine.flush @@ -112,7 +129,6 @@ module Qmf def run() eventImpl = Qmfengine::ResilientConnectionEvent.new - connected = nil new_handlers = nil del_handlers = nil bt_count = 0 @@ -129,7 +145,7 @@ module Qmf new_handlers.each do |nh| @conn_handlers << nh - nh.conn_event_connected() if connected + nh.conn_event_connected() if @connected end new_handlers = nil @@ -143,10 +159,10 @@ module Qmf begin case eventImpl.kind when Qmfengine::ResilientConnectionEvent::CONNECTED - connected = :true + @connected = :true @conn_handlers.each { |h| h.conn_event_connected() } when Qmfengine::ResilientConnectionEvent::DISCONNECTED - connected = nil + @connected = nil @conn_handlers.each { |h| h.conn_event_disconnected(eventImpl.errorText) } when Qmfengine::ResilientConnectionEvent::SESSION_CLOSED eventImpl.sessionContext.handler.sess_event_session_closed(eventImpl.sessionContext, eventImpl.errorText) @@ -189,8 +205,16 @@ module Qmf ##============================================================================== class QmfObject + include MonitorMixin attr_reader :impl, :object_class def initialize(cls, kwargs={}) + super() + @cv = new_cond + @sync_count = 0 + @sync_result = nil + @allow_sets = :false + @broker = kwargs[:broker] if kwargs.include?(:broker) + if cls: @object_class = cls @impl = Qmfengine::Object.new(@object_class.impl) @@ -204,6 +228,22 @@ module Qmf return ObjectId.new(@impl.getObjectId) end + def properties + list = [] + @object_class.properties.each do |prop| + list << [prop, get_attr(prop.name)] + end + return list + end + + def statistics + list = [] + @object_class.statistics.each do |stat| + list << [stat, get_attr(stat.name)] + end + return list + end + def get_attr(name) val = value(name) case val.getType @@ -212,7 +252,7 @@ module Qmf when TYPE_SSTR, TYPE_LSTR then val.asString when TYPE_ABSTIME then val.asInt64 when TYPE_DELTATIME then val.asUint64 - when TYPE_REF then val.asObjectId + when TYPE_REF then ObjectId.new(val.asObjectId) when TYPE_BOOL then val.asBool when TYPE_FLOAT then val.asFloat when TYPE_DOUBLE then val.asDouble @@ -264,6 +304,103 @@ module Qmf set_attr(name, get_attr(name) - by) end + def method_missing(name_in, *args) + # + # Convert the name to a string and determine if it represents an + # attribute assignment (i.e. "attr=") + # + name = name_in.to_s + attr_set = (name[name.length - 1] == 61) + name = name[0..name.length - 2] if attr_set + raise "Sets not permitted on this object" if attr_set && !@allow_sets + + # + # If the name matches a property name, set or return the value of the property. + # + @object_class.properties.each do |prop| + if prop.name == name + if attr_set + return set_attr(name, args[0]) + else + return get_attr(name) + end + end + end + + # + # Do the same for statistics + # + @object_class.statistics.each do |stat| + if stat.name == name + if attr_set + return set_attr(name, args[0]) + else + return get_attr(name) + end + end + end + + # + # If we still haven't found a match for the name, check to see if + # it matches a method name. If so, marshall the arguments and invoke + # the method. + # + @object_class.methods.each do |method| + if method.name == name + raise "Sets not permitted on methods" if attr_set + timeout = 30 + synchronize do + @sync_count = 1 + @impl.invokeMethod(name, _marshall(method, args), self) + @broker.conn.kick if @broker + unless @cv.wait(timeout) { @sync_count == 0 } + raise "Timed out waiting for response" + end + end + + return @sync_result + end + end + + # + # This name means nothing to us, pass it up the line to the parent + # class's handler. + # + super.method_missing(name_in, args) + end + + def _method_result(result) + synchronize do + @sync_result = result + @sync_count -= 1 + @cv.signal + end + end + + # + # Convert a Ruby array of arguments (positional) into a Value object of type "map". + # + private + def _marshall(schema, args) + map = Qmfengine::Value.new(TYPE_MAP) + schema.arguments.each do |arg| + if arg.direction == DIR_IN || arg.direction == DIR_IN_OUT + map.insert(arg.name, Qmfengine::Value.new(arg.typecode)) + end + end + + marshalled = Arguments.new(map) + idx = 0 + schema.arguments.each do |arg| + if arg.direction == DIR_IN || arg.direction == DIR_IN_OUT + marshalled[arg.name] = args[idx] unless args[idx] == nil + idx += 1 + end + end + + return marshalled.map + end + private def value(name) val = @impl.getValue(name.to_s) @@ -277,6 +414,7 @@ module Qmf class AgentObject < QmfObject def initialize(cls, kwargs={}) super(cls, kwargs) + @allow_sets = :true end def destroy @@ -296,20 +434,22 @@ module Qmf end def update() + raise "No linkage to broker" unless @broker + newer = @broker.console.objects(Query.new(:object_id => object_id)) + raise "Expected exactly one update for this object" unless newer.size == 1 + merge_update(newer[0]) end - def mergeUpdate(newObject) + def merge_update(new_object) + @impl.merge(new_object.impl) end def deleted?() - @delete_time > 0 + @impl.isDeleted end def index() end - - def method_missing(name, *args) - end end class ObjectId @@ -323,17 +463,29 @@ module Qmf end def object_num_high - return @impl.getObjectNumHi + @impl.getObjectNumHi end def object_num_low - return @impl.getObjectNumLo + @impl.getObjectNumLo + end + + def broker_bank + @impl.getBrokerBank + end + + def agent_bank + @impl.getAgentBank end def ==(other) return (@impl.getObjectNumHi == other.impl.getObjectNumHi) && (@impl.getObjectNumLo == other.impl.getObjectNumLo) end + + def to_s + @impl.str + end end class Arguments @@ -362,6 +514,14 @@ module Qmf @by_hash.each { |k, v| yield(k, v) } end + def method_missing(name, *args) + if @by_hash.include?(name.to_s) + return @by_hash[name.to_s] + end + + super.method_missing(name, args) + end + def by_key(key) val = @map.byKey(key) case val.getType @@ -370,7 +530,7 @@ module Qmf when TYPE_SSTR, TYPE_LSTR then val.asString when TYPE_ABSTIME then val.asInt64 when TYPE_DELTATIME then val.asUint64 - when TYPE_REF then val.asObjectId + when TYPE_REF then ObjectId.new(val.asObjectId) when TYPE_BOOL then val.asBool when TYPE_FLOAT then val.asFloat when TYPE_DOUBLE then val.asDouble @@ -407,6 +567,32 @@ module Qmf end end + class MethodResponse + def initialize(impl) + @impl = Qmfengine::MethodResponse.new(impl) + end + + def status + @impl.getStatus + end + + def exception + @impl.getException + end + + def text + exception.asString + end + + def args + Arguments.new(@impl.getArgs) + end + + def method_missing(name, *extra_args) + args.__send__(name, extra_args) + end + end + ##============================================================================== ## QUERY ##============================================================================== @@ -421,13 +607,13 @@ module Qmf if kwargs.include?(:key) @impl = Qmfengine::Query.new(kwargs[:key]) elsif kwargs.include?(:object_id) - @impl = Qmfengine::Query.new(kwargs[:object_id]) + @impl = Qmfengine::Query.new(kwargs[:object_id].impl) else package = kwargs[:package] if kwargs.include?(:package) if kwargs.include?(:class) @impl = Qmfengine::Query.new(kwargs[:class], package) else - raise ArgumentError, "Invalid arguments, use :key or :class[,:package]" + raise ArgumentError, "Invalid arguments, use :key, :object_id or :class[,:package]" end end end @@ -470,6 +656,18 @@ module Qmf def name @impl.getName end + + def direction + @impl.getDirection + end + + def typecode + @impl.getType + end + + def to_s + name + end end class SchemaMethod @@ -496,6 +694,10 @@ module Qmf def name @impl.getName end + + def to_s + name + end end class SchemaProperty @@ -516,6 +718,10 @@ module Qmf def name @impl.getName end + + def to_s + name + end end class SchemaStatistic @@ -533,6 +739,10 @@ module Qmf def name @impl.getName end + + def to_s + name + end end class SchemaClassKey @@ -541,12 +751,16 @@ module Qmf @impl = i end - def get_package() - @impl.getPackageName() + def package_name + @impl.getPackageName + end + + def class_name + @impl.getClassName end - def get_class() - @impl.getClassName() + def to_s + @impl.asString end end @@ -590,7 +804,15 @@ module Qmf @impl.addMethod(meth.impl) end - def name + def class_key + SchemaClassKey.new(@impl.getClassKey) + end + + def package_name + @impl.getClassKey.getPackageName + end + + def class_name @impl.getClassKey.getClassName end end @@ -643,7 +865,7 @@ module Qmf def initialize(handler = nil, kwargs={}) super() @handler = handler - @impl = Qmfengine::ConsoleEngine.new + @impl = Qmfengine::Console.new @event = Qmfengine::ConsoleEvent.new @broker_list = [] @cv = new_cond @@ -662,7 +884,7 @@ module Qmf @broker_list.delete(broker) end - def get_packages() + def packages() plist = [] count = @impl.packageCount for i in 0...count @@ -671,7 +893,7 @@ module Qmf return plist end - def get_classes(package, kind=CLASS_OBJECT) + def classes(package, kind=CLASS_OBJECT) clist = [] count = @impl.classCount(package) for i in 0...count @@ -708,7 +930,7 @@ module Qmf end end - def get_agents(broker = nil) + def agents(broker = nil) blist = [] if broker blist << broker @@ -727,11 +949,17 @@ module Qmf return agents end - def get_objects(query, kwargs = {}) + def objects(query, kwargs = {}) timeout = 30 + kwargs.merge!(query) if query.class == Hash + if kwargs.include?(:timeout) timeout = kwargs[:timeout] + kwargs.delete(:timeout) end + + query = Query.new(kwargs) if query.class == Hash + synchronize do @sync_count = 1 @sync_result = [] @@ -745,6 +973,18 @@ module Qmf end end + # Return one and only one object or nil. + def object(query, kwargs = {}) + objs = objects(query, kwargs) + return objs.length == 1 ? objs[0] : nil + end + + # Return the first of potentially many objects. + def first_object(query, kwargs = {}) + objs = objects(query, kwargs) + return objs.length > 0 ? objs[0] : nil + end + def _get_result(list, context) synchronize do list.each do |item| @@ -769,15 +1009,20 @@ module Qmf valid = @impl.getEvent(@event) while valid count += 1 - puts "Console Event: #{@event.kind}" case @event.kind when Qmfengine::ConsoleEvent::AGENT_ADDED + @handler.agent_added(AgentProxy.new(@event.agent, nil)) if @handler when Qmfengine::ConsoleEvent::AGENT_DELETED + @handler.agent_deleted(AgentProxy.new(@event.agent, nil)) if @handler when Qmfengine::ConsoleEvent::NEW_PACKAGE + @handler.new_package(@event.name) if @handler when Qmfengine::ConsoleEvent::NEW_CLASS + @handler.new_class(SchemaClassKey.new(@event.classKey)) if @handler when Qmfengine::ConsoleEvent::OBJECT_UPDATE + @handler.object_update(ConsoleObject.new(nil, :impl => @event.object), @event.hasProps, @event.hasStats) if @handler when Qmfengine::ConsoleEvent::EVENT_RECEIVED when Qmfengine::ConsoleEvent::AGENT_HEARTBEAT + @handler.agent_heartbeat(AgentProxy.new(@event.agent, nil), @event.timestamp) if @handler when Qmfengine::ConsoleEvent::METHOD_RESPONSE end @impl.popEvent @@ -798,14 +1043,23 @@ module Qmf def label @impl.getLabel end + + def broker_bank + @impl.getBrokerBank + end + + def agent_bank + @impl.getAgentBank + end end class Broker < ConnectionHandler include MonitorMixin - attr_reader :impl + attr_reader :impl, :conn, :console, :broker_bank def initialize(console, conn) super() + @broker_bank = 1 @console = console @conn = conn @session = nil @@ -825,7 +1079,7 @@ module Qmf @operational = :false end - def waitForStable(timeout = nil) + def wait_for_stable(timeout = nil) synchronize do return if @stable if timeout @@ -850,7 +1104,6 @@ module Qmf valid = @impl.getEvent(@event) while valid count += 1 - puts "Broker Event: #{@event.kind}" case @event.kind when Qmfengine::BrokerEvent::BROKER_INFO when Qmfengine::BrokerEvent::DECLARE_QUEUE @@ -871,9 +1124,12 @@ module Qmf when Qmfengine::BrokerEvent::QUERY_COMPLETE result = [] for idx in 0...@event.queryResponse.getObjectCount - result << ConsoleObject.new(nil, :impl => @event.queryResponse.getObject(idx)) + result << ConsoleObject.new(nil, :impl => @event.queryResponse.getObject(idx), :broker => self) end @console._get_result(result, @event.context) + when Qmfengine::BrokerEvent::METHOD_RESPONSE + obj = @event.context + obj._method_result(MethodResponse.new(@event.methodResponse)) end @impl.popEvent valid = @impl.getEvent(@event) @@ -946,7 +1202,7 @@ module Qmf end @conn = nil @handler = handler - @impl = Qmfengine::AgentEngine.new(@agentLabel) + @impl = Qmfengine::Agent.new(@agentLabel) @event = Qmfengine::AgentEvent.new @xmtMessage = Qmfengine::Message.new end @@ -1050,5 +1306,4 @@ module Qmf do_events end end - end diff --git a/qpid/cpp/bindings/qmf/tests/agent_ruby.rb b/qpid/cpp/bindings/qmf/tests/agent_ruby.rb index 67591319ee..426a284e7d 100755 --- a/qpid/cpp/bindings/qmf/tests/agent_ruby.rb +++ b/qpid/cpp/bindings/qmf/tests/agent_ruby.rb @@ -40,6 +40,9 @@ class Model @parent_class.add_property(Qmf::SchemaProperty.new("int16val", Qmf::TYPE_INT16)) @parent_class.add_property(Qmf::SchemaProperty.new("int8val", Qmf::TYPE_INT8)) + @parent_class.add_property(Qmf::SchemaProperty.new("sstrval", Qmf::TYPE_SSTR)) + @parent_class.add_property(Qmf::SchemaProperty.new("lstrval", Qmf::TYPE_LSTR)) + @parent_class.add_statistic(Qmf::SchemaStatistic.new("queryCount", Qmf::TYPE_UINT32, :unit => "query", :desc => "Query count")) method = Qmf::SchemaMethod.new("echo", :desc => "Check responsiveness of the agent object") @@ -50,6 +53,14 @@ class Model method.add_argument(Qmf::SchemaArgument.new("test", Qmf::TYPE_SSTR, :dir => Qmf::DIR_IN)) @parent_class.add_method(method) + method = Qmf::SchemaMethod.new("set_short_string", :desc => "Set the short string value in the object") + method.add_argument(Qmf::SchemaArgument.new("value", Qmf::TYPE_SSTR, :dir => Qmf::DIR_IN_OUT)) + @parent_class.add_method(method) + + method = Qmf::SchemaMethod.new("set_long_string", :desc => "Set the long string value in the object") + method.add_argument(Qmf::SchemaArgument.new("value", Qmf::TYPE_LSTR, :dir => Qmf::DIR_IN_OUT)) + @parent_class.add_method(method) + method = Qmf::SchemaMethod.new("create_child", :desc => "Create a new child object") method.add_argument(Qmf::SchemaArgument.new("child_name", Qmf::TYPE_LSTR, :dir => Qmf::DIR_IN)) method.add_argument(Qmf::SchemaArgument.new("child_ref", Qmf::TYPE_REF, :dir => Qmf::DIR_OUT)) @@ -84,68 +95,74 @@ class App < Qmf::AgentHandler def method_call(context, name, object_id, args, userId) # puts "Method: user=#{userId} context=#{context} method=#{name} object_num=#{object_id.object_num_low if object_id} args=#{args}" + retCode = 0 + retText = "OK" + if name == "echo" @agent.method_response(context, 0, "OK", args) elsif name == "set_numerics" - retCode = 0 - retText = "OK" if args['test'] == "big" - @parent.set_attr("uint64val", 0x9494949449494949) - @parent.set_attr("uint32val", 0xa5a55a5a) - @parent.set_attr("uint16val", 0xb66b) - @parent.set_attr("uint8val", 0xc7) + @parent.uint64val = 0x9494949449494949 + @parent.uint32val = 0xa5a55a5a + @parent.uint16val = 0xb66b + @parent.uint8val = 0xc7 - @parent.set_attr("int64val", 1000000000000000000) - @parent.set_attr("int32val", 1000000000) - @parent.set_attr("int16val", 10000) - @parent.set_attr("int8val", 100) + @parent.int64val = 1000000000000000000 + @parent.int32val = 1000000000 + @parent.int16val = 10000 + @parent.int8val = 100 elsif args['test'] == "small" - @parent.set_attr("uint64val", 4) - @parent.set_attr("uint32val", 5) - @parent.set_attr("uint16val", 6) - @parent.set_attr("uint8val", 7) + @parent.uint64val = 4 + @parent.uint32val = 5 + @parent.uint16val = 6 + @parent.uint8val = 7 - @parent.set_attr("int64val", 8) - @parent.set_attr("int32val", 9) - @parent.set_attr("int16val", 10) - @parent.set_attr("int8val", 11) + @parent.int64val = 8 + @parent.int32val = 9 + @parent.int16val = 10 + @parent.int8val = 11 elsif args['test'] == "negative" - @parent.set_attr("uint64val", 0) - @parent.set_attr("uint32val", 0) - @parent.set_attr("uint16val", 0) - @parent.set_attr("uint8val", 0) + @parent.uint64val = 0 + @parent.uint32val = 0 + @parent.uint16val = 0 + @parent.uint8val = 0 - @parent.set_attr("int64val", -10000000000) - @parent.set_attr("int32val", -100000) - @parent.set_attr("int16val", -1000) - @parent.set_attr("int8val", -100) + @parent.int64val = -10000000000 + @parent.int32val = -100000 + @parent.int16val = -1000 + @parent.int8val = -100 else retCode = 1 retText = "Invalid argument value for test" end - @agent.method_response(context, retCode, retText, args) + elsif name == "set_short_string" + @parent.sstrval = args['value'] + + elsif name == "set_long_string" + @parent.lstrval = args['value'] elsif name == "create_child" oid = @agent.alloc_object_id(2) args['child_ref'] = oid @child = Qmf::AgentObject.new(@model.child_class) - @child.set_attr("name", args.by_key("child_name")) + @child.name = args.by_key("child_name") @child.set_object_id(oid) - @agent.method_response(context, 0, "OK", args) elsif name == "probe_userid" args['userid'] = userId - @agent.method_response(context, 0, "OK", args) else - @agent.method_response(context, 1, "Unimplemented Method: #{name}", args) + retCode = 1 + retText = "Unimplemented Method: #{name}" end + + @agent.method_response(context, retCode, retText, args) end def main @@ -161,18 +178,18 @@ class App < Qmf::AgentHandler @agent.set_connection(@connection) @parent = Qmf::AgentObject.new(@model.parent_class) - @parent.set_attr("name", "Parent One") - @parent.set_attr("state", "OPERATIONAL") - - @parent.set_attr("uint64val", 0) - @parent.set_attr("uint32val", 0) - @parent.set_attr("uint16val", 0) - @parent.set_attr("uint8val", 0) - - @parent.set_attr("int64val", 0) - @parent.set_attr("int32val", 0) - @parent.set_attr("int16val", 0) - @parent.set_attr("int8val", 0) + @parent.name = "Parent One" + @parent.state = "OPERATIONAL" + + @parent.uint64val = 0 + @parent.uint32val = 0 + @parent.uint16val = 0 + @parent.uint8val = 0 + + @parent.int64val = 0 + @parent.int32val = 0 + @parent.int16val = 0 + @parent.int8val = 0 @parent_oid = @agent.alloc_object_id(1) @parent.set_object_id(@parent_oid) diff --git a/qpid/cpp/bindings/qmf/tests/ruby_console.rb b/qpid/cpp/bindings/qmf/tests/ruby_console.rb index c071829f09..0fa856c724 100755 --- a/qpid/cpp/bindings/qmf/tests/ruby_console.rb +++ b/qpid/cpp/bindings/qmf/tests/ruby_console.rb @@ -24,13 +24,46 @@ require 'socket' class App < Qmf::ConsoleHandler + def agent_added(agent) + puts "AgentAdded: #{agent.label} broker=#{agent.broker_bank} agent=#{agent.agent_bank}" + end + + def agent_deleted(agent) + puts "AgentDeleted: #{agent.label}" + end + + def new_package(package) + puts "NewPackage: #{package}" + end + + def new_class(class_key) + puts "NewClass: #{class_key}" + end + + def object_update(object, hasProps, hasStats) + puts "ObjectUpdate: #{object.object_class.class_name} props=#{hasProps} stats=#{hasStats}" + puts " broker-bank=#{object.object_id.broker_bank}" + puts " agent-bank=#{object.object_id.agent_bank}" + puts " package=#{object.object_class.package_name}" + end + + def event_received(event); end + + def agent_heartbeat(agent, timestamp) + puts "AgentHeartbeat: #{agent.label} time=#{timestamp/1000000000}" + end + + def method_response(resp); end + def broker_info(broker); end + + def dump_schema - packages = @qmfc.get_packages + packages = @qmfc.packages puts "----- Packages -----" packages.each do |p| puts p puts " ----- Object Classes -----" - classes = @qmfc.get_classes(p) + classes = @qmfc.classes(p) classes.each do |c| puts " #{c.name}" @@ -59,7 +92,7 @@ class App < Qmf::ConsoleHandler end puts " ----- Event Classes -----" - classes = @qmfc.get_classes(p, Qmf::CLASS_EVENT) + classes = @qmfc.classes(p, Qmf::CLASS_EVENT) classes.each do |c| puts " #{c.name}" puts " ---- Args ----" @@ -74,17 +107,17 @@ class App < Qmf::ConsoleHandler def main @settings = Qmf::ConnectionSettings.new - @settings.set_attr("host", ARGV[0]) if ARGV.size > 0 - @settings.set_attr("port", ARGV[1].to_i) if ARGV.size > 1 + @settings.host = ARGV[0] if ARGV.size > 0 + @settings.port = ARGV[1].to_i if ARGV.size > 1 @connection = Qmf::Connection.new(@settings) - @qmfc = Qmf::Console.new + @qmfc = Qmf::Console.new(self) @broker = @qmfc.add_connection(@connection) - @broker.waitForStable + @broker.wait_for_stable - dump_schema + ##dump_schema - agents = @qmfc.get_agents() + agents = @qmfc.agents() puts "---- Agents ----" agents.each do |a| puts " => #{a.label}" @@ -92,13 +125,30 @@ class App < Qmf::ConsoleHandler puts "----" for idx in 0...20 - blist = @qmfc.get_objects(Qmf::Query.new(:class => "broker")) + blist = @qmfc.objects(Qmf::Query.new(:class => "broker")) puts "---- Brokers ----" blist.each do |b| puts " ---- Broker ----" - puts " systemRef: #{b.get_attr('systemRef')}" - puts " port : #{b.get_attr('port')}" - puts " uptime : #{b.get_attr('uptime') / 1000000000}" + puts " systemRef: #{b.systemRef}" + puts " port : #{b.port}" + puts " uptime : #{b.uptime / 1000000000}" + puts " properties : #{b.properties}" + puts " statistics : #{b.statistics}" + + for rep in 0...1 + puts " Pinging..." + ret = b.echo(45, 'text string') + puts " status=#{ret.status} text=#{ret.exception.asString} seq=#{ret.args.sequence} body=#{ret.args.body}" + end + end + puts "----" + + qlist = @qmfc.objects(Qmf::Query.new(:package => "org.apache.qpid.broker", + :class => "queue")) + puts "---- Queues ----" + qlist.each do |q| + puts " ---- Queue ----" + puts " name : #{q.name}" end puts "----" sleep(5) diff --git a/qpid/cpp/bindings/qmf/tests/ruby_console_test.rb b/qpid/cpp/bindings/qmf/tests/ruby_console_test.rb new file mode 100755 index 0000000000..b72c8e3806 --- /dev/null +++ b/qpid/cpp/bindings/qmf/tests/ruby_console_test.rb @@ -0,0 +1,194 @@ +#!/usr/bin/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_base' + +class ConsoleTest < ConsoleTestBase + + def test_A_agent_presence + assert(@connection.connected?, "Connection not connected") + + agents = [] + count = 0 + while agents.size == 0 + agents = @qmfc.objects(Qmf::Query.new(:class => "agent")) + sleep(1) + count += 1 + fail("Timed out waiting for remote agent") if count > 10 + end + + agentList = @qmfc.agents + assert_equal(agentList.size, 2, "Number of agents reported by Console") + end + + def test_A_connection_settings + begin + @settings.bogusAttribute = 25 + fail("Connection settings accepted bogus attribute") + rescue + end + end + + def test_B_basic_method_invocation + parent = @qmfc.object(:class => "parent") + assert(parent, "Number of 'parent' objects") + for seq in 0...10 + result = parent.echo(seq) + assert_equal(result.status, 0, "Method Response Status") + assert_equal(result.text, "OK", "Method Response Text") + assert_equal(result.args.sequence, seq, "Echo Response Sequence") + end + + result = parent.set_numerics("bogus") + assert_equal(result.status, 1) + assert_equal(result.text, "Invalid argument value for test") + end + + def test_C_basic_types_numeric_big + parent = @qmfc.object(:class =>"parent") + assert(parent, "Number of parent objects") + + result = parent.set_numerics("big") + assert_equal(result.status, 0, "Method Response Status") + assert_equal(result.text, "OK", "Method Response Text") + + parent.update + + assert_equal(parent.uint64val, 0x9494949449494949) + assert_equal(parent.uint32val, 0xA5A55A5A) + assert_equal(parent.uint16val, 0xB66B) + assert_equal(parent.uint8val, 0xC7) + + assert_equal(parent.int64val, 1000000000000000000) + assert_equal(parent.int32val, 1000000000) + assert_equal(parent.int16val, 10000) + assert_equal(parent.int8val, 100) + end + + def test_C_basic_types_numeric_small + parent = @qmfc.object(:class =>"parent") + assert(parent, "Number of parent objects") + + result = parent.set_numerics("small") + assert_equal(result.status, 0, "Method Response Status") + assert_equal(result.text, "OK", "Method Response Text") + + parent.update + + assert_equal(parent.uint64val, 4) + assert_equal(parent.uint32val, 5) + assert_equal(parent.uint16val, 6) + assert_equal(parent.uint8val, 7) + + assert_equal(parent.int64val, 8) + assert_equal(parent.int32val, 9) + assert_equal(parent.int16val, 10) + assert_equal(parent.int8val, 11) + end + + def test_C_basic_types_numeric_negative + parent = @qmfc.object(:class =>"parent") + assert(parent, "Number of parent objects") + + result = parent.set_numerics("negative") + assert_equal(result.status, 0, "Method Response Status") + assert_equal(result.text, "OK", "Method Response Text") + + parent.update + + assert_equal(parent.uint64val, 0) + assert_equal(parent.uint32val, 0) + assert_equal(parent.uint16val, 0) + assert_equal(parent.uint8val, 0) + + assert_equal(parent.int64val, -10000000000) + assert_equal(parent.int32val, -100000) + assert_equal(parent.int16val, -1000) + assert_equal(parent.int8val, -100) + end + + def test_C_basic_types_string_short + parent = @qmfc.object(:class =>"parent") + assert(parent, "Number of parent objects") + + strings = [] + strings << "" + strings << "A" + strings << "BC" + strings << "DEF" + strings << "GHIJKLMNOPQRSTUVWXYZ" + big = "a" + for i in 0...270 + big << "X" + end + strings << big + + strings.each do |str| + result = parent.set_short_string(str) + assert_equal(result.status, 0, "Method Response Status") + compare = str + compare = compare[0..254] if compare.size > 255 + assert_equal(result.args.value, compare, "Value returned by method") + parent.update + assert_equal(parent.sstrval, compare, "Value stored in the object") + end + end + + def test_C_basic_types_string_long + parent = @qmfc.object(:class =>"parent") + assert(parent, "Number of parent objects") + + strings = [] + strings << "" + strings << "A" + strings << "BC" + strings << "DEF" + strings << "GHIJKLMNOPQRSTUVWXYZ" + big = "a" + for i in 0...270 + big << "X" + end + strings << big + + strings.each do |str| + result = parent.set_long_string(str) + assert_equal(result.status, 0, "Method Response Status") + assert_equal(result.args.value, str, "Value returned by method") + parent.update + assert_equal(parent.lstrval, str, "Value stored in the object") + end + end + + def test_D_userid_for_method + parent = @qmfc.object(:class => "parent") + assert(parent, "Number of parent objects") + + result = parent.probe_userid + assert_equal(result.status, 0, "Method Response Status") + assert_equal(result.args.userid, "anonymous") + end + +end + +app = ConsoleTest.new + + + diff --git a/qpid/cpp/bindings/qmf/tests/run_interop_tests b/qpid/cpp/bindings/qmf/tests/run_interop_tests index 01d7221ac6..b5545d736d 100755 --- a/qpid/cpp/bindings/qmf/tests/run_interop_tests +++ b/qpid/cpp/bindings/qmf/tests/run_interop_tests @@ -88,11 +88,19 @@ if test -d ${PYTHON_DIR} ; then echo " Ruby agent started at pid $AGENT_PID" ${PYTHON_DIR}/qpid-python-test -m python_console -b localhost:$BROKER_PORT $@ RETCODE=$? - stop_ruby_agent if test x$RETCODE != x0; then echo "FAIL qmf interop tests (Ruby Agent)"; TESTS_FAILED=1 fi + + echo " Ruby Agent (external storage) vs. Ruby Console" + ruby -I${MY_DIR} -I${MY_DIR}/../ruby -I${RUBY_LIB_DIR} ${MY_DIR}/ruby_console_test.rb localhost $BROKER_PORT $@ + RETCODE=$? + stop_ruby_agent + if test x$RETCODE != x0; then + echo "FAIL qmf interop tests (Ruby Console/Ruby Agent)"; + TESTS_FAILED=1 + fi fi # Also against the Pure-Python console: diff --git a/qpid/cpp/bindings/qmf/tests/test_base.rb b/qpid/cpp/bindings/qmf/tests/test_base.rb new file mode 100644 index 0000000000..cb7fd9d4f9 --- /dev/null +++ b/qpid/cpp/bindings/qmf/tests/test_base.rb @@ -0,0 +1,73 @@ +#!/usr/bin/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 'qmf' +require 'socket' + +class ConsoleTestBase < Qmf::ConsoleHandler + def initialize + @settings = Qmf::ConnectionSettings.new + @settings.host = ARGV[0] if ARGV.size > 0 + @settings.port = ARGV[1].to_i if ARGV.size > 1 + @connection = Qmf::Connection.new(@settings) + @qmfc = Qmf::Console.new + + @broker = @qmfc.add_connection(@connection) + @broker.wait_for_stable + + tests = [] + methods.each do |m| + name = m.to_s + tests << name if name[0..4] == "test_" + end + + failures = 0 + + tests.sort.each do |t| + begin + print "#{t}..." + $stdout.flush + send(t) + puts " Pass" + rescue + puts " Fail: #{$!}" + failures += 1 + end + end + + @qmfc.del_connection(@broker) + exit(1) if failures > 0 + end + + def assert_equal(left, right, in_text=nil) + text = " (#{in_text})" if in_text + raise "Assertion failed: #{left} != #{right}#{text}" unless left == right + end + + def assert(condition, in_text=nil) + text = " (#{in_text})" if in_text + raise "Assertion failed: #{left} != #{right}#{text}" unless condition + end + + def fail(text) + raise text + end +end |