require 'gir_ffi_test_helper' describe GirFFI::Builders::FunctionBuilder do describe '#method_definition' do let(:builder) { GirFFI::Builders::FunctionBuilder.new function_info } let(:code) { builder.method_definition } describe 'for Regress:test_array_fixed_out_objects' do let(:function_info) { get_introspection_data 'Regress', 'test_array_fixed_out_objects' } it 'builds a correct definition' do skip unless function_info code.must_equal <<-CODE.reset_indentation def self.test_array_fixed_out_objects _v1 = GirFFI::InOutPointer.for [:pointer, :c] Regress::Lib.regress_test_array_fixed_out_objects _v1 _v2 = GirFFI::SizedArray.wrap([:pointer, Regress::TestObj], 2, _v1.to_value) return _v2 end CODE end end describe 'for functions having a linked length argument' do let(:function_info) { get_introspection_data 'Regress', 'test_array_gint16_in' } it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def self.test_array_gint16_in(ints) n_ints = ints.nil? ? 0 : ints.length _v1 = n_ints _v2 = GirFFI::SizedArray.from(:gint16, -1, ints) _v3 = Regress::Lib.regress_test_array_gint16_in _v1, _v2 return _v3 end CODE end end describe 'for functions with callbacks' do let(:function_info) { get_introspection_data 'Regress', 'test_callback_destroy_notify' } it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def self.test_callback_destroy_notify(&callback) _v1 = Regress::TestCallbackUserData.from(callback) _v2 = GirFFI::InPointer.from_closure_data(_v1.object_id) _v3 = GLib::DestroyNotify.default _v4 = Regress::Lib.regress_test_callback_destroy_notify _v1, _v2, _v3 return _v4 end CODE end end describe 'for functions that take a GValue' do let(:function_info) { get_introspection_data 'GIMarshallingTests', 'gvalue_in' } it 'creates a call to GObject::Value#from' do code.must_equal <<-CODE.reset_indentation def self.gvalue_in(value) _v1 = GObject::Value.from(value) GIMarshallingTests::Lib.gi_marshalling_tests_gvalue_in _v1 end CODE end end describe 'for functions that return a GValue' do let(:function_info) { get_introspection_data 'GIMarshallingTests', 'gvalue_return' } it 'creates a call to #get_value' do code.must_equal <<-CODE.reset_indentation def self.gvalue_return _v1 = GIMarshallingTests::Lib.gi_marshalling_tests_gvalue_return _v2 = GObject::Value.wrap(_v1).get_value return _v2 end CODE end end describe 'for functions that have a GValue out argument' do let(:function_info) { get_introspection_data 'GIMarshallingTests', 'gvalue_out' } it 'creates a call to #get_value' do code.must_equal <<-CODE.reset_indentation def self.gvalue_out _v1 = GirFFI::InOutPointer.for [:pointer, GObject::Value] GIMarshallingTests::Lib.gi_marshalling_tests_gvalue_out _v1 _v2 = GObject::Value.wrap(_v1.to_value).get_value return _v2 end CODE end end describe 'for functions that have a caller-allocated GValue out argument' do let(:function_info) { get_introspection_data 'GIMarshallingTests', 'gvalue_out_caller_allocates' } it 'creates a call to #get_value' do skip unless function_info code.must_equal <<-CODE.reset_indentation def self.gvalue_out_caller_allocates _v1 = GObject::Value.new GIMarshallingTests::Lib.gi_marshalling_tests_gvalue_out_caller_allocates _v1 _v2 = _v1.get_value return _v2 end CODE end end describe 'for functions with a nullable input array' do let(:function_info) { get_introspection_data 'Regress', 'test_array_int_null_in' } it 'builds correct definition' do code.must_equal <<-CODE.reset_indentation def self.test_array_int_null_in(arr) len = arr.nil? ? 0 : arr.length _v1 = len _v2 = GirFFI::SizedArray.from(:gint32, -1, arr) Regress::Lib.regress_test_array_int_null_in _v2, _v1 end CODE end end describe 'for functions with a nullable output array' do let(:function_info) { get_introspection_data 'Regress', 'test_array_int_null_out' } it 'builds correct definition' do code.must_equal <<-CODE.reset_indentation def self.test_array_int_null_out _v1 = GirFFI::InOutPointer.for :gint32 _v2 = GirFFI::InOutPointer.for [:pointer, :c] Regress::Lib.regress_test_array_int_null_out _v2, _v1 _v3 = _v1.to_value _v4 = GirFFI::SizedArray.wrap(:gint32, _v3, _v2.to_value) return _v4 end CODE end end describe 'for a method with an inout array with size argument' do let(:function_info) { get_method_introspection_data 'GIMarshallingTests', 'Object', 'method_array_inout' } it 'builds the correct definition' do code.must_equal <<-CODE.reset_indentation def method_array_inout(ints) length = ints.nil? ? 0 : ints.length _v1 = GirFFI::InOutPointer.for :gint32 _v1.set_value length _v2 = GirFFI::InOutPointer.for [:pointer, :c] _v2.set_value GirFFI::SizedArray.from(:gint32, -1, ints) GIMarshallingTests::Lib.gi_marshalling_tests_object_method_array_inout self, _v2, _v1 _v3 = _v1.to_value _v4 = GirFFI::SizedArray.wrap(:gint32, _v3, _v2.to_value) return _v4 end CODE end end describe 'for a simple method' do let(:function_info) { get_method_introspection_data 'Regress', 'TestObj', 'instance_method' } it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def instance_method _v1 = Regress::Lib.regress_test_obj_instance_method self return _v1 end CODE end end describe 'for GLib::Variant.get_strv' do let(:function_info) { get_method_introspection_data 'GLib', 'Variant', 'get_strv' } it 'builds a correct definition' do size_type = ":guint#{FFI.type_size(:size_t) * 8}" code.must_equal <<-CODE.reset_indentation def get_strv _v1 = GirFFI::InOutPointer.for #{size_type} _v2 = GLib::Lib.g_variant_get_strv self, _v1 _v3 = GLib::Strv.wrap(_v2) return _v3 end CODE end end describe 'for Regress.has_parameter_named_attrs' do let(:function_info) { get_introspection_data 'Regress', 'has_parameter_named_attrs' } it 'builds a correct definition' do skip unless function_info code.must_equal <<-CODE.reset_indentation def self.has_parameter_named_attrs(foo, attributes) _v1 = foo GirFFI::ArgHelper.check_fixed_array_size 32, attributes, \"attributes\" _v2 = GirFFI::SizedArray.from([:pointer, :guint32], 32, attributes) Regress::Lib.regress_has_parameter_named_attrs _v1, _v2 end CODE end end describe 'for GIMarshallingTests::Object#method_int8_arg_and_out_callee' do let(:function_info) do get_method_introspection_data('GIMarshallingTests', 'Object', 'method_int8_arg_and_out_callee') end it 'builds a correct definition' do skip unless function_info code.must_equal <<-CODE.reset_indentation def method_int8_arg_and_out_callee(arg) _v1 = arg _v2 = GirFFI::InOutPointer.for [:pointer, :gint8] GIMarshallingTests::Lib.gi_marshalling_tests_object_method_int8_arg_and_out_callee self, _v1, _v2 _v3 = GirFFI::InOutPointer.new(:gint8, _v2.to_value).to_value return _v3 end CODE end end describe 'for GIMarshallingTests::Object.full_inout' do let(:function_info) do get_method_introspection_data('GIMarshallingTests', 'Object', 'full_inout') end it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def self.full_inout(object) _v1 = GirFFI::InOutPointer.for [:pointer, GIMarshallingTests::Object] _v1.set_value GIMarshallingTests::Object.from(object.ref) GIMarshallingTests::Lib.gi_marshalling_tests_object_full_inout _v1 _v2 = GIMarshallingTests::Object.wrap(_v1.to_value) return _v2 end CODE end end describe 'for Regress::TestObj#instance_method_full' do let(:function_info) do get_method_introspection_data('Regress', 'TestObj', 'instance_method_full') end it 'builds a correct definition including self.ref' do skip unless function_info code.must_equal <<-CODE.reset_indentation def instance_method_full Regress::Lib.regress_test_obj_instance_method_full self.ref end CODE end end end end