Skip to content

Commit

Permalink
Support new additions to Regress test lib [merges 'update-regress-tes…
Browse files Browse the repository at this point in the history
…ts']
  • Loading branch information
mvz committed Nov 26, 2014
2 parents eb118f2 + 4a6d3f7 commit 984fe6e
Show file tree
Hide file tree
Showing 4 changed files with 224 additions and 26 deletions.
82 changes: 56 additions & 26 deletions lib/gir_ffi/builders/callback_argument_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,41 @@ def pre_converted_name
@pre_converted_name ||= new_variable
end

def out_parameter_name
@out_parameter_name ||=
if direction == :inout
new_variable
else
pre_converted_name
end
end

def call_argument_name
if direction == :in
if [:in, :inout].include? direction
pre_converted_name unless array_arg
end
end

def capture_variable_name
result_name if direction == :out
result_name if [:out, :inout].include? direction unless array_arg
end

def pre_conversion
case direction
when :in
["#{pre_converted_name} = #{pre_convertor.conversion}"]
[ingoing_pre_conversion]
when :out
["#{pre_converted_name} = #{out_parameter_preparation}"]
[out_parameter_preparation]
when :inout
[out_parameter_preparation, ingoing_pre_conversion]
when :error
[
"#{pre_converted_name} = #{out_parameter_preparation}",
"begin"
]
[out_parameter_preparation, "begin"]
end
end

def post_conversion
case direction
when :out
when :out, :inout
[outgoing_post_conversion]
when :error
[
Expand All @@ -61,50 +69,72 @@ def result_name
@result_name ||= new_variable
end

def pre_convertor_argument
if direction == :inout
"#{out_parameter_name}.to_value"
else
method_argument_name
end
end

def pre_convertor
@pre_convertor ||= if closure?
ClosureConvertor.new(method_argument_name)
ClosureConvertor.new(pre_convertor_argument)
elsif needs_c_to_ruby_conversion?
CToRubyConvertor.new(type_info,
method_argument_name,
pre_convertor_argument,
length_argument_name)
else
NullConvertor.new(method_argument_name)
NullConvertor.new(pre_convertor_argument)
end
end

def needs_c_to_ruby_conversion?
type_info.needs_c_to_ruby_conversion_for_callbacks?
end

def ingoing_pre_conversion
"#{pre_converted_name} = #{pre_convertor.conversion}"
end

def outgoing_post_conversion
"#{pre_converted_name}.set_value #{outgoing_convertor.conversion}"
"#{out_parameter_name}.set_value #{post_convertor.conversion}"
end

def outgoing_convertor
@outgoing_convertor ||= if type_info.needs_ruby_to_c_conversion_for_callbacks?
RubyToCConvertor.new(type_info, result_name)
else
NullConvertor.new(result_name)
end
def post_convertor
@post_convertor ||= if type_info.needs_ruby_to_c_conversion_for_callbacks?
RubyToCConvertor.new(type_info, post_convertor_argument)
else
NullConvertor.new(post_convertor_argument)
end
end

def out_parameter_preparation
type_spec = type_info.tag_or_class
if allocated_by_us?
"GirFFI::InOutPointer.new(#{type_spec[1].inspect})" \
".tap { |ptr| #{method_argument_name}.put_pointer 0, ptr }"
def post_convertor_argument
if array_arg
"#{array_arg.capture_variable_name}.length"
else
"GirFFI::InOutPointer.new(#{type_spec.inspect}, #{method_argument_name})"
result_name
end
end

def out_parameter_preparation
type_spec = type_info.tag_or_class
value = if allocated_by_us?
"GirFFI::InOutPointer.new(#{type_spec[1].inspect})" \
".tap { |ptr| #{method_argument_name}.put_pointer 0, ptr }"
else
"GirFFI::InOutPointer.new(#{type_spec.inspect}, #{method_argument_name})"
end
"#{out_parameter_name} = #{value}"
end

# Check if an out argument needs to be allocated by us, the callee. Since
# caller_allocates is false by default, we must also check that the type
# is a pointer. For example, an out parameter of type gint8* will always
# be allocate by the caller.
def allocated_by_us?
!@arginfo.caller_allocates? &&
direction == :out &&
!@arginfo.caller_allocates? &&
type_info.pointer? &&
![:object, :zero_terminated].include?(specialized_type_tag)
end
Expand Down
65 changes: 65 additions & 0 deletions test/gir_ffi/builders/callback_argument_builder_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,69 @@
]
end
end

describe "for an argument with direction :inout" do
let(:callback_info) {
get_introspection_data("Regress",
"TestCallbackArrayInOut")
}
let(:array_arg_info) { callback_info.args[0] }
let(:array_arg_builder) {
GirFFI::Builders::CallbackArgumentBuilder.new(var_gen, array_arg_info)
}
let(:length_arg_info) { callback_info.args[1] }
let(:length_arg_builder) {
GirFFI::Builders::CallbackArgumentBuilder.new(var_gen, length_arg_info)
}

before do
skip unless callback_info
length_arg_builder.array_arg = array_arg_builder
array_arg_builder.length_arg = length_arg_builder
end

describe "for arrays with a length argument" do
it "provides a call argument name" do
array_arg_builder.call_argument_name.must_equal "_v1"
end

it "provides a capture variable name" do
array_arg_builder.capture_variable_name.must_equal "_v1"
end

it "has the correct value for #pre_conversion" do
array_arg_builder.pre_conversion.
must_equal ["_v1 = GirFFI::InOutPointer.new([:pointer, :c], ints)",
"_v2 = GirFFI::SizedArray.wrap(:gint32, _v3, _v1.to_value)"]
end

it "has the correct value for #post_conversion" do
array_arg_builder.pre_conversion
array_arg_builder.post_conversion.
must_equal ["_v1.set_value GirFFI::SizedArray.from(:gint32, -1, _v4)"]
end
end

describe "for an array length argument" do
it "does not provide a call argument name" do
length_arg_builder.call_argument_name.must_be_nil
end

it "does not provide a capture variable name" do
length_arg_builder.capture_variable_name.must_be_nil
end

it "has the correct value for #pre_conversion" do
length_arg_builder.pre_conversion.
must_equal ["_v1 = GirFFI::InOutPointer.new(:gint32, length)",
"_v2 = _v1.to_value"]
end

it "has the correct value for #post_conversion" do
length_arg_builder.pre_conversion
length_arg_builder.post_conversion.
must_equal ["_v1.set_value _v3.length"]
end
end
end
end
23 changes: 23 additions & 0 deletions test/gir_ffi/builders/callback_builder_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,28 @@ def self.call_with_argument_mapping(_proc, a)
builder.mapping_method_definition.must_equal expected
end
end

describe "for a callback with an inout array argument" do
let(:callback_info) {
get_introspection_data("Regress",
"TestCallbackArrayInOut")
}
it "returns a valid mapping method" do
skip unless callback_info
expected = <<-CODE.reset_indentation
def self.call_with_argument_mapping(_proc, ints, length)
_v1 = GirFFI::InOutPointer.new(:gint32, length)
_v2 = _v1.to_value
_v3 = GirFFI::InOutPointer.new([:pointer, :c], ints)
_v4 = GirFFI::SizedArray.wrap(:gint32, _v2, _v3.to_value)
_v5 = _proc.call(_v4)
_v1.set_value _v5.length
_v3.set_value GirFFI::SizedArray.from(:gint32, -1, _v5)
end
CODE

builder.mapping_method_definition.must_equal expected
end
end
end
end
80 changes: 80 additions & 0 deletions test/integration/generated_regress_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,25 @@ class << Regress::Lib
end
end

it "has the constant BOOL_CONSTANT" do
skip unless get_introspection_data 'Regress', 'BOOL_CONSTANT'
Regress::BOOL_CONSTANT.must_equal true
end

it "has the constant DOUBLE_CONSTANT" do
assert_equal 44.22, Regress::DOUBLE_CONSTANT
end

it "has the constant GI_SCANNER_ELSE" do
skip unless get_introspection_data 'Regress', 'GI_SCANNER_ELSE'
Regress::GI_SCANNER_ELSE.must_equal 3
end

it "has the constant GI_SCANNER_IFDEF" do
skip unless get_introspection_data 'Regress', 'GI_SCANNER_IFDEF'
Regress::GI_SCANNER_IFDEF.must_equal 3
end

it "has the constant GUINT64_CONSTANT" do
skip unless get_introspection_data 'Regress', 'GUINT64_CONSTANT'
Regress::GUINT64_CONSTANT.must_equal 18_446_744_073_709_551_615
Expand Down Expand Up @@ -214,6 +229,14 @@ class << Regress::Lib
assert Regress::TestBoxed.get_gtype > 0
end

it "has a working method #_not_a_method" do
skip unless get_method_introspection_data('Regress', 'TestBoxed', '_not_a_method')
# FIXME: This method has been moved to a function. Should we still expose
# it as a method?
instance._not_a_method
pass
end

it "has a working method #copy" do
tb2 = instance.copy
assert_instance_of Regress::TestBoxed, tb2
Expand Down Expand Up @@ -629,6 +652,14 @@ class << Regress::Lib
assert_equal 2, a
end

it "has a working method #instance_method_full" do
skip unless get_method_introspection_data('Regress', 'TestObj', 'instance_method_full')
instance.instance_method_full
# FIXME: Is this the behavior we want, or do we want to increase the
# refcount beforehand?
ref_count(instance).must_equal 0
end

it "has a working method #set_bare" do
obj = Regress::TestObj.new_from_file("bar")
instance.set_bare obj
Expand Down Expand Up @@ -924,6 +955,32 @@ class << Regress::Lib
end
end

describe "its 'pptrarray' property" do
it "can be retrieved with #get_property" do
skip 'pptrarray is not implemented properly'
instance.get_property("pptrarray").must_be_nil
end

it "can be retrieved with #pptrarray" do
skip 'pptrarray is not implemented properly'
instance.pptrarray.must_be_nil
end

it "can be set with #set_property" do
skip 'pptrarray is not implemented properly'
arr = Regress.test_garray_container_return
instance.set_property 'pptrarray', arr
instance.pptrarray.must_be :==, arr
end

it "can be set with #pptrarray=" do
skip 'pptrarray is not implemented properly'
arr = Regress.test_garray_container_return
instance.pptrarray = arr
instance.pptrarray.must_be :==, arr
instance.get_property("pptrarray").must_be :==, arr
end
end
describe "its 'string' property" do
it "can be retrieved with #get_property" do
assert_nil instance.get_property("string").get_value
Expand Down Expand Up @@ -1760,6 +1817,16 @@ class << Regress::Lib
assert_equal "[gboolean,gint64,]", Regress.test_array_gtype_in([t1, t2])
end

it "has a working function #test_array_inout_callback" do
skip unless get_introspection_data 'Regress', 'test_array_inout_callback'
Regress.test_array_inout_callback proc { |ints|
arr = ints.to_a
arr.shift
arr
}
pass
end

it "has a working function #test_array_int_full_out" do
Regress.test_array_int_full_out.must_be :==, [0, 1, 2, 3, 4]
end
Expand Down Expand Up @@ -1816,6 +1883,19 @@ class << Regress::Lib
assert_equal true, Regress.test_boolean_true(true)
end

it "has a working function #test_boxeds_not_a_method" do
skip unless get_introspection_data 'Regress', 'test_boxeds_not_a_method'
boxed = Regress::TestBoxed.new_alternative_constructor1 123
Regress.test_boxeds_not_a_method boxed
pass
end

it "has a working function #test_boxeds_not_a_static" do
skip unless get_introspection_data 'Regress', 'test_boxeds_not_a_static'
Regress.test_boxeds_not_a_static
pass
end

it "has a working function #test_cairo_context_full_return" do
ct = Regress.test_cairo_context_full_return
assert_instance_of Cairo::Context, ct
Expand Down

0 comments on commit 984fe6e

Please sign in to comment.