Author: mcpierce
Date: Fri May 31 18:13:12 2013
New Revision: 1488342
URL: http://svn.apache.org/r1488342
Log:
PROTON-322: Extended the Ruby Array class to work with the Data class.
Added attributes for setting the Proton type and description for
encoding an entire array as a described Array. If the type isn't set
then the array is added as an AMQP List instead.
Added:
qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/array.rb
qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/described.rb
qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/mapping.rb
qpid/proton/trunk/proton-c/bindings/ruby/spec/qpid/proton/array_spec.rb
Modified:
qpid/proton/trunk/proton-c/bindings/ruby/ChangeLog
qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton.rb
qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/data.rb
qpid/proton/trunk/proton-c/bindings/ruby/spec/spec_helper.rb
Modified: qpid/proton/trunk/proton-c/bindings/ruby/ChangeLog
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ChangeLog?rev=1488342&r1=1488341&r2=1488342&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/ruby/ChangeLog (original)
+++ qpid/proton/trunk/proton-c/bindings/ruby/ChangeLog Fri May 31 18:13:12 2013
@@ -1,3 +1,6 @@
+version 0.5:
+ * Duck typed the Array class to work with Qpid::Proton::Data.
+
version 0.4:
* No language-specific features developed in this release.
Modified: qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton.rb
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton.rb?rev=1488342&r1=1488341&r2=1488342&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton.rb (original)
+++ qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton.rb Fri May 31
18:13:12 2013
@@ -19,6 +19,9 @@
require "cproton"
+require "qpid_proton/described"
+require "qpid_proton/mapping"
+require "qpid_proton/array"
require "qpid_proton/exceptions"
require "qpid_proton/exception_handling"
require "qpid_proton/message_format"
Added: qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/array.rb
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/array.rb?rev=1488342&view=auto
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/array.rb (added)
+++ qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/array.rb Fri May
31 18:13:12 2013
@@ -0,0 +1,170 @@
+#
+# 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.
+#
+
+#--
+# Patch the Array class to provide methods for adding its contents
+# to a Qpid::Proton::Data instance.
+#++
+
+module Qpid
+
+ module Proton
+
+ # Holds the information for an AMQP Array compound type.
+ #
+ # It holds the type for the array and the descriptor if the
+ # array is described.
+ #
+ class ArrayHeader
+ attr_reader :type
+ attr_reader :descriptor
+
+ def initialize(type, descriptor = nil)
+ @type = type
+ @descriptor = descriptor
+ end
+
+ # Returns true if the array is described.
+ def described?
+ [email protected]?
+ end
+
+ def ==(that)
+ ((@type == that.type) && (@descriptor == that.descriptor))
+ end
+ end
+
+ end
+
+end
+
+class Array
+
+ # Used to declare an array as an AMQP array.
+ #
+ # The value, if defined, is an instance of Qpid::Proton::ArrayHeader
+ attr_accessor :proton_array_header
+
+ # Returns true if the array is the a Proton described type.
+ def proton_described?
+ !@proton_array_header.nil? && @proton_array_header.described?
+ end
+
+ # Puts the elements of the array into the specified Qpid::Proton::Data
object.
+ def proton_put(data)
+ raise TypeError, "data object cannot be nil" if data.nil?
+
+ if @proton_array_header.nil?
+ proton_put_list(data)
+ else
+ proton_put_array(data)
+ end
+ end
+
+ private
+
+ def proton_put_list(data)
+ # create a list, then enter it and add each element
+ data.put_list
+ data.enter
+ each do |element|
+ # get the proton type for the element
+ mapping = Qpid::Proton::Mapping.for_class(element.class)
+ # add the element
+ mapping.put(data, element)
+ end
+ # exit the list
+ data.exit
+ end
+
+ def proton_put_array(data)
+ data.put_array(@proton_array_header.described?, @proton_array_header.type)
+ data.enter
+ if @proton_array_header.described?
+ data.symbol = @proton_array_header.descriptor
+ end
+
+ each do |element|
+ @proton_array_header.type.put(data, element)
+ end
+
+ data.exit
+ end
+
+ class << self
+
+ # Gets the elements of an array or list out of the specified
+ # Qpid::Proton::Data object.
+ def proton_get(data)
+ raise TypeError, "can't convert nil into Qpid::Proton::Data" if data.nil?
+
+ type = data.type
+
+ if type == Qpid::Proton::LIST
+ result = proton_get_list(data)
+ elsif type == Qpid::Proton::ARRAY
+ result = proton_get_array(data)
+ else
+ raise TypeError, "element is not a list and not an array"
+ end
+ end
+
+ private
+
+ def proton_get_list(data)
+ size = data.list
+ raise TypeError, "not a list" unless data.enter
+ elements = []
+ (0...size).each do
+ type = data.next
+ raise TypeError, "missing next element in list" unless type
+ elements << type.get(data)
+ end
+ data.exit
+ return elements
+ end
+
+ def proton_get_array(data)
+ count, described, type = data.array
+
+ raise TypeError, "not an array" unless data.enter
+ elements = []
+
+ descriptor = nil
+
+ if described
+ data.next
+ descriptor = data.symbol
+ end
+
+ elements.proton_array_header = Qpid::Proton::ArrayHeader.new(type,
descriptor)
+ (0...count).each do |which|
+ etype = data.next
+ raise TypeError, "missing next element in array" unless etype
+ raise TypeError, "invalid array element: #{etype}" unless etype == type
+ elements << type.get(data)
+ end
+ data.exit
+ return elements
+ end
+
+ end
+
+end
+
Modified: qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/data.rb
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/data.rb?rev=1488342&r1=1488341&r2=1488342&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/data.rb (original)
+++ qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/data.rb Fri May 31
18:13:12 2013
@@ -161,7 +161,7 @@ module Qpid
# Return the Type object for the current node
def type
- Type.by_code(type_code)
+ Mapping.for_code(type_code)
end
# Returns a representation of the data encoded in AMQP format.
@@ -331,7 +331,7 @@ module Qpid
described = Cproton.pn_data_is_array_described(@data)
array_type = Cproton.pn_data_get_array_type(@data)
return nil if array_type == -1
- [count, described, Type.by_code(array_type) ]
+ [count, described, Mapping.for_code(array_type) ]
end
# Puts a described value.
@@ -614,7 +614,7 @@ module Qpid
# * value - the decimal128 value
def decimal128=(value)
raise TypeError, "invalid decimal128 value: #{value}" if value.nil?
- value = value.to_s(16).rjust(32, "0")
+ value = value.to_s.rjust(32, "0")
bytes = []
value.scan(/(..)/) {|v| bytes << v[0].to_i(16)}
check(Cproton.pn_data_put_decimal128(@data, bytes))
@@ -726,132 +726,6 @@ module Qpid
Cproton.pn_data_get_symbol(@data)
end
- # Convenience class for described types.
- #
- # Holds the descriptor and value, implements methods to get and put a
- # described type in a Data object.
- Described = Struct.new(:descriptor, :value)
- class Described
- def self.get(data)
- def fail; raise 'Not a described type'; end
- (data.described? and data.enter) or fail
- begin
- data.next or fail
- descriptor = data.get
- data.next or fail
- value = data.get
- return Described.new(descriptor, value)
- ensure
- data.exit
- end
- end
-
- def put(data)
- described
- enter
- data.put(@descriptor)
- data.put(@value)
- end
- end
-
- # Convenience class for arrays
- #
- # Convenience class for arrays.
- #
- # An Array with methods to get and put the array in a Data object
- # as an AMQP array.
- class Array < ::Array
- def initialize(descriptor, type, elements=[])
- @descriptor, @type = descriptor, type
- super(elements.collect { |x| x })
- end
-
- attr_reader :descriptor, :type
-
- def ==(o) super; end
- def eql?(o)
- o.class == self.class && @descriptor == o.descriptor && @type ==
o.type &&
- super
- end
-
-
- def self.get(data)
- count, described, type = data.array
- data.enter or raise 'Not an array'
- begin
- descriptor = nil
- if described then
- data.next; descriptor = data.get
- end
- elements = []
- while data.next do; elements << data.get; end
- elements.size == count or
- raise "Array wrong length, expected #{count} but got
#{elements.size}"
- return Array.new(descriptor, type, elements)
- ensure
- data.exit
- end
- end
-
- def put(data)
- data.put_array(@descriptor, @type)
- data.enter
- begin
- data.put(@descriptor) if @descriptor
- elements.each { |e| data.put(e); }
- ensure
- data.exit
- end
- end
- end
-
- # Convenience class for arrays.
- #
- # An array with methods to get and put the in a Data object
- # as an AMQP list.
- class List < ::Array
-
- PROTON_TYPE_FOR_CLASS = {
- ::NilClass => Cproton::PN_NULL,
- ::TrueClass => Cproton::PN_BOOL,
- ::FalseClass => Cproton::PN_BOOL,
- ::Fixnum => Cproton::PN_INT,
- ::Bignum => Cproton::PN_LONG,
- ::String => Cproton::PN_STRING,
- ::Float => Cproton::PN_FLOAT
- }
-
- def initialize(elements = []) super; end
-
- def self.get(data)
- def fail; raise 'Not a list'; end
- size = data.list
- data.enter or fail
- begin
- elements = []
- while data.next do elements << data.get; end
- elements.size == size or
- raise "List wrong length, expected #{size} but got
#{elements.size}"
- return List.new(elements)
- ensure
- data.exit
- end
- end
-
- def put(data)
- data.put_list
- data.enter
- self.each do |e|
- etype = PROTON_TYPE_FOR_CLASS[e.class]
- puts "I think #{e} is of type #{etype}"
- etype = Type.by_code(etype)
- puts "The type helper is #{etype}"
- etype.put(data, e)
- end
- data.exit
- end
- end
-
# Convenience class for maps
#
# A Hash with methods to get and put the map in a Data object as an AMQP
@@ -898,49 +772,6 @@ module Qpid
def self.put(data, value); data.null; end
end
- # Information about AMQP types including how to get/put an object of that
- # type in a Data object.
- #
- # A convenience class is provided for each of the compound types
- # to allow get/put of those types as a single object.
- class Type
- attr_reader :code, :name
-
- def initialize(code,name,klass=nil)
- @code, @name, @klass = code,name,klass;
- @get,@put = name.intern,(name+"=").intern if !klass
- @@by_code ||= {}
- @@by_code[code] = self
- @@by_name ||= {}
- @@by_name[name] = self
- end
-
- def get(data)
- if @klass then @klass.send(:get, data)
- else data.send(@get); end
- end
-
- def put(data, value)
- if @klass then
- @klass.send(:put, data, value)
- else
- data.send(@put, value)
- end
- end
-
- def to_s() return name; end
- def self.by_name(name) @@by_name[name]; end
- def self.by_code(code) @@by_code[code]; end
-
-
- def self.get(data)
- if @klass then @klass.send(:get, data)
- else data.send(@get); end
- end
-
- def to_s; name; end
- end
-
# Get the current value as a single object.
def get
type.get(self);
@@ -951,33 +782,6 @@ module Qpid
type_.put(self, value);
end
- # Constants for all the supported types
- NULL = Type.new(Cproton::PN_NULL, "null", Null)
- BOOL = Type.new(Cproton::PN_BOOL, "bool")
- UBYTE = Type.new(Cproton::PN_UBYTE, "ubyte")
- BYTE = Type.new(Cproton::PN_BYTE, "byte")
- USHORT = Type.new(Cproton::PN_USHORT, "ushort")
- SHORT = Type.new(Cproton::PN_SHORT, "short")
- UINT = Type.new(Cproton::PN_UINT, "uint")
- INT = Type.new(Cproton::PN_INT, "int")
- CHAR = Type.new(Cproton::PN_CHAR, "char")
- ULONG = Type.new(Cproton::PN_ULONG, "ulong")
- LONG = Type.new(Cproton::PN_LONG, "long")
- TIMESTAMP = Type.new(Cproton::PN_TIMESTAMP, "timestamp")
- FLOAT = Type.new(Cproton::PN_FLOAT, "float")
- DOUBLE = Type.new(Cproton::PN_DOUBLE, "double")
- DECIMAL32 = Type.new(Cproton::PN_DECIMAL32, "decimal32")
- DECIMAL64 = Type.new(Cproton::PN_DECIMAL64, "decimal64")
- DECIMAL128 = Type.new(Cproton::PN_DECIMAL128, "decimal128")
- UUID = Type.new(Cproton::PN_UUID, "uuid")
- BINARY = Type.new(Cproton::PN_BINARY, "binary")
- STRING = Type.new(Cproton::PN_STRING, "string")
- SYMBOL = Type.new(Cproton::PN_SYMBOL, "symbol")
- DESCRIBED = Type.new(Cproton::PN_DESCRIBED, "described", Described)
- ARRAY = Type.new(Cproton::PN_ARRAY, "array", Array)
- LIST = Type.new(Cproton::PN_LIST, "list", List)
- MAP = Type.new(Cproton::PN_MAP, "map", Map)
-
private
def valid_uuid?(value)
Added: qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/described.rb
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/described.rb?rev=1488342&view=auto
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/described.rb
(added)
+++ qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/described.rb Fri
May 31 18:13:12 2013
@@ -0,0 +1,72 @@
+#
+# 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.
+#
+
+module Qpid # :nodoc:
+
+ module Proton # :nodoc:
+
+ class Described
+
+ attr_reader :descriptor
+ attr_reader :value
+
+ def initialize(descriptor, value)
+ @descriptor = descriptor
+ @value = value
+ end
+
+ # Retrieves the descriptor and value from the supplied Data object.
+ #
+ # ==== Arguments
+ #
+ # * data - the Qpid::Proton::Data instance
+ #
+ def self.get(data)
+ type = data.next
+ raise TypeError, "not a described type" unless type == Mapping.SYMBOL
+ descriptor = data.symbol
+ type = data.next
+ raise TypeError, "not a described type" unless type == Mapping.STRING
+ value = data.string
+ Described.new(descriptor, value)
+ end
+
+ # Puts the description into the Data object.
+ #
+ # ==== Arguments
+ #
+ # * data - the Qpid::Proton::Data instance
+ #
+ # ==== Examples
+ #
+ # described = Qpid::Proton::Described.new("my-descriptor", "the value")
+ # data = Qpid::Proton::Data.new
+ # ...
+ # described.put(data)
+ #
+ def put(data)
+ data.symbol = @descriptor
+ data.string = @value
+ end
+
+ end
+
+ end
+
+end
Added: qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/mapping.rb
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/mapping.rb?rev=1488342&view=auto
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/mapping.rb (added)
+++ qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/mapping.rb Fri May
31 18:13:12 2013
@@ -0,0 +1,109 @@
+#
+# 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.
+#
+
+module Qpid # :nodoc:
+
+ module Proton # :nodoc:
+
+ # Maps between Proton types and their Ruby native language counterparts.
+ #
+ class Mapping
+
+ attr_reader :code
+ attr_reader :put_method
+ attr_reader :get_method
+
+ # Creates a new mapping.
+ #
+ # ==== Arguments
+ #
+ # * code - the AMQP code for this type
+ # * name - the AMQP name for this type
+ # * klasses - the Ruby classes for this type
+ def initialize(code, name, klasses = nil)
+ @code = code
+ @name = name
+
+ @@by_preferred ||= {}
+ @@by_code ||= {}
+ @@by_code["#{code}"] = self
+ @@by_name ||= {}
+ @@by_name[name] = self
+ @@by_class ||= {}
+
+ unless klasses.nil?
+ klasses.each do |klass|
+ raise "entry exists for #{klass}" if @@by_class.keys.include? klass
+ @@by_class[klass] = self unless klass.nil?
+ end
+ end
+
+ @put_method = (name + "=").intern
+ @get_method = name.intern
+ end
+
+ def to_s; @name; end
+
+ def put(data, value)
+ data.send(@put_method, value)
+ end
+
+ def get(data)
+ data.send(@get_method)
+ end
+
+ def self.for_class(klass) # :nodoc:
+ @@by_class[klass]
+ end
+
+ def self.for_code(code)
+ @@by_code["#{code}"]
+ end
+
+ end
+
+ NULL = Mapping.new(Cproton::PN_NULL, "null", [NilClass])
+ BOOL = Mapping.new(Cproton::PN_BOOL, "bool", [TrueClass, FalseClass])
+ UBYTE = Mapping.new(Cproton::PN_UBYTE, "ubyte")
+ BYTE = Mapping.new(Cproton::PN_BYTE, "byte")
+ USHORT = Mapping.new(Cproton::PN_USHORT, "ushort")
+ SHORT = Mapping.new(Cproton::PN_SHORT, "short")
+ UINT = Mapping.new(Cproton::PN_UINT, "uint")
+ INT = Mapping.new(Cproton::PN_INT, "int")
+ CHAR = Mapping.new(Cproton::PN_CHAR, "char")
+ ULONG = Mapping.new(Cproton::PN_ULONG, "ulong")
+ LONG = Mapping.new(Cproton::PN_LONG, "long", [Fixnum, Bignum])
+ TIMESTAMP = Mapping.new(Cproton::PN_TIMESTAMP, "timestamp", [Date])
+ FLOAT = Mapping.new(Cproton::PN_FLOAT, "float")
+ DOUBLE = Mapping.new(Cproton::PN_DOUBLE, "double", [Float])
+ DECIMAL32 = Mapping.new(Cproton::PN_DECIMAL32, "decimal32")
+ DECIMAL64 = Mapping.new(Cproton::PN_DECIMAL64, "decimal64")
+ DECIMAL128 = Mapping.new(Cproton::PN_DECIMAL128, "decimal128")
+ UUID = Mapping.new(Cproton::PN_UUID, "uuid")
+ BINARY = Mapping.new(Cproton::PN_BINARY, "binary")
+ STRING = Mapping.new(Cproton::PN_STRING, "string", [String])
+ SYMBOL = Mapping.new(Cproton::PN_SYMBOL, "symbol")
+ DESCRIBED = Mapping.new(Cproton::PN_DESCRIBED, "described",
[Qpid::Proton::Described])
+ ARRAY = Mapping.new(Cproton::PN_ARRAY, "array")
+ LIST = Mapping.new(Cproton::PN_LIST, "list", [::Array])
+ MAP = Mapping.new(Cproton::PN_MAP, "map", [::Hash])
+
+ end
+
+end
Added: qpid/proton/trunk/proton-c/bindings/ruby/spec/qpid/proton/array_spec.rb
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/spec/qpid/proton/array_spec.rb?rev=1488342&view=auto
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/ruby/spec/qpid/proton/array_spec.rb
(added)
+++ qpid/proton/trunk/proton-c/bindings/ruby/spec/qpid/proton/array_spec.rb Fri
May 31 18:13:12 2013
@@ -0,0 +1,114 @@
+#
+# 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 "spec_helper"
+
+describe "The extended array type" do
+
+ before :each do
+ @data = Qpid::Proton::Data.new
+ @list = random_list(rand(100))
+ @undescribed = random_array(rand(100))
+ @description = random_string(128)
+ @described = random_array(rand(100), true, @description)
+ end
+
+ it "can be created like a normal array" do
+ value = []
+
+ value.should respond_to :proton_put
+ value.should respond_to :proton_array_header
+ value.class.should respond_to :proton_get
+ value.should respond_to :proton_described?
+ end
+
+ it "raises an error when putting into a nil Data object" do
+ expect {
+ @list.proton_put(nil)
+ }.to raise_error
+ end
+
+ it "raises an error when getting from a nil Data object" do
+ expect {
+ Array.proton_get(nil)
+ }.to raise_error(TypeError)
+ end
+
+ it "raises an error when the data object is empty" do
+ expect {
+ Array.proton_get(@data)
+ }.to raise_error(TypeError)
+ end
+
+ it "raises an error when the current object is not a list" do
+ @data.string = random_string(128)
+ @data.rewind
+
+ expect {
+ Array.proton_get(@data)
+ }.to raise_error(TypeError)
+ end
+
+ it "does not have an array header when it's a simple list" do
+ @list.proton_described?.should be_false
+ end
+
+ it "can be put into a Data object as a list" do
+ @list.proton_put(@data)
+ result = Array.proton_get(@data)
+ result.should =~ @list
+ result.proton_array_header.should be_nil
+ end
+
+ it "has an array header when it's an AMQP array" do
+ @undescribed.proton_array_header.should_not be_nil
+ @described.proton_array_header.should_not be_nil
+ end
+
+ it "raises an error when the elements of an Array are dissimilar and is put
into a Data object" do
+ value = []
+ value.proton_array_header =
Qpid::Proton::ArrayHeader.new(Qpid::Proton::INT)
+ value << random_string(16)
+
+ expect {
+ value.proton_put(@data)
+ }.to raise_error(TypeError)
+ end
+
+ it "can be put into a Data object as an undescribed array" do
+ @undescribed.proton_put(@data)
+ result = Array.proton_get(@data)
+ be_close_array(@undescribed, result)
+
+ result.proton_array_header.should_not be_nil
+ result.proton_array_header.should == @undescribed.proton_array_header
+ result.proton_array_header.described?.should be_false
+ end
+
+ it "can be put into a Data object as a described array" do
+ @described.proton_put(@data)
+ result = Array.proton_get(@data)
+ be_close_array(@described, result)
+
+ result.proton_array_header.should_not be_nil
+ result.proton_array_header.should == @described.proton_array_header
+ result.proton_array_header.described?.should be_true
+ end
+
+end
Modified: qpid/proton/trunk/proton-c/bindings/ruby/spec/spec_helper.rb
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/spec/spec_helper.rb?rev=1488342&r1=1488341&r2=1488342&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/ruby/spec/spec_helper.rb (original)
+++ qpid/proton/trunk/proton-c/bindings/ruby/spec/spec_helper.rb Fri May 31
18:13:12 2013
@@ -30,6 +30,7 @@ rescue
puts "simplecov not available"
end
+require "securerandom"
require "qpid_proton"
# Generates a random string of the specified length
@@ -37,4 +38,74 @@ def random_string(length = 8)
(0...length).map{65.+(rand(25)).chr}.join
end
-require "securerandom"
+# Generates a random list of the specified length.
+def random_list(length)
+ result = []
+ (0...length).each do |element|
+ type = rand(8192) % 4
+ low = rand(512)
+ high = rand(8192)
+
+ case
+ when element == 0 then result << rand(128)
+ when element == 1 then result << random_string(rand(128))
+ when element == 2 then result << rand * (low - high).abs + low
+ when element == 3 then result << SecureRandom.uuid
+ end
+ end
+
+ return result
+end
+
+# Generates a random array of a random type.
+# Returns both the array and the type.
+def random_array(length, described = false, description = nil)
+ result = []
+ type = rand(128) % 4
+ low = rand(512)
+ high = rand(8192)
+
+ (0...length).each do |element|
+ case
+ when type == 0 then result << rand(1024)
+ when type == 1 then result << random_string(rand(128))
+ when type == 2 then result << rand * (low - high).abs + low
+ when type == 3 then result << SecureRandom.uuid
+ end
+ end
+
+ # create the array header
+ case
+ when type == 0 then type = Qpid::Proton::INT
+ when type == 1 then type = Qpid::Proton::STRING
+ when type == 2 then type = Qpid::Proton::FLOAT
+ when type == 3 then type = Qpid::Proton::UUID
+ end
+
+ result.proton_array_header = Qpid::Proton::ArrayHeader.new(type, description)
+
+ return result
+end
+
+# taken from
http://stackoverflow.com/questions/6855944/rounding-problem-with-rspec-tests-when-comparing-float-arrays
+RSpec::Matchers.define :be_close_array do |expected, truth|
+ match do |actual|
+ same = 0
+ for i in 0..actual.length-1
+ same +=1 if actual[i].round(truth) == expected[i].round(truth)
+ end
+ same == actual.length
+ end
+
+ failure_message_for_should do |actual|
+ "expected that #{actual} would be close to #{expected}"
+ end
+
+ failure_message_for_should_not do |actual|
+ "expected that #{actual} would not be close to #{expected}"
+ end
+
+ description do
+ "be a close to #{expected}"
+ end
+end
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]