summaryrefslogtreecommitdiff
path: root/qpid/cpp/bindings
diff options
context:
space:
mode:
Diffstat (limited to 'qpid/cpp/bindings')
-rw-r--r--qpid/cpp/bindings/qmf/python/Makefile.am2
-rw-r--r--qpid/cpp/bindings/qmf/python/qmf.py4
-rw-r--r--qpid/cpp/bindings/qmf/qmfengine.i35
-rw-r--r--qpid/cpp/bindings/qmf/ruby/Makefile.am7
-rw-r--r--qpid/cpp/bindings/qmf/ruby/qmf.rb321
-rwxr-xr-xqpid/cpp/bindings/qmf/tests/agent_ruby.rb103
-rwxr-xr-xqpid/cpp/bindings/qmf/tests/ruby_console.rb76
-rwxr-xr-xqpid/cpp/bindings/qmf/tests/ruby_console_test.rb194
-rwxr-xr-xqpid/cpp/bindings/qmf/tests/run_interop_tests10
-rw-r--r--qpid/cpp/bindings/qmf/tests/test_base.rb73
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