gir_ffi-0.11.4/0000755000004100000410000000000013170036060013226 5ustar www-datawww-datagir_ffi-0.11.4/Rakefile0000644000004100000410000000020113170036060014664 0ustar www-datawww-datarequire 'rake/clean' require 'bundler/gem_tasks' load 'tasks/test.rake' task default: 'test:all' task default: 'test:features' gir_ffi-0.11.4/Gemfile0000644000004100000410000000055513170036060014526 0ustar www-datawww-data# frozen_string_literal: true source 'https://rubygems.org' # The gem's dependencies are specified in gir_ffi.gemspec gemspec if ENV['CI'] if ENV['TRAVIS_RUBY_VERSION'] == '2.2' gem 'coveralls', group: :development end else gem 'pry', '~> 0.10.4', group: :local_development gem 'simplecov', '~> 0.15.0', group: :local_development, platform: :mri end gir_ffi-0.11.4/examples/0000755000004100000410000000000013170036060015044 5ustar www-datawww-datagir_ffi-0.11.4/examples/clutter.rb0000644000004100000410000000460213170036060017055 0ustar www-datawww-data$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib') require 'gir_ffi' GirFFI.setup :Clutter GirFFI.setup :GdkPixbuf class PhotoWall < Clutter::Stage STAGE_WIDTH = 800 STAGE_HEIGHT = 600 THUMBNAIL_SIZE = 200 ROW_COUNT = STAGE_HEIGHT / THUMBNAIL_SIZE COLUMN_COUNT = STAGE_WIDTH / THUMBNAIL_SIZE FOCUS_DEPTH = 100.0 UNFOCUS_DEPTH = 0.0 def self.create_for path stage = PhotoWall.new stage.instance_eval do @path = path @bricks = [] @images = Dir["#{@path}/**/*.{jpg,png}"] @focus = nil set_title "A PhotoWall" set_size STAGE_WIDTH, STAGE_HEIGHT ROW_COUNT.times do |row| COLUMN_COUNT.times do |column| break unless @images[row*COLUMN_COUNT + column] puts "Adding #{@images[row*COLUMN_COUNT + column]}" brick = LittleBrick.new_from_file(@images[row*COLUMN_COUNT + column], row, column) add_actor brick @bricks << brick end end show_all end GObject.signal_connect(stage, "destroy") { Clutter.main_quit } stage end class LittleBrick < Clutter::Actor attr_accessor :row, :col def self.new_from_file fname, row = 0, col = 0 brick = new image = Clutter::Image.new picture = GdkPixbuf::Pixbuf.new_from_file fname image.set_data(picture.get_pixels, picture.has_alpha ? :rgba_8888 : :rgb_888, picture.width, picture.height, picture.rowstride) brick.set_content image brick.instance_eval do @row = row @col = col set_size THUMBNAIL_SIZE, THUMBNAIL_SIZE set_position col * THUMBNAIL_SIZE, row * THUMBNAIL_SIZE set_reactive true end @@focus = nil GObject.signal_connect brick, "button-press-event" do |a_brick| if @@focus @@focus.unfocus else brick.focus end end brick end def focus @@focus = self set_position 0, 0 set_size STAGE_WIDTH, STAGE_HEIGHT raise_top end def unfocus set_position @col * THUMBNAIL_SIZE, @row * THUMBNAIL_SIZE set_size THUMBNAIL_SIZE, THUMBNAIL_SIZE @@focus = nil end end end Clutter.init [] picture_directory = GLib.get_user_special_dir :directory_pictures PhotoWall.create_for picture_directory Clutter.main gir_ffi-0.11.4/examples/main_loop.rb0000644000004100000410000000011313170036060017341 0ustar www-datawww-datarequire 'gir_ffi' main_loop = GLib::MainLoop.new nil, false main_loop.run gir_ffi-0.11.4/gir_ffi.gemspec0000644000004100000410000003531413170036060016206 0ustar www-datawww-data######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- Gem::Specification.new do |s| s.name = "gir_ffi" s.version = "0.11.4" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Matijs van Zuijlen"] s.date = "2017-09-19" s.description = " GirFFI creates bindings for GObject-based libraries at runtime based on introspection\n data provided by the GObject Introspection Repository (GIR) system. Bindings are created\n at runtime and use FFI to interface with the C libraries. In cases where the GIR does not\n provide enough or correct information to create sane bindings, overrides may be created.\n" s.email = ["matijs@matijs.net"] s.extra_rdoc_files = ["Changelog.md", "DESIGN.md", "README.md", "TODO.md"] s.files = ["COPYING.LIB", "Changelog.md", "DESIGN.md", "Gemfile", "README.md", "Rakefile", "TODO.md", "examples/clutter.rb", "examples/main_loop.rb", "lib/ffi-glib.rb", "lib/ffi-glib/array.rb", "lib/ffi-glib/array_methods.rb", "lib/ffi-glib/byte_array.rb", "lib/ffi-glib/bytes.rb", "lib/ffi-glib/container_class_methods.rb", "lib/ffi-glib/destroy_notify.rb", "lib/ffi-glib/error.rb", "lib/ffi-glib/hash_table.rb", "lib/ffi-glib/iconv.rb", "lib/ffi-glib/list.rb", "lib/ffi-glib/list_methods.rb", "lib/ffi-glib/main_loop.rb", "lib/ffi-glib/ptr_array.rb", "lib/ffi-glib/s_list.rb", "lib/ffi-glib/strv.rb", "lib/ffi-glib/variant.rb", "lib/ffi-gobject.rb", "lib/ffi-gobject/closure.rb", "lib/ffi-gobject/initially_unowned.rb", "lib/ffi-gobject/object.rb", "lib/ffi-gobject/object_class.rb", "lib/ffi-gobject/param_spec.rb", "lib/ffi-gobject/ruby_closure.rb", "lib/ffi-gobject/value.rb", "lib/ffi-gobject_introspection.rb", "lib/ffi-gobject_introspection/g_error.rb", "lib/ffi-gobject_introspection/gobject_type_init.rb", "lib/ffi-gobject_introspection/i_arg_info.rb", "lib/ffi-gobject_introspection/i_base_info.rb", "lib/ffi-gobject_introspection/i_callable_info.rb", "lib/ffi-gobject_introspection/i_callback_info.rb", "lib/ffi-gobject_introspection/i_constant_info.rb", "lib/ffi-gobject_introspection/i_enum_info.rb", "lib/ffi-gobject_introspection/i_field_info.rb", "lib/ffi-gobject_introspection/i_flags_info.rb", "lib/ffi-gobject_introspection/i_function_info.rb", "lib/ffi-gobject_introspection/i_interface_info.rb", "lib/ffi-gobject_introspection/i_object_info.rb", "lib/ffi-gobject_introspection/i_property_info.rb", "lib/ffi-gobject_introspection/i_registered_type_info.rb", "lib/ffi-gobject_introspection/i_repository.rb", "lib/ffi-gobject_introspection/i_signal_info.rb", "lib/ffi-gobject_introspection/i_struct_info.rb", "lib/ffi-gobject_introspection/i_type_info.rb", "lib/ffi-gobject_introspection/i_union_info.rb", "lib/ffi-gobject_introspection/i_unresolved_info.rb", "lib/ffi-gobject_introspection/i_value_info.rb", "lib/ffi-gobject_introspection/i_vfunc_info.rb", "lib/ffi-gobject_introspection/lib.rb", "lib/ffi-gobject_introspection/strv.rb", "lib/gir_ffi-base.rb", "lib/gir_ffi-base/gobject.rb", "lib/gir_ffi-base/gobject/lib.rb", "lib/gir_ffi.rb", "lib/gir_ffi/allocation_helper.rb", "lib/gir_ffi/arg_helper.rb", "lib/gir_ffi/boolean.rb", "lib/gir_ffi/boxed_base.rb", "lib/gir_ffi/builder.rb", "lib/gir_ffi/builder_helper.rb", "lib/gir_ffi/builders/argument_builder.rb", "lib/gir_ffi/builders/argument_builder_collection.rb", "lib/gir_ffi/builders/base_argument_builder.rb", "lib/gir_ffi/builders/base_method_builder.rb", "lib/gir_ffi/builders/base_return_value_builder.rb", "lib/gir_ffi/builders/base_type_builder.rb", "lib/gir_ffi/builders/c_to_ruby_convertor.rb", "lib/gir_ffi/builders/callback_argument_builder.rb", "lib/gir_ffi/builders/callback_builder.rb", "lib/gir_ffi/builders/callback_return_value_builder.rb", "lib/gir_ffi/builders/closure_argument_builder.rb", "lib/gir_ffi/builders/closure_convertor.rb", "lib/gir_ffi/builders/closure_return_value_builder.rb", "lib/gir_ffi/builders/closure_to_pointer_convertor.rb", "lib/gir_ffi/builders/constant_builder.rb", "lib/gir_ffi/builders/constructor_builder.rb", "lib/gir_ffi/builders/enum_builder.rb", "lib/gir_ffi/builders/field_builder.rb", "lib/gir_ffi/builders/flags_builder.rb", "lib/gir_ffi/builders/full_c_to_ruby_convertor.rb", "lib/gir_ffi/builders/function_builder.rb", "lib/gir_ffi/builders/initializer_builder.rb", "lib/gir_ffi/builders/initializer_return_value_builder.rb", "lib/gir_ffi/builders/interface_builder.rb", "lib/gir_ffi/builders/mapping_method_builder.rb", "lib/gir_ffi/builders/marshalling_method_builder.rb", "lib/gir_ffi/builders/method_template.rb", "lib/gir_ffi/builders/module_builder.rb", "lib/gir_ffi/builders/null_argument_builder.rb", "lib/gir_ffi/builders/null_class_builder.rb", "lib/gir_ffi/builders/null_convertor.rb", "lib/gir_ffi/builders/null_return_value_builder.rb", "lib/gir_ffi/builders/object_builder.rb", "lib/gir_ffi/builders/pointer_value_convertor.rb", "lib/gir_ffi/builders/property_argument_builder.rb", "lib/gir_ffi/builders/property_builder.rb", "lib/gir_ffi/builders/property_return_value_builder.rb", "lib/gir_ffi/builders/registered_type_builder.rb", "lib/gir_ffi/builders/return_value_builder.rb", "lib/gir_ffi/builders/ruby_to_c_convertor.rb", "lib/gir_ffi/builders/signal_closure_builder.rb", "lib/gir_ffi/builders/struct_builder.rb", "lib/gir_ffi/builders/struct_like.rb", "lib/gir_ffi/builders/type_builder.rb", "lib/gir_ffi/builders/unintrospectable_boxed_builder.rb", "lib/gir_ffi/builders/unintrospectable_builder.rb", "lib/gir_ffi/builders/union_builder.rb", "lib/gir_ffi/builders/user_defined_builder.rb", "lib/gir_ffi/builders/vfunc_argument_builder.rb", "lib/gir_ffi/builders/vfunc_builder.rb", "lib/gir_ffi/builders/with_layout.rb", "lib/gir_ffi/callback_base.rb", "lib/gir_ffi/class_base.rb", "lib/gir_ffi/core.rb", "lib/gir_ffi/enum_base.rb", "lib/gir_ffi/enum_like_base.rb", "lib/gir_ffi/error_argument_info.rb", "lib/gir_ffi/error_type_info.rb", "lib/gir_ffi/ffi_ext.rb", "lib/gir_ffi/ffi_ext/pointer.rb", "lib/gir_ffi/field_argument_info.rb", "lib/gir_ffi/flags_base.rb", "lib/gir_ffi/g_type.rb", "lib/gir_ffi/glib_error.rb", "lib/gir_ffi/in_out_pointer.rb", "lib/gir_ffi/in_pointer.rb", "lib/gir_ffi/info_ext.rb", "lib/gir_ffi/info_ext/full_type_name.rb", "lib/gir_ffi/info_ext/i_arg_info.rb", "lib/gir_ffi/info_ext/i_callable_info.rb", "lib/gir_ffi/info_ext/i_callback_info.rb", "lib/gir_ffi/info_ext/i_field_info.rb", "lib/gir_ffi/info_ext/i_function_info.rb", "lib/gir_ffi/info_ext/i_property_info.rb", "lib/gir_ffi/info_ext/i_registered_type_info.rb", "lib/gir_ffi/info_ext/i_signal_info.rb", "lib/gir_ffi/info_ext/i_type_info.rb", "lib/gir_ffi/info_ext/i_unresolved_info.rb", "lib/gir_ffi/info_ext/i_vfunc_info.rb", "lib/gir_ffi/info_ext/safe_constant_name.rb", "lib/gir_ffi/info_ext/safe_function_name.rb", "lib/gir_ffi/interface_base.rb", "lib/gir_ffi/lib_c.rb", "lib/gir_ffi/method_stubber.rb", "lib/gir_ffi/module_base.rb", "lib/gir_ffi/object_base.rb", "lib/gir_ffi/object_store.rb", "lib/gir_ffi/ownable.rb", "lib/gir_ffi/property_not_found_error.rb", "lib/gir_ffi/receiver_argument_info.rb", "lib/gir_ffi/receiver_type_info.rb", "lib/gir_ffi/registered_type_base.rb", "lib/gir_ffi/return_value_info.rb", "lib/gir_ffi/signal_not_found_error.rb", "lib/gir_ffi/sized_array.rb", "lib/gir_ffi/struct.rb", "lib/gir_ffi/struct_base.rb", "lib/gir_ffi/struct_like_base.rb", "lib/gir_ffi/type_base.rb", "lib/gir_ffi/type_map.rb", "lib/gir_ffi/unintrospectable_boxed_info.rb", "lib/gir_ffi/unintrospectable_signal_info.rb", "lib/gir_ffi/unintrospectable_type_info.rb", "lib/gir_ffi/union.rb", "lib/gir_ffi/union_base.rb", "lib/gir_ffi/user_defined_object_info.rb", "lib/gir_ffi/user_defined_property_info.rb", "lib/gir_ffi/variable_name_generator.rb", "lib/gir_ffi/version.rb", "lib/gir_ffi/vfunc_implementation.rb", "lib/gir_ffi/zero_terminated.rb", "tasks/test.rake", "test/base_test_helper.rb", "test/ffi-glib/array_test.rb", "test/ffi-glib/byte_array_test.rb", "test/ffi-glib/bytes_test.rb", "test/ffi-glib/closure_test.rb", "test/ffi-glib/destroy_notify_test.rb", "test/ffi-glib/hash_table_test.rb", "test/ffi-glib/iconv_test.rb", "test/ffi-glib/list_test.rb", "test/ffi-glib/main_loop_test.rb", "test/ffi-glib/ptr_array_test.rb", "test/ffi-glib/ruby_closure_test.rb", "test/ffi-glib/s_list_test.rb", "test/ffi-glib/strv_test.rb", "test/ffi-glib/variant_test.rb", "test/ffi-gobject/gobject_test.rb", "test/ffi-gobject/object_class_test.rb", "test/ffi-gobject/object_test.rb", "test/ffi-gobject/param_spec_test.rb", "test/ffi-gobject/value_test.rb", "test/ffi-gobject_introspection/gobject_type_init_test.rb", "test/ffi-gobject_introspection/i_base_info_test.rb", "test/ffi-gobject_introspection/i_constant_info_test.rb", "test/ffi-gobject_introspection/i_enum_info_test.rb", "test/ffi-gobject_introspection/i_function_info_test.rb", "test/ffi-gobject_introspection/i_interface_info_test.rb", "test/ffi-gobject_introspection/i_object_info_test.rb", "test/ffi-gobject_introspection/i_property_info_test.rb", "test/ffi-gobject_introspection/i_registered_type_info_test.rb", "test/ffi-gobject_introspection/i_repository_test.rb", "test/ffi-gobject_introspection/i_struct_info_test.rb", "test/ffi-gobject_introspection/i_type_info_test.rb", "test/ffi-gobject_introspection/i_union_info_test.rb", "test/ffi-gobject_introspection/i_vfunc_info_test.rb", "test/ffi-gobject_introspection/lib_test.rb", "test/ffi-gobject_introspection/strv_test.rb", "test/ffi-gobject_test.rb", "test/gir_ffi/allocation_helper_test.rb", "test/gir_ffi/arg_helper_test.rb", "test/gir_ffi/boolean_test.rb", "test/gir_ffi/boxed_base_test.rb", "test/gir_ffi/builder_test.rb", "test/gir_ffi/builders/argument_builder_test.rb", "test/gir_ffi/builders/base_argument_builder_test.rb", "test/gir_ffi/builders/callback_argument_builder_test.rb", "test/gir_ffi/builders/callback_builder_test.rb", "test/gir_ffi/builders/callback_return_value_builder_test.rb", "test/gir_ffi/builders/constant_builder_test.rb", "test/gir_ffi/builders/constructor_builder_test.rb", "test/gir_ffi/builders/enum_builder_test.rb", "test/gir_ffi/builders/field_builder_test.rb", "test/gir_ffi/builders/function_builder_test.rb", "test/gir_ffi/builders/initializer_builder_test.rb", "test/gir_ffi/builders/interface_builder_test.rb", "test/gir_ffi/builders/module_builder_test.rb", "test/gir_ffi/builders/object_builder_test.rb", "test/gir_ffi/builders/property_builder_test.rb", "test/gir_ffi/builders/registered_type_builder_test.rb", "test/gir_ffi/builders/return_value_builder_test.rb", "test/gir_ffi/builders/signal_closure_builder_test.rb", "test/gir_ffi/builders/struct_builder_test.rb", "test/gir_ffi/builders/unintrospectable_boxed_builder_test.rb", "test/gir_ffi/builders/unintrospectable_builder_test.rb", "test/gir_ffi/builders/union_builder_test.rb", "test/gir_ffi/builders/user_defined_builder_test.rb", "test/gir_ffi/builders/vfunc_argument_builder_test.rb", "test/gir_ffi/builders/vfunc_builder_test.rb", "test/gir_ffi/callback_base_test.rb", "test/gir_ffi/class_base_test.rb", "test/gir_ffi/core_test.rb", "test/gir_ffi/error_type_info_test.rb", "test/gir_ffi/ffi_ext/pointer_test.rb", "test/gir_ffi/g_type_test.rb", "test/gir_ffi/in_out_pointer_test.rb", "test/gir_ffi/in_pointer_test.rb", "test/gir_ffi/info_ext/i_callable_info_test.rb", "test/gir_ffi/info_ext/i_callback_info_test.rb", "test/gir_ffi/info_ext/i_field_info_test.rb", "test/gir_ffi/info_ext/i_function_info_test.rb", "test/gir_ffi/info_ext/i_signal_info_test.rb", "test/gir_ffi/info_ext/i_type_info_test.rb", "test/gir_ffi/info_ext/i_unresolved_info_test.rb", "test/gir_ffi/info_ext/safe_constant_name_test.rb", "test/gir_ffi/info_ext/safe_function_name_test.rb", "test/gir_ffi/interface_base_test.rb", "test/gir_ffi/method_stubber_test.rb", "test/gir_ffi/object_base_test.rb", "test/gir_ffi/object_store_test.rb", "test/gir_ffi/receiver_argument_info_test.rb", "test/gir_ffi/sized_array_test.rb", "test/gir_ffi/struct_base_test.rb", "test/gir_ffi/struct_like_base_test.rb", "test/gir_ffi/type_map_test.rb", "test/gir_ffi/unintrospectable_type_info_test.rb", "test/gir_ffi/union_base_test.rb", "test/gir_ffi/user_defined_object_info_test.rb", "test/gir_ffi/user_defined_property_info_test.rb", "test/gir_ffi/variable_name_generator_test.rb", "test/gir_ffi/version_test.rb", "test/gir_ffi/zero_terminated_test.rb", "test/gir_ffi_test_helper.rb", "test/integration/callback_exceptions_test.rb", "test/integration/derived_classes_test.rb", "test/integration/generated_everything_test.rb", "test/integration/generated_gimarshallingtests_test.rb", "test/integration/generated_gio_test.rb", "test/integration/generated_glib_test.rb", "test/integration/generated_gobject_test.rb", "test/integration/generated_gst_test.rb", "test/integration/generated_gtk_source_test.rb", "test/integration/generated_gtop_test.rb", "test/integration/generated_pango_ft2_test.rb", "test/integration/generated_pango_test.rb", "test/integration/generated_regress_test.rb", "test/integration/generated_secret_test.rb", "test/integration/generated_utility_test.rb", "test/integration/generated_warnlib_test.rb", "test/integration/method_lookup_test.rb", "test/introspection_test_helper.rb", "test/lib/Makefile.am", "test/lib/autogen.sh", "test/lib/configure.ac", "test/lib/m4/jhflags.m4", "test/minitest/stats_plugin.rb"] s.homepage = "http://www.github.com/mvz/ruby-gir-ffi" s.licenses = ["LGPL-2.1+"] s.rdoc_options = ["--main", "README.md"] s.require_paths = ["lib"] s.required_ruby_version = Gem::Requirement.new(">= 2.1.0") s.rubygems_version = "1.8.23" s.summary = "FFI-based GObject binding using the GObject Introspection Repository" if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q, ["~> 0.14.1"]) s.add_runtime_dependency(%q, ["~> 1.8"]) s.add_runtime_dependency(%q, ["~> 0.1.1"]) s.add_runtime_dependency(%q, ["~> 0.1.1"]) s.add_development_dependency(%q, ["~> 5.5"]) s.add_development_dependency(%q, ["~> 12.0"]) s.add_development_dependency(%q, ["~> 3.5"]) else s.add_dependency(%q, ["~> 0.14.1"]) s.add_dependency(%q, ["~> 1.8"]) s.add_dependency(%q, ["~> 0.1.1"]) s.add_dependency(%q, ["~> 0.1.1"]) s.add_dependency(%q, ["~> 5.5"]) s.add_dependency(%q, ["~> 12.0"]) s.add_dependency(%q, ["~> 3.5"]) end else s.add_dependency(%q, ["~> 0.14.1"]) s.add_dependency(%q, ["~> 1.8"]) s.add_dependency(%q, ["~> 0.1.1"]) s.add_dependency(%q, ["~> 0.1.1"]) s.add_dependency(%q, ["~> 5.5"]) s.add_dependency(%q, ["~> 12.0"]) s.add_dependency(%q, ["~> 3.5"]) end end gir_ffi-0.11.4/Changelog.md0000644000004100000410000004514513170036060015450 0ustar www-datawww-data# Changelog ## 0.11.4 / 2017-09-19 * Support glib 2.54 and gobject-introspection 1.54 ## 0.11.3 / 2017-05-05 * Allow conversion to native Boolean from any Ruby value ## 0.11.2 / 2017-04-20 * Allow vfunc implementation using a regular method ## 0.11.1 / 2017-01-07 * Fix build on JRuby * Allow clearing properties that take a GObject value * Handle GLists requiring an Interface type ## 0.11.0 / 2016-10-16 * Internal test and code improvements. Some internal APIs have been removed or changed. * Make Strv#each thread-safe. * Drop support for CRuby 2.0. * Move type_init and base Strv implementation into GObjectIntrospection, making it stand-alone. * Move GLib::Boolean to GirFFI::Boolean. * Guard against instantiating abstract classes using the default constructor. * Handle user-defined properties containing dashes * Handle user-defined properties of a large number of types ## 0.10.2 / 2016-04-29 * Update ffi-bit_masks dependency and remove monkey-patch * Support gobject-introspection version 1.48 ## 0.10.1 / 2016-03-28 * Restore JRuby compatibility. - Introduce #owned to flag unions and structs for release at garbage collection time. In JRuby's implementation, FFI::Pointer does not implement #autorelease= and #autorelease?, so this different technique is used to free pointers allocated by GLib. It is in fact doubtful that setting autorelease had any actual effect even on CRuby. - Immediately free string pointers whose ownership is transfered. Again, the #autorelease technique doesn't work on JRuby. - Fix handling of callee-allocated out parameters in vfuncs. The put_pointer method was wrongly called, and JRuby is more picky about what types that method expects, exposing the bug. ## 0.10.0 / 2016-03-23 * Ensure ownership of created RubyClosure objects ## 0.10.0.pre1 / 2016-03-22 * Rework generated method code to use less indirection. * Remove unused classes and methods * Clearly distinguish boxed types from other structs * Take ownership transfer into account in generated methods * Properly free unions, structs and boxed types owned by gir_ffi * Block access to fields that have disguised types ## 0.9.5 / 2016-03-05 * Abort if modules were defined earlier, e.g., through the gems from the ruby-gnome family. * Extend integration testing with GObjectIntrospection's test libraries. * Find signals on user-defined types. * Allow getting and setting of properties with a callback value. * Handle pointer-like signal arguments such as GList. * Handle static methods on interface modules. * Free most self-allocated boxed types using GObject.boxed_free. * Correctly assign length arguments for zero-terminated arguments ## 0.9.4 / 2016-02-22 * Pass nil user data as null pointer, and store a missing callback as nil. This avoids passing a null callback and a non-null user data value, which causes problems with vte_terminal_spawn_sync() and perhaps other functions. ## 0.9.3 / 2016-02-20 * Make allow-none arguments optional in Ruby * Add Clutter example * Clean up mainloop example * Use bit masks for relevant functions in GObjectIntrospection ## 0.9.2 / 2016-02-05 * Do not create a property accessor when a corresponding getter method exists ## 0.9.1 / 2016-02-04 * Add field accessors for Object types for fields that don't have corresponding properties or getter methods * Improve error handling for signals and properties that are not found * Handle signals without GIR data * Add interrupt handler to break out of main loops ## 0.9.0 / 2016-01-21 * Propagate exceptions from callbacks during event loops * Make default object constructor take a hash of properties * Fix implementation of ObjectBase.object_class * Make object class struct types inherit from their parent structs. This makes parent methods and fields available. * Use ObjectBase.object_class instead of old Object#type_class to find properties * Remove Object#type_class * Automatically unpack GValue return values * Use a BitMask to handle flag values * Handle callback arguments as Ruby block arguments * Use user data and destroy notify arguments to automate callback cleanup. This means you can no longer supply your own user data and notifiers. * Support CRuby 2.3 and Rubinius 3.x * Drop support for JRuby 1.7 and Rubinius 2.x. ## 0.8.6 / 2015-12-09 * Change handling of initializers in subclasses * Subclasses with their own GType revert to the default GObject constructor * Subclasses cannot use their parent classes' non-default contructors * Find signals in ancestor classes of unintrospectable types ## 0.8.5 / 2015-12-04 * Improve GObject::Value * Make #wrap_ruby_value work for object classes * Use non-deprecated methods for getting and setting char values * Make set_value and get_value work for interface types ## 0.8.4 / 2015-12-03 * Handle classes with lower-case names * Make ObjectBase a DataConverter so FFI handles it natively * Use more of gobject-introspection's test libraries for testing * Simplify constructor overrides: Custom initializers will no longer be overwritten when setting up the corresponding constructor. * Override GObject::Object.new to not require a GType argument ## 0.8.3 / 2015-11-13 * Fix handling of signal handler return values * Do not create setters for properties that cannot be set ## 0.8.2 / 2015-10-10 * Use inherited constructor for boxed types * Make InOutPointer work correctly for boxed types * Make .for work with boxed types * Make #set_value work with boxed types * Make GObject::Value support nil type: * Make .wrap_ruby_value(nil) work * Make #set_value and #get_value work when the type is TYPE_INVALID * Make .for_gtype work with TYPE_INVALID and TYPE_NONE * Make .from(nil) return a GObject::Value instead of nil * Make #set_ruby_value private * Make GObject::Object.signal_emit work with gobject-introspection 1.46 * Replace or remove all custom .new methods * Make setup_method and setup_instance_method handle symbol arguments ## 0.8.1 / 2015-10-04 * Handle struct array fields with related length fields * Update test library build process ## 0.8.0 / 2015-09-18 * Drop official support for CRuby 1.9.3 * Officially support JRuby 9.0.0.0 * Change handling of initializers in custom subclasses ## 0.7.10 / 2015-09-16 * Allow ffi-gobject and ffi-glib to be required directly * Improve documentation * Remove arbitrary refcount check from finalizer (by John Cupitt) ## 0.7.9 / 2015-05-05 * Unset GValues in finalizer * Dereference GObjects in finalizer * Increase refcount for ingoing :object arguments of functions with full ownership transfer * Increase refcount for receiver arguments with full ownership transfer * Increase refcount for ingoing :object arguments of vfuncs with no ownership transfer * Increase refcount for :object return values of vfuncs with full transfer * Increase refcount for outgoing :object arguments of vfuncs with full ownership transfer * Support Ruby 2.2 * Rename several methods. The old names are deprecated and will be removed in 0.8.0. ## 0.7.8 / 2014-12-09 * Support constants with a falsy value * Support type aliases that resolve to a type that is not introspectable * Support callback arguments with direction :inout * Provide GObject.signal_connect_after and GObject::Object.signal_connect_after * Handle setting GValues (and hence, properties) that have enum values * Various refactorings & coding style cleanups ## 0.7.7 / 2014-10-21 * Handle introspecting boolean constants * Provide config.h for versions of the test libs that need it * Include gemspec in the gem * Avoid needless casting from string to symbol by making #setup_and_call take a string * Avoid argument list unpacking by making #setup_and_call take an array of arguments rather than a variable number of arguments * Remove old example files * Let rubygems know about required Ruby version * Various clean-ups ## 0.7.6 / 2014-08-22 * Work around respond_to? behavior in JRuby 1.6.13 * Deprecate setup_class in favor of load_class * Support GValue containing GArray * Provide constant TYPE_BYTE_ARRAY * Don't recurse looking for signals and properties * Clean up generated code: * Avoid use of an ignored dummy argument * Clean up trailing whitespace * Drop support for Ruby 1.9.2 * Allow data argument for GObject::Object#signal_connect * Let Ruby threads run during GLib's main loop * Make all dependencies versioned * Various refactoring & code cleanup ## 0.7.5 / 2014-06-22 * Use closures as signal handlers, rather than callbacks * Obtain reference to GVariant on creation * Make struct arguments work in JRuby * Various refactoring & code cleanup ## 0.7.4 / 2014-05-03 * Correctly handle closure data arguments originating from C * Handle callee-allocated simple types for callbacks and functions * Handle callback out parameters that are zero-terminated arrays * Handle virtual functions with GError arguments * Support the GBytes type * Handle virtual functions returning GObjects * Avoid overwriting methods with getters for properties with dashes in the name ## 0.7.3 / 2014-03-23 * Restore proper handling of enums in callback arguments * Simplify Rake configuration * Various small fixes * Remove remaining Ruby 1.8 version checks ## 0.7.2 / 2014-01-18 * Officially drop Ruby 1.8 compatibility. * Store GType of generated types in a constant, removing the need to generate a separate get_gtype method for each type. ## 0.7.1 / 2014-01-17 * Handle method setup for methods with unsafe names (i.e., g_iconv()) * Add override for GLib::IConv.open ## 0.7.0 / 2014-01-11 * Type handling: * Handle c arrays with separate length argument for signals * Handle GHashTable values of type :gint8 and :guint32 * Handle signals with int64, Strv, uint64 arguments * Handle arrays of integers cast as pointers * Handle fields of callback type * Handle nested GHashTable * Argument handling: * Refactor argument builder system * Improve handling of user data arguments * Handle signal and callback arguments with direction :out * Handle aliases of container types by making the element type optional * Handle signal and callback return values that need conversion * User defined types: * Pass explicit receiver to initialization block for UserDefinedTypeInfo * Allow user defined types that are anonymous Ruby classes * Register defined properties in a subclass * Support setting virtual function implementations in a subclass * Support adding an interface to a subclass * Support implementing an interface's virtual functions in a subclass * Use FFI's DataConvertor system to handle enums and callbacks * Stop using deprecated GValueArray to construct argument array for signal_emit * Make ITypeInfo#g_type return correct value for c arrays * Make get_property and set_property less smart, moving conversion into the property accessor definitions * Make GObject::Value#get_value handle enums and flags * Clean up deprecated methods ## 0.6.7 / 2013-09-28 * Uniform handling of callback, signal and method arguments * Automatically convert array elements to GValue * Support inline array fields * Support struct fields * Improved field setters and getters * Support many more types of properties * Support skipped arguments and return values * Fix refcount for the result of IBaseInfo#container * Check bounds in GLib::PtrArray#index and GLib::Array#index * Deprecate several methods * Lots of refactoring ## 0.6.6 / 2013-08-05 * Handle GArrays of booleans and structs * Improve handling of gbooleans ## 0.6.5 / 2013-08-03 * Handle inline arrays of structs * Implement equality operator for container types * Fix element size calculation for GArray ## 0.6.4 / 2013-06-30 * Represent enum types by modules wrapping FFI::Enum * Support functions on enums * Handle zero-terminated arrays of types other than int32 * Add override for GLib::Variant#get_string * Handle non-throwing arguments and return values of type GError * Handle arguments and return values of type GPtrArray * Handle caller-allocated arguments of type GArray * Deprecate GObject::Value#ruby_value, replacing it with #get_value ## 0.6.3 / 2013-06-15 * Make use of enums as element type for GHashTable and other containers work ## 0.6.2 / 2013-06-14 * Handle introspectable types with introspectable parent types ## 0.6.1 / 2013-06-09 * Handle SizedArray containing enums ## 0.6.0 / 2013-06-07 * Support Rubinius * Lots of refactoring ## 0.5.2 / 2013-04-23 * Handle signal details in GObject.signal_connect and .signal_emit * Make GValue#set_value check object GType compatibility * Eliminate GObject::Helper module * Handle more argument types * Support Ruby 2.0.0 ## 0.5.1 / 2013-02-01 * Properly handle zero-terminated arrays of :filename * Loosen dependencies on ffi and minitest ## 0.5.0 / 2013-01-19 * Update ffi dependency * Add finalizer to release memory for IBaseInfo and descendents * Remove deprecated methods * Remove pretty-printing functionality * Refactor argument handling ## 0.4.3 / 2012-11-02 * Remove gobject-introspection version check * Make tests pass with gobject-introspection 1.34 * Ongoing refactoring ## 0.4.2 / 2012-09-22 * Make objects and interfaces wrap poiners in the class that matches their GType. ## 0.4.1 / 2012-09-18 * Remove workarounds for older versions of gobject-introspection * Mark certain methods as deprecated. These will be removed in 0.5.0 * Handle :filename type arguments in InPointer * Refactoring ## 0.4.0 / 2012-08-24 * Move Gtk+ bindings to their own gem (gir_ffi-gtk). ## 0.3.2 / 2012-08-24 * Correctly set FFI return type when callbacks that return GObjects have incomplete type specification. ## 0.3.1 / 2012-05-13 * Correctly map Interface types in callbacks. ## 0.3.0 / 2012-04-09 * Improve process of defining initializers in derived classes. * Make interfaces know their GType. * Make classes created by the Unintrospectable builder know their GType. * Create property accessors instead of field accessors for GObjects. * Add Ruby-style getter and setter methods (by Antonio Terceiro). * Add #signal_connect instance method (by Antonio Terceiro). * Make GirFFI's tests pass with gobject-introspection 0.10. * Improve unintrospectable type handling. * Bug fixes and refactorings. * Start implementing #define_type, for creating descendent types that the GObject system knows about. ## 0.2.3 / 2011-12-31 * Fix issue #7: methods that take GValues will autoconvert other values. * Fix method lookup when include'ing a module that is an Interface. * Various refactorings. ## 0.2.2 / 2011-12-07 * Fix issue #19: Check if a GLib::PtrArray.add method was generated before attempting to remove it. * Fix two issues with pretty printing that made output for GLib have syntax errors. ## 0.2.1 / 2011-11-20 * Fix handling of output parameters that are arrays of pointers to structures (i.e., of type Foo***). ## 0.2.0 / 2011-11-19 * Add support for properties, with #get_property and #set_property. * Add support for fields. - Create field accessor methods. - Get rid of #[] and #[]=. * Explicitely load libgirepository with ABI version 1. * Improve implementation of GLib container classes (GList etc.): - Real constructors. - #append and friends are instance methods now. - Conversion methods to cast Ruby containers to GLib containers. * Start implementing pretty printing. * Various refactorings. ## 0.1.0 / 2011-10-28 * Put bindings for GObjectIntrospection in their own namespace. * GirFFI.setup no longer loads overrides. * Add ffi-gtk2 and ffi-gtk3 files for loading Gtk+ overrides. ## 0.0.14 / 2011-10-28 * Support GObject Introspection version 1.30: - Add support for layouts with fixed-length arrays. - Handle type names starting with underscores. - Call g_signal_emitv directly to avoid conflict in introspection info with earlier versions of GObject Introspection. ## 0.0.13 / 2011-09-09 * Remove IErrorDomain related code. This functinality was removed from GObject Introspection in version 1.29.17 ## 0.0.12 / 2011-09-04 * No longer use `_id2ref` to locate objects past as user data pointers. * Fix failing tests on JRuby. ## 0.0.11 / 2011-08-22 * Change interface to the underlying builder in generated modules and classes. * Handle string, enum, union, flags signal arguments. * Handle string arguments in GObject.signal_emit. * Handle enum signal arguments. * Fix finding signals in non-introspectable types. * Fix method setup in non-introspectable types. * Refactoring. ## 0.0.10 / 2011-05-18 * Handle GObject interfaces properly. * Create types only defined by the GType system. * Support GType array return values. ## 0.0.9 / 2011-05-02 * More complete support for the basic types. * Improved support for GList, GSList, GStrv, and GValue. * Add support for GHashTable, GVariant, GByteArray, and GArray. * Generate constants. * When setting up a module, set up its dependencies as well. * Test against the GIMarshallingTests test namespace. * Use minitest/spec for testing. * Various bug fixes and internal improvements. ## 0.0.8 / 2011-04-08 * Generate modules with names starting with a lowercase letter (like cairo). * Allow specifying the typelib version on setup. * Rename methods #methods and #type of the introspection classes to avoid clashing with standard Ruby methods. * Refactoring. ## 0.0.7 / 2011-04-01 * Support gobject-introspection 0.10, drop support for earlier versions. - Use Regress, not Everything, for testing. - Deal with functions that are no longer introspectable. * Correctly handle constructors that declare their return type different from their class. * Implement RubyClosure, a GObject::Closure for handling ruby callbacks. * Handle GLib's singly and doubly linked lists. * Handle callback types defined in-place (like Closure's marshal). * Refactoring. ## 0.0.6 / 2011-03-01 * Cast returned GObjects to their actual type. * Properly cast callback arguments. * Handle the case where functions formally return interfaces. * Make sure Gtk::Window has the correct number of references after creation. * Refactoring and some small fixes. ## 0.0.5 / 2010-12-30 * Don't create instance methods out of functions and vice versa. * Find signals on interfaces, too. * Implement tests for most of Everything. * Correctly handle array + size arguments. * Handle most other argument types. * Various internal changes and other fixes. ## 0.0.4 / 2010-12-14 * Lots of changes to the internals. * Handle out-only arguments. * Make use of callbacks from other namespaces work. * Handle virtual methods where the invoker method has a different name. * Implement usable signal_connect and signal_emit. * Sink floating references when creating a GObject. * Implement Union type. * Many small bug fixes. ## 0.0.3 / 2010-11-19 * Update to restore Ruby 1.9 support. * Handle functions with the 'throws' property set. * Handle classes without specified fields. ## 0.0.2 / 2010-11-14 * Several fixes to method creation. ## 0.0.1 / 2010-10-25 * Initial release. gir_ffi-0.11.4/lib/0000755000004100000410000000000013170036060013774 5ustar www-datawww-datagir_ffi-0.11.4/lib/gir_ffi-base/0000755000004100000410000000000013170036060016311 5ustar www-datawww-datagir_ffi-0.11.4/lib/gir_ffi-base/gobject.rb0000644000004100000410000000264013170036060020255 0ustar www-datawww-data# frozen_string_literal: true # Ensure GObject is defined by GirFFI itself raise 'The module GObject was already defined elsewhere' if Kernel.const_defined? :GObject require 'gir_ffi-base/gobject/lib' # The part of the GObject namespace that is needed by GirFFI. # # :reek:TooManyConstants: because it needs to hold the type constants. module GObject def self.type_from_name(name) Lib.g_type_from_name name end def self.type_fundamental(gtype) Lib.g_type_fundamental gtype end TYPE_INVALID = type_from_name('invalid') TYPE_NONE = type_from_name('void') TYPE_INTERFACE = type_from_name('GInterface') TYPE_CHAR = type_from_name('gchar') TYPE_UCHAR = type_from_name('guchar') TYPE_BOOLEAN = type_from_name('gboolean') TYPE_INT = type_from_name('gint') TYPE_UINT = type_from_name('guint') TYPE_LONG = type_from_name('glong') TYPE_ULONG = type_from_name('gulong') TYPE_INT64 = type_from_name('gint64') TYPE_UINT64 = type_from_name('guint64') TYPE_ENUM = type_from_name('GEnum') TYPE_FLAGS = type_from_name('GFlags') TYPE_FLOAT = type_from_name('gfloat') TYPE_DOUBLE = type_from_name('gdouble') TYPE_STRING = type_from_name('gchararray') TYPE_POINTER = type_from_name('gpointer') TYPE_BOXED = type_from_name('GBoxed') TYPE_PARAM = type_from_name('GParam') TYPE_OBJECT = type_from_name('GObject') TYPE_GTYPE = type_from_name('GType') TYPE_VARIANT = type_from_name('GVariant') end gir_ffi-0.11.4/lib/gir_ffi-base/gobject/0000755000004100000410000000000013170036060017726 5ustar www-datawww-datagir_ffi-0.11.4/lib/gir_ffi-base/gobject/lib.rb0000644000004100000410000000053313170036060021022 0ustar www-datawww-data# frozen_string_literal: true require 'ffi/bit_masks' module GObject # Module for attaching functions from the gobject library module Lib extend FFI::Library extend FFI::BitMasks ffi_lib 'gobject-2.0' attach_function :g_type_from_name, [:string], :size_t attach_function :g_type_fundamental, [:size_t], :size_t end end gir_ffi-0.11.4/lib/gir_ffi.rb0000644000004100000410000000014013170036060015721 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/core' require 'ffi-glib' require 'ffi-gobject' gir_ffi-0.11.4/lib/ffi-gobject_introspection/0000755000004100000410000000000013170036060021133 5ustar www-datawww-datagir_ffi-0.11.4/lib/ffi-gobject_introspection/gobject_type_init.rb0000644000004100000410000000062013170036060025157 0ustar www-datawww-data# frozen_string_literal: true require 'ffi' module GObjectIntrospection # Provides access to the g_type_init function. module GObjectTypeInit def self.type_init Lib.g_type_init end # Module for attaching g_type_init from the gobject library. module Lib extend FFI::Library ffi_lib 'gobject-2.0' attach_function :g_type_init, [], :void end end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_repository.rb0000644000004100000410000000430113170036060024205 0ustar www-datawww-data# frozen_string_literal: true require 'singleton' require 'ffi-gobject_introspection/lib' require 'ffi-gobject_introspection/strv' require 'ffi-gobject_introspection/g_error' module GObjectIntrospection # The Gobject Introspection Repository. This class is the point of # access to the introspection typelibs. # This class wraps the GIRepository struct. class IRepository def initialize @gobj = Lib.g_irepository_get_default end include Singleton def self.default instance end def self.prepend_search_path(path) Lib.g_irepository_prepend_search_path path end def self.type_tag_to_string(type) Lib.g_type_tag_to_string type end def require(namespace, version = nil, flags = 0) errpp = FFI::MemoryPointer.new(:pointer).write_pointer nil Lib.g_irepository_require @gobj, namespace, version, flags, errpp errp = errpp.read_pointer raise GError.new(errp).message unless errp.null? end def n_infos(namespace) Lib.g_irepository_get_n_infos @gobj, namespace end def info(namespace, index) wrap_info Lib.g_irepository_get_info(@gobj, namespace, index) end # Utility method def infos(namespace) (0..(n_infos(namespace) - 1)).map do |idx| info namespace, idx end end def find_by_name(namespace, name) wrap_info Lib.g_irepository_find_by_name(@gobj, namespace, name) end def find_by_gtype(gtype) raise ArgumentError, "Type #{gtype} is not a valid type" if gtype.zero? wrap_info Lib.g_irepository_find_by_gtype(@gobj, gtype) end def dependencies(namespace) strv_p = Lib.g_irepository_get_dependencies(@gobj, namespace) strv = Strv.new strv_p strv.to_a end def shared_library(namespace) Lib.g_irepository_get_shared_library @gobj, namespace end def version(namespace) Lib.g_irepository_get_version @gobj, namespace end def self.wrap_ibaseinfo_pointer(ptr) return nil if ptr.null? type = Lib.g_base_info_get_type ptr klass = TYPEMAP[type] klass.wrap ptr end private def wrap_info(ptr) self.class.wrap_ibaseinfo_pointer ptr end end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_unresolved_info.rb0000644000004100000410000000035013170036060025167 0ustar www-datawww-data# frozen_string_literal: true require 'ffi-gobject_introspection/i_base_info' module GObjectIntrospection # Wraps a GIBaseInfo struct in the case where the info type is :unresolved. class IUnresolvedInfo < IBaseInfo end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_object_info.rb0000644000004100000410000000500313170036060024247 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIObjectInfo struct. # Represents an object. class IObjectInfo < IRegisteredTypeInfo def type_name Lib.g_object_info_get_type_name @gobj end def type_init Lib.g_object_info_get_type_init @gobj end def abstract? Lib.g_object_info_get_abstract @gobj end def fundamental? Lib.g_object_info_get_fundamental @gobj end def parent IObjectInfo.wrap Lib.g_object_info_get_parent(@gobj) end def n_interfaces Lib.g_object_info_get_n_interfaces @gobj end def interface(index) IInterfaceInfo.wrap Lib.g_object_info_get_interface(@gobj, index) end ## build_array_method :interfaces def n_fields Lib.g_object_info_get_n_fields @gobj end def field(index) IFieldInfo.wrap Lib.g_object_info_get_field(@gobj, index) end ## build_array_method :fields def n_properties Lib.g_object_info_get_n_properties @gobj end def property(index) IPropertyInfo.wrap Lib.g_object_info_get_property(@gobj, index) end def properties @properties ||= Array.new(n_properties) { |idx| property(idx) } end def find_property(name) name = name.to_s.tr('_', '-') properties.find { |prop| prop.name == name } end def get_n_methods Lib.g_object_info_get_n_methods @gobj end def get_method(index) IFunctionInfo.wrap Lib.g_object_info_get_method(@gobj, index) end ## build_array_method :get_methods def find_method(name) IFunctionInfo.wrap Lib.g_object_info_find_method(@gobj, name.to_s) end def n_signals Lib.g_object_info_get_n_signals @gobj end def signal(index) ISignalInfo.wrap Lib.g_object_info_get_signal(@gobj, index) end ## build_array_method :signals build_finder_method :find_signal def n_vfuncs Lib.g_object_info_get_n_vfuncs @gobj end def vfunc(index) IVFuncInfo.wrap Lib.g_object_info_get_vfunc(@gobj, index) end def find_vfunc(name) IVFuncInfo.wrap Lib.g_object_info_find_vfunc(@gobj, name.to_s) end ## build_array_method :vfuncs def n_constants Lib.g_object_info_get_n_constants @gobj end def constant(index) IConstantInfo.wrap Lib.g_object_info_get_constant(@gobj, index) end ## build_array_method :constants def class_struct IStructInfo.wrap Lib.g_object_info_get_class_struct(@gobj) end end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_field_info.rb0000644000004100000410000000105613170036060024070 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIFieldInfo struct. # Represents a field of an IStructInfo or an IUnionInfo. class IFieldInfo < IBaseInfo def flags Lib.g_field_info_get_flags @gobj end def size Lib.g_field_info_get_size @gobj end def offset Lib.g_field_info_get_offset @gobj end def field_type ITypeInfo.wrap Lib.g_field_info_get_type(@gobj) end def readable? flags[:readable] end def writable? flags[:writable] end end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_vfunc_info.rb0000644000004100000410000000055613170036060024132 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIVFuncInfo struct. # Represents a virtual function. class IVFuncInfo < ICallableInfo def flags Lib.g_vfunc_info_get_flags self end def throws? flags.fetch :throws end def invoker IFunctionInfo.wrap Lib.g_vfunc_info_get_invoker self end end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/lib.rb0000644000004100000410000002771713170036060022244 0ustar www-datawww-data# frozen_string_literal: true require 'ffi' require 'ffi/bit_masks' module GObjectIntrospection # Module for attaching functions from the girepository library module Lib extend FFI::Library extend FFI::BitMasks ffi_lib 'girepository-1.0' # IRepository enum :IRepositoryLoadFlags, [:LAZY, (1 << 0)] attach_function :g_irepository_get_default, [], :pointer attach_function :g_irepository_prepend_search_path, [:string], :void attach_function :g_irepository_require, [:pointer, :string, :string, :IRepositoryLoadFlags, :pointer], :pointer attach_function :g_irepository_get_version, [:pointer, :string], :string attach_function :g_irepository_get_n_infos, [:pointer, :string], :int attach_function :g_irepository_get_info, [:pointer, :string, :int], :pointer attach_function :g_irepository_find_by_name, [:pointer, :string, :string], :pointer attach_function :g_irepository_find_by_gtype, [:pointer, :size_t], :pointer attach_function :g_irepository_get_dependencies, [:pointer, :string], :pointer attach_function :g_irepository_get_shared_library, [:pointer, :string], :string # IBaseInfo enum :IInfoType, [ :invalid, :function, :callback, :struct, :boxed, :enum, :flags, :object, :interface, :constant, :invalid_was_error_domain, # deprecated in GI 1.29.17 :union, :value, :signal, :vfunc, :property, :field, :arg, :type, :unresolved ] attach_function :g_base_info_ref, [:pointer], :void attach_function :g_base_info_unref, [:pointer], :void attach_function :g_base_info_get_attribute, [:pointer, :string], :string attach_function :g_base_info_get_type, [:pointer], :IInfoType attach_function :g_base_info_get_name, [:pointer], :string attach_function :g_base_info_get_namespace, [:pointer], :string attach_function :g_base_info_get_container, [:pointer], :pointer attach_function :g_base_info_is_deprecated, [:pointer], :bool attach_function :g_base_info_equal, [:pointer, :pointer], :bool # IFunctionInfo bit_mask :IFunctionInfoFlags, is_method: (1 << 0), is_constructor: (1 << 1), is_getter: (1 << 2), is_setter: (1 << 3), wraps_vfunc: (1 << 4), throws: (1 << 5) attach_function :g_function_info_get_symbol, [:pointer], :string attach_function :g_function_info_get_flags, [:pointer], :IFunctionInfoFlags # ICallableInfo enum :ITransfer, [ :nothing, :container, :everything ] attach_function :g_callable_info_get_return_type, [:pointer], :pointer attach_function :g_callable_info_get_caller_owns, [:pointer], :ITransfer attach_function :g_callable_info_may_return_null, [:pointer], :bool attach_function :g_callable_info_can_throw_gerror, [:pointer], :bool attach_function :g_callable_info_get_instance_ownership_transfer, [:pointer], :ITransfer attach_function :g_callable_info_get_n_args, [:pointer], :int attach_function :g_callable_info_get_arg, [:pointer, :int], :pointer attach_function :g_callable_info_skip_return, [:pointer], :bool # IArgInfo enum :IDirection, [ :in, :out, :inout ] enum :IScopeType, [ :invalid, :call, :async, :notified ] attach_function :g_arg_info_get_direction, [:pointer], :IDirection attach_function :g_arg_info_is_return_value, [:pointer], :bool attach_function :g_arg_info_is_optional, [:pointer], :bool attach_function :g_arg_info_is_caller_allocates, [:pointer], :bool attach_function :g_arg_info_is_skip, [:pointer], :bool attach_function :g_arg_info_may_be_null, [:pointer], :bool attach_function :g_arg_info_get_ownership_transfer, [:pointer], :ITransfer attach_function :g_arg_info_get_scope, [:pointer], :IScopeType attach_function :g_arg_info_get_closure, [:pointer], :int attach_function :g_arg_info_get_destroy, [:pointer], :int attach_function :g_arg_info_get_type, [:pointer], :pointer # The values of ITypeTag were changed in an incompatible way between # gobject-introspection version 0.9.0 and 0.9.1. Therefore, we need to # retrieve the correct values before declaring the ITypeTag enum. attach_function :tmp_type_tag_to_string, :g_type_tag_to_string, [:int], :string type_tag_map = (0..31).map do |id| sym = tmp_type_tag_to_string(id).to_sym if sym == :unknown nil else [sym, id] end end.compact.flatten enum :ITypeTag, type_tag_map # Now, attach g_type_tag_to_string again under its own name with an # improved signature. attach_function :g_type_tag_to_string, [:ITypeTag], :string enum :IArrayType, [ :c, :array, :ptr_array, :byte_array ] attach_function :g_type_info_is_pointer, [:pointer], :bool attach_function :g_type_info_get_tag, [:pointer], :ITypeTag attach_function :g_type_info_get_param_type, [:pointer, :int], :pointer attach_function :g_type_info_get_interface, [:pointer], :pointer attach_function :g_type_info_get_array_length, [:pointer], :int attach_function :g_type_info_get_array_fixed_size, [:pointer], :int attach_function :g_type_info_get_array_type, [:pointer], :IArrayType attach_function :g_type_info_is_zero_terminated, [:pointer], :bool # IStructInfo attach_function :g_struct_info_get_n_fields, [:pointer], :int attach_function :g_struct_info_get_field, [:pointer, :int], :pointer attach_function :g_struct_info_get_n_methods, [:pointer], :int attach_function :g_struct_info_get_method, [:pointer, :int], :pointer attach_function :g_struct_info_find_method, [:pointer, :string], :pointer attach_function :g_struct_info_get_size, [:pointer], :int attach_function :g_struct_info_get_alignment, [:pointer], :int attach_function :g_struct_info_is_gtype_struct, [:pointer], :bool # IValueInfo attach_function :g_value_info_get_value, [:pointer], :long # IFieldInfo bit_mask :IFieldInfoFlags, readable: (1 << 0), writable: (1 << 1) attach_function :g_field_info_get_flags, [:pointer], :IFieldInfoFlags attach_function :g_field_info_get_size, [:pointer], :int attach_function :g_field_info_get_offset, [:pointer], :int attach_function :g_field_info_get_type, [:pointer], :pointer # IUnionInfo attach_function :g_union_info_get_n_fields, [:pointer], :int attach_function :g_union_info_get_field, [:pointer, :int], :pointer attach_function :g_union_info_get_n_methods, [:pointer], :int attach_function :g_union_info_get_method, [:pointer, :int], :pointer attach_function :g_union_info_find_method, [:pointer, :string], :pointer attach_function :g_union_info_get_size, [:pointer], :int attach_function :g_union_info_get_alignment, [:pointer], :int # IRegisteredTypeInfo attach_function :g_registered_type_info_get_type_name, [:pointer], :string attach_function :g_registered_type_info_get_type_init, [:pointer], :string attach_function :g_registered_type_info_get_g_type, [:pointer], :size_t # IEnumInfo attach_function :g_enum_info_get_storage_type, [:pointer], :ITypeTag attach_function :g_enum_info_get_n_values, [:pointer], :int attach_function :g_enum_info_get_value, [:pointer, :int], :pointer attach_function :g_enum_info_get_n_methods, [:pointer], :int attach_function :g_enum_info_get_method, [:pointer, :int], :pointer # IObjectInfo attach_function :g_object_info_get_type_name, [:pointer], :string attach_function :g_object_info_get_type_init, [:pointer], :string attach_function :g_object_info_get_abstract, [:pointer], :bool attach_function :g_object_info_get_parent, [:pointer], :pointer attach_function :g_object_info_get_n_interfaces, [:pointer], :int attach_function :g_object_info_get_interface, [:pointer, :int], :pointer attach_function :g_object_info_get_n_fields, [:pointer], :int attach_function :g_object_info_get_field, [:pointer, :int], :pointer attach_function :g_object_info_get_n_properties, [:pointer], :int attach_function :g_object_info_get_property, [:pointer, :int], :pointer attach_function :g_object_info_get_n_methods, [:pointer], :int attach_function :g_object_info_get_method, [:pointer, :int], :pointer attach_function :g_object_info_find_method, [:pointer, :string], :pointer attach_function :g_object_info_get_n_signals, [:pointer], :int attach_function :g_object_info_get_signal, [:pointer, :int], :pointer attach_function :g_object_info_get_n_vfuncs, [:pointer], :int attach_function :g_object_info_get_vfunc, [:pointer, :int], :pointer attach_function :g_object_info_find_vfunc, [:pointer, :string], :pointer attach_function :g_object_info_get_n_constants, [:pointer], :int attach_function :g_object_info_get_constant, [:pointer, :int], :pointer attach_function :g_object_info_get_class_struct, [:pointer], :pointer attach_function :g_object_info_get_fundamental, [:pointer], :bool # IVFuncInfo bit_mask :IVFuncInfoFlags, must_chain_up: (1 << 0), must_override: (1 << 1), must_not_override: (1 << 2), throws: (1 << 3) attach_function :g_vfunc_info_get_flags, [:pointer], :IVFuncInfoFlags attach_function :g_vfunc_info_get_invoker, [:pointer], :pointer # IInterfaceInfo attach_function :g_interface_info_get_n_prerequisites, [:pointer], :int attach_function :g_interface_info_get_prerequisite, [:pointer, :int], :pointer attach_function :g_interface_info_get_n_properties, [:pointer], :int attach_function :g_interface_info_get_property, [:pointer, :int], :pointer attach_function :g_interface_info_get_n_methods, [:pointer], :int attach_function :g_interface_info_get_method, [:pointer, :int], :pointer attach_function :g_interface_info_find_method, [:pointer, :string], :pointer attach_function :g_interface_info_get_n_signals, [:pointer], :int attach_function :g_interface_info_get_signal, [:pointer, :int], :pointer attach_function :g_interface_info_get_n_vfuncs, [:pointer], :int attach_function :g_interface_info_get_vfunc, [:pointer, :int], :pointer attach_function :g_interface_info_find_vfunc, [:pointer, :string], :pointer attach_function :g_interface_info_get_n_constants, [:pointer], :int attach_function :g_interface_info_get_constant, [:pointer, :int], :pointer attach_function :g_interface_info_get_iface_struct, [:pointer], :pointer # Union type representing an argument value class GIArgument < FFI::Union signed_size_t = "int#{FFI.type_size(:size_t) * 8}".to_sym layout :v_boolean, :int, :v_int8, :int8, :v_uint8, :uint8, :v_int16, :int16, :v_uint16, :uint16, :v_int32, :int32, :v_uint32, :uint32, :v_int64, :int64, :v_uint64, :uint64, :v_float, :float, :v_double, :double, :v_short, :short, :v_ushort, :ushort, :v_int, :int, :v_uint, :uint, :v_long, :long, :v_ulong, :ulong, :v_ssize, signed_size_t, :v_size, :size_t, :v_string, :string, :v_pointer, :pointer end # IConstInfo # attach_function :g_constant_info_get_type, [:pointer], :pointer attach_function :g_constant_info_get_value, [:pointer, :pointer], :int # IPropertyInfo # attach_function :g_property_info_get_type, [:pointer], :pointer # NOTE: This type has more values, but these are the ones used bit_mask :ParamFlags, readable: (1 << 0), writable: (1 << 1), construct: (1 << 2), construct_only: (1 << 3) attach_function :g_property_info_get_flags, [:pointer], :ParamFlags end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_property_info.rb0000644000004100000410000000107313170036060024670 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIPropertyInfo struct. # Represents a property of an IObjectInfo or an IInterfaceInfo. class IPropertyInfo < IBaseInfo def property_type ITypeInfo.wrap Lib.g_property_info_get_type(@gobj) end def flags Lib.g_property_info_get_flags @gobj end def readable? flags[:readable] end def writeable? flags[:writable] end def construct? flags[:construct] end def construct_only? flags[:construct_only] end end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_signal_info.rb0000644000004100000410000000027413170036060024263 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GISignalInfo struct. # Represents a signal. # Not implemented yet. class ISignalInfo < ICallableInfo end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_interface_info.rb0000644000004100000410000000362013170036060024744 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a IInterfaceInfo struct. # Represents an interface. class IInterfaceInfo < IRegisteredTypeInfo def n_prerequisites Lib.g_interface_info_get_n_prerequisites @gobj end def prerequisite(index) IBaseInfo.wrap Lib.g_interface_info_get_prerequisite(@gobj, index) end ## build_array_method :prerequisites def n_properties Lib.g_interface_info_get_n_properties @gobj end def property(index) IPropertyInfo.wrap Lib.g_interface_info_get_property(@gobj, index) end ## build_array_method :properties, :property build_finder_method :find_property, :n_properties def get_n_methods Lib.g_interface_info_get_n_methods @gobj end def get_method(index) IFunctionInfo.wrap Lib.g_interface_info_get_method(@gobj, index) end ## build_array_method :get_methods def find_method(name) IFunctionInfo.wrap Lib.g_interface_info_find_method(@gobj, name.to_s) end def n_signals Lib.g_interface_info_get_n_signals @gobj end def signal(index) ISignalInfo.wrap Lib.g_interface_info_get_signal(@gobj, index) end ## build_array_method :signals build_finder_method :find_signal def n_vfuncs Lib.g_interface_info_get_n_vfuncs @gobj end def vfunc(index) IVFuncInfo.wrap Lib.g_interface_info_get_vfunc(@gobj, index) end ## build_array_method :vfuncs def find_vfunc(name) IVFuncInfo.wrap Lib.g_interface_info_find_vfunc(@gobj, name) end def n_constants Lib.g_interface_info_get_n_constants @gobj end def constant(index) IConstantInfo.wrap Lib.g_interface_info_get_constant(@gobj, index) end ## build_array_method :constants def iface_struct IStructInfo.wrap Lib.g_interface_info_get_iface_struct(@gobj) end end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_type_info.rb0000644000004100000410000000161713170036060023771 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GITypeInfo struct. # Represents type information, direction, transfer etc. class ITypeInfo < IBaseInfo def pointer? Lib.g_type_info_is_pointer @gobj end def tag Lib.g_type_info_get_tag @gobj end def param_type(index) ITypeInfo.wrap Lib.g_type_info_get_param_type(@gobj, index) end def interface ptr = Lib.g_type_info_get_interface @gobj IRepository.wrap_ibaseinfo_pointer ptr end def array_length Lib.g_type_info_get_array_length @gobj end def array_fixed_size Lib.g_type_info_get_array_fixed_size @gobj end def array_type Lib.g_type_info_get_array_type @gobj end def zero_terminated? Lib.g_type_info_is_zero_terminated @gobj end def name raise 'Should not call this for ITypeInfo' end end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_struct_info.rb0000644000004100000410000000172613170036060024335 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIStructInfo struct. # Represents a struct. class IStructInfo < IRegisteredTypeInfo def n_fields Lib.g_struct_info_get_n_fields @gobj end def field(index) IFieldInfo.wrap Lib.g_struct_info_get_field(@gobj, index) end ## build_array_method :fields build_finder_method :find_field def get_n_methods Lib.g_struct_info_get_n_methods @gobj end def get_method(index) IFunctionInfo.wrap Lib.g_struct_info_get_method(@gobj, index) end ## build_array_method :get_methods # There is a function g_struct_info_find_method but it causes a core dump. build_finder_method :find_method, :get_n_methods, :get_method def size Lib.g_struct_info_get_size @gobj end def alignment Lib.g_struct_info_get_alignment @gobj end def gtype_struct? Lib.g_struct_info_is_gtype_struct @gobj end end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_value_info.rb0000644000004100000410000000037013170036060024117 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIValueInfo struct. # Represents one of the enum values of an IEnumInfo. class IValueInfo < IBaseInfo def value Lib.g_value_info_get_value @gobj end end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_callable_info.rb0000644000004100000410000000205713170036060024546 0ustar www-datawww-data# frozen_string_literal: true require 'ffi-gobject_introspection/i_base_info' require 'ffi-gobject_introspection/i_type_info' require 'ffi-gobject_introspection/i_arg_info' module GObjectIntrospection # Wraps a GICallableInfo struct; represents a callable, either # IFunctionInfo, ICallbackInfo or IVFuncInfo. class ICallableInfo < IBaseInfo def return_type ITypeInfo.wrap Lib.g_callable_info_get_return_type(@gobj) end def caller_owns Lib.g_callable_info_get_caller_owns @gobj end def may_return_null? Lib.g_callable_info_may_return_null @gobj end def can_throw_gerror? Lib.g_callable_info_can_throw_gerror @gobj end def n_args Lib.g_callable_info_get_n_args @gobj end def arg(index) IArgInfo.wrap Lib.g_callable_info_get_arg(@gobj, index) end ## build_array_method :args def skip_return? Lib.g_callable_info_skip_return @gobj end def instance_ownership_transfer Lib.g_callable_info_get_instance_ownership_transfer @gobj end end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_flags_info.rb0000644000004100000410000000024113170036060024074 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIEnumInfo struct, if it represents a flag type. class IFlagsInfo < IEnumInfo end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_enum_info.rb0000644000004100000410000000142313170036060023747 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIEnumInfo struct if it represents an enum. # If it represents a flag, an IFlagsInfo object is used instead. class IEnumInfo < IRegisteredTypeInfo def n_values Lib.g_enum_info_get_n_values @gobj end def value(index) IValueInfo.wrap Lib.g_enum_info_get_value(@gobj, index) end ## build_array_method :values def get_n_methods Lib.g_enum_info_get_n_methods @gobj end def get_method(index) IFunctionInfo.wrap Lib.g_enum_info_get_method(@gobj, index) end ## build_array_method :get_methods build_finder_method :find_method, :get_n_methods, :get_method def storage_type Lib.g_enum_info_get_storage_type @gobj end end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_function_info.rb0000644000004100000410000000115213170036060024627 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIFunctionInfo struct. # Represents a function or method. class IFunctionInfo < ICallableInfo def symbol Lib.g_function_info_get_symbol @gobj end def flags Lib.g_function_info_get_flags @gobj end def method? flags[:is_method] end def constructor? flags[:is_constructor] end def getter? flags[:is_getter] end def setter? flags[:is_setter] end def wraps_vfunc? flags[:wraps_vfunc] end def throws? flags[:throws] end end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_callback_info.rb0000644000004100000410000000032713170036060024541 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GICallbackInfo struct. Has no methods in addition to the ones # inherited from ICallableInfo. class ICallbackInfo < ICallableInfo end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_registered_type_info.rb0000644000004100000410000000070313170036060026201 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIRegisteredTypeInfo struct. # Represents a registered type. class IRegisteredTypeInfo < IBaseInfo def type_name Lib.g_registered_type_info_get_type_name @gobj end def type_init Lib.g_registered_type_info_get_type_init @gobj end def g_type Lib.g_registered_type_info_get_g_type @gobj end alias_method :gtype, :g_type end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_base_info.rb0000644000004100000410000000627713170036060023731 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps GIBaseInfo struct, the base \type for all info types. # Decendant types will be implemented as needed. class IBaseInfo def initialize(ptr, lib = Lib) raise ArgumentError, 'ptr must not be null' if ptr.null? ObjectSpace.define_finalizer self, self.class.make_finalizer(lib, ptr) @gobj = ptr @lib = lib end def self.make_finalizer(lib, ptr) proc { lib.g_base_info_unref ptr } end def to_ptr @gobj end # This is a helper method to construct a method returning an array, out # of the methods returning their number and the individual elements. # # For example, given the methods +n_foos+ and +foo+(+i+), this method # will create an additional method +foos+ returning all foos. # # Provide the second parameter if the plural is not trivially # constructed by adding +s+ to the singular. # # Examples: # # build_array_method :fields # build_array_mehtod :properties, :property # build_array_method :get_methods # def self.build_array_method(method, single = nil) method = method.to_s single ||= method.to_s[0..-2] count = method.sub(/^(get_)?/, '\\1n_') class_eval <<-CODE def #{method} (0..(#{count} - 1)).map do |i| #{single} i end end CODE end # This is a helper method to construct a method for finding an element, out # of the methods returning their number and the individual elements. # # For example, given the methods +n_foos+ and +foo+(+i+), this method will # create an additional method +find_foo+ returning the foo with the # matching name. # # Optionally provide counter and fetcher methods if they cannot be # trivially derived from the finder method. # # Examples: # # build_finder_method :find_field # build_finder_method :find_property, :n_properties # build_finder_method :find_method, :get_n_methods, :get_method # def self.build_finder_method(method, counter = nil, fetcher = nil) method = method.to_s single = method.sub(/^find_/, '') counter ||= "n_#{single}s" fetcher ||= single class_eval <<-CODE def #{method}(name) name = name.to_s #{counter}.times do |i| it = #{fetcher}(i) return it if it.name == name end nil end CODE end def name Lib.g_base_info_get_name @gobj end def info_type Lib.g_base_info_get_type @gobj end def namespace Lib.g_base_info_get_namespace @gobj end def safe_namespace namespace.gsub(/^./, &:upcase) end def container ptr = Lib.g_base_info_get_container @gobj Lib.g_base_info_ref ptr IRepository.wrap_ibaseinfo_pointer ptr end def deprecated? Lib.g_base_info_is_deprecated @gobj end def attribute(name) Lib.g_base_info_get_attribute @gobj, name end def self.wrap(ptr) new ptr unless ptr.null? end def ==(other) other.is_a?(IBaseInfo) && Lib.g_base_info_equal(@gobj, other) end end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_arg_info.rb0000644000004100000410000000172113170036060023555 0ustar www-datawww-data# frozen_string_literal: true require 'ffi-gobject_introspection/i_base_info' module GObjectIntrospection # Wraps a GIArgInfo struct. # Represents an argument. class IArgInfo < IBaseInfo def direction Lib.g_arg_info_get_direction @gobj end def return_value? Lib.g_arg_info_is_return_value @gobj end def optional? Lib.g_arg_info_is_optional @gobj end def caller_allocates? Lib.g_arg_info_is_caller_allocates @gobj end def may_be_null? Lib.g_arg_info_may_be_null @gobj end def skip? Lib.g_arg_info_is_skip @gobj end def ownership_transfer Lib.g_arg_info_get_ownership_transfer @gobj end def scope Lib.g_arg_info_get_scope @gobj end def closure Lib.g_arg_info_get_closure @gobj end def destroy Lib.g_arg_info_get_destroy @gobj end def argument_type ITypeInfo.wrap Lib.g_arg_info_get_type(@gobj) end end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/g_error.rb0000644000004100000410000000061513170036060023121 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps GLib's GError struct. class GError # GLib's GError struct. class Struct < FFI::Struct layout :domain, :uint32, :code, :int, :message, :string end def initialize(ptr) @struct = self.class::Struct.new(ptr) end def message @struct[:message] end end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_constant_info.rb0000644000004100000410000000211113170036060024627 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIConstantInfo struct; represents a constant. class IConstantInfo < IBaseInfo TYPE_TAG_TO_UNION_MEMBER = { gboolean: :v_boolean, gint8: :v_int8, gint16: :v_int16, gint32: :v_int32, gint64: :v_int64, guint8: :v_uint8, guint16: :v_uint16, guint32: :v_uint32, guint64: :v_uint64, gdouble: :v_double, utf8: :v_string }.freeze def value case type_tag when :utf8 raw_value.force_encoding('utf-8') when :gboolean raw_value.nonzero? ? true : false else raw_value end end def constant_type ITypeInfo.wrap Lib.g_constant_info_get_type self end private def type_tag @type_tag ||= constant_type.tag end def raw_value value_union = Lib::GIArgument.new Lib.g_constant_info_get_value self, value_union value_union[union_member_key] end def union_member_key TYPE_TAG_TO_UNION_MEMBER[type_tag] end end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/strv.rb0000644000004100000410000000132613170036060022460 0ustar www-datawww-data# frozen_string_literal: true require 'ffi' module GObjectIntrospection # Represents a null-terminated array of strings. # GLib uses this # construction, but does not provide any actual functions for this class. class Strv include Enumerable POINTER_SIZE = FFI.type_size(:pointer) def initialize(ptr) @ptr = ptr end def to_ptr @ptr end def each offset = 0 while (ptr = fetch_ptr offset) offset += POINTER_SIZE yield ptr.read_string end end def self.wrap(ptr) new ptr end private def fetch_ptr(offset) return if @ptr.null? ptr = @ptr.get_pointer offset ptr unless ptr.null? end end end gir_ffi-0.11.4/lib/ffi-gobject_introspection/i_union_info.rb0000644000004100000410000000146613170036060024142 0ustar www-datawww-data# frozen_string_literal: true module GObjectIntrospection # Wraps a GIUnionInfo struct. # Represents a union. class IUnionInfo < IRegisteredTypeInfo def n_fields Lib.g_union_info_get_n_fields @gobj end def field(index) IFieldInfo.wrap Lib.g_union_info_get_field(@gobj, index) end ## build_array_method :fields def get_n_methods Lib.g_union_info_get_n_methods @gobj end def get_method(index) IFunctionInfo.wrap Lib.g_union_info_get_method(@gobj, index) end ## build_array_method :get_methods def find_method(name) IFunctionInfo.wrap Lib.g_union_info_find_method(@gobj, name.to_s) end def size Lib.g_union_info_get_size @gobj end def alignment Lib.g_union_info_get_alignment @gobj end end end gir_ffi-0.11.4/lib/ffi-gobject.rb0000644000004100000410000000760113170036060016504 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/core' # Bypass check for existing modules GirFFI::Builders::ModuleBuilder.new('GObject').generate require 'ffi-gobject/value' require 'ffi-gobject/initially_unowned' require 'ffi-gobject/closure' require 'ffi-gobject/object' require 'ffi-gobject/object_class' require 'ffi-gobject/param_spec' require 'ffi-gobject/ruby_closure' require 'gir_ffi/signal_not_found_error' # Module representing GLib's GObject namespace. module GObject def self.type_from_instance_pointer(inst_ptr) return nil if inst_ptr.null? klsptr = inst_ptr.get_pointer 0 klsptr.get_gtype 0 end def self.type_from_instance(instance) type_from_instance_pointer instance.to_ptr end def self.type_name_from_instance(instance) type_name type_from_instance instance end def self.object_class_from_instance(instance) object_class_from_instance_pointer instance.to_ptr end def self.object_class_from_instance_pointer(inst_ptr) return nil if inst_ptr.null? klsptr = inst_ptr.get_pointer 0 ObjectClass.wrap klsptr end def self.signal_lookup_from_instance(signal, object) signal_lookup signal, type_from_instance(object) end def self.signal_emit(object, detailed_signal, *args) signal, detail = detailed_signal.split('::') signal_id = signal_lookup_from_instance signal, object detail_quark = GLib.quark_from_string(detail) sig_info = object.class.find_signal signal argument_gvalues = sig_info.arguments_to_gvalues object, args return_gvalue = sig_info.gvalue_for_return_value result = signal_emitv argument_gvalues, signal_id, detail_quark, return_gvalue # NOTE: Depending on the version of GObjectIntrospection, the result will # be stored in result or return_gvalue. This was changed between versions # 1.44 and 1.46. result || return_gvalue.get_value end def self.signal_connect(object, detailed_signal, data = nil, after = false, &block) raise ArgumentError, 'Block needed' unless block_given? signal_name, = detailed_signal.split('::') sig_info = object.class.find_signal signal_name closure = sig_info.wrap_in_closure do |*args| block.call(*args << data) end signal_connect_closure object, detailed_signal, closure, after end def self.signal_connect_after(object, detailed_signal, data = nil, &block) signal_connect object, detailed_signal, data, true, &block end load_class :Callback load_class :ClosureNotify load_class :ConnectFlags load_class :ClosureMarshal load_class :ParamFlags # NOTE: This Lib module is set up in `gir_ffi-base/gobject/lib.rb`. module Lib attach_function :g_object_ref_sink, [:pointer], :pointer attach_function :g_object_ref, [:pointer], :pointer attach_function :g_object_unref, [:pointer], :pointer attach_function :g_value_copy, [:pointer, :pointer], :void attach_function :g_value_init, [:pointer, :size_t], :pointer attach_function :g_value_unset, [:pointer], :pointer attach_function :g_array_get_type, [], :size_t attach_function :g_byte_array_get_type, [], :size_t attach_function :g_hash_table_get_type, [], :size_t attach_function :g_strv_get_type, [], :size_t attach_function :g_signal_connect_data, [:pointer, :string, Callback, :pointer, ClosureNotify, ConnectFlags], :ulong attach_function :g_closure_ref, [:pointer], :pointer attach_function :g_closure_sink, [:pointer], :pointer attach_function :g_closure_set_marshal, [:pointer, ClosureMarshal], :void attach_function :g_param_spec_ref, [:pointer], :pointer attach_function :g_param_spec_sink, [:pointer], :pointer attach_function :g_type_class_ref, [:size_t], :pointer end TYPE_ARRAY = Lib.g_array_get_type TYPE_BYTE_ARRAY = Lib.g_byte_array_get_type TYPE_HASH_TABLE = Lib.g_hash_table_get_type TYPE_STRV = Lib.g_strv_get_type end gir_ffi-0.11.4/lib/ffi-gobject_introspection.rb0000644000004100000410000000411713170036060021463 0ustar www-datawww-data# frozen_string_literal: true require 'ffi-gobject_introspection/gobject_type_init' GObjectIntrospection::GObjectTypeInit.type_init require 'ffi-gobject_introspection/i_base_info' require 'ffi-gobject_introspection/i_callable_info' require 'ffi-gobject_introspection/i_callback_info' require 'ffi-gobject_introspection/i_function_info' require 'ffi-gobject_introspection/i_constant_info' require 'ffi-gobject_introspection/i_field_info' require 'ffi-gobject_introspection/i_registered_type_info' require 'ffi-gobject_introspection/i_interface_info' require 'ffi-gobject_introspection/i_property_info' require 'ffi-gobject_introspection/i_vfunc_info' require 'ffi-gobject_introspection/i_signal_info' require 'ffi-gobject_introspection/i_object_info' require 'ffi-gobject_introspection/i_struct_info' require 'ffi-gobject_introspection/i_value_info' require 'ffi-gobject_introspection/i_union_info' require 'ffi-gobject_introspection/i_enum_info' require 'ffi-gobject_introspection/i_flags_info' require 'ffi-gobject_introspection/i_unresolved_info' module GObjectIntrospection # Map info type to class. Default is IBaseInfo. TYPEMAP = { invalid: IBaseInfo, function: IFunctionInfo, callback: ICallbackInfo, struct: IStructInfo, # TODO: There's no GIBoxedInfo, so what does :boxed mean? boxed: IBaseInfo, enum: IEnumInfo, flags: IFlagsInfo, object: IObjectInfo, interface: IInterfaceInfo, constant: IConstantInfo, invalid_was_error_domain: IBaseInfo, union: IUnionInfo, value: IValueInfo, signal: ISignalInfo, vfunc: IVFuncInfo, property: IPropertyInfo, field: IFieldInfo, arg: IArgInfo, type: ITypeInfo, unresolved: IUnresolvedInfo }.freeze end require 'ffi-gobject_introspection/i_repository' gir_ffi-0.11.4/lib/ffi-glib.rb0000644000004100000410000000405313170036060016002 0ustar www-datawww-data# frozen_string_literal: true # Ensure GLib is defined by GirFFI itself raise 'The module GLib was already defined elsewhere' if Kernel.const_defined? :GLib require 'gir_ffi/core' # Bypass check for existing modules GirFFI::Builders::ModuleBuilder.new('GLib').generate require 'ffi-glib/array' require 'ffi-glib/byte_array' require 'ffi-glib/bytes' require 'ffi-glib/destroy_notify' require 'ffi-glib/error' require 'ffi-glib/hash_table' require 'ffi-glib/iconv' require 'ffi-glib/list' require 'ffi-glib/main_loop' require 'ffi-glib/ptr_array' require 'ffi-glib/s_list' require 'ffi-glib/strv' require 'ffi-glib/variant' # Module representing GLib's GLib namespace. module GLib load_class :HFunc load_class :HashFunc load_class :EqualFunc load_class :Func # Module for attaching functions from the glib library. # NOTE: This module is defined by the call to GirFFI.setup above. module Lib attach_function :g_slist_prepend, [:pointer, :pointer], :pointer attach_function :g_list_append, [:pointer, :pointer], :pointer attach_function :g_hash_table_foreach, [:pointer, HFunc, :pointer], :void attach_function :g_hash_table_new, [HashFunc, EqualFunc], :pointer attach_function :g_hash_table_insert, [:pointer, :pointer, :pointer], :void attach_function :g_byte_array_new, [], :pointer attach_function :g_byte_array_append, [:pointer, :pointer, :uint], :pointer attach_function :g_bytes_get_data, [:pointer, :pointer], :pointer attach_function :g_bytes_new, [:pointer, :size_t], :pointer attach_function :g_array_new, [:int, :int, :uint], :pointer attach_function :g_array_append_vals, [:pointer, :pointer, :uint], :pointer attach_function :g_array_get_element_size, [:pointer], :uint attach_function :g_ptr_array_new, [], :pointer attach_function :g_ptr_array_add, [:pointer, :pointer], :void attach_function :g_ptr_array_foreach, [:pointer, Func, :pointer], :pointer attach_function :g_iconv_open, [:pointer, :pointer], :pointer attach_function :g_variant_ref_sink, [:pointer], :pointer end end gir_ffi-0.11.4/lib/ffi-gobject/0000755000004100000410000000000013170036060016153 5ustar www-datawww-datagir_ffi-0.11.4/lib/ffi-gobject/ruby_closure.rb0000644000004100000410000000271213170036060021217 0ustar www-datawww-data# frozen_string_literal: true require 'ffi-gobject/closure' module GObject # Encapsulates Ruby blocks as GObject Closures. class RubyClosure < Closure # @api private BLOCK_STORE = {} # Extend the standard +GObject::Closure+ layout with a field block_id to store # the object_id of the associated block. # # @api private class Struct < GirFFI::Struct layout :parent, Closure::Struct, 0, :block_id, :int64 end def initialize(&block) raise ArgumentError unless block_given? initialize_simple(self.class::Struct.size, nil) self.block = block set_marshal proc { |*args| self.class.marshaller(*args) } end # @api private def self.marshaller(closure, return_value, param_values, _invocation_hint, _marshal_data) # TODO: Improve by registering RubyClosure as a GObject type rclosure = wrap(closure.to_ptr) param_values ||= [] args = param_values.map(&:get_value) result = rclosure.invoke_block(*args) return_value.set_value(result) if return_value end # @api private # TODO: Re-structure so invoke_block can become a private method def invoke_block(*args) block.call(*args) end private # @api private def block=(block) id = block.object_id BLOCK_STORE[id] = block @struct[:block_id] = id end def block BLOCK_STORE[@struct[:block_id]] end end end gir_ffi-0.11.4/lib/ffi-gobject/value.rb0000644000004100000410000001226313170036060017620 0ustar www-datawww-data# frozen_string_literal: true GObject.load_class :Value module GObject # Overrides for GValue, GObject's generic value container structure. class Value remove_method :init def initialize super struct.owned = true to_ptr.autorelease = nil end def init(type) Lib.g_value_init self, type unless [TYPE_NONE, TYPE_INVALID].include? type self end def self.make_finalizer(struct) proc do if struct.owned? ptr = struct.to_ptr unless struct[:g_type] == TYPE_INVALID Lib.g_value_unset ptr end GObject.boxed_free gtype, ptr end end end METHOD_MAP = { TYPE_INVALID => [:get_none, :set_none], # TYPE_NONE is skipped TYPE_INTERFACE => [:get_object, :set_instance_enhanced], TYPE_CHAR => [:get_schar, :set_schar], TYPE_UCHAR => [:get_uchar, :set_uchar], TYPE_BOOLEAN => [:get_boolean, :set_boolean], TYPE_INT => [:get_int, :set_int], TYPE_UINT => [:get_uint, :set_uint], TYPE_LONG => [:get_long, :set_long], TYPE_ULONG => [:get_ulong, :set_ulong], TYPE_INT64 => [:get_int64, :set_int64], TYPE_UINT64 => [:get_uint64, :set_uint64], TYPE_ENUM => [:get_enum_enhanced, :set_enum_enhanced], TYPE_FLAGS => [:get_flags, :set_flags], TYPE_FLOAT => [:get_float, :set_float], TYPE_DOUBLE => [:get_double, :set_double], TYPE_STRING => [:get_string, :set_string], TYPE_POINTER => [:get_pointer, :set_pointer], TYPE_BOXED => [:get_boxed, :set_boxed], TYPE_PARAM => [:get_param, :set_param], TYPE_OBJECT => [:get_object, :set_instance_enhanced], TYPE_GTYPE => [:get_gtype, :set_gtype], TYPE_VARIANT => [:get_variant, :set_variant] }.freeze def set_value(val) send set_method, val end alias_method :value=, :set_value def current_gtype @struct[:g_type] end def current_fundamental_type GObject.type_fundamental current_gtype end def current_gtype_name GObject.type_name current_gtype end def get_value value = get_value_plain if current_fundamental_type == TYPE_BOXED wrap_boxed value else value end end def get_value_plain send get_method end # TODO: Give more generic name def self.wrap_ruby_value(val) new.tap { |gv| gv.__send__ :set_ruby_value, val } end def self.from(val) case val when self val else wrap_ruby_value val end end def self.for_gtype(gtype) new.tap do |it| it.init gtype end end # TODO: Combine with wrap_ruby_value def self.wrap_instance(instance) new.tap do |it| it.init GObject.type_from_instance instance it.set_instance instance end end def self.copy_value_to_pointer(value, pointer, offset = 0) target = wrap(pointer + offset) target.init(value.current_gtype) Lib.g_value_copy value, target unless value.uninitialized? end def uninitialized? current_gtype == TYPE_INVALID end private def set_ruby_value(val) init_for_ruby_value val if uninitialized? set_value val end CLASS_TO_GTYPE_MAP = { NilClass => TYPE_INVALID, TrueClass => TYPE_BOOLEAN, FalseClass => TYPE_BOOLEAN, Integer => TYPE_INT, String => TYPE_STRING }.freeze def init_for_ruby_value(val) if val.class.respond_to? :gtype return init val.class.gtype end CLASS_TO_GTYPE_MAP.each do |klass, type| return init type if val.is_a? klass end raise "Can't handle #{val.class}" end def set_none(_); end def get_none; end def set_instance_enhanced(val) check_type_compatibility val if val set_instance val end def set_enum_enhanced(val) val = current_gtype_class[val] if val.is_a? Symbol set_enum val end def get_enum_enhanced current_gtype_class.wrap(get_enum) end def current_gtype_class GirFFI::Builder.build_by_gtype(current_gtype) end def check_type_compatibility(val) unless GObject::Value.type_compatible(GObject.type_from_instance(val), current_gtype) raise ArgumentError, "#{val.class} is incompatible with #{current_gtype_name}" end end def wrap_boxed(boxed) case current_gtype when TYPE_STRV GLib::Strv.wrap boxed when TYPE_HASH_TABLE GLib::HashTable.wrap [:gpointer, :gpointer], boxed when TYPE_ARRAY GLib::Array.wrap nil, boxed else current_gtype_class.wrap(boxed) unless boxed.null? end end def get_method method_map_entry.first end def set_method method_map_entry.last end def method_map_entry METHOD_MAP[current_gtype] || METHOD_MAP[current_fundamental_type] || raise("No method map entry for #{current_gtype_name}") end end end gir_ffi-0.11.4/lib/ffi-gobject/object.rb0000644000004100000410000001210313170036060017743 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/property_not_found_error' GObject.load_class :Object module GObject # Overrides for GObject, GObject's generic base class. class Object setup_method 'new' if !GLib.check_version(2, 54, 0) setup_method 'newv' def initialize_with_automatic_gtype(properties = {}) names = [] values = [] properties.each do |name, value| name = name.to_s gvalue = gvalue_for_property(name) gvalue.set_value value names << name values << gvalue end initialize_without_automatic_gtype(self.class.gtype, names, values) end else def initialize_with_automatic_gtype(properties = {}) gparameters = properties.map do |name, value| name = name.to_s property_param_spec(name) GObject::Parameter.new.tap do |gparam| gparam.name = name gparam.value = value end end initialize_without_automatic_gtype(self.class.gtype, gparameters) end end alias_method :initialize_without_automatic_gtype, :initialize alias_method :initialize, :initialize_with_automatic_gtype alias_method :base_initialize, :initialize private :base_initialize remove_method :ref def ref Lib.g_object_ref self self end def store_pointer(ptr) super ObjectSpace.define_finalizer self, self.class.make_finalizer(ptr) end def self.make_finalizer(ptr) proc do rc = GObject::Object::Struct.new(ptr)[:ref_count] if rc.zero? warn "not unreffing #{name}:#{ptr} (#{rc})" else GObject::Lib.g_object_unref ptr end end end # TODO: Generate accessor methods from GIR at class definition time def method_missing(method, *args) getter_name = "get_#{method}" return send(getter_name, *args) if respond_to?(getter_name) if method.to_s =~ /(.*)=$/ setter_name = "set_#{Regexp.last_match[1]}" return send(setter_name, *args) if respond_to?(setter_name) end super end def respond_to_missing?(*) false end def signal_connect(event, data = nil, &block) GObject.signal_connect(self, event, data, &block) end def signal_connect_after(event, data = nil, &block) GObject.signal_connect_after(self, event, data, &block) end setup_instance_method 'get_property' setup_instance_method 'set_property' def get_property_extended(property_name) value = get_property(property_name) type_info = get_property_type property_name property_value_post_conversion value, type_info end def get_property_with_override(property_name) gvalue = gvalue_for_property property_name get_property_without_override property_name, gvalue gvalue.get_value end def set_property_extended(property_name, value) type_info = get_property_type property_name adjusted_value = property_value_pre_conversion(value, type_info) set_property property_name, adjusted_value end def set_property_with_override(property_name, value) gvalue = gvalue_for_property(property_name) gvalue.set_value value set_property_without_override property_name, gvalue end alias_method :get_property_without_override, :get_property alias_method :get_property, :get_property_with_override alias_method :set_property_without_override, :set_property alias_method :set_property, :set_property_with_override setup_instance_method 'is_floating' alias_method :floating?, :is_floating private def get_property_type(property_name) prop = self.class.find_property(property_name) prop.property_type end def gvalue_for_property(property_name) gtype = property_gtype property_name GObject::Value.for_gtype gtype end def property_gtype(property_name) pspec = property_param_spec(property_name) pspec.value_type end def property_param_spec(property_name) object_class.find_property property_name or raise GirFFI::PropertyNotFoundError.new(property_name, self.class) end # TODO: Move to ITypeInfo and unify with ArgHelper.cast_from_pointer def property_value_post_conversion(val, type_info) case type_info.flattened_tag when :ghash GLib::HashTable.from type_info.element_type, val when :glist GLib::List.from type_info.element_type, val when :callback GirFFI::Builder.build_class(type_info.interface).wrap val else val end end # TODO: Move to ITypeInfo and unify with ArgHelper.cast_from_pointer def property_value_pre_conversion(val, type_info) case type_info.flattened_tag when :ghash GLib::HashTable.from type_info.element_type, val when :glist GLib::List.from type_info.element_type, val when :strv GLib::Strv.from val when :callback GirFFI::Builder.build_class(type_info.interface).from val else val end end end end gir_ffi-0.11.4/lib/ffi-gobject/closure.rb0000644000004100000410000000255613170036060020164 0ustar www-datawww-data# frozen_string_literal: true GObject.load_class :Closure module GObject # Overrides for GClosure, GObject's base class for closure objects. # # To create Closure objects wrapping Ruby code, use {RubyClosure}. class Closure setup_method :new_simple setup_instance_method :invoke # @override # # @param [Proc] marshal The marshaller to use for this closure object def set_marshal(marshal) callback = ClosureMarshal.from marshal Lib.g_closure_set_marshal self, callback end # @override # # This override of invoke ensures the return value location can be passed # in as the first argument, which is needed to ensure the GValue is # initialized with the proper type. # # @param [GObject::Value] return_value The GValue to store the return # value, or nil if no return value is expected. # @param [Array] param_values the closure parameters. def invoke(return_value, param_values) rval = Value.from(return_value) n_params = param_values.length params = GirFFI::SizedArray.from(Value, -1, param_values) Lib.g_closure_invoke self, rval, n_params, params, nil rval.get_value end def store_pointer(ptr) # NOTE: Call C functions directly to avoid extra argument conversion Lib.g_closure_ref ptr Lib.g_closure_sink ptr super end end end gir_ffi-0.11.4/lib/ffi-gobject/initially_unowned.rb0000644000004100000410000000072113170036060022235 0ustar www-datawww-data# frozen_string_literal: true GObject.load_class :InitiallyUnowned module GObject # Overrides for GInitiallyUnowned, GObject's base class for objects that # start with a floating reference. class InitiallyUnowned # Initializing method used in constructors. For InitiallyUnowned and # descendants, this needs to sink the object's floating reference. def store_pointer(ptr) super ::GObject::Lib.g_object_ref_sink ptr end end end gir_ffi-0.11.4/lib/ffi-gobject/param_spec.rb0000644000004100000410000000046413170036060020616 0ustar www-datawww-data# frozen_string_literal: true GObject.load_class :ParamSpec module GObject # Overrides for GParamSpec, GObject's base class for parameter specifications. class ParamSpec def ref Lib.g_param_spec_ref self self end def accessor_name get_name.tr('-', '_') end end end gir_ffi-0.11.4/lib/ffi-gobject/object_class.rb0000644000004100000410000000071713170036060021140 0ustar www-datawww-data# frozen_string_literal: true GObject.load_class :ObjectClass module GObject # Overrides for GObjectClass, a struct containing GObject's class data class ObjectClass def set_property=(callback) @struct[:set_property] = GObject::ObjectSetPropertyFunc.from callback end def get_property=(callback) @struct[:get_property] = GObject::ObjectGetPropertyFunc.from callback end def gtype to_ptr.get_gtype 0 end end end gir_ffi-0.11.4/lib/gir_ffi/0000755000004100000410000000000013170036060015401 5ustar www-datawww-datagir_ffi-0.11.4/lib/gir_ffi/ffi_ext.rb0000644000004100000410000000010113170036060017342 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/ffi_ext/pointer' gir_ffi-0.11.4/lib/gir_ffi/module_base.rb0000644000004100000410000000130013170036060020177 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Base module for modules representing GLib namespaces. module ModuleBase def method_missing(method, *arguments, &block) result = setup_method method.to_s return super unless result send method, *arguments, &block end def respond_to_missing?(method, *) gir_ffi_builder.method_available? method end def const_missing(classname) load_class(classname) end def load_class(classname) gir_ffi_builder.build_namespaced_class classname.to_s end def gir_ffi_builder self::GIR_FFI_BUILDER end def setup_method(name) gir_ffi_builder.setup_method name end end end gir_ffi-0.11.4/lib/gir_ffi/sized_array.rb0000644000004100000410000000522613170036060020247 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Class representing an array with a determined size class SizedArray include Enumerable attr_reader :element_type, :size def initialize(element_type, size, pointer) @element_type = element_type @size = size @pointer = pointer end def to_ptr @pointer end def index(idx) ptr = InOutPointer.new element_type, @pointer + idx * element_size ptr.to_ruby_value end def each size.times do |idx| yield index(idx) end end def ==(other) to_a.eql? other.to_a end def size_in_bytes size * element_size end def self.get_value_from_pointer(pointer, offset) pointer + offset end def self.copy_value_to_pointer(value, pointer) size = value.size_in_bytes pointer.put_bytes(0, value.to_ptr.read_bytes(size)) end def self.wrap(element_type, size, pointer) new element_type, size, pointer unless pointer.null? end private def element_ffi_type @element_ffi_type ||= TypeMap.type_specification_to_ffi_type element_type end def element_size @element_size ||= FFI.type_size element_ffi_type end class << self def from(element_type, size, item) return unless item case item when FFI::Pointer wrap element_type, size, item when self from_sized_array size, item else from_enumerable element_type, size, item end end def copy_from(element_type, size, item) return unless item enumerable = case item when FFI::Pointer wrap(element_type, size, item).to_a when self item.to_a else item end case element_type when Array _main_type, sub_type = *element_type enumerable = enumerable.map { |it| sub_type.copy_from it } end from_enumerable element_type, size, enumerable end private def from_sized_array(size, sized_array) check_size size, sized_array.size sized_array end def from_enumerable(element_type, expected_size, arr) size = arr.size check_size expected_size, size ptr = InPointer.from_array element_type, arr wrap element_type, size, ptr end def check_size(expected_size, size) if expected_size != -1 && size != expected_size raise ArgumentError, "Expected size #{expected_size}, got #{size}" end end end end end gir_ffi-0.11.4/lib/gir_ffi/user_defined_object_info.rb0000644000004100000410000000307113170036060022724 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/user_defined_property_info' require 'gir_ffi/vfunc_implementation' module GirFFI # Represents a user defined type, conforming, as needed, to the interface of # GObjectIntrospection::IObjectInfo. class UserDefinedObjectInfo attr_reader :properties, :vfunc_implementations def initialize(klass) @klass = klass @properties = [] @vfunc_implementations = [] yield self if block_given? end def described_class @klass end def install_property(property) @properties << UserDefinedPropertyInfo.new(property) end def install_vfunc_implementation(name, implementation = nil) implementation ||= ->(obj, *args) { obj.public_send name, *args } @vfunc_implementations << VFuncImplementation.new(name, implementation) end def find_method(_method) nil end def find_instance_method(_method) nil end def parent_gtype @parent_gtype ||= GType.new(@klass.superclass.gtype) end def parent @parent ||= gir.find_by_gtype(parent_gtype.to_i) end # TODO: Create custom class that includes the interfaces instead def class_struct parent.class_struct end def interfaces (@klass.included_modules - @klass.superclass.included_modules).map(&:gir_info) end def find_signal(_signal_name) nil end attr_writer :g_name def g_name @g_name ||= @klass.name end private def gir @gir ||= GObjectIntrospection::IRepository.default end end end gir_ffi-0.11.4/lib/gir_ffi/flags_base.rb0000644000004100000410000000102713170036060020014 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/enum_like_base' module GirFFI # Base module for flags. module FlagsBase include EnumLikeBase def native_type self::BitMask.native_type end def to_native(value, context) case value when Symbol value = { value => true } end self::BitMask.to_native(value, context) end def from_native(*args) self::BitMask.from_native(*args).select { |_k, v| v } end def [](arg) self::BitMask[arg] end end end gir_ffi-0.11.4/lib/gir_ffi/signal_not_found_error.rb0000644000004100000410000000053613170036060022473 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Exception class to be raised when a signal is not found. class SignalNotFoundError < RuntimeError attr_reader :signal_name def initialize(signal_name, klass) @signal_name = signal_name @klass = klass super "Signal '#{signal_name}' not found in #{klass}" end end end gir_ffi-0.11.4/lib/gir_ffi/interface_base.rb0000644000004100000410000000132213170036060020656 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/registered_type_base' module GirFFI # Base module for modules representing GLib interfaces. module InterfaceBase include RegisteredTypeBase def setup_and_call(method, arguments, &block) method_name = setup_method method.to_s unless method_name raise NoMethodError, "undefined method `#{method}' for #{self}" end send method_name, *arguments, &block end def setup_instance_method(name) gir_ffi_builder.setup_instance_method name end def setup_method(name) gir_ffi_builder.setup_method name end def wrap(ptr) ptr.to_object end def to_ffi_type :pointer end end end gir_ffi-0.11.4/lib/gir_ffi/unintrospectable_boxed_info.rb0000644000004100000410000000117013170036060023502 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/info_ext/full_type_name' module GirFFI # Represents a boxed type not found in the GIR, conforming, as needed, to the # interface of GObjectIntrospection::IUnionInfo and GObjectIntrospection::IStructInfo. class UnintrospectableBoxedInfo attr_reader :g_type def initialize(gtype) @g_type = gtype end def info_type :unintrospectable_boxed end def safe_name GObject.type_name g_type end DEFAULT_BOXED_NAMESPACE = 'GLib'.freeze def namespace DEFAULT_BOXED_NAMESPACE end def fields [] end end end gir_ffi-0.11.4/lib/gir_ffi/g_type.rb0000644000004100000410000000073313170036060017220 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Wrapper class providing extended functionality for a GType, which is # normally just a kind of integer class GType def initialize(gtype) @gtype = gtype end def to_i @gtype end def class_size type_query.class_size end def instance_size type_query.instance_size end private def type_query @type_query ||= GObject.type_query @gtype end end end gir_ffi-0.11.4/lib/gir_ffi/class_base.rb0000644000004100000410000000561013170036060020027 0ustar www-datawww-data# frozen_string_literal: true require 'forwardable' require 'gir_ffi/registered_type_base' require 'gir_ffi/builders/null_class_builder' module GirFFI # Base class for all generated classes and structs. Contains code for dealing # with the generated nested Struct classes. class ClassBase extend RegisteredTypeBase extend Forwardable GIR_FFI_BUILDER = Builders::NullClassBuilder.new attr_reader :struct def_delegators :@struct, :to_ptr def setup_and_call(method, arguments, &block) method_name = self.class.try_in_ancestors(:setup_instance_method, method.to_s) unless method_name raise NoMethodError, "undefined method `#{method}' for #{self}" end send method_name, *arguments, &block end # NOTE: JRuby should fix FFI::MemoryPointer#== to return true for # equivalent FFI::Pointer. For now, user to_ptr.address def ==(other) other.class == self.class && to_ptr.address == other.to_ptr.address end def self.setup_and_call(method, arguments, &block) method_name = try_in_ancestors(:setup_method, method.to_s) unless method_name raise NoMethodError, "undefined method `#{method}' for #{self}" end send method_name, *arguments, &block end def self.try_in_ancestors(method, *arguments) ancestors.each do |klass| if klass.respond_to?(method) result = klass.send(method, *arguments) return result if result end end nil end def self.to_ffi_type self::Struct end def self.setup_method(name) gir_ffi_builder.setup_method name end def self.setup_instance_method(name) gir_ffi_builder.setup_instance_method name end # Wrap the passed pointer in an instance of the current class, or a # descendant type if applicable. def self.wrap(ptr) direct_wrap ptr end # Wrap the passed pointer in an instance of the current class. Will not # do any casting to subtypes or additional processing. def self.direct_wrap(ptr) return nil if !ptr || ptr.null? obj = allocate obj.__send__ :assign_pointer, ptr obj end # Pass-through casting method. This may become a type checking # method. It is overridden by GValue to implement wrapping of plain # Ruby objects. def self.from(val) val end private # Stores a pointer created by a constructor function. Derived classes may # perform additional processing. For example, InitiallyUnowned overrides it # to sink the floating object. # # This method assumes the pointer will always be of the type corresponding # to the current class, and never of a subtype. # # @param ptr Pointer to the object's C structure def store_pointer(ptr) assign_pointer ptr end def assign_pointer(ptr) @struct = self.class::Struct.new(ptr) end end end gir_ffi-0.11.4/lib/gir_ffi/callback_base.rb0000644000004100000410000000416013170036060020455 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/type_base' module GirFFI # Base module for callbacks and vfuncs. # NOTE: Another option would be to derive this class from FFI::Function, # allowing a more natural implementation of from_native, to_native and wrap. class CallbackBase < Proc extend TypeBase extend FFI::DataConverter def self.native_type FFI::Type::POINTER end # TODO: Return instance of this class def self.from_native(value, _context) return nil if !value || value.null? FFI::Function.new(gir_ffi_builder.return_ffi_type, gir_ffi_builder.argument_ffi_types, value) end def self.to_native(value, _context) case value when CallbackBase value.to_native when FFI::Function value end end def self.wrap(ptr) from_native ptr, nil end CALLBACKS = {} def self.store_callback(prc) CALLBACKS[prc.object_id] = prc end def self.drop_callback(prc) CALLBACKS.delete prc.object_id end # Create Callback from a Proc. Makes sure arguments are properly wrapped, # and the callback is stored to prevent garbage collection. def self.from(prc) wrap_proc(prc).tap do |cb| store_callback cb end end def self.wrap_proc(prc) return unless prc new do |*args| begin call_with_argument_mapping(prc, *args) rescue StandardError => e GLib::MainLoop.handle_exception e end end end def self.to_ffi_type self end def to_native @to_native ||= begin builder = self.class.gir_ffi_builder FFI::Function.new(builder.return_ffi_type, builder.argument_ffi_types, self) end end def to_ptr to_native.to_ptr end def self.copy_value_to_pointer(value, pointer) pointer.put_pointer 0, to_native(value, nil) end def self.get_value_from_pointer(pointer, offset) from_native pointer.get_pointer(offset), nil end end end gir_ffi-0.11.4/lib/gir_ffi/type_base.rb0000644000004100000410000000034213170036060017700 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Base module for all generated GLib types. module TypeBase def gir_ffi_builder self::GIR_FFI_BUILDER end def gir_info self::GIR_INFO end end end gir_ffi-0.11.4/lib/gir_ffi/vfunc_implementation.rb0000644000004100000410000000045313170036060022156 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Simple wrapper class to represent the implementation of a VFunc. class VFuncImplementation attr_reader :name, :implementation def initialize(name, implementation) @name = name @implementation = implementation end end end gir_ffi-0.11.4/lib/gir_ffi/receiver_argument_info.rb0000644000004100000410000000104313170036060022445 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Class to represent the info for the receiver argument of a callback or # signal handler. Implements the necessary parts of IArgumentInfo's # interface. class ReceiverArgumentInfo attr_reader :argument_type def initialize(type) @argument_type = type end def direction :in end # Assume we don't need to increase the refcount for the receiver argument. def ownership_transfer :everything end def name '_instance' end end end gir_ffi-0.11.4/lib/gir_ffi/error_argument_info.rb0000644000004100000410000000052413170036060021775 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/error_type_info' module GirFFI # Represents an error argument with the same interface as IArgumentInfo class ErrorArgumentInfo def direction :error end def argument_type @argument_type ||= ErrorTypeInfo.new end def name '_error' end end end gir_ffi-0.11.4/lib/gir_ffi/struct.rb0000644000004100000410000000024113170036060017247 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/ownable' module GirFFI # Struct that can be owned. class Struct < FFI::Struct include Ownable end end gir_ffi-0.11.4/lib/gir_ffi/receiver_type_info.rb0000644000004100000410000000076313170036060021614 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Represents the type of the receiver of a signal or vfunc, conforming, as # needed, to the interface of GObjectIntrospection::ITypeInfo class ReceiverTypeInfo include InfoExt::ITypeInfo def initialize(interface_info) @interface_info = interface_info end def interface @interface_info end def tag :interface end def pointer? false end def array_length -1 end end end gir_ffi-0.11.4/lib/gir_ffi/builder_helper.rb0000644000004100000410000000106113170036060020711 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Set of helper methods used in the builders. module BuilderHelper def optionally_define_constant(parent, name) if parent.const_defined? name, false parent.const_get name else parent.const_set name, yield end end def get_or_define_class(namespace, name, parent) optionally_define_constant(namespace, name) { Class.new parent } end def get_or_define_module(parent, name) optionally_define_constant(parent, name) { Module.new } end end end gir_ffi-0.11.4/lib/gir_ffi/property_not_found_error.rb0000644000004100000410000000055613170036060023104 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Exception class to be raised when a property is not found. class PropertyNotFoundError < RuntimeError attr_reader :property_name def initialize(property_name, klass) @property_name = property_name @klass = klass super "Property '#{property_name}' not found in #{klass}" end end end gir_ffi-0.11.4/lib/gir_ffi/object_base.rb0000644000004100000410000000330213170036060020164 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/class_base' module GirFFI # Base class for all generated classes of type :object. class ObjectBase < ClassBase extend FFI::DataConverter def object_class self.class.object_class end def self.native_type FFI::Type::POINTER end def self.to_ffi_type self end def self.to_native(it, _) it.to_ptr end def self.get_value_from_pointer(pointer, offset = 0) pointer.get_pointer offset end def self.copy_value_to_pointer(value, pointer, offset = 0) pointer.put_pointer offset, value.to_ptr end # Wrap the passed pointer in an instance of its type's corresponding class, # generally assumed to be a descendant of the current type. def self.wrap(ptr) ptr.to_object end def self.copy_from(val) val.ref if val end # # Find property info for the named property. # # @param name The property's name # # @return [GObjectIntrospection::IPropertyInfo] The property's info # def self.find_property(name) gir_ffi_builder.find_property name or raise GirFFI::PropertyNotFoundError.new(name, self) end # # Find signal info for the named signal. # # @param name The signal's name # # @return [GObjectIntrospection::ISignalInfo] The signal's info # def self.find_signal(name) gir_ffi_builder.find_signal name or raise GirFFI::SignalNotFoundError.new(name, self) end def self.object_class @object_class ||= begin ptr = GObject::Lib.g_type_class_ref(gtype) gir_ffi_builder.object_class_struct.wrap ptr end end end end gir_ffi-0.11.4/lib/gir_ffi/lib_c.rb0000644000004100000410000000041113170036060016772 0ustar www-datawww-data# frozen_string_literal: true require 'ffi' module GirFFI # Library of libc functions. module LibC extend FFI::Library ffi_lib FFI::Library::LIBC attach_function :malloc, [:size_t], :pointer attach_function :free, [:pointer], :void end end gir_ffi-0.11.4/lib/gir_ffi/in_out_pointer.rb0000644000004100000410000000224213170036060020763 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # The InOutPointer class handles conversion between ruby types and # pointers for arguments with direction :inout and :out. # class InOutPointer < FFI::Pointer attr_reader :value_type def initialize(type, ptr) @value_type = type super ptr end def to_value case value_ffi_type when Module value_ffi_type.get_value_from_pointer(self, 0) when Symbol send("get_#{value_ffi_type}", 0) else raise NotImplementedError end end # Convert more fully to a ruby value than #to_value def to_ruby_value bare_value = to_value case value_type when :utf8 bare_value.to_utf8 when Array value_type[1].wrap bare_value when Class value_type.wrap bare_value else bare_value end end def self.allocate_new(type) ffi_type = TypeMap.type_specification_to_ffi_type type ptr = FFI::MemoryPointer.new(ffi_type) new type, ptr end private def value_ffi_type @value_ffi_type ||= TypeMap.type_specification_to_ffi_type value_type end end end gir_ffi-0.11.4/lib/gir_ffi/method_stubber.rb0000644000004100000410000000071213170036060020734 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Generates method stubs that will replace themselves with the real # method upon being called. class MethodStubber def initialize(method_info) @info = method_info end def method_stub <<-STUB.reset_indentation def #{@info.method? ? '' : 'self.'}#{@info.safe_name} *args, &block setup_and_call "#{@info.name}", args, &block end STUB end end end gir_ffi-0.11.4/lib/gir_ffi/boxed_base.rb0000644000004100000410000000126613170036060020026 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/class_base' module GirFFI # Base class for generated classes representing boxed types. class BoxedBase < StructBase def initialize store_pointer(nil) end def self.make_finalizer(struct) proc do if struct.owned? struct.owned = nil GObject.boxed_free gtype, struct.to_ptr end end end def self.copy(val) ptr = GObject.boxed_copy(gtype, val) wrap(ptr) end private def store_pointer(*) super make_finalizer end def make_finalizer ObjectSpace.define_finalizer self, self.class.make_finalizer(struct) end end end gir_ffi-0.11.4/lib/gir_ffi/glib_error.rb0000644000004100000410000000066213170036060020060 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Exception class to be raised whenever an error is signaled through # GLib::Error. class GLibError < RuntimeError attr_reader :domain_quark attr_reader :code def initialize(g_error) @domain_quark = g_error.domain @code = g_error.code super g_error.message end def domain @domain ||= GLib.quark_to_string @domain_quark end end end gir_ffi-0.11.4/lib/gir_ffi/union_base.rb0000644000004100000410000000057213170036060020054 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/boxed_base' module GirFFI # Base class for generated classes representing GLib unions. class UnionBase < ClassBase extend FFI::DataConverter include GirFFI::StructLikeBase def initialize @struct = self.class::Struct.new @struct.owned = true @struct.to_ptr.autorelease = false end end end gir_ffi-0.11.4/lib/gir_ffi/variable_name_generator.rb0000644000004100000410000000043713170036060022565 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Generates a sequence of unique variable names used in generating # function definitions. class VariableNameGenerator def initialize @varno = 0 end def new_var @varno += 1 "_v#{@varno}" end end end gir_ffi-0.11.4/lib/gir_ffi/info_ext.rb0000644000004100000410000000116613170036060017545 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/info_ext/full_type_name' require 'gir_ffi/info_ext/i_arg_info' require 'gir_ffi/info_ext/i_callable_info' require 'gir_ffi/info_ext/i_callback_info' require 'gir_ffi/info_ext/i_field_info' require 'gir_ffi/info_ext/i_function_info' require 'gir_ffi/info_ext/i_property_info' require 'gir_ffi/info_ext/i_registered_type_info' require 'gir_ffi/info_ext/i_signal_info' require 'gir_ffi/info_ext/i_type_info' require 'gir_ffi/info_ext/i_unresolved_info' require 'gir_ffi/info_ext/i_vfunc_info' require 'gir_ffi/info_ext/safe_constant_name' require 'gir_ffi/info_ext/safe_function_name' gir_ffi-0.11.4/lib/gir_ffi/boolean.rb0000644000004100000410000000134413170036060017347 0ustar www-datawww-data# frozen_string_literal: true require 'ffi' module GirFFI # Class representing a boolean (natively, an int). class Boolean extend FFI::DataConverter native_type FFI::Type::INT FROM_NATIVE = { 0 => false, 1 => true }.freeze TO_NATIVE = FROM_NATIVE.invert def self.from_native(value, _context) FROM_NATIVE.fetch(value) end def self.to_native(value, _context) TO_NATIVE.fetch(value ? true : false) end def self.size FFI.type_size FFI::Type::INT end def self.copy_value_to_pointer(value, pointer) pointer.put_int 0, to_native(value, nil) end def self.get_value_from_pointer(pointer, offset) from_native pointer.get_int(offset), nil end end end gir_ffi-0.11.4/lib/gir_ffi/version.rb0000644000004100000410000000014613170036060017414 0ustar www-datawww-data# frozen_string_literal: true # Current GirFFI version module GirFFI VERSION = '0.11.4'.freeze end gir_ffi-0.11.4/lib/gir_ffi/ownable.rb0000644000004100000410000000070313170036060017355 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Module implementing the concept of ownership. Owned objects need to have # their memory freed or ref count lowered when they're garbage collected. # Note that this attribute is generally placed on the nested struct of an # object, and the relevant action is performed when the object's finalizer is # run. module Ownable attr_accessor :owned def owned? owned end end end gir_ffi-0.11.4/lib/gir_ffi/unintrospectable_signal_info.rb0000644000004100000410000000172613170036060023665 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Represents a signal not found in the GIR, conforming, as needed, to the # interface of GObjectIntrospection::ISignalInfo. class UnintrospectableSignalInfo attr_reader :signal_id def initialize(signal_id) @signal_id = signal_id end def name GObject.signal_name signal_id end def wrap_in_closure(&block) GObject::RubyClosure.new(&block) end def arguments_to_gvalues(instance, arguments) param_gtypes = signal_query.param_types || [] argument_gvalues = param_gtypes.zip(arguments).map do |gtype, arg| GObject::Value.for_gtype(gtype).tap { |it| it.set_value arg } end argument_gvalues.unshift GObject::Value.wrap_instance(instance) end def gvalue_for_return_value GObject::Value.for_gtype signal_query.return_type end private def signal_query @signal_query ||= GObject.signal_query signal_id end end end gir_ffi-0.11.4/lib/gir_ffi/unintrospectable_type_info.rb0000644000004100000410000000223213170036060023362 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/info_ext/full_type_name' module GirFFI # Represents a type not found in the GIR, conforming, as needed, to the # interface of GObjectIntrospection::IObjectInfo. class UnintrospectableTypeInfo attr_reader :g_type def initialize(gtype, gir = GObjectIntrospection::IRepository.default, gobject = GObject) @g_type = gtype @gir = gir @gobject = gobject end def info_type :unintrospectable end def safe_name @gobject.type_name @g_type end def parent @gir.find_by_gtype(parent_gtype) || self.class.new(parent_gtype, @gir, @gobject) end def parent_gtype @parent_gtype ||= @gobject.type_parent @g_type end def namespace parent.namespace end def interfaces @gobject.type_interfaces(@g_type).map do |gtype| @gir.find_by_gtype gtype end.compact end def fields [] end def find_signal(_any) nil end # TODO: Create custom class that includes the interfaces instead def class_struct parent.class_struct end end end gir_ffi-0.11.4/lib/gir_ffi/object_store.rb0000644000004100000410000000105713170036060020413 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Helper class for storing objects for later retrieval. Used to store user # data arguments. class ObjectStore def initialize @store = {} end def store(obj) return FFI::Pointer::NULL if obj.nil? # FIXME: Don't use object_id! key = obj.object_id @store[key] = obj FFI::Pointer.new(key) end def fetch(ptr) return if ptr.null? key = ptr.address if @store.key? key @store[key] else ptr end end end end gir_ffi-0.11.4/lib/gir_ffi/error_type_info.rb0000644000004100000410000000064313170036060021136 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/info_ext/i_type_info' module GirFFI # Represents the type of an error argument for callbacks and functions, # conforming, as needed, to the interface of GObjectIntrospection::ITypeInfo class ErrorTypeInfo include GirFFI::InfoExt::ITypeInfo def array_length -1 end def tag :error end def pointer? true end end end gir_ffi-0.11.4/lib/gir_ffi/core.rb0000644000004100000410000000164513170036060016664 0ustar www-datawww-data# frozen_string_literal: true require 'ffi' require 'ffi/bit_masks' require 'ffi-gobject_introspection' require 'gir_ffi-base' require 'gir_ffi/ffi_ext' require 'gir_ffi/class_base' require 'gir_ffi/type_map' require 'gir_ffi/info_ext' require 'gir_ffi/in_pointer' require 'gir_ffi/in_out_pointer' require 'gir_ffi/sized_array' require 'gir_ffi/zero_terminated' require 'gir_ffi/arg_helper' require 'gir_ffi/builder' require 'gir_ffi/user_defined_object_info' require 'gir_ffi/builders/user_defined_builder' require 'gir_ffi/version' module GirFFI # Core GirFFI interface. module Core def setup(namespace, version = nil) namespace = namespace.to_s Builder.build_module namespace, version end def define_type(klass, &block) info = UserDefinedObjectInfo.new(klass, &block) Builders::UserDefinedBuilder.new(info).build_class klass.gtype end end end GirFFI.extend GirFFI::Core gir_ffi-0.11.4/lib/gir_ffi/info_ext/0000755000004100000410000000000013170036060017214 5ustar www-datawww-datagir_ffi-0.11.4/lib/gir_ffi/info_ext/i_unresolved_info.rb0000644000004100000410000000047713170036060023262 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extensions for GObjectIntrospection::IUnresolvedInfo needed by GirFFI module IUnresolvedInfo def to_ffi_type :pointer end end end end GObjectIntrospection::IUnresolvedInfo.send :include, GirFFI::InfoExt::IUnresolvedInfo gir_ffi-0.11.4/lib/gir_ffi/info_ext/i_field_info.rb0000644000004100000410000000073713170036060022156 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extensions for GObjectIntrospection::IFieldInfo needed by GirFFI module IFieldInfo def layout_specification [name.to_sym, field_type.to_ffi_type, offset] end def related_array_length_field index = field_type.array_length container.fields[index] if index > -1 end end end end GObjectIntrospection::IFieldInfo.send :include, GirFFI::InfoExt::IFieldInfo gir_ffi-0.11.4/lib/gir_ffi/info_ext/i_vfunc_info.rb0000644000004100000410000000123613170036060022207 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extensions for GObjectIntrospection::IVFuncInfo needed by GirFFI # TODO: Merge implementation with ICallbackInfo and ISignalInfo extensions. module IVFuncInfo def argument_ffi_types args.map(&:to_callback_ffi_type).tap do |types| types << :pointer if throws? end end def return_ffi_type return_type.to_callback_ffi_type end def invoker_name invoker && invoker.name end def has_invoker? invoker end end end end GObjectIntrospection::IVFuncInfo.send :include, GirFFI::InfoExt::IVFuncInfo gir_ffi-0.11.4/lib/gir_ffi/info_ext/i_property_info.rb0000644000004100000410000000057313170036060022755 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extensions for GObjectIntrospection::IPropertyInfo needed by GirFFI module IPropertyInfo def getter_name name.tr('-', '_') end def setter_name "#{getter_name}=" end end end end GObjectIntrospection::IPropertyInfo.send :include, GirFFI::InfoExt::IPropertyInfo gir_ffi-0.11.4/lib/gir_ffi/info_ext/safe_constant_name.rb0000644000004100000410000000145713170036060023377 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extension module provinding a #safe_name method suitable for types. module SafeConstantName def safe_name name.tr('-', '_').gsub(/^./) do |char| case char when '_' 'Private___' else char.upcase end end end end end end GObjectIntrospection::ICallbackInfo.send :include, GirFFI::InfoExt::SafeConstantName GObjectIntrospection::IConstantInfo.send :include, GirFFI::InfoExt::SafeConstantName GObjectIntrospection::IRegisteredTypeInfo.send :include, GirFFI::InfoExt::SafeConstantName GObjectIntrospection::ISignalInfo.send :include, GirFFI::InfoExt::SafeConstantName GObjectIntrospection::IVFuncInfo.send :include, GirFFI::InfoExt::SafeConstantName gir_ffi-0.11.4/lib/gir_ffi/info_ext/i_signal_info.rb0000644000004100000410000000213513170036060022342 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extensions for GObjectIntrospection::ISignalInfo needed by GirFFI module ISignalInfo # Create a signal hander closure. Wraps the given block in a custom # descendent of RubyClosure with a marshaller tailored for this signal. # # @param block The body of the signal handler # # @return [GObject::RubyClosure] The signal handler closure, ready to be # passed as a GClosure to C. def wrap_in_closure(&block) bldr = Builders::SignalClosureBuilder.new(self) bldr.build_class.new(&block) end def arguments_to_gvalues(instance, arguments) arg_g_values = args.zip(arguments).map do |info, arg| info.argument_type.make_g_value.tap { |it| it.set_value arg } end arg_g_values.unshift GObject::Value.wrap_instance(instance) end def gvalue_for_return_value return_type.make_g_value end end end end GObjectIntrospection::ISignalInfo.send :include, GirFFI::InfoExt::ISignalInfo gir_ffi-0.11.4/lib/gir_ffi/info_ext/safe_function_name.rb0000644000004100000410000000056613170036060023373 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extension module provinding a #safe_name method suitable for functions. module SafeFunctionName def safe_name name = self.name return '_' if name.empty? name end end end end GObjectIntrospection::IFunctionInfo.send :include, GirFFI::InfoExt::SafeFunctionName gir_ffi-0.11.4/lib/gir_ffi/info_ext/i_type_info.rb0000644000004100000410000001512113170036060022045 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builder_helper' module GirFFI module InfoExt # Extensions for GObjectIntrospection::ITypeInfo needed by GirFFI module ITypeInfo def self.flattened_tag_to_gtype_map @flattened_tag_to_gtype_map ||= { [:array, true] => GObject::TYPE_ARRAY, [:c, true] => GObject::TYPE_POINTER, [:gboolean, false] => GObject::TYPE_BOOLEAN, [:ghash, true] => GObject::TYPE_HASH_TABLE, [:glist, true] => GObject::TYPE_POINTER, [:gint32, false] => GObject::TYPE_INT, [:gint64, false] => GObject::TYPE_INT64, [:guint64, false] => GObject::TYPE_UINT64, [:strv, true] => GObject::TYPE_STRV, [:utf8, true] => GObject::TYPE_STRING, [:void, true] => GObject::TYPE_POINTER, [:void, false] => GObject::TYPE_NONE }.freeze end def gtype return interface.gtype if tag == :interface ITypeInfo.flattened_tag_to_gtype_map.fetch [flattened_tag, pointer?] end def make_g_value GObject::Value.for_gtype gtype end def element_type case tag when :glist, :gslist, :array, :c enumerable_element_type when :ghash dictionary_element_type end end def flattened_tag case tag when :interface interface_type when :array flattened_array_type else tag end end def interface_type tag == :interface && interface.info_type end def hidden_struct_type? flattened_tag == :struct && interface.size.zero? end def tag_or_class base = case tag when :interface interface_class when :ghash [tag, *element_type] else flattened_tag end if pointer? && tag != :utf8 && tag != :filename [:pointer, base] else base end end def interface_class Builder.build_class interface if tag == :interface end TAG_TO_WRAPPER_CLASS_MAP = { array: 'GLib::Array', byte_array: 'GLib::ByteArray', c: 'GirFFI::SizedArray', error: 'GLib::Error', ghash: 'GLib::HashTable', glist: 'GLib::List', gslist: 'GLib::SList', ptr_array: 'GLib::PtrArray', strv: 'GLib::Strv', utf8: 'GirFFI::InPointer', # TODO: Create a string-like class void: 'GirFFI::InPointer', # TODO: Create a void-pointer class zero_terminated: 'GirFFI::ZeroTerminated' }.freeze # TODO: Use class rather than class name def argument_class_name interface_class_name || TAG_TO_WRAPPER_CLASS_MAP[flattened_tag] end def interface_class_name interface.full_type_name if tag == :interface end def to_ffi_type return :pointer if pointer? case tag when :interface interface.to_ffi_type when :array [subtype_ffi_type(0), array_fixed_size] else TypeMap.map_basic_type tag end end def to_callback_ffi_type return :pointer if pointer? case tag when :interface # TODO: Move this logic into interface case interface.info_type when :enum, :flags :int32 else :pointer end when :gboolean # TODO: Move this logic into TypeMap :bool else TypeMap.map_basic_type tag end end TAGS_NEEDING_RUBY_TO_C_CONVERSION = [ :array, :c, :callback, :error, :ghash, :glist, :gslist, :object, :ptr_array, :struct, :strv, :utf8, :zero_terminated ].freeze TAGS_NEEDING_C_TO_RUBY_CONVERSION = [ :array, :byte_array, :c, :error, :filename, :ghash, :glist, :gslist, :interface, :object, :ptr_array, :struct, :strv, :union, :utf8, :zero_terminated ].freeze def needs_ruby_to_c_conversion_for_functions? TAGS_NEEDING_RUBY_TO_C_CONVERSION.include?(flattened_tag) end def needs_c_to_ruby_conversion_for_functions? TAGS_NEEDING_C_TO_RUBY_CONVERSION.include?(flattened_tag) end def needs_ruby_to_c_conversion_for_callbacks? [:enum].include?(flattened_tag) || needs_ruby_to_c_conversion_for_functions? end def needs_c_to_ruby_conversion_for_callbacks? [:callback, :enum].include?(flattened_tag) || needs_c_to_ruby_conversion_for_functions? end def needs_c_to_ruby_conversion_for_closures? [:array, :c, :ghash, :glist, :struct, :strv].include?(flattened_tag) end def needs_ruby_to_c_conversion_for_closures? [:array].include?(flattened_tag) end def needs_ruby_to_c_conversion_for_properties? [:glist, :ghash, :strv, :callback].include?(flattened_tag) end def needs_c_to_ruby_conversion_for_properties? [:glist, :ghash, :callback].include?(flattened_tag) end def extra_conversion_arguments case flattened_tag when :c [element_type, array_fixed_size] when :array, :ghash, :glist, :gslist, :ptr_array, :zero_terminated [element_type] else [] end end GOBJECT_VALUE_NAME = 'GObject::Value'.freeze def gvalue? argument_class_name == GOBJECT_VALUE_NAME end private def subtype_tag_or_class(index) param_type(index).tag_or_class end def dictionary_element_type [subtype_tag_or_class(0), subtype_tag_or_class(1)] end def enumerable_element_type subtype_tag_or_class 0 end def subtype_ffi_type(index) subtype = param_type(index).to_ffi_type if subtype == :pointer # NOTE: Don't use pointer directly to appease JRuby. :"uint#{FFI.type_size(:pointer) * 8}" else subtype end end def flattened_array_type if zero_terminated? zero_terminated_array_type else array_type end end def zero_terminated_array_type case element_type when :utf8, :filename :strv else :zero_terminated end end end end end GObjectIntrospection::ITypeInfo.send :include, GirFFI::InfoExt::ITypeInfo gir_ffi-0.11.4/lib/gir_ffi/info_ext/i_callable_info.rb0000644000004100000410000000051513170036060022624 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extensions for GObjectIntrospection::ICallableInfo needed by GirFFI module ICallableInfo def argument_ffi_types args.map(&:to_ffi_type) end end end end GObjectIntrospection::ICallableInfo.send :include, GirFFI::InfoExt::ICallableInfo gir_ffi-0.11.4/lib/gir_ffi/info_ext/full_type_name.rb0000644000004100000410000000114213170036060022542 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extension module provinding a #full_type_name method suitable for # callbacks, constants and registered types. Signals and vfuncs need a # different implementation. module FullTypeName def full_type_name "#{safe_namespace}::#{safe_name}" end end end end GObjectIntrospection::ICallbackInfo.send :include, GirFFI::InfoExt::FullTypeName GObjectIntrospection::IConstantInfo.send :include, GirFFI::InfoExt::FullTypeName GObjectIntrospection::IRegisteredTypeInfo.send :include, GirFFI::InfoExt::FullTypeName gir_ffi-0.11.4/lib/gir_ffi/info_ext/i_function_info.rb0000644000004100000410000000075613170036060022721 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extensions for GObjectIntrospection::IFunctionInfo needed by GirFFI module IFunctionInfo def argument_ffi_types super.tap do |types| types.unshift :pointer if method? types << :pointer if throws? end end def return_ffi_type return_type.to_ffi_type end end end end GObjectIntrospection::IFunctionInfo.send :include, GirFFI::InfoExt::IFunctionInfo gir_ffi-0.11.4/lib/gir_ffi/info_ext/i_callback_info.rb0000644000004100000410000000074713170036060022630 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extensions for GObjectIntrospection::ICallbackInfo needed by GirFFI module ICallbackInfo def to_ffi_type Builder.build_class(self) end def argument_ffi_types args.map(&:to_callback_ffi_type) end def return_ffi_type return_type.to_callback_ffi_type end end end end GObjectIntrospection::ICallbackInfo.send :include, GirFFI::InfoExt::ICallbackInfo gir_ffi-0.11.4/lib/gir_ffi/info_ext/i_registered_type_info.rb0000644000004100000410000000130213170036060024256 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builder_helper' module GirFFI module InfoExt # Extensions for GObjectIntrospection::IRegisteredTypeInfo needed by GirFFI module IRegisteredTypeInfo def to_ffi_type to_type.to_ffi_type end def to_type Builder.build_class self end def find_instance_method(method) info = find_method method return info if info && info.method? end def find_method(_method) raise 'Must be overridden in subclass' end end end end GObjectIntrospection::IRegisteredTypeInfo.send :include, GirFFI::InfoExt::IRegisteredTypeInfo gir_ffi-0.11.4/lib/gir_ffi/info_ext/i_arg_info.rb0000644000004100000410000000074113170036060021637 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module InfoExt # Extensions for GObjectIntrospection::IArgInfo needed by GirFFI module IArgInfo def to_ffi_type return :pointer if direction != :in argument_type.to_ffi_type end def to_callback_ffi_type return :pointer if direction != :in argument_type.to_callback_ffi_type end end end end GObjectIntrospection::IArgInfo.send :include, GirFFI::InfoExt::IArgInfo gir_ffi-0.11.4/lib/gir_ffi/zero_terminated.rb0000644000004100000410000000266113170036060021126 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Represents a null-terminated array. class ZeroTerminated include Enumerable attr_reader :element_type def initialize(elm_t, ptr) @element_type = elm_t @ptr = ptr end def to_ptr @ptr end def self.from(type, arg) new type, InPointer.from_array(type, arg) end def self.wrap(type, arg) new type, arg end def each return if @ptr.null? offset = 0 while (val = read_value(offset)) offset += ffi_type_size yield wrap_value(val) end end def ==(other) to_a == other.to_a end private def read_value(offset) val = fetch_value(offset) val unless val.zero? end def getter_method @getter_method ||= "get_#{ffi_type}" end def fetch_value(offset) case ffi_type when Module ffi_type.get_value_from_pointer(@ptr, offset) when Symbol @ptr.send(getter_method, offset) else raise NotImplementedError end end def wrap_value(val) case element_type when Array element_type.last.wrap val when Class element_type.wrap val else val end end def ffi_type @ffi_type ||= TypeMap.type_specification_to_ffi_type element_type end def ffi_type_size @ffi_type_size ||= FFI.type_size(ffi_type) end end end gir_ffi-0.11.4/lib/gir_ffi/return_value_info.rb0000644000004100000410000000073713170036060021463 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Represents a return value with the same interface as IArgumentInfo class ReturnValueInfo attr_reader :argument_type attr_reader :ownership_transfer def initialize(type, ownership_transfer, skip) @argument_type = type @ownership_transfer = ownership_transfer @skip = skip end def skip? @skip end def direction :return end def name nil end end end gir_ffi-0.11.4/lib/gir_ffi/struct_like_base.rb0000644000004100000410000000307013170036060021250 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Base module providing class methods for generated classes representing GLib # structs, unions and boxed types. module StructLikeBase def self.included(base) base.extend ClassMethods end # Class methods for struct-like classes. module ClassMethods def native_type FFI::Type::Struct.new(self::Struct) end def to_ffi_type self end # NOTE: Needed for JRuby's FFI def to_native(value, _context) value.struct end def get_value_from_pointer(pointer, offset) pointer + offset end def size self::Struct.size end def copy_value_to_pointer(value, pointer, offset = 0) bytes = value.to_ptr.read_bytes(size) pointer.put_bytes offset, bytes end # Create an unowned copy of the struct represented by val def copy_from(val) disown copy from(val) end # Wrap an owned copy of the struct represented by val def wrap_copy(val) own copy(val) end # Wrap value and take ownership of it def wrap_own(val) own wrap(val) end private def own(val) val.struct.owned = true if val val end def disown(val) val.struct.owned = nil if val val end # Create a copy of the struct represented by val def copy(val) return unless val new.tap do |copy| copy_value_to_pointer(val, copy.to_ptr) end end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/0000755000004100000410000000000013170036060017212 5ustar www-datawww-datagir_ffi-0.11.4/lib/gir_ffi/builders/mapping_method_builder.rb0000644000004100000410000000323313170036060024241 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/variable_name_generator' require 'gir_ffi/builders/callback_argument_builder' require 'gir_ffi/builders/vfunc_argument_builder' require 'gir_ffi/builders/callback_return_value_builder' require 'gir_ffi/builders/argument_builder_collection' require 'gir_ffi/builders/base_method_builder' module GirFFI module Builders # Implements the creation mapping method for a callback or vfunc # handler. This method converts arguments from C to Ruby, and the # result from Ruby to C. class MappingMethodBuilder < BaseMethodBuilder def self.for_callback(info) new nil, info, CallbackArgumentBuilder end def self.for_vfunc(receiver_info, info) new receiver_info, info, VFuncArgumentBuilder end def initialize(receiver_info, info, builder_class) super(info, CallbackReturnValueBuilder, receiver_info: receiver_info, argument_builder_class: builder_class) end ## Methods used by MethodTemplate def method_name 'call_with_argument_mapping' end def method_arguments @method_arguments ||= argument_builder_collection.method_argument_names.dup.unshift('_proc') end def invocation "_proc.call(#{call_argument_list})" end def result if (name = argument_builder_collection.return_value_name) ["return #{name}"] else [] end end def singleton_method? true end private def call_argument_list argument_builder_collection.call_argument_names.join(', ') end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/property_builder.rb0000644000004100000410000000671513170036060023142 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/method_template' require 'gir_ffi/builders/argument_builder_collection' require 'gir_ffi/builders/property_argument_builder' require 'gir_ffi/builders/property_return_value_builder' require 'gir_ffi/variable_name_generator' require 'gir_ffi/field_argument_info' module GirFFI module Builders # Method builder used for the creation of property getter methods. class PropertyGetterBuilder attr_reader :info attr_reader :return_value_builder def initialize(info, return_value_builder) @return_value_builder = return_value_builder @info = info end def method_definition template.method_definition end def template @template ||= MethodTemplate.new(self, argument_builder_collection) end def singleton_method? false end def method_name info.getter_name end def method_arguments [] end def preparation [] end def invocation "get_property('#{info.name}')" end def result [return_value_builder.return_value_name] end private def argument_builder_collection @argument_builder_collection ||= ArgumentBuilderCollection.new(return_value_builder, []) end end # Creates property getter and setter code for a given IPropertyInfo. class PropertyBuilder def initialize(property_info) @info = property_info end def build setup_getter setup_setter if setting_allowed end def setup_getter container_class.class_eval getter_def unless container_defines_getter_method? end def container_defines_getter_method? container_info.find_instance_method getter_name end def setup_setter container_class.class_eval setter_def end def getter_def PropertyGetterBuilder.new(@info, getter_builder).method_definition end def setter_def converting_setter_def end private def getter_builder @getter_builder ||= PropertyReturnValueBuilder.new(VariableNameGenerator.new, argument_info) end def converting_setter_def <<-CODE.reset_indentation def #{setter_name} value #{setter_builder.pre_conversion.join("\n")} set_property("#{property_name}", #{setter_builder.call_argument_name}) end CODE end def setter_builder @setter_builder ||= PropertyArgumentBuilder.new(VariableNameGenerator.new, argument_info) end def property_name @info.name end def getter_name @info.getter_name end def setter_name @info.setter_name end def type_info @type_info ||= @info.property_type end def argument_info @argument_info ||= FieldArgumentInfo.new('value', type_info) end def container_class @container_class ||= container_module.const_get(container_info.safe_name) end def container_module @container_module ||= Object.const_get(container_info.safe_namespace) end def container_info @container_info ||= @info.container end def setting_allowed @info.writeable? && !@info.construct_only? end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/full_c_to_ruby_convertor.rb0000644000004100000410000000072213170036060024650 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/c_to_ruby_convertor' module GirFFI module Builders # Builder that generates code to convert values from C to Ruby, including # GValue unpacking. Used by argument builders. class FullCToRubyConvertor < CToRubyConvertor def conversion if @type_info.gvalue? "GObject::Value.wrap(#{@argument}).get_value" else super end end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/null_argument_builder.rb0000644000004100000410000000104313170036060024117 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Argument builder that does nothing. Implements the Null Object pattern. class NullArgumentBuilder def initialize(*); end def pre_conversion [] end def post_conversion [] end def array_length_idx -1 end def method_argument_name nil end def return_value_name nil end def call_argument_name nil end def capture_variable_name nil end def post_converted_name nil end end end gir_ffi-0.11.4/lib/gir_ffi/builders/unintrospectable_builder.rb0000644000004100000410000000166213170036060024633 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/object_builder' require 'gir_ffi/unintrospectable_signal_info' module GirFFI module Builders # Implements the creation of a class representing an object type for # which no data is found in the GIR. Typically, these are created to # cast objects returned by a function that returns an interface. class UnintrospectableBuilder < ObjectBuilder def klass @klass ||= TypeBuilder::CACHE[target_gtype] ||= Class.new(superclass) end def setup_class setup_constants setup_layout setup_interfaces end def setup_instance_method(_method) false end def find_signal(signal_name) info = super return info if info signal_id = GObject.signal_lookup signal_name, target_gtype return UnintrospectableSignalInfo.new(signal_id) if signal_id > 0 end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/callback_return_value_builder.rb0000644000004100000410000000251613170036060025600 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/base_return_value_builder' require 'gir_ffi/builders/ruby_to_c_convertor' module GirFFI module Builders # Implements building post-processing statements for return values of # callbacks. class CallbackReturnValueBuilder < BaseReturnValueBuilder def post_conversion if has_post_conversion? optional_outgoing_ref + base_post_conversion else [] end end private def has_post_conversion? relevant? && needs_ruby_to_c_conversion? end def needs_ruby_to_c_conversion? type_info.needs_ruby_to_c_conversion_for_callbacks? end def optional_outgoing_ref if outgoing_ref_needed? ["#{capture_variable_name}.ref"] else [] end end def base_post_conversion if specialized_type_tag == :object ["#{post_converted_name} = #{post_convertor.conversion}.to_ptr"] else ["#{post_converted_name} = #{post_convertor.conversion}"] end end def post_convertor @post_convertor ||= RubyToCConvertor.new(type_info, capture_variable_name) end def outgoing_ref_needed? ownership_transfer == :everything && specialized_type_tag == :object end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/base_method_builder.rb0000644000004100000410000000554613170036060023531 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/argument_builder' require 'gir_ffi/builders/argument_builder_collection' require 'gir_ffi/builders/method_template' require 'gir_ffi/builders/null_argument_builder' require 'gir_ffi/error_argument_info' require 'gir_ffi/return_value_info' require 'gir_ffi/variable_name_generator' module GirFFI module Builders # Base class for method definition builders. class BaseMethodBuilder def initialize(info, return_value_builder_class, receiver_info: nil, argument_builder_class: ArgumentBuilder) @info = info @return_value_builder_class = return_value_builder_class @argument_builder_class = argument_builder_class @receiver_info = receiver_info end def variable_generator @variable_generator ||= VariableNameGenerator.new end def method_definition template.method_definition end def template @template ||= MethodTemplate.new(self, argument_builder_collection) end # Methods used for setting up the builders def argument_builders @argument_builders ||= @info.args.map { |arg| make_argument_builder arg } end def return_value_info @return_value_info ||= ReturnValueInfo.new(@info.return_type, @info.caller_owns, @info.skip_return?) end def return_value_builder @return_value_builder = @return_value_builder_class.new(variable_generator, return_value_info) end def receiver_builder @receiver_builder ||= @receiver_info ? make_argument_builder(@receiver_info) : nil end def argument_builder_collection @argument_builder_collection ||= ArgumentBuilderCollection.new(return_value_builder, argument_builders, error_argument_builder: error_argument, receiver_builder: receiver_builder) end def error_argument @error_argument ||= if @info.can_throw_gerror? make_argument_builder ErrorArgumentInfo.new else NullArgumentBuilder.new end end # Methods used by MethodTemplate def invocation "#{lib_name}.#{@info.symbol} #{function_call_arguments.join(', ')}".strip end def method_arguments argument_builder_collection.method_argument_names end def preparation [] end private def lib_name "#{@info.safe_namespace}::Lib" end def make_argument_builder(argument_info) @argument_builder_class.new variable_generator, argument_info end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/null_class_builder.rb0000644000004100000410000000037413170036060023410 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Class builder that does nothing class NullClassBuilder def setup_method(_) nil end def setup_instance_method(_) nil end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/ruby_to_c_convertor.rb0000644000004100000410000000201013170036060023616 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Builder that generates code to convert values from Ruby to C. Used by # argument builders. class RubyToCConvertor def initialize(type_info, argument_name, ownership_transfer: nil) @type_info = type_info @argument_name = argument_name @ownership_transfer = ownership_transfer end def conversion args = conversion_arguments @argument_name "#{@type_info.argument_class_name}.#{conversion_method}(#{args})" end def conversion_arguments(name) @type_info.extra_conversion_arguments.map(&:inspect).push(name).join(', ') end private def conversion_method case @type_info.flattened_tag when :utf8 'from_utf8' when :struct, :c case @ownership_transfer when :everything 'copy_from' else 'from' end else 'from' end end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/argument_builder.rb0000644000004100000410000001434113170036060023072 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/base_argument_builder' require 'gir_ffi/builders/closure_to_pointer_convertor' require 'gir_ffi/builders/full_c_to_ruby_convertor' require 'gir_ffi/builders/ruby_to_c_convertor' require 'gir_ffi/builders/pointer_value_convertor' require 'gir_ffi/builders/null_convertor' module GirFFI module Builders # Implements building pre- and post-processing statements for arguments. class ArgumentBuilder < BaseArgumentBuilder def method_argument_name name if has_input_value? && !helper_argument? end def block_argument? specialized_type_tag == :callback end def allow_none? arginfo.may_be_null? end def post_converted_name @post_converted_name ||= if has_post_conversion? new_variable else call_argument_name end end def return_value_name if has_output_value? post_converted_name unless array_length_parameter? end end def capture_variable_name nil end def pre_conversion pr = [] if has_ingoing_component? pr << fixed_array_size_check if needs_size_check? pr << array_length_assignment if array_length_parameter? end case direction when :in pr << "#{call_argument_name} = #{ingoing_convertor.conversion}" when :inout pr << out_parameter_preparation pr << ingoing_value_storage when :out pr << out_parameter_preparation when :error pr << "#{call_argument_name} = FFI::MemoryPointer.new(:pointer).write_pointer nil" end pr end def post_conversion if direction == :error ["GirFFI::ArgHelper.check_error(#{call_argument_name})"] elsif has_post_conversion? value = output_value ["#{post_converted_name} = #{value}"] else [] end end private def ingoing_value_storage PointerValueConvertor.new(type_spec). value_to_pointer(call_argument_name, ingoing_convertor.conversion) end def has_post_conversion? has_output_value? && (!caller_allocated_object? || gvalue?) end def output_value if caller_allocated_object? && gvalue? return "#{call_argument_name}.get_value" end base = pointer_to_value_method_call call_argument_name, type_spec if needs_out_conversion? outgoing_convertor(base).conversion elsif allocated_by_them? && specialized_type_tag != :void pointer_to_value_method_call base, sub_type_spec else base end end def outgoing_convertor(base) FullCToRubyConvertor.new(type_info, base, length_argument_name, ownership_transfer: @arginfo.ownership_transfer) end def sub_type_spec type_spec[1] end def pointer_to_value_method_call(ptr_exp, spec) PointerValueConvertor.new(spec).pointer_to_value(ptr_exp) end def needs_out_conversion? type_info.needs_c_to_ruby_conversion_for_functions? end def gvalue? type_info.gvalue? end # Check if an out argument needs to be allocated by them, 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 allocated by the caller (that's us). def allocated_by_them? !@arginfo.caller_allocates? && type_info.pointer? end def length_argument_name length_arg && length_arg.post_converted_name end def needs_size_check? specialized_type_tag == :c && type_info.array_fixed_size > -1 end def fixed_array_size_check size = type_info.array_fixed_size "GirFFI::ArgHelper.check_fixed_array_size #{size}, #{name}, \"#{name}\"" end def skipped_in? @arginfo.skip? end def skipped_out? @arginfo.skip? || @array_arg && @array_arg.specialized_type_tag == :strv end def has_output_value? (direction == :inout || direction == :out) && !skipped_out? end def has_input_value? has_ingoing_component? && !skipped_in? end def has_ingoing_component? (direction == :inout || direction == :in) end def array_length_assignment arrname = @array_arg.name "#{name} = #{arrname}.nil? ? 0 : #{arrname}.length" end def out_parameter_preparation value = if caller_allocated_object? if specialized_type_tag == :array "#{argument_class_name}.new #{type_info.element_type.inspect}" else "#{argument_class_name}.new" end else ffi_type_spec = TypeMap.type_specification_to_ffi_type type_spec "FFI::MemoryPointer.new #{ffi_type_spec.inspect}" end "#{call_argument_name} = #{value}" end def type_spec type_info.tag_or_class end def caller_allocated_object? [:struct, :array].include?(specialized_type_tag) && @arginfo.caller_allocates? end DESTROY_NOTIFIER = 'GLib::DestroyNotify.default'.freeze def ingoing_convertor if skipped_in? NullConvertor.new('0') elsif destroy_notifier? NullConvertor.new(DESTROY_NOTIFIER) elsif closure? ClosureToPointerConvertor.new(pre_convertor_argument, @is_closure) elsif type_info.needs_ruby_to_c_conversion_for_functions? RubyToCConvertor.new(type_info, pre_convertor_argument, ownership_transfer: ownership_transfer) else NullConvertor.new(pre_convertor_argument) end end def pre_convertor_argument if ownership_transfer == :everything && specialized_type_tag == :object "#{name} && #{name}.ref" else name end end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/vfunc_builder.rb0000644000004100000410000000302313170036060022364 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/return_value_info' require 'gir_ffi/builders/base_type_builder' require 'gir_ffi/builders/mapping_method_builder' require 'gir_ffi/receiver_type_info' require 'gir_ffi/receiver_argument_info' require 'gir_ffi/callback_base' module GirFFI module Builders # Implements the creation of a class representing the implementation of a # vfunc. This class will be able to turn a proc into an FFI::Function that # can serve as such an implementation in C. The class will be namespaced # inside class defining the vfunc. class VFuncBuilder < BaseTypeBuilder def setup_class setup_constants klass.class_eval mapping_method_definition end def klass @klass ||= get_or_define_class container_class, @classname, CallbackBase end def mapping_method_definition receiver_info = ReceiverArgumentInfo.new receiver_type_info MappingMethodBuilder.for_vfunc(receiver_info, info).method_definition end def receiver_type_info ReceiverTypeInfo.new(container_info) end def container_class @container_class ||= Builder.build_class(container_info) end def container_info @container_info ||= info.container end def argument_ffi_types @argument_ffi_types ||= info.argument_ffi_types. unshift(receiver_type_info.to_callback_ffi_type) end def return_ffi_type @return_ffi_type ||= info.return_ffi_type end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/interface_builder.rb0000644000004100000410000000136613170036060023213 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/registered_type_builder' require 'gir_ffi/interface_base' module GirFFI module Builders # Implements the creation of a module representing an Interface. class InterfaceBuilder < RegisteredTypeBuilder def interface_struct @interface_struct ||= Builder.build_class iface_struct_info end private def klass @klass ||= get_or_define_module namespace_module, @classname end # FIXME: The word 'class' is not really correct. def setup_class klass.extend InterfaceBase setup_constants stub_methods end def iface_struct_info @iface_struct_info ||= info.iface_struct end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/signal_closure_builder.rb0000644000004100000410000000215613170036060024262 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/base_type_builder' require 'gir_ffi/builders/marshalling_method_builder' module GirFFI module Builders # Implements the creation of a closure class for handling a particular # signal. The type will be attached to the appropriate class. class SignalClosureBuilder < BaseTypeBuilder def setup_class setup_constants klass.class_eval marshaller_definition end def setup_method(_method) nil end def marshaller_definition container_type_info = ReceiverTypeInfo.new(container_info) receiver_info = ReceiverArgumentInfo.new(container_type_info) MarshallingMethodBuilder.for_signal(receiver_info, info).method_definition end def klass @klass ||= get_or_define_class container_class, @classname, GObject::RubyClosure end def container_class @container_class ||= Builder.build_class(container_info) end def container_info @container_info ||= info.container end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/base_argument_builder.rb0000644000004100000410000000505713170036060024070 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Abstract parent class of the argument building classes. These # classes are used by FunctionBuilder to create the code that # processes each argument before and after the actual function call. class BaseArgumentBuilder KEYWORDS = %w( alias and begin break case class def do else elsif end ensure false for if in module next nil not or redo rescue retry return self super then true undef unless until when while yield ).freeze attr_reader :arginfo attr_accessor :length_arg, :array_arg def initialize(var_gen, arginfo) @var_gen = var_gen @arginfo = arginfo @length_arg = nil @array_arg = nil @is_closure = false @destroy_notifier = false end def name @name ||= safe(arginfo.name) end def direction @direction ||= arginfo.direction end def type_info @type_info ||= arginfo.argument_type end def specialized_type_tag type_info.flattened_tag end # TODO: Use class rather than class name def argument_class_name type_info.argument_class_name end def array_length_idx type_info.array_length end def closure_idx arginfo.closure end def destroy_idx arginfo.destroy end # TODO: closure unfortunately means two things in GLib: a closure # argument (user_data), and the Closure class (a callable object). Make # the distinction more explicit in GirFFI. def closure=(arg) @is_closure = arg end # TODO: Unify relationship set-up methods and improve naming. We # currently have length_arg=, array_arg=, closure= and # mark_as_destroy_notifier. def mark_as_destroy_notifier(callback) @destroy_notifier = callback end def array_length_parameter? @array_arg end def closure? @is_closure end def destroy_notifier? @destroy_notifier end def helper_argument? array_length_parameter? || closure? || destroy_notifier? end def ownership_transfer arginfo.ownership_transfer end def safe(name) if KEYWORDS.include? name "#{name}_" else name end end def call_argument_name @call_argument_name ||= new_variable end def new_variable @var_gen.new_var end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/vfunc_argument_builder.rb0000644000004100000410000000163713170036060024277 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/callback_argument_builder' module GirFFI module Builders # Convertor for arguments for vfuncs. Used when building the # argument mapper for vfuncs. class VFuncArgumentBuilder < CallbackArgumentBuilder def pre_conversion if ingoing_ref_needed? super + ["#{pre_converted_name}.ref"] else super end end def post_conversion if outgoing_ref_needed? ["#{result_name}.ref"] + super else super end end private def ingoing_ref_needed? direction == :in && ownership_transfer == :nothing && specialized_type_tag == :object end def outgoing_ref_needed? direction == :out && ownership_transfer == :everything && specialized_type_tag == :object end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/initializer_return_value_builder.rb0000644000004100000410000000075013170036060026365 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/base_return_value_builder' module GirFFI module Builders # Implements post-conversion for initializer functions class InitializerReturnValueBuilder < BaseReturnValueBuilder def post_conversion result = [] result << "store_pointer(#{capture_variable_name})" if specialized_type_tag == :struct result << '@struct.owned = true' end result end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/property_argument_builder.rb0000644000004100000410000000110713170036060025032 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/base_argument_builder' module GirFFI module Builders # Convertor for arguments for property setters. class PropertyArgumentBuilder < BaseArgumentBuilder def pre_conversion pr = [] pr << "#{call_argument_name} = #{ingoing_convertor.conversion}" pr end def ingoing_convertor if type_info.needs_ruby_to_c_conversion_for_properties? RubyToCConvertor.new(type_info, name) else NullConvertor.new(name) end end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/flags_builder.rb0000644000004100000410000000135613170036060022346 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/enum_builder' require 'gir_ffi/flags_base' module GirFFI module Builders # Implements the creation of a flags type. The type will be # attached to the appropriate namespace module, and will be defined # as a bit_mask for FFI. class FlagsBuilder < EnumBuilder def setup_ffi_type optionally_define_constant klass, :BitMask do lib.bit_mask(enum_sym, value_spec) end end def value_spec info.values.map do |vinfo| val = GirFFI::ArgHelper.cast_uint32_to_int32(vinfo.value) { vinfo.name.to_sym => val } end.reduce(:merge) end def superclass FlagsBase end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/marshalling_method_builder.rb0000644000004100000410000000347113170036060025113 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/variable_name_generator' require 'gir_ffi/builders/closure_argument_builder' require 'gir_ffi/builders/closure_return_value_builder' require 'gir_ffi/builders/argument_builder_collection' require 'gir_ffi/builders/method_template' module GirFFI module Builders # Implements the creation mapping method for a signal # handler. This method converts arguments from C to Ruby, and the # result from Ruby to C. class MarshallingMethodBuilder < BaseMethodBuilder def self.for_signal(receiver_info, info) new receiver_info, info end def initialize(receiver_info, info) super(info, ClosureReturnValueBuilder, receiver_info: receiver_info, argument_builder_class: ClosureArgumentBuilder) end ## Methods used by MethodTemplate def method_name 'marshaller' end def method_arguments %w(closure return_value param_values _invocation_hint _marshal_data) end def preparation if param_names.size == 1 ["#{param_names.first} = param_values.first.get_value_plain"] else ["#{param_names.join(', ')} = param_values.map(&:get_value_plain)"] end end def invocation "wrap(closure.to_ptr).invoke_block(#{call_argument_list})" end def result if (name = @argument_builder_collection.return_value_name) ["return_value.set_value #{name}"] else [] end end def singleton_method? true end private def call_argument_list @argument_builder_collection.call_argument_names.join(', ') end def param_names @param_names ||= @argument_builder_collection.method_argument_names end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/closure_return_value_builder.rb0000644000004100000410000000062113170036060025513 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/callback_return_value_builder' module GirFFI module Builders # Implements building post-processing statements for return values of # closures. class ClosureReturnValueBuilder < CallbackReturnValueBuilder def needs_ruby_to_c_conversion? type_info.needs_ruby_to_c_conversion_for_closures? end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/with_layout.rb0000644000004100000410000000215313170036060022110 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/field_builder' module GirFFI module Builders # Implements the creation of classes representing types with layout, # i.e., :union, :struct, :object. # NOTE: This module depends on methods in RegisteredTypeBuilder. module WithLayout def layout_specification spec = base_layout_specification if spec.empty? dummy_layout_specification else spec end end private def setup_layout spec = layout_specification struct_class.class_eval { layout(*spec) } end def dummy_layout_specification if parent_info [:parent, superclass::Struct, 0] else [:dummy, :char, 0] end end def base_layout_specification fields.map(&:layout_specification).flatten(1) end def klass @klass ||= get_or_define_class namespace_module, @classname, superclass end def struct_class @structklass ||= get_or_define_class klass, :Struct, layout_superclass end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/closure_to_pointer_convertor.rb0000644000004100000410000000112013170036060025550 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Builder that generates code to convert closure arguments ('user data') # from Ruby to C. Used by argument builders. class ClosureToPointerConvertor def initialize(argument_name, callback_argument) @argument_name = argument_name @callback_argument = callback_argument end def conversion "GirFFI::ArgHelper.store(#{callback_argument_name})" end private def callback_argument_name @callback_argument.call_argument_name end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/base_return_value_builder.rb0000644000004100000410000000175513170036060024762 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/base_argument_builder' module GirFFI module Builders # Implements building post-processing statements for return values of # callbacks. class BaseReturnValueBuilder < BaseArgumentBuilder def relevant? !void_return_value? && !arginfo.skip? end def capture_variable_name @capture_variable_name ||= new_variable if relevant? end def post_converted_name @post_converted_name ||= if has_post_conversion? new_variable else capture_variable_name end end def return_value_name post_converted_name if has_return_value_name? end def void_return_value? specialized_type_tag == :void && !type_info.pointer? end def has_return_value_name? relevant? && !array_arg end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/null_convertor.rb0000644000004100000410000000044013170036060022610 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Argument convertor that does nothing class NullConvertor def initialize(argument_name) @argument_name = argument_name end def conversion @argument_name end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/base_type_builder.rb0000644000004100000410000000163513170036060023225 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builder_helper' module GirFFI # Base class for type builders. class BaseTypeBuilder include BuilderHelper def initialize(info) @info = info @namespace = @info.namespace @classname = @info.safe_name end def build_class instantiate_class unless defined? @klass @klass end def instantiate_class setup_class unless already_set_up end attr_reader :info private def namespace_module @namespace_module ||= Builder.build_module @namespace end def lib @lib ||= namespace_module::Lib end def setup_constants klass.const_set :GIR_INFO, info klass.const_set :GIR_FFI_BUILDER, self end def already_set_up klass.const_defined? :GIR_FFI_BUILDER, false end def gir @gir ||= GObjectIntrospection::IRepository.default end end end gir_ffi-0.11.4/lib/gir_ffi/builders/user_defined_builder.rb0000644000004100000410000001673313170036060023713 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/object_builder' require 'gir_ffi/g_type' module GirFFI module Builders # Implements the creation of GObject subclasses from Ruby. class UserDefinedBuilder < ObjectBuilder def initialize(info) @info = info end def setup_class setup_layout register_type setup_constants setup_property_accessors setup_constructor TypeBuilder::CACHE[@gtype] = klass end def target_gtype @gtype ||= klass.gtype end private def register_type @gtype = GObject.type_register_static(parent_gtype.to_i, info.g_name, gobject_type_info, 0) included_interfaces.each do |interface| ifinfo = gobject_interface_info interface GObject.type_add_interface_static @gtype, interface.gtype, ifinfo end end def parent_info @info.parent end def parent_gtype @info.parent_gtype end def interface_gtypes included_interfaces.map { |interface| GType.new(interface.gtype) } end def included_interfaces klass.included_modules - Object.included_modules end def klass @klass ||= @info.described_class end def gobject_type_info GObject::TypeInfo.new.tap do |type_info| type_info.class_size = class_size type_info.instance_size = instance_size type_info.class_init = class_init_proc end end def gobject_interface_info(interface) GObject::InterfaceInfo.new.tap do |interface_info| interface_info.interface_init = interface_init_proc(interface) end end def class_init_proc proc do |type_class_or_ptr, _data| object_class_ptr = type_class_or_ptr.to_ptr setup_properties object_class_ptr setup_vfuncs object_class_ptr end end def interface_init_proc(interface) proc do |interface_or_ptr, _data| interface_ptr = interface_or_ptr.to_ptr setup_interface_vfuncs interface, interface_ptr end end def instance_size size = parent_gtype.instance_size alignment = struct_class.alignment properties.each do |prop| type_size = FFI.type_size(prop.ffi_type) size += [type_size, alignment].max end size end def class_size parent_gtype.class_size + interface_gtypes.map(&:class_size).inject(0, :+) end def setup_properties(object_class_ptr) object_class = GObject::ObjectClass.wrap object_class_ptr object_class.get_property = property_getter object_class.set_property = property_setter properties.each_with_index do |property, index| object_class.install_property index + 1, property.param_spec end end def property_getter proc do |object, _property_id, value, pspec| value.set_value object.send(pspec.accessor_name) end end def property_setter proc do |object, _property_id, value, pspec| object.send("#{pspec.accessor_name}=", value.get_value) end end def setup_vfuncs(object_class_ptr) super_class_struct = superclass.gir_ffi_builder.object_class_struct::Struct.new(object_class_ptr) info.vfunc_implementations.each do |impl| setup_vfunc super_class_struct, impl end end def setup_interface_vfuncs(interface, interface_ptr) interface_builder = interface.gir_ffi_builder interface_struct = interface_builder.interface_struct::Struct.new(interface_ptr) interface_info = interface_builder.info info.vfunc_implementations.each do |impl| setup_interface_vfunc interface_info, interface_struct, impl end end def setup_vfunc(super_class_struct, impl) vfunc_name = impl.name vfunc_info = parent_info.find_vfunc vfunc_name.to_s if vfunc_info install_vfunc super_class_struct, vfunc_name, vfunc_info, impl.implementation end end def setup_interface_vfunc(interface_info, interface_struct, impl) vfunc_name = impl.name vfunc_info = interface_info.find_vfunc vfunc_name.to_s if vfunc_info install_vfunc interface_struct, vfunc_name, vfunc_info, impl.implementation end end def install_vfunc(container_struct, vfunc_name, vfunc_info, implementation) vfunc = VFuncBuilder.new(vfunc_info).build_class container_struct[vfunc_name] = vfunc.from implementation end def properties info.properties end def layout_specification parent_spec = [:parent, superclass::Struct] offset = parent_gtype.instance_size alignment = superclass::Struct.alignment fields_spec = properties.flat_map do |param_info| field_name = param_info.accessor_name.to_sym ffi_type = param_info.ffi_type type_size = FFI.type_size(ffi_type) spec = [field_name, ffi_type, offset] offset += [type_size, alignment].max spec end parent_spec + fields_spec end # TODO: Move this to its own file. # TODO: See if this or FieldTypeInfo can be merged with with # UserDefinedPropertyInfo. class UserDefinedPropertyFieldInfo # Field info for user-defined property class FieldTypeInfo include InfoExt::ITypeInfo def initialize(property_info) @property_info = property_info end def tag @property_info.type_tag end def pointer? @property_info.pointer_type? end def interface_type @property_info.interface_type_tag if tag == :interface end def hidden_struct_type? false end def interface_class Builder.build_by_gtype @property_info.value_type if tag == :interface end def interface_class_name interface_class.name if tag == :interface end end def initialize(property_info, container, offset) @property_info = property_info @container = container @offset = offset end attr_reader :container, :offset def name @property_info.accessor_name end def field_type @field_type ||= FieldTypeInfo.new @property_info end def related_array_length_field nil end def writable? @property_info.writable? end end def setup_property_accessors offset = parent_gtype.instance_size alignment = struct_class.alignment properties.each do |param_info| field_info = UserDefinedPropertyFieldInfo.new(param_info, info, offset) type_size = FFI.type_size(param_info.ffi_type) offset += [type_size, alignment].max FieldBuilder.new(field_info, klass).build end end def method_introspection_data(_method) nil end def setup_constructor code = <<-CODE def initialize ptr = GObject::Lib.g_object_newv #{@gtype}, 0, nil store_pointer(ptr) end CODE klass.class_eval code end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/closure_convertor.rb0000644000004100000410000000064213170036060023316 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Builder that generates code to convert closure arguments ('user data') # from C to Ruby. Used by argument builders. class ClosureConvertor def initialize(argument_name) @argument_name = argument_name end def conversion "GirFFI::ArgHelper::OBJECT_STORE.fetch(#{@argument_name})" end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/callback_builder.rb0000644000004100000410000000225213170036060023002 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/base_type_builder' require 'gir_ffi/builders/mapping_method_builder' require 'gir_ffi/callback_base' module GirFFI module Builders # Implements the creation of a callback type. The type will be # attached to the appropriate namespace module, and will be defined # as a callback for FFI. class CallbackBuilder < BaseTypeBuilder def setup_class setup_callback setup_constants klass.class_eval mapping_method_definition end def setup_callback optionally_define_constant klass, :Callback do lib.callback callback_sym, argument_ffi_types, return_ffi_type end end def klass @klass ||= get_or_define_class namespace_module, @classname, CallbackBase end def mapping_method_definition MappingMethodBuilder.for_callback(info).method_definition end def callback_sym @classname.to_sym end def argument_ffi_types @argument_ffi_types ||= @info.argument_ffi_types end def return_ffi_type @return_ffi_type ||= @info.return_ffi_type end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/argument_builder_collection.rb0000644000004100000410000001024713170036060025306 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Class representing the argument and return value builders for a method, # callback mapping function or marshaller. Implements collecting the # conversion code and parameter and variable names for use by function # builders. class ArgumentBuilderCollection attr_reader :return_value_builder def initialize(return_value_builder, argument_builders, receiver_builder: nil, error_argument_builder: nil) @receiver_builder = receiver_builder @error_argument_builder = error_argument_builder @base_argument_builders = argument_builders @return_value_builder = return_value_builder set_up_argument_relations end def parameter_preparation builders_for_pre_conversion.map(&:pre_conversion).flatten end def return_value_conversion builders_for_post_conversion.map(&:post_conversion).flatten end def capture_variable_names @capture_variable_names ||= all_builders.map(&:capture_variable_name).compact end def call_argument_names @call_argument_names ||= argument_builders.map(&:call_argument_name).compact end def method_argument_names @method_argument_names ||= begin base, block = split_off_block_argument args = base_argument_names(base) args << "&#{block.method_argument_name}" if block args end end def return_value_name return_value_builder.return_value_name end def return_value_names @return_value_names ||= all_builders.map(&:return_value_name).compact end def has_return_values? return_value_names.any? end private def argument_builders @argument_builders ||= @base_argument_builders.dup.tap do |builders| builders.unshift @receiver_builder if @receiver_builder builders.push @error_argument_builder if @error_argument_builder end end def set_up_argument_relations @base_argument_builders.each do |bldr| if (idx = bldr.closure_idx) >= 0 @base_argument_builders[idx].closure = bldr end if (idx = bldr.destroy_idx) >= 0 @base_argument_builders[idx].mark_as_destroy_notifier bldr end end all_builders.each do |bldr| if (idx = bldr.array_length_idx) >= 0 other = @base_argument_builders[idx] next unless other bldr.length_arg = other other.array_arg = bldr end end end def all_builders @all_builders ||= [return_value_builder] + argument_builders end def builders_for_pre_conversion @builders_for_pre_conversion ||= sorted_base_argument_builders.dup.tap do |builders| builders.unshift @receiver_builder if @receiver_builder builders.push @error_argument_builder if @error_argument_builder end end def builders_for_post_conversion @builders_for_post_conversion ||= sorted_base_argument_builders.dup.tap do |builders| builders.unshift @receiver_builder if @receiver_builder builders.unshift @error_argument_builder if @error_argument_builder builders.push return_value_builder end end def sorted_base_argument_builders @sorted_base_argument_builders ||= @base_argument_builders. sort_by.with_index { |arg, i| [arg.array_length_idx, i] } end def split_off_block_argument builders_with_name = argument_builders.select(&:method_argument_name) blocks, base = builders_with_name.partition(&:block_argument?) return base, blocks.first end def base_argument_names(arguments) required_found = false arguments.reverse.map do |it| name = it.method_argument_name if it.allow_none? && !required_found "#{name} = nil" else required_found = true name end end.compact.reverse end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/module_builder.rb0000644000004100000410000000603213170036060022533 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builder_helper' require 'gir_ffi/module_base' require 'gir_ffi/builders/function_builder' require 'indentation' module GirFFI module Builders # Builds a module based on information found in the introspection # repository. class ModuleBuilder include BuilderHelper def initialize(module_name, namespace: module_name, version: nil) @namespace = namespace @version = version @safe_namespace = module_name end def generate modul end def setup_method(method) go = function_introspection_data method.to_s return false unless go Builder.attach_ffi_function lib, go modul.class_eval FunctionBuilder.new(go).method_definition true end def method_available?(method) function_introspection_data(method.to_s) and true end def build_namespaced_class(classname) info = find_namespaced_class_info(classname) Builder.build_class info end def find_namespaced_class_info(classname) name = classname.to_s info = gir.find_by_name(@namespace, name) || gir.find_by_name(@namespace, name.sub(/^./, &:downcase)) unless info raise NameError, "Class #{classname} not found in namespace #{@namespace}" end info end private def modul unless defined? @module build_dependencies instantiate_module setup_lib_for_ffi unless lib_already_set_up setup_module unless already_set_up end @module end def build_dependencies deps = gir.dependencies @namespace deps.each do |dep| name, version = dep.split '-' Builder.build_module name, version end end def instantiate_module @module = get_or_define_module ::Object, @safe_namespace end def setup_module @module.extend ModuleBase @module.const_set :GIR_FFI_BUILDER, self end def already_set_up @module.const_defined? :GIR_FFI_BUILDER end def setup_lib_for_ffi lib.extend FFI::Library lib.extend FFI::BitMasks lib.ffi_lib_flags :global, :lazy if shared_library_specification lib.ffi_lib(*shared_library_specification.split(/,/)) end end def shared_library_specification @shared_library_specification ||= gir.shared_library(@namespace) end def lib_already_set_up (class << lib; self; end).include? FFI::Library end def lib @lib ||= get_or_define_module modul, :Lib end def function_introspection_data(function) info = gir.find_by_name @namespace, function.to_s return unless info info.info_type == :function ? info : nil end def gir @gir ||= GObjectIntrospection::IRepository.default.tap do |it| it.require @namespace, @version end end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/constant_builder.rb0000644000004100000410000000111713170036060023076 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/base_type_builder' module GirFFI module Builders # Implements the creation of a constant. Though semantically not a # type, its build method is like that of the types, in that it is # triggered by a missing constant in the parent namespace. The # constant will be attached to the appropriate namespace module. class ConstantBuilder < BaseTypeBuilder def build_class @klass ||= optionally_define_constant namespace_module, @classname do info.value end end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/type_builder.rb0000644000004100000410000000273313170036060022233 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/callback_builder' require 'gir_ffi/builders/constant_builder' require 'gir_ffi/builders/enum_builder' require 'gir_ffi/builders/flags_builder' require 'gir_ffi/builders/interface_builder' require 'gir_ffi/builders/object_builder' require 'gir_ffi/builders/struct_builder' require 'gir_ffi/builders/signal_closure_builder' require 'gir_ffi/builders/unintrospectable_boxed_builder' require 'gir_ffi/builders/unintrospectable_builder' require 'gir_ffi/builders/union_builder' require 'gir_ffi/builders/vfunc_builder' module GirFFI module Builders # Builds a class based on information found in the introspection # repository. module TypeBuilder CACHE = {} TYPE_MAP = { callback: CallbackBuilder, constant: ConstantBuilder, enum: EnumBuilder, flags: FlagsBuilder, interface: InterfaceBuilder, object: ObjectBuilder, struct: StructBuilder, union: UnionBuilder, unintrospectable_boxed: UnintrospectableBoxedBuilder, unintrospectable: UnintrospectableBuilder }.freeze def self.build(info) builder_for(info).build_class end # TODO: Pull up to include :function and :module def self.builder_for(info) TYPE_MAP[info.info_type].new(info) end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/union_builder.rb0000644000004100000410000000107213170036060022375 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/registered_type_builder' require 'gir_ffi/builders/struct_like' require 'gir_ffi/union_base' require 'gir_ffi/union' module GirFFI module Builders # Implements the creation of a class representing union type. The # class will have a nested GirFFI::Union class to represent its C union. class UnionBuilder < RegisteredTypeBuilder include StructLike def layout_superclass GirFFI::Union end private def superclass UnionBase end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/field_builder.rb0000644000004100000410000001677513170036060022350 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/argument_builder' require 'gir_ffi/builders/base_argument_builder' require 'gir_ffi/builders/null_argument_builder' require 'gir_ffi/builders/pointer_value_convertor' require 'gir_ffi/variable_name_generator' require 'gir_ffi/field_argument_info' module GirFFI module Builders # Creates field getter and setter code for a given IFieldInfo. class FieldBuilder # Convertor for fields for field getters. Used when building getter # methods. class GetterArgumentBuilder < BaseArgumentBuilder attr_reader :array_length_idx def initialize(var_gen, field_argument_info, field_info, array_length_idx: -1) super(var_gen, field_argument_info) @field_info = field_info @length_arg = NullArgumentBuilder.new @array_length_idx = array_length_idx end def pre_conversion [ "#{field_ptr} = @struct.to_ptr + #{field_offset}", "#{bare_value} = #{pointer_to_value_conversion}" ] end def capture_variable_name nil end def post_converted_name @post_converted_name ||= if has_post_conversion? new_variable else bare_value end end def return_value_name post_converted_name end def post_conversion if has_post_conversion? ["#{post_converted_name} = #{post_convertor.conversion}"] else [] end end private def pointer_to_value_conversion PointerValueConvertor.new(field_type_tag).pointer_to_value(field_ptr) end def field_offset @field_info.offset end def field_ptr @field_ptr ||= @var_gen.new_var end def typed_ptr @typed_ptr ||= @var_gen.new_var end def bare_value @bare_value ||= @var_gen.new_var end def field_type_tag @field_type_tag ||= @field_info.field_type.tag_or_class end def field_type @field_type ||= @field_info.field_type end def has_post_conversion? type_info.needs_c_to_ruby_conversion_for_functions? end def post_convertor @post_convertor ||= CToRubyConvertor.new(type_info, bare_value, length_arg.post_converted_name) end end # Class to represent argument info for the argument of a getter method. # Implements the necessary parts of IArgumentInfo's interface. class GetterArgumentInfo attr_reader :name, :argument_type def initialize(name, type) @name = name @argument_type = type end def closure -1 end def destroy -1 end def direction :out end def ownership_transfer :nothing end def caller_allocates? false end def skip? false end end # Builder for field getters # TODO: Derive from BaseMethodBuilder class GetterBuilder def initialize(info) @info = info end def method_definition template.method_definition end def singleton_method? false end def method_name @info.name end def method_arguments [] end def preparation [] end def invocation nil end def result [getter_argument_builder.return_value_name] end private def var_gen @var_gen ||= VariableNameGenerator.new end def template @template ||= MethodTemplate.new(self, argument_builders) end def argument_builders @argument_builders ||= ArgumentBuilderCollection.new( NullReturnValueBuilder.new, base_argument_builders) end def base_argument_builders if array_length_field [getter_argument_builder, length_argument_builder] else [getter_argument_builder] end end def getter_argument_builder @getter_argument_builder ||= GetterArgumentBuilder.new(var_gen, field_argument_info, @info, array_length_idx: array_length_field ? 1 : -1) end def length_argument_builder @length_argument_builder ||= GetterArgumentBuilder.new(var_gen, length_argument_info, array_length_field) end def array_length_field @info.related_array_length_field end def length_argument_info @length_argument_info ||= GetterArgumentInfo.new 'length', array_length_field.field_type end def field_offset @info.offset end def field_type_tag @field_type_tag ||= @info.field_type.tag_or_class.inspect end def field_type @field_type ||= @info.field_type end def field_argument_info @field_argument_info ||= GetterArgumentInfo.new 'value', field_type end end attr_reader :info def initialize(field_info, container_class) @info = field_info @container_class = container_class end def build setup_getter setup_setter end def setup_getter return if container_defines_getter_method? return if hidden_struct_type? container_class.class_eval getter_def end def container_defines_getter_method? container_info.find_instance_method info.name end def setup_setter return unless info.writable? return if hidden_struct_type? container_class.class_eval setter_def end def getter_def getter_builder = GetterBuilder.new(info) getter_builder.method_definition end # TODO: Use MethodTemplate def setter_def builder = setter_builder field_ptr = builder.new_variable <<-CODE.reset_indentation def #{info.name}= #{builder.method_argument_name} #{field_ptr} = @struct.to_ptr + #{info.offset} #{builder.pre_conversion.join("\n ")} #{value_storage(field_ptr, builder)} end CODE end private def value_storage(typed_ptr, builder) PointerValueConvertor.new(field_type_tag). value_to_pointer(typed_ptr, builder.call_argument_name) end def field_type_tag @field_type_tag ||= field_type.tag_or_class end attr_reader :container_class def container_info @container_info ||= info.container end def field_type @field_type ||= @info.field_type end def field_argument_info @field_argument_info ||= FieldArgumentInfo.new 'value', field_type end def setter_builder @setter_builder ||= ArgumentBuilder.new(VariableNameGenerator.new, field_argument_info) end def hidden_struct_type? field_type.hidden_struct_type? end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/enum_builder.rb0000644000004100000410000000244313170036060022214 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/registered_type_builder' require 'gir_ffi/enum_base' module GirFFI module Builders # Implements the creation of an enum or flags type. The type will be # attached to the appropriate namespace module, and will be defined # as an enum for FFI. class EnumBuilder < RegisteredTypeBuilder private def enum_sym @classname.to_sym end def value_spec info.values.map do |vinfo| val = GirFFI::ArgHelper.cast_uint32_to_int32(vinfo.value) [vinfo.name.to_sym, val] end.flatten end def setup_class setup_ffi_type klass.extend superclass setup_constants stub_methods setup_inspect end def klass @klass ||= get_or_define_module namespace_module, @classname end def setup_ffi_type optionally_define_constant klass, :Enum do lib.enum(enum_sym, value_spec) end end def setup_inspect klass.instance_eval <<-RUBY def self.inspect "#{@namespace}::#{@classname}" end RUBY end def already_set_up klass.respond_to? :gtype end def superclass EnumBase end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/callback_argument_builder.rb0000644000004100000410000001200413170036060024700 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/base_argument_builder' require 'gir_ffi/builders/c_to_ruby_convertor' require 'gir_ffi/builders/closure_convertor' require 'gir_ffi/builders/null_convertor' require 'gir_ffi/builders/pointer_value_convertor' module GirFFI module Builders # Convertor for arguments for ruby callbacks. Used when building the # argument mapper for callbacks. class CallbackArgumentBuilder < BaseArgumentBuilder def method_argument_name @method_argument_name ||= name || new_variable end def block_argument? false end def allow_none? false end 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 [:in, :inout].include? direction pre_converted_name unless array_arg end end def capture_variable_name unless array_arg result_name if [:out, :inout].include? direction end end def pre_conversion case direction when :in [ingoing_pre_conversion] when :out [out_parameter_preparation] when :inout [out_parameter_preparation, ingoing_pre_conversion] when :error [out_parameter_preparation, 'begin'] end end def post_conversion case direction when :out, :inout [value_to_pointer_conversion] when :error [ "rescue => #{result_name}", value_to_pointer_conversion, 'end' ] else [] end end private def result_name @result_name ||= new_variable end def pre_convertor_argument if direction == :inout pointer_to_value_conversion else method_argument_name end end def pointer_value_convertor @pointer_value_convertor ||= if allocated_by_us? PointerValueConvertor.new(type_spec[1]) else PointerValueConvertor.new(type_spec) end end def pointer_to_value_conversion pointer_value_convertor.pointer_to_value(out_parameter_name) end def value_to_pointer_conversion pointer_value_convertor.value_to_pointer(out_parameter_name, post_convertor.conversion) end def pre_convertor @pre_convertor ||= if closure? ClosureConvertor.new(pre_convertor_argument) elsif needs_c_to_ruby_conversion? CToRubyConvertor.new(type_info, pre_convertor_argument, length_argument_name) else 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 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 post_convertor_argument if array_arg "#{array_arg.capture_variable_name}.length" else result_name end end def out_parameter_preparation value = if allocated_by_us? ffi_type = TypeMap.type_specification_to_ffi_type type_spec.last "FFI::MemoryPointer.new(#{ffi_type.inspect})" \ ".tap { |ptr| #{method_argument_name}.put_pointer 0, ptr }" else method_argument_name end "#{out_parameter_name} = #{value}" end def type_spec type_info.tag_or_class 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? direction == :out && !@arginfo.caller_allocates? && type_info.pointer? && ![:object, :zero_terminated].include?(specialized_type_tag) end def length_argument_name length_arg && length_arg.pre_converted_name end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/unintrospectable_boxed_builder.rb0000644000004100000410000000123313170036060026006 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/registered_type_builder' require 'gir_ffi/builders/struct_like' module GirFFI module Builders # Implements the creation of a class representing a boxed type for # which no data is found in the GIR. class UnintrospectableBoxedBuilder < RegisteredTypeBuilder include StructLike def klass @klass ||= TypeBuilder::CACHE[target_gtype] ||= Class.new(superclass) end def setup_class setup_layout setup_constants end def superclass BoxedBase end def layout_superclass GirFFI::Struct end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/null_return_value_builder.rb0000644000004100000410000000056313170036060025016 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Implements a blank return value matching ReturnValueBuilder's interface. class NullReturnValueBuilder def initialize; end def array_length_idx -1 end def capture_variable_name nil end def post_conversion [] end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/function_builder.rb0000644000004100000410000000207113170036060023072 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/return_value_builder' require 'gir_ffi/builders/base_method_builder' module GirFFI module Builders # Implements the creation of a Ruby function definition out of a GIR # IFunctionInfo. class FunctionBuilder < BaseMethodBuilder def initialize(info) super(info, ReturnValueBuilder) end def method_name @info.safe_name end def result if argument_builder_collection.has_return_values? ["return #{argument_builder_collection.return_value_names.join(', ')}"] else [] end end def singleton_method? !@info.method? end def function_call_arguments ca = argument_builder_collection.call_argument_names.dup ca.unshift receiver_call_argument if @info.method? ca end private def receiver_call_argument if @info.instance_ownership_transfer == :everything 'self.ref' else 'self' end end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/object_builder.rb0000644000004100000410000001021213170036060022507 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/registered_type_builder' require 'gir_ffi/builders/with_layout' require 'gir_ffi/builders/property_builder' require 'gir_ffi/object_base' require 'gir_ffi/struct' module GirFFI module Builders # Implements the creation of a class representing a GObject Object. class ObjectBuilder < RegisteredTypeBuilder include WithLayout # Dummy builder for the ObjectBase class class ObjectBaseBuilder def build_class ObjectBase end def ancestor_infos [] end end def find_signal(signal_name) seek_in_ancestor_infos { |info| info.find_signal signal_name } end def find_property(property_name) seek_in_ancestor_infos { |info| info.find_property property_name } end def object_class_struct @object_class_struct ||= Builder.build_class object_class_struct_info end def ancestor_infos @ancestor_infos ||= [info] + info.interfaces + parent_ancestor_infos end def eligible_fields info.fields.reject do |finfo| fname = finfo.name fname == 'parent_instance' || info.find_instance_method("get_#{fname}") || info.find_property(fname) end end def eligible_properties info.properties.reject do |pinfo| info.find_instance_method("get_#{pinfo.name}") end end protected def object_class_struct_info @object_class_struct_info ||= info.class_struct || parent_builder.object_class_struct_info end private def setup_class setup_layout setup_constants stub_methods setup_field_accessors setup_property_accessors setup_vfunc_invokers setup_interfaces provide_initializer end # FIXME: Private method only used in subclass def layout_superclass GirFFI::Struct end def parent_info info.parent end def superclass @superclass ||= parent_builder.build_class end def parent_builder @parent_builder ||= if parent_info Builders::TypeBuilder.builder_for(parent_info) else ObjectBaseBuilder.new end end def parent_ancestor_infos @parent_ancestor_infos ||= parent_builder.ancestor_infos end def setup_field_accessors eligible_fields.each do |finfo| FieldBuilder.new(finfo, klass).build end end def setup_property_accessors eligible_properties.each do |prop| PropertyBuilder.new(prop).build end end # TODO: Guard agains accidental invocation of undefined vfuncs. # TODO: Create object responsible for creating these invokers def setup_vfunc_invokers info.vfuncs.each do |vfinfo| define_vfunc_invoker vfinfo.name, vfinfo.invoker_name if vfinfo.has_invoker? end end def define_vfunc_invoker(vfunc_name, invoker_name) return if vfunc_name == invoker_name klass.class_eval " def #{vfunc_name} *args, &block #{invoker_name}(*args, &block) end " end def provide_initializer return if info.find_method 'new' if info.abstract? klass.class_eval <<-RUBY def initialize(*) raise NoMethodError end RUBY else klass.class_eval <<-RUBY def initialize(properties = {}) base_initialize(properties) end RUBY end end def setup_interfaces interfaces.each do |iface| klass.send :include, iface end end def interfaces info.interfaces.map do |ifinfo| GirFFI::Builder.build_class ifinfo end end def seek_in_ancestor_infos ancestor_infos.each do |info| item = yield info return item if item end nil end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/method_template.rb0000644000004100000410000000426013170036060022714 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Encapsulates the general structure of generated methods, consisting of a # preparation phase where arguments are converted to the form needed by the # main call of the method, the main call itself, a post-processing phase # where the return values and any 'out' arguments of the main call are # converted into a form suitable for returning, and finally the returning # of said values to the caller. # # The different method builders collaborate with MethodTemplate to build # the desired method. class MethodTemplate def initialize(builder, argument_builder_collection) @builder = builder @argument_builder_collection = argument_builder_collection end def method_definition code = "def #{qualified_method_name}" code += "(#{method_arguments.join(', ')})" if method_arguments.any? method_lines.each { |line| code += "\n #{line}" } code + "\nend\n" end private def qualified_method_name "#{@builder.singleton_method? ? 'self.' : ''}#{@builder.method_name}" end def method_arguments @builder.method_arguments end def method_lines method_preparation + parameter_preparation + invocation + return_value_conversion + result end def method_preparation @builder.preparation end def parameter_preparation @argument_builder_collection.parameter_preparation end def invocation if result_name_list.empty? plain_invocation else capturing_invocation end end def return_value_conversion @argument_builder_collection.return_value_conversion end def result @builder.result end def result_name_list @result_name_list ||= @argument_builder_collection.capture_variable_names.join(', ') end def capturing_invocation ["#{result_name_list} = #{@builder.invocation}"] end def plain_invocation [@builder.invocation].compact end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/pointer_value_convertor.rb0000644000004100000410000000166613170036060024525 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Encapsulates knowledge about how to store values in pointers, and how to # fetch values from pointers. class PointerValueConvertor def initialize(type_spec) @type_spec = type_spec end def pointer_to_value(ptr_exp) case ffi_type_spec when Module "#{ffi_type_spec}.get_value_from_pointer(#{ptr_exp}, 0)" when Symbol "#{ptr_exp}.get_#{ffi_type_spec}(0)" end end def value_to_pointer(ptr_exp, value_exp) case ffi_type_spec when Module "#{ffi_type_spec}.copy_value_to_pointer(#{value_exp}, #{ptr_exp})" when Symbol "#{ptr_exp}.put_#{ffi_type_spec} 0, #{value_exp}" end end private attr_reader :type_spec def ffi_type_spec TypeMap.type_specification_to_ffi_type type_spec end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/c_to_ruby_convertor.rb0000644000004100000410000000362213170036060023630 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module Builders # Builder that generates code to convert values from C to Ruby. Used by # argument builders. class CToRubyConvertor def initialize(type_info, argument, length_arg, ownership_transfer: nil) @type_info = type_info @argument = argument @length_arg = length_arg @ownership_transfer = ownership_transfer end def conversion case @type_info.flattened_tag when :utf8, :filename if @ownership_transfer == :everything "GirFFI::AllocationHelper.free_after #{@argument}, &:to_utf8" else "#{@argument}.to_utf8" end when :object base = "#{@type_info.argument_class_name}.wrap(#{conversion_argument_list})" @ownership_transfer == :nothing ? "#{base}.tap { |it| it && it.ref }" : base else "#{argument_class}.#{conversion_method}(#{conversion_argument_list})" end end private def conversion_method case @type_info.flattened_tag when :struct, :union case @ownership_transfer when :everything 'wrap_own' when :nothing 'wrap_copy' else 'wrap' end else 'wrap' end end def conversion_argument_list conversion_arguments.join(', ') end def conversion_arguments case @type_info.flattened_tag when :c [@type_info.element_type.inspect, array_size, @argument] else @type_info.extra_conversion_arguments.map(&:inspect).push(@argument) end end def array_size if @length_arg @length_arg else @type_info.array_fixed_size end end def argument_class @type_info.argument_class_name end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/closure_argument_builder.rb0000644000004100000410000000065113170036060024625 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/callback_argument_builder' module GirFFI module Builders # Convertor for arguments for RubyClosure objects. Used when building the # marshaller for signal handler closures. class ClosureArgumentBuilder < CallbackArgumentBuilder def needs_c_to_ruby_conversion? type_info.needs_c_to_ruby_conversion_for_closures? end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/initializer_builder.rb0000644000004100000410000000130213170036060023564 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/initializer_return_value_builder' require 'gir_ffi/builders/base_method_builder' module GirFFI module Builders # Implements the creation of a Ruby object initializer definition out of a # GIR IFunctionInfo. class InitializerBuilder < BaseMethodBuilder def initialize(info) super(info, InitializerReturnValueBuilder) end def singleton_method? false end def method_name @info.safe_name.sub(/^new/, 'initialize') end def result [] end def function_call_arguments argument_builder_collection.call_argument_names end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/property_return_value_builder.rb0000644000004100000410000000061313170036060025724 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/return_value_builder' module GirFFI module Builders # Implements building post-processing statements for return values of # property getters. class PropertyReturnValueBuilder < ReturnValueBuilder def needs_c_to_ruby_conversion? type_info.needs_c_to_ruby_conversion_for_properties? end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/registered_type_builder.rb0000644000004100000410000000461313170036060024447 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/base_type_builder' require 'gir_ffi/method_stubber' require 'gir_ffi/builders/function_builder' require 'gir_ffi/builders/constructor_builder' require 'gir_ffi/builders/initializer_builder' module GirFFI module Builders # Base class for type builders building types specified by subtypes # of IRegisteredTypeInfo. These are types whose C representation is # complex, i.e., a struct or a union. class RegisteredTypeBuilder < BaseTypeBuilder def setup_method(method) method_info = info.find_method method return unless method_info attach_and_define_method method_info, meta_class end def setup_instance_method(method) method_info = info.find_instance_method method return unless method_info attach_and_define_method method_info, build_class end def target_gtype info.g_type end private def meta_class (class << build_class; self; end) end def attach_and_define_method(method_info, modul) method = method_info.safe_name attach_method method_info remove_old_method method, modul define_method method_info method end def define_method(method_info) if method_info.constructor? initializer_builder = InitializerBuilder.new(method_info) initializer_name = initializer_builder.method_name.to_sym unless build_class.private_instance_methods(false).include? initializer_name build_class.class_eval initializer_builder.method_definition end build_class.class_eval ConstructorBuilder.new(method_info).method_definition else build_class.class_eval FunctionBuilder.new(method_info).method_definition end end def remove_old_method(method, modul) modul.class_eval { remove_method method if method_defined? method } end def attach_method(method_info) Builder.attach_ffi_function lib, method_info end def stub_methods info.get_methods.each do |minfo| klass.class_eval MethodStubber.new(minfo).method_stub end end def setup_constants klass.const_set :G_TYPE, target_gtype super end def parent_info nil end def fields info.fields end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/constructor_builder.rb0000644000004100000410000000263213170036060023635 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/argument_builder_collection' require 'gir_ffi/builders/method_template' require 'gir_ffi/builders/null_return_value_builder' module GirFFI module Builders # Implements the creation of a Ruby constructor definition out of a # GIR IFunctionInfo. # TODO: Derive from BaseMethodBuilder class ConstructorBuilder def initialize(info) @info = info return_value_builder = NullReturnValueBuilder.new arg_builders = ArgumentBuilderCollection.new(return_value_builder, []) @template = MethodTemplate.new(self, arg_builders) end def method_definition @template.method_definition end def singleton_method? true end def method_name @info.safe_name end def method_arguments ['*args', '&block'] end def preparation if @info.safe_name == 'new' ['obj = allocate'] else [ "raise NoMethodError unless self == #{@info.container.full_type_name}", 'obj = allocate' ] end end def invocation "obj.__send__ #{initializer_name.to_sym.inspect}, #{method_arguments.join(', ')}" end def result ['obj'] end private def initializer_name @info.safe_name.sub(/^new/, 'initialize') end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/return_value_builder.rb0000644000004100000410000000240113170036060023755 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/base_return_value_builder' require 'gir_ffi/builders/full_c_to_ruby_convertor' require 'gir_ffi/builders/closure_convertor' module GirFFI module Builders # Implements building post-processing statements for return values. class ReturnValueBuilder < BaseReturnValueBuilder def post_conversion result = [] if has_post_conversion? result << "#{post_converted_name} = #{post_convertor.conversion}" end result end def has_post_conversion? closure? || needs_c_to_ruby_conversion? end def needs_c_to_ruby_conversion? type_info.needs_c_to_ruby_conversion_for_functions? end private def post_convertor @post_convertor ||= if closure? ClosureConvertor.new(capture_variable_name) else FullCToRubyConvertor.new(type_info, capture_variable_name, length_argument_name, ownership_transfer: arginfo.ownership_transfer) end end def length_argument_name length_arg && length_arg.post_converted_name end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/struct_like.rb0000644000004100000410000000075613170036060022077 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/with_layout' module GirFFI module Builders # Implements base methods used by struct and union builders module StructLike include WithLayout def setup_class setup_layout setup_constants stub_methods setup_field_accessors end def setup_field_accessors fields.each do |finfo| FieldBuilder.new(finfo, klass).build end end end end end gir_ffi-0.11.4/lib/gir_ffi/builders/struct_builder.rb0000644000004100000410000000162713170036060022577 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/registered_type_builder' require 'gir_ffi/builders/struct_like' require 'gir_ffi/struct_base' module GirFFI module Builders # Implements the creation of a class representing a Struct. class StructBuilder < RegisteredTypeBuilder include StructLike def layout_superclass GirFFI::Struct end def superclass if info.gtype_struct? # HACK: Inheritance chain is not expressed in GObject's code correctly. type_name = info.full_type_name return GObject::ObjectClass if type_name == 'GObject::InitiallyUnownedClass' type = fields.first.field_type return type.tag_or_class if type.tag == :interface end if GObject.type_fundamental(info.gtype) == GObject::TYPE_BOXED return BoxedBase end StructBase end end end end gir_ffi-0.11.4/lib/gir_ffi/ffi_ext/0000755000004100000410000000000013170036060017025 5ustar www-datawww-datagir_ffi-0.11.4/lib/gir_ffi/ffi_ext/pointer.rb0000644000004100000410000000152713170036060021037 0ustar www-datawww-data# frozen_string_literal: true module GirFFI module FFIExt # Extensions to FFI::Pointer module Pointer def to_ptr self end def zero? null? end # FIXME: Should probably not be here. def to_object return nil if null? gtype = GObject.type_from_instance_pointer self Builder.build_by_gtype(gtype).direct_wrap self end def to_utf8 null? ? nil : read_string.force_encoding('utf-8') end end end end FFI::Pointer.prepend GirFFI::FFIExt::Pointer FFI::Pointer.class_eval do size_t_getter = case FFI.type_size(:size_t) when 4 :get_uint32 when 8 :get_uint64 end alias_method :get_size_t, size_t_getter alias_method :get_gtype, :get_size_t end gir_ffi-0.11.4/lib/gir_ffi/struct_base.rb0000644000004100000410000000060213170036060020242 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/struct_like_base' module GirFFI # Base class for generated classes representing GLib structs. class StructBase < ClassBase extend FFI::DataConverter include GirFFI::StructLikeBase def initialize @struct = self.class::Struct.new @struct.owned = true @struct.to_ptr.autorelease = false end end end gir_ffi-0.11.4/lib/gir_ffi/union.rb0000644000004100000410000000023613170036060017057 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/ownable' module GirFFI # Union that can be owned. class Union < FFI::Union include Ownable end end gir_ffi-0.11.4/lib/gir_ffi/field_argument_info.rb0000644000004100000410000000101713170036060021725 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Class to represent argument info for the argument of a setter method. # Implements the necessary parts of IArgumentInfo's interface. # TODO: Rename and add direction argument or subclass class FieldArgumentInfo attr_reader :name, :argument_type def initialize(name, type) @name = name @argument_type = type end def direction :in end def ownership_transfer :everything end def skip? false end end end gir_ffi-0.11.4/lib/gir_ffi/allocation_helper.rb0000644000004100000410000000042113170036060021407 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/lib_c' module GirFFI # Helper module for alloction-related functionality. module AllocationHelper def self.free_after(ptr) result = yield ptr LibC.free ptr unless ptr.null? result end end end gir_ffi-0.11.4/lib/gir_ffi/enum_like_base.rb0000644000004100000410000000160713170036060020674 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/registered_type_base' module GirFFI # Base module for enums and flags. module EnumLikeBase include FFI::DataConverter include RegisteredTypeBase def wrap(arg) self[arg] end def from(arg) self[arg] end def size native_type.size end def copy_value_to_pointer(value, pointer) pointer.put_int32 0, to_native(value, nil) end def get_value_from_pointer(pointer, offset) from_native pointer.get_int32(offset), nil end def setup_and_call(method, arguments, &block) result = setup_method method.to_s unless result raise "Unable to set up method #{method} in #{self}" end send method, *arguments, &block end def to_ffi_type self end def setup_method(name) gir_ffi_builder.setup_method name end end end gir_ffi-0.11.4/lib/gir_ffi/arg_helper.rb0000644000004100000410000000377413170036060020051 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/allocation_helper' require 'gir_ffi/builder' require 'gir_ffi/glib_error' require 'gir_ffi/object_store' module GirFFI # Helper module containing methods used during argument conversion in # generated methods. module ArgHelper OBJECT_STORE = ObjectStore.new def self.check_error(errpp) err = GLib::Error.wrap(errpp.read_pointer) raise GLibError, err if err end def self.check_fixed_array_size(size, arr, name) unless arr.size.equal? size raise ArgumentError, "#{name} should have size #{size}" end end # NOTE: Only used in List, SList and HashTable classes. # TODO: Stop using basic types and instead cast type to an ITypeInfo # look-alike. def self.cast_from_pointer(type, ptr) case type when Symbol cast_from_simple_type_pointer(type, ptr) when Class type.wrap ptr when Array cast_from_complex_type_pointer(type, ptr) end end def self.cast_uint32_to_int32(val) if val >= 0x80000000 -(0x100000000 - val) else val end end def self.cast_pointer_to_int32(ptr) cast_uint32_to_int32(ptr.address & 0xffffffff) end def self.store(obj) OBJECT_STORE.store(obj) end def self.cast_from_simple_type_pointer(type, ptr) case type when :utf8, :filename ptr.to_utf8 when :gint32, :gint8 cast_pointer_to_int32 ptr when :guint32 ptr.address else raise "Don't know how to cast #{type}" end end def self.cast_from_complex_type_pointer(type, ptr) main_type, (container_type, *element_type) = *type case main_type when :pointer case container_type when :ghash return GLib::HashTable.wrap(element_type, ptr) end end raise "Don't know how to cast #{type}" end private_class_method :cast_from_complex_type_pointer, :cast_from_simple_type_pointer end end gir_ffi-0.11.4/lib/gir_ffi/in_pointer.rb0000644000004100000410000000572113170036060020101 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # The InPointer module handles conversion from ruby types to pointers for # arguments with direction :in. This is used for arguments that are # arrays, strings, or interfaces. module InPointer def self.from_array(type, ary) return unless ary case type when :utf8, :filename from_utf8_array ary when :gboolean from_boolean_array ary when Symbol from_basic_type_array type, ary when Class if type == GObject::Value from_gvalue_array type, ary else from_struct_array type, ary end when Module from_enum_array type, ary when Array main_type, sub_type = *type raise "Unexpected main type #{main_type}" if main_type != :pointer from_pointer_array sub_type, ary else raise NotImplementedError, type end end def self.from(type, val) return unless val case type when :utf8, :filename from_utf8 val when :gint32, :guint32, :gint8, :GType FFI::Pointer.new val when GirFFI::EnumLikeBase FFI::Pointer.new type[val] when Module, :void val.to_ptr else raise NotImplementedError, type end end class << self private def from_utf8_array(ary) from_basic_type_array :pointer, ary.map { |str| from_utf8 str } end def from_boolean_array(ary) from_basic_type_array :int, ary.map { |val| val ? 1 : 0 } end def from_pointer_array(type, ary) from_basic_type_array :pointer, ary.map { |elem| from type, elem } end def from_gvalue_array(type, ary) ary = ary.map do |it| if it.is_a? GObject::Value it else GObject::Value.wrap_ruby_value it end end from_struct_array type, ary end def from_struct_array(type, ary) ffi_type = TypeMap.type_specification_to_ffi_type type type_size = FFI.type_size(ffi_type) length = ary.length ptr = FFI::MemoryPointer.new type_size * (length + 1) ptr.autorelease = false ary.each_with_index do |item, idx| type.copy_value_to_pointer item, ptr, idx * type_size end ptr end def from_enum_array(type, ary) from_basic_type_array :int32, ary.map { |sym| type.to_native sym, nil } end public def from_utf8(str) return unless str ptr = FFI::MemoryPointer.from_string(str) ptr.autorelease = false ptr end private def from_basic_type_array(type, ary) ffi_type = TypeMap.type_specification_to_ffi_type type type_size = FFI.type_size(ffi_type) FFI::MemoryPointer.new(type_size * (ary.length + 1)).tap do |block| block.autorelease = false block.send "put_array_of_#{ffi_type}", 0, ary end end end end end gir_ffi-0.11.4/lib/gir_ffi/type_map.rb0000644000004100000410000000262613170036060017552 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/boolean' require 'gir_ffi/sized_array' module GirFFI # Maps GObject type tags and type specification to types FFI can handle. module TypeMap sz = FFI.type_size(:size_t) * 8 gsize_type = "uint#{sz}".to_sym TAG_TYPE_MAP = { enum: :int32, flags: :int32, ghash: :pointer, glist: :pointer, gslist: :pointer, strv: :pointer, interface: :pointer, error: :pointer, ptr_array: :pointer, array: :pointer, c: GirFFI::SizedArray, utf8: :pointer, GType: gsize_type, gboolean: GirFFI::Boolean, gunichar: :uint32, gint8: :int8, guint8: :uint8, gint16: :int16, guint16: :uint16, gint: :int, guint: :uint, gint32: :int32, guint32: :uint32, gint64: :int64, guint64: :uint64, glong: :long, gulong: :ulong, gsize: gsize_type, gfloat: :float, gdouble: :double, void: :void }.freeze def self.map_basic_type(type) sym = type.to_sym TAG_TYPE_MAP[sym] || sym end def self.type_specification_to_ffi_type(type) case type when Module type.to_ffi_type when Array type[0] else map_basic_type(type) end end end end gir_ffi-0.11.4/lib/gir_ffi/enum_base.rb0000644000004100000410000000062413170036060017666 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/enum_like_base' module GirFFI # Base module for enums. module EnumBase include EnumLikeBase def native_type self::Enum.native_type end def to_native(*args) self::Enum.to_native(*args) end def from_native(*args) self::Enum.from_native(*args) end def [](arg) self::Enum[arg] end end end gir_ffi-0.11.4/lib/gir_ffi/user_defined_property_info.rb0000644000004100000410000000471513170036060023350 0ustar www-datawww-data# frozen_string_literal: true module GirFFI # Represents a property of a user defined type. class UserDefinedPropertyInfo def initialize(param_spec) @param_spec = param_spec end attr_reader :param_spec def name @param_spec.get_name end def accessor_name @param_spec.accessor_name end def writable? @param_spec.flags[:writable] end def value_type @param_spec.value_type end # TODO: Unify with InfoExt::ITypeInfo.flattened_tag_to_gtype_map G_TYPE_POINTER_MAP = { GObject::TYPE_BOOLEAN => false, GObject::TYPE_CHAR => false, GObject::TYPE_UCHAR => false, GObject::TYPE_FLOAT => false, GObject::TYPE_DOUBLE => false, GObject::TYPE_INT => false, GObject::TYPE_UINT => false, GObject::TYPE_LONG => false, GObject::TYPE_ULONG => false, GObject::TYPE_INT64 => false, GObject::TYPE_UINT64 => false, GObject::TYPE_ENUM => false, GObject::TYPE_FLAGS => false, GObject::TYPE_STRING => true, GObject::TYPE_BOXED => true, GObject::TYPE_OBJECT => true }.freeze def pointer_type? G_TYPE_POINTER_MAP.fetch(fundamental_value_type) end # TODO: Unify with InfoExt::ITypeInfo.flattened_tag_to_gtype_map G_TYPE_TAG_MAP = { GObject::TYPE_BOOLEAN => :gboolean, GObject::TYPE_CHAR => :gint8, GObject::TYPE_UCHAR => :guint8, GObject::TYPE_FLOAT => :gfloat, GObject::TYPE_DOUBLE => :gdouble, GObject::TYPE_INT => :gint, GObject::TYPE_UINT => :guint, GObject::TYPE_LONG => :glong, GObject::TYPE_ULONG => :gulong, GObject::TYPE_INT64 => :gint64, GObject::TYPE_UINT64 => :guint64, GObject::TYPE_ENUM => :interface, GObject::TYPE_FLAGS => :interface, GObject::TYPE_STRING => :utf8, GObject::TYPE_BOXED => :interface, GObject::TYPE_OBJECT => :interface }.freeze def type_tag G_TYPE_TAG_MAP.fetch(fundamental_value_type) end G_TYPE_INTERFACE_TAG_MAP = { GObject::TYPE_ENUM => :enum, GObject::TYPE_FLAGS => :flags, GObject::TYPE_BOXED => :struct, GObject::TYPE_OBJECT => :object }.freeze def interface_type_tag G_TYPE_INTERFACE_TAG_MAP.fetch(fundamental_value_type) end def fundamental_value_type @fundamental_value_type ||= GObject.type_fundamental value_type end def ffi_type GirFFI::TypeMap.map_basic_type(type_tag) end end end gir_ffi-0.11.4/lib/gir_ffi/builder.rb0000644000004100000410000000330613170036060017356 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/builders/type_builder' require 'gir_ffi/builders/module_builder' require 'gir_ffi/builder_helper' require 'gir_ffi/unintrospectable_type_info' require 'gir_ffi/unintrospectable_boxed_info' module GirFFI # Builds modules and classes based on information found in the # introspection repository. Call its build_module and build_class methods # to create the modules and classes used in your program. module Builder extend BuilderHelper def self.build_class(info) Builders::TypeBuilder.build(info) end def self.build_by_gtype(gtype) info = GObjectIntrospection::IRepository.default.find_by_gtype gtype info ||= case GObject.type_fundamental gtype when GObject::TYPE_BOXED UnintrospectableBoxedInfo.new gtype when GObject::TYPE_OBJECT UnintrospectableTypeInfo.new gtype end build_class info end def self.build_module(namespace, version = nil) module_name = namespace.sub(/\A./, &:upcase) if const_defined? module_name modul = const_get module_name unless modul.const_defined? :GIR_FFI_BUILDER raise "The module #{module_name} was already defined elsewhere" end end Builders::ModuleBuilder.new(module_name, namespace: namespace, version: version).generate end # TODO: Move elsewhere, perhaps to FunctionBuilder. def self.attach_ffi_function(lib, info) sym = info.symbol return if lib.method_defined? sym lib.attach_function sym, info.argument_ffi_types, info.return_ffi_type end end end gir_ffi-0.11.4/lib/gir_ffi/registered_type_base.rb0000644000004100000410000000041413170036060022115 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi/type_base' module GirFFI # Base module for generated registered GLib types (these are types that have a # GType). module RegisteredTypeBase include TypeBase def gtype self::G_TYPE end end end gir_ffi-0.11.4/lib/gir_ffi-base.rb0000644000004100000410000000041713170036060016640 0ustar www-datawww-data# frozen_string_literal: true # # This section contains code that is needed by GirFFI, but belongs in modules # that can only be created fully once GirFFI is fully loaded. # Some base GObject functions and constants are needed by GirFFI. require 'gir_ffi-base/gobject' gir_ffi-0.11.4/lib/ffi-glib/0000755000004100000410000000000013170036060015453 5ustar www-datawww-datagir_ffi-0.11.4/lib/ffi-glib/variant.rb0000644000004100000410000000157513170036060017454 0ustar www-datawww-data# frozen_string_literal: true GLib.load_class :Variant module GLib # Overrides for GVariant, GLib's variant data type. class Variant setup_instance_method 'get_string' def get_string_with_override get_string_without_override.first end alias_method :get_string_without_override, :get_string alias_method :get_string, :get_string_with_override # Initializing method used in constructors. For Variant, this needs to sink # the variant's floating reference. # # NOTE: This is very hard to test since it is not possible to get the # variant's ref count directely. However, there is an error when running # the tests on 32-bit systems. # def store_pointer(ptr) Lib.g_variant_ref_sink ptr super end # For variants, wrap_copy does not do any copying. def self.wrap_copy(val) wrap(val) end end end gir_ffi-0.11.4/lib/ffi-glib/s_list.rb0000644000004100000410000000072713170036060017303 0ustar www-datawww-data# frozen_string_literal: true require 'ffi-glib/list_methods' GLib.load_class :SList module GLib # Overrides for GSList, GLib's singly-linked list implementation. class SList include ListMethods def self.from_enumerable(type, arr) arr.reverse.reduce(new(type)) { |lst, val| lst.prepend val } end def prepend(data) self.class.wrap(element_type, Lib.g_slist_prepend(self, element_ptr_for(data))) end end end gir_ffi-0.11.4/lib/ffi-glib/ptr_array.rb0000644000004100000410000000246313170036060020010 0ustar www-datawww-data# frozen_string_literal: true require 'ffi-glib/container_class_methods' require 'ffi-glib/array_methods' GLib.load_class :PtrArray module GLib # Overrides for GPtrArray, GLib's automatically growing array of # pointers. class PtrArray include Enumerable include ArrayMethods extend ContainerClassMethods attr_reader :element_type POINTER_SIZE = FFI.type_size(:pointer) class << self # Remove stub generated by builder. remove_method :add if method_defined? :add end def initialize(type) @element_type = type store_pointer Lib.g_ptr_array_new end def self.from_enumerable(type, it) new(type).tap { |arr| arr.add_array it } end def self.add(array, data) array.add data end def reset_typespec(typespec) @element_type = typespec self end def add(data) ptr = GirFFI::InPointer.from element_type, data Lib.g_ptr_array_add self, ptr end def add_array(ary) ary.each { |item| add item } end def data_ptr @struct[:pdata] end def element_size POINTER_SIZE end def each length.times do |idx| yield index(idx) end end def length @struct[:len] end def ==(other) to_a == other.to_a end end end gir_ffi-0.11.4/lib/ffi-glib/destroy_notify.rb0000644000004100000410000000071313170036060021062 0ustar www-datawww-data# frozen_string_literal: true GLib.load_class :DestroyNotify module GLib # Overrides for DestroyNotify, the callback type for destroy notifications. # It should not be necessary to create objects of this class from Ruby # directly. class DestroyNotify def self.default @default ||= from proc { |user_data| callback_key = GirFFI::ArgHelper::OBJECT_STORE.fetch(user_data) drop_callback callback_key } end end end gir_ffi-0.11.4/lib/ffi-glib/byte_array.rb0000644000004100000410000000072213170036060020142 0ustar www-datawww-data# frozen_string_literal: true GLib.load_class :ByteArray module GLib # Overrides for GByteArray, GLib's automatically growing array of bytes. class ByteArray def to_string data.read_string len end def append(data) bytes = GirFFI::InPointer.from_utf8 data len = data.bytesize self.class.wrap Lib.g_byte_array_append(to_ptr, bytes, len) end def initialize store_pointer(Lib.g_byte_array_new) end end end gir_ffi-0.11.4/lib/ffi-glib/bytes.rb0000644000004100000410000000176613170036060017140 0ustar www-datawww-data# frozen_string_literal: true GLib.load_class :Bytes module GLib # Overrides for GBytes, GLib's immutable array of bytes. class Bytes include Enumerable remove_method :get_data if method_defined? :get_data # @override # NOTE: Needed due to mis-identification of the element-type of the # resulting sized array for the default binding. def get_data length_ptr = FFI::MemoryPointer.new :size_t data_ptr = Lib.g_bytes_get_data self, length_ptr length = length_ptr.get_size_t(0) GirFFI::SizedArray.wrap(:guint8, length, data_ptr) end def each(&block) data.each(&block) end def self.from(it) case it when self it when FFI::Pointer wrap it else new it end end def initialize(arr) data = GirFFI::SizedArray.from :guint8, arr.size, arr store_pointer Lib.g_bytes_new data.to_ptr, data.size end private def data @data ||= get_data end end end gir_ffi-0.11.4/lib/ffi-glib/iconv.rb0000644000004100000410000000054413170036060017121 0ustar www-datawww-data# frozen_string_literal: true GLib.load_class :IConv module GLib # Overrides for IConv class IConv def self.open(to_codeset, from_codeset) to_ptr = GirFFI::InPointer.from_utf8 to_codeset from_ptr = GirFFI::InPointer.from_utf8 from_codeset result_ptr = Lib.g_iconv_open(to_ptr, from_ptr) wrap(result_ptr) end end end gir_ffi-0.11.4/lib/ffi-glib/list_methods.rb0000644000004100000410000000251313170036060020477 0ustar www-datawww-data# frozen_string_literal: true require 'ffi-glib/container_class_methods' module GLib # Common methods for List and SList. module ListMethods include Enumerable attr_reader :element_type def self.included(base) # Override default field accessors. replace_method base, :next, :tail replace_method base, :data, :head base.extend ContainerClassMethods end def self.replace_method(base, old, new) base.class_eval do remove_method old alias_method old, new end end def initialize(type) store_pointer(FFI::Pointer.new(0)) @element_type = type end def each reset_iterator while (elem = next_element) yield elem end end def tail self.class.wrap(element_type, @struct[:next]) end def head GirFFI::ArgHelper.cast_from_pointer(element_type, @struct[:data]) end def reset_typespec(typespec) @element_type = typespec self end def ==(other) to_a == other.to_a end private def reset_iterator @current = self end def next_element return unless @current element = @current.head @current = @current.tail element end def element_ptr_for(data) GirFFI::InPointer.from(element_type, data) end end end gir_ffi-0.11.4/lib/ffi-glib/hash_table.rb0000644000004100000410000000376013170036060020100 0ustar www-datawww-data# frozen_string_literal: true require 'ffi-glib/container_class_methods' GLib.load_class :HashTable module GLib # Overrides for GHashTable, GLib's hash table implementation. class HashTable include Enumerable extend ContainerClassMethods attr_reader :key_type attr_reader :value_type def initialize(key_type, value_type) @key_type = key_type @value_type = value_type store_pointer Lib.g_hash_table_new( hash_function_for_key_type, equality_function_for_key_type) end # @api private def self.from_enumerable(typespec, hash) ghash = new(*typespec) hash.each do |key, val| ghash.insert key, val end ghash end def each prc = proc do |keyptr, valptr, _userdata| key = GirFFI::ArgHelper.cast_from_pointer key_type, keyptr val = GirFFI::ArgHelper.cast_from_pointer value_type, valptr yield key, val end callback = GLib::HFunc.from prc ::GLib::Lib.g_hash_table_foreach to_ptr, callback, nil end def to_hash Hash[to_a] end # @override def insert(key, value) keyptr = GirFFI::InPointer.from key_type, key valptr = GirFFI::InPointer.from value_type, value ::GLib::Lib.g_hash_table_insert to_ptr, keyptr, valptr end # @api private def reset_typespec(typespec) @key_type, @value_type = *typespec self end private def hash_function_for_key_type case @key_type when :utf8 FFI::Function.new(:uint, [:pointer], find_support_function('g_str_hash')) end end def equality_function_for_key_type case @key_type when :utf8 FFI::Function.new(:int, [:pointer, :pointer], find_support_function('g_str_equal')) end end def find_support_function(name) lib = ::GLib::Lib.ffi_libraries.first lib.find_function(name) end end end gir_ffi-0.11.4/lib/ffi-glib/list.rb0000644000004100000410000000071013170036060016751 0ustar www-datawww-data# frozen_string_literal: true require 'ffi-glib/list_methods' GLib.load_class :List module GLib # Overrides for GList, GLib's doubly linked list implementation. class List include ListMethods def self.from_enumerable(type, arr) arr.reduce(new(type)) { |lst, val| lst.append val } end def append(data) self.class.wrap(element_type, Lib.g_list_append(self, element_ptr_for(data))) end end end gir_ffi-0.11.4/lib/ffi-glib/array.rb0000644000004100000410000000402013170036060017112 0ustar www-datawww-data# frozen_string_literal: true require 'ffi-glib/container_class_methods' require 'ffi-glib/array_methods' GLib.load_class :Array module GLib # Overrides for GArray, GLib's automatically growing array. It should not # be necessary to create objects of this class from Ruby directly. class Array include Enumerable include ArrayMethods extend ContainerClassMethods attr_reader :element_type def initialize(type) @element_type = type ptr = Lib.g_array_new(0, 0, calculated_element_size) store_pointer(ptr) end # @api private def self.from_enumerable(elmtype, it) new(elmtype).tap { |arr| arr.append_vals it } end # @api private def self.calculated_element_size(type) ffi_type = GirFFI::TypeMap.type_specification_to_ffi_type(type) FFI.type_size(ffi_type) end # @override def append_vals(ary) bytes = GirFFI::InPointer.from_array element_type, ary Lib.g_array_append_vals(self, bytes, ary.length) self end def each length.times do |idx| yield index(idx) end end def length @struct[:len] end def get_element_size Lib.g_array_get_element_size self end alias_method :element_size, :get_element_size def ==(other) to_a == other.to_a end # @api private def reset_typespec(typespec = nil) if typespec @element_type = typespec check_element_size_match else @element_type = guess_element_type end self end private def data_ptr @struct[:data] end def calculated_element_size self.class.calculated_element_size element_type end def check_element_size_match unless calculated_element_size == get_element_size warn 'WARNING: Element sizes do not match' end end def guess_element_type case get_element_size when 1 then :uint8 when 2 then :uint16 when 4 then :uint32 when 8 then :uint64 end end end end gir_ffi-0.11.4/lib/ffi-glib/container_class_methods.rb0000644000004100000410000000160213170036060022671 0ustar www-datawww-data# frozen_string_literal: true module GLib # Common methods for container classes: Array, PtrArray, List, SList and # HashTable. module ContainerClassMethods def wrap(typespec, ptr) # HACK: wrap and from are almost the same! ptr = case ptr when nil nil when FFI::Pointer ptr when self ptr.to_ptr when GirFFI::BoxedBase ptr.to_ptr end super(ptr).tap do |container| container.reset_typespec typespec if container end end def from(typespec = :void, it) case it when nil nil when FFI::Pointer wrap typespec, it when self it.reset_typespec typespec when GirFFI::BoxedBase wrap typespec, it.to_ptr else from_enumerable typespec, it end end end end gir_ffi-0.11.4/lib/ffi-glib/main_loop.rb0000644000004100000410000000264513170036060017764 0ustar www-datawww-data# frozen_string_literal: true require 'singleton' GLib.load_class :MainLoop module GLib # Overrides for GMainLoop, GLib's event loop class MainLoop # Class encapsulationg logic for running an idle handler to make Ruby code # run during GLib's event loop. class ThreadEnabler include Singleton FRAMERATE = 25 DEFAULT_TIMEOUT = 1000 / FRAMERATE def initialize(timeout = DEFAULT_TIMEOUT) @timeout = timeout end def setup_idle_handler @handler_id ||= GLib.timeout_add(GLib::PRIORITY_DEFAULT, @timeout, &handler_proc) end private def handler_proc proc do ::Thread.pass true end end end EXCEPTIONS = [] RUNNING_LOOPS = [] setup_instance_method :run def run_with_thread_enabler if RUBY_ENGINE == 'ruby' ThreadEnabler.instance.setup_idle_handler end RUNNING_LOOPS << self result = run_without_thread_enabler ex = EXCEPTIONS.shift RUNNING_LOOPS.pop raise ex if ex result end def self.handle_exception(ex) current_loop = RUNNING_LOOPS.last raise ex unless current_loop EXCEPTIONS << ex current_loop.quit end alias_method :run_without_thread_enabler, :run alias_method :run, :run_with_thread_enabler end end Signal.trap 'INT' do GLib::MainLoop.handle_exception(Interrupt.new) end gir_ffi-0.11.4/lib/ffi-glib/array_methods.rb0000644000004100000410000000070713170036060020645 0ustar www-datawww-data# frozen_string_literal: true module GLib # Common methods for GLib::Array and GLib::PtrArray module ArrayMethods # Re-implementation of the g_array_index and g_ptr_array_index macros def index(idx) if idx >= length || idx < 0 raise IndexError, "Index #{idx} outside of bounds 0..#{length - 1}" end ptr = GirFFI::InOutPointer.new element_type, data_ptr + idx * element_size ptr.to_ruby_value end end end gir_ffi-0.11.4/lib/ffi-glib/error.rb0000644000004100000410000000055013170036060017131 0ustar www-datawww-data# frozen_string_literal: true GLib.load_class :Error module GLib # Overrides for GError, used by GLib for handling non-fatal errors. class Error GIR_FFI_DOMAIN = GLib.quark_from_string('gir_ffi') def self.from_exception(ex) new_literal GIR_FFI_DOMAIN, 0, ex.message end def self.from(it) from_exception it end end end gir_ffi-0.11.4/lib/ffi-glib/strv.rb0000644000004100000410000000121313170036060016773 0ustar www-datawww-data# frozen_string_literal: true module GLib # Represents a null-terminated array of strings. GLib uses this construction, # but does not provide any actual functions for this class. # # The implementation is mainly inherited from GObjectIntrospection::Strv. class Strv < GObjectIntrospection::Strv def ==(other) to_a == other.to_a end def self.from(it) case it when nil nil when FFI::Pointer wrap it when self it else from_enumerable it end end def self.from_enumerable(enum) wrap GirFFI::InPointer.from_array :utf8, enum end end end gir_ffi-0.11.4/COPYING.LIB0000644000004100000410000006347613170036060014706 0ustar www-datawww-data GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! gir_ffi-0.11.4/test/0000755000004100000410000000000013170036060014205 5ustar www-datawww-datagir_ffi-0.11.4/test/ffi-gobject_introspection/0000755000004100000410000000000013170036060021344 5ustar www-datawww-datagir_ffi-0.11.4/test/ffi-gobject_introspection/i_enum_info_test.rb0000644000004100000410000000066413170036060025225 0ustar www-datawww-data# frozen_string_literal: true require 'introspection_test_helper' describe GObjectIntrospection::IEnumInfo do describe '#find_method' do before do gir = GObjectIntrospection::IRepository.default gir.require 'Regress', nil @info = gir.find_by_name 'Regress', 'TestEnum' end it 'finds a method by name' do result = @info.find_method('param') result.name.must_equal 'param' end end end gir_ffi-0.11.4/test/ffi-gobject_introspection/i_repository_test.rb0000644000004100000410000000406013170036060025457 0ustar www-datawww-data# frozen_string_literal: true require 'introspection_test_helper' describe GObjectIntrospection::IRepository do let(:gir) { GObjectIntrospection::IRepository.default } describe 'an instance' do it 'is not created by calling new()' do assert_raises NoMethodError do GObjectIntrospection::IRepository.new end end it 'is created by calling default()' do assert_kind_of GObjectIntrospection::IRepository, gir end it 'is a singleton' do gir2 = GObjectIntrospection::IRepository.default assert_equal gir, gir2 end end describe '#require' do it "raises an error if the namespace doesn't exist" do assert_raises RuntimeError do gir.require 'VeryUnlikelyGObjectNamespaceName', nil end end it 'allows version to be nil' do gir.require 'GObject', nil pass end it 'allows version to be left out' do gir.require 'GObject' pass end end describe '#find_by_gtype' do it 'raises an error if 0 is passed as the gtype' do proc { gir.find_by_gtype 0 }.must_raise ArgumentError end end describe '#n_infos' do it 'yields more than one object for the GObject namespace' do gir.require 'GObject', '2.0' assert_operator gir.n_infos('GObject'), :>, 0 end end describe '#info' do it 'yields IBaseInfo objects' do gir.require 'GObject', '2.0' assert_kind_of GObjectIntrospection::IBaseInfo, gir.info('GObject', 0) end end describe '#dependencies' do it 'returns a list of dependencies of the given namespace' do result = gir.dependencies('GObject') result.must_equal ['GLib-2.0'] end it 'passes its struct pointer to the c function just in case' do ptr = gir.instance_variable_get(:@gobj) allow(GObjectIntrospection::Lib).to receive(:g_irepository_get_dependencies). and_call_original gir.dependencies('GObject') expect(GObjectIntrospection::Lib).to have_received(:g_irepository_get_dependencies). with(ptr, 'GObject') end end end gir_ffi-0.11.4/test/ffi-gobject_introspection/i_registered_type_info_test.rb0000644000004100000410000000130013170036060027443 0ustar www-datawww-data# frozen_string_literal: true require 'introspection_test_helper' describe GObjectIntrospection::IRegisteredTypeInfo do describe '#get_type_name' do describe 'for an interface' do let(:registered_type_info) do get_introspection_data('GIMarshallingTests', 'Interface') end it 'returns interface name' do registered_type_info.type_name.must_equal 'GIMarshallingTestsInterface' end end describe 'for a type that is not an interface' do let(:registered_type_info) do get_introspection_data('GIMarshallingTests', 'Enum') end it 'returns nil' do registered_type_info.type_name.must_be_nil end end end end gir_ffi-0.11.4/test/ffi-gobject_introspection/i_union_info_test.rb0000644000004100000410000000064313170036060025406 0ustar www-datawww-data# frozen_string_literal: true require 'introspection_test_helper' describe GObjectIntrospection::IUnionInfo do let(:object_info) { get_introspection_data('GLib', 'Mutex') } describe '#find_method' do it 'finds a method by name string' do object_info.find_method('clear').wont_be_nil end it 'finds a method by name symbol' do object_info.find_method(:clear).wont_be_nil end end end gir_ffi-0.11.4/test/ffi-gobject_introspection/lib_test.rb0000644000004100000410000000046713170036060023505 0ustar www-datawww-data# frozen_string_literal: true require 'introspection_test_helper' describe GObjectIntrospection::Lib::GIArgument do describe 'its member :v_ssize' do it 'is signed' do gia = GObjectIntrospection::Lib::GIArgument.new gia[:v_int64] = -1 assert_equal(-1, gia[:v_ssize]) end end end gir_ffi-0.11.4/test/ffi-gobject_introspection/i_base_info_test.rb0000644000004100000410000000324013170036060025164 0ustar www-datawww-data# frozen_string_literal: true require 'introspection_test_helper' describe GObjectIntrospection::IBaseInfo do let(:described_class) { GObjectIntrospection::IBaseInfo } describe '#initialize' do it 'raises an error if a null pointer is passed' do expect(ptr = Object.new).to receive(:null?).and_return true proc { described_class.new ptr }.must_raise ArgumentError end it 'raises no error if a non-null pointer is passed' do expect(ptr = Object.new).to receive(:null?).and_return false described_class.new ptr pass end end describe '#deprecated?' do let(:deprecated_info) { get_introspection_data 'Regress', 'test_versioning' } let(:other_info) { get_introspection_data 'Regress', 'test_value_return' } it 'returns true for a deprecated item' do skip unless deprecated_info deprecated_info.must_be :deprecated? end it 'returns false for a non-deprecated item' do other_info.wont_be :deprecated? end end describe 'upon garbage collection' do it 'calls g_base_info_unref' do if jruby? || rubinius? skip 'cannot be reliably tested on JRuby and Rubinius' end expect(ptr = Object.new).to receive(:null?).and_return false expect(lib = Object.new).to receive(:g_base_info_unref).with(ptr).and_return nil described_class.new ptr, lib GC.start # Yes, the next three lines are needed. https://gist.github.com/4277829 allow(ptr2 = Object.new).to receive(:null?).and_return false allow(lib).to receive(:g_base_info_unref).with(ptr2).and_return nil described_class.new ptr2, lib GC.start GC.start end end end gir_ffi-0.11.4/test/ffi-gobject_introspection/strv_test.rb0000644000004100000410000000233513170036060023731 0ustar www-datawww-data# frozen_string_literal: true require 'base_test_helper' describe GObjectIntrospection::Strv do it 'wraps a pointer' do strv = GObjectIntrospection::Strv.new :some_pointer assert_equal :some_pointer, strv.to_ptr end describe '::wrap' do it 'takes a pointer and returns a GObjectIntrospection::Strv wrapping it' do strv = GObjectIntrospection::Strv.wrap :some_pointer assert_instance_of GObjectIntrospection::Strv, strv assert_equal :some_pointer, strv.to_ptr end end describe '#each' do it 'yields each string element' do ary = %w(one two three) ptrs = ary.map { |a| FFI::MemoryPointer.from_string(a) } ptrs << nil block = FFI::MemoryPointer.new(:pointer, ptrs.length) block.write_array_of_pointer ptrs strv = GObjectIntrospection::Strv.new block arr = [] strv.each do |str| arr << str end assert_equal %w(one two three), arr end it 'yields zero times for a Strv wrapping a null pointer' do strv = GObjectIntrospection::Strv.new FFI::Pointer.new(0) strv.each do |_str| flunk end end end it 'includes Enumerable' do GObjectIntrospection::Strv.must_include Enumerable end end gir_ffi-0.11.4/test/ffi-gobject_introspection/i_interface_info_test.rb0000644000004100000410000000112713170036060026214 0ustar www-datawww-data# frozen_string_literal: true require 'introspection_test_helper' describe GObjectIntrospection::IInterfaceInfo do let(:object_info) { get_introspection_data('GObject', 'TypePlugin') } describe '#find_method' do it 'finds a method by name string' do object_info.find_method('complete_interface_info').wont_be_nil end it 'finds a method by name symbol' do object_info.find_method(:complete_interface_info).wont_be_nil end end describe '#type_name' do it 'returns the correct name' do object_info.type_name.must_equal 'GTypePlugin' end end end gir_ffi-0.11.4/test/ffi-gobject_introspection/i_type_info_test.rb0000644000004100000410000000201413170036060025231 0ustar www-datawww-data# frozen_string_literal: true require 'introspection_test_helper' describe GObjectIntrospection::ITypeInfo do describe '#name?' do let(:object_info) { get_introspection_data('GIMarshallingTests', 'Object') } let(:vfunc_info) { object_info.find_vfunc('vfunc_array_out_parameter') } let(:arg_info) { vfunc_info.args[0] } let(:type_info) { arg_info.argument_type } it 'raises an error' do skip unless vfunc_info proc do type_info.name end.must_raise RuntimeError end end describe '#interface' do describe 'for unresolvable interface types' do let(:function_info) { get_introspection_data 'GObject', 'signal_set_va_marshaller' } let(:argument_info) { function_info.args.last } let(:type_info) { argument_info.argument_type } it 'returns an IUnresolvableInfo object' do result = type_info.interface result.info_type.must_equal :unresolved result.must_be_kind_of GObjectIntrospection::IUnresolvedInfo end end end end gir_ffi-0.11.4/test/ffi-gobject_introspection/i_struct_info_test.rb0000644000004100000410000000106413170036060025600 0ustar www-datawww-data# frozen_string_literal: true require 'introspection_test_helper' describe GObjectIntrospection::IStructInfo do let(:object_info) { get_introspection_data('GObject', 'Closure') } describe '#find_method' do it 'finds a method by name string' do object_info.find_method('new_simple').wont_be_nil end it 'finds a method by name symbol' do object_info.find_method(:new_simple).wont_be_nil end end describe '#type_name' do it 'returns the correct name' do object_info.type_name.must_equal 'GClosure' end end end gir_ffi-0.11.4/test/ffi-gobject_introspection/i_constant_info_test.rb0000644000004100000410000000157613170036060026115 0ustar www-datawww-data# frozen_string_literal: true require 'introspection_test_helper' describe GObjectIntrospection::IConstantInfo do describe 'for GLib::USEC_PER_SEC, a constant of type :gint32' do let(:constant_info) { get_introspection_data 'GLib', 'USEC_PER_SEC' } it 'returns :gint32 as its type' do assert_equal :gint32, constant_info.constant_type.tag end it 'returns 1_000_000 as its value' do assert_equal 1_000_000, constant_info.value end end describe 'for GLib::SOURCE_CONTINUE, a constant of type :gboolean' do let(:constant_info) { get_introspection_data 'GLib', 'SOURCE_CONTINUE' } before do skip unless constant_info end it 'returns :gboolean as its type' do assert_equal :gboolean, constant_info.constant_type.tag end it 'returns true as its value' do assert_equal true, constant_info.value end end end gir_ffi-0.11.4/test/ffi-gobject_introspection/i_object_info_test.rb0000644000004100000410000000235413170036060025525 0ustar www-datawww-data# frozen_string_literal: true require 'introspection_test_helper' describe GObjectIntrospection::IObjectInfo do let(:object_info) { get_introspection_data('GObject', 'Object') } describe '#find_vfunc' do it 'finds a vfunc by name string' do object_info.find_vfunc('finalize').wont_be_nil end it 'finds a vfunc by name symbol' do object_info.find_vfunc(:finalize).wont_be_nil end end describe '#find_method' do it 'finds a method by name string' do object_info.find_method('bind_property').wont_be_nil end it 'finds a method by name symbol' do object_info.find_method(:bind_property).wont_be_nil end end describe '#find_property' do let(:object_info) { get_introspection_data('GObject', 'Binding') } it 'finds a property by name string' do object_info.find_property('source-property').wont_be_nil end it 'finds a property by snake case string' do object_info.find_property('source_property').wont_be_nil end it 'finds a property by name symbol' do object_info.find_property(:source).wont_be_nil end end describe '#type_name' do it 'returns the correct name' do object_info.type_name.must_equal 'GObject' end end end gir_ffi-0.11.4/test/ffi-gobject_introspection/i_function_info_test.rb0000644000004100000410000000017013170036060026076 0ustar www-datawww-data# frozen_string_literal: true require 'introspection_test_helper' describe GObjectIntrospection::IFunctionInfo do end gir_ffi-0.11.4/test/ffi-gobject_introspection/i_vfunc_info_test.rb0000644000004100000410000000214513170036060025376 0ustar www-datawww-data# frozen_string_literal: true require 'introspection_test_helper' describe GObjectIntrospection::IVFuncInfo do let(:vfunc_info) do get_vfunc_introspection_data 'GIMarshallingTests', 'Object', 'method_int8_in' end let(:throwing_vfunc_info) do get_vfunc_introspection_data 'GIMarshallingTests', 'Object', 'vfunc_meth_with_err' end let(:vfunc_info_with_different_invoker) do get_vfunc_introspection_data 'Regress', 'TestObj', 'matrix' end describe '#throws?' do it 'returns false if there is no error argument' do vfunc_info.wont_be :throws? end it 'returns true if there is and error argument' do throwing_vfunc_info.must_be :throws? end end describe '#invoker' do it 'returns nil if no invoker method is present' do throwing_vfunc_info.invoker.must_be_nil end it 'returns info for the invoker method if present' do vfunc_info.invoker.name.must_equal 'method_int8_in' end it 'returns the correct invoker even if named differently' do vfunc_info_with_different_invoker.invoker.name.must_equal 'do_matrix' end end end gir_ffi-0.11.4/test/ffi-gobject_introspection/i_property_info_test.rb0000644000004100000410000000241313170036060026137 0ustar www-datawww-data# frozen_string_literal: true require 'introspection_test_helper' describe GObjectIntrospection::IPropertyInfo do describe "for Regress::TestObj's 'double' property" do let(:property_info) { get_property_introspection_data 'Regress', 'TestObj', 'double' } it 'returns :gdouble as its type' do property_info.property_type.tag.must_equal :gdouble end it 'flags the property as readable' do property_info.readable?.must_equal true end it 'flags the property as writeable' do property_info.writeable?.must_equal true end it 'flags the property as not construct-only' do property_info.construct_only?.must_equal false end end describe "for GObject::Binding's 'target-property' property" do let(:property_info) do get_property_introspection_data 'GObject', 'Binding', 'target-property' end it 'returns :utf8 as its type' do property_info.property_type.tag.must_equal :utf8 end it 'flags the property as readable' do property_info.readable?.must_equal true end it 'flags the property as writeable' do property_info.writeable?.must_equal true end it 'flags the property as construct-only' do property_info.construct_only?.must_equal true end end end gir_ffi-0.11.4/test/ffi-gobject_introspection/gobject_type_init_test.rb0000644000004100000410000000142113170036060026427 0ustar www-datawww-data# frozen_string_literal: true require 'introspection_test_helper' describe GObjectIntrospection::GObjectTypeInit do describe 'Lib' do it 'represents the gobject-2.0 library' do GObjectIntrospection::GObjectTypeInit::Lib.ffi_libraries.first.name. must_match(/gobject-2\.0/) end it 'provides the g_type_init function' do GObjectIntrospection::GObjectTypeInit::Lib.must_respond_to :g_type_init end end describe '.type_init' do it 'calls the g_type_init function from the gobject-2.0 library' do allow(GObjectIntrospection::GObjectTypeInit::Lib).to receive(:g_type_init) GObjectIntrospection::GObjectTypeInit.type_init expect(GObjectIntrospection::GObjectTypeInit::Lib).to have_received(:g_type_init) end end end gir_ffi-0.11.4/test/introspection_test_helper.rb0000644000004100000410000000266413170036060022040 0ustar www-datawww-data# frozen_string_literal: true require 'base_test_helper' require 'ffi-gobject_introspection' GObjectIntrospection::IRepository.prepend_search_path File.join(File.dirname(__FILE__), 'lib') module LocalSharedLibrary def shared_library(namespace) case namespace when 'Everything', 'GIMarshallingTests', 'Regress', 'Utility', 'WarnLib' File.join(File.dirname(__FILE__), 'lib', "lib#{namespace.downcase}.so") else super end end end GObjectIntrospection::IRepository.prepend LocalSharedLibrary module IntrospectionTestExtensions module_function def get_introspection_data(namespace, name) gir = GObjectIntrospection::IRepository.default gir.require namespace, nil gir.find_by_name namespace, name end def get_field_introspection_data(namespace, klass, name) get_introspection_data(namespace, klass).find_field name end def get_method_introspection_data(namespace, klass, name) get_introspection_data(namespace, klass).find_method name end def get_property_introspection_data(namespace, klass, name) get_introspection_data(namespace, klass).find_property name end def get_signal_introspection_data(namespace, klass, name) get_introspection_data(namespace, klass).find_signal name end def get_vfunc_introspection_data(namespace, klass, name) get_introspection_data(namespace, klass).find_vfunc name end end Minitest::Test.send :include, IntrospectionTestExtensions gir_ffi-0.11.4/test/lib/0000755000004100000410000000000013170036060014753 5ustar www-datawww-datagir_ffi-0.11.4/test/lib/autogen.sh0000755000004100000410000000012213170036060016747 0ustar www-datawww-data#!/bin/sh # Run this to generate all the initial makefiles, etc. autoreconf -ivf gir_ffi-0.11.4/test/lib/Makefile.am0000644000004100000410000000732113170036060017012 0ustar www-datawww-dataACLOCAL_AMFLAGS = -I m4 AUTOMAKE_OPTIONS = 1.7 # We need to build a shared library, which can be dlopened # it does not work with noinst_LTLIBRARIES testlib_LTLIBRARIES = \ libeverything.la \ libgimarshallingtests.la libregress.la libutility.la libwarnlib.la testlibdir = $(prefix)/unused GI_TESTDIR = $(GI_DATADIR)/tests install-testlibLTLIBRARIES: # prevent it from being installed libeverything_la_SOURCES = $(GI_DATADIR)/tests/everything.c $(GI_DATADIR)/tests/everything.h libeverything_la_CFLAGS = $(GLIB_CFLAGS) libeverything_la_LDFLAGS = -module -avoid-version libgimarshallingtests_la_SOURCES = $(GI_DATADIR)/tests/gimarshallingtests.c $(GI_DATADIR)/tests/gimarshallingtests.h libgimarshallingtests_la_CFLAGS = $(GIO_CFLAGS) libgimarshallingtests_la_LDFLAGS = -module -avoid-version libregress_la_SOURCES = $(GI_TESTDIR)/regress.c $(GI_TESTDIR)/regress.h if HAVE_EXTRA_TEST_FILES libregress_la_SOURCES += \ $(GI_TESTDIR)/annotation.c $(GI_TESTDIR)/annotation.h \ $(GI_TESTDIR)/foo.c $(GI_TESTDIR)/foo.h \ $(GI_TESTDIR)/drawable.c $(GI_TESTDIR)/drawable.h endif libregress_la_CFLAGS = $(GIO_CFLAGS) $(CAIRO_CFLAGS) libregress_la_LDFLAGS = -module -avoid-version $(GIO_LIBS) $(CAIRO_LIBS) if HAVE_EXTRA_TEST_FILES libutility_la_SOURCES = $(GI_DATADIR)/tests/utility.c $(GI_DATADIR)/tests/utility.h libutility_la_CFLAGS = $(GLIB_CFLAGS) libutility_la_LDFLAGS = -module -avoid-version libwarnlib_la_SOURCES = $(GI_DATADIR)/tests/warnlib.c $(GI_DATADIR)/tests/warnlib.h libwarnlib_la_CFLAGS = $(GIO_CFLAGS) libwarnlib_la_LDFLAGS = -module -avoid-version endif GIRS = Everything-1.0.gir GIMarshallingTests-1.0.gir Regress-1.0.gir Everything-1.0.gir: libeverything.la $(AM_V_GEN) g-ir-scanner --include=GLib-2.0 \ --namespace=$(@:-1.0.gir=) --nsversion=1.0 \ --warn-all --warn-error \ --library=$< --libtool="$(top_builddir)/libtool" \ --output $@ $(libeverything_la_SOURCES) Everything-1.0.typelib: Everything-1.0.gir $(AM_V_GEN) g-ir-compiler $< -o $@ GIMarshallingTests-1.0.gir: libgimarshallingtests.la $(AM_V_GEN) g-ir-scanner --include=Gio-2.0 \ --namespace=GIMarshallingTests --nsversion=1.0 \ --symbol-prefix=gi_marshalling_tests \ --warn-all --warn-error \ --library=libgimarshallingtests.la \ --libtool="$(top_builddir)/libtool" \ --output $@ \ $(libgimarshallingtests_la_SOURCES) GIMarshallingTests-1.0.typelib: GIMarshallingTests-1.0.gir $(AM_V_GEN) g-ir-compiler $< -o $@ regress_SCANNER_INCLUDES= --include=cairo-1.0 --include=Gio-2.0 Regress-1.0.gir: libregress.la $(AM_V_GEN) g-ir-scanner $(regress_SCANNER_INCLUDES) \ --namespace=Regress --nsversion=1.0 --pkg=cairo-gobject \ --warn-all --warn-error \ --library=libregress.la \ --libtool="$(top_builddir)/libtool" \ --output $@ \ $(libregress_la_SOURCES) Regress-1.0.typelib: Regress-1.0.gir $(AM_V_GEN) g-ir-compiler --includedir=. $< -o $@ if HAVE_EXTRA_TEST_FILES GIRS += Utility-1.0.gir WarnLib-1.0.gir Regress-1.0.gir: Utility-1.0.gir regress_SCANNER_INCLUDES += --include-uninstalled=Utility-1.0.gir Utility-1.0.gir: libutility.la $(AM_V_GEN) g-ir-scanner --include=GLib-2.0 --include=GObject-2.0 \ --namespace=$(@:-1.0.gir=) --nsversion=1.0 \ --warn-all --warn-error \ --library=$< --libtool="$(top_builddir)/libtool" \ --output $@ $(libutility_la_SOURCES) Utility-1.0.typelib: Utility-1.0.gir $(AM_V_GEN) g-ir-compiler $< -o $@ WarnLib-1.0.gir: libwarnlib.la $(AM_V_GEN) g-ir-scanner --include=Gio-2.0 \ --namespace=$(@:-1.0.gir=) --nsversion=1.0 \ --symbol-prefix=warnlib \ --warn-all \ --library=$< --libtool="$(top_builddir)/libtool" \ --output $@ $(libwarnlib_la_SOURCES) WarnLib-1.0.typelib: WarnLib-1.0.gir $(AM_V_GEN) g-ir-compiler $< -o $@ endif .la.so: test -L $@ || $(LN_S) .libs/$@ $@ all: $(testlib_LTLIBRARIES:.la=.so) $(GIRS:.gir=.typelib) gir_ffi-0.11.4/test/lib/configure.ac0000644000004100000410000000163113170036060017242 0ustar www-datawww-data# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) AC_INIT(dummy_test_lib, 0.0.1) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([1.7 foreign]) AM_MAINTAINER_MODE AM_CONFIG_HEADER([config.h]) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],) # Checks for programs. AC_PROG_CC AM_PROG_CC_C_O AC_PROG_LIBTOOL PKG_PROG_PKG_CONFIG if test "$GCC" = "yes"; then JH_ADD_CFLAG([-Wall]) JH_ADD_CFLAG([-fno-strict-aliasing]) fi PKG_CHECK_MODULES(GIO, [gio-2.0]) PKG_CHECK_MODULES(GLIB, [glib-2.0]) PKG_CHECK_MODULES(CAIRO, [cairo]) GI_DATADIR=$($PKG_CONFIG --variable=gidatadir gobject-introspection-1.0) AC_SUBST(GI_DATADIR) AC_CHECK_FILE($GI_DATADIR/tests/annotation.c, have_annotation=true, have_annotation=false) AM_CONDITIONAL(HAVE_EXTRA_TEST_FILES, test x$have_annotation = xtrue) AC_CONFIG_FILES([Makefile]) AC_OUTPUT gir_ffi-0.11.4/test/lib/m4/0000755000004100000410000000000013170036060015273 5ustar www-datawww-datagir_ffi-0.11.4/test/lib/m4/jhflags.m40000644000004100000410000000106113170036060017151 0ustar www-datawww-datadnl dnl JH_ADD_CFLAG(FLAG) dnl checks whether the C compiler supports the given flag, and if so, adds dnl it to $CFLAGS. If the flag is already present in the list, then the dnl check is not performed. AC_DEFUN([JH_ADD_CFLAG], [ case " $CFLAGS " in *@<:@\ \ @:>@$1@<:@\ \ @:>@*) ;; *) save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $1" AC_MSG_CHECKING([whether [$]CC understands $1]) AC_TRY_COMPILE([], [], [jh_has_option=yes], [jh_has_option=no]) AC_MSG_RESULT($jh_has_option) if test $jh_has_option = no; then CFLAGS="$save_CFLAGS" fi ;; esac]) gir_ffi-0.11.4/test/ffi-gobject/0000755000004100000410000000000013170036060016364 5ustar www-datawww-datagir_ffi-0.11.4/test/ffi-gobject/object_class_test.rb0000644000004100000410000000165613170036060022413 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' require 'ffi-gobject' describe GObject::ObjectClass do describe '#list_properties' do it "returns GIMarshallingTests::OverridesObject's properties" do obj = GIMarshallingTests::OverridesObject.new object_class = GObject.object_class_from_instance obj info = get_introspection_data 'GIMarshallingTests', 'OverridesObject' expected_props = info.properties.map(&:name) expected_props += info.parent.properties.map(&:name) props = object_class.list_properties prop_names = props.map(&:get_name) prop_names.sort.must_equal expected_props.sort end end describe '#gtype' do it 'returns the correct GType' do obj = GIMarshallingTests::OverridesObject.new object_class = GObject.object_class_from_instance obj object_class.gtype.must_equal GIMarshallingTests::OverridesObject.gtype end end end gir_ffi-0.11.4/test/ffi-gobject/object_test.rb0000644000004100000410000000735413170036060021227 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' require 'ffi-gobject' GirFFI.setup :GIMarshallingTests describe GObject::Object do describe '.new' do it 'is overridden to take only one argument' do GObject::Object.new({}).must_be_instance_of GObject::Object end it 'can be used to create objects with properties' do obj = GIMarshallingTests::SubObject.new(int: 13) obj.int.must_equal 13 end it 'allows omission of the first argument' do GObject::Object.new.must_be_instance_of GObject::Object end it 'raises an error for properties that do not exist' do proc { GObject::Object.new(dog: 'bark') }.must_raise GirFFI::PropertyNotFoundError end end describe '#get_property' do it 'is overridden to have arity 1' do GObject::Object.instance_method('get_property').arity.must_equal 1 end it 'raises an error for a property that does not exist' do instance = GObject::Object.new proc { instance.get_property 'foo-bar' }.must_raise GirFFI::PropertyNotFoundError end end describe '#get_property_extended' do it 'raises an error for a property that does not exist' do instance = GObject::Object.new proc { instance.get_property_extended 'foo-bar' }. must_raise GirFFI::PropertyNotFoundError end end describe '#set_property' do it 'raises an error for a property that does not exist' do instance = GObject::Object.new proc { instance.set_property 'foo-bar', 123 }.must_raise GirFFI::PropertyNotFoundError end end describe '#set_property_extended' do it 'raises an error for a property that does not exist' do instance = GObject::Object.new proc { instance.set_property_extended 'foo-bar', 123 }. must_raise GirFFI::PropertyNotFoundError end end describe 'automatic accessor methods' do class AccessorTest < GObject::Object def get_x @x end def set_x(val) @x = val end end subject { AccessorTest.new } it 'reads x by calling get_x' do subject.set_x(1) assert_equal 1, subject.x end it 'writes x by calling set_x' do subject.x = 2 assert_equal 2, subject.x end end describe '#signal_connect' do subject { GObject::Object.new } it 'delegates to GObject' do expect(GObject).to receive(:signal_connect).with(subject, 'some-event', nil) subject.signal_connect('some-event') do nothing end end it 'delegates to GObject if an optional data argument is passed' do expect(GObject).to receive(:signal_connect).with(subject, 'some-event', 'data') subject.signal_connect('some-event', 'data') do nothing end end end describe '#signal_connect_after' do subject { GObject::Object.new } it 'delegates to GObject' do expect(GObject).to receive(:signal_connect_after).with(subject, 'some-event', nil) subject.signal_connect_after('some-event') do nothing end end it 'delegates to GObject if an optional data argument is passed' do expect(GObject).to receive(:signal_connect_after).with(subject, 'some-event', 'data') subject.signal_connect_after('some-event', 'data') do nothing end end end describe 'upon garbage collection' do it 'lowers the reference count' do if jruby? || rubinius? skip 'cannot be reliably tested on JRuby and Rubinius' end ptr = GObject::Object.new.to_ptr ref_count(ptr).must_equal 1 GC.start # Creating a new object is sometimes needed to trigger enough garbage collection. GObject::Object.new sleep 1 GC.start GC.start ref_count(ptr).must_equal 0 end end end gir_ffi-0.11.4/test/ffi-gobject/gobject_test.rb0000644000004100000410000000570413170036060021373 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' require 'ffi-gobject' GirFFI.setup :GIMarshallingTests describe GObject do describe '.type_init' do it 'does not raise an error' do GObject.type_init pass end end it 'has constants for the fundamental GTypes' do GObject::TYPE_INVALID.must_equal GObject.type_from_name('invalid') GObject.type_name(GObject::TYPE_INVALID).must_be_nil GObject.type_name(GObject::TYPE_NONE).must_equal 'void' GObject.type_name(GObject::TYPE_INTERFACE).must_equal 'GInterface' GObject.type_name(GObject::TYPE_CHAR).must_equal 'gchar' GObject.type_name(GObject::TYPE_UCHAR).must_equal 'guchar' GObject.type_name(GObject::TYPE_BOOLEAN).must_equal 'gboolean' GObject.type_name(GObject::TYPE_INT).must_equal 'gint' GObject.type_name(GObject::TYPE_UINT).must_equal 'guint' GObject.type_name(GObject::TYPE_LONG).must_equal 'glong' GObject.type_name(GObject::TYPE_ULONG).must_equal 'gulong' GObject.type_name(GObject::TYPE_INT64).must_equal 'gint64' GObject.type_name(GObject::TYPE_UINT64).must_equal 'guint64' GObject.type_name(GObject::TYPE_ENUM).must_equal 'GEnum' GObject.type_name(GObject::TYPE_FLAGS).must_equal 'GFlags' GObject.type_name(GObject::TYPE_FLOAT).must_equal 'gfloat' GObject.type_name(GObject::TYPE_DOUBLE).must_equal 'gdouble' GObject.type_name(GObject::TYPE_STRING).must_equal 'gchararray' GObject.type_name(GObject::TYPE_POINTER).must_equal 'gpointer' GObject.type_name(GObject::TYPE_BOXED).must_equal 'GBoxed' GObject.type_name(GObject::TYPE_PARAM).must_equal 'GParam' GObject.type_name(GObject::TYPE_OBJECT).must_equal 'GObject' GObject.type_name(GObject::TYPE_GTYPE).must_equal 'GType' GObject.type_name(GObject::TYPE_VARIANT).must_equal 'GVariant' GObject.type_name(GObject::TYPE_STRV).must_equal 'GStrv' GObject.type_name(GObject::TYPE_HASH_TABLE).must_equal 'GHashTable' end describe '::object_class_from_instance' do it 'returns a GObject::ObjectClass with the correct GType' do obj = GIMarshallingTests::OverridesObject.new object_class = GObject.object_class_from_instance obj gtype = object_class.g_type_class.g_type object_class.must_be_instance_of GObject::ObjectClass gtype.must_equal GIMarshallingTests::OverridesObject.gtype end end describe 'creating ParamSpecs' do describe '#param_spec_int' do it 'creates a GObject::ParamSpecInt' do spec = GObject.param_spec_int('foo', 'foo bar', 'The Foo Bar Property', 10, 20, 15, 3) spec.must_be_instance_of GObject::ParamSpecInt spec.minimum.must_equal 10 spec.maximum.must_equal 20 spec.default_value.must_equal 15 end end end end gir_ffi-0.11.4/test/ffi-gobject/value_test.rb0000644000004100000410000002405013170036060021065 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :Regress GirFFI.setup :Gio describe GObject::Value do describe '::Struct' do describe 'layout' do let(:layout) { GObject::Value::Struct.layout } it 'consists of :g_type and :data' do layout.members.must_equal [:g_type, :data] end it 'has an array as its second element' do types = layout.fields.map(&:type) types[1].class.must_equal FFI::Type::Array end end end describe '.for_gtype' do it 'handles char' do gv = GObject::Value.for_gtype GObject::TYPE_CHAR gv.current_gtype.must_equal GObject::TYPE_CHAR end it 'handles invalid type' do gv = GObject::Value.for_gtype GObject::TYPE_INVALID gv.current_gtype.must_equal GObject::TYPE_INVALID end it 'handles void type' do gv = GObject::Value.for_gtype GObject::TYPE_NONE gv.current_gtype.must_equal GObject::TYPE_INVALID end end describe '::wrap_ruby_value' do it 'wraps a boolean false' do gv = GObject::Value.wrap_ruby_value false assert_instance_of GObject::Value, gv gv.get_boolean.must_equal false end it 'wraps a boolean true' do gv = GObject::Value.wrap_ruby_value true assert_instance_of GObject::Value, gv gv.get_boolean.must_equal true end it 'wraps an Integer' do gv = GObject::Value.wrap_ruby_value 42 gv.get_int.must_equal 42 end it 'wraps a String' do gv = GObject::Value.wrap_ruby_value 'Some Random String' gv.get_string.must_equal 'Some Random String' end it 'wraps nil' do gv = GObject::Value.wrap_ruby_value nil assert_instance_of GObject::Value, gv gv.get_value.must_be_nil end it 'wraps object values' do value = GObject::Object.new({}) gv = GObject::Value.wrap_ruby_value value value.ref_count.must_equal 2 gv.get_value.must_equal value value.ref_count.must_equal 3 end end describe '#set_value' do it 'handles signed char values' do value = -83 gv = GObject::Value.for_gtype GObject::TYPE_CHAR gv.set_value value gv.get_schar.must_equal value end it 'handles unsigned char values' do value = 174 gv = GObject::Value.for_gtype GObject::TYPE_UCHAR gv.set_value value gv.get_uchar.must_equal value end it 'handles enum values presented as symbols' do value = :value2 gv = GObject::Value.for_gtype Regress::TestEnum.gtype gv.set_value value gv.get_value.must_equal value end it 'handles enum values presented as numbers' do value = :value2 gv = GObject::Value.for_gtype Regress::TestEnum.gtype gv.set_value Regress::TestEnum[value] gv.get_value.must_equal value end it 'handles GType values' do value = GObject::TYPE_STRING gv = GObject::Value.for_gtype GObject::TYPE_GTYPE gv.set_value value gv.get_gtype.must_equal value end it 'handles int64 values' do value = 0x1234_5678_9012_3456 gv = GObject::Value.for_gtype GObject::TYPE_INT64 gv.set_value value gv.get_int64.must_equal value end it 'handles long values' do value = FFI.type_size(:long) == 8 ? 0x1234_5678_9012_3456 : 0x1234_5678 gv = GObject::Value.for_gtype GObject::TYPE_LONG gv.set_value value gv.get_long.must_equal value end it 'handles uchar values' do value = 83 gv = GObject::Value.for_gtype GObject::TYPE_UCHAR gv.set_value value gv.get_uchar.must_equal value end it 'handles uint values' do value = 0x1234_5678 gv = GObject::Value.for_gtype GObject::TYPE_UINT gv.set_value value gv.get_uint.must_equal value end it 'handles uint64 values' do value = 0x1234_5678_9012_3456 gv = GObject::Value.for_gtype GObject::TYPE_UINT64 gv.set_value value gv.get_uint64.must_equal value end it 'handles ulong values' do value = FFI.type_size(:long) == 8 ? 0x1234_5678_9012_3456 : 0x1234_5678 gv = GObject::Value.for_gtype GObject::TYPE_ULONG gv.set_value value gv.get_ulong.must_equal value end it 'handles variant values' do value = GLib::Variant.new_string('Foo') gv = GObject::Value.for_gtype GObject::TYPE_VARIANT gv.set_value value gv.get_variant.must_equal value end it 'handles object values' do value = GObject::Object.new({}) gv = GObject::Value.for_gtype GObject::Object.gtype gv.set_value value gv.get_object.must_equal value end it 'handles interface values' do value = Gio.file_new_for_path('/') gv = GObject::Value.for_gtype Gio::File.gtype gv.set_value value gv.get_object.must_equal value end end describe '#get_value' do it 'unwraps a boolean false' do gv = GObject::Value.wrap_ruby_value false result = gv.get_value result.must_equal false end it 'unwraps a boolean true' do gv = GObject::Value.wrap_ruby_value true result = gv.get_value result.must_equal true end it 'unwraps a signed char' do value = -42 gv = GObject::Value.for_gtype GObject::TYPE_CHAR gv.set_schar value gv.get_value.must_equal value end it 'unwraps an unsigned char' do value = 173 gv = GObject::Value.for_gtype GObject::TYPE_UCHAR gv.set_uchar value gv.get_value.must_equal value end it 'unwraps an enum value' do value = :value2 gv = GObject::Value.for_gtype Regress::TestEnum.gtype gv.set_enum Regress::TestEnum[value] gv.get_value.must_equal value end it 'unwraps a flags value' do value = Regress::TestFlags[:flag1] | Regress::TestFlags[:flag3] gv = GObject::Value.for_gtype Regress::TestFlags.gtype gv.set_flags value gv.get_value.must_equal value end it 'unwraps a GType' do value = GObject::TYPE_STRING gv = GObject::Value.for_gtype GObject::TYPE_GTYPE gv.set_gtype value gv.get_value.must_equal value end it 'unwraps an int64' do value = 0x1234_5678_9012_3456 gv = GObject::Value.for_gtype GObject::TYPE_INT64 gv.set_int64 value gv.get_value.must_equal value end it 'unwraps a long' do value = FFI.type_size(:long) == 8 ? 0x1234_5678_9012_3456 : 0x1234_5678 gv = GObject::Value.for_gtype GObject::TYPE_LONG gv.set_long value gv.get_value.must_equal value end it 'unwraps an uchar' do value = 3 gv = GObject::Value.for_gtype GObject::TYPE_UCHAR gv.set_uchar value gv.get_value.must_equal value end it 'unwraps an uint' do value = 0x1234_5678 gv = GObject::Value.for_gtype GObject::TYPE_UINT gv.set_uint value gv.get_value.must_equal value end it 'unwraps an uint64' do value = 0x1234_5678_9012_3456 gv = GObject::Value.for_gtype GObject::TYPE_UINT64 gv.set_uint64 value gv.get_value.must_equal value end it 'unwraps an ulong' do value = FFI.type_size(:long) == 8 ? 0x1234_5678_9012_3456 : 0x1234_5678 gv = GObject::Value.for_gtype GObject::TYPE_ULONG gv.set_ulong value gv.get_value.must_equal value end it 'unwraps a variant' do value = GLib::Variant.new_string('Foo') gv = GObject::Value.for_gtype GObject::TYPE_VARIANT gv.set_variant value gv.get_value.must_equal value end it 'works with a ByteArray' do ba = GLib::ByteArray.new.append('some bytes') v = GObject::Value.for_gtype GObject::TYPE_BYTE_ARRAY v.set_boxed ba result = v.get_value result.to_string.must_equal 'some bytes' result.must_be_kind_of GLib::ByteArray end it 'works with an Array' do arr = GLib::Array.from(:uint, [1, 2, 3]) v = GObject::Value.for_gtype GObject::TYPE_ARRAY v.set_boxed arr result = v.get_value result.must_be_kind_of GLib::Array result.reset_typespec(:uint).to_a.must_equal [1, 2, 3] end it 'unwraps a Strv' do strv = GLib::Strv.from %w(foo bar) val = GObject::Value.for_gtype GObject::TYPE_STRV val.set_boxed strv result = val.get_value result.must_be_kind_of GLib::Strv result.to_a.must_equal %w(foo bar) end end describe '::from' do it 'creates a gint GValue from a Ruby Integer' do gv = GObject::Value.from 21 gv.current_gtype_name.must_equal 'gint' gv.get_value.must_equal 21 end it 'returns its argument if given a GValue' do gv = GObject::Value.from 21 gv2 = GObject::Value.from gv gv2.current_gtype_name.must_equal 'gint' gv2.get_value.must_equal 21 end it 'creates a null GValue from a Ruby nil' do gv = GObject::Value.from nil gv.current_gtype.must_equal GObject::TYPE_INVALID gv.get_value.must_be_nil end end describe '#set_value' do before do GirFFI.setup :GIMarshallingTests end it 'raises an error when setting an incompatible object type' do o = GIMarshallingTests::Object.new 1 v = GObject::Value.new.init(GIMarshallingTests::OverridesObject.gtype) proc { v.set_value o }.must_raise ArgumentError end it 'works with a ByteArray' do ba = GLib::ByteArray.new.append('some bytes') v = GObject::Value.new.init(GObject.type_from_name('GByteArray')) v.set_value ba v.get_value.to_string.must_equal 'some bytes' end end describe 'upon garbage collection' do it 'restores the underlying GValue to its pristine state' do if jruby? || rubinius? skip 'cannot be reliably tested on JRuby and Rubinius' end value = GObject::Value.from 42 # Drop reference to original GObject::Value value = GObject::Value.wrap value.to_ptr value.current_gtype_name.must_equal 'gint' GC.start # Creating a new object is sometimes needed to trigger enough garbage collection. GObject::Value.new sleep 1 GC.start GC.start value.current_gtype_name.wont_equal 'gint' end end end gir_ffi-0.11.4/test/ffi-gobject/param_spec_test.rb0000644000004100000410000000133013170036060022057 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' require 'ffi-gobject' describe GObject::ParamSpec do let(:pspec) do GObject.param_spec_int('foo-bar', 'foo bar', 'Foo Bar', 1, 3, 2, readable: true, writable: true) end describe '#ref' do it 'increases the ref count' do old = pspec.ref_count pspec.ref pspec.ref_count.must_equal old + 1 end end describe '#accessor_name' do it 'returns a safe ruby method name' do pspec.accessor_name.must_equal 'foo_bar' end end it 'cannot be instantiated directly' do proc { GObject::ParamSpec.new }.must_raise NoMethodError end end gir_ffi-0.11.4/test/gir_ffi/0000755000004100000410000000000013170036060015612 5ustar www-datawww-datagir_ffi-0.11.4/test/gir_ffi/version_test.rb0000644000004100000410000000030113170036060020655 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe 'GirFFI::VERSION' do it 'is set to a valid version number' do GirFFI::VERSION.must_match(/\d+\.\d+\.\d+/) end end gir_ffi-0.11.4/test/gir_ffi/method_stubber_test.rb0000644000004100000410000000336413170036060022212 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::MethodStubber do describe '#method_stub' do let(:stubber) { GirFFI::MethodStubber.new(method_info) } let(:result) { stubber.method_stub } describe 'for a regular method' do let(:method_info) do get_method_introspection_data('Regress', 'TestObj', 'instance_method') end it 'creates a method stub' do result.must_equal <<-STUB.reset_indentation def instance_method *args, &block setup_and_call "instance_method", args, &block end STUB end end describe 'for a static method' do let(:method_info) do get_method_introspection_data('Regress', 'TestObj', 'static_method') end it 'creates a class method stub' do result.must_equal <<-STUB.reset_indentation def self.static_method *args, &block setup_and_call "static_method", args, &block end STUB end end describe 'for a module function' do let(:method_info) do get_introspection_data('Regress', 'test_int') end it 'creates a module method stub' do result.must_equal <<-STUB.reset_indentation def self.test_int *args, &block setup_and_call "test_int", args, &block end STUB end end describe 'for a method with an empty name' do let(:method_info) { get_method_introspection_data('GLib', 'IConv', '') } it 'creates a method stub with a safe name that sets up the unsafe method' do result.must_equal <<-STUB.reset_indentation def _ *args, &block setup_and_call "", args, &block end STUB end end end end gir_ffi-0.11.4/test/gir_ffi/struct_like_base_test.rb0000644000004100000410000001211313170036060022516 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :GIMarshallingTests describe GirFFI::StructLikeBase do describe 'wrap_copy' do it 'returns a wrapped owned copy of structs' do original = GIMarshallingTests::SimpleStruct.new copy = GIMarshallingTests::SimpleStruct.wrap_copy(original.to_ptr) copy.to_ptr.wont_be :==, original.to_ptr copy.to_ptr.wont_be :autorelease? copy.struct.must_be :owned? end it 'returns a wrapped owned copy of unions' do original = GIMarshallingTests::Union.new copy = GIMarshallingTests::Union.wrap_copy(original.to_ptr) copy.to_ptr.wont_be :==, original.to_ptr copy.to_ptr.wont_be :autorelease? copy.struct.must_be :owned? end it 'returns a wrapped owned copy of boxed types' do original = GIMarshallingTests::BoxedStruct.new copy = GIMarshallingTests::BoxedStruct.wrap_copy(original.to_ptr) ptr = copy.to_ptr ptr.wont_be :==, original.to_ptr ptr.wont_be :autorelease? if ptr.respond_to? :autorelease copy.struct.must_be :owned? end it 'returns nil when passed nil' do GIMarshallingTests::SimpleStruct.wrap_copy(nil).must_be_nil end end describe 'copy_from' do it 'returns an unowned copy of unions' do original = GIMarshallingTests::Union.new original.long_ = 42 copy = GIMarshallingTests::Union.copy_from(original) copy.long_.must_equal 42 copy.to_ptr.wont_be :==, original.to_ptr copy.to_ptr.wont_be :autorelease? copy.struct.wont_be :owned? end it 'returns an unowned copy of structs' do original = GIMarshallingTests::SimpleStruct.new copy = GIMarshallingTests::SimpleStruct.copy_from(original) copy.to_ptr.wont_be :==, original.to_ptr copy.to_ptr.wont_be :autorelease? copy.struct.wont_be :owned? end it 'returns nil when passed nil' do GIMarshallingTests::SimpleStruct.copy_from(nil).must_be_nil end it 'converts its argument if that is possible' do GObject::Value.copy_from(4).must_be_instance_of GObject::Value end end describe 'wrap_own' do it 'wraps and owns the supplied pointer for structs' do original = GIMarshallingTests::SimpleStruct.new original.struct.owned = false copy = GIMarshallingTests::SimpleStruct.wrap_own(original.to_ptr) copy.to_ptr.must_equal original.to_ptr copy.to_ptr.wont_be :autorelease? copy.struct.must_be :owned? end it 'wraps and owns the supplied pointer for unions' do original = GIMarshallingTests::Union.new original.struct.owned = false copy = GIMarshallingTests::Union.wrap_own(original.to_ptr) copy.to_ptr.must_equal original.to_ptr copy.to_ptr.wont_be :autorelease? copy.struct.must_be :owned? end it 'returns nil when passed nil' do GIMarshallingTests::SimpleStruct.wrap_own(nil).must_be_nil end end describe '.native_type' do let(:type) { GIMarshallingTests::SimpleStruct.native_type } it 'is a struct by value' do type.must_be_instance_of FFI::StructByValue end it 'wraps the types nested struct class' do type.struct_class.must_equal GIMarshallingTests::SimpleStruct::Struct end end describe '.to_native' do it "returns the supplied value's struct" do object = GIMarshallingTests::SimpleStruct.new result = object.class.to_native(object, 'some-context') result.must_equal object.struct end end describe '.to_ffi_type' do it 'returns the class itself' do klass = GIMarshallingTests::SimpleStruct ffi_type = klass.to_ffi_type ffi_type.must_equal klass end end describe '.get_value_from_pointer' do let(:klass) { GIMarshallingTests::SimpleStruct } it 'returns just a pointer' do object = klass.new ptr = object.to_ptr result = klass.get_value_from_pointer(ptr, 0) result.must_be :==, ptr end it 'uses offset correctly' do struct1 = klass.new.tap { |it| it.long_ = 42 } struct2 = klass.new.tap { |it| it.long_ = 24 } array_ptr = GirFFI::InPointer.from_array(klass, [struct1, struct2]) ptr = klass.get_value_from_pointer(array_ptr, klass.size) result = klass.wrap(ptr) result.long_.must_equal 24 end end describe '.copy_value_to_pointer' do let(:klass) { GIMarshallingTests::SimpleStruct } let(:struct) { klass.new } it 'copies data correctly' do struct.long_ = 42 target = FFI::MemoryPointer.new klass.size klass.copy_value_to_pointer(struct, target) result = klass.wrap(target) result.long_.must_equal 42 end it 'uses offset correctly' do struct.long_ = 42 target = FFI::MemoryPointer.new klass.size + 10 klass.copy_value_to_pointer(struct, target, 10) result = klass.wrap(target + 10) result.long_.must_equal 42 end end it 'adds its class methods to classes that include it' do klass = Class.new klass.send :include, GirFFI::StructLikeBase klass.singleton_class.must_include GirFFI::StructLikeBase::ClassMethods end end gir_ffi-0.11.4/test/gir_ffi/type_map_test.rb0000644000004100000410000000076313170036060021022 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::TypeMap do describe '.type_specification_to_ffi_type' do it 'returns the nested FFI::Enum for an Enum module' do GirFFI::TypeMap.type_specification_to_ffi_type(GLib::DateMonth). must_equal GLib::DateMonth end it 'returns the class itself for a Struct class' do GirFFI::TypeMap.type_specification_to_ffi_type(GObject::EnumValue). must_equal GObject::EnumValue end end end gir_ffi-0.11.4/test/gir_ffi/unintrospectable_type_info_test.rb0000644000004100000410000000725213170036060024641 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' require 'gir_ffi/unintrospectable_type_info' describe GirFFI::UnintrospectableTypeInfo do describe '#info_type' do it 'returns :unintrospectable' do info = GirFFI::UnintrospectableTypeInfo.new :some_type info.info_type.must_equal :unintrospectable end end describe '#parent' do describe 'when the GIR knows about the parent gtype' do it "finds the parent's info by gtype" do gobject = Object.new gir = Object.new expect(gobject).to receive(:type_parent).with(:some_type).and_return :foo expect(gir).to receive(:find_by_gtype).with(:foo).and_return :foo_info info = GirFFI::UnintrospectableTypeInfo.new(:some_type, gir, gobject) info.parent.must_equal :foo_info end end describe 'when the GIR does not know about the parent gtype' do it 'creates a new UnintrospectableTypeInfo from the parent gtype' do gobject = Object.new gir = Object.new expect(gobject).to receive(:type_parent).with(:some_type).and_return :foo expect(gir).to receive(:find_by_gtype).with(:foo).and_return nil info = GirFFI::UnintrospectableTypeInfo.new(:some_type, gir, gobject) info.parent.g_type.must_equal :foo end end end describe '#interfaces' do it 'finds interface infos by gtype' do gobject = Object.new gir = Object.new expect(gobject).to receive(:type_interfaces).with(:some_type).and_return [:foo, :bar] expect(gir).to receive(:find_by_gtype).with(:foo).and_return :foo_info expect(gir).to receive(:find_by_gtype).with(:bar).and_return :bar_info info = GirFFI::UnintrospectableTypeInfo.new(:some_type, gir, gobject) info.interfaces.must_equal [:foo_info, :bar_info] end it 'skips interfaces that have no introspection data' do gobject = Object.new gir = Object.new expect(gobject).to receive(:type_interfaces).with(:some_type).and_return [:foo, :bar] expect(gir).to receive(:find_by_gtype).with(:foo).and_return :foo_info expect(gir).to receive(:find_by_gtype).with(:bar).and_return nil info = GirFFI::UnintrospectableTypeInfo.new(:some_type, gir, gobject) info.interfaces.must_equal [:foo_info] end end describe '#g_type' do it 'returns the passed-in gtype' do info = GirFFI::UnintrospectableTypeInfo.new(:some_type) info.g_type.must_equal :some_type end end describe '#fields' do it 'returns an empty array' do info = GirFFI::UnintrospectableTypeInfo.new(:some_type) info.fields.must_equal [] end end describe '#namespace' do it "returns the parent class' namespace" do gobject = Object.new gir = Object.new parent_info = Object.new expect(gobject).to receive(:type_parent).with(:some_type).and_return :foo expect(gir).to receive(:find_by_gtype).with(:foo).and_return parent_info expect(parent_info).to receive(:namespace).and_return 'FooNamespace' info = GirFFI::UnintrospectableTypeInfo.new(:some_type, gir, gobject) info.namespace.must_equal 'FooNamespace' end end describe '#safe_name' do it 'finds the class name by gtype' do gobject = Object.new expect(gobject).to receive(:type_name).with(:some_type).and_return 'GSomeType' info = GirFFI::UnintrospectableTypeInfo.new(:some_type, nil, gobject) info.safe_name.must_equal 'GSomeType' end end describe '#find_signal' do it 'indicates that no signals can be found' do info = GirFFI::UnintrospectableTypeInfo.new(:some_type) result = info.find_signal 'any' result.must_be_nil end end end gir_ffi-0.11.4/test/gir_ffi/class_base_test.rb0000644000004100000410000001205313170036060021276 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::ClassBase do describe 'a simple descendant' do let(:klass) do Class.new(GirFFI::ClassBase) do self::Struct = Class.new(GirFFI::Struct) do layout :foo, :int32 end end end let(:object) { klass.wrap FFI::MemoryPointer.new(:int32) } it 'has #from as a pass-through method' do result = klass.from :foo result.must_equal :foo end describe '#==' do it 'returns true when comparing to an object of the same class and pointer' do other = klass.wrap object.to_ptr object.must_be :==, other other.must_be :==, object end it 'returns true when comparing to an object of the same class and a pointer with the same address' do ptr = FFI::Pointer.new object.to_ptr other = klass.wrap ptr object.must_be :==, other other.must_be :==, object end it 'returns false when comparing to an object of a sub/superclass and the same pointer' do subclass = Class.new(klass) other = subclass.wrap object.to_ptr object.wont_be :==, other other.wont_be :==, object end it 'returns false when comparing to an object of the same class and different pointer' do other = klass.wrap FFI::MemoryPointer.new(:int32) object.wont_be :==, other other.wont_be :==, object end it "returns false when comparing to an object that doesn't respond to #to_ptr" do other = Object.new object.wont_be :==, other other.wont_be :==, object end it 'returns false when comparing to an object of a different class and same pointer' do allow(other = Object.new).to receive(:to_ptr).and_return object.to_ptr object.wont_be :==, other other.wont_be :==, object end it 'returns false when comparing to an object of a different class and different pointer' do allow(other = Object.new).to receive(:to_ptr).and_return FFI::MemoryPointer.new(:int32) object.wont_be :==, other other.wont_be :==, object end end end describe '.setup_and_call' do it 'looks up class methods in all builders' do expect(builder = Object.new).to receive(:setup_method).with('foo').and_return 'foo' klass = Class.new GirFFI::ClassBase klass.const_set :GIR_FFI_BUILDER, builder expect(sub_builder = Object.new).to receive(:setup_method).with('foo').and_return nil sub_klass = Class.new klass do def self.foo; end end sub_klass.const_set :GIR_FFI_BUILDER, sub_builder sub_klass.setup_and_call :foo, [] end it 'calls the method given by the result of .setup_method' do expect(builder = Object.new).to receive(:setup_method).with('foo').and_return 'bar' klass = Class.new GirFFI::ClassBase do def self.bar 'correct-result' end def initialize; end end klass.const_set :GIR_FFI_BUILDER, builder result = klass.setup_and_call :foo, [] result.must_equal 'correct-result' end it 'raises a sensible error if the method is not found' do expect(builder = Object.new).to receive(:setup_method).with('foo').and_return nil klass = Class.new GirFFI::ClassBase do def initialize; end end klass.const_set :GIR_FFI_BUILDER, builder proc { klass.setup_and_call :foo, [] }. must_raise(NoMethodError).message. must_match(/^undefined method `foo' for/) end end describe '#setup_and_call' do it 'looks up instance methods in all builders' do expect(builder = Object.new).to receive(:setup_instance_method).with('foo').and_return 'foo' klass = Class.new GirFFI::ClassBase klass.const_set :GIR_FFI_BUILDER, builder expect(sub_builder = Object.new).to receive(:setup_instance_method).with('foo').and_return nil sub_klass = Class.new klass do def foo; end def initialize; end end sub_klass.const_set :GIR_FFI_BUILDER, sub_builder obj = sub_klass.new obj.setup_and_call :foo, [] end it 'calls the method given by the result of .setup_instance_method' do expect(builder = Object.new).to receive(:setup_instance_method).with('foo').and_return 'bar' klass = Class.new GirFFI::ClassBase do def bar 'correct-result' end def initialize; end end klass.const_set :GIR_FFI_BUILDER, builder obj = klass.new result = obj.setup_and_call :foo, [] result.must_equal 'correct-result' end it 'raises a sensible error if the method is not found' do expect(builder = Object.new).to receive(:setup_instance_method).with('foo').and_return nil klass = Class.new GirFFI::ClassBase do def initialize; end end klass.const_set :GIR_FFI_BUILDER, builder obj = klass.new proc { obj.setup_and_call :foo, [] }. must_raise(NoMethodError).message. must_match(/^undefined method `foo' for/) end end end gir_ffi-0.11.4/test/gir_ffi/builder_test.rb0000644000004100000410000002177613170036060020641 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :Regress GirFFI.setup :GIMarshallingTests describe GirFFI::Builder do let(:gir) { GObjectIntrospection::IRepository.default } describe '.build_class' do it 'does not replace existing classes' do oldclass = GObject::Object GirFFI::Builder.build_class get_introspection_data('GObject', 'Object') GObject::Object.must_equal oldclass end end describe '.build_module' do it 'refuses to build existing modules defined elsewhere' do result = -> { GirFFI::Builder.build_module('Array') }.must_raise result.message.must_equal 'The module Array was already defined elsewhere' end describe 'building a module for the first time' do before do save_module :Regress GirFFI::Builder.build_module 'Regress' end it 'creates a Lib module ready to attach functions from the shared library' do gir = GObjectIntrospection::IRepository.default expected = [gir.shared_library('Regress')] assert_equal expected, Regress::Lib.ffi_libraries.map(&:name) end after do restore_module :Regress end end describe 'building a module that already exists' do it 'does not replace the existing module' do oldmodule = Regress GirFFI::Builder.build_module 'Regress' assert_equal oldmodule, Regress end it 'does not replace the existing Lib module' do oldmodule = Regress::Lib GirFFI::Builder.build_module 'Regress' assert_equal oldmodule, Regress::Lib end end it 'passes the version on to ModuleBuilder' do builder = double(generate: nil) expect(GirFFI::Builders::ModuleBuilder).to receive(:new). with('Foo', namespace: 'Foo', version: '1.0'). and_return builder GirFFI::Builder.build_module 'Foo', '1.0' end end describe '.build_by_gtype' do it 'returns the class types known to the GIR' do result = GirFFI::Builder.build_by_gtype GObject::Object.gtype result.must_equal GObject::Object end it 'returns the class for user-defined types' do klass = Class.new GIMarshallingTests::OverridesObject Object.const_set "Derived#{Sequence.next}", klass gtype = GirFFI.define_type klass found_klass = GirFFI::Builder.build_by_gtype gtype found_klass.must_equal klass end it 'returns a valid class for boxed classes unknown to GIR' do object_class = GIMarshallingTests::PropertiesObject.object_class property = object_class.find_property 'some-boxed-glist' gtype = property.value_type gtype.wont_equal GObject::TYPE_NONE found_klass = GirFFI::Builder.build_by_gtype gtype found_klass.name.must_be_nil found_klass.ancestors.must_include GirFFI::BoxedBase end end describe '.attach_ffi_function' do let(:lib) { Module.new } it 'calls attach_function with the correct types for Regress.test_callback_destroy_notify' do function_info = get_introspection_data 'Regress', 'test_callback_destroy_notify' expect(lib). to receive(:attach_function). with('regress_test_callback_destroy_notify', [Regress::TestCallbackUserData, :pointer, GLib::DestroyNotify], :int32). and_return true GirFFI::Builder.attach_ffi_function(lib, function_info) end it 'calls attach_function with the correct types for Regress::TestObj#torture_signature_0' do info = get_method_introspection_data 'Regress', 'TestObj', 'torture_signature_0' expect(lib). to receive(:attach_function). with('regress_test_obj_torture_signature_0', [:pointer, :int32, :pointer, :pointer, :pointer, :pointer, :uint32], :void). and_return true GirFFI::Builder.attach_ffi_function(lib, info) end it 'calls attach_function with the correct types for Regress::TestObj#instance_method' do info = get_method_introspection_data 'Regress', 'TestObj', 'instance_method' expect(lib).to receive(:attach_function). with('regress_test_obj_instance_method', [:pointer], :int32). and_return true GirFFI::Builder.attach_ffi_function(lib, info) end it 'calls attach_function with the correct types for Regress.test_array_gint32_in' do info = get_introspection_data 'Regress', 'test_array_gint32_in' expect(lib).to receive(:attach_function). with('regress_test_array_gint32_in', [:int32, :pointer], :int32). and_return true GirFFI::Builder.attach_ffi_function(lib, info) end it 'does not attach the function if it is already defined' do info = get_introspection_data 'Regress', 'test_array_gint32_in' allow(lib).to receive(:method_defined?).and_return true expect(lib).not_to receive(:attach_function) GirFFI::Builder.attach_ffi_function(lib, info) end end # # NOTE: Legacy tests below. # describe 'looking at Regress.test_callback_destroy_notify' do before do save_module :GObject save_module :Regress GirFFI::Builder.build_module 'GObject' GirFFI::Builder.build_module 'Regress' @go = get_introspection_data 'Regress', 'test_callback_destroy_notify' end it 'defines ffi callback types :Callback and :ClosureNotify' do Regress.setup_method 'test_callback_destroy_notify' tcud = Regress::Lib.find_type :TestCallbackUserData dn = GLib::Lib.find_type :DestroyNotify assert_equal FFI.find_type(:int32), tcud.result_type assert_equal FFI.find_type(:void), dn.result_type assert_equal [FFI.find_type(:pointer)], tcud.param_types assert_equal [FFI.find_type(:pointer)], dn.param_types end after do restore_module :Regress restore_module :GObject end end describe 'building Regress::TestBoxed' do before do GirFFI::Builder.build_class get_introspection_data('Regress', 'TestBoxed') end it 'sets up #wrap' do assert Regress::TestBoxed.respond_to? 'wrap' end it 'sets up #allocate' do assert Regress::TestBoxed.respond_to? 'allocate' end end describe 'built Regress module' do before do save_module :Regress GirFFI::Builder.build_module 'Regress' end it 'autocreates singleton methods' do refute_defines_singleton_method Regress, :test_uint Regress.test_uint 31 assert_defines_singleton_method Regress, :test_uint end it 'autocreates the TestObj class on first access' do assert !Regress.const_defined?(:TestObj) Regress::TestObj.must_be_instance_of Class assert Regress.const_defined? :TestObj end it 'knows its own module builder' do Regress.gir_ffi_builder.must_be_instance_of GirFFI::Builders::ModuleBuilder end after do restore_module :Regress end end describe 'having built Regress::TestObj' do before do GirFFI::Builder.build_class get_introspection_data('Regress', 'TestObj') end it 'C functions for called instance methods get attached to Regress::Lib' do o = Regress::TestObj.new_from_file('foo') o.instance_method Regress::Lib.must_respond_to :regress_test_obj_instance_method end it 'the built class knows its own GIR info' do Regress::TestObj.gir_info.name.must_equal 'TestObj' end it 'the built class knows its own class builder' do Regress::TestObj.gir_ffi_builder.must_be_instance_of GirFFI::Builders::ObjectBuilder end end describe 'built Regress::TestSubObj' do it 'inherits #set_bare from its superclass' do o1 = Regress::TestSubObj.new o1.set_bare(nil) pass end it 'overrides #instance_method' do obj = Regress::TestObj.new_from_file('foo') subobj = Regress::TestSubObj.new obj.instance_method.must_equal(-1) subobj.instance_method.must_equal 0 end end describe 'building Regress::TestSubObj' do before do save_module :Regress GirFFI::Builder.build_class get_introspection_data('Regress', 'TestSubObj') end it 'sets up the Regress namespace' do assert Regress.const_defined? :Lib assert Regress.respond_to? :gir_ffi_builder assert Regress.const_defined? :GIR_FFI_BUILDER end it 'creates the Regress::Lib module ready to attach functions from the shared library' do expected = [gir.shared_library('Regress')] assert_equal expected, Regress::Lib.ffi_libraries.map(&:name) end it 'builds parent classes also' do assert Regress.const_defined? :TestObj assert Object.const_defined? :GObject assert GObject.const_defined? :Object end it 'sets up the inheritance chain' do ancestors = Regress::TestSubObj.ancestors assert_equal [ Regress::TestSubObj, Regress::TestObj, GObject::Object ], ancestors[0..2] end it 'creates a Regress::TestSubObj#to_ptr method' do assert Regress::TestSubObj.public_method_defined? :to_ptr end after do restore_module :Regress end end end gir_ffi-0.11.4/test/gir_ffi/arg_helper_test.rb0000644000004100000410000001114513170036060021310 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::ArgHelper do describe '.cast_from_pointer' do it 'handles class types' do klass = Class.new expect(klass).to receive(:wrap).with(:pointer_value).and_return :wrapped_value GirFFI::ArgHelper.cast_from_pointer(klass, :pointer_value).must_equal :wrapped_value end describe 'for :gint8' do it 'handles negative :gint8' do ptr = FFI::Pointer.new(-127) GirFFI::ArgHelper.cast_from_pointer(:gint8, ptr).must_equal(-127) end it 'handles positive :gint8' do ptr = FFI::Pointer.new(128) GirFFI::ArgHelper.cast_from_pointer(:gint8, ptr).must_equal(128) end end it 'handles :guint32' do ptr = FFI::Pointer.new(0xffffffff) GirFFI::ArgHelper.cast_from_pointer(:guint32, ptr).must_equal(0xffffffff) end describe 'for :gint32' do it 'handles positive :gint32' do ptr = FFI::Pointer.new(1) GirFFI::ArgHelper.cast_from_pointer(:gint32, ptr).must_equal(1) end it 'handles negative :gint32' do ptr = FFI::Pointer.new(0xffffffff) GirFFI::ArgHelper.cast_from_pointer(:gint32, ptr).must_equal(-1) end it 'handles largest negative :gint32' do ptr = FFI::Pointer.new(0x80000000) GirFFI::ArgHelper.cast_from_pointer(:gint32, ptr).must_equal(-0x80000000) end it 'handles largest positive :gint32' do ptr = FFI::Pointer.new(0x7fffffff) GirFFI::ArgHelper.cast_from_pointer(:gint32, ptr).must_equal(0x7fffffff) end end it 'handles :utf8' do ptr = FFI::MemoryPointer.from_string 'foo' GirFFI::ArgHelper.cast_from_pointer(:utf8, ptr).must_equal 'foo' end it 'handles :filename' do ptr = FFI::MemoryPointer.from_string 'foo' GirFFI::ArgHelper.cast_from_pointer(:filename, ptr).must_equal 'foo' end it 'handles GHashTable' do hash = GLib::HashTable.from [:utf8, :gint32], 'foo' => 1, 'bar' => 2 ptr = hash.to_ptr result = GirFFI::ArgHelper.cast_from_pointer([:pointer, [:ghash, :utf8, :gint32]], ptr) result.to_hash.must_equal hash.to_hash end describe 'when passing a broken typespec' do it 'raises on unknown symbol' do ptr = FFI::Pointer.new(0xffffffff) exception = -> { GirFFI::ArgHelper.cast_from_pointer(:foo, ptr) }.must_raise exception.message.must_equal "Don't know how to cast foo" end it 'raises on unexpected main type for complex type' do ptr = FFI::Pointer.new(0xffffffff) exception = -> { GirFFI::ArgHelper.cast_from_pointer([:utf8], ptr) }.must_raise exception.message.must_equal "Don't know how to cast [:utf8]" end it 'raises on unexpected sub type for complex type' do ptr = FFI::Pointer.new(0xffffffff) exception = -> { GirFFI::ArgHelper.cast_from_pointer([:pointer, :utf8], ptr) }.must_raise exception.message.must_equal "Don't know how to cast [:pointer, :utf8]" end it 'raises on unexpected container type for complex type' do ptr = FFI::Pointer.new(0xffffffff) exception = -> { GirFFI::ArgHelper.cast_from_pointer([:pointer, [:gint32]], ptr) }.must_raise exception.message.must_equal "Don't know how to cast [:pointer, [:gint32]]" end end end describe '.store' do describe 'when called with nil' do it 'returns a null pointer' do GirFFI::ArgHelper.store(nil).must_be :null? end end describe 'when called with a string' do it 'stores the string in GirFFI::ArgHelper::OBJECT_STORE' do str = 'Foo' ptr = GirFFI::ArgHelper.store(str) result = GirFFI::ArgHelper::OBJECT_STORE.fetch(ptr) result.must_equal str end end end describe '.check_fixed_array_size' do it 'passes if array has the correct size' do GirFFI::ArgHelper.check_fixed_array_size(3, [1, 2, 3], 'foo') pass end it 'raises if array does not have the correct size' do result = lambda do GirFFI::ArgHelper.check_fixed_array_size(3, [1, 2], 'foo') end.must_raise ArgumentError result.message.must_equal 'foo should have size 3' end end describe '.check_error' do it 'does nothing if there is no error' do err_ptr = double('err_ptr', read_pointer: nil) GirFFI::ArgHelper.check_error err_ptr pass end it 'raises an exception if there is an error' do err = GLib::Error.new err_ptr = double('err_ptr', read_pointer: err.to_ptr) -> { GirFFI::ArgHelper.check_error err_ptr }.must_raise GirFFI::GLibError end end end gir_ffi-0.11.4/test/gir_ffi/user_defined_property_info_test.rb0000644000004100000410000000170613170036060024615 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' require 'gir_ffi/user_defined_property_info' describe GirFFI::UserDefinedPropertyInfo do let(:pspec) do GObject.param_spec_int('foo-bar', 'foo bar', 'Foo Bar', 1, 3, 2, readable: true, writable: true) end let(:info) { GirFFI::UserDefinedPropertyInfo.new pspec } describe '#param_spec' do it 'returns the passed in parameter specification' do info.param_spec.must_equal pspec end end describe '#name' do it 'returns the name retrieved from the parameter specification' do info.name.must_equal 'foo-bar' end end describe '#ffi_type' do it 'returns the ffi type corresponding to the type tag' do info.ffi_type.must_equal :int end end describe '#type_tag' do it 'returns the mapped type symbol' do info.type_tag.must_equal :gint end end end gir_ffi-0.11.4/test/gir_ffi/boxed_base_test.rb0000644000004100000410000000407113170036060021273 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :GIMarshallingTests describe GirFFI::BoxedBase do describe 'initialize' do it 'sets up the held struct pointer' do # NOTE: GObject::Value uses the generic constructor, unlike # GIMarshallingTests::BoxedStruct, which has its own constructor. value = GObject::Value.new value.to_ptr.wont_be_nil end end describe 'copy_from' do it 'returns a copy with owned false' do original = GIMarshallingTests::BoxedStruct.new copy = GIMarshallingTests::BoxedStruct.copy_from(original) ptr = copy.to_ptr ptr.wont_be :==, original.to_ptr ptr.wont_be :autorelease? if ptr.respond_to? :autorelease? copy.struct.wont_be :owned? end end describe 'wrap_own' do it 'wraps and owns the supplied pointer' do original = GIMarshallingTests::BoxedStruct.new copy = GIMarshallingTests::BoxedStruct.wrap_own(original.to_ptr) ptr = copy.to_ptr ptr.must_equal original.to_ptr ptr.wont_be :autorelease? if ptr.respond_to? :autorelease? copy.struct.must_be :owned? end end describe 'upon garbage collection' do it 'frees and disowns the underlying struct if it is owned' do if jruby? || rubinius? skip 'cannot be reliably tested on JRuby and Rubinius' end allow(GObject).to receive(:boxed_free) gtype = GIMarshallingTests::BoxedStruct.gtype owned_struct = GIMarshallingTests::BoxedStruct.new.struct owned_ptr = owned_struct.to_ptr unowned_struct = GIMarshallingTests::BoxedStruct.new.struct unowned_struct.owned = false unowned_ptr = unowned_struct.to_ptr GC.start # Creating a new object is sometimes needed to trigger enough garbage collection. GIMarshallingTests::BoxedStruct.new sleep 1 GC.start GC.start expect(GObject).to have_received(:boxed_free).with(gtype, owned_ptr) expect(GObject).not_to have_received(:boxed_free).with(gtype, unowned_ptr) owned_struct.wont_be :owned? end end end gir_ffi-0.11.4/test/gir_ffi/allocation_helper_test.rb0000644000004100000410000000175313170036060022670 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::AllocationHelper do describe '.free_after' do before do allow(GirFFI::LibC).to receive(:free) end it 'frees the passed-in pointer' do ptr = double('pointer', null?: false) GirFFI::AllocationHelper.free_after(ptr) {} expect(GirFFI::LibC).to have_received(:free).with(ptr) end it 'does not free a passed-in null pointer' do ptr = double('pointer', null?: true) GirFFI::AllocationHelper.free_after(ptr) {} expect(GirFFI::LibC).not_to have_received(:free) end it 'yields ptr to the block' do ptr = double('pointer', null?: false) foo = nil GirFFI::AllocationHelper.free_after(ptr) { |it| foo = it } foo.must_equal ptr end it 'returns the result of the block' do ptr = double('pointer', null?: false) result = GirFFI::AllocationHelper.free_after(ptr) { 'bar' } result.must_equal 'bar' end end end gir_ffi-0.11.4/test/gir_ffi/boolean_test.rb0000644000004100000410000000203713170036060020617 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Boolean do it 'has the same native size as an int' do FFI.type_size(GirFFI::Boolean).must_equal FFI.type_size :int end describe '.from_native' do it 'converts 0 to false' do GirFFI::Boolean.from_native(0, 'whatever').must_equal false end it 'converts 1 to true' do GirFFI::Boolean.from_native(1, 'whatever').must_equal true end end describe '.to_native' do it 'converts false to 0' do GirFFI::Boolean.to_native(false, 'whatever').must_equal 0 end it 'converts true to 1' do GirFFI::Boolean.to_native(true, 'whatever').must_equal 1 end it 'converts nil to 0' do GirFFI::Boolean.to_native(nil, 'whatever').must_equal 0 end it 'converts truthy value to 1' do GirFFI::Boolean.to_native('i am truth!', 'whatever').must_equal 1 end end describe '.size' do it 'returns the correct type size' do GirFFI::Boolean.size.must_equal FFI.type_size :int end end end gir_ffi-0.11.4/test/gir_ffi/sized_array_test.rb0000644000004100000410000001565013170036060021521 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::SizedArray do describe '::wrap' do it 'takes a type, size and pointer and returns a GirFFI::SizedArray wrapping them' do expect(ptr = Object.new).to receive(:null?).and_return false sarr = GirFFI::SizedArray.wrap :gint32, 3, ptr assert_instance_of GirFFI::SizedArray, sarr assert_equal ptr, sarr.to_ptr assert_equal 3, sarr.size assert_equal :gint32, sarr.element_type end it 'returns nil if the wrapped pointer is null' do expect(ptr = Object.new).to receive(:null?).and_return true sarr = GirFFI::SizedArray.wrap :gint32, 3, ptr sarr.must_be_nil end end describe '#each' do it 'yields each element' do ary = %w(one two three) ptrs = ary.map { |a| FFI::MemoryPointer.from_string(a) } ptrs << nil block = FFI::MemoryPointer.new(:pointer, ptrs.length) block.write_array_of_pointer ptrs sarr = GirFFI::SizedArray.new :utf8, 3, block arr = [] sarr.each do |str| arr << str end assert_equal %w(one two three), arr end end describe '::from' do describe 'from a Ruby array' do it 'creates a GirFFI::SizedArray with the same elements' do arr = GirFFI::SizedArray.from :gint32, 3, [3, 2, 1] arr.must_be_instance_of GirFFI::SizedArray assert_equal [3, 2, 1], arr.to_a end it 'raises an error if the array has the wrong number of elements' do proc { GirFFI::SizedArray.from :gint32, 4, [3, 2, 1] }.must_raise ArgumentError end it "uses the array's size if passed -1 as the size" do arr = GirFFI::SizedArray.from :gint32, -1, [3, 2, 1] arr.size.must_equal 3 end end describe 'from a GirFFI::SizedArray' do it 'return its argument' do arr = GirFFI::SizedArray.from :gint32, 3, [3, 2, 1] arr2 = GirFFI::SizedArray.from :gint32, 3, arr assert_equal arr, arr2 end it 'raises an error if the argument has the wrong number of elements' do arr = GirFFI::SizedArray.from :gint32, 3, [3, 2, 1] proc { GirFFI::SizedArray.from :gint32, 4, arr }.must_raise ArgumentError end end it 'returns nil when passed nil' do arr = GirFFI::SizedArray.from :gint32, 0, nil arr.must_be_nil end it 'wraps its argument if given a pointer' do arr = GirFFI::SizedArray.from :gint32, 3, [3, 2, 1] arr2 = GirFFI::SizedArray.from :gint32, 3, arr.to_ptr assert_instance_of GirFFI::SizedArray, arr2 refute arr2.equal? arr arr2.to_ptr.must_equal arr.to_ptr end end describe '.copy_from' do describe 'from a Ruby array' do it 'creates an unowned GirFFI::SizedArray with the same elements' do arr = GirFFI::SizedArray.copy_from :gint32, 3, [3, 2, 1] arr.must_be_instance_of GirFFI::SizedArray assert_equal [3, 2, 1], arr.to_a arr.to_ptr.wont_be :autorelease? end it 'creates unowned copies of struct pointer elements' do struct = GIMarshallingTests::BoxedStruct.new struct.long_ = 2342 struct.struct.must_be :owned? arr = GirFFI::SizedArray.copy_from([:pointer, GIMarshallingTests::BoxedStruct], 1, [struct]) arr.must_be_instance_of GirFFI::SizedArray arr.to_ptr.wont_be :autorelease? struct_copy = arr.first struct_copy.long_.must_equal struct.long_ struct_copy.to_ptr.wont_be :==, struct.to_ptr struct_copy.struct.wont_be :owned? end it 'increases the ref count of object pointer elements' do obj = GIMarshallingTests::Object.new 42 arr = GirFFI::SizedArray.copy_from([:pointer, GIMarshallingTests::Object], -1, [obj, nil]) arr.must_be_instance_of GirFFI::SizedArray arr.to_ptr.wont_be :autorelease? arr.to_a.must_equal [obj, nil] obj.ref_count.must_equal 2 end end describe 'from a GirFFI::SizedArray' do it 'return an unowned copy of its argument' do arr = GirFFI::SizedArray.from :gint32, 3, [3, 2, 1] arr2 = GirFFI::SizedArray.copy_from :gint32, 3, arr arr.to_ptr.wont_be :==, arr2.to_ptr arr2.to_a.must_equal [3, 2, 1] arr2.to_ptr.wont_be :autorelease? end end it 'returns nil when passed nil' do arr = GirFFI::SizedArray.copy_from :gint32, 0, nil arr.must_be_nil end it 'creates an unowned copy of its argument if given a pointer' do arr = GirFFI::SizedArray.from :gint32, 3, [3, 2, 1] arr2 = GirFFI::SizedArray.copy_from :gint32, 3, arr.to_ptr assert_instance_of GirFFI::SizedArray, arr2 arr2.to_ptr.wont_be :==, arr.to_ptr arr2.to_ptr.wont_be :autorelease? arr2.to_a.must_equal [3, 2, 1] end end describe '#==' do it 'returns true when comparing to an array with the same elements' do sized = GirFFI::SizedArray.from :int32, 3, [1, 2, 3] sized.must_be :==, [1, 2, 3] end it 'returns false when comparing to an array with different elements' do sized = GirFFI::SizedArray.from :int32, 3, [1, 2, 3] sized.wont_be :==, [1, 2] end it 'returns true when comparing to a sized array with the same elements' do sized = GirFFI::SizedArray.from :int32, 3, [1, 2, 3] other = GirFFI::SizedArray.from :int32, 3, [1, 2, 3] sized.must_be :==, other end it 'returns false when comparing to a sized array with different elements' do sized = GirFFI::SizedArray.from :int32, 3, [1, 2, 3] other = GirFFI::SizedArray.from :int32, 2, [1, 2] sized.wont_be :==, other end end describe '#size_in_bytes' do it 'returns the correct value' do sized = GirFFI::SizedArray.from :int32, 3, [1, 2, 3] sized.size_in_bytes.must_equal 12 end end describe '.get_value_from_pointer' do it 'returns just a pointer' do sized = GirFFI::SizedArray.from :int32, 3, [1, 2, 3] ptr = sized.to_ptr result = GirFFI::SizedArray.get_value_from_pointer(ptr, 0) result.must_be :==, ptr end it 'offsets correctly' do sized = GirFFI::SizedArray.from :int32, 3, [1, 2, 3] ptr = sized.to_ptr next_ptr = GirFFI::SizedArray.get_value_from_pointer(ptr, 4) tail = GirFFI::SizedArray.from(:int32, 2, next_ptr) tail.must_be :==, [2, 3] end end describe '.copy_value_to_pointer' do it 'copies data correctly' do sized = GirFFI::SizedArray.from :int32, 3, [1, 2, 3] target = FFI::MemoryPointer.new sized.size_in_bytes GirFFI::SizedArray.copy_value_to_pointer(sized, target) result = GirFFI::SizedArray.from :int32, 3, target result.must_be :==, [1, 2, 3] end end it 'includes Enumerable' do GirFFI::SizedArray.must_include Enumerable end end gir_ffi-0.11.4/test/gir_ffi/in_out_pointer_test.rb0000644000004100000410000000314113170036060022232 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::InOutPointer do describe '.new' do it 'wraps an existing pointer and a type' do ptr = FFI::MemoryPointer.new(:int32) ptr.put_int32 0, 42 instance = GirFFI::InOutPointer.new :gint32, ptr instance.to_value.must_equal 42 end end describe '#to_value' do it 'returns the held value' do ptr = GirFFI::InOutPointer.allocate_new :gint32 ptr.put_int32 0, 123 assert_equal 123, ptr.to_value end describe 'for :gboolean values' do it 'works when the value is false' do ptr = GirFFI::InOutPointer.allocate_new :gboolean ptr.put_int 0, 0 ptr.to_value.must_equal false end it 'works when the value is true' do ptr = GirFFI::InOutPointer.allocate_new :gboolean ptr.put_int 0, 1 ptr.to_value.must_equal true end end describe 'for :utf8 values' do it 'returns a pointer to the held string value' do str_ptr = GirFFI::InPointer.from_utf8 'Some value' ptr = GirFFI::InOutPointer.allocate_new :utf8 ptr.put_pointer 0, str_ptr assert_equal 'Some value', ptr.to_value.read_string end end describe 'for struct values' do it 'returns a pointer to the held value' do val = GObject::EnumValue.new val.value = 3 ptr = GirFFI::InOutPointer.allocate_new GObject::EnumValue GObject::EnumValue.copy_value_to_pointer val, ptr result = ptr.to_value GObject::EnumValue.wrap(result).value.must_equal 3 end end end end gir_ffi-0.11.4/test/gir_ffi/object_base_test.rb0000644000004100000410000000154613170036060021444 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :Regress describe GirFFI::ObjectBase do let(:derived_class) { Class.new GirFFI::ObjectBase } describe '.wrap' do it 'delegates conversion to the wrapped pointer' do expect(ptr = Object.new).to receive(:to_object).and_return 'good-result' derived_class.wrap(ptr).must_equal 'good-result' end end describe '.to_ffi_type' do it 'returns itself' do derived_class.to_ffi_type.must_equal derived_class end end describe '.object_class' do it 'returns an object of the class struct type' do Regress::TestObj.object_class.must_be_instance_of Regress::TestObjClass end it 'caches its result' do first = Regress::TestObj.object_class second = Regress::TestObj.object_class second.must_be :eql?, first end end end gir_ffi-0.11.4/test/gir_ffi/struct_base_test.rb0000644000004100000410000000110613170036060021512 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :GIMarshallingTests describe GirFFI::StructBase do it 'inherits from StructLikeBase' do GirFFI::StructBase.must_include GirFFI::StructLikeBase end describe 'new' do it 'creates an instance with an owned struct' do instance = GIMarshallingTests::SimpleStruct.new instance.struct.must_be :owned? end it 'ensures the wrapped pointer is not autoreleased' do instance = GIMarshallingTests::SimpleStruct.new instance.to_ptr.wont_be :autorelease? end end end gir_ffi-0.11.4/test/gir_ffi/in_pointer_test.rb0000644000004100000410000001144013170036060021344 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' require 'gir_ffi/in_pointer' describe GirFFI::InPointer do describe '.from_array' do it 'returns nil when passed nil' do result = GirFFI::InPointer.from_array :gint32, nil assert_nil result end it 'handles type tag :GType' do GirFFI::InPointer.from_array :GType, [2] end it 'handles enum types' do e = Module.new do extend GirFFI::EnumBase self::Enum = FFI::Enum.new [:foo, :bar, :baz], :qux end ptr = GirFFI::InPointer.from_array e, [:bar, :foo, :baz] ptr.read_array_of_int32(3).must_equal [1, 0, 2] end it 'handles struct types' do e = Class.new(GirFFI::StructBase) do self::Struct = Class.new(GirFFI::Struct) do layout :foo, :int32, :bar, :int32 end end struct = e::Struct.allocate struct[:foo] = 42 struct[:bar] = 24 ptr = GirFFI::InPointer.from_array e, [struct] ptr.wont_be :==, struct.to_ptr new_struct = e::Struct.new ptr new_struct[:foo].must_equal 42 new_struct[:bar].must_equal 24 end it 'handles typed pointers' do p1 = GirFFI::InPointer.from :gint32, 42 p2 = GirFFI::InPointer.from :gint32, 24 ptr = GirFFI::InPointer.from_array [:pointer, :gint32], [p1, p2] ptr.read_array_of_pointer(2).must_equal [p1, p2] end it 'handles pointer casting' do ptr = GirFFI::InPointer.from_array [:pointer, :gint32], [42, 24] ptr.read_array_of_pointer(2).map(&:address).must_equal [42, 24] end end describe 'an instance created with .from_array :gint32' do before do @result = GirFFI::InPointer.from_array :gint32, [24, 13] end it 'holds a pointer to the correct input values' do assert_equal 24, @result.get_int(0) assert_equal 13, @result.get_int(4) end it 'is an instance of FFI::MemoryPointer' do @result.must_be_instance_of FFI::MemoryPointer end it 'is zero-terminated' do assert_equal 0, @result.get_int(8) end end describe 'an instance created with .from_array :utf8' do before do @result = GirFFI::InPointer.from_array :utf8, %w(foo bar baz) end it 'returns an array of pointers to strings' do ary = @result.read_array_of_pointer(3) assert_equal %w(foo bar baz), ary.map(&:read_string) end end describe 'an instance created with .from_array :filename' do before do @result = GirFFI::InPointer.from_array :filename, %w(foo bar baz) end it 'returns an array of pointers to strings' do ary = @result.read_array_of_pointer(3) assert_equal %w(foo bar baz), ary.map(&:read_string) end end describe 'an instance created with .from :utf8' do before do @result = GirFFI::InPointer.from :utf8, 'foo' end it 'returns a pointer to the given string' do assert_equal 'foo', @result.read_string end it 'is an instance of FFI::MemoryPointer' do @result.must_be_instance_of FFI::MemoryPointer end end describe 'an instance created with .from :guint32' do before do @result = GirFFI::InPointer.from :guint32, 12_345 end it 'returns a pointer with an address equal to the given value' do assert_equal 12_345, @result.address end it 'is an instance of FFI::Pointer' do @result.must_be_instance_of FFI::Pointer end end describe 'an instance created with .from :filename' do before do @result = GirFFI::InPointer.from :filename, 'foo' end it 'returns a pointer to the given string' do assert_equal 'foo', @result.read_string end end describe '.from' do it 'returns nil when passed nil' do result = GirFFI::InPointer.from :foo, nil assert_nil result end it "sets the pointer's address to the passed value for type :gint8" do result = GirFFI::InPointer.from :gint8, 23 assert_equal 23, result.address end it 'handles enum types' do e = Module.new do extend GirFFI::EnumBase self::Enum = FFI::Enum.new [:foo, :bar, :baz], :qux end ptr = GirFFI::InPointer.from e, :bar ptr.address.must_equal 1 end describe 'for type :void' do it 'returns the result of to_ptr' do obj = Object.new def obj.to_ptr :test_value end GirFFI::InPointer.from(:void, obj).must_equal :test_value end it 'returns nil when passed nil' do GirFFI::InPointer.from(:void, nil).must_be_nil end end describe 'for types that are classes' do it 'returns the result of to_ptr' do klass = Class.new obj = klass.new def obj.to_ptr :test_value end GirFFI::InPointer.from(klass, obj).must_equal :test_value end end end end gir_ffi-0.11.4/test/gir_ffi/error_type_info_test.rb0000644000004100000410000000224213170036060022403 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' require 'gir_ffi/error_type_info' describe GirFFI::ErrorTypeInfo do let(:instance) { GirFFI::ErrorTypeInfo.new } describe '#array_length' do it 'returns the correct value' do instance.array_length.must_equal(-1) end end describe '#tag_or_class' do it 'returns the correct value' do instance.tag_or_class.must_equal [:pointer, :error] end end describe '#pointer?' do it 'returns the correct value' do instance.pointer?.must_equal true end end describe '#flattened_tag' do it 'returns the correct value' do instance.flattened_tag.must_equal :error end end describe '#extra_conversion_arguments' do it 'returns the correct value' do instance.extra_conversion_arguments.must_equal [] end end describe '#argument_class_name' do it 'returns the correct value' do instance.argument_class_name.must_equal 'GLib::Error' end end describe '#needs_ruby_to_c_conversion_for_callbacks?' do it 'returns the correct value' do instance.needs_ruby_to_c_conversion_for_callbacks?.must_equal true end end end gir_ffi-0.11.4/test/gir_ffi/union_base_test.rb0000644000004100000410000000106713170036060021324 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :GIMarshallingTests describe GirFFI::UnionBase do it 'inherits from StructLikeBase' do GirFFI::StructBase.must_include GirFFI::StructLikeBase end describe 'new' do it 'creates an instance with an owned struct' do instance = GIMarshallingTests::Union.new instance.struct.must_be :owned? end it 'ensures the wrapped pointer is not autoreleased' do instance = GIMarshallingTests::Union.new instance.to_ptr.wont_be :autorelease? end end end gir_ffi-0.11.4/test/gir_ffi/info_ext/0000755000004100000410000000000013170036060017425 5ustar www-datawww-datagir_ffi-0.11.4/test/gir_ffi/info_ext/safe_function_name_test.rb0000644000004100000410000000107713170036060024641 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::InfoExt::SafeFunctionName do let(:klass) do Class.new do include GirFFI::InfoExt::SafeFunctionName end end let(:info) { klass.new } describe '#safe_name' do it 'keeps lower case names lower case' do expect(info).to receive(:name).and_return 'foo' assert_equal 'foo', info.safe_name end it 'returns a non-empty string if name is empty' do expect(info).to receive(:name).and_return '' assert_equal '_', info.safe_name end end end gir_ffi-0.11.4/test/gir_ffi/info_ext/safe_constant_name_test.rb0000644000004100000410000000117013170036060024637 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::InfoExt::SafeConstantName do let(:klass) do Class.new do include GirFFI::InfoExt::SafeConstantName end end let(:info) { klass.new } describe '#safe_name' do it 'makes names starting with an underscore safe' do expect(info).to receive(:name).and_return '_foo' assert_equal 'Private___foo', info.safe_name end it 'makes names with dashes safe' do expect(info).to receive(:name).and_return 'this-could-be-a-signal-name' info.safe_name.must_equal 'This_could_be_a_signal_name' end end end gir_ffi-0.11.4/test/gir_ffi/info_ext/i_unresolved_info_test.rb0000644000004100000410000000060113170036060024517 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::InfoExt::IUnresolvedInfo do let(:klass) do Class.new do include GirFFI::InfoExt::IUnresolvedInfo end end let(:unresolved_info) { klass.new } describe '#to_ffi_type' do it 'returns the most generic type' do unresolved_info.to_ffi_type.must_equal :pointer end end end gir_ffi-0.11.4/test/gir_ffi/info_ext/i_field_info_test.rb0000644000004100000410000000211413170036060023415 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::InfoExt::IFieldInfo do let(:klass) do Class.new do include GirFFI::InfoExt::IFieldInfo end end let(:field_info) { klass.new } describe '#layout_specification' do it 'returns an array of name, typespec and offset' do expect(type = Object.new).to receive(:to_ffi_type).and_return :bar expect(field_info).to receive(:name).and_return 'foo' expect(field_info).to receive(:field_type).and_return type expect(field_info).to receive(:offset).and_return 0 result = field_info.layout_specification assert_equal [:foo, :bar, 0], result end it 'keeps a complex typespec intact' do expect(type = Object.new).to receive(:to_ffi_type).and_return [:bar, 2] expect(field_info).to receive(:name).and_return 'foo' expect(field_info).to receive(:field_type).and_return type expect(field_info).to receive(:offset).and_return 0 result = field_info.layout_specification assert_equal [:foo, [:bar, 2], 0], result end end end gir_ffi-0.11.4/test/gir_ffi/info_ext/i_type_info_test.rb0000644000004100000410000005123413170036060023322 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::InfoExt::ITypeInfo do let(:klass) do Class.new do include GirFFI::InfoExt::ITypeInfo end end let(:type_info) { klass.new } let(:elmtype_info) { klass.new } let(:keytype_info) { klass.new } let(:valtype_info) { klass.new } let(:iface_info) { Object.new } let(:callback_type_info) do get_introspection_data('Regress', 'test_callback').args[0].argument_type end let(:ghash_type_info) do get_introspection_data('Regress', 'test_ghash_nested_everything_return').return_type end describe '#to_ffi_type' do it 'returns an array with elements subtype and size for type :array' do expect(type_info).to receive(:pointer?).and_return false allow(type_info).to receive(:tag).and_return :array expect(type_info).to receive(:array_fixed_size).and_return 2 expect(elmtype_info).to receive(:to_ffi_type).and_return :foo expect(type_info).to receive(:param_type).with(0).and_return elmtype_info result = type_info.to_ffi_type assert_equal [:foo, 2], result end describe 'for an :interface type' do before do allow(type_info).to receive(:interface).and_return iface_info allow(type_info).to receive(:tag).and_return :interface allow(type_info).to receive(:pointer?).and_return false end it "maps a the interface's ffi_type" do allow(iface_info).to receive(:to_ffi_type).and_return :foo type_info.to_ffi_type.must_equal :foo end end end describe '#element_type' do it 'returns the element type for lists' do allow(elmtype_info).to receive(:tag).and_return :foo expect(elmtype_info).to receive(:pointer?).and_return false expect(type_info).to receive(:tag).and_return :glist expect(type_info).to receive(:param_type).with(0).and_return elmtype_info result = type_info.element_type result.must_equal :foo end it 'returns the key and value types for ghashes' do allow(keytype_info).to receive(:tag).and_return :foo expect(keytype_info).to receive(:pointer?).and_return false allow(valtype_info).to receive(:tag).and_return :bar expect(valtype_info).to receive(:pointer?).and_return false expect(type_info).to receive(:tag).and_return :ghash expect(type_info).to receive(:param_type).with(0).and_return keytype_info expect(type_info).to receive(:param_type).with(1).and_return valtype_info result = type_info.element_type result.must_equal [:foo, :bar] end it 'returns nil for other types' do expect(type_info).to receive(:tag).and_return :foo result = type_info.element_type result.must_be_nil end it 'returns [:pointer, :void] if the element type is a pointer with tag :void' do allow(elmtype_info).to receive(:tag_or_class).and_return [:pointer, :void] expect(type_info).to receive(:tag).and_return :glist expect(type_info).to receive(:param_type).with(0).and_return elmtype_info assert_equal [:pointer, :void], type_info.element_type end end describe '#flattened_tag' do describe 'for a simple type' do it 'returns the type tag' do allow(type_info).to receive(:tag).and_return :uint32 type_info.flattened_tag.must_equal :uint32 end end describe 'for a zero-terminated array' do before do allow(type_info).to receive(:tag).and_return :array allow(type_info).to receive(:param_type).with(0).and_return elmtype_info allow(type_info).to receive(:zero_terminated?).and_return true end describe 'of utf8' do it 'returns :strv' do allow(elmtype_info).to receive(:tag).and_return :utf8 allow(elmtype_info).to receive(:pointer?).and_return true type_info.flattened_tag.must_equal :strv end end describe 'of filename' do it 'returns :strv' do allow(elmtype_info).to receive(:tag).and_return :filename allow(elmtype_info).to receive(:pointer?).and_return true type_info.flattened_tag.must_equal :strv end end describe 'of another type' do it 'returns :zero_terminated' do allow(elmtype_info).to receive(:tag).and_return :foo allow(elmtype_info).to receive(:pointer?).and_return false type_info.flattened_tag.must_equal :zero_terminated end end end describe 'for a fixed length c-like array' do it 'returns :c' do expect(type_info).to receive(:tag).and_return :array expect(type_info).to receive(:zero_terminated?).and_return false expect(type_info).to receive(:array_type).and_return :c type_info.flattened_tag.must_equal :c end end describe 'for a GLib array' do it 'returns :c' do expect(type_info).to receive(:tag).and_return :array expect(type_info).to receive(:zero_terminated?).and_return false expect(type_info).to receive(:array_type).and_return :array type_info.flattened_tag.must_equal :array end end end describe '#tag_or_class' do describe 'for a simple type' do it "returns the type's tag" do allow(type_info).to receive(:tag).and_return :foo expect(type_info).to receive(:pointer?).and_return false type_info.tag_or_class.must_equal :foo end end describe 'for utf8 strings' do it 'returns the tag :utf8' do allow(type_info).to receive(:tag).and_return :utf8 expect(type_info).to receive(:pointer?).and_return true type_info.tag_or_class.must_equal :utf8 end end describe 'for filename strings' do it 'returns the tag :filename' do allow(type_info).to receive(:tag).and_return :filename expect(type_info).to receive(:pointer?).and_return true type_info.tag_or_class.must_equal :filename end end describe 'for an interface class' do let(:interface) { Object.new } before do allow(type_info).to receive(:tag).and_return :interface allow(type_info).to receive(:interface).and_return iface_info expect(type_info).to receive(:pointer?).and_return false expect(GirFFI::Builder).to receive(:build_class).with(iface_info).and_return interface end describe 'when the interface type is :enum' do it 'returns the built interface module' do allow(iface_info).to receive(:info_type).and_return :enum type_info.tag_or_class.must_equal interface end end describe 'when the interface type is :object' do it 'returns the built interface class' do allow(iface_info).to receive(:info_type).and_return :object type_info.tag_or_class.must_equal interface end end describe 'when the interface type is :struct' do it 'returns the built interface class' do allow(iface_info).to receive(:info_type).and_return :struct type_info.tag_or_class.must_equal interface end end end describe 'for a callback' do it "returns the callback's wrapper class" do callback_type_info.tag_or_class.must_equal Regress::TestCallback end end describe 'for a pointer to simple type :foo' do it 'returns [:pointer, :foo]' do allow(type_info).to receive(:tag).and_return :foo expect(type_info).to receive(:pointer?).and_return true type_info.tag_or_class.must_equal [:pointer, :foo] end end describe 'for a pointer to :void' do it 'returns [:pointer, :void]' do allow(type_info).to receive(:tag).and_return :void allow(type_info).to receive(:pointer?).and_return true type_info.tag_or_class.must_equal [:pointer, :void] end end describe 'for a complex nested hash type' do it 'returns a representeation of the nested structure' do ghash_type_info.tag_or_class.must_equal( [:pointer, [:ghash, :utf8, [:pointer, [:ghash, :utf8, :utf8]]]]) end end end describe '#to_callback_ffi_type' do describe 'for an :interface argument' do before do allow(type_info).to receive(:interface).and_return iface_info allow(type_info).to receive(:tag).and_return :interface allow(type_info).to receive(:pointer?).and_return false end it 'correctly maps a :union argument to :pointer' do allow(iface_info).to receive(:info_type).and_return :union type_info.to_callback_ffi_type.must_equal :pointer end it 'correctly maps a :flags argument to :int32' do allow(iface_info).to receive(:info_type).and_return :flags type_info.to_callback_ffi_type.must_equal :int32 end end end describe '#extra_conversion_arguments' do describe 'for normal types' do before do allow(type_info).to receive(:tag).and_return :foo end it 'returns an empty array' do type_info.extra_conversion_arguments.must_equal [] end end describe 'for a fixed-size array' do before do allow(type_info).to receive(:tag).and_return :array allow(type_info).to receive(:zero_terminated?).and_return false allow(type_info).to receive(:array_type).and_return :c allow(type_info).to receive(:array_fixed_size).and_return 3 allow(type_info).to receive(:param_type).with(0).and_return elmtype_info allow(elmtype_info).to receive(:tag_or_class).and_return :foo end it 'returns an array containing the element type' do type_info.extra_conversion_arguments.must_equal [:foo, 3] end end describe 'for a zero-terminated array' do before do allow(type_info).to receive(:tag).and_return :array allow(type_info).to receive(:zero_terminated?).and_return true allow(type_info).to receive(:param_type).with(0).and_return elmtype_info allow(elmtype_info).to receive(:tag_or_class).and_return :foo end it 'returns an array containing the element type' do type_info.extra_conversion_arguments.must_equal [:foo] end end describe 'for a GArray' do before do allow(type_info).to receive(:tag).and_return :array allow(type_info).to receive(:zero_terminated?).and_return false allow(type_info).to receive(:array_type).and_return :array allow(type_info).to receive(:param_type).with(0).and_return elmtype_info allow(elmtype_info).to receive(:tag_or_class).and_return :foo end it 'returns an array containing the element type' do type_info.extra_conversion_arguments.must_equal [:foo] end end describe 'for a GHashTable' do before do allow(type_info).to receive(:tag).and_return :ghash allow(type_info).to receive(:param_type).with(0).and_return keytype_info allow(type_info).to receive(:param_type).with(1).and_return valtype_info allow(keytype_info).to receive(:tag_or_class).and_return :foo allow(valtype_info).to receive(:tag_or_class).and_return :bar end it 'returns an array containing the element type pair' do type_info.extra_conversion_arguments.must_equal [[:foo, :bar]] end end describe 'for a GList' do before do allow(type_info).to receive(:tag).and_return :glist allow(type_info).to receive(:param_type).with(0).and_return elmtype_info allow(elmtype_info).to receive(:tag_or_class).and_return :foo end it 'returns an array containing the element type' do type_info.extra_conversion_arguments.must_equal [:foo] end end describe 'for a GSList' do before do allow(type_info).to receive(:tag).and_return :gslist allow(type_info).to receive(:param_type).with(0).and_return elmtype_info allow(elmtype_info).to receive(:tag_or_class).and_return :foo end it 'returns an array containing the element type' do type_info.extra_conversion_arguments.must_equal [:foo] end end describe 'for a GPtrArray' do before do allow(type_info).to receive(:tag).and_return :array allow(type_info).to receive(:zero_terminated?).and_return false allow(type_info).to receive(:array_type).and_return :ptr_array allow(type_info).to receive(:param_type).with(0).and_return elmtype_info allow(elmtype_info).to receive(:tag_or_class).and_return :foo end it 'returns an array containing the element type' do type_info.extra_conversion_arguments.must_equal [:foo] end end describe 'for a :callback' do before do allow(interface_type_info = Object.new).to receive(:namespace).and_return 'Bar' allow(interface_type_info).to receive(:name).and_return 'Foo' allow(type_info).to receive(:tag).and_return :callback allow(type_info).to receive(:interface).and_return interface_type_info end it 'returns an empty array' do type_info.extra_conversion_arguments.must_equal [] end end end describe '#argument_class_name' do before do allow(type_info).to receive(:tag).and_return tag end describe 'for :gint32' do let(:tag) { :gint32 } it 'is nil' do type_info.argument_class_name.must_be_nil end end describe 'for interfaces' do let(:tag) { :interface } before do allow(type_info).to receive(:interface).and_return iface_info allow(iface_info).to receive(:info_type).and_return interface_type allow(iface_info).to receive(:full_type_name).and_return 'Bar::Foo' end describe 'for :struct' do let(:interface_type) { :struct } it 'equals the struct class name' do type_info.argument_class_name.must_equal 'Bar::Foo' end end describe 'for :union' do let(:interface_type) { :union } it 'equals the union class name' do type_info.argument_class_name.must_equal 'Bar::Foo' end end describe 'for :interface' do let(:interface_type) { :interface } it 'equals the interface module name' do type_info.argument_class_name.must_equal 'Bar::Foo' end end describe 'for :object' do let(:interface_type) { :object } it 'equals the object class name' do type_info.argument_class_name.must_equal 'Bar::Foo' end end describe 'for :callback' do let(:interface_type) { :callback } it 'equals the callback type name' do type_info.argument_class_name.must_equal 'Bar::Foo' end end end describe 'for :strv' do let(:tag) { :strv } it 'equals GLib::Strv' do type_info.argument_class_name.must_equal 'GLib::Strv' end end describe 'for arrays' do let(:tag) { :array } before do allow(type_info).to receive(:param_type).with(0).and_return elmtype_info allow(elmtype_info).to receive(:tag_or_class).and_return :foo end describe 'for :zero_terminated' do before do allow(type_info).to receive(:zero_terminated?).and_return true end it 'equals GirFFI::ZeroTerminated' do type_info.argument_class_name.must_equal 'GirFFI::ZeroTerminated' end end describe 'for :byte_array' do before do allow(type_info).to receive(:zero_terminated?).and_return false allow(type_info).to receive(:array_type).and_return :byte_array end it 'equals GLib::ByteArray' do type_info.argument_class_name.must_equal 'GLib::ByteArray' end end describe 'for :ptr_array' do before do allow(type_info).to receive(:zero_terminated?).and_return false allow(type_info).to receive(:array_type).and_return :ptr_array end it 'equals GLib::PtrArray' do type_info.argument_class_name.must_equal 'GLib::PtrArray' end end describe 'for :array' do before do allow(type_info).to receive(:zero_terminated?).and_return false allow(type_info).to receive(:array_type).and_return :array end it 'equals GLib::Array' do type_info.argument_class_name.must_equal 'GLib::Array' end end end describe 'for :glist' do let(:tag) { :glist } it 'equals GLib::List' do type_info.argument_class_name.must_equal 'GLib::List' end end describe 'for :gslist' do let(:tag) { :gslist } it 'equals GLib::SList' do type_info.argument_class_name.must_equal 'GLib::SList' end end describe 'for :ghash' do let(:tag) { :ghash } it 'equals GLib::HashTable' do type_info.argument_class_name.must_equal 'GLib::HashTable' end end describe 'for :error' do let(:tag) { :error } it 'equals GLib::Error' do type_info.argument_class_name.must_equal 'GLib::Error' end end end describe '#gtype' do before do allow(type_info).to receive(:tag).and_return tag allow(type_info).to receive(:pointer?).and_return pointer? end describe 'for :void' do let(:tag) { :void } let(:pointer?) { false } it 'equals the none type' do GObject.type_name(type_info.gtype).must_equal 'void' end end describe 'for :void pointer' do let(:tag) { :void } let(:pointer?) { true } it 'equals the none type' do GObject.type_name(type_info.gtype).must_equal 'gpointer' end end describe 'for :gboolean' do let(:tag) { :gboolean } let(:pointer?) { false } it 'equals the gboolean type' do GObject.type_name(type_info.gtype).must_equal 'gboolean' end end describe 'for :gint32' do let(:tag) { :gint32 } let(:pointer?) { false } it 'equals the gint type' do GObject.type_name(type_info.gtype).must_equal 'gint' end end describe 'for :gint64' do let(:tag) { :gint64 } let(:pointer?) { false } it 'equals the gint64 type' do GObject.type_name(type_info.gtype).must_equal 'gint64' end end describe 'for :guint64' do let(:tag) { :guint64 } let(:pointer?) { false } it 'equals the guint64 type' do GObject.type_name(type_info.gtype).must_equal 'guint64' end end describe 'for pointer to :utf8' do let(:tag) { :utf8 } let(:pointer?) { true } it 'equals the gchararray type' do GObject.type_name(type_info.gtype).must_equal 'gchararray' end end describe 'for pointer to :ghash' do let(:tag) { :ghash } let(:pointer?) { true } it 'equals the GHashTable type' do GObject.type_name(type_info.gtype).must_equal 'GHashTable' end end describe 'for pointer to :glist' do let(:tag) { :glist } let(:pointer?) { true } it 'equals the pointer type' do GObject.type_name(type_info.gtype).must_equal 'gpointer' end end describe 'for arrays' do let(:tag) { :array } let(:pointer?) { true } describe 'for pointer to GArray' do before do allow(type_info).to receive(:zero_terminated?).and_return false allow(type_info).to receive(:array_type).and_return :array end it 'equals the GArray type' do GObject.type_name(type_info.gtype).must_equal 'GArray' end end describe 'for a C array' do before do allow(type_info).to receive(:zero_terminated?).and_return false allow(type_info).to receive(:array_type).and_return :c end it 'equals the gpointer type' do GObject.type_name(type_info.gtype).must_equal 'gpointer' end end describe 'for a zero-terminated array' do before do allow(type_info).to receive(:param_type).with(0).and_return elmtype_info allow(type_info).to receive(:zero_terminated?).and_return true end describe 'of utf8' do it 'equals the GStrv type' do allow(elmtype_info).to receive(:tag).and_return :utf8 allow(elmtype_info).to receive(:pointer?).and_return true GObject.type_name(type_info.gtype).must_equal 'GStrv' end end describe 'of filename' do it 'equals the GStrv type' do allow(elmtype_info).to receive(:tag).and_return :filename allow(elmtype_info).to receive(:pointer?).and_return true GObject.type_name(type_info.gtype).must_equal 'GStrv' end end end end end end gir_ffi-0.11.4/test/gir_ffi/info_ext/i_signal_info_test.rb0000644000004100000410000000157413170036060023620 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :Regress describe GirFFI::InfoExt::ISignalInfo do let(:klass) do Class.new do include GirFFI::InfoExt::ICallableInfo include GirFFI::InfoExt::ISignalInfo end end let(:signal_info) { klass.new } describe '#arguments_to_gvalues' do let(:object) { Regress::TestSubObj.new } let(:boxed) { Regress::TestSimpleBoxedA.const_return } let(:signal_info) { Regress::TestSubObj.find_signal 'test-with-static-scope-arg' } let(:result) { signal_info.arguments_to_gvalues(object, [boxed]) } it 'correctly wraps :object' do result[0].get_value.must_equal object end it 'correctly wraps :struct' do result_boxed = result[1].get_value result_boxed.some_int8.must_equal boxed.some_int8 result_boxed.some_int.must_equal boxed.some_int end end end gir_ffi-0.11.4/test/gir_ffi/info_ext/i_function_info_test.rb0000644000004100000410000000461513170036060024167 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::InfoExt::IFunctionInfo do let(:klass) do Class.new do include GirFFI::InfoExt::ICallableInfo include GirFFI::InfoExt::IFunctionInfo end end let(:function_info) { klass.new } describe '#argument_ffi_types' do before do allow(arg_info1 = Object.new).to receive(:to_ffi_type).and_return :type1 allow(arg_info2 = Object.new).to receive(:to_ffi_type).and_return :type2 allow(function_info).to receive(:args).and_return [arg_info1, arg_info2] end describe 'for a simple function with several arguments' do before do allow(function_info).to receive(:method?).and_return false allow(function_info).to receive(:throws?).and_return false end it 'returns the ffi types of the arguments' do function_info.argument_ffi_types.must_equal [:type1, :type2] end end describe 'for a throwing function with several arguments' do before do allow(function_info).to receive(:method?).and_return false allow(function_info).to receive(:throws?).and_return true end it 'appends :pointer to represent the error argument' do function_info.argument_ffi_types.must_equal [:type1, :type2, :pointer] end end describe 'for a method with several arguments' do before do allow(function_info).to receive(:method?).and_return true allow(function_info).to receive(:throws?).and_return false end it 'prepends :pointer to represent the method reciever' do function_info.argument_ffi_types.must_equal [:pointer, :type1, :type2] end end describe 'for a throwing method with several arguments' do before do allow(function_info).to receive(:method?).and_return true allow(function_info).to receive(:throws?).and_return true end it 'adds :pointer for both the reciever and the error argument' do function_info.argument_ffi_types.must_equal [:pointer, :type1, :type2, :pointer] end end end describe '#return_ffi_type' do it 'returns the ffi type of the return type' do allow(return_type_info = Object.new).to receive(:to_ffi_type).and_return :some_type allow(function_info).to receive(:return_type).and_return return_type_info function_info.return_ffi_type.must_equal :some_type end end end gir_ffi-0.11.4/test/gir_ffi/info_ext/i_callable_info_test.rb0000644000004100000410000000136213170036060024075 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::InfoExt::ICallableInfo do let(:klass) do Class.new do include GirFFI::InfoExt::ICallableInfo end end let(:callable_info) { klass.new } describe '#argument_ffi_types' do describe 'for a simple callable with several arguments' do before do allow(arg_info1 = Object.new).to receive(:to_ffi_type).and_return :type1 allow(arg_info2 = Object.new).to receive(:to_ffi_type).and_return :type2 allow(callable_info).to receive(:args).and_return [arg_info1, arg_info2] end it 'returns the ffi types of the arguments' do callable_info.argument_ffi_types.must_equal [:type1, :type2] end end end end gir_ffi-0.11.4/test/gir_ffi/info_ext/i_callback_info_test.rb0000644000004100000410000000111113170036060024062 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::InfoExt::ICallbackInfo do let(:klass) do Class.new do include GirFFI::InfoExt::ICallbackInfo end end let(:callback_info) { klass.new } describe '#return_ffi_type' do it 'returns the callback ffi type of the return type' do allow(return_type_info = Object.new).to receive(:to_callback_ffi_type).and_return :some_type allow(callback_info).to receive(:return_type).and_return return_type_info callback_info.return_ffi_type.must_equal :some_type end end end gir_ffi-0.11.4/test/gir_ffi/receiver_argument_info_test.rb0000644000004100000410000000137113170036060023721 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' require 'gir_ffi/receiver_argument_info' describe GirFFI::ReceiverArgumentInfo do let(:dummy_type) { 'foo' } let(:instance) { GirFFI::ReceiverArgumentInfo.new dummy_type } describe '#argument_type' do it 'returns the argument type' do instance.argument_type.must_equal dummy_type end end describe '#direction' do it 'returns the correct value' do instance.direction.must_equal :in end end describe '#ownership_transfer' do it 'returns the correct value' do instance.ownership_transfer.must_equal :everything end end describe '#name' do it 'returns the correct value' do instance.name.must_equal '_instance' end end end gir_ffi-0.11.4/test/gir_ffi/zero_terminated_test.rb0000644000004100000410000000460613170036060022377 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::ZeroTerminated do describe '.from' do let(:result) { GirFFI::ZeroTerminated.from :int32, [1, 2, 3] } it 'converts the passed array into a zero-terminated c array' do ptr = result.to_ptr ptr.read_array_of_int32(4).must_equal [1, 2, 3, 0] end it 'returns a GirFFI::ZeroTerminated object' do result.must_be_instance_of GirFFI::ZeroTerminated end end describe '.wrap' do it 'wraps the given type and pointer' do ptr = GirFFI::InPointer.from_array :int32, [1, 2, 3, 0] zt = GirFFI::ZeroTerminated.wrap :foo, ptr zt.element_type.must_equal :foo zt.to_ptr.must_equal ptr end end describe '#each' do it 'yields each element' do zt = GirFFI::ZeroTerminated.from :int32, [1, 2, 3] arr = [] zt.each do |int| arr << int end arr.must_equal [1, 2, 3] end it 'yields zero times for a ZeroTerminated wrapping a null pointer' do zt = GirFFI::ZeroTerminated.wrap :int32, FFI::Pointer.new(0) zt.each do |_str| flunk end end it 'works for :int8' do zt = GirFFI::ZeroTerminated.from :int8, [1, 2, 3] arr = [] zt.each do |int| arr << int end arr.must_equal [1, 2, 3] end end describe '#==' do it 'returns true when comparing to an array with the same elements' do zero_terminated = GirFFI::ZeroTerminated.from :int32, [1, 2, 3] (zero_terminated == [1, 2, 3]).must_equal true end it 'returns false when comparing to an array with different elements' do zero_terminated = GirFFI::ZeroTerminated.from :int32, [1, 2, 3] (zero_terminated == [1, 2]).must_equal false end it 'returns true when comparing to a zero-terminated array with the same elements' do zero_terminated = GirFFI::ZeroTerminated.from :int32, [1, 2, 3] other = GirFFI::ZeroTerminated.from :int32, [1, 2, 3] (zero_terminated == other).must_equal true end it 'returns false when comparing to a zero-terminated array with different elements' do zero_terminated = GirFFI::ZeroTerminated.from :int32, [1, 2, 3] other = GirFFI::ZeroTerminated.from :int32, [1, 2] (zero_terminated == other).must_equal false end end it 'includes Enumerable' do GirFFI::ZeroTerminated.must_include Enumerable end end gir_ffi-0.11.4/test/gir_ffi/builders/0000755000004100000410000000000013170036060017423 5ustar www-datawww-datagir_ffi-0.11.4/test/gir_ffi/builders/signal_closure_builder_test.rb0000644000004100000410000001372513170036060025536 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::SignalClosureBuilder do let(:builder) { GirFFI::Builders::SignalClosureBuilder.new signal_info } describe '#build_class' do let(:signal_info) do get_signal_introspection_data 'Regress', 'TestObj', 'test' end it 'builds a descendant of RubyClosure' do klass = builder.build_class klass.ancestors.must_include GObject::RubyClosure end end describe '#marshaller_definition' do describe 'for a signal with no arguments or return value' do let(:signal_info) do get_signal_introspection_data 'Regress', 'TestObj', 'test' end it 'returns a valid marshaller converting only the receiver' do expected = <<-CODE.reset_indentation def self.marshaller(closure, return_value, param_values, _invocation_hint, _marshal_data) _instance = param_values.first.get_value_plain _v1 = _instance wrap(closure.to_ptr).invoke_block(_v1) end CODE builder.marshaller_definition.must_equal expected end end describe 'for a signal with an argument and a return value' do let(:signal_info) do get_signal_introspection_data 'Regress', 'TestObj', 'sig-with-int64-prop' end it 'returns a valid mapping method' do skip unless signal_info expected = <<-CODE.reset_indentation def self.marshaller(closure, return_value, param_values, _invocation_hint, _marshal_data) _instance, i = param_values.map(&:get_value_plain) _v1 = _instance _v2 = i _v3 = wrap(closure.to_ptr).invoke_block(_v1, _v2) return_value.set_value _v3 end CODE builder.marshaller_definition.must_equal expected end end describe 'for a signal with an enum argument' do let(:signal_info) do get_signal_introspection_data 'Gio', 'MountOperation', 'reply' end it 'returns a valid mapping method' do expected = <<-CODE.reset_indentation def self.marshaller(closure, return_value, param_values, _invocation_hint, _marshal_data) _instance, result = param_values.map(&:get_value_plain) _v1 = _instance _v2 = result wrap(closure.to_ptr).invoke_block(_v1, _v2) end CODE builder.marshaller_definition.must_equal expected end end describe 'for a signal with a array plus length arguments' do let(:signal_info) do get_signal_introspection_data 'Regress', 'TestObj', 'sig-with-array-len-prop' end it 'returns a valid mapping method' do skip unless signal_info expected = <<-CODE.reset_indentation def self.marshaller(closure, return_value, param_values, _invocation_hint, _marshal_data) _instance, arr, len = param_values.map(&:get_value_plain) _v1 = _instance _v2 = len _v3 = GirFFI::SizedArray.wrap(:guint32, _v2, arr) wrap(closure.to_ptr).invoke_block(_v1, _v3) end CODE builder.marshaller_definition.must_equal expected end end describe 'for a signal with a struct argument' do let(:signal_info) do get_signal_introspection_data 'Regress', 'TestObj', 'test-with-static-scope-arg' end it 'returns a valid mapping method' do skip unless signal_info expected = <<-CODE.reset_indentation def self.marshaller(closure, return_value, param_values, _invocation_hint, _marshal_data) _instance, object = param_values.map(&:get_value_plain) _v1 = _instance _v2 = Regress::TestSimpleBoxedA.wrap(object) wrap(closure.to_ptr).invoke_block(_v1, _v2) end CODE builder.marshaller_definition.must_equal expected end end describe 'for a signal returning an array of integers' do let(:signal_info) do get_signal_introspection_data 'Regress', 'TestObj', 'sig-with-intarray-ret' end it 'returns a valid mapping method' do skip unless signal_info expected = <<-CODE.reset_indentation def self.marshaller(closure, return_value, param_values, _invocation_hint, _marshal_data) _instance, i = param_values.map(&:get_value_plain) _v1 = _instance _v2 = i _v3 = wrap(closure.to_ptr).invoke_block(_v1, _v2) _v4 = GLib::Array.from(:gint32, _v3) return_value.set_value _v4 end CODE builder.marshaller_definition.must_equal expected end end describe 'for a signal returning an string' do let(:signal_info) do get_signal_introspection_data 'Gtk', 'Scale', 'format-value' end it 'returns a mapping method that passes the string result to return_value directly' do skip unless signal_info expected = <<-CODE.reset_indentation def self.marshaller(closure, return_value, param_values, _invocation_hint, _marshal_data) _instance, value = param_values.map(&:get_value_plain) _v1 = _instance _v2 = value _v3 = wrap(closure.to_ptr).invoke_block(_v1, _v2) return_value.set_value _v3 end CODE builder.marshaller_definition.must_equal expected end end describe 'for a signal with GList argument' do let(:signal_info) do get_signal_introspection_data 'Regress', 'AnnotationObject', 'list-signal' end it 'returns a valid mapping method' do skip unless signal_info expected = <<-CODE.reset_indentation def self.marshaller(closure, return_value, param_values, _invocation_hint, _marshal_data) _instance, list = param_values.map(&:get_value_plain) _v1 = _instance _v2 = GLib::List.wrap(:utf8, list) wrap(closure.to_ptr).invoke_block(_v1, _v2) end CODE builder.marshaller_definition.must_equal expected end end end end gir_ffi-0.11.4/test/gir_ffi/builders/constant_builder_test.rb0000644000004100000410000000016013170036060024343 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::ConstantBuilder do end gir_ffi-0.11.4/test/gir_ffi/builders/vfunc_argument_builder_test.rb0000644000004100000410000000646213170036060025550 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::VFuncArgumentBuilder do let(:var_gen) { GirFFI::VariableNameGenerator.new } let(:builder) { GirFFI::Builders::VFuncArgumentBuilder.new(var_gen, arg_info) } describe 'for a plain in argument' do let(:vfunc_info) do get_vfunc_introspection_data 'GIMarshallingTests', 'Object', 'method_int8_in' end let(:arg_info) { vfunc_info.args[0] } it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = in_'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal [] end end describe 'for a transfer-none in argument' do let(:vfunc_info) do get_vfunc_introspection_data 'GIMarshallingTests', 'Object', 'vfunc_in_object_transfer_none' end let(:arg_info) { vfunc_info.args[0] } it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = GObject::Object.wrap(object)', '_v1.ref'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal [] end end describe 'for a transfer-none outgoing object argument' do let(:vfunc_info) do get_vfunc_introspection_data 'GIMarshallingTests', 'Object', 'vfunc_out_object_transfer_none' end let(:arg_info) { vfunc_info.args[0] } it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = object'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v1.put_pointer 0, GObject::Object.from(_v2)'] end end describe 'for a full-transfer outgoing object argument' do let(:vfunc_info) do get_vfunc_introspection_data 'GIMarshallingTests', 'Object', 'vfunc_out_object_transfer_full' end let(:arg_info) { vfunc_info.args[0] } it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = object'] end it 'has the correct value for #post_conversion' do builder.pre_conversion builder.post_conversion.must_equal ['_v2.ref', '_v1.put_pointer 0, GObject::Object.from(_v2)'] end end describe 'for a full-transfer outgoing non-object argument' do let(:vfunc_info) do get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'method_int8_arg_and_out_callee') end let(:arg_info) { vfunc_info.args[1] } it 'has the correct value for #pre_conversion' do builder.pre_conversion. must_equal ['_v1 = FFI::MemoryPointer.new(:int8).tap { |ptr| out.put_pointer 0, ptr }'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v1.put_int8 0, _v2'] end end describe 'for a receiver argument' do let(:object_info) { get_introspection_data('GIMarshallingTests', 'Object') } let(:type_info) { GirFFI::ReceiverTypeInfo.new(object_info) } let(:arg_info) { GirFFI::ReceiverArgumentInfo.new(type_info) } it 'has the correct value for #pre_conversion' do builder.pre_conversion. must_equal ['_v1 = GIMarshallingTests::Object.wrap(_instance)'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal [] end end end gir_ffi-0.11.4/test/gir_ffi/builders/union_builder_test.rb0000644000004100000410000000207513170036060023651 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::UnionBuilder do let(:union_info) { get_introspection_data('GObject', 'TypeCValue') } let(:builder) { GirFFI::Builders::UnionBuilder.new union_info } describe '#setup_instance_method' do it "returns nil looking for a method that doesn't exist" do builder.setup_instance_method('blub').must_be_nil end end describe '#layout_specification' do it 'returns the correct layout for GObject::TypeCValue' do long_type = FFI.type_size(:long) == 8 ? :int64 : :int32 builder.layout_specification.must_equal [:v_int, :int32, 0, :v_long, long_type, 0, :v_int64, :int64, 0, :v_double, :double, 0, :v_pointer, :pointer, 0] end end describe '#layout_superclass' do it 'returns GirFFI::Union' do builder.layout_superclass.must_equal GirFFI::Union end end end gir_ffi-0.11.4/test/gir_ffi/builders/user_defined_builder_test.rb0000644000004100000410000004465513170036060025167 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :GIMarshallingTests GirFFI.setup :Regress describe GirFFI::Builders::UserDefinedBuilder do let(:base_klass) { GIMarshallingTests::Object } let(:klass) do Object.const_set("DerivedClass#{Sequence.next}", Class.new(base_klass)) end let(:builder) { GirFFI::Builders::UserDefinedBuilder.new info } let(:info) { GirFFI::UserDefinedObjectInfo.new klass } describe '#build_class' do before do builder.build_class end describe 'with type info containing one integer property' do let(:info) do GirFFI::UserDefinedObjectInfo.new klass do |it| it.install_property GObject.param_spec_int('foo-bar', 'foo bar', 'The Foo Bar Property', 10, 20, 15, readable: true, writable: true) end end it 'registers a type that is bigger than the parent' do gtype = klass.gtype q = GObject.type_query gtype q.instance_size.must_be :>, GIMarshallingTests::Object::Struct.size end it "gives the type's Struct fields for the parent and the property" do klass::Struct.members.must_equal [:parent, :foo_bar] end it 'creates accessor functions for the property' do obj = klass.new obj.foo_bar = 13 obj.foo_bar.must_equal 13 end it 'makes the property retrievable using #get_property' do obj = klass.new obj.foo_bar = 13 obj.get_property('foo-bar').must_equal 13 end it 'makes the property settable using #set_property' do obj = klass.new obj.set_property('foo-bar', 20) obj.foo_bar.must_equal 20 end it 'keeps parent properties accessible through their accessors' do obj = klass.new obj.int = 24 obj.int.must_equal 24 end it 'keeps parent properties accessible through get_property and set_property' do obj = klass.new obj.set_property('int', 24) obj.get_property('int').must_equal 24 end end describe 'with type info containing properties of several different types' do let(:info) do GirFFI::UserDefinedObjectInfo.new klass do |it| it.install_property GObject.param_spec_string('string-prop', 'string property', 'The String Property', 'this is the default value', readable: true, writable: true) it.install_property GObject.param_spec_int('int-prop', 'integer property', 'The Integer Property', 10, 20, 15, readable: true, writable: true) it.install_property GObject.param_spec_long('long-prop', 'long property', 'The Long Property', 10.0, 50.0, 42.0, readable: true, writable: true) end end it 'registers a type of the proper size' do expected_size = klass::Struct.size gtype = klass.gtype q = GObject.type_query gtype q.instance_size.must_equal expected_size end it "gives the type's Struct fields for the parent and the properties with the correct offsets" do offsets = klass::Struct.offsets alignment = klass::Struct.alignment alignment.must_equal 8 # TODO: Fix tests for platforms where this fails. offsets.must_equal [[:parent, 0], [:string_prop, 32], [:int_prop, 40], [:long_prop, 48]] end it 'creates accessor functions for the string property' do obj = klass.new obj.string_prop = 'hello!' obj.string_prop.must_equal 'hello!' end it 'creates accessor functions for the integer property' do obj = klass.new obj.int_prop = 13 obj.int_prop.must_equal 13 end end describe 'with a boxed property' do let(:boxed_gtype) { GIMarshallingTests::BoxedStruct.gtype } let(:info) do GirFFI::UserDefinedObjectInfo.new klass do |it| it.install_property GObject.param_spec_boxed('boxed-prop', 'boxed property', 'The Boxed Property', boxed_gtype, readable: true, writable: true) end end it 'registers a type of the proper size' do expected_size = klass::Struct.size gtype = klass.gtype q = GObject.type_query gtype q.instance_size.must_equal expected_size end it "gives the type's Struct fields for the parent and the property" do klass::Struct.members.must_equal [:parent, :boxed_prop] end it 'creates accessor functions for the property' do obj = klass.new boxed = GIMarshallingTests::BoxedStruct.new boxed.long_ = 423 obj.boxed_prop = boxed obj.boxed_prop.long_.must_equal 423 end end describe 'with an object property' do let(:object_gtype) { GIMarshallingTests::Object.gtype } let(:info) do GirFFI::UserDefinedObjectInfo.new klass do |it| it.install_property GObject.param_spec_object('object-prop', 'object property', 'The Object Property', object_gtype, readable: true, writable: true) end end it 'registers a type of the proper size' do expected_size = klass::Struct.size gtype = klass.gtype q = GObject.type_query gtype q.instance_size.must_equal expected_size end it "gives the type's Struct fields for the parent and the property" do klass::Struct.members.must_equal [:parent, :object_prop] end it 'creates accessor functions for the property' do obj = klass.new object = GIMarshallingTests::Object.new 42 object.int = 423 obj.object_prop = object obj.object_prop.int.must_equal 423 end it 'allows clearing the property throught the setter method' do obj = klass.new obj.object_prop = nil obj.object_prop.must_be_nil end it 'handles reference counting correctly when using the accessor' do obj = klass.new object = GIMarshallingTests::Object.new 42 obj.object_prop = object object.ref_count.must_equal 2 end it 'handles reference counting correctly when using the set_property method' do obj = klass.new object = GIMarshallingTests::Object.new 42 object.ref_count.must_equal 1 obj.set_property('object_prop', object) object.ref_count.must_equal 4 # Due to extra Value#set_value + Value#get_value end end describe 'with a boolean property' do let(:object_gtype) { GIMarshallingTests::Object.gtype } let(:info) do GirFFI::UserDefinedObjectInfo.new klass do |it| it.install_property GObject.param_spec_boolean('the-prop', 'the property', 'The Property', true, readable: true, writable: true) end end it 'creates accessor functions for the property' do obj = klass.new obj.the_prop = true obj.the_prop.must_equal true end end describe 'with a char property' do let(:object_gtype) { GIMarshallingTests::Object.gtype } let(:info) do GirFFI::UserDefinedObjectInfo.new klass do |it| it.install_property GObject.param_spec_char('the-prop', 'the property', 'The Property', -20, 100, 15, readable: true, writable: true) end end it 'creates accessor functions for the property' do obj = klass.new obj.the_prop = -13 obj.the_prop.must_equal(-13) end end describe 'with a uchar property' do let(:object_gtype) { GIMarshallingTests::Object.gtype } let(:info) do GirFFI::UserDefinedObjectInfo.new klass do |it| it.install_property GObject.param_spec_uchar('the-prop', 'the property', 'The Property', 10, 100, 15, readable: true, writable: true) end end it 'creates accessor functions for the property' do obj = klass.new obj.the_prop = 13 obj.the_prop.must_equal 13 end end describe 'with a uint property' do let(:object_gtype) { GIMarshallingTests::Object.gtype } let(:info) do GirFFI::UserDefinedObjectInfo.new klass do |it| it.install_property GObject.param_spec_uint('the-prop', 'the property', 'The Property', 10, 100, 15, readable: true, writable: true) end end it 'creates accessor functions for the property' do obj = klass.new obj.the_prop = 423 obj.the_prop.must_equal 423 end end describe 'with a ulong property' do let(:object_gtype) { GIMarshallingTests::Object.gtype } let(:info) do GirFFI::UserDefinedObjectInfo.new klass do |it| it.install_property GObject.param_spec_ulong('the-prop', 'the property', 'The Property', 10, 100, 15, readable: true, writable: true) end end it 'creates accessor functions for the property' do obj = klass.new obj.the_prop = 423_432 obj.the_prop.must_equal 423_432 end end describe 'with a int64 property' do let(:object_gtype) { GIMarshallingTests::Object.gtype } let(:info) do GirFFI::UserDefinedObjectInfo.new klass do |it| it.install_property GObject.param_spec_int64('the-prop', 'the property', 'The Property', 10, 100, 15, readable: true, writable: true) end end it 'creates accessor functions for the property' do obj = klass.new obj.the_prop = -423_432 obj.the_prop.must_equal(-423_432) end end describe 'with a uint64 property' do let(:object_gtype) { GIMarshallingTests::Object.gtype } let(:info) do GirFFI::UserDefinedObjectInfo.new klass do |it| it.install_property GObject.param_spec_uint64('the-prop', 'the property', 'The Property', 10, 100, 15, readable: true, writable: true) end end it 'creates accessor functions for the property' do obj = klass.new obj.the_prop = 423_432 obj.the_prop.must_equal 423_432 end end describe 'with a float property' do let(:object_gtype) { GIMarshallingTests::Object.gtype } let(:info) do GirFFI::UserDefinedObjectInfo.new klass do |it| it.install_property GObject.param_spec_float('the-prop', 'the property', 'The Property', 10.0, 100.0, 15.0, readable: true, writable: true) end end it 'creates accessor functions for the property' do obj = klass.new obj.the_prop = 42.23 obj.the_prop.must_be_within_epsilon 42.23 end end describe 'with a double property' do let(:object_gtype) { GIMarshallingTests::Object.gtype } let(:info) do GirFFI::UserDefinedObjectInfo.new klass do |it| it.install_property GObject.param_spec_double('the-prop', 'the property', 'The Property', 10.0, 100.0, 15.0, readable: true, writable: true) end end it 'creates accessor functions for the property' do obj = klass.new obj.the_prop = 42.23 obj.the_prop.must_equal 42.23 end end describe 'with an enum property' do let(:object_gtype) { GIMarshallingTests::Object.gtype } let(:info) do GirFFI::UserDefinedObjectInfo.new klass do |it| prop = GObject.param_spec_enum('the-prop', 'the property', 'The Property', GIMarshallingTests::GEnum.gtype, 0, readable: true, writable: true) it.install_property prop end end it 'creates accessor functions for the property' do obj = klass.new obj.the_prop = :value2 obj.the_prop.must_equal :value2 end end describe 'with a flags property' do let(:object_gtype) { GIMarshallingTests::Object.gtype } let(:info) do GirFFI::UserDefinedObjectInfo.new klass do |it| prop = GObject.param_spec_flags('the-prop', 'the property', 'The Property', GIMarshallingTests::Flags.gtype, 0, readable: true, writable: true) it.install_property prop end end it 'creates accessor functions for the property' do obj = klass.new obj.the_prop = { value2: true } obj.the_prop.must_equal value2: true end end describe 'when deriving from a class with hidden struct size' do let(:parent_class) { Regress::TestInheritDrawable } let(:parent_size) do GObject.type_query(parent_class.gtype).instance_size end let(:klass) do Object.const_set("DerivedClass#{Sequence.next}", Class.new(parent_class)) end let(:info) do GirFFI::UserDefinedObjectInfo.new klass do |it| it.install_property GObject.param_spec_int('int-prop', 'integer property', 'Integer Property', 10, 20, 15, readable: true, writable: true) end end it 'registers a type that is bigger than the parent' do klass_size = GObject.type_query(klass.gtype).instance_size klass_size.must_be :>, parent_size end it 'leaves enough space in derived struct layout' do struct_size = klass::Struct.size struct_size.must_be :>, parent_size end end describe 'with type info containing an overridden g_name' do let(:info) do GirFFI::UserDefinedObjectInfo.new klass do |it| it.g_name = "OtherName#{Sequence.next}" end end it 'registers a type under the overridden name' do registered_name = GObject.type_name(klass.gtype) registered_name.must_equal info.g_name registered_name.wont_equal klass.name end end describe 'with type info containing a vfunc' do let(:info) do GirFFI::UserDefinedObjectInfo.new klass do |it| it.install_vfunc_implementation :method_int8_in, proc { |instance, in_| instance.int = in_ } end end it 'allows the vfunc to be called through its invoker' do obj = klass.new obj.method_int8_in 12 obj.int.must_equal 12 end end describe 'when using a default vfunc implementation' do let(:base_klass) { Regress::TestObj } let(:info) do GirFFI::UserDefinedObjectInfo.new klass do |it| it.install_vfunc_implementation :matrix end end before do klass.class_eval do def matrix(_arg) 44 end end end it 'allows the vfunc to be called through its invoker' do obj = klass.new obj.do_matrix('bar').must_equal 44 end end describe 'with type info containing a vfunc from an included Interface' do let(:info) do klass.class_eval { include GIMarshallingTests::Interface } GirFFI::UserDefinedObjectInfo.new klass do |it| it.install_vfunc_implementation :test_int8_in, proc { |instance, in_| instance.int = in_ } end end it 'marks the type as conforming to the included Interface' do iface_gtype = GIMarshallingTests::Interface.gtype GObject.type_interfaces(klass.gtype).to_a.must_equal [iface_gtype] end it 'allows the vfunc to be called through its invoker' do obj = klass.new obj.test_int8_in 12 obj.int.must_equal 12 end end it 'keeps the gtype for an already registered class' do gtype = klass.gtype other_builder = GirFFI::Builders::UserDefinedBuilder.new info other_klass = other_builder.build_class other_klass.gtype.must_equal gtype end it 'creates a class with a new GType' do klass.gtype.wont_equal GIMarshallingTests::Object.gtype end it 'makes the registered class return objects with the correct GType' do obj = klass.new GObject.type_from_instance(obj).must_equal klass.gtype end end describe '#object_class_struct' do it 'returns the parent class struct' do builder.object_class_struct.must_equal GIMarshallingTests::ObjectClass end end end gir_ffi-0.11.4/test/gir_ffi/builders/vfunc_builder_test.rb0000644000004100000410000001712713170036060023646 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::VFuncBuilder do let(:builder) { GirFFI::Builders::VFuncBuilder.new vfunc_info } describe '#mapping_method_definition' do let(:result) { builder.mapping_method_definition } before do skip unless vfunc_info end describe 'for a vfunc with only one argument' do let(:vfunc_info) do get_vfunc_introspection_data 'GIMarshallingTests', 'Object', 'method_int8_in' end it 'returns a valid mapping method including receiver' do expected = <<-CODE.reset_indentation def self.call_with_argument_mapping(_proc, _instance, in_) _v1 = GIMarshallingTests::Object.wrap(_instance) _v2 = in_ _proc.call(_v1, _v2) end CODE result.must_equal expected end end describe 'for a vfunc returning an enum' do let(:vfunc_info) do get_vfunc_introspection_data 'GIMarshallingTests', 'Object', 'vfunc_return_enum' end it 'returns a valid mapping method including receiver' do expected = <<-CODE.reset_indentation def self.call_with_argument_mapping(_proc, _instance) _v1 = GIMarshallingTests::Object.wrap(_instance) _v2 = _proc.call(_v1) _v3 = GIMarshallingTests::Enum.from(_v2) return _v3 end CODE result.must_equal expected end end describe 'for a vfunc with a callback argument' do let(:vfunc_info) do get_vfunc_introspection_data 'GIMarshallingTests', 'Object', 'vfunc_with_callback' end it 'returns a valid mapping method including receiver' do expected = <<-CODE.reset_indentation def self.call_with_argument_mapping(_proc, _instance, callback, callback_data) _v1 = GIMarshallingTests::Object.wrap(_instance) _v2 = GIMarshallingTests::CallbackIntInt.wrap(callback) _v3 = GirFFI::ArgHelper::OBJECT_STORE.fetch(callback_data) _proc.call(_v1, _v2, _v3) end CODE result.must_equal expected end end describe 'for a vfunc with an out argument allocated by them, the caller' do let(:vfunc_info) do get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'method_int8_arg_and_out_caller') end it 'returns a valid mapping method including receiver' do expected = <<-CODE.reset_indentation def self.call_with_argument_mapping(_proc, _instance, arg, out) _v1 = GIMarshallingTests::Object.wrap(_instance) _v2 = arg _v3 = out _v4 = _proc.call(_v1, _v2) _v3.put_int8 0, _v4 end CODE result.must_equal expected end end describe 'for a vfunc with an out argument allocated by us, the callee' do let(:vfunc_info) do get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'method_int8_arg_and_out_callee') end it 'returns a valid mapping method including receiver' do expected = <<-CODE.reset_indentation def self.call_with_argument_mapping(_proc, _instance, arg, out) _v1 = GIMarshallingTests::Object.wrap(_instance) _v2 = arg _v3 = FFI::MemoryPointer.new(:int8).tap { |ptr| out.put_pointer 0, ptr } _v4 = _proc.call(_v1, _v2) _v3.put_int8 0, _v4 end CODE result.must_equal expected end end describe 'for a vfunc with a GObject::Value out argument allocated by them, the caller' do let(:vfunc_info) do get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'vfunc_caller_allocated_out_parameter') end it 'returns a valid mapping method including receiver' do expected = <<-CODE.reset_indentation def self.call_with_argument_mapping(_proc, _instance, a) _v1 = GIMarshallingTests::Object.wrap(_instance) _v2 = a _v3 = _proc.call(_v1) GObject::Value.copy_value_to_pointer(GObject::Value.from(_v3), _v2) end CODE result.must_equal expected end end describe 'for a vfunc with an error argument' do let(:vfunc_info) do get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'vfunc_meth_with_err') end it 'returns a valid mapping method including receiver' do expected = <<-CODE.reset_indentation def self.call_with_argument_mapping(_proc, _instance, x, _error) _v1 = GIMarshallingTests::Object.wrap(_instance) _v2 = x _v3 = _error begin _v4 = _proc.call(_v1, _v2) rescue => _v5 _v3.put_pointer 0, GLib::Error.from(_v5) end return _v4 end CODE result.must_equal expected end end describe 'for a vfunc with a full-transfer return value' do let(:vfunc_info) do get_vfunc_introspection_data 'GIMarshallingTests', 'Object', 'vfunc_return_object_transfer_full' end it 'returns a valid mapping method' do expected = <<-CODE.reset_indentation def self.call_with_argument_mapping(_proc, _instance) _v1 = GIMarshallingTests::Object.wrap(_instance) _v2 = _proc.call(_v1) _v2.ref _v3 = GObject::Object.from(_v2).to_ptr return _v3 end CODE result.must_equal expected end end describe 'for a vfunc with a transfer-none in argument' do let(:vfunc_info) do get_vfunc_introspection_data 'GIMarshallingTests', 'Object', 'vfunc_in_object_transfer_none' end it 'returns a valid mapping method' do expected = <<-CODE.reset_indentation def self.call_with_argument_mapping(_proc, _instance, object) _v1 = GIMarshallingTests::Object.wrap(_instance) _v2 = GObject::Object.wrap(object) _v2.ref _proc.call(_v1, _v2) end CODE result.must_equal expected end end describe 'for a vfunc with a full-transfer outgoing argument' do let(:vfunc_info) do get_vfunc_introspection_data 'GIMarshallingTests', 'Object', 'vfunc_out_object_transfer_full' end it 'returns a valid mapping method' do expected = <<-CODE.reset_indentation def self.call_with_argument_mapping(_proc, _instance, object) _v1 = GIMarshallingTests::Object.wrap(_instance) _v2 = object _v3 = _proc.call(_v1) _v3.ref _v2.put_pointer 0, GObject::Object.from(_v3) end CODE result.must_equal expected end end end describe '#argument_ffi_types' do let(:result) { builder.argument_ffi_types } before do skip unless vfunc_info end describe 'for a vfunc with only one argument' do let(:vfunc_info) do get_vfunc_introspection_data 'GIMarshallingTests', 'Object', 'method_int8_in' end it 'returns the correct FFI types including :pointer for the receiver' do result.must_equal [:pointer, :int8] end end end describe '#return_ffi_type' do let(:result) { builder.return_ffi_type } before do skip unless vfunc_info end describe 'for a vfunc returning an object' do let(:vfunc_info) do get_vfunc_introspection_data 'GIMarshallingTests', 'Object', 'vfunc_return_object_transfer_full' end it 'returns :pointer' do result.must_equal :pointer end end end end gir_ffi-0.11.4/test/gir_ffi/builders/constructor_builder_test.rb0000644000004100000410000000225213170036060025103 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::ConstructorBuilder do describe '#method_definition' do let(:builder) { GirFFI::Builders::ConstructorBuilder.new function_info } let(:code) { builder.method_definition } describe 'for constructors with the default name' do let(:function_info) { get_method_introspection_data 'Regress', 'TestObj', 'new' } it 'builds a constructor' do code.must_equal <<-CODE.reset_indentation def self.new(*args, &block) obj = allocate obj.__send__ :initialize, *args, &block obj end CODE end end describe 'for constructors with a custom name' do let(:function_info) { get_method_introspection_data 'Regress', 'TestObj', 'new_from_file' } it 'builds a custom constructor' do code.must_equal <<-CODE.reset_indentation def self.new_from_file(*args, &block) raise NoMethodError unless self == Regress::TestObj obj = allocate obj.__send__ :initialize_from_file, *args, &block obj end CODE end end end end gir_ffi-0.11.4/test/gir_ffi/builders/callback_argument_builder_test.rb0000644000004100000410000001015013170036060026150 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::CallbackArgumentBuilder do let(:var_gen) { GirFFI::VariableNameGenerator.new } let(:builder) { GirFFI::Builders::CallbackArgumentBuilder.new(var_gen, arg_info) } describe 'for an argument with direction :out' do describe 'for :zero_terminated' do let(:vfunc_info) do get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'vfunc_array_out_parameter') end let(:arg_info) { vfunc_info.args[0] } before { skip unless vfunc_info } it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = a'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v1.put_pointer 0, GirFFI::ZeroTerminated.from(:gfloat, _v2)'] end end describe 'when the argument is allocated by us, the callee' do let(:vfunc_info) do get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'method_int8_arg_and_out_callee') end let(:arg_info) { vfunc_info.args[1] } it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new(:int8).tap { |ptr| out.put_pointer 0, ptr }'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v1.put_int8 0, _v2'] end end end describe 'for an argument with direction :error' do let(:arg_info) { GirFFI::ErrorArgumentInfo.new } it 'sets up a rescueing block in #pre_conversion' do builder.pre_conversion.must_equal [ '_v1 = _error', 'begin' ] end it 'converts any exceptions to GLib::Error in #post_conversion' do builder.post_conversion.must_equal [ 'rescue => _v1', '_v2.put_pointer 0, GLib::Error.from(_v1)', 'end' ] end end describe 'for an argument with direction :inout' do let(:callback_info) do get_introspection_data('Regress', 'TestCallbackArrayInOut') end let(:array_arg_info) { callback_info.args[0] } let(:array_arg_builder) do GirFFI::Builders::CallbackArgumentBuilder.new(var_gen, array_arg_info) end let(:length_arg_info) { callback_info.args[1] } let(:length_arg_builder) do GirFFI::Builders::CallbackArgumentBuilder.new(var_gen, length_arg_info) end 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 = ints', '_v2 = GirFFI::SizedArray.wrap(:gint32, _v3, _v1.get_pointer(0))'] end it 'has the correct value for #post_conversion' do array_arg_builder.pre_conversion array_arg_builder.post_conversion. must_equal ['_v1.put_pointer 0, 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 = length', '_v2 = _v1.get_int32(0)'] end it 'has the correct value for #post_conversion' do length_arg_builder.pre_conversion length_arg_builder.post_conversion. must_equal ['_v1.put_int32 0, _v3.length'] end end end end gir_ffi-0.11.4/test/gir_ffi/builders/property_builder_test.rb0000644000004100000410000001056313170036060024406 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::PropertyBuilder do let(:builder) { GirFFI::Builders::PropertyBuilder.new property_info } describe 'for a property of type :glist' do let(:property_info) { get_property_introspection_data('Regress', 'TestObj', 'list') } it 'generates the correct getter definition' do expected = <<-CODE.reset_indentation def list _v1 = get_property('list') _v2 = GLib::List.wrap(:utf8, _v1) _v2 end CODE builder.getter_def.must_equal expected end it 'generates the correct setter definition' do expected = <<-CODE.reset_indentation def list= value _v1 = GLib::List.from(:utf8, value) set_property("list", _v1) end CODE builder.setter_def.must_equal expected end end describe 'for a property of type :ghash' do let(:property_info) { get_property_introspection_data('Regress', 'TestObj', 'hash-table') } it 'generates the correct getter definition' do expected = <<-CODE.reset_indentation def hash_table _v1 = get_property('hash-table') _v2 = GLib::HashTable.wrap([:utf8, :gint8], _v1) _v2 end CODE builder.getter_def.must_equal expected end it 'generates the correct setter definition' do expected = <<-CODE.reset_indentation def hash_table= value _v1 = GLib::HashTable.from([:utf8, :gint8], value) set_property("hash-table", _v1) end CODE builder.setter_def.must_equal expected end end describe 'for a property of type :strv' do let(:property_info) do get_property_introspection_data('GIMarshallingTests', 'PropertiesObject', 'some-strv') end before do skip unless property_info end it 'generates the correct getter definition' do expected = <<-CODE.reset_indentation def some_strv _v1 = get_property('some-strv') _v1 end CODE builder.getter_def.must_equal expected end it 'generates the correct setter definition' do expected = <<-CODE.reset_indentation def some_strv= value _v1 = GLib::Strv.from(value) set_property("some-strv", _v1) end CODE builder.setter_def.must_equal expected end end describe 'for a property of type :utf8' do let(:property_info) { get_property_introspection_data('Regress', 'TestObj', 'string') } it 'generates the correct getter definition' do expected = <<-CODE.reset_indentation def string _v1 = get_property('string') _v1 end CODE builder.getter_def.must_equal expected end it 'generates the correct setter definition' do expected = <<-CODE.reset_indentation def string= value _v1 = value set_property("string", _v1) end CODE builder.setter_def.must_equal expected end end describe 'for a property of a callback type' do let(:property_info) do get_property_introspection_data('Regress', 'AnnotationObject', 'function-property') end it 'generates the correct getter definition' do expected = <<-CODE.reset_indentation def function_property _v1 = get_property('function-property') _v2 = Regress::AnnotationCallback.wrap(_v1) _v2 end CODE builder.getter_def.must_equal expected end it 'generates the correct setter definition' do expected = <<-CODE.reset_indentation def function_property= value _v1 = Regress::AnnotationCallback.from(value) set_property("function-property", _v1) end CODE builder.setter_def.must_equal expected end end describe '#container_defines_getter_method?' do let(:property_info) { Object.new.tap { |o| o.extend GirFFI::InfoExt::IPropertyInfo } } let(:container_info) { Object.new } before do allow(property_info).to receive(:container).and_return container_info allow(property_info).to receive(:name).and_return 'foo-bar' allow(container_info).to receive(:find_instance_method).with('foo_bar').and_return true end it 'finds methods with underscores for properties with dashes' do builder.container_defines_getter_method?.must_equal true end end end gir_ffi-0.11.4/test/gir_ffi/builders/struct_builder_test.rb0000644000004100000410000000656513170036060024055 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::StructBuilder do describe '#layout_specification' do it 'returns the correct layout for Regress::TestStructA' do info = get_introspection_data 'Regress', 'TestStructA' builder = GirFFI::Builders::StructBuilder.new info builder.layout_specification.must_equal [:some_int, :int32, 0, :some_int8, :int8, 4, :some_double, :double, 8, :some_enum, Regress::TestEnum, 16] end describe 'for a struct with a simple layout' do before do @field = Object.new @struct = Object.new allow(@struct).to receive(:namespace).and_return 'Foo' allow(@struct).to receive(:safe_name).and_return 'Bar' allow(@struct).to receive(:fields).and_return [@field] @builder = GirFFI::Builders::StructBuilder.new @struct end it 'creates the correct layout specification' do expect(@field).to receive(:layout_specification).and_return [:bar, :int32, 0] spec = @builder.layout_specification assert_equal [:bar, :int32, 0], spec end end describe 'for a struct with a layout with a complex type' do it 'does not flatten the complex type specification' do expect(simplefield = Object.new).to receive(:layout_specification).and_return [:bar, :foo, 0] expect(complexfield = Object.new).to receive(:layout_specification).and_return [:baz, [:qux, 2], 0] expect(struct = Object.new).to receive(:fields).and_return [simplefield, complexfield] allow(struct).to receive(:safe_name).and_return 'Bar' allow(struct).to receive(:namespace).and_return 'Foo' builder = GirFFI::Builders::StructBuilder.new struct spec = builder.layout_specification assert_equal [:bar, :foo, 0, :baz, [:qux, 2], 0], spec end end end describe '#superclass' do it 'returns StructBase for a normal struct' do info = get_introspection_data 'Regress', 'TestStructA' builder = GirFFI::Builders::StructBuilder.new info builder.superclass.must_equal GirFFI::StructBase end it 'returns BoxedBase for a boxed type' do info = get_introspection_data 'Regress', 'TestSimpleBoxedB' builder = GirFFI::Builders::StructBuilder.new info builder.superclass.must_equal GirFFI::BoxedBase end it 'returns the GObject parent class for a type class' do info = get_introspection_data 'GIMarshallingTests', 'SubSubObjectClass' builder = GirFFI::Builders::StructBuilder.new info builder.superclass.must_equal GIMarshallingTests::SubObjectClass end it 'returns ObjectClass for InitiallyUnownedClass' do info = get_introspection_data 'GObject', 'InitiallyUnownedClass' builder = GirFFI::Builders::StructBuilder.new info builder.superclass.must_equal GObject::ObjectClass end end describe '#setup_class' do before do save_module :Regress end it 'stubs the structs methods' do info = get_introspection_data 'Regress', 'TestStructA' builder = GirFFI::Builders::StructBuilder.new info builder.setup_class assert_defines_instance_method Regress::TestStructA, :clone end after do restore_module :Regress end end end gir_ffi-0.11.4/test/gir_ffi/builders/field_builder_test.rb0000644000004100000410000001101313170036060023574 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::FieldBuilder do let(:klass) { 'dummy' } let(:instance) { GirFFI::Builders::FieldBuilder.new field_info, klass } describe 'for a field of type :gint8 with an offset' do let(:field_info) { get_field_introspection_data 'Regress', 'TestSimpleBoxedA', 'some_int8' } it 'creates the right getter method' do expected = <<-CODE.reset_indentation def some_int8 _v1 = @struct.to_ptr + #{field_info.offset} _v2 = _v1.get_int8(0) _v2 end CODE instance.getter_def.must_equal expected end it 'creates the right setter method' do expected = <<-CODE.reset_indentation def some_int8= value _v1 = @struct.to_ptr + #{field_info.offset} _v2 = value _v1.put_int8 0, _v2 end CODE instance.setter_def.must_equal expected end end describe 'for a field of type :struct' do let(:field_info) { get_field_introspection_data 'Regress', 'TestBoxed', 'nested_a' } it 'creates the right getter method' do expected = <<-CODE.reset_indentation def nested_a _v1 = @struct.to_ptr + #{field_info.offset} _v2 = Regress::TestSimpleBoxedA.get_value_from_pointer(_v1, 0) _v3 = Regress::TestSimpleBoxedA.wrap(_v2) _v3 end CODE instance.getter_def.must_equal expected end it 'creates the right setter method' do expected = <<-CODE.reset_indentation def nested_a= value _v1 = @struct.to_ptr + #{field_info.offset} _v2 = Regress::TestSimpleBoxedA.copy_from(value) Regress::TestSimpleBoxedA.copy_value_to_pointer(_v2, _v1) end CODE instance.setter_def.must_equal expected end end describe 'for a field of type :enum' do let(:field_info) { get_field_introspection_data 'Regress', 'TestStructA', 'some_enum' } it 'creates the right getter method' do expected = <<-CODE.reset_indentation def some_enum _v1 = @struct.to_ptr + #{field_info.offset} _v2 = Regress::TestEnum.get_value_from_pointer(_v1, 0) _v2 end CODE instance.getter_def.must_equal expected end end describe 'for an inline fixed-size array field' do let(:field_info) { get_field_introspection_data 'Regress', 'TestStructE', 'some_union' } it 'creates the right getter method' do expected = <<-CODE.reset_indentation def some_union _v1 = @struct.to_ptr + #{field_info.offset} _v2 = GirFFI::SizedArray.get_value_from_pointer(_v1, 0) _v3 = GirFFI::SizedArray.wrap(Regress::TestStructE__some_union__union, 2, _v2) _v3 end CODE instance.getter_def.must_equal expected end it 'creates the right setter method' do expected = <<-CODE.reset_indentation def some_union= value _v1 = @struct.to_ptr + #{field_info.offset} GirFFI::ArgHelper.check_fixed_array_size 2, value, \"value\" _v2 = GirFFI::SizedArray.copy_from(Regress::TestStructE__some_union__union, 2, value) GirFFI::SizedArray.copy_value_to_pointer(_v2, _v1) end CODE instance.setter_def.must_equal expected end end describe 'for a field of type :callback' do let(:field_info) { get_field_introspection_data 'GObject', 'TypeInfo', 'class_init' } it 'creates the right setter method' do expected = <<-CODE.reset_indentation def class_init= value _v1 = @struct.to_ptr + #{field_info.offset} _v2 = GObject::ClassInitFunc.from(value) GObject::ClassInitFunc.copy_value_to_pointer(_v2, _v1) end CODE instance.setter_def.must_equal expected end end describe 'for a field with a related array length field' do let(:field_info) { get_field_introspection_data 'GObject', 'SignalQuery', 'param_types' } let(:n_params_field_info) { get_field_introspection_data 'GObject', 'SignalQuery', 'n_params' } it 'creates the right getter method' do skip if field_info.field_type.array_length < 0 expected = <<-CODE.reset_indentation def param_types _v1 = @struct.to_ptr + #{n_params_field_info.offset} _v2 = _v1.get_uint32(0) _v3 = @struct.to_ptr + #{field_info.offset} _v4 = _v3.get_pointer(0) _v5 = GirFFI::SizedArray.wrap(:GType, _v2, _v4) _v5 end CODE instance.getter_def.must_equal expected end end end gir_ffi-0.11.4/test/gir_ffi/builders/initializer_builder_test.rb0000644000004100000410000000342113170036060025040 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::InitializerBuilder do describe '#method_definition' do let(:builder) { GirFFI::Builders::InitializerBuilder.new function_info } let(:code) { builder.method_definition } describe 'for constructors with the default name' do let(:function_info) { get_method_introspection_data 'Regress', 'TestObj', 'new' } it 'builds an initializer' do code.must_equal <<-CODE.reset_indentation def initialize(obj) _v1 = Regress::TestObj.from(obj) _v2 = Regress::Lib.regress_test_obj_new _v1 store_pointer(_v2) end CODE end end describe 'for constructors with a custom name' do let(:function_info) { get_method_introspection_data 'Regress', 'TestObj', 'new_from_file' } it 'builds a custom initializer' do code.must_equal <<-CODE.reset_indentation def initialize_from_file(x) _v1 = GirFFI::InPointer.from_utf8(x) _v2 = FFI::MemoryPointer.new(:pointer).write_pointer nil _v3 = Regress::Lib.regress_test_obj_new_from_file _v1, _v2 GirFFI::ArgHelper.check_error(_v2) store_pointer(_v3) end CODE end end describe 'for constructors for boxed types' do let(:function_info) do get_method_introspection_data 'GIMarshallingTests', 'BoxedStruct', 'new' end it 'builds an initializer that sets owned to true' do code.must_equal <<-CODE.reset_indentation def initialize _v1 = GIMarshallingTests::Lib.gi_marshalling_tests_boxed_struct_new store_pointer(_v1) @struct.owned = true end CODE end end end end gir_ffi-0.11.4/test/gir_ffi/builders/unintrospectable_builder_test.rb0000644000004100000410000000363413170036060026104 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :Gio GirFFI.setup :Gst describe GirFFI::Builders::UnintrospectableBuilder do describe 'building the GLocalFile type' do before do Gio.file_new_for_path '/' @gtype = GObject.type_from_name 'GLocalFile' @info = GirFFI::UnintrospectableTypeInfo.new(@gtype) @bldr = GirFFI::Builders::UnintrospectableBuilder.new(@info) @klass = @bldr.build_class end it 'builds a class' do assert_instance_of Class, @klass end it 'builds a class derived from GObject::Object' do assert_includes @klass.ancestors, GObject::Object end it 'builds a class derived from Gio::File' do assert_includes @klass.ancestors, Gio::File end it 'returns the same class when built again' do other_bldr = GirFFI::Builders::UnintrospectableBuilder.new(@info) other_klass = other_bldr.build_class assert_equal @klass, other_klass end describe 'its #find_signal method' do it "returns nil for a signal that doesn't exist" do @bldr.find_signal('foo').must_be_nil end it 'finds signals in ancestor classes' do signal = @bldr.find_signal 'notify' signal.name.must_equal 'notify' end end describe '#object_class_struct' do it 'returns the parent class struct' do @bldr.object_class_struct.must_equal GObject::ObjectClass end end end describe 'building the GstFakeSink type' do let(:instance) { Gst::ElementFactory.make('fakesink', 'sink') } let(:klass) { instance.class } let(:builder) { klass.gir_ffi_builder } before do Gst.init [] end describe 'its #find_signal method' do it 'finds signals that are not defined in the GIR' do signal = builder.find_signal 'handoff' signal.wont_be_nil signal.name.must_equal 'handoff' end end end end gir_ffi-0.11.4/test/gir_ffi/builders/unintrospectable_boxed_builder_test.rb0000644000004100000410000000213713170036060027262 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :GIMarshallingTests describe GirFFI::Builders::UnintrospectableBoxedBuilder do let(:instance) { GIMarshallingTests::PropertiesObject.new } let(:property) { instance.object_class.find_property 'some-boxed-glist' } let(:gtype) { property.value_type } let(:info) { GirFFI::UnintrospectableBoxedInfo.new(gtype) } let(:bldr) { GirFFI::Builders::UnintrospectableBoxedBuilder.new(info) } let(:klass) { bldr.build_class } before do skip unless get_property_introspection_data('GIMarshallingTests', 'PropertiesObject', 'some-boxed-glist') end it 'builds a class' do klass.must_be_instance_of Class end it 'builds a class derived from GirFFI::BoxedBase' do klass.ancestors.must_include GirFFI::BoxedBase end it 'returns the same class when built again' do other_bldr = GirFFI::Builders::UnintrospectableBoxedBuilder.new(info) other_klass = other_bldr.build_class other_klass.must_equal klass end end gir_ffi-0.11.4/test/gir_ffi/builders/argument_builder_test.rb0000644000004100000410000005324513170036060024350 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::ArgumentBuilder do let(:var_gen) { GirFFI::VariableNameGenerator.new } let(:builder) { GirFFI::Builders::ArgumentBuilder.new(var_gen, arg_info) } describe 'for an argument with direction :in' do describe 'for :c' do describe 'with full ownership transfer' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'array_struct_take_in').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion. must_equal ['_v1 = GirFFI::SizedArray.copy_from([:pointer, GIMarshallingTests::BoxedStruct], -1, structs)'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal [] end end end describe 'for :callback' do let(:arg_info) do get_introspection_data('Regress', 'test_callback_destroy_notify').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = Regress::TestCallbackUserData.from(callback)'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal [] end end describe 'for :zero_terminated' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'array_in_len_zero_terminated').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = GirFFI::ZeroTerminated.from(:gint32, ints)'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal [] end end describe 'for :void' do let(:arg_info) { get_introspection_data('Regress', 'test_callback_user_data').args[1] } describe 'when it is a regular argument' do before do builder.closure = false end it 'has the correct value for method_argument_name' do builder.method_argument_name.must_equal arg_info.name end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = user_data'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal [] end end describe 'when it is a closure' do before do callback = Object.new allow(callback).to receive(:call_argument_name).and_return 'foo' builder.closure = callback end it 'has the correct value for method_argument_name' do builder.method_argument_name.must_be_nil end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = GirFFI::ArgHelper.store(foo)'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal [] end end end end describe 'for an argument with direction :out' do describe 'for :enum' do let(:arg_info) { get_introspection_data('GIMarshallingTests', 'genum_out').args[0] } it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new GIMarshallingTests::GEnum'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GIMarshallingTests::GEnum.get_value_from_pointer(_v1, 0)'] end end describe 'for :flags' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'flags_out').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new GIMarshallingTests::Flags'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GIMarshallingTests::Flags.get_value_from_pointer(_v1, 0)'] end end describe 'for :object' do describe 'with full ownership transfer' do let(:arg_info) do get_method_introspection_data('Regress', 'TestObj', 'null_out').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :pointer'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = Regress::TestObj.wrap(_v1.get_pointer(0))'] end end describe 'with no ownership transfer' do let(:arg_info) do get_method_introspection_data('GIMarshallingTests', 'Object', 'none_out').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :pointer'] end it 'has the correct value for #post_conversion' do builder.post_conversion. must_equal ['_v2 = GIMarshallingTests::Object.wrap(_v1.get_pointer(0)).tap { |it| it && it.ref }'] end end end describe 'for :struct' do describe 'when not allocated by the caller' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'boxed_struct_out').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal [ '_v1 = FFI::MemoryPointer.new :pointer' ] end it 'has the correct value for #post_conversion' do builder.post_conversion. must_equal ['_v2 = GIMarshallingTests::BoxedStruct.wrap_copy(_v1.get_pointer(0))'] end end describe 'when allocated by the caller' do let(:arg_info) do get_method_introspection_data('Regress', 'TestStructA', 'clone').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = Regress::TestStructA.new'] end it 'has empty #post_conversion' do builder.post_conversion.must_equal [] end end end describe 'for :strv' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'gstrv_out').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :pointer'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GLib::Strv.wrap(_v1.get_pointer(0))'] end end describe 'for :array' do describe 'when allocated by the callee' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'garray_utf8_none_out').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :pointer'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GLib::Array.wrap(:utf8, _v1.get_pointer(0))'] end end describe 'when allocated by the caller' do let(:function_info) do get_introspection_data('GIMarshallingTests', 'garray_utf8_full_out_caller_allocated') end let(:arg_info) { function_info.args[0] } before do skip unless function_info end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = GLib::Array.new :utf8'] end it 'has empty #post_conversion' do builder.post_conversion.must_equal [] end end end describe 'for :ptr_array' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'gptrarray_utf8_none_out').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :pointer'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GLib::PtrArray.wrap(:utf8, _v1.get_pointer(0))'] end end describe 'for :error' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'gerror_out').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :pointer'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GLib::Error.wrap(_v1.get_pointer(0))'] end end describe 'for :c' do describe 'with fixed size' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'array_fixed_out').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :pointer'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GirFFI::SizedArray.wrap(:gint32, 4, _v1.get_pointer(0))'] end end describe 'with separate size parameter' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'array_out').args[0] end let(:length_argument) { Object.new } before do allow(length_argument).to receive(:post_converted_name).and_return 'bar' builder.length_arg = length_argument end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :pointer'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GirFFI::SizedArray.wrap(:gint32, bar, _v1.get_pointer(0))'] end end end describe 'for :glist' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'glist_utf8_none_out').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :pointer'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GLib::List.wrap(:utf8, _v1.get_pointer(0))'] end end describe 'for :gslist' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'gslist_utf8_none_out').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :pointer'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GLib::SList.wrap(:utf8, _v1.get_pointer(0))'] end end describe 'for :ghash' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'ghashtable_utf8_none_out').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :pointer'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GLib::HashTable.wrap([:utf8, :utf8], _v1.get_pointer(0))'] end end describe 'for :utf8' do describe 'with full ownership transfer' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'utf8_full_out').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :pointer'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal [ '_v2 = GirFFI::AllocationHelper.free_after _v1.get_pointer(0), &:to_utf8' ] end it 'has the correct value for #return_value_name' do builder.post_conversion builder.return_value_name.must_equal '_v2' end end describe 'with no ownership transfer' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'utf8_none_out').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :pointer'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = _v1.get_pointer(0).to_utf8'] end end end describe 'for :void' do let(:function_info) do get_introspection_data('Everything', 'one_outparam_gpointer') end let(:arg_info) { function_info.args[0] } before do skip unless function_info end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :pointer'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = _v1.get_pointer(0)'] end end end describe 'for an argument with direction :inout' do describe 'for :enum' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'enum_inout').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new GIMarshallingTests::Enum', "GIMarshallingTests::Enum.copy_value_to_pointer(#{arg_info.name}, _v1)"] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GIMarshallingTests::Enum.get_value_from_pointer(_v1, 0)'] end end describe 'for :flags' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'no_type_flags_inout').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion. must_equal ['_v1 = FFI::MemoryPointer.new GIMarshallingTests::NoTypeFlags', "GIMarshallingTests::NoTypeFlags.copy_value_to_pointer(#{arg_info.name}, _v1)"] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GIMarshallingTests::NoTypeFlags.get_value_from_pointer(_v1, 0)'] end end describe 'for :gint32' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'int32_inout_min_max').args[0] end it 'has the correct value for method_argument_name' do builder.method_argument_name.must_equal arg_info.name end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :int32', "_v1.put_int32 0, #{arg_info.name}"] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = _v1.get_int32(0)'] end end describe 'for an array length' do let(:function_info) do get_introspection_data('Regress', 'test_array_int_inout') end let(:arg_info) { function_info.args[0] } let(:array_arg_info) { function_info.args[1] } let(:array_arg_builder) do GirFFI::Builders::ArgumentBuilder.new(var_gen, array_arg_info) end before do builder.array_arg = array_arg_builder end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['n_ints = ints.nil? ? 0 : ints.length', '_v1 = FFI::MemoryPointer.new :int32', '_v1.put_int32 0, n_ints'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = _v1.get_int32(0)'] end end describe 'for :strv' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'gstrv_inout').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :pointer', '_v1.put_pointer 0, GLib::Strv.from(g_strv)'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GLib::Strv.wrap(_v1.get_pointer(0))'] end end describe 'for :ptr_array' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'gptrarray_utf8_none_inout').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :pointer', '_v1.put_pointer 0, GLib::PtrArray.from(:utf8, parray_)'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GLib::PtrArray.wrap(:utf8, _v1.get_pointer(0))'] end end describe 'for :utf8' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'utf8_none_inout').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :pointer', '_v1.put_pointer 0, GirFFI::InPointer.from_utf8(utf8)'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = _v1.get_pointer(0).to_utf8'] end end describe 'for :struct' do describe 'with full ownership transfer' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'boxed_struct_inout').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal [ '_v1 = FFI::MemoryPointer.new :pointer', '_v1.put_pointer 0, GIMarshallingTests::BoxedStruct.copy_from(struct_)' ] end it 'has the correct value for #post_conversion' do builder.post_conversion. must_equal ['_v2 = GIMarshallingTests::BoxedStruct.wrap_own(_v1.get_pointer(0))'] end end end describe 'for :c' do describe 'with fixed size' do let(:arg_info) do get_introspection_data('GIMarshallingTests', 'array_fixed_inout').args[0] end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal [ 'GirFFI::ArgHelper.check_fixed_array_size 4, ints, "ints"', '_v1 = FFI::MemoryPointer.new :pointer', '_v1.put_pointer 0, GirFFI::SizedArray.from(:gint32, 4, ints)' ] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GirFFI::SizedArray.wrap(:gint32, 4, _v1.get_pointer(0))'] end end describe 'with separate size parameter' do let(:function_info) do get_introspection_data('Regress', 'test_array_int_inout') end let(:length_arg_info) { function_info.args[0] } let(:arg_info) { function_info.args[1] } let(:length_arg_builder) do GirFFI::Builders::ArgumentBuilder.new(var_gen, length_arg_info) end before do builder.length_arg = length_arg_builder end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal [ '_v1 = FFI::MemoryPointer.new :pointer', '_v1.put_pointer 0, GirFFI::SizedArray.copy_from(:gint32, -1, ints)' ] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v3 = GirFFI::SizedArray.wrap(:gint32, _v2, _v1.get_pointer(0))'] end end end end describe 'for a skipped argument with direction :in' do let(:arg_info) do get_method_introspection_data('Regress', 'TestObj', 'skip_param').args[2] end it 'has the correct value for method_argument_name' do builder.method_argument_name.must_be_nil end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = 0'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal [] end end describe 'for a skipped argument with direction :inout' do let(:arg_info) do get_method_introspection_data('Regress', 'TestObj', 'skip_inout_param').args[3] end it 'has the correct value for method_argument_name' do builder.method_argument_name.must_be_nil end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :int32', '_v1.put_int32 0, 0'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal [] end end describe 'for a skipped argument with direction :out' do let(:arg_info) do get_method_introspection_data('Regress', 'TestObj', 'skip_out_param').args[1] end it 'has the correct value for method_argument_name' do builder.method_argument_name.must_be_nil end it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal ['_v1 = FFI::MemoryPointer.new :int32'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal [] end end describe 'for an argument with direction :error' do let(:arg_info) { GirFFI::ErrorArgumentInfo.new } it 'has the correct value for #pre_conversion' do builder.pre_conversion.must_equal [ '_v1 = FFI::MemoryPointer.new(:pointer).write_pointer nil' ] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal [ 'GirFFI::ArgHelper.check_error(_v1)' ] end end end gir_ffi-0.11.4/test/gir_ffi/builders/callback_return_value_builder_test.rb0000644000004100000410000000524513170036060027052 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::CallbackReturnValueBuilder do let(:var_gen) { GirFFI::VariableNameGenerator.new } let(:return_value_info) { GirFFI::ReturnValueInfo.new(type_info, ownership_transfer, false) } let(:type_info) { callback_info.return_type } let(:ownership_transfer) { callback_info.caller_owns } let(:builder) do GirFFI::Builders::CallbackReturnValueBuilder.new(var_gen, return_value_info) end before do skip unless callback_info end describe 'for :gint32' do let(:callback_info) { get_introspection_data('GIMarshallingTests', 'CallbackIntInt') } it 'has no statements in #post_conversion' do builder.post_conversion.must_equal [] end it 'returns the result of the callback directly' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v1' end end describe 'for :void' do let(:callback_info) do get_introspection_data('GIMarshallingTests', 'CallbackMultipleOutParameters') end it 'has no statements in #post_conversion' do builder.post_conversion.must_equal [] end it 'returns nothing' do builder.capture_variable_name.must_be_nil builder.return_value_name.must_be_nil end end describe 'for :enum' do let(:callback_info) do get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'vfunc_return_enum') end it 'converts the result' do # Ensure variable names are generated in order builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v2 = GIMarshallingTests::Enum.from(_v1)'] end it 'returns the result of the conversion' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end describe 'for :object with full transfer' do let(:callback_info) do get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'vfunc_return_object_transfer_full') end it 'increases the refcount of the result and converts it to a pointer' do # Ensure variable names are generated in order builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v1.ref', '_v2 = GObject::Object.from(_v1).to_ptr'] end it 'returns the result of the conversion' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end end gir_ffi-0.11.4/test/gir_ffi/builders/function_builder_test.rb0000644000004100000410000004710713170036060024353 0ustar www-datawww-data# frozen_string_literal: true 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 'generally' do let(:function_info) { get_method_introspection_data 'GObject', 'Object', 'get_property' } it 'returns the same result when called twice' do original = builder.method_definition copy = builder.method_definition copy.must_equal original end end 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 = FFI::MemoryPointer.new :pointer Regress::Lib.regress_test_array_fixed_out_objects _v1 _v2 = GirFFI::SizedArray.wrap([:pointer, Regress::TestObj], 2, _v1.get_pointer(0)) 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 methods taking a zero-terminated array with length argument' do let(:function_info) { get_method_introspection_data 'Regress', 'AnnotationObject', 'parse_args' } it 'builds a correct definition' do skip unless function_info code.must_equal <<-CODE.reset_indentation def parse_args(argv) argc = argv.nil? ? 0 : argv.length _v1 = FFI::MemoryPointer.new :int32 _v1.put_int32 0, argc _v2 = FFI::MemoryPointer.new :pointer _v2.put_pointer 0, GLib::Strv.from(argv) Regress::Lib.regress_annotation_object_parse_args self, _v1, _v2 _v3 = GLib::Strv.wrap(_v2.get_pointer(0)) 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::ArgHelper.store(_v1) _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 = FFI::MemoryPointer.new :pointer GIMarshallingTests::Lib.gi_marshalling_tests_gvalue_out _v1 _v2 = GObject::Value.wrap(_v1.get_pointer(0)).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 = nil) 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 = FFI::MemoryPointer.new :int32 _v2 = FFI::MemoryPointer.new :pointer Regress::Lib.regress_test_array_int_null_out _v2, _v1 _v3 = _v1.get_int32(0) _v4 = GirFFI::SizedArray.wrap(:gint32, _v3, _v2.get_pointer(0)) 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 = FFI::MemoryPointer.new :int32 _v1.put_int32 0, length _v2 = FFI::MemoryPointer.new :pointer _v2.put_pointer 0, GirFFI::SizedArray.from(:gint32, -1, ints) GIMarshallingTests::Lib.gi_marshalling_tests_object_method_array_inout self, _v2, _v1 _v3 = _v1.get_int32(0) _v4 = GirFFI::SizedArray.wrap(:gint32, _v3, _v2.get_pointer(0)) 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 = ":uint#{FFI.type_size(:size_t) * 8}" code.must_equal <<-CODE.reset_indentation def get_strv _v1 = FFI::MemoryPointer.new #{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 = FFI::MemoryPointer.new :pointer GIMarshallingTests::Lib.gi_marshalling_tests_object_method_int8_arg_and_out_callee self, _v1, _v2 _v3 = _v2.get_pointer(0).get_int8(0) return _v3 end CODE end end describe 'object ownership transfer' do describe 'for GIMarshallingTests::Object#full_in' do let(:function_info) do get_method_introspection_data('GIMarshallingTests', 'Object', 'full_in') end # NOTE: This method is transfer-ownership: none, despite the name. it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def full_in GIMarshallingTests::Lib.gi_marshalling_tests_object_full_in self 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 = FFI::MemoryPointer.new :pointer _v1.put_pointer 0, GIMarshallingTests::Object.from(object && object.ref) GIMarshallingTests::Lib.gi_marshalling_tests_object_full_inout _v1 _v2 = GIMarshallingTests::Object.wrap(_v1.get_pointer(0)) return _v2 end CODE end end describe 'for GIMarshallingTests::Object.full_out' do let(:function_info) do get_method_introspection_data('GIMarshallingTests', 'Object', 'full_out') end it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def self.full_out _v1 = FFI::MemoryPointer.new :pointer GIMarshallingTests::Lib.gi_marshalling_tests_object_full_out _v1 _v2 = GIMarshallingTests::Object.wrap(_v1.get_pointer(0)) return _v2 end CODE end end describe 'for GIMarshallingTests::Object.full_return' do let(:function_info) do get_method_introspection_data('GIMarshallingTests', 'Object', 'full_return') end it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def self.full_return _v1 = GIMarshallingTests::Lib.gi_marshalling_tests_object_full_return _v2 = GIMarshallingTests::Object.wrap(_v1) return _v2 end CODE end end describe 'for GIMarshallingTests::Object#none_in' do let(:function_info) do get_method_introspection_data('GIMarshallingTests', 'Object', 'none_in') end it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def none_in GIMarshallingTests::Lib.gi_marshalling_tests_object_none_in self end CODE end end describe 'for GIMarshallingTests::Object.none_inout' do let(:function_info) do get_method_introspection_data('GIMarshallingTests', 'Object', 'none_inout') end it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def self.none_inout(object) _v1 = FFI::MemoryPointer.new :pointer _v1.put_pointer 0, GIMarshallingTests::Object.from(object) GIMarshallingTests::Lib.gi_marshalling_tests_object_none_inout _v1 _v2 = GIMarshallingTests::Object.wrap(_v1.get_pointer(0)).tap { |it| it && it.ref } return _v2 end CODE end end describe 'for GIMarshallingTests::Object.none_out' do let(:function_info) do get_method_introspection_data('GIMarshallingTests', 'Object', 'none_out') end it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def self.none_out _v1 = FFI::MemoryPointer.new :pointer GIMarshallingTests::Lib.gi_marshalling_tests_object_none_out _v1 _v2 = GIMarshallingTests::Object.wrap(_v1.get_pointer(0)).tap { |it| it && it.ref } return _v2 end CODE end end describe 'for GIMarshallingTests::Object.none_return' do let(:function_info) do get_method_introspection_data('GIMarshallingTests', 'Object', 'none_return') end it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def self.none_return _v1 = GIMarshallingTests::Lib.gi_marshalling_tests_object_none_return _v2 = GIMarshallingTests::Object.wrap(_v1).tap { |it| it && it.ref } 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 describe 'struct ownership transfer' do describe 'for GIMarshallingTests::BoxedStruct.inout' do let(:function_info) do get_method_introspection_data('GIMarshallingTests', 'BoxedStruct', 'inout') end it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def self.inout(struct_) _v1 = FFI::MemoryPointer.new :pointer _v1.put_pointer 0, GIMarshallingTests::BoxedStruct.copy_from(struct_) GIMarshallingTests::Lib.gi_marshalling_tests_boxed_struct_inout _v1 _v2 = GIMarshallingTests::BoxedStruct.wrap_own(_v1.get_pointer(0)) return _v2 end CODE end end describe 'for GIMarshallingTests::BoxedStruct.out' do let(:function_info) do get_method_introspection_data('GIMarshallingTests', 'BoxedStruct', 'out') end it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def self.out _v1 = FFI::MemoryPointer.new :pointer GIMarshallingTests::Lib.gi_marshalling_tests_boxed_struct_out _v1 _v2 = GIMarshallingTests::BoxedStruct.wrap_copy(_v1.get_pointer(0)) return _v2 end CODE end end describe 'for GIMarshallingTests::BoxedStruct.returnv' do let(:function_info) do get_method_introspection_data('GIMarshallingTests', 'BoxedStruct', 'returnv') end it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def self.returnv _v1 = GIMarshallingTests::Lib.gi_marshalling_tests_boxed_struct_returnv _v2 = GIMarshallingTests::BoxedStruct.wrap_copy(_v1) return _v2 end CODE end end end describe 'string ownership transfer' do describe 'for Regress.test_utf8_out' do let(:function_info) { get_introspection_data 'Regress', 'test_utf8_out' } it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def self.test_utf8_out _v1 = FFI::MemoryPointer.new :pointer Regress::Lib.regress_test_utf8_out _v1 _v2 = GirFFI::AllocationHelper.free_after _v1.get_pointer(0), &:to_utf8 return _v2 end CODE end end end describe 'for functions with an allow-none ingoing parameter' do let(:function_info) { get_introspection_data 'Regress', 'test_utf8_null_in' } it 'builds correct definition with default parameter value' do code.must_equal <<-CODE.reset_indentation def self.test_utf8_null_in(in_ = nil) _v1 = GirFFI::InPointer.from_utf8(in_) Regress::Lib.regress_test_utf8_null_in _v1 end CODE end end describe 'for functions where some allow-none cannot be honored' do let(:function_info) { get_introspection_data 'GIMarshallingTests', 'array_in_utf8_two_in_out_of_order' } it 'builds correct definition with default parameter value on the later arguments' do code.must_equal <<-CODE.reset_indentation def self.array_in_utf8_two_in_out_of_order(a, ints, b = nil) length = ints.nil? ? 0 : ints.length _v1 = length _v2 = GirFFI::InPointer.from_utf8(a) _v3 = GirFFI::InPointer.from_utf8(b) _v4 = GirFFI::SizedArray.from(:gint32, -1, ints) GIMarshallingTests::Lib.gi_marshalling_tests_array_in_utf8_two_in_out_of_order _v1, _v2, _v4, _v3 end CODE end end describe 'ownership transfer for an ingoing array of structs' do describe 'with no ownership transfer of the elements' do let(:function_info) { get_introspection_data 'GIMarshallingTests', 'array_struct_in' } it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def self.array_struct_in(structs) length = structs.nil? ? 0 : structs.length _v1 = length _v2 = GirFFI::SizedArray.from([:pointer, GIMarshallingTests::BoxedStruct], -1, structs) GIMarshallingTests::Lib.gi_marshalling_tests_array_struct_in _v2, _v1 end CODE end end describe 'with ownership transfer of the elements' do let(:function_info) { get_introspection_data 'GIMarshallingTests', 'array_struct_take_in' } it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def self.array_struct_take_in(structs) length = structs.nil? ? 0 : structs.length _v1 = length _v2 = GirFFI::SizedArray.copy_from([:pointer, GIMarshallingTests::BoxedStruct], -1, structs) GIMarshallingTests::Lib.gi_marshalling_tests_array_struct_take_in _v2, _v1 end CODE end end end end end gir_ffi-0.11.4/test/gir_ffi/builders/return_value_builder_test.rb0000644000004100000410000003227313170036060025237 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::ReturnValueBuilder do let(:var_gen) { GirFFI::VariableNameGenerator.new } let(:type_info) { method_info.return_type } let(:ownership_transfer) { method_info.caller_owns } let(:return_type_info) { GirFFI::ReturnValueInfo.new(type_info, ownership_transfer, false) } let(:builder) do GirFFI::Builders::ReturnValueBuilder.new(var_gen, return_type_info) end describe 'for :gint32' do let(:method_info) do get_introspection_data('GIMarshallingTests', 'int_return_min') end it 'has no statements in #post_conversion' do builder.post_conversion.must_equal [] end it 'returns the result of the c function directly' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v1' end end describe 'for :struct' do describe 'with transfer :nothing' do let(:method_info) do get_method_introspection_data('GIMarshallingTests', 'BoxedStruct', 'returnv') end it 'wraps and copies the result in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v2 = GIMarshallingTests::BoxedStruct.wrap_copy(_v1)'] end it 'returns the copied result' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end end describe 'for :union' do let(:method_info) do get_method_introspection_data('GIMarshallingTests', 'Union', 'returnv') end it 'wraps the result in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v2 = GIMarshallingTests::Union.wrap_copy(_v1)'] end it 'returns the wrapped result' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end describe 'for :interface' do let(:method_info) do get_method_introspection_data('Gio', 'File', 'new_for_commandline_arg') end it 'wraps the result in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v2 = Gio::File.wrap(_v1)'] end it 'returns the wrapped result' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end describe 'for :object' do describe 'with full ownership transfer' do let(:method_info) do get_method_introspection_data('GIMarshallingTests', 'Object', 'full_return') end it 'wraps the result in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v2 = GIMarshallingTests::Object.wrap(_v1)'] end it 'returns the wrapped result' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end describe 'with no ownership transfer' do let(:method_info) do get_method_introspection_data('GIMarshallingTests', 'Object', 'none_return') end it 'wraps the result in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion. must_equal ['_v2 = GIMarshallingTests::Object.wrap(_v1).tap { |it| it && it.ref }'] end it 'returns the wrapped result' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end end describe 'for :strv' do let(:method_info) do get_method_introspection_data('GLib', 'KeyFile', 'get_locale_string_list') end it 'wraps the result in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v2 = GLib::Strv.wrap(_v1)'] end it 'returns the wrapped result' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end describe 'for :zero_terminated' do let(:method_info) do get_method_introspection_data('GLib', 'Variant', 'dup_bytestring') end before do skip unless type_info.zero_terminated? end it 'wraps the result in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v2 = GirFFI::ZeroTerminated.wrap(:guint8, _v1)'] end it 'returns the wrapped result' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end describe 'for :byte_array' do let(:method_info) do get_introspection_data('GIMarshallingTests', 'bytearray_full_return') end it 'wraps the result in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v2 = GLib::ByteArray.wrap(_v1)'] end it 'returns the wrapped result' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end describe 'for :ptr_array' do let(:method_info) do get_introspection_data('GIMarshallingTests', 'gptrarray_utf8_none_return') end it 'wraps the result in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v2 = GLib::PtrArray.wrap(:utf8, _v1)'] end it 'returns the wrapped result' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end describe 'for :glist' do let(:method_info) do get_introspection_data('GIMarshallingTests', 'glist_int_none_return') end it 'wraps the result in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v2 = GLib::List.wrap(:gint32, _v1)'] end it 'returns the wrapped result' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end describe 'for :gslist' do let(:method_info) do get_introspection_data('GIMarshallingTests', 'gslist_int_none_return') end it 'wraps the result in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v2 = GLib::SList.wrap(:gint32, _v1)'] end it 'returns the wrapped result' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end describe 'for :ghash' do let(:method_info) do get_introspection_data('GIMarshallingTests', 'ghashtable_int_none_return') end it 'wraps the result in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v2 = GLib::HashTable.wrap([:gint32, :gint32], _v1)'] end it 'returns the wrapped result' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end describe 'for :array' do let(:method_info) do get_introspection_data('GIMarshallingTests', 'garray_int_none_return') end it 'wraps the result in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v2 = GLib::Array.wrap(:gint32, _v1)'] end it 'returns the wrapped result' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end describe 'for :error' do let(:method_info) do get_introspection_data('GIMarshallingTests', 'gerror_return') end it 'wraps the result in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v2 = GLib::Error.wrap(_v1)'] end it 'returns the wrapped result' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end describe 'for :c' do describe 'with fixed size' do let(:method_info) do get_introspection_data('GIMarshallingTests', 'array_fixed_int_return') end it 'converts the result in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v2 = GirFFI::SizedArray.wrap(:gint32, 4, _v1)'] end it 'returns the wrapped result' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end describe 'with separate size parameter' do let(:length_argument) { Object.new } let(:method_info) do get_method_introspection_data('GIMarshallingTests', 'Object', 'method_array_return') end before do allow(length_argument).to receive(:post_converted_name).and_return 'bar' builder.length_arg = length_argument end it 'converts the result in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v2 = GirFFI::SizedArray.wrap(:gint32, bar, _v1)'] end it 'returns the wrapped result' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end end describe 'for :utf8' do describe 'with no transfer' do let(:method_info) do get_introspection_data('GIMarshallingTests', 'utf8_none_return') end it 'converts the result in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v2 = _v1.to_utf8'] end it 'returns the converted result' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end describe 'with full transfer' do let(:method_info) do get_introspection_data('GIMarshallingTests', 'utf8_full_return') end it 'autoreleases and converts the result in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion. must_equal ['_v2 = GirFFI::AllocationHelper.free_after _v1, &:to_utf8'] end it 'returns the converted result' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end end describe 'for :void pointer' do let(:ownership_transfer) { :nothing } let(:callback_info) do get_introspection_data('GIMarshallingTests', 'CallbackIntInt') end let(:type_info) { callback_info.args[1].argument_type } before do skip unless callback_info end it 'has no statements in #post_conversion' do builder.post_conversion.must_equal [] end it 'returns the result of the c function directly' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v1' end end describe 'for :void' do let(:method_info) do get_method_introspection_data('Regress', 'TestObj', 'null_out') end it 'has no statements in #post_conversion' do builder.post_conversion.must_equal [] end it 'marks itself as irrelevant' do builder.relevant?.must_equal false end it 'returns nothing' do builder.return_value_name.must_be_nil end end describe 'for a closure argument' do let(:ownership_transfer) { :nothing } let(:callback_info) do get_introspection_data('Regress', 'TestCallbackUserData') end let(:type_info) { callback_info.args[0].argument_type } before do builder.closure = true end it 'fetches the stored object in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v2 = GirFFI::ArgHelper::OBJECT_STORE.fetch(_v1)'] end it 'returns the stored object' do builder.capture_variable_name.must_equal '_v1' builder.return_value_name.must_equal '_v2' end end describe 'for a skipped return value' do let(:method_info) do get_method_introspection_data('Regress', 'TestObj', 'skip_return_val') end let(:return_type_info) { GirFFI::ReturnValueInfo.new(type_info, :nothing, true) } it 'has no statements in #post_conversion' do builder.post_conversion.must_equal [] end it 'marks itself as irrelevant' do builder.relevant?.must_equal false end it 'returns nothing' do builder.return_value_name.must_be_nil end end end gir_ffi-0.11.4/test/gir_ffi/builders/base_argument_builder_test.rb0000644000004100000410000000016413170036060025332 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::BaseArgumentBuilder do end gir_ffi-0.11.4/test/gir_ffi/builders/module_builder_test.rb0000644000004100000410000000255513170036060024011 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::ModuleBuilder do let(:gir) { GObjectIntrospection::IRepository.default } describe '#find_namespaced_class_info' do it 'finds the info in the GIR' do allow(gir).to receive(:require).with('Foo', nil) builder = GirFFI::Builders::ModuleBuilder.new 'Foo' expect(gir).to receive(:find_by_name).with('Foo', 'Bar').and_return 'gir info' builder.find_namespaced_class_info(:Bar).must_equal 'gir info' end it 'checks downcased class name as an alternative' do allow(gir).to receive(:require).with('Foo', nil) builder = GirFFI::Builders::ModuleBuilder.new 'Foo' expect(gir).to receive(:find_by_name).with('Foo', 'Bar').and_return nil expect(gir).to receive(:find_by_name).with('Foo', 'bar').and_return 'gir info' builder.find_namespaced_class_info(:Bar).must_equal 'gir info' end it 'raises a clear error if the named class does not exist' do allow(gir).to receive(:require).with('Foo', nil) builder = GirFFI::Builders::ModuleBuilder.new 'Foo' expect(gir).to receive(:find_by_name).with('Foo', 'Bar').and_return nil expect(gir).to receive(:find_by_name).with('Foo', 'bar').and_return nil assert_raises NameError do builder.find_namespaced_class_info :Bar end end end end gir_ffi-0.11.4/test/gir_ffi/builders/registered_type_builder_test.rb0000644000004100000410000000164413170036060025720 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :Regress describe GirFFI::Builders::RegisteredTypeBuilder do describe '#setup_instance_method' do it 'restores a method that was removed' do Regress::TestObj.class_eval { remove_method 'instance_method' } builder = Regress::TestObj.gir_ffi_builder builder.setup_instance_method 'instance_method' obj = Regress::TestObj.constructor obj.must_respond_to 'instance_method' end it 'returns the name of the generated method' do builder = Regress::TestObj.gir_ffi_builder result = builder.setup_instance_method 'instance_method' result.must_equal 'instance_method' end it 'returns the name of the generated method if different from the info name' do builder = GLib::IConv.gir_ffi_builder result = builder.setup_instance_method '' result.must_equal '_' end end end gir_ffi-0.11.4/test/gir_ffi/builders/enum_builder_test.rb0000644000004100000410000000100713170036060023457 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::EnumBuilder do describe 'creating Regress::TestEnum' do before do save_module :Regress end it 'makes the created type know its proper name' do info = get_introspection_data 'Regress', 'TestEnum' builder = GirFFI::Builders::EnumBuilder.new info enum = builder.build_class enum.inspect.must_equal 'Regress::TestEnum' end after do restore_module :Regress end end end gir_ffi-0.11.4/test/gir_ffi/builders/callback_builder_test.rb0000644000004100000410000000735313170036060024261 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::CallbackBuilder do let(:builder) { GirFFI::Builders::CallbackBuilder.new callback_info } describe '#mapping_method_definition' do describe 'for a callback with arguments and return value' do let(:callback_info) { get_introspection_data 'Regress', 'TestCallbackFull' } it 'returns a valid mapping method' do expected = <<-CODE.reset_indentation def self.call_with_argument_mapping(_proc, foo, bar, path) _v1 = foo _v2 = bar _v3 = path.to_utf8 _v4 = _proc.call(_v1, _v2, _v3) return _v4 end CODE builder.mapping_method_definition.must_equal expected end end describe 'for a callback with no arguments or return value' do let(:callback_info) { get_introspection_data 'Regress', 'TestSimpleCallback' } it 'returns a valid mapping method' do expected = <<-CODE.reset_indentation def self.call_with_argument_mapping(_proc) _proc.call() end CODE builder.mapping_method_definition.must_equal expected end end describe 'for a callback with a closure argument' do let(:callback_info) { get_introspection_data 'Regress', 'TestCallbackUserData' } it 'returns a valid mapping method' do expected = <<-CODE.reset_indentation def self.call_with_argument_mapping(_proc, user_data) _v1 = GirFFI::ArgHelper::OBJECT_STORE.fetch(user_data) _v2 = _proc.call(_v1) return _v2 end CODE builder.mapping_method_definition.must_equal expected end end describe 'for a callback with one out argument' do let(:callback_info) do get_introspection_data('GIMarshallingTests', 'CallbackOneOutParameter') end it 'returns a valid mapping method' do expected = <<-CODE.reset_indentation def self.call_with_argument_mapping(_proc, a) _v1 = a _v2 = _proc.call() _v1.put_float 0, _v2 end CODE builder.mapping_method_definition.must_equal expected end end describe 'for a callback with an inout array argument' do let(:callback_info) do get_introspection_data('Regress', 'TestCallbackArrayInOut') end 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 = length _v2 = _v1.get_int32(0) _v3 = ints _v4 = GirFFI::SizedArray.wrap(:gint32, _v2, _v3.get_pointer(0)) _v5 = _proc.call(_v4) _v1.put_int32 0, _v5.length _v3.put_pointer 0, GirFFI::SizedArray.from(:gint32, -1, _v5) end CODE builder.mapping_method_definition.must_equal expected end end describe 'for a callback with a value in argument' do let(:field_info) do get_field_introspection_data('GObject', 'ObjectClass', 'get_property') end let(:callback_info) do field_info.field_type.interface end it 'returns a valid mapping method' do expected = <<-CODE.reset_indentation def self.call_with_argument_mapping(_proc, object, property_id, value, pspec) _v1 = GObject::Object.wrap(object) _v2 = property_id _v3 = GObject::Value.wrap(value) _v4 = GObject::ParamSpec.wrap(pspec) _proc.call(_v1, _v2, _v3, _v4) end CODE builder.mapping_method_definition.must_equal expected end end end end gir_ffi-0.11.4/test/gir_ffi/builders/interface_builder_test.rb0000644000004100000410000000152313170036060024456 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::InterfaceBuilder do let(:interface_builder) do GirFFI::Builders::InterfaceBuilder.new( get_introspection_data('Regress', 'TestInterface')) end describe '#build_class' do before do info = get_introspection_data 'GObject', 'TypePlugin' @bldr = GirFFI::Builders::InterfaceBuilder.new info @iface = @bldr.build_class end it 'builds an interface as a module' do assert_instance_of Module, @iface end it 'creates methods on the interface' do assert_defines_instance_method @iface, :complete_interface_info end end describe '#interface_struct' do it 'returns the interface struct type' do interface_builder.interface_struct.must_equal Regress::TestInterfaceIface end end end gir_ffi-0.11.4/test/gir_ffi/builders/object_builder_test.rb0000644000004100000410000000670213170036060023770 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::Builders::ObjectBuilder do let(:obj_builder) do GirFFI::Builders::ObjectBuilder.new( get_introspection_data('Regress', 'TestObj')) end let(:sub_obj_builder) do GirFFI::Builders::ObjectBuilder.new( get_introspection_data('Regress', 'TestSubObj')) end let(:param_spec_builder) do GirFFI::Builders::ObjectBuilder.new( get_introspection_data('GObject', 'ParamSpec')) end describe '#find_signal' do it 'finds the signal "test" for TestObj' do sig = obj_builder.find_signal 'test' sig.name.must_equal 'test' end it 'finds the signal "test" for TestSubObj' do sig = sub_obj_builder.find_signal 'test' sig.name.must_equal 'test' end it 'finds the signal "changed" for Gtk::Entry' do builder = GirFFI::Builders::ObjectBuilder.new get_introspection_data('Gtk', 'Entry') sig = builder.find_signal 'changed' sig.name.must_equal 'changed' end it "returns nil for a signal that doesn't exist" do obj_builder.find_signal('foo').must_be_nil end end describe '#find_property' do it 'finds a property specified on the class itself' do prop = obj_builder.find_property('int') prop.name.must_equal 'int' end it 'finds a property specified on the parent class' do prop = sub_obj_builder.find_property('int') prop.name.must_equal 'int' end it 'returns nil if the property is not found' do sub_obj_builder.find_property('this-property-does-not-exist').must_be_nil end end describe '#object_class_struct' do it 'returns the class struct type' do obj_builder.object_class_struct.must_equal Regress::TestObjClass end it 'returns the parent struct type for classes without their own struct' do binding_info = get_introspection_data 'GObject', 'Binding' builder = GirFFI::Builders::ObjectBuilder.new binding_info builder.object_class_struct.must_equal GObject::ObjectClass end end describe 'for a struct without defined fields' do let(:info) { get_introspection_data 'GObject', 'Binding' } it 'uses a single field of the parent struct type as the default layout' do info.n_fields.must_equal 0 builder = GirFFI::Builders::ObjectBuilder.new info spec = builder.send :layout_specification assert_equal [:parent, GObject::Object::Struct, 0], spec end end describe '#eligible_fields' do it 'skips fields that have a matching getter method' do result = param_spec_builder.eligible_fields result.map(&:name).wont_include 'name' end it 'skips fields that have a matching property' do result = obj_builder.eligible_fields result.map(&:name).wont_include 'hash_table' end it 'skips the parent instance field' do result = obj_builder.eligible_fields result.map(&:name).wont_include 'parent_instance' end end describe '#eligible_properties' do let(:wi_builder) do GirFFI::Builders::ObjectBuilder.new( get_introspection_data('Regress', 'TestWi8021x')) end it 'includes properties that do not have a matching getter method' do result = obj_builder.eligible_properties result.map(&:name).must_include 'double' end it 'skips properties that have a matching getter method' do result = wi_builder.eligible_properties result.map(&:name).wont_include 'testbool' end end end gir_ffi-0.11.4/test/gir_ffi/ffi_ext/0000755000004100000410000000000013170036060017236 5ustar www-datawww-datagir_ffi-0.11.4/test/gir_ffi/ffi_ext/pointer_test.rb0000644000004100000410000000131313170036060022300 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::FFIExt::Pointer do let(:klass) { Class.new { include GirFFI::FFIExt::Pointer } } describe '#to_object' do it 'finds the wrapping class by gtype and wraps the pointer in it' do ptr = klass.new expect(ptr).to receive(:null?).and_return false object_class = Class.new expect(GObject).to receive(:type_from_instance_pointer).with(ptr).and_return 0xdeadbeef expect(GirFFI::Builder).to receive(:build_by_gtype).with(0xdeadbeef).and_return object_class expect(object_class).to receive(:direct_wrap).with(ptr).and_return 'good-result' ptr.to_object.must_equal 'good-result' end end end gir_ffi-0.11.4/test/gir_ffi/object_store_test.rb0000644000004100000410000000171413170036060021663 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::ObjectStore do let(:store) { GirFFI::ObjectStore.new } describe '#store' do it 'returns a non-null pointer when storing objects' do obj = Object.new ptr = store.store obj ptr.wont_be :null? end it 'returns a null pointer when storing nil' do ptr = store.store nil ptr.must_be :null? end end describe '#fetch' do it 'returns the stored object when passed the key pointer' do obj = Object.new ptr = store.store obj result = store.fetch ptr result.must_equal obj end it 'returns the nil object when passed a null pointer' do ptr = FFI::Pointer.new(0) result = store.fetch ptr result.must_be_nil end it 'returns the pointer itself when passed an unknown pointer' do ptr = FFI::Pointer.new(42) result = store.fetch ptr result.must_equal ptr end end end gir_ffi-0.11.4/test/gir_ffi/callback_base_test.rb0000644000004100000410000000125213170036060021724 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::CallbackBase do describe '.store_callback' do it 'stores the passed in proc in CALLBACKS' do dummy_proc = 'some-callback' GirFFI::CallbackBase.store_callback dummy_proc GirFFI::CallbackBase::CALLBACKS[dummy_proc.object_id].must_equal dummy_proc end end describe '.drop_callback' do it 'removes the corresponding proc from CALLBACKS' do dummy_proc = 'some-callback' GirFFI::CallbackBase.store_callback dummy_proc GirFFI::CallbackBase.drop_callback dummy_proc GirFFI::CallbackBase::CALLBACKS[dummy_proc.object_id].must_be_nil end end end gir_ffi-0.11.4/test/gir_ffi/variable_name_generator_test.rb0000644000004100000410000000070413170036060024032 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' require 'gir_ffi/variable_name_generator' describe GirFFI::VariableNameGenerator do describe '#new_var' do it 'generates a sequence of predictable variable names' do gen = GirFFI::VariableNameGenerator.new assert_equal '_v1', gen.new_var assert_equal '_v2', gen.new_var assert_equal '_v3', gen.new_var assert_equal '_v4', gen.new_var end end end gir_ffi-0.11.4/test/gir_ffi/user_defined_object_info_test.rb0000644000004100000410000000644313170036060024202 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' require 'gir_ffi/user_defined_object_info' GirFFI.setup :GIMarshallingTests describe GirFFI::UserDefinedObjectInfo do describe '#described_class' do let(:info) { GirFFI::UserDefinedObjectInfo.new :some_class } it 'returns the class passed to #initialize' do info.described_class.must_equal :some_class end end describe '#install_property' do let(:info) { GirFFI::UserDefinedObjectInfo.new :some_class } let(:foo_spec) { Object.new } it 'adds the passed in property to the list of properties' do expect(foo_spec).to receive(:get_name).and_return :foo info.install_property foo_spec info.properties.map(&:name).must_equal [:foo] end end describe '#install_vfunc_implementation' do let(:info) { GirFFI::UserDefinedObjectInfo.new :some_class } let(:implementation) { Object.new } it 'adds to the list of vfunc implementations' do info.vfunc_implementations.must_equal [] info.install_vfunc_implementation :foo, implementation info.vfunc_implementations.map(&:name).must_equal [:foo] end it 'stores the passed-in implementation in the implementation object' do info.install_vfunc_implementation :foo, implementation impl = info.vfunc_implementations.first impl.implementation.must_equal implementation end it 'provides a default implementation' do info.install_vfunc_implementation :foo impl = info.vfunc_implementations.first impl.implementation.must_be_instance_of Proc end end describe '#initialize' do let(:foo_spec) { Object.new } let(:bar_spec) { Object.new } let(:info) do GirFFI::UserDefinedObjectInfo.new :some_class do |inf| inf.install_property foo_spec inf.install_property bar_spec end end before do expect(foo_spec).to receive(:get_name).and_return :foo expect(bar_spec).to receive(:get_name).and_return :bar end it 'yields the new object to the block passed' do info.properties.map(&:name).must_equal [:foo, :bar] end end describe '#g_name' do let(:klass) { Object.new } let(:info) { GirFFI::UserDefinedObjectInfo.new klass } before do allow(klass).to receive(:name).and_return 'foo' end it "returns the described class' name by default" do info.g_name.must_equal 'foo' end it 'returns the the name set by #g_name= if present' do info.g_name = 'bar' info.g_name.must_equal 'bar' end end describe '#find_method' do let(:klass) { Object.new } let(:info) { GirFFI::UserDefinedObjectInfo.new klass } it 'finds no methods' do info.find_method('foo').must_be_nil end end describe '#find_signal' do let(:klass) { Object.new } let(:info) { GirFFI::UserDefinedObjectInfo.new klass } it 'finds no signals' do info.find_signal('foo').must_be_nil end end describe '#interfaces' do let(:modul) { GIMarshallingTests::Interface } let(:klass) { Class.new GIMarshallingTests::Object } let(:info) { GirFFI::UserDefinedObjectInfo.new klass } before do klass.send :include, modul end it 'returns the interface infos for the include modules' do info.interfaces.must_equal [modul.gir_info] end end end gir_ffi-0.11.4/test/gir_ffi/core_test.rb0000644000004100000410000000575613170036060020143 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :GIMarshallingTests describe GirFFI::Core do it 'sets up cairo as Cairo' do GirFFI.setup :cairo assert Object.const_defined?(:Cairo) end it 'sets up xlib, which has no shared library' do gir = GObjectIntrospection::IRepository.default gir.require 'xlib' assert_nil gir.shared_library('xlib'), 'Precondition for test failed' GirFFI.setup :xlib end it 'sets up dependencies' do save_module :GObject save_module :Regress GirFFI.setup :Regress assert Object.const_defined?(:GObject) restore_module :Regress restore_module :GObject end describe '.setup' do it 'passes the desired version down to the module builder' do expect(GirFFI::Builder).to receive(:build_module).with('Regress', '0.1') GirFFI.setup :Regress, '0.1' end end describe '::define_type' do describe 'without a block' do before do @klass = Class.new GIMarshallingTests::OverridesObject Object.const_set "DerivedA#{Sequence.next}", @klass @gtype = GirFFI.define_type @klass end it 'returns a GType for the derived class' do parent_gtype = GIMarshallingTests::OverridesObject.gtype @gtype.wont_equal parent_gtype GObject.type_name(@gtype).must_equal @klass.name end it 'makes #gtype on the registered class return the new GType' do @klass.gtype.must_equal @gtype end it 'registers a type with the same size as the parent' do q = GObject.type_query @gtype q.instance_size.must_equal GIMarshallingTests::OverridesObject::Struct.size end it 'creates a struct class for the derived class with just one member' do @klass::Struct.members.must_equal [:parent] end it 'allows the new class to be instantiated' do obj = @klass.new type = GObject.type_from_instance obj type.must_equal @gtype end end describe 'with a block with a call to #install_property' do before do @klass = Class.new GIMarshallingTests::OverridesObject Object.const_set "DerivedB#{Sequence.next}", @klass @gtype = GirFFI.define_type @klass do |info| info.install_property GObject.param_spec_int('foo', 'foo bar', 'The Foo Bar Property', 10, 20, 15, 3) end end it 'registers a type that is bigger than the parent' do q = GObject.type_query @gtype q.instance_size.must_be :>, GIMarshallingTests::OverridesObject::Struct.size end it 'gives the types Struct the fields :parent and :foo' do @klass::Struct.members.must_equal [:parent, :foo] end it 'creates accessor functions for the property' do obj = @klass.new obj.foo = 13 obj.foo.must_equal 13 end end end end gir_ffi-0.11.4/test/gir_ffi/interface_base_test.rb0000644000004100000410000000077613170036060022142 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GirFFI::InterfaceBase do let(:interface) { Module.new { extend GirFFI::InterfaceBase } } describe '#wrap' do it 'delegates conversion to the wrapped pointer' do expect(ptr = Object.new).to receive(:to_object).and_return 'good-result' interface.wrap(ptr).must_equal 'good-result' end end describe '.to_ffi_type' do it 'returns :pointer' do interface.to_ffi_type.must_equal :pointer end end end gir_ffi-0.11.4/test/gir_ffi/g_type_test.rb0000644000004100000410000000144013170036060020464 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' require 'gir_ffi/g_type' describe GirFFI::GType do let(:gobject_gtype) { GObject::Object.gtype } let(:gobject_type_query) { GObject.type_query gobject_gtype } describe '#to_i' do it 'returns the integer gtype' do gt = GirFFI::GType.new(gobject_gtype) gt.to_i.must_equal gobject_gtype end end describe '#class_size' do it 'returns the class size for object types' do gt = GirFFI::GType.new(gobject_gtype) gt.class_size.must_equal gobject_type_query.class_size end end describe '#instance_size' do it 'returns the instance size for object types' do gt = GirFFI::GType.new(gobject_gtype) gt.instance_size.must_equal gobject_type_query.instance_size end end end gir_ffi-0.11.4/test/gir_ffi_test_helper.rb0000644000004100000410000000304113170036060020533 0ustar www-datawww-data# frozen_string_literal: true require 'introspection_test_helper' require 'gir_ffi' # Global sequence provider. Needed to make unique class names. class Sequence def self.next @seq ||= 0 @seq += + 1 end end module GirFFITestExtensions SAVED_MODULES = {} def save_module(name) return unless Object.const_defined? name puts "Saving #{name} over existing" if SAVED_MODULES.key? name SAVED_MODULES[name] = Object.const_get name Object.send(:remove_const, name) end def restore_module(name) if Object.const_defined? name Object.send(:remove_const, name) end return unless SAVED_MODULES.key? name Object.const_set name, SAVED_MODULES[name] SAVED_MODULES.delete name end def ref_count(ptr) GObject::Object::Struct.new(ptr)[:ref_count] end def max_for_unsigned_type(type) (1 << (FFI.type_size(type) * 8)) - 1 end def max_for_type(type) (1 << (FFI.type_size(type) * 8 - 1)) - 1 end def min_for_type(type) ~max_for_type(type) end def max_long max_for_type :long end def min_long min_for_type :long end def max_size_t max_for_unsigned_type :size_t end def max_ssize_t # FFI has no :ssize_t, but it's the same number of bits as :size_t max_for_type :size_t end def min_ssize_t min_for_type :size_t end def max_ushort max_for_unsigned_type :ushort end def max_uint max_for_unsigned_type :uint end def max_ulong max_for_unsigned_type :ulong end end Minitest::Test.send :include, GirFFITestExtensions gir_ffi-0.11.4/test/integration/0000755000004100000410000000000013170036060016530 5ustar www-datawww-datagir_ffi-0.11.4/test/integration/generated_secret_test.rb0000644000004100000410000000066213170036060023423 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe 'The generated Secret module' do describe 'Secret::Schema' do it 'has a working constructor' do begin GirFFI.setup :Secret rescue RuntimeError skip 'No GIR data for Secret available' end instance = Secret::Schema.new('foo', :none, 'bar' => :string) instance.must_be_instance_of Secret::Schema end end end gir_ffi-0.11.4/test/integration/generated_warnlib_test.rb0000644000004100000410000000243413170036060023573 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe 'The generated WarnLib module' do before do begin GirFFI.setup :WarnLib rescue RuntimeError skip 'WarnLib GIR not available' end end describe 'WarnLib::Whatever' do let(:derived_klass) do Object.const_set("DerivedClass#{Sequence.next}", Class.new(GObject::Object)) end before do @result = nil derived_klass.class_eval { include WarnLib::Whatever } GirFFI.define_type derived_klass do |info| info.install_vfunc_implementation :do_boo, proc { |_obj, x, _y| @result = "boo#{x}" } info.install_vfunc_implementation :do_moo, proc { |_obj, x, _y| @result = "moo#{x}" } end end let(:instance) { derived_klass.new } it 'has a working method #do_boo' do instance.do_boo 42, nil @result.must_equal 'boo42' end it 'has a working method #do_moo' do instance.do_moo 23, nil @result.must_equal 'moo23' end end it 'has a working function #throw_unpaired' do proc { WarnLib.throw_unpaired }.must_raise GirFFI::GLibError end it 'has a working function #unpaired_error_quark' do result = WarnLib.unpaired_error_quark GLib.quark_to_string(result).must_equal 'warnlib-unpaired-error' end end gir_ffi-0.11.4/test/integration/generated_gtk_source_test.rb0000644000004100000410000000142013170036060024274 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' # Tests behavior of objects in the generated GtkSource namespace. describe 'The generated GtkSource module' do before do begin GirFFI.setup :GtkSource rescue RuntimeError skip 'GtkSource GIR not available' end end describe 'GtkSource::CompletionContext' do let(:instance) { GtkSource::CompletionContext.new } it 'allows adding proposals' do proposals = [ GtkSource::CompletionItem.new('Proposal 1', 'Proposal 1', nil, 'blah 1'), GtkSource::CompletionItem.new('Proposal 2', 'Proposal 2', nil, 'blah 2'), GtkSource::CompletionItem.new('Proposal 3', 'Proposal 3', nil, 'blah 3') ] instance.add_proposals nil, proposals, true end end end gir_ffi-0.11.4/test/integration/generated_gst_test.rb0000644000004100000410000000161613170036060022733 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :Gst Gst.init [] # Tests behavior of objects in the generated Gio namespace. describe 'the generated Gst module' do describe 'Gst::FakeSink' do let(:instance) { Gst::ElementFactory.make('fakesink', 'sink') } it 'allows the handoff signal to be connected and emitted' do a = nil instance.signal_connect('handoff') { a = 10 } GObject.signal_emit(instance, 'handoff') a.must_equal 10 end it 'correctly fetches the name' do instance.name.must_equal 'sink' end end describe 'Gst::AutoAudioSink' do let(:instance) { Gst::ElementFactory.make('autoaudiosink', 'audiosink') } it 'correctly fetches the name' do skip 'Audio sink was not created' unless instance instance.get_name.must_equal 'audiosink' instance.name.must_equal 'audiosink' end end end gir_ffi-0.11.4/test/integration/generated_gio_test.rb0000644000004100000410000000623513170036060022716 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :Gio # Tests generated methods and functions in the Gio namespace. describe 'The generated Gio module' do describe 'File#new_for_path, a method returning an interface,' do it 'returns an object of a more specific class' do file = Gio::File.new_for_path('/') refute_instance_of Gio::File, file assert_includes file.class.ancestors, Gio::File end end describe 'the result of #file_new_from_path' do before do @it = Gio.file_new_for_path('/') end it 'is able to set up a method in a class that is not the first ancestor' do anc = @it.class.ancestors assert_equal [Gio::File, GObject::Object], anc[1, 2] refute_defines_instance_method Gio::File, :get_qdata assert_defines_instance_method GObject::Object, :get_qdata @it.setup_and_call :get_qdata, 1 end it 'knows its GType' do instance_gtype = GObject.type_from_instance @it @it.class.gtype.must_equal instance_gtype end end describe 'the FileInfo class' do describe 'an instance' do before do file = Gio.file_new_for_path('/') @fileinfo = file.query_info '*', :none, nil end it 'has a working #get_attribute_type method' do type = @fileinfo.get_attribute_type 'standard::display-name' assert_equal :string, type end end end describe 'the action-added signal' do before do @grp = Gio::SimpleActionGroup.new end it "correctly passes on the string parameter 'action_name'" do a = nil GObject.signal_connect @grp, 'action-added' do |_grp, action_name, _user_data| a = action_name end GObject.signal_emit @grp, 'action-added', 'foo' assert_equal 'foo', a end end describe 'the reply signal' do before do @mo = Gio::MountOperation.new end it "correctly passes on the enum parameter 'result'" do a = nil GObject.signal_connect @mo, 'reply' do |_mnt, result, _user_data| a = result end GObject.signal_emit @mo, 'reply', :unhandled assert_equal :unhandled, a end end describe 'the CharsetConverter class' do it 'includes two interfaces' do klass = Gio::CharsetConverter assert_includes klass.ancestors, Gio::Converter assert_includes klass.ancestors, Gio::Initable end it 'allows an instance to find the #reset method' do cnv = Gio::CharsetConverter.new 'utf8', 'utf8' cnv.reset pass end end describe 'the SocketSourceFunc callback' do it 'can be cast to a native function' do Gio::SocketSourceFunc.new { |*args| p args }.to_native end end describe 'Gio::SimpleAction' do let(:simple_action) { Gio::SimpleAction.new('test', 'd') } it 'can read the property "state-type" with #get_property' do simple_action.get_property('state-type').must_be_nil end it 'can read the property "state-type" with #state_type' do simple_action.state_type.must_be_nil end it 'cannot write the property "state-type" with #state_type=' do simple_action.wont_respond_to :state_type= end end end gir_ffi-0.11.4/test/integration/method_lookup_test.rb0000644000004100000410000000152513170036060022770 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' # Tests how methods are looked up and generated on first use. describe 'Looking up methods' do before do save_module :Regress GirFFI.setup :Regress end describe 'an instance method' do it 'is found from a subclass' do assert_defines_instance_method Regress::TestObj, :forced_method refute_defines_instance_method Regress::TestSubObj, :forced_method sub_object = Regress::TestSubObj.new sub_object.forced_method end end describe 'a class method' do it 'is found from a subclass' do assert_defines_singleton_method Regress::TestObj, :static_method refute_defines_singleton_method Regress::TestSubObj, :static_method Regress::TestSubObj.static_method 42 end end after do restore_module :Regress end end gir_ffi-0.11.4/test/integration/generated_glib_test.rb0000644000004100000410000000072413170036060023052 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' # Tests generated classes, methods and functions in the GLib namespace. describe 'The generated GLib module' do it 'can auto-generate the GLib::IConv class' do klass = GLib::IConv klass.must_be_instance_of Class end it 'can auto-generate the GLib::SOURCE_REMOVE constant' do skip unless get_introspection_data 'GLib', 'SOURCE_REMOVE' GLib::SOURCE_REMOVE.must_equal false end end gir_ffi-0.11.4/test/integration/generated_pango_ft2_test.rb0000644000004100000410000000070213170036060024010 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :PangoFT2 # Tests generated methods and functions in the PangoFT2 namespace. describe PangoFT2 do describe PangoFT2::FontMap do it 'has a working method #load_font' do font_map = PangoFT2::FontMap.new context = font_map.create_context font_description = Pango::FontDescription.new font_map.load_font context, font_description end end end gir_ffi-0.11.4/test/integration/generated_gimarshallingtests_test.rb0000644000004100000410000026417513170036060026055 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' require 'gir_ffi' GirFFI.setup :GIMarshallingTests # Tests generated methods and functions in the GIMarshallingTests namespace. describe GIMarshallingTests do let(:derived_klass) do Object.const_set("DerivedClass#{Sequence.next}", Class.new(GIMarshallingTests::Object)) end def make_derived_instance GirFFI.define_type derived_klass do |info| yield info if block_given? end derived_klass.new end describe 'GIMarshallingTests::BoxedStruct' do let(:instance) { GIMarshallingTests::BoxedStruct.new } it 'has a writable field long_' do instance.long_ = 42 assert_equal 42, instance.long_ instance.long_ = 43 assert_equal 43, instance.long_ end it 'has a writable field string_' do skip unless get_field_introspection_data('GIMarshallingTests', 'BoxedStruct', 'string_') instance.string_ = 'foobar' instance.string_.must_equal 'foobar' end it 'has a writable field g_strv' do instance.g_strv.must_be :==, [] instance.g_strv = %w(foo bar) instance.g_strv.must_be :==, %w(foo bar) end it 'creates an instance using #new' do bx = GIMarshallingTests::BoxedStruct.new assert_instance_of GIMarshallingTests::BoxedStruct, bx bx.struct.must_be :owned? end it 'has a working method #inv' do instance.long_ = 42 instance.inv pass end it 'has a working function #inout' do bx = GIMarshallingTests::BoxedStruct.new bx.long_ = 42 bx.struct.must_be :owned? res = GIMarshallingTests::BoxedStruct.inout bx bx.struct.must_be :owned? res.struct.must_be :owned? assert_equal 0, res.long_ end it 'has a working function #out' do res = GIMarshallingTests::BoxedStruct.out res.struct.must_be :owned? assert_equal 42, res.long_ end it 'has a working function #returnv' do res = GIMarshallingTests::BoxedStruct.returnv res.struct.must_be :owned? assert_equal 42, res.long_ res.g_strv.must_be :==, %w(0 1 2) end end it 'has the constant CONSTANT_GERROR_CODE' do assert_equal 5, GIMarshallingTests::CONSTANT_GERROR_CODE end it 'has the constant CONSTANT_GERROR_DEBUG_MESSAGE' do GIMarshallingTests::CONSTANT_GERROR_DEBUG_MESSAGE.must_equal( 'we got an error, life is shit') end it 'has the constant CONSTANT_GERROR_DOMAIN' do assert_equal 'gi-marshalling-tests-gerror-domain', GIMarshallingTests::CONSTANT_GERROR_DOMAIN end it 'has the constant CONSTANT_GERROR_MESSAGE' do assert_equal 'gi-marshalling-tests-gerror-message', GIMarshallingTests::CONSTANT_GERROR_MESSAGE end it 'has the constant CONSTANT_NUMBER' do assert_equal 42, GIMarshallingTests::CONSTANT_NUMBER end it 'has the constant CONSTANT_UTF8' do assert_equal 'const ♥ utf8', GIMarshallingTests::CONSTANT_UTF8 end describe 'GIMarshallingTests::Enum' do it 'has the member :value1' do assert_equal 0, GIMarshallingTests::Enum[:value1] end it 'has the member :value2' do assert_equal 1, GIMarshallingTests::Enum[:value2] end it 'has the member :value3' do assert_equal 42, GIMarshallingTests::Enum[:value3] end end describe 'GIMarshallingTests::Flags' do it 'has the member :value1' do assert_equal 1, GIMarshallingTests::Flags[:value1] end it 'has the member :value2' do assert_equal 2, GIMarshallingTests::Flags[:value2] end it 'has the member :value3' do assert_equal 4, GIMarshallingTests::Flags[:value3] end it 'has the member :mask' do assert_equal 3, GIMarshallingTests::Flags[:mask] end it 'has the member :mask2' do assert_equal 3, GIMarshallingTests::Flags[:mask2] end it 'has a working function #in' do GIMarshallingTests::Flags.in value2: true end it 'has a working function #in_zero' do GIMarshallingTests::Flags.in_zero 0 end it 'has a working function #inout' do result = GIMarshallingTests::Flags.inout value2: true result.must_equal(value1: true) end it 'has a working function #out' do result = GIMarshallingTests::Flags.out result.must_equal(value2: true) end it 'has a working function #returnv' do result = GIMarshallingTests::Flags.returnv result.must_equal(value2: true) end end describe 'GIMarshallingTests::GEnum' do it 'has the member :value1' do assert_equal 0, GIMarshallingTests::GEnum[:value1] end it 'has the member :value2' do assert_equal 1, GIMarshallingTests::GEnum[:value2] end it 'has the member :value3' do assert_equal 42, GIMarshallingTests::GEnum[:value3] end it 'has a working function #in' do GIMarshallingTests::GEnum.in :value3 end it 'has a working function #inout' do result = GIMarshallingTests::GEnum.inout :value3 result.must_equal :value1 end it 'has a working function #out' do result = GIMarshallingTests::GEnum.out result.must_equal :value3 end it 'has a working function #returnv' do result = GIMarshallingTests::GEnum.returnv result.must_equal :value3 end end describe 'GIMarshallingTests::Interface' do it 'has a working method #test_int8_in' do derived_klass.class_eval { include GIMarshallingTests::Interface } derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :test_int8_in, proc { |obj, in_| obj.int = in_ } end derived_instance.test_int8_in 8 derived_instance.int.must_equal 8 end end describe 'GIMarshallingTests::Interface2' do it 'must be tested for clashes with Interface' do skip 'Needs more work to determine desired behavior' end end describe 'GIMarshallingTests::Interface3' do it 'has a working method #test_variant_array_in' do skip unless get_introspection_data 'GIMarshallingTests', 'Interface3' derived_klass.class_eval { include GIMarshallingTests::Interface3 } derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :test_variant_array_in, proc { |obj, in_| obj.int = in_.to_a.first.get_byte } end derived_instance.test_variant_array_in [GLib::Variant.new_byte(42)] derived_instance.int.must_equal 42 end end describe 'GIMarshallingTests::InterfaceImpl' do before do skip unless get_introspection_data 'GIMarshallingTests', 'InterfaceImpl' end it 'has a working method #get_as_interface' do obj = GIMarshallingTests::InterfaceImpl.new [] result = obj.get_as_interface result.must_be_kind_of GIMarshallingTests::Interface end end describe 'GIMarshallingTests::NestedStruct' do let(:instance) { GIMarshallingTests::NestedStruct.new } it 'has a writable field simple_struct' do assert_instance_of GIMarshallingTests::SimpleStruct, instance.simple_struct new_struct = GIMarshallingTests::SimpleStruct.new new_struct.int8 = 42 instance.simple_struct = new_struct instance.simple_struct.int8.must_equal 42 end end describe 'GIMarshallingTests::NoTypeFlags' do it 'has the member :value1' do assert_equal 1, GIMarshallingTests::NoTypeFlags[:value1] end it 'has the member :value2' do assert_equal 2, GIMarshallingTests::NoTypeFlags[:value2] end it 'has the member :value3' do assert_equal 4, GIMarshallingTests::NoTypeFlags[:value3] end it 'has the member :mask' do assert_equal 3, GIMarshallingTests::NoTypeFlags[:mask] end it 'has the member :mask2' do assert_equal 3, GIMarshallingTests::NoTypeFlags[:mask2] end end describe 'GIMarshallingTests::NotSimpleStruct' do let(:instance) { GIMarshallingTests::NotSimpleStruct.new } it 'has a writable field pointer' do instance.pointer.must_be_nil nested = GIMarshallingTests::NestedStruct.new nested.simple_struct.int8 = 23 instance.pointer = nested instance.pointer.simple_struct.int8.must_equal 23 end end it 'has the constant OVERRIDES_CONSTANT' do assert_equal 42, GIMarshallingTests::OVERRIDES_CONSTANT end describe 'GIMarshallingTests::Object' do it 'creates an instance using #new' do ob = GIMarshallingTests::Object.new 42 assert_instance_of GIMarshallingTests::Object, ob assert_equal 42, ob.int end it 'fails to create an instance using #new_fail' do skip unless get_method_introspection_data('GIMarshallingTests', 'Object', 'new_fail') proc { GIMarshallingTests::Object.new_fail 42 }.must_raise GirFFI::GLibError end it 'has a working function #full_inout' do ob = GIMarshallingTests::Object.new 42 ob.ref_count.must_equal 1 res = GIMarshallingTests::Object.full_inout ob ob.ref_count.must_equal 1 res.ref_count.must_equal 1 res.must_be_instance_of GIMarshallingTests::Object res.int.must_equal 0 end it 'has a working function #full_out' do res = GIMarshallingTests::Object.full_out res.must_be_instance_of GIMarshallingTests::Object res.ref_count.must_equal 1 end it 'has a working function #full_return' do res = GIMarshallingTests::Object.full_return res.must_be_instance_of GIMarshallingTests::Object res.ref_count.must_equal 1 end it 'has a working function #none_inout' do ob = GIMarshallingTests::Object.new 42 ob.ref_count.must_equal 1 res = GIMarshallingTests::Object.none_inout ob ob.ref_count.must_equal 1 res.ref_count.must_equal 2 res.must_be_instance_of GIMarshallingTests::Object ob.int.must_equal 42 res.int.must_equal 0 end it 'has a working function #none_out' do res = GIMarshallingTests::Object.none_out res.must_be_instance_of GIMarshallingTests::Object res.ref_count.must_equal 2 end it 'has a working function #none_return' do res = GIMarshallingTests::Object.none_return res.must_be_instance_of GIMarshallingTests::Object res.ref_count.must_equal 2 end it 'has a working function #static_method' do GIMarshallingTests::Object.static_method pass end let(:instance) { GIMarshallingTests::Object.new 42 } it 'has a working method #call_vfunc_with_callback' do skip unless get_method_introspection_data('GIMarshallingTests', 'Object', 'call_vfunc_with_callback') cb = nil user_data = nil result = nil derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :vfunc_with_callback, proc { |_obj, callback, callback_data| cb = callback user_data = callback_data.address result = callback.call(42, callback_data) } end derived_instance.call_vfunc_with_callback user_data.must_equal 0xdeadbeef # TODO: Change implementation of CallbackBase so that this becomes an # instance of GIMarshallingTests::CallbackIntInt cb.must_be_instance_of FFI::Function result.must_equal 42 end it 'has a working method #full_in' do skip 'This function is defined in the header but not implemented' end it 'has a working method #get_ref_info_for_vfunc_in_object_transfer_full' do skip unless get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'vfunc_in_object_transfer_full') obj = nil derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :vfunc_in_object_transfer_full, proc { |_this, object| obj = object } end result = derived_instance. get_ref_info_for_vfunc_in_object_transfer_full GIMarshallingTests::Object.gtype result.must_equal [1, false] obj.must_be_instance_of GIMarshallingTests::Object end it 'has a working method #get_ref_info_for_vfunc_in_object_transfer_none' do skip unless get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'vfunc_in_object_transfer_none') obj = nil derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :vfunc_in_object_transfer_none, proc { |_this, object| obj = object } end result = derived_instance. get_ref_info_for_vfunc_in_object_transfer_none GIMarshallingTests::Object.gtype obj.ref_count.must_be :>, 0 result.must_equal [2, false] obj.must_be_instance_of GIMarshallingTests::Object end it 'has a working method #get_ref_info_for_vfunc_out_object_transfer_full' do skip unless get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'vfunc_out_object_transfer_full') obj = nil derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :vfunc_out_object_transfer_full, proc { |_obj| obj = GIMarshallingTests::Object.new(42) } end result = derived_instance.get_ref_info_for_vfunc_out_object_transfer_full obj.ref_count.must_be :>, 0 # TODO: Check desired result result.must_equal [2, false] end it 'has a working method #get_ref_info_for_vfunc_out_object_transfer_none' do skip unless get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'vfunc_out_object_transfer_none') derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :vfunc_out_object_transfer_none, proc { |_obj| GIMarshallingTests::Object.new 42 } end result = derived_instance.get_ref_info_for_vfunc_out_object_transfer_none result.must_equal [1, false] end it 'has a working method #get_ref_info_for_vfunc_return_object_transfer_full' do skip unless get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'vfunc_return_object_transfer_full') derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :vfunc_return_object_transfer_full, proc { |_obj| GIMarshallingTests::Object.new 42 } end result = derived_instance.get_ref_info_for_vfunc_return_object_transfer_full result.must_equal [2, false] end it 'has a working method #get_ref_info_for_vfunc_return_object_transfer_none' do skip unless get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'vfunc_return_object_transfer_none') derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :vfunc_return_object_transfer_none, proc { |_obj| GIMarshallingTests::Object.new 42 } end result = derived_instance.get_ref_info_for_vfunc_return_object_transfer_none result.must_equal [1, false] end it 'has a working method #int8_in' do derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :method_int8_in, proc { |obj, in_| obj.int = in_ } end derived_instance.int8_in 23 derived_instance.int.must_equal 23 end it 'has a working method #int8_out' do # GLib minor version and GObjectIntrospection minor version should be in sync skip 'Introspection data is not generated correctly' if GLib::MINOR_VERSION < 42 derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :method_int8_out, proc { |_obj| 42 } end derived_instance.int8_out.must_equal 42 end it 'has a working method #method' do instance.method pass end it 'has a working method #method_array_in' do instance.method_array_in [-1, 0, 1, 2] pass end it 'has a working method #method_array_inout' do res = instance.method_array_inout [-1, 0, 1, 2] res.must_be :==, [-2, -1, 0, 1, 2] end it 'has a working method #method_array_out' do res = instance.method_array_out res.must_be :==, [-1, 0, 1, 2] end it 'has a working method #method_array_return' do res = instance.method_array_return res.must_be :==, [-1, 0, 1, 2] end it 'has a working method #method_int8_arg_and_out_callee' do skip unless get_method_introspection_data('GIMarshallingTests', 'Object', 'method_int8_arg_and_out_callee') derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :method_int8_arg_and_out_callee, proc { |_obj, arg| 2 * arg } end result = derived_instance.method_int8_arg_and_out_callee 32 result.must_equal 64 end it 'has a working method #method_int8_arg_and_out_caller' do skip unless get_method_introspection_data('GIMarshallingTests', 'Object', 'method_int8_arg_and_out_caller') derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :method_int8_arg_and_out_caller, proc { |_obj, arg| 2 * arg } end result = derived_instance.method_int8_arg_and_out_caller 32 result.must_equal 64 end it 'has a working method #method_int8_in' do derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :method_int8_in, proc { |obj, in_| obj.int = in_ } end derived_instance.method_int8_in 108 derived_instance.int.must_equal 108 end it 'has a working method #method_int8_out' do derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :method_int8_out, proc { |_obj| 42 } end derived_instance.method_int8_out.must_equal 42 end it 'has a working method #method_str_arg_out_ret' do skip unless get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'method_str_arg_out_ret') derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :method_str_arg_out_ret, proc { |_obj, arg| [arg, 42] } end derived_instance.method_str_arg_out_ret('foo').must_equal ['foo', 42] end it 'has a working method #method_variant_array_in' do skip 'This function is defined in the header but not implemented' end it 'has a working method #method_with_default_implementation' do instance.method_with_default_implementation 104 assert_equal 104, instance.int end it 'has a working method #none_in' do instance.none_in pass end it 'has a working method #overridden_method' do instance.set_property('int', 0) instance.overridden_method pass end it 'has a working method #vfunc_array_out_parameter' do skip unless get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'vfunc_array_out_parameter') derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :vfunc_array_out_parameter, proc { |_obj| [1.1, 2.2, 3.3] } end result = derived_instance.vfunc_array_out_parameter arr = result.to_a arr.length.must_equal 3 arr[0].must_be_close_to 1.1 arr[1].must_be_close_to 2.2 arr[2].must_be_close_to 3.3 end it 'has a working method #vfunc_caller_allocated_out_parameter' do skip unless get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'vfunc_caller_allocated_out_parameter') derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :vfunc_caller_allocated_out_parameter, proc { |_obj| 'Hello!' } end result = derived_instance.vfunc_caller_allocated_out_parameter result.must_equal 'Hello!' end it 'has a working method #vfunc_meth_with_error' do derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :vfunc_meth_with_err, proc { |_object, x| raise 'This is not the answer!' unless x == 42 true } end result = derived_instance.vfunc_meth_with_error 42 result.must_equal true err = proc { derived_instance.vfunc_meth_with_error(21) }. must_raise GirFFI::GLibError err.message.must_equal 'This is not the answer!' err.domain.must_equal 'gir_ffi' err.code.must_equal 0 end it 'has a working method #vfunc_multiple_out_parameters' do derived_instance = make_derived_instance do |info| info.install_vfunc_implementation( :vfunc_multiple_out_parameters, proc { |*_args| [42.1, -142.3] }) end result = derived_instance.vfunc_multiple_out_parameters result[0].must_be_close_to 42.1 result[1].must_be_close_to(-142.3) end it 'has a working method #vfunc_one_out_parameter' do derived_instance = make_derived_instance do |info| info.install_vfunc_implementation( :vfunc_one_out_parameter, proc { |*_args| 23.4 }) end derived_instance.vfunc_one_out_parameter. must_be_within_epsilon 23.4 end it 'has a working method #vfunc_out_enum' do skip unless get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'vfunc_out_enum') derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :vfunc_out_enum, proc { |_obj| :value2 } end derived_instance.vfunc_out_enum.must_equal :value2 end it 'has a working method #vfunc_return_enum' do skip unless get_vfunc_introspection_data('GIMarshallingTests', 'Object', 'vfunc_return_enum') derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :vfunc_return_enum, proc { |_obj| :value2 } end derived_instance.vfunc_return_enum.must_equal :value2 end it 'has a working method #vfunc_return_value_and_multiple_out_parameters' do derived_instance = make_derived_instance do |info| info.install_vfunc_implementation( :vfunc_return_value_and_multiple_out_parameters, proc { |*_args| [42, -142, 3] }) end derived_instance.vfunc_return_value_and_multiple_out_parameters. must_equal [42, -142, 3] end it 'has a working method #vfunc_return_value_and_one_out_parameter' do derived_instance = make_derived_instance do |info| info.install_vfunc_implementation( :vfunc_return_value_and_one_out_parameter, proc { |*_args| [42, -142] }) end derived_instance.vfunc_return_value_and_one_out_parameter. must_equal [42, -142] end it 'has a working method #vfunc_return_value_only' do derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :vfunc_return_value_only, proc { |_obj| 0x1234_5678 } end result = derived_instance.vfunc_return_value_only result.must_equal 0x1234_5678 end it 'has a working method #vfunc_with_callback' do skip unless get_method_introspection_data('GIMarshallingTests', 'Object', 'vfunc_with_callback') result = 1 derived_instance = make_derived_instance do |info| info.install_vfunc_implementation :vfunc_with_callback, proc { |_obj, callback, callback_data| callback.call(42, callback_data) } end derived_instance.vfunc_with_callback { |val, user_data| result = val + user_data } # The current implementation of the vfunc_with_callback method currently # doesn't actually call the virtual function vfunc_with_callback. result.must_equal 1 result.wont_equal 42 + 23 end describe "its 'int' property" do it 'can be retrieved with #get_property' do assert_equal 42, instance.get_property('int') end it 'can be retrieved with #int' do assert_equal 42, instance.int end it 'can be set with #set_property' do instance.set_property('int', 13) assert_equal 13, instance.get_property('int') end it 'can be set with #int=' do instance.int = 1 assert_equal 1, instance.int end end end describe 'GIMarshallingTests::OverridesObject' do it 'creates an instance using #new' do ob = GIMarshallingTests::OverridesObject.new assert_instance_of GIMarshallingTests::OverridesObject, ob end it 'has a working function #returnv' do ob = GIMarshallingTests::OverridesObject.returnv assert_instance_of GIMarshallingTests::OverridesObject, ob end let(:instance) { GIMarshallingTests::OverridesObject.new } it 'has a working method #method' do result = instance.method result.must_equal 42 end it 'does not have accessors for its parent instance' do instance.wont_respond_to :parent_instance instance.wont_respond_to :parent_instance= end it 'has a readable field long_' do instance.long_.must_equal 0 instance.wont_respond_to :long_= end end describe 'GIMarshallingTests::OverridesStruct' do let(:instance) { GIMarshallingTests::OverridesStruct.new } it 'has a writable field long_' do instance.long_ = 43 instance.long_.must_equal 43 end it 'creates an instance using #new' do ob = GIMarshallingTests::OverridesStruct.new assert_instance_of GIMarshallingTests::OverridesStruct, ob end it 'has a working method #method' do instance.method.must_equal 42 end it 'has a working function #returnv' do ob = GIMarshallingTests::OverridesStruct.returnv assert_instance_of GIMarshallingTests::OverridesStruct, ob end end describe 'GIMarshallingTests::PointerStruct' do it 'creates an instance using #new' do ps = GIMarshallingTests::PointerStruct.new assert_instance_of GIMarshallingTests::PointerStruct, ps end let(:instance) { GIMarshallingTests::PointerStruct.new } it 'has a writable field long_' do assert_equal 0, instance.long_ instance.long_ = 1056 assert_equal 1056, instance.long_ end it 'has a working method #inv' do instance.long_ = 42 instance.inv pass end it 'has a working function #returnv' do ob = GIMarshallingTests::PointerStruct.returnv assert_instance_of GIMarshallingTests::PointerStruct, ob end end describe 'GIMarshallingTests::PropertiesObject' do it 'creates an instance using #new' do ob = GIMarshallingTests::PropertiesObject.new assert_instance_of GIMarshallingTests::PropertiesObject, ob end let(:instance) { GIMarshallingTests::PropertiesObject.new } describe "its 'some-boolean' property" do it 'can be retrieved with #get_property' do instance.get_property('some-boolean').must_equal false end it 'can be retrieved with #some_boolean' do instance.some_boolean.must_equal false end it 'can be set with #set_property' do instance.set_property('some-boolean', true) instance.get_property('some-boolean').must_equal true end it 'can be set with #some_boolean=' do instance.some_boolean = true instance.get_property('some-boolean').must_equal true end end describe "its 'some-boxed-glist' property" do before do skip unless get_property_introspection_data('GIMarshallingTests', 'PropertiesObject', 'some-boxed-glist') end it 'can be retrieved with #get_property' do instance.get_property('some-boxed-glist').must_be_nil end it 'can be retrieved with #some_boxed_glist' do instance.some_boxed_glist.must_be_nil end it 'can be set with #set_property_extended' do instance.set_property_extended('some-boxed-glist', [1, 2, 3]) instance.some_boxed_glist.to_a.must_equal [1, 2, 3] end it 'can be set with #some_boxed_glist=' do instance.some_boxed_glist = [1, 2, 3] instance.some_boxed_glist.to_a.must_equal [1, 2, 3] instance.get_property_extended('some-boxed-glist').to_a.must_equal [1, 2, 3] end end describe "its 'some-boxed-struct' property" do before do skip unless get_property_introspection_data('GIMarshallingTests', 'PropertiesObject', 'some-boxed-struct') end it 'can be retrieved with #get_property' do instance.get_property('some-boxed-struct').must_be_nil end it 'can be retrieved with #some_boxed_struct' do instance.some_boxed_struct.must_be_nil end it 'can be set with #set_property' do boxed = GIMarshallingTests::BoxedStruct.new boxed.long_ = 42 instance.set_property('some-boxed-struct', boxed) instance.get_property('some-boxed-struct').long_.must_equal 42 end it 'can be set with #some_boxed_struct=' do boxed = GIMarshallingTests::BoxedStruct.new boxed.long_ = 43 instance.some_boxed_struct = boxed instance.some_boxed_struct.long_.must_equal 43 end end describe "its 'some-char' property" do it 'can be retrieved with #get_property' do instance.get_property('some-char').must_equal 0 end it 'can be retrieved with #some_char' do instance.some_char.must_equal 0 end it 'can be set with #set_property' do instance.set_property 'some-char', 42 instance.get_property('some-char').must_equal 42 end it 'can be set with #some_char=' do instance.some_char = 43 instance.some_char.must_equal 43 end end describe "its 'some-double' property" do it 'can be retrieved with #get_property' do instance.get_property('some-double').must_equal 0.0 end it 'can be retrieved with #some_double' do instance.some_double.must_equal 0.0 end it 'can be set with #set_property' do instance.set_property('some-double', 3.14) instance.get_property('some-double').must_equal 3.14 end it 'can be set with #some_double=' do instance.some_double = 3.14 instance.some_double.must_equal 3.14 end end describe "its 'some-float' property" do it 'can be retrieved with #get_property' do instance.get_property('some-float').must_equal 0.0 end it 'can be retrieved with #some_float' do instance.some_float.must_equal 0.0 end it 'can be set with #set_property' do instance.set_property('some-float', 3.14) instance.get_property('some-float').must_be_close_to 3.14 end it 'can be set with #some_float=' do instance.some_float = 3.14 instance.some_float.must_be_close_to 3.14 end end describe "its 'some-int' property" do it 'can be retrieved with #get_property' do instance.get_property('some-int').must_equal 0 end it 'can be retrieved with #some_int' do instance.some_int.must_equal 0 end it 'can be set with #set_property' do instance.set_property 'some-int', 4242 instance.get_property('some-int').must_equal 4242 end it 'can be set with #some_int=' do instance.some_int = 4243 instance.some_int.must_equal 4243 end end describe "its 'some-int64' property" do it 'can be retrieved with #get_property' do instance.get_property('some-int64').must_equal 0 end it 'can be retrieved with #some_int64' do instance.some_int64.must_equal 0 end it 'can be set with #set_property' do instance.set_property 'some-int64', 42_000_000_000_000 instance.get_property('some-int64').must_equal 42_000_000_000_000 end it 'can be set with #some_int64=' do instance.some_int64 = 43_000_000_000_000 instance.some_int64.must_equal 43_000_000_000_000 end end describe "its 'some-long' property" do it 'can be retrieved with #get_property' do instance.get_property('some-long').must_equal 0 end it 'can be retrieved with #some_long' do instance.some_long.must_equal 0 end it 'can be set with #set_property' do instance.set_property 'some-long', 4242 instance.get_property('some-long').must_equal 4242 end it 'can be set with #some_long=' do instance.some_long = 4243 instance.some_long.must_equal 4243 end end describe "its 'some-object' property" do before do skip unless get_property_introspection_data('GIMarshallingTests', 'PropertiesObject', 'some-object') end it 'can be retrieved with #get_property' do instance.get_property('some-object').must_be_nil end it 'can be retrieved with #some_object' do instance.some_object.must_be_nil end it 'can be set with #set_property' do ob = GIMarshallingTests::Object.new 42 instance.set_property 'some-object', ob instance.get_property('some-object').must_equal ob end it 'can be set with #some_object=' do ob = GIMarshallingTests::Object.new 42 instance.some_object = ob instance.some_object.must_equal ob end end describe "its 'some-strv' property" do before do skip unless get_property_introspection_data('GIMarshallingTests', 'PropertiesObject', 'some-strv') end it 'can be retrieved with #get_property' do instance.get_property('some-strv').must_be :==, [] end it 'can be retrieved with #some_strv' do instance.some_strv.must_be :==, [] end it 'can be set with #set_property_extended' do instance.set_property_extended('some-strv', %w(foo bar)) instance.get_property('some-strv').must_be :==, %w(foo bar) end it 'can be set with #some_strv=' do instance.some_strv = %w(foo bar) instance.some_strv.must_be :==, %w(foo bar) end end describe "its 'some-uchar' property" do it 'can be retrieved with #get_property' do instance.get_property('some-uchar').must_equal 0 end it 'can be retrieved with #some_uchar' do instance.some_uchar.must_equal 0 end it 'can be set with #set_property' do instance.set_property 'some-uchar', 42 instance.get_property('some-uchar').must_equal 42 end it 'can be set with #some_uchar=' do instance.some_uchar = 43 instance.some_uchar.must_equal 43 end end describe "its 'some-uint' property" do it 'can be retrieved with #get_property' do instance.get_property('some-uint').must_equal 0 end it 'can be retrieved with #some_uint' do instance.some_uint.must_equal 0 end it 'can be set with #set_property' do instance.set_property 'some-uint', 4242 instance.get_property('some-uint').must_equal 4242 end it 'can be set with #some_uint=' do instance.some_uint = 4243 instance.some_uint.must_equal 4243 end end describe "its 'some-uint64' property" do it 'can be retrieved with #get_property' do instance.get_property('some-uint64').must_equal 0 end it 'can be retrieved with #some_uint64' do instance.some_uint64.must_equal 0 end it 'can be set with #set_property' do instance.set_property 'some-uint64', 42_000_000_000_000 instance.get_property('some-uint64').must_equal 42_000_000_000_000 end it 'can be set with #some_uint64=' do instance.some_uint64 = 43_000_000_000_000 instance.some_uint64.must_equal 43_000_000_000_000 end end describe "its 'some-ulong' property" do it 'can be retrieved with #get_property' do instance.get_property('some-ulong').must_equal 0 end it 'can be retrieved with #some_ulong' do instance.some_ulong.must_equal 0 end it 'can be set with #set_property' do instance.set_property 'some-ulong', 4242 instance.get_property('some-ulong').must_equal 4242 end it 'can be set with #some_ulong=' do instance.some_ulong = 4243 instance.some_ulong.must_equal 4243 end end describe "its 'some-variant' property" do before do skip unless get_property_introspection_data('GIMarshallingTests', 'PropertiesObject', 'some-variant') end it 'can be retrieved with #get_property' do instance.get_property('some-variant').must_be_nil end it 'can be retrieved with #some_variant' do instance.some_variant.must_be_nil end it 'can be set with #set_property' do value = GLib::Variant.new_string('Foo') instance.set_property 'some-variant', value instance.get_property('some-variant').must_equal value end it 'can be set with #some_variant=' do value = GLib::Variant.new_string('Foo') instance.some_variant = value instance.some_variant.must_equal value end end end describe 'GIMarshallingTests::SecondEnum' do it 'has the member :secondvalue1' do assert_equal 0, GIMarshallingTests::SecondEnum[:secondvalue1] end it 'has the member :secondvalue2' do assert_equal 1, GIMarshallingTests::SecondEnum[:secondvalue2] end end describe 'GIMarshallingTests::SimpleStruct' do it 'creates an instance using #new' do ss = GIMarshallingTests::SimpleStruct.new assert_instance_of GIMarshallingTests::SimpleStruct, ss end let(:instance) { GIMarshallingTests::SimpleStruct.new } it 'has a writable field long_' do instance.long_.must_equal 0 instance.long_ = 1056 instance.long_.must_equal 1056 end it 'has a writable field int8' do instance.int8.must_equal 0 instance.int8 = -43 instance.int8.must_equal(-43) end it 'has a working method #inv' do instance.long_ = 6 instance.int8 = 7 instance.inv pass end it 'has a working method #method' do instance.long_ = 6 instance.int8 = 7 instance.method pass end it 'has a working function #returnv' do ss = GIMarshallingTests::SimpleStruct.returnv assert_instance_of GIMarshallingTests::SimpleStruct, ss end end describe 'GIMarshallingTests::SubObject' do it 'creates an instance using #new' do so = GIMarshallingTests::SubObject.new so.must_be_instance_of GIMarshallingTests::SubObject GObject.type_name_from_instance(so). must_equal 'GIMarshallingTestsSubObject' end let(:instance) { GIMarshallingTests::SubObject.new } it 'has a working method #overwritten_method' do instance.overwritten_method pass end it 'has a working method #sub_method' do instance.sub_method pass end it 'does not have accessors for its parent instance' do instance.wont_respond_to :parent_instance instance.wont_respond_to :parent_instance= end end describe 'GIMarshallingTests::SubSubObject' do it 'creates an instance using #new' do so = GIMarshallingTests::SubSubObject.new assert_instance_of GIMarshallingTests::SubSubObject, so GObject.type_name_from_instance(so). must_equal 'GIMarshallingTestsSubSubObject' end let(:instance) { GIMarshallingTests::SubSubObject.new } it 'does not have accessors for its parent instance' do instance.wont_respond_to :parent_instance instance.wont_respond_to :parent_instance= end end describe 'GIMarshallingTests::Union' do it 'creates an instance with #new' do u = GIMarshallingTests::Union.new assert_instance_of GIMarshallingTests::Union, u end let(:instance) { GIMarshallingTests::Union.new } it 'has a writable field long_' do assert_equal 0, instance.long_ instance.long_ = 1056 assert_equal 1056, instance.long_ end it 'has a working method #inv' do instance.long_ = 42 instance.inv pass end it 'has a working method #method' do instance.long_ = 42 instance.method pass end it 'has a working function #inout' do skip 'This function is defined in the header but not implemented' end it 'has a working function #out' do skip 'This function is defined in the header but not implemented' end it 'has a working function #returnv' do u = GIMarshallingTests::Union.returnv assert_instance_of GIMarshallingTests::Union, u end end it 'has a working function #array_enum_in' do GIMarshallingTests.array_enum_in [:value1, :value2, :value3] end it 'has a working function #array_fixed_inout' do res = GIMarshallingTests.array_fixed_inout [-1, 0, 1, 2] res.must_be :==, [2, 1, 0, -1] end it 'has a working function #array_fixed_int_in' do GIMarshallingTests.array_fixed_int_in [-1, 0, 1, 2] pass end it 'has a working function #array_fixed_int_return' do res = GIMarshallingTests.array_fixed_int_return res.must_be :==, [-1, 0, 1, 2] end it 'has a working function #array_fixed_out' do res = GIMarshallingTests.array_fixed_out res.must_be :==, [-1, 0, 1, 2] end it 'has a working function #array_fixed_out_struct' do res = GIMarshallingTests.array_fixed_out_struct assert_equal [[7, 6], [6, 7]], res.map { |s| [s.long_, s.int8] } end it 'has a working function #array_fixed_short_in' do GIMarshallingTests.array_fixed_short_in [-1, 0, 1, 2] pass end it 'has a working function #array_fixed_short_return' do res = GIMarshallingTests.array_fixed_short_return res.must_be :==, [-1, 0, 1, 2] end it 'has a working function #array_gvariant_container_in' do v1 = GLib::Variant.new_int32(27) v2 = GLib::Variant.new_string('Hello') result = GIMarshallingTests.array_gvariant_container_in [v1, v2] arr = result.to_a arr.size.must_equal 2 arr[0].get_int32.must_equal 27 arr[1].get_string.must_equal 'Hello' end it 'has a working function #array_gvariant_full_in' do v1 = GLib::Variant.new_int32(27) v2 = GLib::Variant.new_string('Hello') result = GIMarshallingTests.array_gvariant_full_in [v1, v2] arr = result.to_a arr.size.must_equal 2 arr[0].get_int32.must_equal 27 arr[1].get_string.must_equal 'Hello' end it 'has a working function #array_gvariant_none_in' do v1 = GLib::Variant.new_int32(27) v2 = GLib::Variant.new_string('Hello') result = GIMarshallingTests.array_gvariant_none_in [v1, v2] arr = result.to_a arr.size.must_equal 2 arr[0].get_int32.must_equal 27 arr[1].get_string.must_equal 'Hello' end it 'has a working function #array_in' do GIMarshallingTests.array_in [-1, 0, 1, 2] pass end it 'has a working function #array_in_guint64_len' do GIMarshallingTests.array_in_guint64_len [-1, 0, 1, 2] pass end it 'has a working function #array_in_guint8_len' do GIMarshallingTests.array_in_guint8_len [-1, 0, 1, 2] pass end it 'has a working function #array_in_len_before' do GIMarshallingTests.array_in_len_before [-1, 0, 1, 2] pass end it 'has a working function #array_in_len_zero_terminated' do GIMarshallingTests.array_in_len_zero_terminated [-1, 0, 1, 2] pass end it 'has a working function #array_in_nonzero_nonlen' do skip unless get_introspection_data 'GIMarshallingTests', 'array_in_nonzero_nonlen' GIMarshallingTests.array_in_nonzero_nonlen 1, 'abcd'.bytes.to_a pass end it 'has a working function #array_in_utf8_two_in' do skip unless get_introspection_data 'GIMarshallingTests', 'array_in_utf8_two_in' GIMarshallingTests.array_in_utf8_two_in [-1, 0, 1, 2], '1', '2' pass end it 'has a working function #array_in_utf8_two_in_out_of_order' do skip unless get_introspection_data 'GIMarshallingTests', 'array_in_utf8_two_in_out_of_order' GIMarshallingTests.array_in_utf8_two_in_out_of_order '1', [-1, 0, 1, 2], '2' pass end it 'has a working function #array_inout' do res = GIMarshallingTests.array_inout [-1, 0, 1, 2] res.must_be :==, [-2, -1, 0, 1, 2] end it 'has a working function #array_inout_etc' do arr, sum = GIMarshallingTests.array_inout_etc 42, [-1, 0, 1, 2], 24 arr.must_be :==, [42, -1, 0, 1, 24] sum.must_equal 42 + 24 end it 'has a working function #array_out' do res = GIMarshallingTests.array_out res.must_be :==, [-1, 0, 1, 2] end it 'has a working function #array_out_etc' do arr, sum = GIMarshallingTests.array_out_etc 42, 24 arr.must_be :==, [42, 0, 1, 24] sum.must_equal 42 + 24 end it 'has a working function #array_return' do res = GIMarshallingTests.array_return res.must_be :==, [-1, 0, 1, 2] end it 'has a working function #array_return_etc' do arr, sum = GIMarshallingTests.array_return_etc 42, 24 arr.must_be :==, [42, 0, 1, 24] sum.must_equal 42 + 24 end it 'has a working function #array_simple_struct_in' do arr = [1, 2, 3].map do |val| GIMarshallingTests::SimpleStruct.new.tap { |struct| struct.long_ = val } end GIMarshallingTests.array_simple_struct_in arr end it 'has a working function #array_string_in' do GIMarshallingTests.array_string_in %w(foo bar) pass end it 'has a working function #array_struct_in' do arr = [1, 2, 3].map do |val| GIMarshallingTests::BoxedStruct.new.tap { |struct| struct.long_ = val } end GIMarshallingTests.array_struct_in arr end it 'has a working function #array_struct_take_in' do arr = [1, 2, 3].map do |val| GIMarshallingTests::BoxedStruct.new.tap { |struct| struct.long_ = val } end # NOTE: This copies values so arr's elements stay valid GIMarshallingTests.array_struct_take_in arr arr.map(&:long_).must_equal [1, 2, 3] end it 'has a working function #array_struct_value_in' do skip unless get_introspection_data 'GIMarshallingTests', 'array_struct_value_in' arr = [1, 2, 3].map do |val| GIMarshallingTests::BoxedStruct.new.tap { |struct| struct.long_ = val } end GIMarshallingTests.array_struct_value_in arr end it 'has a working function #array_uint8_in' do arr = 'abcd'.bytes.to_a GIMarshallingTests.array_uint8_in arr pass end it 'has a working function #array_zero_terminated_in' do GIMarshallingTests.array_zero_terminated_in %w(0 1 2) pass end it 'has a working function #array_zero_terminated_inout' do res = GIMarshallingTests.array_zero_terminated_inout %w(0 1 2) res.must_be :==, ['-1', '0', '1', '2'] end it 'has a working function #array_zero_terminated_out' do res = GIMarshallingTests.array_zero_terminated_out res.must_be :==, %w(0 1 2) end it 'has a working function #array_zero_terminated_return' do res = GIMarshallingTests.array_zero_terminated_return res.must_be :==, %w(0 1 2) end it 'has a working function #array_zero_terminated_return_null' do res = GIMarshallingTests.array_zero_terminated_return_null res.must_be :==, [] end it 'has a working function #array_zero_terminated_return_struct' do res = GIMarshallingTests.array_zero_terminated_return_struct res.to_a.map(&:long_).must_equal [42, 43, 44] end it 'has a working function #boolean_in_false' do GIMarshallingTests.boolean_in_false false pass end it 'has a working function #boolean_in_true' do GIMarshallingTests.boolean_in_true true pass end it 'has a working function #boolean_inout_false_true' do res = GIMarshallingTests.boolean_inout_false_true false res.must_equal true end it 'has a working function #boolean_inout_true_false' do res = GIMarshallingTests.boolean_inout_true_false true res.must_equal false end it 'has a working function #boolean_out_false' do res = GIMarshallingTests.boolean_out_false res.must_equal false end it 'has a working function #boolean_out_true' do res = GIMarshallingTests.boolean_out_true res.must_equal true end it 'has a working function #boolean_return_false' do res = GIMarshallingTests.boolean_return_false res.must_equal false end it 'has a working function #boolean_return_true' do res = GIMarshallingTests.boolean_return_true res.must_equal true end it 'has a working function #boxed_struct_inout' do bx = GIMarshallingTests::BoxedStruct.new bx.long_ = 42 res = GIMarshallingTests.boxed_struct_inout bx res.long_.must_equal 0 end it 'has a working function #boxed_struct_out' do res = GIMarshallingTests.boxed_struct_out res.long_.must_equal 42 end it 'has a working function #boxed_struct_returnv' do res = GIMarshallingTests.boxed_struct_returnv res.long_.must_equal 42 res.g_strv.must_be :==, %w(0 1 2) end it 'has a working function #bytearray_full_return' do ret = GIMarshallingTests.bytearray_full_return assert_instance_of GLib::ByteArray, ret assert_includes( ['0123'.bytes.to_a, "\x001\xFF3".bytes.to_a], ret.to_string.bytes.to_a) end it 'has a working function #bytearray_none_in' do val = GIMarshallingTests.bytearray_full_return.to_string ba = GLib::ByteArray.new ba = ba.append val GIMarshallingTests.bytearray_none_in ba pass end it 'has a working function #callback_multiple_out_parameters' do result = GIMarshallingTests.callback_multiple_out_parameters do |*_args| [12.0, 13.0] end result.must_equal [12.0, 13.0] end it 'has a working function #callback_one_out_parameter' do result = GIMarshallingTests.callback_one_out_parameter { 42.0 } result.must_equal 42.0 end it 'has a working function #callback_owned_boxed' do skip unless get_introspection_data 'GIMarshallingTests', 'callback_owned_boxed' a = nil callback = proc { |box, _callback_data| a = box.long_ * 2 } result = GIMarshallingTests.callback_owned_boxed(&callback) result.must_equal 1 a.must_equal 2 result = GIMarshallingTests.callback_owned_boxed(&callback) result.must_equal 2 a.must_equal 4 end it 'has a working function #callback_return_value_and_multiple_out_parameters' do result = GIMarshallingTests.callback_return_value_and_multiple_out_parameters do |*_args| [42, -142, 3] end result.must_equal [42, -142, 3] end it 'has a working function #callback_return_value_and_one_out_parameter' do result = GIMarshallingTests.callback_return_value_and_one_out_parameter do |*_args| [42, -142] end result.must_equal [42, -142] end it 'has a working function #callback_return_value_only' do result = GIMarshallingTests.callback_return_value_only { 42 } result.must_equal 42 end it 'has a working function #double_in' do GIMarshallingTests.double_in Float::MAX pass end it 'has a working function #double_inout' do ret = GIMarshallingTests.double_inout Float::MAX assert_in_epsilon 2.225e-308, ret end it 'has a working function #double_out' do ret = GIMarshallingTests.double_out ret.must_equal Float::MAX end it 'has a working function #double_return' do ret = GIMarshallingTests.double_return ret.must_equal Float::MAX end it 'has a working function #enum_in' do GIMarshallingTests.enum_in :value3 pass end it 'has a working function #enum_inout' do e = GIMarshallingTests.enum_inout :value3 e.must_equal :value1 end it 'has a working function #enum_out' do e = GIMarshallingTests.enum_out e.must_equal :value3 end it 'has a working function #enum_returnv' do e = GIMarshallingTests.enum_returnv e.must_equal :value3 end it 'has a working function #filename_list_return' do fl = GIMarshallingTests.filename_list_return fl.must_be_nil end it 'has a working function #flags_in' do GIMarshallingTests.flags_in value2: true pass end it 'has a working function #flags_in_zero' do GIMarshallingTests.flags_in_zero 0 pass end it 'has a working function #flags_inout' do res = GIMarshallingTests.flags_inout value2: true res.must_equal(value1: true) end it 'has a working function #flags_out' do res = GIMarshallingTests.flags_out res.must_equal(value2: true) end it 'has a working function #flags_returnv' do res = GIMarshallingTests.flags_returnv res.must_equal(value2: true) end it 'has a working function #float_in' do # float_return returns MAX_FLT flt = GIMarshallingTests.float_return GIMarshallingTests.float_in flt pass end it 'has a working function #float_inout' do # float_return returns MAX_FLT flt = GIMarshallingTests.float_return res = GIMarshallingTests.float_inout flt assert_in_epsilon 1.175e-38, res end it 'has a working function #float_out' do flt = GIMarshallingTests.float_out assert_in_epsilon 3.402e+38, flt end it 'has a working function #float_return' do flt = GIMarshallingTests.float_return assert_in_epsilon 3.402e+38, flt end it 'has a working function #garray_int_none_in' do arr = [-1, 0, 1, 2] GIMarshallingTests.garray_int_none_in arr pass end it 'has a working function #garray_int_none_return' do arr = GIMarshallingTests.garray_int_none_return arr.must_be :==, [-1, 0, 1, 2] end it 'has a working function #garray_uint64_none_in' do skip unless get_introspection_data 'GIMarshallingTests', 'garray_uint64_none_in' GIMarshallingTests.garray_uint64_none_in [0, 0xffff_ffff_ffff_ffff] pass end it 'has a working function #garray_uint64_none_return' do skip unless get_introspection_data 'GIMarshallingTests', 'garray_uint64_none_return' res = GIMarshallingTests.garray_uint64_none_return res.must_be :==, [0, 0xffff_ffff_ffff_ffff] end it 'has a working function #garray_utf8_container_inout' do res = GIMarshallingTests.garray_utf8_container_inout %w(0 1 2) res.must_be :==, ['-2', '-1', '0', '1'] end it 'has a working function #garray_utf8_container_out' do res = GIMarshallingTests.garray_utf8_container_out res.must_be :==, %w(0 1 2) end it 'has a working function #garray_utf8_container_return' do res = GIMarshallingTests.garray_utf8_container_return res.must_be :==, %w(0 1 2) end it 'has a working function #garray_utf8_full_inout' do arr = %w(0 1 2) res = GIMarshallingTests.garray_utf8_full_inout arr res.must_be :==, ['-2', '-1', '0', '1'] end it 'has a working function #garray_utf8_full_out' do res = GIMarshallingTests.garray_utf8_full_out res.must_be :==, %w(0 1 2) end it 'has a working function #garray_utf8_full_out_caller_allocated' do skip unless get_introspection_data 'GIMarshallingTests', 'garray_utf8_full_out_caller_allocated' res = GIMarshallingTests.garray_utf8_full_out_caller_allocated res.must_be :==, %w(0 1 2) end it 'has a working function #garray_utf8_full_return' do res = GIMarshallingTests.garray_utf8_full_return res.must_be :==, %w(0 1 2) end it 'has a working function #garray_utf8_none_in' do arr = %w(0 1 2) GIMarshallingTests.garray_utf8_none_in arr pass end it 'has a working function #garray_utf8_none_inout' do arr = %w(0 1 2) res = GIMarshallingTests.garray_utf8_none_inout arr res.must_be :==, ['-2', '-1', '0', '1'] end it 'has a working function #garray_utf8_none_out' do res = GIMarshallingTests.garray_utf8_none_out res.must_be :==, %w(0 1 2) end it 'has a working function #garray_utf8_none_return' do res = GIMarshallingTests.garray_utf8_none_return res.must_be :==, %w(0 1 2) end it 'has a working function #gbytes_full_return' do skip unless get_introspection_data 'GIMarshallingTests', 'gbytes_full_return' res = GIMarshallingTests.gbytes_full_return res.to_a.must_equal [0, 49, 0xFF, 51] end it 'has a working function #gbytes_none_in' do skip unless get_introspection_data 'GIMarshallingTests', 'gbytes_none_in' GIMarshallingTests.gbytes_none_in [0, 49, 0xFF, 51] pass end it 'has a working function #gclosure_in' do cl = GObject::RubyClosure.new { 42 } GIMarshallingTests.gclosure_in cl pass end it 'has a working function #gclosure_return' do cl = GIMarshallingTests.gclosure_return gv = GObject::Value.wrap_ruby_value 0 result = cl.invoke gv, [] gv.get_value.must_equal 42 result.must_equal 42 end it 'has a working function #genum_in' do GIMarshallingTests.genum_in :value3 pass end it 'has a working function #genum_inout' do res = GIMarshallingTests.genum_inout :value3 res.must_equal :value1 end it 'has a working function #genum_out' do res = GIMarshallingTests.genum_out res.must_equal :value3 end it 'has a working function #genum_returnv' do res = GIMarshallingTests.genum_returnv res.must_equal :value3 end it 'has a working function #gerror' do begin GIMarshallingTests.gerror flunk 'Error should have been raised' rescue GirFFI::GLibError => e e.message.must_equal GIMarshallingTests::CONSTANT_GERROR_MESSAGE e.domain.must_equal GIMarshallingTests::CONSTANT_GERROR_DOMAIN e.code.must_equal GIMarshallingTests::CONSTANT_GERROR_CODE end end it 'has a working function #gerror_array_in' do begin GIMarshallingTests.gerror_array_in [1, 2, 3] flunk 'Error should have been raised' rescue GirFFI::GLibError => e e.message.must_equal GIMarshallingTests::CONSTANT_GERROR_MESSAGE e.domain.must_equal GIMarshallingTests::CONSTANT_GERROR_DOMAIN e.code.must_equal GIMarshallingTests::CONSTANT_GERROR_CODE end end it 'has a working function #gerror_out' do error, debug = GIMarshallingTests.gerror_out debug.must_equal GIMarshallingTests::CONSTANT_GERROR_DEBUG_MESSAGE error.message.must_equal GIMarshallingTests::CONSTANT_GERROR_MESSAGE end it 'has a working function #gerror_out_transfer_none' do error, debug = GIMarshallingTests.gerror_out_transfer_none debug.must_equal GIMarshallingTests::CONSTANT_GERROR_DEBUG_MESSAGE error.message.must_equal GIMarshallingTests::CONSTANT_GERROR_MESSAGE end it 'has a working function #gerror_return' do error = GIMarshallingTests.gerror_return error.message.must_equal GIMarshallingTests::CONSTANT_GERROR_MESSAGE end it 'has a working function #ghashtable_int_none_in' do GIMarshallingTests.ghashtable_int_none_in( -1 => 1, 0 => 0, 1 => -1, 2 => -2) end it 'has a working function #ghashtable_int_none_return' do gh = GIMarshallingTests.ghashtable_int_none_return assert_equal({ -1 => 1, 0 => 0, 1 => -1, 2 => -2 }, gh.to_hash) end it 'has a working function #ghashtable_utf8_container_in' do skip 'This function is defined in the header but not implemented' end it 'has a working function #ghashtable_utf8_container_inout' do hsh = { '-1' => '1', '0' => '0', '1' => '-1', '2' => '-2' } res = GIMarshallingTests.ghashtable_utf8_container_inout hsh assert_equal({ '-1' => '1', '0' => '0', '1' => '1' }, res.to_hash) end it 'has a working function #ghashtable_utf8_container_out' do res = GIMarshallingTests.ghashtable_utf8_container_out assert_equal({ '-1' => '1', '0' => '0', '1' => '-1', '2' => '-2' }, res.to_hash) end it 'has a working function #ghashtable_utf8_container_return' do res = GIMarshallingTests.ghashtable_utf8_container_return assert_equal({ '-1' => '1', '0' => '0', '1' => '-1', '2' => '-2' }, res.to_hash) end it 'has a working function #ghashtable_utf8_full_in' do skip 'This function is defined in the header but not implemented' end it 'has a working function #ghashtable_utf8_full_inout' do hsh = { '-1' => '1', '0' => '0', '1' => '-1', '2' => '-2' } res = GIMarshallingTests.ghashtable_utf8_full_inout hsh assert_equal({ '-1' => '1', '0' => '0', '1' => '1' }, res.to_hash) end it 'has a working function #ghashtable_utf8_full_out' do res = GIMarshallingTests.ghashtable_utf8_full_out assert_equal({ '-1' => '1', '0' => '0', '1' => '-1', '2' => '-2' }, res.to_hash) end it 'has a working function #ghashtable_utf8_full_return' do res = GIMarshallingTests.ghashtable_utf8_full_return assert_equal({ '-1' => '1', '0' => '0', '1' => '-1', '2' => '-2' }, res.to_hash) end it 'has a working function #ghashtable_utf8_none_in' do hsh = { '-1' => '1', '0' => '0', '1' => '-1', '2' => '-2' } GIMarshallingTests.ghashtable_utf8_none_in hsh pass end it 'has a working function #ghashtable_utf8_none_inout' do hsh = { '-1' => '1', '0' => '0', '1' => '-1', '2' => '-2' } res = GIMarshallingTests.ghashtable_utf8_none_inout hsh assert_equal({ '-1' => '1', '0' => '0', '1' => '1' }, res.to_hash) end it 'has a working function #ghashtable_utf8_none_out' do res = GIMarshallingTests.ghashtable_utf8_none_out assert_equal({ '-1' => '1', '0' => '0', '1' => '-1', '2' => '-2' }, res.to_hash) end it 'has a working function #ghashtable_utf8_none_return' do res = GIMarshallingTests.ghashtable_utf8_none_return assert_equal({ '-1' => '1', '0' => '0', '1' => '-1', '2' => '-2' }, res.to_hash) end it 'has a working function #glist_int_none_in' do GIMarshallingTests.glist_int_none_in [-1, 0, 1, 2] pass end it 'has a working function #glist_int_none_return' do res = GIMarshallingTests.glist_int_none_return res.must_be :==, [-1, 0, 1, 2] end it 'has a working function #glist_uint32_none_in' do skip unless get_introspection_data 'GIMarshallingTests', 'glist_uint32_none_in' GIMarshallingTests.glist_uint32_none_in [0, 0xffff_ffff] pass end it 'has a working function #glist_uint32_none_return' do skip unless get_introspection_data 'GIMarshallingTests', 'glist_uint32_none_return' res = GIMarshallingTests.glist_uint32_none_return res.must_be :==, [0, 0xffff_ffff] end it 'has a working function #glist_utf8_container_inout' do res = GIMarshallingTests.glist_utf8_container_inout %w(0 1 2) res.must_be :==, ['-2', '-1', '0', '1'] end it 'has a working function #glist_utf8_container_out' do res = GIMarshallingTests.glist_utf8_container_out res.must_be :==, %w(0 1 2) end it 'has a working function #glist_utf8_container_return' do res = GIMarshallingTests.glist_utf8_container_return res.must_be :==, %w(0 1 2) end it 'has a working function #glist_utf8_full_inout' do res = GIMarshallingTests.glist_utf8_full_inout %w(0 1 2) res.must_be :==, ['-2', '-1', '0', '1'] end it 'has a working function #glist_utf8_full_out' do res = GIMarshallingTests.glist_utf8_full_out res.must_be :==, %w(0 1 2) end it 'has a working function #glist_utf8_full_return' do res = GIMarshallingTests.glist_utf8_full_return res.must_be :==, %w(0 1 2) end it 'has a working function #glist_utf8_none_in' do GIMarshallingTests.glist_utf8_none_in %w(0 1 2) end it 'has a working function #glist_utf8_none_inout' do res = GIMarshallingTests.glist_utf8_none_inout %w(0 1 2) res.must_be :==, ['-2', '-1', '0', '1'] end it 'has a working function #glist_utf8_none_out' do res = GIMarshallingTests.glist_utf8_none_out res.must_be :==, %w(0 1 2) end it 'has a working function #glist_utf8_none_return' do res = GIMarshallingTests.glist_utf8_none_return res.must_be :==, %w(0 1 2) end it 'has a working function #gptrarray_utf8_container_inout' do res = GIMarshallingTests.gptrarray_utf8_container_inout %w(0 1 2) res.must_be :==, ['-2', '-1', '0', '1'] end it 'has a working function #gptrarray_utf8_container_out' do res = GIMarshallingTests.gptrarray_utf8_container_out res.must_be :==, %w(0 1 2) end it 'has a working function #gptrarray_utf8_container_return' do res = GIMarshallingTests.gptrarray_utf8_container_return res.must_be :==, %w(0 1 2) end it 'has a working function #gptrarray_utf8_full_inout' do res = GIMarshallingTests.gptrarray_utf8_full_inout %w(0 1 2) res.must_be :==, ['-2', '-1', '0', '1'] end it 'has a working function #gptrarray_utf8_full_out' do res = GIMarshallingTests.gptrarray_utf8_full_out res.must_be :==, %w(0 1 2) end it 'has a working function #gptrarray_utf8_full_return' do res = GIMarshallingTests.gptrarray_utf8_full_return res.must_be :==, %w(0 1 2) end it 'has a working function #gptrarray_utf8_none_in' do GIMarshallingTests.gptrarray_utf8_none_in %w(0 1 2) end it 'has a working function #gptrarray_utf8_none_inout' do res = GIMarshallingTests.gptrarray_utf8_none_inout %w(0 1 2) res.must_be :==, ['-2', '-1', '0', '1'] end it 'has a working function #gptrarray_utf8_none_out' do res = GIMarshallingTests.gptrarray_utf8_none_out res.must_be :==, %w(0 1 2) end it 'has a working function #gptrarray_utf8_none_return' do res = GIMarshallingTests.gptrarray_utf8_none_return res.must_be :==, %w(0 1 2) end it 'has a working function #gslist_int_none_in' do GIMarshallingTests.gslist_int_none_in [-1, 0, 1, 2] pass end it 'has a working function #gslist_int_none_return' do res = GIMarshallingTests.gslist_int_none_return res.must_be :==, [-1, 0, 1, 2] end it 'has a working function #gslist_utf8_container_inout' do res = GIMarshallingTests.gslist_utf8_container_inout %w(0 1 2) res.must_be :==, ['-2', '-1', '0', '1'] end it 'has a working function #gslist_utf8_container_out' do res = GIMarshallingTests.gslist_utf8_container_out res.must_be :==, %w(0 1 2) end it 'has a working function #gslist_utf8_container_return' do res = GIMarshallingTests.gslist_utf8_container_return res.must_be :==, %w(0 1 2) end it 'has a working function #gslist_utf8_full_inout' do res = GIMarshallingTests.gslist_utf8_full_inout %w(0 1 2) res.must_be :==, ['-2', '-1', '0', '1'] end it 'has a working function #gslist_utf8_full_out' do res = GIMarshallingTests.gslist_utf8_full_out res.must_be :==, %w(0 1 2) end it 'has a working function #gslist_utf8_full_return' do res = GIMarshallingTests.gslist_utf8_full_return res.must_be :==, %w(0 1 2) end it 'has a working function #gslist_utf8_none_in' do GIMarshallingTests.gslist_utf8_none_in %w(0 1 2) pass end it 'has a working function #gslist_utf8_none_inout' do res = GIMarshallingTests.gslist_utf8_none_inout %w(0 1 2) res.must_be :==, ['-2', '-1', '0', '1'] end it 'has a working function #gslist_utf8_none_out' do res = GIMarshallingTests.gslist_utf8_none_out res.must_be :==, %w(0 1 2) end it 'has a working function #gslist_utf8_none_return' do res = GIMarshallingTests.gslist_utf8_none_return res.must_be :==, %w(0 1 2) end it 'has a working function #gstrv_in' do GIMarshallingTests.gstrv_in %w(0 1 2) pass end it 'has a working function #gstrv_inout' do res = GIMarshallingTests.gstrv_inout %w(0 1 2) res.must_be :==, ['-1', '0', '1', '2'] end it 'has a working function #gstrv_out' do res = GIMarshallingTests.gstrv_out res.must_be :==, %w(0 1 2) end it 'has a working function #gstrv_return' do res = GIMarshallingTests.gstrv_return res.must_be :==, %w(0 1 2) end it 'has a working function #gtype_in' do GIMarshallingTests.gtype_in GObject::TYPE_NONE pass end it 'has a working function #gtype_inout' do res = GIMarshallingTests.gtype_inout GObject::TYPE_NONE res.must_equal GObject::TYPE_INT end it 'has a working function #gtype_out' do res = GIMarshallingTests.gtype_out res.must_equal GObject::TYPE_NONE end it 'has a working function #gtype_return' do res = GIMarshallingTests.gtype_return res.must_equal GObject::TYPE_NONE end it 'has a working function #gtype_string_in' do GIMarshallingTests.gtype_string_in GObject::TYPE_STRING pass end it 'has a working function #gtype_string_out' do res = GIMarshallingTests.gtype_string_out res.must_equal GObject::TYPE_STRING end it 'has a working function #gtype_string_return' do res = GIMarshallingTests.gtype_string_return res.must_equal GObject::TYPE_STRING end it 'has a working function #gvalue_flat_array' do GIMarshallingTests.gvalue_flat_array [42, '42', true] pass end it 'has a working function #gvalue_flat_array_round_trip' do result = GIMarshallingTests.gvalue_flat_array_round_trip 42, '42', true arr = result.to_a arr[0].get_value.must_equal 42 arr[1].get_value.must_equal '42' arr[2].get_value.must_equal true end it 'has a working function #gvalue_in' do GIMarshallingTests.gvalue_in GObject::Value.wrap_ruby_value(42) GIMarshallingTests.gvalue_in 42 pass end it 'has a working function #gvalue_in_enum' do gv = GObject::Value.new gv.init GIMarshallingTests::GEnum.gtype gv.set_enum GIMarshallingTests::GEnum[:value3] GIMarshallingTests.gvalue_in_enum gv pass end it 'has a working function #gvalue_in_with_modification' do skip unless get_introspection_data 'GIMarshallingTests', 'gvalue_in_with_modification' gv = GObject::Value.wrap_ruby_value(42) GIMarshallingTests.gvalue_in_with_modification gv gv.get_value.must_equal 24 end it 'has a working function #gvalue_in_with_type' do gv = GObject::Value.new gv.init GIMarshallingTests::SubSubObject.gtype GIMarshallingTests.gvalue_in_with_type gv, GIMarshallingTests::Object.gtype end it 'has a working function #gvalue_inout' do res = GIMarshallingTests.gvalue_inout GObject::Value.wrap_ruby_value(42) res.must_equal '42' res = GIMarshallingTests.gvalue_inout 42 res.must_equal '42' end it 'has a working function #gvalue_int64_in' do skip unless get_introspection_data 'GIMarshallingTests', 'gvalue_int64_in' gv = GObject::Value.new gv.init GObject::TYPE_INT64 gv.set_value 0x7fff_ffff_ffff_ffff GIMarshallingTests.gvalue_int64_in gv pass end it 'has a working function #gvalue_int64_out' do skip unless get_introspection_data 'GIMarshallingTests', 'gvalue_int64_out' gv = GIMarshallingTests.gvalue_int64_out gv.must_equal 0x7fff_ffff_ffff_ffff end it 'has a working function #gvalue_out' do res = GIMarshallingTests.gvalue_out res.must_equal 42 end it 'has a working function #gvalue_out_caller_allocates' do skip unless get_introspection_data 'GIMarshallingTests', 'gvalue_out_caller_allocates' res = GIMarshallingTests.gvalue_out_caller_allocates res.must_equal 42 end it 'has a working function #gvalue_return' do res = GIMarshallingTests.gvalue_return res.must_equal 42 end it 'has a working function #init_function' do res, arr = GIMarshallingTests.init_function %w(foo bar baz) res.must_equal true arr.must_be :==, %w(foo bar) end it 'has a working function #int16_in_max' do GIMarshallingTests.int16_in_max 0x7fff pass end it 'has a working function #int16_in_min' do GIMarshallingTests.int16_in_min(-0x8000) pass end it 'has a working function #int16_inout_max_min' do res = GIMarshallingTests.int16_inout_max_min 0x7fff assert_equal res, -0x8000 end it 'has a working function #int16_inout_min_max' do res = GIMarshallingTests.int16_inout_min_max(-0x8000) assert_equal 0x7fff, res end it 'has a working function #int16_out_max' do res = GIMarshallingTests.int16_out_max assert_equal 0x7fff, res end it 'has a working function #int16_out_min' do res = GIMarshallingTests.int16_out_min assert_equal(-0x8000, res) end it 'has a working function #int16_return_max' do res = GIMarshallingTests.int16_return_max assert_equal 0x7fff, res end it 'has a working function #int16_return_min' do res = GIMarshallingTests.int16_return_min assert_equal(-0x8000, res) end it 'has a working function #int32_in_max' do GIMarshallingTests.int32_in_max 0x7fffffff pass end it 'has a working function #int32_in_min' do GIMarshallingTests.int32_in_min(-0x80000000) pass end it 'has a working function #int32_inout_max_min' do res = GIMarshallingTests.int32_inout_max_min 0x7fffffff assert_equal(-0x80000000, res) end it 'has a working function #int32_inout_min_max' do res = GIMarshallingTests.int32_inout_min_max(-0x80000000) assert_equal 0x7fffffff, res end it 'has a working function #int32_out_max' do res = GIMarshallingTests.int32_out_max assert_equal 0x7fffffff, res end it 'has a working function #int32_out_min' do res = GIMarshallingTests.int32_out_min assert_equal(-0x80000000, res) end it 'has a working function #int32_return_max' do res = GIMarshallingTests.int32_return_max assert_equal 0x7fffffff, res end it 'has a working function #int32_return_min' do res = GIMarshallingTests.int32_return_min assert_equal(-0x80000000, res) end it 'has a working function #int64_in_max' do GIMarshallingTests.int64_in_max 0x7fffffffffffffff pass end it 'has a working function #int64_in_min' do GIMarshallingTests.int64_in_min(-0x8000000000000000) pass end it 'has a working function #int64_inout_max_min' do res = GIMarshallingTests.int64_inout_max_min 0x7fffffffffffffff assert_equal(-0x8000000000000000, res) end it 'has a working function #int64_inout_min_max' do res = GIMarshallingTests.int64_inout_min_max(-0x8000000000000000) assert_equal 0x7fffffffffffffff, res end it 'has a working function #int64_out_max' do res = GIMarshallingTests.int64_out_max assert_equal 0x7fffffffffffffff, res end it 'has a working function #int64_out_min' do res = GIMarshallingTests.int64_out_min assert_equal(-0x8000000000000000, res) end it 'has a working function #int64_return_max' do res = GIMarshallingTests.int64_return_max assert_equal 0x7fffffffffffffff, res end it 'has a working function #int64_return_min' do res = GIMarshallingTests.int64_return_min assert_equal(-0x8000000000000000, res) end it 'has a working function #int8_in_max' do GIMarshallingTests.int8_in_max 0x7f pass end it 'has a working function #int8_in_min' do GIMarshallingTests.int8_in_min(-0x80) pass end it 'has a working function #int8_inout_max_min' do res = GIMarshallingTests.int8_inout_max_min 0x7f assert_equal(-0x80, res) end it 'has a working function #int8_inout_min_max' do res = GIMarshallingTests.int8_inout_min_max(-0x80) assert_equal 0x7f, res end it 'has a working function #int8_out_max' do res = GIMarshallingTests.int8_out_max assert_equal 0x7f, res end it 'has a working function #int8_out_min' do res = GIMarshallingTests.int8_out_min assert_equal(-0x80, res) end it 'has a working function #int8_return_max' do res = GIMarshallingTests.int8_return_max assert_equal 0x7f, res end it 'has a working function #int8_return_min' do res = GIMarshallingTests.int8_return_min assert_equal(-0x80, res) end it 'has a working function #int_in_max' do GIMarshallingTests.int_in_max 0x7fffffff pass end it 'has a working function #int_in_min' do GIMarshallingTests.int_in_min(-0x80000000) pass end it 'has a working function #int_inout_max_min' do res = GIMarshallingTests.int_inout_max_min 0x7fffffff assert_equal(-0x80000000, res) end it 'has a working function #int_inout_min_max' do res = GIMarshallingTests.int_inout_min_max(-0x80000000) assert_equal 0x7fffffff, res end it 'has a working function #int_one_in_utf8_two_in_one_allows_none' do skip unless get_introspection_data('GIMarshallingTests', 'int_one_in_utf8_two_in_one_allows_none') GIMarshallingTests.int_one_in_utf8_two_in_one_allows_none 1, '2', '3' GIMarshallingTests.int_one_in_utf8_two_in_one_allows_none 1, nil, '3' pass end it 'has a working function #int_out_max' do res = GIMarshallingTests.int_out_max assert_equal 0x7fffffff, res end it 'has a working function #int_out_min' do res = GIMarshallingTests.int_out_min assert_equal(-0x80000000, res) end it 'has a working function #int_out_out' do res = GIMarshallingTests.int_out_out assert_equal [6, 7], res end it 'has a working function #int_return_max' do res = GIMarshallingTests.int_return_max assert_equal 0x7fffffff, res end it 'has a working function #int_return_min' do res = GIMarshallingTests.int_return_min assert_equal(-0x80000000, res) end it 'has a working function #int_return_out' do res = GIMarshallingTests.int_return_out assert_equal [6, 7], res end it 'has a working function #int_three_in_three_out' do res = GIMarshallingTests.int_three_in_three_out 4, 5, 6 assert_equal [4, 5, 6], res end it 'has a working function #int_two_in_utf8_two_in_with_allow_none' do skip unless get_introspection_data('GIMarshallingTests', 'int_two_in_utf8_two_in_with_allow_none') GIMarshallingTests.int_two_in_utf8_two_in_with_allow_none 1, 2, '3', '4' GIMarshallingTests.int_two_in_utf8_two_in_with_allow_none 1, 2, nil, nil pass end it 'has a working function #long_in_max' do GIMarshallingTests.long_in_max max_long pass end it 'has a working function #long_in_min' do GIMarshallingTests.long_in_min min_long pass end it 'has a working function #long_inout_max_min' do res = GIMarshallingTests.long_inout_max_min max_long assert_equal min_long, res end it 'has a working function #long_inout_min_max' do res = GIMarshallingTests.long_inout_min_max min_long assert_equal max_long, res end it 'has a working function #long_out_max' do res = GIMarshallingTests.long_out_max assert_equal max_long, res end it 'has a working function #long_out_min' do res = GIMarshallingTests.long_out_min assert_equal min_long, res end it 'has a working function #long_return_max' do res = GIMarshallingTests.long_return_max assert_equal max_long, res end it 'has a working function #long_return_min' do res = GIMarshallingTests.long_return_min assert_equal min_long, res end it 'has a working function #multi_array_key_value_in' do keys = %w(one two three) values = [1, 2, 3].map { |val| GObject::Value.wrap_ruby_value val } GIMarshallingTests.multi_array_key_value_in keys, values end it 'has a working function #no_type_flags_in' do GIMarshallingTests.no_type_flags_in value2: true pass end it 'has a working function #no_type_flags_in_zero' do GIMarshallingTests.no_type_flags_in_zero 0 pass end it 'has a working function #no_type_flags_inout' do res = GIMarshallingTests.no_type_flags_inout value2: true res.must_equal(value1: true) end it 'has a working function #no_type_flags_out' do res = GIMarshallingTests.no_type_flags_out res.must_equal(value2: true) end it 'has a working function #no_type_flags_returnv' do res = GIMarshallingTests.no_type_flags_returnv res.must_equal(value2: true) end it 'has a working function #overrides_struct_returnv' do res = GIMarshallingTests.overrides_struct_returnv res.must_be_instance_of GIMarshallingTests::OverridesStruct end it 'has a working function #param_spec_in_bool' do # GLib minor version and GObjectIntrospection minor version should be in sync skip 'param_spec_in_bool tests the wrong type' if GLib::MINOR_VERSION < 42 ps = GObject.param_spec_boolean 'mybool', 'nick', 'blurb', true, :readable GIMarshallingTests.param_spec_in_bool ps pass end it 'has a working function #param_spec_out' do skip unless get_introspection_data 'GIMarshallingTests', 'param_spec_out' res = GIMarshallingTests.param_spec_out res.value_type.must_equal GObject::TYPE_STRING res.get_name.must_equal 'test-param' end it 'has a working function #param_spec_return' do skip unless get_introspection_data 'GIMarshallingTests', 'param_spec_return' res = GIMarshallingTests.param_spec_return res.value_type.must_equal GObject::TYPE_STRING res.get_name.must_equal 'test-param' end it 'has a working function #pointer_in_return' do ptr = FFI::MemoryPointer.new 1 res = GIMarshallingTests.pointer_in_return ptr assert_equal ptr.address, res.address end it 'has a working function #pointer_struct_get_type' do res = GIMarshallingTests.pointer_struct_get_type gtype = GObject.type_from_name 'GIMarshallingTestsPointerStruct' assert_equal gtype, res end it 'has a working function #pointer_struct_returnv' do res = GIMarshallingTests.pointer_struct_returnv assert_instance_of GIMarshallingTests::PointerStruct, res assert_equal 42, res.long_ end it 'has a working function #return_gvalue_flat_array' do result = GIMarshallingTests.return_gvalue_flat_array arr = result.to_a arr[0].get_value.must_equal 42 arr[1].get_value.must_equal '42' arr[2].get_value.must_equal true end it 'has a working function #short_in_max' do GIMarshallingTests.short_in_max 0x7fff pass end it 'has a working function #short_in_min' do GIMarshallingTests.short_in_min(-0x8000) pass end it 'has a working function #short_inout_max_min' do res = GIMarshallingTests.short_inout_max_min 0x7fff assert_equal(-0x8000, res) end it 'has a working function #short_inout_min_max' do res = GIMarshallingTests.short_inout_min_max(-0x8000) assert_equal 0x7fff, res end it 'has a working function #short_out_max' do res = GIMarshallingTests.short_out_max assert_equal 0x7fff, res end it 'has a working function #short_out_min' do res = GIMarshallingTests.short_out_min assert_equal(-0x8000, res) end it 'has a working function #short_return_max' do res = GIMarshallingTests.short_return_max assert_equal 0x7fff, res end it 'has a working function #short_return_min' do res = GIMarshallingTests.short_return_min assert_equal(-0x8000, res) end it 'has a working function #simple_struct_returnv' do res = GIMarshallingTests.simple_struct_returnv assert_instance_of GIMarshallingTests::SimpleStruct, res assert_equal 6, res.long_ assert_equal 7, res.int8 end it 'has a working function #size_in' do GIMarshallingTests.size_in max_size_t end it 'has a working function #size_inout' do res = GIMarshallingTests.size_inout max_size_t assert_equal 0, res end it 'has a working function #size_out' do res = GIMarshallingTests.size_out assert_equal max_size_t, res end it 'has a working function #size_return' do res = GIMarshallingTests.size_return assert_equal max_size_t, res end it 'has a working function #ssize_in_max' do GIMarshallingTests.ssize_in_max max_ssize_t pass end it 'has a working function #ssize_in_min' do GIMarshallingTests.ssize_in_min min_ssize_t pass end it 'has a working function #ssize_inout_max_min' do res = GIMarshallingTests.ssize_inout_max_min max_ssize_t assert_equal min_ssize_t, res end it 'has a working function #ssize_inout_min_max' do res = GIMarshallingTests.ssize_inout_min_max min_ssize_t assert_equal max_ssize_t, res end it 'has a working function #ssize_out_max' do res = GIMarshallingTests.ssize_out_max assert_equal max_ssize_t, res end it 'has a working function #ssize_out_min' do res = GIMarshallingTests.ssize_out_min assert_equal min_ssize_t, res end it 'has a working function #ssize_return_max' do res = GIMarshallingTests.ssize_return_max assert_equal max_ssize_t, res end it 'has a working function #ssize_return_min' do res = GIMarshallingTests.ssize_return_min assert_equal min_ssize_t, res end it 'has a working function #test_interface_test_int8_in' do derived_klass.class_eval { include GIMarshallingTests::Interface } instance = make_derived_instance do |info| info.install_vfunc_implementation :test_int8_in, proc { |obj, in_| obj.int = in_ } end instance.int.must_equal 0 GIMarshallingTests.test_interface_test_int8_in instance, 8 instance.int.must_equal 8 end it 'has a working function #time_t_in' do GIMarshallingTests.time_t_in 1_234_567_890 pass end it 'has a working function #time_t_inout' do res = GIMarshallingTests.time_t_inout 1_234_567_890 assert_equal 0, res end it 'has a working function #time_t_out' do res = GIMarshallingTests.time_t_out assert_equal 1_234_567_890, res end it 'has a working function #time_t_return' do res = GIMarshallingTests.time_t_return assert_equal 1_234_567_890, res end it 'has a working function #uint16_in' do GIMarshallingTests.uint16_in 0xffff pass end it 'has a working function #uint16_inout' do res = GIMarshallingTests.uint16_inout 0xffff assert_equal 0, res end it 'has a working function #uint16_out' do res = GIMarshallingTests.uint16_out assert_equal 0xffff, res end it 'has a working function #uint16_return' do res = GIMarshallingTests.uint16_return assert_equal 0xffff, res end it 'has a working function #uint32_in' do GIMarshallingTests.uint32_in 0xffffffff end it 'has a working function #uint32_inout' do res = GIMarshallingTests.uint32_inout 0xffffffff assert_equal 0, res end it 'has a working function #uint32_out' do res = GIMarshallingTests.uint32_out assert_equal 0xffffffff, res end it 'has a working function #uint32_return' do res = GIMarshallingTests.uint32_return assert_equal 0xffffffff, res end it 'has a working function #uint64_in' do GIMarshallingTests.uint64_in 0xffff_ffff_ffff_ffff pass end it 'has a working function #uint64_inout' do res = GIMarshallingTests.uint64_inout 0xffff_ffff_ffff_ffff assert_equal 0, res end it 'has a working function #uint64_out' do res = GIMarshallingTests.uint64_out assert_equal 0xffff_ffff_ffff_ffff, res end it 'has a working function #uint64_return' do res = GIMarshallingTests.uint64_return assert_equal 0xffff_ffff_ffff_ffff, res end it 'has a working function #uint8_in' do GIMarshallingTests.uint8_in 0xff end it 'has a working function #uint8_inout' do res = GIMarshallingTests.uint8_inout 0xff assert_equal 0, res end it 'has a working function #uint8_out' do res = GIMarshallingTests.uint8_out assert_equal 0xff, res end it 'has a working function #uint8_return' do res = GIMarshallingTests.uint8_return assert_equal 0xff, res end it 'has a working function #uint_in' do GIMarshallingTests.uint_in max_uint pass end it 'has a working function #uint_inout' do res = GIMarshallingTests.uint_inout max_uint assert_equal 0, res end it 'has a working function #uint_out' do res = GIMarshallingTests.uint_out assert_equal max_uint, res end it 'has a working function #uint_return' do res = GIMarshallingTests.uint_return assert_equal max_uint, res end it 'has a working function #ulong_in' do GIMarshallingTests.ulong_in max_ulong end it 'has a working function #ulong_inout' do res = GIMarshallingTests.ulong_inout max_ulong assert_equal 0, res end it 'has a working function #ulong_out' do res = GIMarshallingTests.ulong_out assert_equal max_ulong, res end it 'has a working function #ulong_return' do res = GIMarshallingTests.ulong_return assert_equal max_ulong, res end it 'has a working function #union_inout' do skip 'This function is defined in the header but not implemented' end it 'has a working function #union_out' do skip 'This function is defined in the header but not implemented' end it 'has a working function #union_returnv' do res = GIMarshallingTests.union_returnv assert_instance_of GIMarshallingTests::Union, res assert_equal 42, res.long_ end it 'has a working function #ushort_in' do GIMarshallingTests.ushort_in max_ushort pass end it 'has a working function #ushort_inout' do res = GIMarshallingTests.ushort_inout max_ushort assert_equal 0, res end it 'has a working function #ushort_out' do res = GIMarshallingTests.ushort_out assert_equal max_ushort, res end it 'has a working function #ushort_return' do res = GIMarshallingTests.ushort_return assert_equal max_ushort, res end it 'has a working function #utf8_as_uint8array_in' do skip unless get_introspection_data 'GIMarshallingTests', 'utf8_as_uint8array_in' GIMarshallingTests.utf8_as_uint8array_in GIMarshallingTests::CONSTANT_UTF8.bytes.to_a pass end it 'has a working function #utf8_dangling_out' do res = GIMarshallingTests.utf8_dangling_out assert_nil res end it 'has a working function #utf8_full_in' do skip 'This function is defined in the header but not implemented' end it 'has a working function #utf8_full_inout' do res = GIMarshallingTests.utf8_full_inout 'const ♥ utf8' assert_equal '', res end it 'has a working function #utf8_full_out' do res = GIMarshallingTests.utf8_full_out assert_equal 'const ♥ utf8', res end it 'has a working function #utf8_full_return' do res = GIMarshallingTests.utf8_full_return assert_equal 'const ♥ utf8', res end it 'has a working function #utf8_none_in' do GIMarshallingTests.utf8_none_in 'const ♥ utf8' pass end it 'has a working function #utf8_none_inout' do res = GIMarshallingTests.utf8_none_inout 'const ♥ utf8' assert_equal '', res end it 'has a working function #utf8_none_out' do res = GIMarshallingTests.utf8_none_out assert_equal 'const ♥ utf8', res end it 'has a working function #utf8_none_return' do res = GIMarshallingTests.utf8_none_return assert_equal 'const ♥ utf8', res end end gir_ffi-0.11.4/test/integration/generated_utility_test.rb0000644000004100000410000001045713170036060023644 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :Utility describe Utility do describe 'Utility::Buffer' do let(:instance) { Utility::Buffer.new } it 'has a writable field data' do instance.data.must_equal FFI::Pointer::NULL instance.data = FFI::Pointer.new 54_321 instance.data.must_equal FFI::Pointer.new 54_321 end it 'has a writable field length' do instance.length.must_equal 0 instance.length = 42 instance.length.must_equal 42 end end describe 'Utility::Byte' do let(:instance) { Utility::Byte.new } it 'has a writable field value' do instance.value.must_equal 0 instance.value = 42 instance.value.must_equal 42 end it 'has a writable field first_nibble' do skip 'This field is not exposed in the GIR' instance.value = 0xAB instance.first_nibble.must_equal 0xA instance.first_nibble = 0x4 instance.value.must_equal 0x4B end it 'has a writable field second_nibble' do skip 'This field is not exposed in the GIR' instance.value = 0xAB instance.second_nibble.must_equal 0xB instance.second_nibble = 0x4 instance.value.must_equal 0xA4 end end describe 'Utility::EnumType' do it 'has the member :a' do Utility::EnumType[:a].must_equal 0 end it 'has the member :b' do Utility::EnumType[:b].must_equal 1 end it 'has the member :c' do Utility::EnumType[:c].must_equal 2 end end describe 'Utility::FlagType' do it 'has the member :a' do Utility::FlagType[:a].must_equal 1 end it 'has the member :b' do Utility::FlagType[:b].must_equal 2 end it 'has the member :c' do Utility::FlagType[:c].must_equal 4 end end describe 'Utility::Object' do let(:instance) { Utility::Object.new } it 'has a working method #watch_dir' do # This method doesn't actually do anything instance.watch_dir('/') {} pass end end describe 'Utility::Struct' do let(:instance) { Utility::Struct.new } it 'has a writable field field' do instance.field.must_equal 0 instance.field = 42 instance.field.must_equal 42 end it 'has a writable field bitfield1' do skip 'Bitfield bit width is not implemented yet' instance.bitfield1.must_equal 0 instance.bitfield1 = 15 instance.bitfield1.must_equal 7 end it 'has a writable field bitfield2' do skip 'Bitfield bit width is not implemented yet' instance.bitfield2.must_equal 0 instance.bitfield2 = 15 instance.bitfield2.must_equal 3 end it 'has a writable field data' do instance.data.to_a.must_equal [0] * 16 end end describe 'Utility::TaggedValue' do let(:instance) { Utility::TaggedValue.new } it 'has a writable field tag' do instance.tag.must_equal 0 instance.tag = 42 instance.tag.must_equal 42 end it 'has a writable field v_pointer' do skip 'This field is not exposed in the GIR' instance.v_pointer.must_equal FFI::Pointer::NULL instance.v_pointer = FFI::Pointer.new(4321) instance.v_pointer.must_equal FFI::Pointer.new(4321) end it 'has a writable field v_real' do skip 'This field is not exposed in the GIR' instance.v_real.must_equal 0.0 instance.v_real = 42.23 instance.v_real.must_equal 42.23 end it 'has a writable field v_integer' do skip 'This field is not exposed in the GIR' instance.v_integer.must_equal 0 instance.v_integer = 42 instance.v_integer.must_equal 42 end end describe 'Utility::Union' do let(:instance) { Utility::Union.new } it 'has a writable field pointer' do instance.pointer.must_be_nil instance.pointer = 'hello 42' instance.pointer.must_equal 'hello 42' end it 'has a writable field integer' do instance.integer.must_equal 0 instance.integer = 42 instance.integer.must_equal 42 end it 'has a writable field real' do instance.real.must_equal 0.0 instance.real = 42.23 instance.real.must_equal 42.23 end end it 'has a working function #dir_foreach' do # This method doesn't actually do anything result = Utility.dir_foreach('/') {} result.must_be_nil end end gir_ffi-0.11.4/test/integration/generated_gtop_test.rb0000644000004100000410000000131113170036060023077 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' # Tests generated methods and functions in the GTop namespace. This namespace # contains types with bad names, like 'glibtop_cpu'. describe 'The generated GTop module' do before do begin GirFFI.setup :GTop rescue RuntimeError skip 'No GIR data for GTop available' end end describe 'Glibtop' do it 'is a valid struct class' do GTop::Glibtop.ancestors.must_include GirFFI::StructBase end it 'can be created using Glibtop.init' do skip unless get_method_introspection_data 'GTop', 'glibtop', 'init' instance = GTop::Glibtop.init instance.must_be_kind_of GTop::Glibtop end end end gir_ffi-0.11.4/test/integration/derived_classes_test.rb0000644000004100000410000000230413170036060023252 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :Regress # Tests deriving Ruby classes from GObject classes. describe 'For derived classes' do describe 'setting up methods when first called' do before do save_module :GIMarshallingTests GirFFI.setup :GIMarshallingTests end describe 'when an interface is mixed in' do before do @klass = Class.new GIMarshallingTests::OverridesObject @klass.send :include, GIMarshallingTests::Interface end it 'finds class methods in the superclass' do @klass.returnv end it 'finds instance methods in the superclass' do obj = @klass.new result = obj.method result.must_equal 42 end end after do restore_module :GIMarshallingTests end end describe 'the initializer' do it 'works if it calls super' do klass = Class.new Regress::TestSubObj do attr_reader :animal def initialize(animal) super() @animal = animal end end obj = klass.new 'dog' obj.must_be_instance_of klass obj.to_ptr.wont_be_nil obj.animal.must_equal 'dog' end end end gir_ffi-0.11.4/test/integration/callback_exceptions_test.rb0000644000004100000410000000321613170036060024113 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :Regress class CallbackTestException < RuntimeError; end describe 'An exception in a callback' do describe 'for signals' do let(:object) { Regress::TestSubObj.new } before do object.signal_connect 'test' do raise CallbackTestException, 'Boom' end end describe 'when the signal is emitted synchronously' do it 'raises an error' do proc { GObject.signal_emit object, 'test' }.must_raise CallbackTestException end end describe 'when the signal is emitted during an event loop' do it 'causes loop run to be terminated with an exception' do main_loop = GLib::MainLoop.new nil, false GLib.timeout_add GLib::PRIORITY_DEFAULT, 1 do GObject.signal_emit object, 'test' false end # Guard against runaway loop GLib.timeout_add GLib::PRIORITY_DEFAULT, 500 do main_loop.quit end proc do main_loop.run end.must_raise CallbackTestException end end end describe 'for other callbacks' do describe 'when the callback occurs during an event loop' do it 'causes loop run to be terminated with an exception' do main_loop = GLib::MainLoop.new nil, false GLib.timeout_add GLib::PRIORITY_DEFAULT, 1 do raise CallbackTestException, 'Boom' end # Guard against runaway loop GLib.timeout_add GLib::PRIORITY_DEFAULT, 500 do main_loop.quit end proc do main_loop.run end.must_raise CallbackTestException end end end end gir_ffi-0.11.4/test/integration/generated_pango_test.rb0000644000004100000410000000110013170036060023226 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :Pango # Tests generated methods and functions in the Pango namespace. describe Pango do describe Pango::Language do it 'has a working method #get_scripts' do lang = Pango::Language.from_string 'ja' result = lang.get_scripts if result.is_a? GirFFI::SizedArray scripts = result else ptr, size = *result scripts = GirFFI::SizedArray.new Pango::Script, size, ptr end scripts.must_be :==, [:han, :katakana, :hiragana] end end end gir_ffi-0.11.4/test/integration/generated_gobject_test.rb0000644000004100000410000000665013170036060023556 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :Regress describe GObject do describe '.type_interfaces' do it 'works, showing that returning an array of GType works' do klass = GObject::TypeModule ifcs = GObject.type_interfaces klass.gtype assert_equal 1, ifcs.size end end describe '.signal_set_va_marshaller' do it 'can be set up' do result = GObject.setup_method 'signal_set_va_marshaller' result.must_equal true end end describe GObject::TypeInfo do let(:instance) { GObject::TypeInfo.new } it 'has a working field setter for class_init' do instance.class_init = proc do |_object_class, _data| end end it 'has a working field getter for class_init' do instance.class_init.must_be_nil instance.class_init = proc do |_object_class, _data| end result = instance.class_init result.wont_be_nil result.must_be_instance_of FFI::Function end end describe GObject::TypePlugin do it 'is implemented as a module' do mod = GObject::TypePlugin assert_instance_of Module, mod refute_instance_of Class, mod end end describe GObject::TypeModule do it 'has the GObject::TypePlugin module as an ancestor' do klass = GObject::TypeModule assert_includes klass.ancestors, GObject::TypePlugin end end describe GObject::ValueArray do it 'uses the constructor provided by GObject' do instance = GObject::ValueArray.new 16 instance.n_prealloced.must_equal 16 instance.n_values.must_equal 0 end end describe GObject::SignalQuery do it 'works' do GObject::SignalQuery.new pass end it 'uses the n_params field for the length of param_types' do field_info = get_field_introspection_data 'GObject', 'SignalQuery', 'param_types' skip if field_info.field_type.array_length < 0 gtype = GObject::Object.gtype signals = GObject.signal_list_ids gtype signal_query = GObject.signal_query signals.first signal_query.n_params.must_equal 1 signal_query.param_types.size.must_equal 1 end end describe GObject::Binding do it 'is created with GObject::Object#bind_property' do source = Regress::TestObj.constructor target = Regress::TestObj.constructor binding = source.bind_property 'double', target, 'double', :default binding.must_be_kind_of GObject::Binding end describe 'an instance' do let(:source) { Regress::TestObj.constructor } let(:target) { Regress::TestObj.constructor } let(:binding) { source.bind_property 'double', target, 'double', :default } it 'can read the property "target-property" with #get_property' do binding.get_property('target-property').must_equal 'double' end it 'can read the property "target-property" with #target_property' do binding.target_property.must_equal 'double' end it 'cannot write the property "target-property" with #target_property=' do binding.wont_respond_to :target_property= end end end describe GObject::ParamSpec do it 'does not have a separate #name field accessor' do pspec = GObject.param_spec_int('foo', 'foo bar', 'The Foo Bar Property', 10, 20, 15, 3) pspec.wont_respond_to :name end end end gir_ffi-0.11.4/test/integration/generated_regress_test.rb0000644000004100000410000033600413170036060023612 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :Regress if IntrospectionTestExtensions.get_introspection_data 'Regress', 'TestInheritDrawable' class ConcreteDrawable < Regress::TestInheritDrawable end GirFFI.define_type ConcreteDrawable end # Tests generated methods and functions in the Regress namespace. describe Regress do describe Regress::Lib do it 'extends FFI::Library' do class << Regress::Lib must_be :include?, FFI::Library end end end it 'has the constant ANNOTATION_CALCULATED_DEFINE' do skip unless get_introspection_data 'Regress', 'ANNOTATION_CALCULATED_DEFINE' Regress::ANNOTATION_CALCULATED_DEFINE.must_equal 100 end it 'has the constant ANNOTATION_CALCULATED_LARGE' do skip unless get_introspection_data 'Regress', 'ANNOTATION_CALCULATED_LARGE' skip 'Constant is marked with the wrong type' Regress::ANNOTATION_CALCULATED_LARGE.must_equal 10_000_000_000 end it 'has the constant ANNOTATION_CALCULATED_LARGE_DIV' do skip unless get_introspection_data 'Regress', 'ANNOTATION_CALCULATED_LARGE_DIV' Regress::ANNOTATION_CALCULATED_LARGE_DIV.must_equal 1_000_000 end describe 'Regress::ATestError' do before do skip unless get_introspection_data 'Regress', 'ATestError' end it 'has the member :code0' do Regress::ATestError[:code0].must_equal 0 end it 'has the member :code1' do Regress::ATestError[:code1].must_equal 1 end it 'has the member :code2' do Regress::ATestError[:code2].must_equal 2 end end describe 'Regress::AnAnonymousUnion' do before do skip unless get_introspection_data 'Regress', 'AnAnonymousUnion' end let(:instance) { Regress::AnAnonymousUnion.new } it 'has a writable field x' do instance.x.must_equal 0 instance.x = 42 instance.x.must_equal 42 end it 'has a writable field a' do skip 'Anonymous union fields are not exposed in the GIR data' end it 'has a writable field padding' do skip 'Anonymous union fields are not exposed in the GIR data' end end describe 'Regress::AnnotationBitfield' do before do skip unless get_introspection_data 'Regress', 'AnnotationBitfield' end it 'has the member :foo' do Regress::AnnotationBitfield[:foo].must_equal 1 end it 'has the member :bar' do Regress::AnnotationBitfield[:bar].must_equal 2 end end describe 'Regress::AnnotationFields' do before do skip unless get_introspection_data 'Regress', 'AnnotationFields' end let(:instance) { Regress::AnnotationFields.new } it 'has a writable field field1' do instance.field1.must_equal 0 instance.field1 = 42 instance.field1.must_equal 42 end it 'has a writable field arr' do instance.arr.must_be_nil instance.arr = [1, 2, 3] # TODO: len should be set automatically instance.len = 3 instance.arr.to_a.must_equal [1, 2, 3] instance.len.must_equal 3 end it 'has a writable field len' do skip 'len should not be set independently' end end describe 'Regress::AnnotationObject' do let(:instance) { Regress::AnnotationObject.new } it 'has an attribute org.example.Test' do info = get_introspection_data('Regress', 'AnnotationObject') info.attribute('org.example.Test').must_equal 'cows' end it 'has a working method #allow_none' do instance.allow_none('hello!').must_be_nil instance.allow_none(nil).must_be_nil instance.allow_none.must_be_nil end it 'has a working method #calleeowns' do result, object = instance.calleeowns result.must_equal 1 object.must_be_nil end it 'has a working method #calleesowns' do result, toown1, toown2 = instance.calleesowns result.must_equal 1 toown1.must_be_nil toown2.must_be_nil end it 'has a working method #compute_sum' do instance.compute_sum [1, 2, 3] pass end it 'has a working method #compute_sum_n' do instance.compute_sum_n [1, 2, 3] pass end it 'has a working method #compute_sum_nz' do instance.compute_sum_nz [1, 2, 3] pass end it 'has a working method #create_object' do result = instance.create_object result.must_equal instance end it 'has a working method #do_not_use' do # TODO: Handle deprecation instance.do_not_use.must_be_nil end it 'has a working method #extra_annos' do info = get_method_introspection_data('Regress', 'AnnotationObject', 'extra_annos') info.attribute('org.foobar').must_equal 'testvalue' instance.extra_annos.must_be_nil end it 'has a working method #foreach' do a = 1 instance.foreach { a += 1 } a.must_equal 1 end it 'has a working method #get_hash' do result = instance.get_hash hash = result.to_hash hash['one'].must_equal instance hash['two'].must_equal instance end it 'has a working method #get_objects' do list = instance.get_objects list.to_a.must_equal [instance] end it 'has a working method #get_strings' do list = instance.get_strings list.to_a.must_equal %w(bar regress_annotation) end it 'has a working method #hidden_self' do instance.hidden_self.must_be_nil end it 'has a working method #in' do # TODO: Automatically convert to pointer argument ptr = FFI::MemoryPointer.new(:int, 1) ptr.put_int 0, 2342 instance.in(ptr).must_equal 2342 end it 'has a working method #inout' do instance.inout(2342).must_equal [2343, 2343] end it 'has a working method #inout2' do instance.inout2(2342).must_equal [2343, 2343] end it 'has a working method #inout3' do instance.inout3(2342).must_equal [2343, 2342] end it 'has a working method #method' do instance.method.must_equal 1 end it 'has a working method #notrans' do instance.notrans.must_be_nil end it 'has a working method #out' do instance.out.must_equal [1, 2] end it 'has a working method #parse_args' do instance.parse_args(%w(one two)).to_a.must_equal %w(one two) end it 'has a working method #set_data' do # TODO: Explicitely allow or deny passing a string here. instance.set_data([1, 2, 3]).must_be_nil end it 'has a working method #set_data2' do instance.set_data2([1, -2, 3]).must_be_nil end it 'has a working method #set_data3' do instance.set_data3([1, 2, 3]).must_be_nil end it 'has a working method #string_out' do instance.string_out.must_equal [false, nil] end it 'has a working method #use_buffer' do skip 'Ingoing pointer argument conversion is not implemented yet' instance.use_buffer(FFI::MemoryPointer.new(:void, 1)).must_be_nil end it 'has a working method #watch_full' do instance.watch {} end it 'has a working method #with_voidp' do # NOTE: Anything implementing #to_ptr could be passed in here obj = Regress::AnnotationObject.new instance.with_voidp(obj).must_be_nil end describe "its 'function-property' property" do it 'can be retrieved with #get_property_extended' do instance.get_property_extended('function-property').must_be_nil end it 'can be retrieved with #function_property' do instance.function_property.must_be_nil end it 'can be set with #set_property_extended' do instance.set_property_extended('function-property', proc {}) # AnnotationObject doesn't actually store stuff instance.function_property.must_be_nil end it 'can be set with #function_property=' do instance.function_property = proc {} # AnnotationObject doesn't actually store stuff instance.get_property_extended('function-property').must_be_nil end end describe "its 'string-property' property" do it 'can be retrieved with #get_property' do instance.get_property('string-property').must_be_nil end it 'can be retrieved with #string_property' do instance.string_property.must_be_nil end it 'can be set with #set_property' do instance.set_property('string-property', 'hello 42') # AnnotationObject doesn't actually store stuff instance.string_property.must_be_nil end it 'can be set with #string_property=' do instance.string_property = 'hello 42' # AnnotationObject doesn't actually store stuff instance.get_property('string-property').must_be_nil end end describe "its 'tab-property' property" do it 'can be retrieved with #get_property' do instance.get_property('tab-property').must_be_nil end it 'can be retrieved with #tab_property' do instance.tab_property.must_be_nil end it 'can be set with #set_property' do instance.set_property('tab-property', 'hello 42') # AnnotationObject doesn't actually store stuff instance.tab_property.must_be_nil end it 'can be set with #tab_property=' do instance.tab_property = 'hello 42' # AnnotationObject doesn't actually store stuff instance.get_property('tab-property').must_be_nil end end it "handles the 'attribute-signal' signal" do signal_info = get_signal_introspection_data('Regress', 'AnnotationObject', 'attribute-signal') argument_infos = signal_info.args argument_infos.first.attribute('some.annotation.foo1').must_equal 'val1' argument_infos.last.attribute('some.annotation.foo2').must_equal 'val2' result = nil instance.signal_connect 'attribute-signal' do |_obj, _arg1, _arg2, _user_data| # This signal uses a null marshaller, so the return value is never passed on. result = 'hello' end GObject.signal_emit instance, 'attribute-signal', 'foo', 'bar' result.must_equal 'hello' end it "handles the 'doc-empty-arg-parsing' signal" do test = nil instance.signal_connect 'doc-empty-arg-parsing' do |_obj, arg1, _user_data| test = arg1 end result = GObject.signal_emit instance, 'doc-empty-arg-parsing', FFI::Pointer.new(123) result.must_be_nil test.address.must_equal 123 end it "handles the 'list-signal' signal" do result = nil instance.signal_connect 'list-signal' do |_obj, list, _user_data| result = list end # TODO: Automatically convert to GLib::List GObject.signal_emit instance, 'list-signal', GLib::List.from(:utf8, %w(foo bar)) result.to_a.must_equal %w(foo bar) end it "handles the 'string-signal' signal" do result = nil instance.signal_connect 'string-signal' do |_obj, string, _user_data| result = string end GObject.signal_emit instance, 'string-signal', 'foo' result.must_equal 'foo' end end describe 'Regress::AnnotationStruct' do let(:instance) { Regress::AnnotationStruct.new } it 'has a writable field objects' do instance.objects.to_a.must_equal [nil] * 10 obj = Regress::AnnotationObject.new instance.objects = [nil] * 5 + [obj] + [nil] * 4 instance.objects.to_a[5].must_equal obj end end describe 'Regress::AnonymousUnionAndStruct' do let(:instance) { Regress::AnonymousUnionAndStruct.new } before do skip unless get_introspection_data 'Regress', 'AnonymousUnionAndStruct' end it 'has a writable field x' do instance.x = 42 instance.x.must_equal 42 end it 'has a writable field a' do skip 'Anonymous struct fields are not exposed in the GIR data' end it 'has a writable field b' do skip 'Anonymous struct fields are not exposed in the GIR data' end it 'has a writable field padding' do skip 'Anonymous union fields are not exposed in the GIR data' 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 FOO_DEFINE_SHOULD_BE_EXPOSED' do Regress::FOO_DEFINE_SHOULD_BE_EXPOSED.must_equal 'should be exposed' end it 'has the constant FOO_PIE_IS_TASTY' do Regress::FOO_PIE_IS_TASTY.must_equal 3.141590 end it 'has the constant FOO_SUCCESS_INT' do Regress::FOO_SUCCESS_INT.must_equal 4408 end describe 'Regress::FooASingle' do it 'has the member :foo_some_single_enum' do Regress::FooASingle[:foo_some_single_enum].must_equal 0 end end describe 'Regress::FooAddressType' do it 'has the member :invalid' do Regress::FooAddressType[:invalid].must_equal 0 end it 'has the member :ipv4' do Regress::FooAddressType[:ipv4].must_equal 1 end it 'has the member :ipv6' do Regress::FooAddressType[:ipv6].must_equal 2 end end describe 'Regress::FooBRect' do let(:instance) { Regress::FooBRect.wrap(Regress::FooBRect::Struct.new.to_ptr) } it 'has a writable field x' do instance.x.must_equal 0.0 instance.x = 23.42 instance.x.must_equal 23.42 end it 'has a writable field y' do instance.y.must_equal 0.0 instance.y = 23.42 instance.y.must_equal 23.42 end it 'creates an instance using #new' do skip 'This function is defined in the header but not implemented' end it 'has a working method #add' do skip 'This function is defined in the header but not implemented' end end describe 'Regress::FooBUnion' do let(:instance) { Regress::FooBUnion.wrap(Regress::FooBUnion::Struct.new.to_ptr) } it 'has a writable field type' do instance.type.must_equal 0 instance.type = 42 instance.type.must_equal 42 end it 'has a writable field v' do instance.v.must_equal 0.0 instance.v = 23.42 instance.v.must_equal 23.42 end it 'has a writable field rect' do instance.rect.must_be_nil rect = Regress::FooBRect.wrap(Regress::FooBRect::Struct.new.to_ptr) rect.x = 42 rect.y = 23 skip 'Cannot copy FooBRect structs' instance.rect = rect instance.rect.x.must_equal 42.0 instance.rect.y.must_equal 23.0 end it 'creates an instance using #new' do skip 'This function is defined in the header but not implemented' end it 'has a working method #get_contained_type' do skip 'This function is defined in the header but not implemented' end end describe 'Regress::FooBoxed' do let(:instance) { Regress::FooBoxed.new } it 'creates an instance using #new' do instance.must_be_instance_of Regress::FooBoxed end it 'has a working method #method' do instance.method.must_be_nil end end describe 'Regress::FooBuffer' do let(:instance) { Regress::FooBuffer.new } it 'creates an instance using #new' do instance.must_be_instance_of Regress::FooBuffer end it 'has a working method #some_method' do instance.some_method.must_be_nil end end describe 'Regress::FooDBusData' do let(:instance) { Regress::FooDBusData.new } it 'creates an instance using #new' do instance.must_be_instance_of Regress::FooDBusData end it 'has a working method #method' do skip 'This function is defined in the header but not implemented' end end describe 'Regress::FooEnumFullname' do it 'has the member :one' do Regress::FooEnumFullname[:one].must_equal 1 end it 'has the member :two' do Regress::FooEnumFullname[:two].must_equal 2 end it 'has the member :three' do Regress::FooEnumFullname[:three].must_equal 3 end end describe 'Regress::FooEnumNoType' do it 'has the member :un' do Regress::FooEnumNoType[:un].must_equal 1 end it 'has the member :deux' do Regress::FooEnumNoType[:deux].must_equal 2 end it 'has the member :trois' do Regress::FooEnumNoType[:trois].must_equal 3 end it 'has the member :neuf' do Regress::FooEnumNoType[:neuf].must_equal 9 end end describe 'Regress::FooEnumType' do it 'has the member :alpha' do Regress::FooEnumType[:alpha].must_equal 0 end it 'has the member :beta' do Regress::FooEnumType[:beta].must_equal 1 end it 'has the member :delta' do Regress::FooEnumType[:delta].must_equal 2 end it 'has a working function #method' do skip 'This function is defined in the header but not implemented' end it 'has a working function #returnv' do skip 'This function is defined in the header but not implemented' end end describe 'Regress::FooError' do it 'has the member :good' do Regress::FooError[:good].must_equal 0 end it 'has the member :bad' do Regress::FooError[:bad].must_equal 1 end it 'has the member :ugly' do Regress::FooError[:ugly].must_equal 2 end it 'has a working function #quark' do quark = Regress::FooError.quark GLib.quark_to_string(quark).must_equal 'regress_foo-error-quark' end end describe 'Regress::FooEvent' do let(:instance) { Regress::FooEvent.new } it 'has a writable field type' do instance.type.must_equal 0 instance.type = 23 instance.type.must_equal 23 end it 'has a writable field any' do instance.any.send_event.must_equal 0 any = Regress::FooEventAny.new any.send_event = 42 instance.any = any instance.any.send_event.must_equal 42 end it 'has a writable field expose' do instance.expose.send_event.must_equal 0 instance.expose.count.must_equal 0 expose = Regress::FooEventExpose.new expose.send_event = 23 expose.count = 14 instance.expose = expose instance.expose.send_event.must_equal 23 instance.expose.count.must_equal 14 end end describe 'Regress::FooEventAny' do let(:instance) { Regress::FooEventAny.new } it 'has a writable field send_event' do instance.send_event.must_equal 0 instance.send_event = 23 instance.send_event.must_equal 23 end end describe 'Regress::FooEventExpose' do let(:instance) { Regress::FooEventExpose.new } it 'has a writable field send_event' do instance.send_event.must_equal 0 instance.send_event = 23 instance.send_event.must_equal 23 end it 'has a writable field count' do instance.count.must_equal 0 instance.count = 42 instance.count.must_equal 42 end end describe 'Regress::FooFlagsNoType' do it 'has the member :ett' do Regress::FooFlagsNoType[:ett].must_equal 1 end it 'has the member :tva' do Regress::FooFlagsNoType[:tva].must_equal 2 end it 'has the member :fyra' do Regress::FooFlagsNoType[:fyra].must_equal 4 end end describe 'Regress::FooFlagsType' do it 'has the member :first' do Regress::FooFlagsType[:first].must_equal 1 end it 'has the member :second' do Regress::FooFlagsType[:second].must_equal 2 end it 'has the member :third' do Regress::FooFlagsType[:third].must_equal 4 end end describe 'Regress::FooForeignStruct' do let(:instance) { Regress::FooForeignStruct.new } it 'has a writable field regress_foo' do instance.regress_foo.must_equal 0 instance.regress_foo = 143 instance.regress_foo.must_equal 143 end it 'creates an instance using #new' do instance.must_be_instance_of Regress::FooForeignStruct end it 'has a working method #copy' do instance.regress_foo = 585 result = instance.copy instance.regress_foo = 0 result.regress_foo.must_equal 585 end end describe 'Regress::FooInterface' do it 'has a working function #static_method' do Regress::FooInterface.static_method(42).must_be_nil end it 'has a working method #do_regress_foo' do instance = Regress::FooObject.new instance.must_be_kind_of Regress::FooInterface instance.do_regress_foo(42).must_be_nil end end describe 'Regress::FooObject' do let(:instance) { Regress::FooObject.new } it 'creates an instance using #new' do instance.must_be_instance_of Regress::FooObject end it 'creates an instance using #new_as_super' do other_instance = Regress::FooObject.new_as_super other_instance.must_be_instance_of Regress::FooObject end it 'has a working function #a_global_method' do skip 'This function is defined in the header but not implemented' end it 'has a working function #get_default' do Regress::FooObject.get_default.must_be_nil end it 'has a working function #static_meth' do skip 'This function is defined in the header but not implemented' end it 'has a working method #append_new_stack_layer' do instance.append_new_stack_layer(42).must_be_nil end it 'has a working method #dup_name' do instance.dup_name.must_equal 'regress_foo' end it 'has a working method #external_type' do result = instance.external_type result.must_be_nil end it 'has a working method #get_name' do instance.get_name.must_equal 'regress_foo' end it 'has a working method #handle_glyph' do skip 'This function is defined in the header but not implemented' end it 'has a working method #is_it_time_yet' do instance.is_it_time_yet(Time.now.to_i).must_be_nil end it 'has a working method #read' do instance.read(12, 13).must_be_nil end it 'has a working method #various' do skip 'This function is defined in the header but not implemented' end it 'has a working method #virtual_method' do skip 'This function is defined in the header but not implemented' end describe "its 'string' property" do it 'can be retrieved with #get_property' do instance.get_property('string').must_be_nil end it 'can be retrieved with #string' do instance.string.must_be_nil end it 'can be set with #set_property' do instance.set_property 'string', 'hello 42' # FooObject doesn't actually store stuff instance.string.must_be_nil instance.get_property('string').must_be_nil end it 'can be set with #string=' do instance.string = 'hello 42' # FooObject doesn't actually store stuff instance.string.must_be_nil instance.get_property('string').must_be_nil end end it "handles the 'signal' signal" do instance.signal_connect 'signal' do 'hello' end result = GObject.signal_emit instance, 'signal' result.must_equal 'hello' end end describe 'Regress::FooOtherObject' do it 'is derived from GObject::Object' do Regress::FooOtherObject.superclass.must_equal GObject::Object end end describe 'Regress::FooRectangle' do let(:instance) { Regress::FooRectangle.new } it 'has a writable field x' do instance.x.must_equal 0 instance.x = 23 instance.x.must_equal 23 end it 'has a writable field y' do instance.y.must_equal 0 instance.y = 23 instance.y.must_equal 23 end it 'has a writable field width' do instance.width.must_equal 0 instance.width = 23 instance.width.must_equal 23 end it 'has a writable field height' do instance.height.must_equal 0 instance.height = 23 instance.height.must_equal 23 end it 'has a working method #add' do skip 'Not implemented yet' other_instance = Regress::FooRectangle.new instance.add other_instance end end describe 'Regress::FooStackLayer' do it 'has the member :desktop' do Regress::FooStackLayer[:desktop].must_equal 0 end it 'has the member :bottom' do Regress::FooStackLayer[:bottom].must_equal 1 end it 'has the member :normal' do Regress::FooStackLayer[:normal].must_equal 2 end it 'has the member :top' do Regress::FooStackLayer[:top].must_equal 4 end it 'has the member :dock' do Regress::FooStackLayer[:dock].must_equal 4 end it 'has the member :fullscreen' do Regress::FooStackLayer[:fullscreen].must_equal 5 end it 'has the member :focused_window' do Regress::FooStackLayer[:focused_window].must_equal 6 end it 'has the member :override_redirect' do Regress::FooStackLayer[:override_redirect].must_equal 7 end it 'has the member :last' do Regress::FooStackLayer[:last].must_equal 8 end end describe 'Regress::FooStruct' do let(:instance) { Regress::FooStruct.new } it 'blocks access to the hidden struct field priv' do proc { instance.priv = nil }.must_raise NoMethodError proc { instance.priv }.must_raise NoMethodError end it 'has a writable field member' do instance.member.must_equal 0 instance.member = 23 instance.member.must_equal 23 end end describe 'Regress::FooSubInterface' do let(:derived_klass) do Object.const_set("DerivedClass#{Sequence.next}", Class.new(Regress::FooObject)) end def make_derived_instance derived_klass.send :include, Regress::FooSubInterface GirFFI.define_type derived_klass do |info| yield info if block_given? end derived_klass.new end it 'has a working method #do_bar' do result = nil instance = make_derived_instance do |info| info.install_vfunc_implementation :do_bar, proc { |obj| result = obj.get_name } end instance.do_bar result.must_equal 'regress_foo' end it 'has a working method #do_baz' do a = nil instance = make_derived_instance do |info| # TODO: Do not pass callback again in user_data if destroy notifier is absent info.install_vfunc_implementation :do_baz, proc { |obj, callback, _user_data| callback.call; a = obj.get_name } end b = nil instance.do_baz { b = 'hello' } a.must_equal 'regress_foo' b.must_equal 'hello' end it "handles the 'destroy-event' signal" do a = nil instance = make_derived_instance instance.signal_connect 'destroy-event' do a = 'hello' end GObject.signal_emit instance, 'destroy-event' a.must_equal 'hello' end end describe 'Regress::FooSubobject' do it 'creates an instance using #new' do skip 'This function is defined in the header but not implemented' end end describe 'Regress::FooThingWithArray' do let(:instance) { Regress::FooThingWithArray.new } it 'has a writable field x' do instance.x.must_equal 0 instance.x = 23 instance.x.must_equal 23 end it 'has a writable field y' do instance.y.must_equal 0 instance.y = 23 instance.y.must_equal 23 end it 'has a writable field lines' do instance.lines.must_be :==, [0] * 80 instance.lines = (1..80).to_a instance.lines.must_be :==, (1..80).to_a end it 'has a writable field data' do instance.data.must_equal FFI::Pointer::NULL instance.data = FFI::Pointer.new(23) instance.data.must_equal FFI::Pointer.new(23) end end describe 'Regress::FooUnion' do let(:instance) { Regress::FooUnion.new } it 'has a writable field regress_foo' do instance.regress_foo.must_equal 0 instance.regress_foo = 23 instance.regress_foo.must_equal 23 end end describe 'Regress::FooUtilityStruct' do let(:instance) { Regress::FooUtilityStruct.new } it 'has a writable field bar' do struct = Utility::Struct.new struct.field = 23 instance.bar.field.must_equal 0 instance.bar = struct instance.bar.field.must_equal 23 end 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 end it 'has the constant GUINT64_CONSTANTA' do skip unless get_introspection_data 'Regress', 'GUINT64_CONSTANTA' Regress::GUINT64_CONSTANTA.must_equal 18_446_744_073_709_551_615 end it 'has the constant G_GINT64_CONSTANT' do skip unless get_introspection_data 'Regress', 'G_GINT64_CONSTANT' Regress::G_GINT64_CONSTANT.must_equal 1000 end it 'has the constant INT_CONSTANT' do assert_equal 4422, Regress::INT_CONSTANT end it 'has the constant LONG_STRING_CONSTANT' do Regress::LONG_STRING_CONSTANT.must_equal %w(TYPE VALUE ENCODING CHARSET LANGUAGE DOM INTL POSTAL PARCEL HOME WORK PREF VOICE FAX MSG CELL PAGER BBS MODEM CAR ISDN VIDEO AOL APPLELINK ATTMAIL CIS EWORLD INTERNET IBMMAIL MCIMAIL POWERSHARE PRODIGY TLX X400 GIF CGM WMF BMP MET PMB DIB PICT TIFF PDF PS JPEG QTIME MPEG MPEG2 AVI WAVE AIFF PCM X509 PGP).join(',') end describe 'Regress::LikeGnomeKeyringPasswordSchema' do before do skip unless get_introspection_data 'Regress', 'LikeGnomeKeyringPasswordSchema' end it 'creates an instance using #new' do obj = Regress::LikeGnomeKeyringPasswordSchema.new obj.must_be_instance_of Regress::LikeGnomeKeyringPasswordSchema end let(:instance) { Regress::LikeGnomeKeyringPasswordSchema.new } it 'has a writable field dummy' do instance.dummy.must_equal 0 instance.dummy = 42 instance.dummy.must_equal 42 end it 'has a writable field attributes' do skip 'Introspection data cannot deal with type of this field yet' end it 'has a writable field dummy2' do instance.dummy2.must_equal 0.0 instance.dummy2 = 42.42 instance.dummy2.must_equal 42.42 end end describe 'Regress::LikeXklConfigItem' do before do skip unless get_introspection_data 'Regress', 'LikeXklConfigItem' end let(:instance) { Regress::LikeXklConfigItem.new } let(:name_array) { 'foo'.bytes.to_a + [0] * 29 } it 'has a writable field name' do # TODO: Should an array of gint8 be more string-like? instance.name.to_a.must_equal [0] * 32 instance.name = name_array instance.name.to_a.must_equal name_array end it 'has a working method #set_name' do instance.set_name 'foo' instance.name.to_a.must_equal name_array end end it 'has the constant MAXUINT64' do skip unless get_introspection_data 'Regress', 'MAXUINT64' Regress::MAXUINT64.must_equal 0xffff_ffff_ffff_ffff end it 'has the constant MININT64' do skip unless get_introspection_data 'Regress', 'MININT64' Regress::MININT64.must_equal(-0x8000_0000_0000_0000) end it 'has the constant Mixed_Case_Constant' do assert_equal 4423, Regress::Mixed_Case_Constant end it 'has the constant NEGATIVE_INT_CONSTANT' do skip unless get_introspection_data 'Regress', 'NEGATIVE_INT_CONSTANT' Regress::NEGATIVE_INT_CONSTANT.must_equal(-42) end it 'has the constant STRING_CONSTANT' do assert_equal 'Some String', Regress::STRING_CONSTANT end describe 'Regress::TestABCError' do before do skip unless get_introspection_data 'Regress', 'TestABCError' end it 'has the member :code1' do Regress::TestABCError[:code1].must_equal 1 end it 'has the member :code2' do Regress::TestABCError[:code2].must_equal 2 end it 'has the member :code3' do Regress::TestABCError[:code3].must_equal 3 end it 'has a working function #quark' do quark = Regress::TestABCError.quark GLib.quark_to_string(quark).must_equal 'regress-test-abc-error' end end describe 'Regress::TestBoxed' do let(:instance) { Regress::TestBoxed.new_alternative_constructor1 123 } it 'has a writable field some_int8' do instance.some_int8.must_equal 123 instance.some_int8 = -43 instance.some_int8.must_equal(-43) end it 'has a writable field nested_a' do instance.nested_a.some_int.must_equal 0 nested = Regress::TestSimpleBoxedA.new nested.some_int = 12_345 instance.nested_a = nested instance.nested_a.some_int.must_equal 12_345 end it 'blocks access to the hidden struct field priv' do proc { instance.priv = nil }.must_raise NoMethodError proc { instance.priv }.must_raise NoMethodError end it 'creates an instance using #new' do tb = Regress::TestBoxed.new assert_instance_of Regress::TestBoxed, tb end it 'creates an instance using #new_alternative_constructor1' do tb = Regress::TestBoxed.new_alternative_constructor1 1 assert_instance_of Regress::TestBoxed, tb assert_equal 1, tb.some_int8 end it 'creates an instance using #new_alternative_constructor2' do tb = Regress::TestBoxed.new_alternative_constructor2 1, 2 assert_instance_of Regress::TestBoxed, tb assert_equal 1 + 2, tb.some_int8 end it 'creates an instance using #new_alternative_constructor3' do tb = Regress::TestBoxed.new_alternative_constructor3 '54' assert_instance_of Regress::TestBoxed, tb assert_equal 54, tb.some_int8 end it 'has non-zero positive result for #gtype' do assert Regress::TestBoxed.gtype > 0 end it 'has a working method #_not_a_method' do # NOTE: This method is marked as moved, but this is not exposed in the typelib skip unless get_method_introspection_data('Regress', 'TestBoxed', '_not_a_method') instance._not_a_method pass end it 'has a working method #copy' do tb2 = instance.copy assert_instance_of Regress::TestBoxed, tb2 assert_equal 123, tb2.some_int8 instance.some_int8 = 89 assert_equal 123, tb2.some_int8 end it 'has a working method #equals' do tb2 = Regress::TestBoxed.new_alternative_constructor2 120, 3 assert_equal true, instance.equals(tb2) end end describe 'Regress::TestBoxedB' do let(:instance) { Regress::TestBoxedB.new 8, 42 } it 'has a writable field some_int8' do instance.some_int8.must_equal 8 instance.some_int8 = -43 instance.some_int8.must_equal(-43) end it 'has a writable field some_long' do instance.some_long.must_equal 42 instance.some_long = -4342 instance.some_long.must_equal(-4342) end it 'creates an instance using #new' do tb = Regress::TestBoxedB.new 8, 42 assert_instance_of Regress::TestBoxedB, tb end it 'has a working method #copy' do cp = instance.copy cp.must_be_instance_of Regress::TestBoxedB cp.some_int8.must_equal 8 cp.some_long.must_equal 42 instance.some_int8 = 2 cp.some_int8.must_equal 8 end end describe 'Regress::TestBoxedC' do before do skip unless get_introspection_data 'Regress', 'TestBoxedC' end let(:instance) { Regress::TestBoxedC.new } it 'has a writable field refcount' do instance.refcount.must_equal 1 instance.refcount = 2 instance.refcount.must_equal 2 end it 'has a writable field another_thing' do instance.another_thing.must_equal 42 instance.another_thing = 4342 instance.another_thing.must_equal 4342 end it 'creates an instance using #new' do tb = Regress::TestBoxedC.new assert_instance_of Regress::TestBoxedC, tb end end describe 'Regress::TestBoxedD' do let(:instance) { Regress::TestBoxedD.new 'foo', 42 } before do skip unless get_introspection_data 'Regress', 'TestBoxedD' end it 'creates an instance using #new' do instance.must_be_instance_of Regress::TestBoxedD end it 'has a working method #copy' do copy = instance.copy copy.must_be_instance_of Regress::TestBoxedD instance.get_magic.must_equal copy.get_magic instance.wont_equal copy end it 'has a working method #free' do skip "#free is used internally and shouldn't be exposed" instance.free pass end it 'has a working method #get_magic' do instance.get_magic.must_equal 'foo'.length + 42 end end describe 'Regress::TestDEFError' do before do skip unless get_introspection_data 'Regress', 'TestDEFError' end it 'has the member :code0' do Regress::TestDEFError[:code0].must_equal 0 end it 'has the member :code1' do Regress::TestDEFError[:code1].must_equal 1 end it 'has the member :code2' do Regress::TestDEFError[:code2].must_equal 2 end end describe 'Regress::TestEnum' do it 'has the member :value1' do Regress::TestEnum[:value1].must_equal 0 end it 'has the member :value2' do Regress::TestEnum[:value2].must_equal 1 end it 'has the member :value3' do Regress::TestEnum[:value3].must_equal(-1) end it 'has the member :value4' do Regress::TestEnum[:value4].must_equal 48 end it 'has a working function #param' do Regress::TestEnum.param(:value1).must_equal('value1') Regress::TestEnum.param(:value2).must_equal('value2') Regress::TestEnum.param(:value3).must_equal('value3') Regress::TestEnum.param(:value4).must_equal('value4') Regress::TestEnum.param(0).must_equal('value1') Regress::TestEnum.param(1).must_equal('value2') Regress::TestEnum.param(-1).must_equal('value3') Regress::TestEnum.param(48).must_equal('value4') end end describe 'Regress::TestEnumNoGEnum' do it 'has the member :evalue1' do Regress::TestEnumNoGEnum[:evalue1].must_equal 0 end it 'has the member :evalue2' do Regress::TestEnumNoGEnum[:evalue2].must_equal 42 end it 'has the member :evalue3' do Regress::TestEnumNoGEnum[:evalue3].must_equal 48 end end describe 'Regress::TestEnumUnsigned' do it 'has the member :value1' do Regress::TestEnumUnsigned[:value1].must_equal 1 end # NOTE In c, the positive and negative values are not distinguished it 'has the member :value2' do Regress::TestEnumUnsigned[:value2].must_equal(-2_147_483_648) end end describe 'Regress::TestError' do before do skip unless get_introspection_data 'Regress', 'TestError' end it 'has the member :code1' do Regress::TestError[:code1].must_equal 1 end it 'has the member :code2' do Regress::TestError[:code2].must_equal 2 end it 'has the member :code3' do Regress::TestError[:code3].must_equal 3 end it 'has a working function #quark' do quark = Regress::TestError.quark GLib.quark_to_string(quark).must_equal 'regress-test-error' end end describe 'Regress::TestFlags' do it 'has the member :flag1' do assert_equal 1, Regress::TestFlags[:flag1] end it 'has the member :flag2' do assert_equal 2, Regress::TestFlags[:flag2] end it 'has the member :flag3' do assert_equal 4, Regress::TestFlags[:flag3] end end describe 'Regress::TestFloating' do it 'creates an instance using #new' do o = Regress::TestFloating.new o.must_be_instance_of Regress::TestFloating end describe 'an instance' do before do @o = Regress::TestFloating.new end it 'has a reference count of 1' do assert_equal 1, @o.ref_count end it 'has been sunk' do @o.wont_be :floating? end end end describe 'Regress::TestFundamentalObject' do it 'does not have GObject::Object as an ancestor' do refute_includes Regress::TestFundamentalObject.ancestors, GObject::Object end it 'cannot be instantiated' do proc { Regress::TestFundamentalObject.new }.must_raise NoMethodError end let(:derived_instance) { Regress::TestFundamentalSubObject.new 'foo' } it 'has a working method #ref' do derived_instance.refcount.must_equal 1 derived_instance.ref derived_instance.refcount.must_equal 2 end it 'has a working method #unref' do derived_instance.refcount.must_equal 1 derived_instance.unref derived_instance.refcount.must_equal 0 end end describe 'Regress::TestFundamentalSubObject' do it 'creates an instance using #new' do obj = Regress::TestFundamentalSubObject.new 'foo' obj.must_be_instance_of Regress::TestFundamentalSubObject end let(:instance) { Regress::TestFundamentalSubObject.new 'foo' } it 'is a subclass of TestFundamentalObject' do assert_kind_of Regress::TestFundamentalObject, instance end it 'has a field :data storing the constructor parameter' do assert_equal 'foo', instance.data end it "can access its parent class' fields directly" do instance.flags.must_equal 0 end end describe 'Regress::TestInheritDrawable' do before do skip unless get_introspection_data 'Regress', 'TestInheritDrawable' end it 'cannot be instantiated' do proc { Regress::TestInheritDrawable.new }.must_raise NoMethodError end let(:derived_instance) { ConcreteDrawable.new } it 'has a working method #do_foo' do derived_instance.do_foo 42 pass end it 'has a working method #do_foo_maybe_throw' do derived_instance.do_foo_maybe_throw 42 proc { derived_instance.do_foo_maybe_throw 41 }.must_raise GirFFI::GLibError end it 'has a working method #get_origin' do derived_instance.get_origin.must_equal [0, 0] end it 'has a working method #get_size' do derived_instance.get_size.must_equal [42, 42] end end describe 'Regress::TestInheritPixmapObjectClass' do it 'has a writable field parent_class' do skip 'This is a class struct without defined class' end end describe 'Regress::TestInterface' do it 'is a module' do assert_instance_of Module, Regress::TestInterface end it 'extends InterfaceBase' do metaclass = class << Regress::TestInterface; self; end assert_includes metaclass.ancestors, GirFFI::InterfaceBase end it 'has non-zero positive result for #gtype' do Regress::TestInterface.gtype.must_be :>, 0 end end describe 'Regress::TestObj' do it 'creates an instance using #constructor' do obj = Regress::TestObj.constructor obj.must_be_instance_of Regress::TestObj end it 'creates an instance using #new' do o1 = Regress::TestObj.constructor o2 = Regress::TestObj.new o1 o2.must_be_instance_of Regress::TestObj end it 'creates an instance using #new_callback' do a = 1 o = Regress::TestObj.new_callback { a = 2 } assert_instance_of Regress::TestObj, o a.must_equal 2 # Regress::TestObj.new_callback adds a callback to the list of notified # callbacks. Thaw the callbacks to make sure the list is cleared for # later tests. result = Regress.test_callback_thaw_notifications result.must_equal 2 end it 'creates an instance using #new_from_file' do o = Regress::TestObj.new_from_file('foo') assert_instance_of Regress::TestObj, o end it 'has a working function #null_out' do obj = Regress::TestObj.null_out obj.must_be_nil end it 'has a working function #static_method' do rv = Regress::TestObj.static_method 623 assert_equal 623.0, rv end it 'has a working function #static_method_callback' do a = 1 Regress::TestObj.static_method_callback { a = 2 } assert_equal 2, a end let(:instance) { Regress::TestObj.new_from_file('foo') } describe 'its gtype' do it 'can be found through gtype and GObject.type_from_instance' do gtype = Regress::TestObj.gtype r = GObject.type_from_instance instance assert_equal gtype, r end end it 'has a reference count of 1' do assert_equal 1, instance.ref_count end it 'does not float' do instance.wont_be :floating? end it 'has a working method #matrix' do instance.matrix('bar').must_equal 42 end it 'has a working method #do_matrix' do instance.do_matrix('bar').must_equal 42 end it 'has a working method #emit_sig_with_array_len_prop' do skip unless get_method_introspection_data('Regress', 'TestObj', 'emit_sig_with_array_len_prop') array = nil instance.signal_connect 'sig-with-array-len-prop' do |_obj, ary| array = ary.to_a end instance.emit_sig_with_array_len_prop array.to_a.must_equal [0, 1, 2, 3, 4] end it 'has a working method #emit_sig_with_foreign_struct' do skip unless get_method_introspection_data('Regress', 'TestObj', 'emit_sig_with_foreign_struct') has_fired = false instance.signal_connect 'sig-with-foreign-struct' do |_obj, cr| has_fired = true cr.must_be_instance_of Cairo::Context end instance.emit_sig_with_foreign_struct assert has_fired end it 'has a working method #emit_sig_with_int64' do skip unless get_signal_introspection_data 'Regress', 'TestObj', 'sig-with-int64-prop' instance.signal_connect 'sig-with-int64-prop' do |_obj, i, _ud| i end instance.emit_sig_with_int64 end it 'has a working method #emit_sig_with_obj' do has_fired = false instance.signal_connect 'sig-with-obj' do |_it, obj| has_fired = true obj.int.must_equal 3 end instance.emit_sig_with_obj assert has_fired end it 'has a working method #emit_sig_with_uint64' do skip unless get_signal_introspection_data 'Regress', 'TestObj', 'sig-with-uint64-prop' instance.signal_connect 'sig-with-uint64-prop' do |_obj, i, _ud| i end instance.emit_sig_with_uint64 end it 'has a working method #forced_method' do instance.forced_method pass end it 'has a working method #instance_method' do rv = instance.instance_method assert_equal(-1, rv) end it 'has a working method #instance_method_callback' do a = 1 instance.instance_method_callback { a = 2 } 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.ref_count.must_equal 1 instance.instance_method_full instance.ref_count.must_equal 1 end it 'has a working method #not_nullable_element_typed_gpointer_in' do skip unless get_method_introspection_data('Regress', 'TestObj', 'not_nullable_element_typed_gpointer_in') instance.not_nullable_element_typed_gpointer_in [1, 2, 3] # TODO: Make method raise when passed nil end it 'has a working method #not_nullable_typed_gpointer_in' do skip unless get_method_introspection_data('Regress', 'TestObj', 'not_nullable_typed_gpointer_in') obj = Regress::TestObj.new_from_file('bar') instance.not_nullable_typed_gpointer_in obj # TODO: Make method raise when passed nil end it 'has a working method #set_bare' do obj = Regress::TestObj.new_from_file('bar') instance.set_bare obj instance.bare.must_equal obj end it 'has a working method #skip_inout_param' do a = 1 c = 2.0 num1 = 3 num2 = 4 result, out_b, sum = instance.skip_inout_param a, c, num1, num2 result.must_equal true out_b.must_equal a + 1 sum.must_equal num1 + 10 * num2 end it 'has a working method #skip_out_param' do a = 1 c = 2.0 d = 3 num1 = 4 num2 = 5 result, out_d, sum = instance.skip_out_param a, c, d, num1, num2 result.must_equal true out_d.must_equal d + 1 sum.must_equal num1 + 10 * num2 end it 'has a working method #skip_param' do a = 1 d = 3 num1 = 4 num2 = 5 result, out_b, out_d, sum = instance.skip_param a, d, num1, num2 result.must_equal true out_b.must_equal a + 1 out_d.must_equal d + 1 sum.must_equal num1 + 10 * num2 end it 'has a working method #skip_return_val' do a = 1 c = 2.0 d = 3 num1 = 4 num2 = 5 out_b, out_d, out_sum = instance.skip_return_val a, c, d, num1, num2 out_b.must_equal a + 1 out_d.must_equal d + 1 out_sum.must_equal num1 + 10 * num2 end it 'has a working method #skip_return_val_no_out' do result = instance.skip_return_val_no_out 1 result.must_be_nil proc { instance.skip_return_val_no_out 0 }.must_raise GirFFI::GLibError end it 'has a working method #torture_signature_0' do y, z, q = instance.torture_signature_0(-21, 'hello', 13) assert_equal [-21, 2 * -21, 'hello'.length + 13], [y, z, q] end it 'has a working method #torture_signature_1' do ret, y, z, q = instance.torture_signature_1(-21, 'hello', 12) [ret, y, z, q].must_equal [true, -21, 2 * -21, 'hello'.length + 12] proc { instance.torture_signature_1(-21, 'hello', 11) }. must_raise GirFFI::GLibError end describe "its 'bare' property" do it 'can be retrieved with #get_property' do instance.get_property('bare').must_be_nil end it 'can be retrieved with #bare' do instance.bare.must_be_nil end it 'can be set with #set_property' do obj = Regress::TestObj.new_from_file('bar') instance.set_property 'bare', obj instance.get_property('bare').must_equal obj end it 'can be set with #bare=' do obj = Regress::TestObj.new_from_file('bar') instance.bare = obj instance.bare.must_equal obj instance.get_property('bare').must_equal obj end end describe "its 'boxed' property" do it 'can be retrieved with #get_property' do instance.get_property('boxed').must_be_nil end it 'can be retrieved with #boxed' do instance.boxed.must_be_nil end it 'can be set with #set_property' do tb = Regress::TestBoxed.new_alternative_constructor1 75 instance.set_property 'boxed', tb instance.get_property('boxed').some_int8.must_equal 75 end it 'can be set with #boxed=' do tb = Regress::TestBoxed.new_alternative_constructor1 75 instance.boxed = tb instance.boxed.some_int8.must_equal tb.some_int8 instance.get_property('boxed').some_int8.must_equal tb.some_int8 end end describe "its 'double' property" do it 'can be retrieved with #get_property' do instance.get_property('double').must_equal 0.0 end it 'can be retrieved with #double' do instance.double.must_equal 0.0 end it 'can be set with #set_property' do instance.set_property 'double', 3.14 instance.get_property('double').must_equal 3.14 end it 'can be set with #double=' do instance.double = 3.14 instance.double.must_equal 3.14 instance.get_property('double').must_equal 3.14 end end describe "its 'float' property" do it 'can be retrieved with #get_property' do instance.get_property('float').must_equal 0.0 end it 'can be retrieved with #float' do instance.float.must_equal 0.0 end it 'can be set with #set_property' do instance.set_property 'float', 3.14 instance.get_property('float').must_be_close_to 3.14 end it 'can be set with #float=' do instance.float = 3.14 instance.float.must_be_close_to 3.14 instance.get_property('float').must_be_close_to 3.14 end end describe "its 'gtype' property" do before do skip unless get_property_introspection_data('Regress', 'TestObj', 'gtype') end it 'can be retrieved with #get_property' do instance.get_property('gtype').must_equal 0 end it 'can be retrieved with #gtype' do instance.gtype.must_equal 0 end it 'can be set with #set_property' do instance.set_property 'gtype', GObject::TYPE_INT64 instance.get_property('gtype').must_equal GObject::TYPE_INT64 end it 'can be set with #gtype=' do instance.gtype = GObject::TYPE_STRING instance.gtype.must_equal GObject::TYPE_STRING instance.get_property('gtype').must_equal GObject::TYPE_STRING end end describe "its 'hash-table' property" do it 'can be retrieved with #get_property' do instance.get_property('hash-table').must_be_nil end it 'can be retrieved with #hash_table' do instance.hash_table.must_be_nil end it 'can be set with #set_property_extended' do instance.set_property_extended 'hash-table', 'foo' => -4, 'bar' => 83 instance.hash_table.to_hash.must_equal('foo' => -4, 'bar' => 83) end it 'can be set with #hash_table=' do instance.hash_table = { 'foo' => -4, 'bar' => 83 } instance.hash_table.to_hash.must_equal('foo' => -4, 'bar' => 83) instance.get_property_extended('hash-table').to_hash.must_equal('foo' => -4, 'bar' => 83) end end describe "its 'hash-table-old' property" do it 'can be retrieved with #get_property' do instance.get_property('hash-table-old').must_be_nil end it 'can be retrieved with #hash_table_old' do instance.hash_table_old.must_be_nil end it 'can be set with #set_property_extended' do instance.set_property_extended 'hash-table-old', 'foo' => 34, 'bar' => -3 instance.hash_table_old.to_hash.must_equal('foo' => 34, 'bar' => -3) end it 'can be set with #hash_table_old=' do instance.hash_table_old = { 'foo' => 34, 'bar' => -3 } instance.hash_table_old.to_hash.must_equal('foo' => 34, 'bar' => -3) instance.get_property_extended('hash-table-old').to_hash.must_equal('foo' => 34, 'bar' => -3) end end describe "its 'int' property" do it 'can be retrieved with #get_property' do assert_equal 0, instance.get_property('int') end it 'can be retrieved with #int' do assert_equal 0, instance.int end it 'can be set with #set_property' do instance.set_property 'int', 42 assert_equal 42, instance.get_property('int') end it 'can be set with #int=' do instance.int = 41 assert_equal 41, instance.get_property('int') assert_equal 41, instance.int end end describe "its 'list' property" do it 'can be retrieved with #get_property_extended' do instance.get_property_extended('list').must_be_nil end it 'can be retrieved with #list' do instance.list.must_be_nil end it 'can be set with #set_property_extended' do instance.set_property_extended 'list', %w(foo bar) instance.list.to_a.must_equal %w(foo bar) end it 'can be set with #list=' do instance.list = %w(foo bar) instance.list.to_a.must_equal %w(foo bar) instance.get_property_extended('list').must_be :==, %w(foo bar) end end describe "its 'list-old' property" do it 'can be retrieved with #get_property' do instance.get_property_extended('list-old').must_be_nil end it 'can be retrieved with #list_old' do instance.list_old.must_be_nil end it 'can be set with #set_property_extended' do instance.set_property_extended 'list-old', %w(foo bar) instance.list_old.must_be :==, %w(foo bar) end it 'can be set with #list_old=' do instance.list_old = %w(foo bar) instance.list_old.must_be :==, %w(foo bar) instance.get_property_extended('list-old').must_be :==, %w(foo bar) 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') end it 'can be retrieved with #string' do assert_nil instance.string end it 'can be set with #set_property' do instance.set_property 'string', 'foobar' assert_equal 'foobar', instance.get_property('string') end it 'can be set with #string=' do instance.string = 'foobar' assert_equal 'foobar', instance.string assert_equal 'foobar', instance.get_property('string') end end it "handles the 'all' signal" do a = nil GObject.signal_connect(instance, 'all') { a = 4 } GObject.signal_emit instance, 'all' a.must_equal 4 end it "handles the 'cleanup' signal" do a = nil GObject.signal_connect(instance, 'cleanup') { a = 4 } GObject.signal_emit instance, 'cleanup' a.must_equal 4 end it "handles the 'first' signal" do a = nil GObject.signal_connect(instance, 'first') { a = 4 } GObject.signal_emit instance, 'first' a.must_equal 4 end it "handles the 'sig-with-array-len-prop' signal" do skip unless get_signal_introspection_data 'Regress', 'TestObj', 'sig-with-array-len-prop' a = nil GObject.signal_connect(instance, 'sig-with-array-len-prop') do |_obj, arr, _user_data| a = arr end arr = GirFFI::InPointer.from_array(:uint, [1, 2, 3]) GObject.signal_emit instance, 'sig-with-array-len-prop', arr, 3 a.to_a.must_equal [1, 2, 3] end it "handles the 'sig-with-array-prop' signal" do a = nil GObject.signal_connect(instance, 'sig-with-array-prop') { |_, arr, _| a = arr } GObject.signal_emit instance, 'sig-with-array-prop', GLib::Array.from(:uint, [1, 2, 3]) a.to_a.must_equal [1, 2, 3] end it "handles the 'sig-with-foreign-struct' signal" do skip unless get_signal_introspection_data 'Regress', 'TestObj', 'sig-with-foreign-struct' a = nil instance.signal_connect 'sig-with-foreign-struct' do |_obj, ct| a = ct end cairo_context = Regress.test_cairo_context_full_return GObject.signal_emit instance, 'sig-with-foreign-struct', cairo_context a.must_be_instance_of Cairo::Context a.must_equal cairo_context end it "handles the 'sig-with-hash-prop' signal" do a = nil GObject.signal_connect(instance, 'sig-with-hash-prop') do |_, ghash, _| a = ghash.to_hash end g_hash_table = GLib::HashTable.from([:utf8, GObject::Value], 'foo' => GObject::Value.from('bar')) GObject.signal_emit instance, 'sig-with-hash-prop', g_hash_table a['foo'].must_be_instance_of GObject::Value a['foo'].get_value.must_equal 'bar' end it "handles the 'sig-with-int64-prop' signal" do skip unless get_signal_introspection_data 'Regress', 'TestObj', 'sig-with-int64-prop' a = nil GObject.signal_connect(instance, 'sig-with-int64-prop') do |_obj, int64, _user_data| a = int64 end result = GObject.signal_emit instance, 'sig-with-int64-prop', 0x7fff_ffff_ffff_ffff a.must_equal 0x7fff_ffff_ffff_ffff result.must_equal 0x7fff_ffff_ffff_ffff end it "handles the 'sig-with-intarray-ret' signal" do skip unless get_signal_introspection_data 'Regress', 'TestObj', 'sig-with-intarray-ret' a = nil GObject.signal_connect(instance, 'sig-with-intarray-ret') do |_, i, _| a = i [3, 2, 1] end result = GObject.signal_emit instance, 'sig-with-intarray-ret', 3 a.must_equal 3 result.to_a.must_equal [3, 2, 1] end it "handles the 'sig-with-obj' signal" do a = nil GObject.signal_connect(instance, 'sig-with-obj') do |_, obj, _| a = obj end object = Regress::TestObj.constructor GObject.signal_emit instance, 'sig-with-obj', object a.must_equal object end it "handles the 'sig-with-strv' signal" do a = nil GObject.signal_connect(instance, 'sig-with-strv') do |_, strs, _| a = strs end GObject.signal_emit instance, 'sig-with-strv', GLib::Strv.from(%w(foo bar)) a.to_a.must_equal %w(foo bar) end it "handles the 'sig-with-uint64-prop' signal" do skip unless get_signal_introspection_data 'Regress', 'TestObj', 'sig-with-uint64-prop' a = nil GObject.signal_connect(instance, 'sig-with-uint64-prop') do |_, uint64, _| a = uint64 end result = GObject.signal_emit instance, 'sig-with-uint64-prop', 0xffff_ffff_ffff_ffff a.must_equal 0xffff_ffff_ffff_ffff result.must_equal 0xffff_ffff_ffff_ffff end it "handles the 'test' signal" do a = b = nil o = Regress::TestSubObj.new GObject.signal_connect(o, 'test', 2) { |i, d| a = d; b = i } GObject.signal_emit o, 'test' assert_equal [2, o], [a, b] end it "handles the 'test-with-static-scope-arg' signal" do a = nil GObject.signal_connect(instance, 'test-with-static-scope-arg') do |_, obj, _| a = obj end arg = Regress::TestSimpleBoxedA.new arg.some_int = 12_345 GObject.signal_emit instance, 'test-with-static-scope-arg', arg a.some_int.must_equal 12_345 end end describe 'Regress::TestOtherError' do before do skip unless get_introspection_data 'Regress', 'TestOtherError' end it 'has the member :code1' do Regress::TestOtherError[:code1].must_equal 1 end it 'has the member :code2' do Regress::TestOtherError[:code2].must_equal 2 end it 'has the member :code3' do Regress::TestOtherError[:code3].must_equal 3 end it 'has a working function #quark' do quark = Regress::TestOtherError.quark GLib.quark_to_string(quark).must_equal 'regress-test-other-error' end end describe 'Regress::TestPrivateEnum' do it 'has the member :public_enum_before' do Regress::TestPrivateEnum[:public_enum_before].must_equal 1 end it 'does not have the member :private' do Regress::TestPrivateEnum[:private].must_be_nil end it 'has the member :public_enum_after' do Regress::TestPrivateEnum[:public_enum_after].must_equal 4 end end describe 'Regress::TestPrivateStruct' do let(:instance) { Regress::TestPrivateStruct.new } it 'has a writable field this_is_public_before' do instance.this_is_public_before.must_equal 0 instance.this_is_public_before = 42 instance.this_is_public_before.must_equal 42 end it 'has a private field this_is_private' do skip 'This field is identified as readable in the typelib' instance.wont_respond_to :this_is_private instance.wont_respond_to :this_is_private= end it 'has a writable field this_is_public_after' do instance.this_is_public_after.must_equal 0 instance.this_is_public_after = 42 instance.this_is_public_after.must_equal 42 end end describe 'Regress::TestReferenceEnum' do before do skip unless get_introspection_data 'Regress', 'TestReferenceEnum' end it 'has the member :0' do Regress::TestReferenceEnum[:"0"].must_equal 4 end it 'has the member :1' do Regress::TestReferenceEnum[:"1"].must_equal 2 end it 'has the member :2' do Regress::TestReferenceEnum[:"2"].must_equal 54 end it 'has the member :3' do Regress::TestReferenceEnum[:"3"].must_equal 4 end it 'has the member :4' do Regress::TestReferenceEnum[:"4"].must_equal 216 end it 'has the member :5' do Regress::TestReferenceEnum[:"5"].must_equal(-217) end end describe 'Regress::TestSimpleBoxedA' do it 'creates an instance using #new' do obj = Regress::TestSimpleBoxedA.new assert_instance_of Regress::TestSimpleBoxedA, obj end let(:instance) { Regress::TestSimpleBoxedA.new } it 'has a writable field some_int' do instance.some_int.must_equal 0 instance.some_int = 42 instance.some_int.must_equal 42 end it 'has a writable field some_int8' do instance.some_int8.must_equal 0 instance.some_int8 = 42 instance.some_int8.must_equal 42 end it 'has a writable field some_double' do instance.some_double.must_equal 0.0 instance.some_double = 42.0 instance.some_double.must_equal 42.0 end it 'has a writable field some_enum' do instance.some_enum.must_equal :value1 instance.some_enum = :value4 instance.some_enum.must_equal :value4 end it 'has a working method #copy' do instance.some_int = 4236 obj2 = instance.copy obj2.must_be_instance_of Regress::TestSimpleBoxedA obj2.some_int.must_equal instance.some_int instance.some_int = 89 obj2.some_int.wont_equal instance.some_int end it 'has a working method #equals' do instance.some_int = 4236 ob2 = Regress::TestSimpleBoxedA.new ob2.some_int = 4236 ob2.equals(instance).must_equal true ob2.some_enum = :value3 ob2.equals(instance).must_equal true ob2.some_int = 42 ob2.equals(instance).wont_equal true end it 'has a working function #const_return' do result = Regress::TestSimpleBoxedA.const_return [result.some_int, result.some_int8, result.some_double].must_equal [5, 6, 7.0] end end describe 'Regress::TestSimpleBoxedB' do let(:instance) { Regress::TestSimpleBoxedB.new } it 'has a writable field some_int8' do instance.some_int8.must_equal 0 instance.some_int8 = 42 instance.some_int8.must_equal 42 end it 'has a writable field nested_a' do instance.nested_a.some_int.must_equal 0 instance.nested_a = Regress::TestSimpleBoxedA.const_return instance.nested_a.some_int.must_equal 5 end it 'has a working method #copy' do instance.some_int8 = -42 instance.nested_a.some_int = 4242 copy = instance.copy [copy.some_int8, copy.nested_a.some_int].must_equal [-42, 4242] instance.some_int8 = 103 copy.some_int8.must_equal(-42) end end describe 'Regress::TestStructA' do let(:instance) { Regress::TestStructA.new } it 'has a writable field some_int' do instance.some_int.must_equal 0 instance.some_int = 2556 instance.some_int.must_equal 2556 end it 'has a writable field some_int8' do instance.some_int8.must_equal 0 instance.some_int8 = -10 instance.some_int8.must_equal(-10) end it 'has a writable field some_double' do instance.some_double.must_equal 0.0 instance.some_double = 1.03455e20 instance.some_double.must_equal 1.03455e20 end it 'has a writable field some_enum' do instance.some_enum.must_equal :value1 instance.some_enum = :value2 instance.some_enum.must_equal :value2 end it 'has a working method #clone' do a = Regress::TestStructA.new a.some_int = 2556 a.some_int8 = -10 a.some_double = 1.03455e20 a.some_enum = :value2 b = a.clone assert_equal 2556, b.some_int assert_equal(-10, b.some_int8) assert_equal 1.03455e20, b.some_double assert_equal :value2, b.some_enum end it 'has a working function #parse' do skip unless get_method_introspection_data 'Regress', 'TestStructA', 'parse' a = Regress::TestStructA.parse('this string is actually ignored') a.some_int.must_equal 23 end end describe 'Regress::TestStructB' do let(:instance) { Regress::TestStructB.new } it 'has a writable field some_int8' do instance.some_int8.must_equal 0 instance.some_int8 = 42 instance.some_int8.must_equal 42 end it 'has a writable field nested_a' do instance.nested_a.some_int.must_equal 0 nested = Regress::TestStructA.new nested.some_int = -4321 instance.nested_a = nested instance.nested_a.some_int.must_equal(-4321) end it 'has a working method #clone' do a = Regress::TestStructB.new a.some_int8 = 42 a.nested_a.some_int = 2556 a.nested_a.some_int8 = -10 a.nested_a.some_double = 1.03455e20 a.nested_a.some_enum = :value2 b = a.clone assert_equal 42, b.some_int8 assert_equal 2556, b.nested_a.some_int assert_equal(-10, b.nested_a.some_int8) assert_equal 1.03455e20, b.nested_a.some_double assert_equal :value2, b.nested_a.some_enum end end describe 'Regress::TestStructC' do let(:instance) { Regress::TestStructC.new } it 'has a writable field another_int' do instance.another_int.must_equal 0 instance.another_int = 42 instance.another_int.must_equal 42 end it 'has a writable field obj' do o = Regress::TestSubObj.new instance.obj.must_be_nil instance.obj = o instance.obj.must_equal o end end describe 'Regress::TestStructD' do let(:instance) { Regress::TestStructD.new } it 'has a writable field array1' do instance.array1.must_be :==, [] struct = Regress::TestStructA.new instance.array1 = [struct] instance.array1.must_be :==, [struct] end it 'has a writable field array2' do instance.array2.must_be :==, [] o = Regress::TestSubObj.new instance.array2 = [o] instance.array2.must_be :==, [o] end it 'has a writable field field' do instance.field.must_be_nil o = Regress::TestSubObj.new instance.field = o instance.field.must_equal o end it 'has a writable field list' do instance.list.must_be_nil o = Regress::TestSubObj.new instance.list = [o] instance.list.must_be :==, [o] end it 'has a writable field garray' do instance.garray.must_be_nil o = Regress::TestSubObj.new instance.garray = [o] instance.garray.must_be :==, [o] end end describe 'Regress::TestStructE' do let(:instance) { Regress::TestStructE.new } it 'has a writable field some_type' do instance.some_type.must_equal 0 instance.some_type = GObject::TYPE_STRING instance.some_type.must_equal GObject::TYPE_STRING end it 'has a writable field some_union' do instance.some_union.map(&:v_int).must_equal [0, 0] union1 = Regress::TestStructE__some_union__union.new union1.v_int = 42 union2 = Regress::TestStructE__some_union__union.new union2.v_int = 84 instance.some_union = [union1, union2] instance.some_union.map(&:v_int).must_equal [42, 84] end end describe 'Regress::TestStructE__some_union__union' do let(:instance) { Regress::TestStructE__some_union__union.new } it 'has a writable field v_int' do instance.v_int.must_equal 0 instance.v_int = -54_321 instance.v_int.must_equal(-54_321) end it 'has a writable field v_uint' do instance.v_uint.must_equal 0 instance.v_uint = 54_321 instance.v_uint.must_equal 54_321 end it 'has a writable field v_long' do instance.v_long.must_equal 0 instance.v_long = -54_321 instance.v_long.must_equal(-54_321) end it 'has a writable field v_ulong' do instance.v_long.must_equal 0 instance.v_long = 54_321 instance.v_long.must_equal 54_321 end it 'has a writable field v_int64' do instance.v_int64.must_equal 0 instance.v_int64 = -54_321_000_000_000 instance.v_int64.must_equal(-54_321_000_000_000) end it 'has a writable field v_uint64' do instance.v_uint64.must_equal 0 instance.v_uint64 = 54_321_000_000_000 instance.v_uint64.must_equal 54_321_000_000_000 end it 'has a writable field v_float' do instance.v_float.must_equal 0 instance.v_float = 3.1415 instance.v_float.must_be_close_to 3.1415 end it 'has a writable field v_double' do instance.v_double.must_equal 0 instance.v_double = 3.1415 instance.v_double.must_equal 3.1415 end it 'has a writable field v_pointer' do instance.v_pointer.must_be :null? instance.v_pointer = FFI::Pointer.new 54_321 instance.v_pointer.address.must_equal 54_321 end end describe 'Regress::TestStructF' do before do skip unless get_introspection_data 'Regress', 'TestStructF' end let(:instance) { Regress::TestStructF.new } it 'has a writable field ref_count' do instance.ref_count.must_equal 0 instance.ref_count = 1 instance.ref_count.must_equal 1 end it 'has a writable field data1' do instance.data1.must_be :null? instance.data1 = FFI::MemoryPointer.new(:int32).tap { |it| it.put_int(0, 42) } instance.data1.read_int.must_equal 42 end # TODO: Check what gobject-introspection should/will do with these fields. it 'has a writable field data2' do skip 'Introspection data cannot deal with type of this field yet' end it 'has a writable field data3' do skip 'Introspection data cannot deal with type of this field yet' end it 'has a writable field data4' do skip 'Introspection data cannot deal with type of this field yet' end it 'has a writable field data5' do skip 'Introspection data cannot deal with type of this field yet' end it 'has a writable field data6' do skip 'Introspection data cannot deal with type of this field yet' end end describe 'Regress::TestStructFixedArray' do let(:instance) { Regress::TestStructFixedArray.new } it 'has a writable field just_int' do instance.just_int.must_equal 0 instance.just_int = 42 instance.just_int.must_equal 42 end it 'has a writable field array' do instance.array.must_be :==, [0] * 10 instance.array = (1..10).to_a instance.array.must_be :==, (1..10).to_a end it 'has a working method #frob' do instance.array = (0..9).to_a instance.frob instance.array.must_be :==, (42..42 + 9).to_a instance.just_int.must_equal 7 end end describe 'Regress::TestSubObj' do it 'creates an instance using #new' do tso = Regress::TestSubObj.new assert_instance_of Regress::TestSubObj, tso end it "does not create an instance using its parent object's custom constructors" do proc { Regress::TestSubObj.constructor }.must_raise NoMethodError end let(:instance) { Regress::TestSubObj.new } it 'has a working method #instance_method' do res = instance.instance_method assert_equal 0, res end it 'has a working method #unset_bare' do instance.unset_bare pass end it 'does not have a field parent_instance' do instance.wont_respond_to :parent_instance end end describe 'Regress::TestWi8021x' do it 'creates an instance using #new' do o = Regress::TestWi8021x.new assert_instance_of Regress::TestWi8021x, o end it 'has a working function #static_method' do assert_equal(-84, Regress::TestWi8021x.static_method(-42)) end let(:instance) { Regress::TestWi8021x.new } it 'has a working method #get_testbool' do instance.get_testbool.must_equal true end it 'has a working method #set_testbool' do instance.set_testbool true instance.get_testbool.must_equal true instance.set_testbool false instance.get_testbool.must_equal false end describe "its 'testbool' property" do it 'can be retrieved with #get_property' do instance.get_property('testbool').must_equal true end it 'can be retrieved with #testbool' do instance.testbool.must_equal true end it 'can be set with #set_property' do instance.set_property 'testbool', true instance.get_testbool.must_equal true instance.get_property('testbool').must_equal true instance.set_property 'testbool', false instance.get_testbool.must_equal false instance.get_property('testbool').must_equal false end it 'can be set with #testbool=' do instance.testbool = true instance.testbool.must_equal true instance.get_testbool.must_equal true instance.get_property('testbool').must_equal true instance.testbool = false instance.testbool.must_equal false instance.get_testbool.must_equal false instance.get_property('testbool').must_equal false end end end it 'has the constant UTF8_CONSTANT' do assert_equal 'const ♥ utf8', Regress::UTF8_CONSTANT end it 'has a working function #aliased_caller_alloc' do result = Regress.aliased_caller_alloc result.must_be_instance_of Regress::TestBoxed end it 'has a working function #annotation_attribute_func' do info = get_introspection_data('Regress', 'annotation_attribute_func') param = info.args.last param.attribute('some.annotation').must_equal 'value' param.attribute('another.annotation').must_equal 'blahvalue' obj = Regress::AnnotationObject.new Regress.annotation_attribute_func(obj, 'hello').must_equal 42 end it 'has a working function #annotation_custom_destroy' do result = Regress.annotation_custom_destroy {} result.must_be_nil end it 'has a working function #annotation_get_source_file' do Regress.annotation_get_source_file.must_be_nil end it 'has a working function #annotation_init' do result = Regress.annotation_init %w(foo bar) result.to_a.must_equal %w(foo bar) end it 'has a working function #annotation_invalid_regress_annotation' do Regress.annotation_invalid_regress_annotation(42).must_be_nil end it 'has a working function #annotation_ptr_array' do # TODO: Automatically convert array elements to correct type val1 = GObject::Value.from 1 val2 = GObject::Value.from 'a' Regress.annotation_ptr_array([val1, val2]).must_be_nil end it 'has a working function #annotation_return_array' do Regress.annotation_return_array.must_be_nil end it 'has a working function #annotation_return_filename' do skip 'This function is wrongly annotated as transfer-ownership: full' Regress.annotation_return_filename.must_equal 'a utf-8 filename' end it 'has a working function #annotation_set_source_file' do Regress.annotation_set_source_file('a filename').must_be_nil end it 'has a working function #annotation_space_after_comment_bug631690' do Regress.annotation_space_after_comment_bug631690.must_be_nil end it 'has a working function #annotation_string_array_length' do Regress.annotation_string_array_length(%w(foo bar)).must_be_nil end it 'has a working function #annotation_string_zero_terminated' do Regress.annotation_string_zero_terminated.to_a.must_equal [] end it 'has a working function #annotation_string_zero_terminated_out' do Regress.annotation_string_zero_terminated_out(%w(foo bar)).to_a. must_equal %w(foo bar) end it 'has a working function #annotation_test_parsing_bug630862' do Regress.annotation_test_parsing_bug630862.must_be_nil end it 'has a working function #annotation_transfer_floating' do Regress.setup_method :annotation_transfer_floating method = Regress.method :annotation_transfer_floating # NOTE: The arity of this method was changed in GObjectIntrospection 1.53.2 if method.arity == 1 object = GObject::Object.new Regress.annotation_transfer_floating(object).must_be_nil else Regress.annotation_transfer_floating.must_be_nil end end it 'has a working function #annotation_versioned' do Regress.annotation_versioned.must_be_nil end it 'has a working function #atest_error_quark' do skip unless get_introspection_data 'Regress', 'atest_error_quark' result = Regress.atest_error_quark GLib.quark_to_string(result).must_equal 'regress-atest-error' end it 'has a working function #foo_async_ready_callback' do skip 'This function is defined in the header but not implemented' end it 'has a working function #foo_destroy_notify_callback' do skip 'This function is defined in the header but not implemented' end it 'has a working function #foo_enum_type_method' do skip 'This function is defined in the header but not implemented' end it 'has a working function #foo_enum_type_returnv' do skip 'This function is defined in the header but not implemented' end it 'has a working function #foo_error_quark' do result = Regress.foo_error_quark GLib.quark_to_string(result).must_equal('regress_foo-error-quark') end it 'has a working function #foo_init' do Regress.foo_init.must_equal 0x1138 end it 'has a working function #foo_interface_static_method' do Regress.foo_interface_static_method(42).must_be_nil end it 'has a working function #foo_method_external_references' do skip 'This function is defined in the header but not implemented' end it 'has a working function #foo_not_a_constructor_new' do Regress.foo_not_a_constructor_new.must_be_nil end it 'has a working function #foo_test_array' do Regress.foo_test_array.must_be_nil end it 'has a working function #foo_test_const_char_param' do skip 'This function is defined in the header but not implemented' end it 'has a working function #foo_test_const_char_retval' do skip 'This function is defined in the header but not implemented' end it 'has a working function #foo_test_const_struct_param' do skip 'This function is defined in the header but not implemented' end it 'has a working function #foo_test_const_struct_retval' do skip 'This function is defined in the header but not implemented' end it 'has a working function #foo_test_string_array' do Regress.foo_test_string_array(%w(foo bar)).must_be_nil end it 'has a working function #foo_test_string_array_with_g' do Regress.foo_test_string_array_with_g(%w(foo bar)).must_be_nil end it 'has a working function #foo_test_unsigned_qualifier' do skip 'This function is defined in the header but not implemented' end it 'has a working function #foo_test_unsigned_type' do skip 'This function is defined in the header but not implemented' end it 'has a working function #func_obj_null_in' do Regress.func_obj_null_in nil Regress.func_obj_null_in Regress::TestObj.constructor pass end it 'has a working function #func_obj_nullable_in' do Regress.func_obj_null_in nil Regress.func_obj_null_in Regress::TestObj.constructor pass end it 'has a working function #get_variant' do skip unless get_introspection_data 'Regress', 'get_variant' var = Regress.get_variant var.get_int32.must_equal 42 # TODO: Make var not floating end it 'has a working function #global_get_flags_out' do result = Regress.global_get_flags_out result.must_equal(flag1: true, flag3: true) end it 'has a working function #has_parameter_named_attrs' do skip unless get_introspection_data 'Regress', 'has_parameter_named_attrs' Regress.has_parameter_named_attrs 42, [23] * 32 pass end it 'has a working function #introspectable_via_alias' do Regress.introspectable_via_alias [] pass end it 'has a working function #set_abort_on_error' do Regress.set_abort_on_error false Regress.set_abort_on_error true pass end it 'has a working function #test_abc_error_quark' do skip unless get_introspection_data 'Regress', 'test_abc_error_quark' quark = Regress.test_abc_error_quark GLib.quark_to_string(quark).must_equal 'regress-test-abc-error' end it 'has a working function #test_array_callback' do a = nil b = nil c = 95 result = Regress.test_array_callback do |one, two| a = one b = two c end result.must_equal 2 * c a.to_a.must_equal [-1, 0, 1, 2] b.to_a.must_equal %w(one two three) end it 'has a working function #test_array_fixed_out_objects' do result = Regress.test_array_fixed_out_objects gtype = Regress::TestObj.gtype result.size.must_equal 2 result.each do |o| assert_instance_of Regress::TestObj, o assert_equal gtype, GObject.type_from_instance(o) end end it 'has a working function #test_array_fixed_size_int_in' do assert_equal 5 + 4 + 3 + 2 + 1, Regress.test_array_fixed_size_int_in([5, 4, 3, 2, 1]) end describe '#test_array_fixed_size_int_in' do it 'raises an error when called with the wrong number of arguments' do assert_raises ArgumentError do Regress.test_array_fixed_size_int_in [2] end end end it 'has a working function #test_array_fixed_size_int_out' do Regress.test_array_fixed_size_int_out.must_be :==, [0, 1, 2, 3, 4] end it 'has a working function #test_array_fixed_size_int_return' do Regress.test_array_fixed_size_int_return.must_be :==, [0, 1, 2, 3, 4] end it 'has a working function #test_array_gint16_in' do assert_equal 5 + 4 + 3, Regress.test_array_gint16_in([5, 4, 3]) end it 'has a working function #test_array_gint32_in' do assert_equal 5 + 4 + 3, Regress.test_array_gint32_in([5, 4, 3]) end it 'has a working function #test_array_gint64_in' do assert_equal 5 + 4 + 3, Regress.test_array_gint64_in([5, 4, 3]) end it 'has a working function #test_array_gint8_in' do assert_equal 5 + 4 + 3, Regress.test_array_gint8_in([5, 4, 3]) end it 'has a working function #test_array_gtype_in' do t1 = GObject.type_from_name 'gboolean' t2 = GObject.type_from_name 'gint64' 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 do |ints| arr = ints.to_a arr.shift arr end 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 it 'has a working function #test_array_int_in' do assert_equal 5 + 4 + 3, Regress.test_array_int_in([5, 4, 3]) end it 'has a working function #test_array_int_inout' do Regress.test_array_int_inout([5, 2, 3]).must_be :==, [3, 4] end it 'has a working function #test_array_int_none_out' do Regress.test_array_int_none_out.must_be :==, [1, 2, 3, 4, 5] end it 'has a working function #test_array_int_null_in' do Regress.test_array_int_null_in nil pass end it 'has a working function #test_array_int_null_out' do Regress.test_array_int_null_out.must_be_nil end it 'has a working function #test_array_int_out' do Regress.test_array_int_out.must_be :==, [0, 1, 2, 3, 4] end it 'has a working function #test_array_struct_out' do skip unless get_introspection_data 'Regress', 'test_array_struct_out' result = Regress.test_array_struct_out result.map(&:some_int).must_equal [22, 33, 44] end it 'has a working function #test_async_ready_callback' do main_loop = GLib::MainLoop.new nil, false a = 1 Regress.test_async_ready_callback do main_loop.quit a = 2 end main_loop.run assert_equal 2, a end it 'has a working function #test_boolean' do assert_equal false, Regress.test_boolean(false) assert_equal true, Regress.test_boolean(true) end it 'has a working function #test_boolean_false' do assert_equal false, Regress.test_boolean_false(false) end it 'has a working function #test_boolean_true' do 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 end it 'has a working function #test_cairo_context_none_in' do ct = Regress.test_cairo_context_full_return Regress.test_cairo_context_none_in ct end it 'has a working function #test_cairo_surface_full_out' do cs = Regress.test_cairo_surface_full_out assert_instance_of Cairo::Surface, cs end it 'has a working function #test_cairo_surface_full_return' do cs = Regress.test_cairo_surface_full_return assert_instance_of Cairo::Surface, cs end it 'has a working function #test_cairo_surface_none_in' do cs = Regress.test_cairo_surface_full_return Regress.test_cairo_surface_none_in cs end it 'has a working function #test_cairo_surface_none_return' do cs = Regress.test_cairo_surface_none_return assert_instance_of Cairo::Surface, cs end it 'has a working function #test_callback' do result = Regress.test_callback { 5 } assert_equal 5, result end it 'has a working function #test_callback_async' do a = 1 stored_proc = nil Regress.test_callback_async { |user_data| stored_proc = user_data; a = 2 } result = Regress.test_callback_thaw_async a.must_equal 2 stored_proc.wont_be_nil result.must_equal 2 # TODO: See when we can clean up the stored callback for async callbacks. GirFFI::CallbackBase::CALLBACKS[stored_proc.object_id].must_equal stored_proc end it 'has a working function #test_callback_destroy_notify' do a = 1 stored_proc = nil r1 = Regress.test_callback_destroy_notify { |user_data| stored_proc = user_data; a = 2 } a.must_equal 2 stored_id = stored_proc.object_id GirFFI::CallbackBase::CALLBACKS[stored_id].must_equal stored_proc a = 3 r2 = Regress.test_callback_thaw_notifications a.must_equal 2 r1.must_equal r2 GirFFI::CallbackBase::CALLBACKS[stored_id].must_be_nil end it 'has a working function #test_callback_destroy_notify_no_user_data' do skip unless get_introspection_data 'Regress', 'test_callback_destroy_notify_no_user_data' callback_times_called = 0 b = :not_nil result = Regress.test_callback_destroy_notify_no_user_data do |user_data| callback_times_called += 1 b = user_data callback_times_called * 5 end callback_times_called.must_equal 1 result.must_equal 5 b.must_be_nil result = Regress.test_callback_thaw_notifications callback_times_called.must_equal 2 result.must_equal 10 b.must_be_nil end it 'has a working function #test_callback_return_full' do skip unless get_introspection_data 'Regress', 'test_callback_return_full' obj = Regress::TestObj.constructor Regress.test_callback_return_full { obj } obj.ref_count.must_equal 1 end it 'has a working function #test_callback_thaw_async' do invoked = [] Regress.test_callback_async { invoked << 1; 1 } Regress.test_callback_async { invoked << 2; 2 } Regress.test_callback_async { invoked << 3; 3 } result = Regress.test_callback_thaw_async invoked.must_equal [3, 2, 1] result.must_equal 1 end it 'has a working function #test_callback_thaw_notifications' do Regress.test_callback_destroy_notify { 42 } Regress.test_callback_destroy_notify { 24 } result = Regress.test_callback_thaw_notifications result.must_equal 66 end it 'has a working function #test_callback_user_data' do stored_id = nil result = Regress.test_callback_user_data { |u| stored_id = u; 5 } # TODO: Ensure that the key stored_id is no longer in the callback store stored_id.wont_be_nil result.must_equal 5 end it 'has a working function #test_closure' do c = GObject::RubyClosure.new { 5235 } r = Regress.test_closure c assert_equal 5235, r end it 'has a working function #test_closure_one_arg' do c = GObject::RubyClosure.new { |a| a * 2 } r = Regress.test_closure_one_arg c, 2 assert_equal 4, r end it 'has a working function #test_closure_variant' do arg = GLib::Variant.new_string 'foo' # TODO: Convert proc to RubyClosure automatically closure = GObject::RubyClosure.new do |variant| str = variant.get_string if str == 'foo' GLib::Variant.new_int32 40 else GLib::Variant.new_string 'bar' end end result = Regress.test_closure_variant closure, arg result.get_int32.must_equal 40 end it 'has a working function #test_date_in_gvalue' do date = Regress.test_date_in_gvalue skip unless date.respond_to? :get_year assert_equal [1984, :december, 5], [date.get_year, date.get_month, date.get_day] end it 'has a working function #test_def_error_quark' do skip unless get_introspection_data 'Regress', 'test_def_error_quark' quark = Regress.test_def_error_quark GLib.quark_to_string(quark).must_equal 'regress-test-def-error' end it 'has a working function #test_double' do r = Regress.test_double 5435.32 assert_equal 5435.32, r end it 'has a working function #test_enum_param' do r = Regress.test_enum_param :value3 assert_equal 'value3', r end it 'has a working function #test_error_quark' do skip unless get_introspection_data 'Regress', 'test_error_quark' quark = Regress.test_error_quark GLib.quark_to_string(quark).must_equal 'regress-test-error' end it 'has a working function #test_filename_return' do arr = Regress.test_filename_return arr.must_be :==, ['åäö', '/etc/fstab'] end it 'has a working function #test_float' do r = Regress.test_float 5435.32 assert_in_delta 5435.32, r, 0.001 end it 'has a working function #test_garray_container_return' do arr = Regress.test_garray_container_return arr.must_be_instance_of GLib::PtrArray arr.len.must_equal 1 ptr = arr.pdata ptr2 = ptr.read_pointer ptr2.read_string.must_be :==, 'regress' end it 'has a working function #test_garray_full_return' do result = Regress.test_garray_full_return result.to_a.must_equal ['regress'] end it 'has a working function #test_gerror_callback' do result = nil Regress.test_gerror_callback { |err| result = err.message } result.must_equal 'regression test error' end it 'has a working function #test_ghash_container_return' do hash = Regress.test_ghash_container_return hash.must_be_instance_of GLib::HashTable hash.to_hash.must_equal('foo' => 'bar', 'baz' => 'bat', 'qux' => 'quux') end it 'has a working function #test_ghash_everything_return' do ghash = Regress.test_ghash_everything_return ghash.to_hash.must_be :==, 'foo' => 'bar', 'baz' => 'bat', 'qux' => 'quux' end it 'has a working function #test_ghash_gvalue_in' do skip unless get_introspection_data 'Regress', 'test_ghash_gvalue_in' skip unless get_introspection_data 'Regress', 'test_ghash_gvalue_return' hash_table = Regress.test_ghash_gvalue_return Regress.test_ghash_gvalue_in hash_table end it 'has a working function #test_ghash_gvalue_return' do skip unless get_introspection_data 'Regress', 'test_ghash_gvalue_return' result = Regress.test_ghash_gvalue_return hash = result.to_hash has_enum_and_flag_keys = hash.key?('flags') hash['integer'].get_value.must_equal 12 hash['boolean'].get_value.must_equal true hash['string'].get_value.must_equal 'some text' hash['strings'].get_value.to_a.must_equal %w(first second third) if has_enum_and_flag_keys hash['flags'].get_value.must_equal Regress::TestFlags[:flag1] | Regress::TestFlags[:flag3] hash['enum'].get_value.must_equal :value2 end expected_keys = if has_enum_and_flag_keys %w(boolean enum flags integer string strings) else %w(boolean integer string strings) end hash.keys.sort.must_equal expected_keys end it 'has a working function #test_ghash_nested_everything_return' do result = Regress.test_ghash_nested_everything_return hash = result.to_hash hash.keys.must_equal ['wibble'] hash['wibble'].to_hash.must_equal('foo' => 'bar', 'baz' => 'bat', 'qux' => 'quux') end it 'has a working function #test_ghash_nested_everything_return2' do result = Regress.test_ghash_nested_everything_return2 hash = result.to_hash hash.keys.must_equal ['wibble'] hash['wibble'].to_hash.must_equal('foo' => 'bar', 'baz' => 'bat', 'qux' => 'quux') end it 'has a working function #test_ghash_nothing_in' do Regress.test_ghash_nothing_in('foo' => 'bar', 'baz' => 'bat', 'qux' => 'quux') end it 'has a working function #test_ghash_nothing_in2' do Regress.test_ghash_nothing_in2('foo' => 'bar', 'baz' => 'bat', 'qux' => 'quux') end it 'has a working function #test_ghash_nothing_return' do ghash = Regress.test_ghash_nothing_return ghash.to_hash.must_be :==, 'foo' => 'bar', 'baz' => 'bat', 'qux' => 'quux' end it 'has a working function #test_ghash_nothing_return2' do ghash = Regress.test_ghash_nothing_return2 ghash.to_hash.must_be :==, 'foo' => 'bar', 'baz' => 'bat', 'qux' => 'quux' end it 'has a working function #test_ghash_null_in' do Regress.test_ghash_null_in(nil) end it 'has a working function #test_ghash_null_out' do ghash = Regress.test_ghash_null_out ghash.must_be_nil end it 'has a working function #test_ghash_null_return' do ghash = Regress.test_ghash_null_return ghash.must_be_nil end it 'has a working function #test_glist_container_return' do list = Regress.test_glist_container_return assert_instance_of GLib::List, list list.must_be :==, %w(1 2 3) end it 'has a working function #test_glist_everything_return' do list = Regress.test_glist_everything_return list.must_be :==, %w(1 2 3) end it 'has a working function #test_glist_gtype_container_in' do skip unless get_introspection_data 'Regress', 'test_glist_gtype_container_in' Regress.test_glist_gtype_container_in [Regress::TestObj.gtype, Regress::TestSubObj.gtype] pass end it 'has a working function #test_glist_nothing_in' do Regress.test_glist_nothing_in %w(1 2 3) pass end it 'has a working function #test_glist_nothing_in2' do Regress.test_glist_nothing_in2 %w(1 2 3) pass end it 'has a working function #test_glist_nothing_return' do list = Regress.test_glist_nothing_return list.must_be :==, %w(1 2 3) end it 'has a working function #test_glist_nothing_return2' do list = Regress.test_glist_nothing_return2 list.must_be :==, %w(1 2 3) end it 'has a working function #test_glist_null_in' do Regress.test_glist_null_in nil pass end it 'has a working function #test_glist_null_out' do result = Regress.test_glist_null_out result.must_be_nil end it 'has a working function #test_gslist_container_return' do slist = Regress.test_gslist_container_return assert_instance_of GLib::SList, slist slist.must_be :==, %w(1 2 3) end it 'has a working function #test_gslist_everything_return' do slist = Regress.test_gslist_everything_return slist.must_be :==, %w(1 2 3) end it 'has a working function #test_gslist_nothing_in' do Regress.test_gslist_nothing_in %w(1 2 3) pass end it 'has a working function #test_gslist_nothing_in2' do Regress.test_gslist_nothing_in2 %w(1 2 3) pass end it 'has a working function #test_gslist_nothing_return' do slist = Regress.test_gslist_nothing_return slist.must_be :==, %w(1 2 3) end it 'has a working function #test_gslist_nothing_return2' do slist = Regress.test_gslist_nothing_return2 slist.must_be :==, %w(1 2 3) end it 'has a working function #test_gslist_null_in' do Regress.test_gslist_null_in nil pass end it 'has a working function #test_gslist_null_out' do result = Regress.test_gslist_null_out result.must_be_nil end it 'has a working function #test_gtype' do result = Regress.test_gtype 23 assert_equal 23, result end it 'has a working function #test_gvariant_as' do Regress.test_gvariant_as.get_strv.to_a.must_equal %w(one two three) end it 'has a working function #test_gvariant_asv' do result = Regress.test_gvariant_asv result.n_children.must_equal 2 result.lookup_value('name').get_string.must_equal 'foo' result.lookup_value('timeout').get_int32.must_equal 10 end it 'has a working function #test_gvariant_i' do Regress.test_gvariant_i.get_int32.must_equal 1 end it 'has a working function #test_gvariant_s' do Regress.test_gvariant_s.get_string.must_equal 'one' end it 'has a working function #test_gvariant_v' do Regress.test_gvariant_v.get_variant.get_string.must_equal 'contents' end it 'has a working function #test_hash_table_callback' do value = nil Regress.test_hash_table_callback('foo' => 42) { |hash| value = hash } value.to_hash.must_equal('foo' => 42) end it 'has a working function #test_int' do result = Regress.test_int 23 assert_equal 23, result end it 'has a working function #test_int16' do result = Regress.test_int16 23 assert_equal 23, result end it 'has a working function #test_int32' do result = Regress.test_int32 23 assert_equal 23, result end it 'has a working function #test_int64' do result = Regress.test_int64 2_300_000_000_000 assert_equal 2_300_000_000_000, result end it 'has a working function #test_int8' do result = Regress.test_int8 23 assert_equal 23, result end it 'has a working function #test_int_out_utf8' do len = Regress.test_int_out_utf8 'How long?' assert_equal 9, len end it 'has a working function #test_int_value_arg' do gv = GObject::Value.new gv.init GObject.type_from_name 'gint' gv.set_int 343 result = Regress.test_int_value_arg gv assert_equal 343, result end it 'has a working function #test_long' do long_val = FFI.type_size(:long) == 8 ? 2_300_000_000_000 : 2_000_000_000 result = Regress.test_long long_val assert_equal long_val, result end it 'has a working function #test_multi_callback' do a = 1 result = Regress.test_multi_callback do a += 1 23 end assert_equal 2 * 23, result assert_equal 3, a end it 'has a working function #test_multi_double_args' do one, two = Regress.test_multi_double_args 23.1 assert_equal 2 * 23.1, one assert_equal 3 * 23.1, two end it 'has a working function #test_multiline_doc_comments' do Regress.test_multiline_doc_comments.must_be_nil end it 'has a working function #test_nested_parameter' do Regress.test_nested_parameter(3).must_be_nil end it 'has a working function #test_noptr_callback' do skip unless get_introspection_data 'Regress', 'test_noptr_callback' a = 0 Regress.test_noptr_callback { a = 1 } a.must_equal 1 end it 'has a working function #test_null_gerror_callback' do value = nil Regress.test_owned_gerror_callback { |err| value = err } value.message.must_equal 'regression test owned error' end it 'has a working function #test_owned_gerror_callback' do value = nil Regress.test_owned_gerror_callback { |err| value = err } value.message.must_equal 'regression test owned error' end it 'has a working function #test_return_allow_none' do skip unless get_introspection_data 'Regress', 'test_return_allow_none' result = Regress.test_return_allow_none result.must_be_nil end it 'has a working function #test_return_nullable' do skip unless get_introspection_data 'Regress', 'test_return_nullable' result = Regress.test_return_nullable result.must_be_nil end it 'has a working function #test_short' do result = Regress.test_short 23 assert_equal 23, result end it 'has a working function #test_simple_boxed_a_const_return' do result = Regress.test_simple_boxed_a_const_return assert_equal [5, 6, 7.0], [result.some_int, result.some_int8, result.some_double] end it 'has a working function #test_simple_callback' do a = 0 Regress.test_simple_callback { a = 1 } assert_equal 1, a end it 'has a working function #test_size' do assert_equal 2354, Regress.test_size(2354) end it 'has a working function #test_ssize' do assert_equal(-2_000_000, Regress.test_ssize(-2_000_000)) end it 'has a working function #test_struct_a_parse' do skip unless get_introspection_data 'Regress', 'test_struct_a_parse' a = Regress.test_struct_a_parse('this string is actually ignored') a.must_be_instance_of Regress::TestStructA a.some_int.must_equal 23 end it 'has a working function #test_strv_in' do assert_equal true, Regress.test_strv_in(%w(1 2 3)) end it 'has a working function #test_strv_in_gvalue' do arr = Regress.test_strv_in_gvalue arr.must_be :==, %w(one two three) end it 'has a working function #test_strv_out' do arr = Regress.test_strv_out arr.must_be :==, %w(thanks for all the fish) end it 'has a working function #test_strv_out_c' do arr = Regress.test_strv_out_c arr.must_be :==, %w(thanks for all the fish) end it 'has a working function #test_strv_out_container' do arr = Regress.test_strv_out_container arr.must_be :==, %w(1 2 3) end it 'has a working function #test_strv_outarg' do arr = Regress.test_strv_outarg arr.must_be :==, %w(1 2 3) end it 'has a working function #test_timet' do # Time rounded to seconds. t = Time.at(Time.now.to_i) result = Regress.test_timet(t.to_i) assert_equal t, Time.at(result) end it 'has a working function #test_torture_signature_0' do y, z, q = Regress.test_torture_signature_0 86, 'foo', 2 assert_equal [86, 2 * 86, 3 + 2], [y, z, q] end it 'has a working function #test_torture_signature_1' do ret, y, z, q = Regress.test_torture_signature_1(-21, 'hello', 12) [ret, y, z, q].must_equal [true, -21, 2 * -21, 'hello'.length + 12] proc { Regress.test_torture_signature_1(-21, 'hello', 11) }. must_raise GirFFI::GLibError end it 'has a working function #test_torture_signature_2' do a = 1 y, z, q = Regress.test_torture_signature_2 244, 'foofoo', 31 do |u| a = u end assert_equal [244, 2 * 244, 6 + 31], [y, z, q] end it 'has a working function #test_uint' do assert_equal 31, Regress.test_uint(31) end it 'has a working function #test_uint16' do assert_equal 31, Regress.test_uint16(31) end it 'has a working function #test_uint32' do assert_equal 540_000, Regress.test_uint32(540_000) end it 'has a working function #test_uint64' do assert_equal 54_000_000_000_000, Regress.test_uint64(54_000_000_000_000) end it 'has a working function #test_uint8' do assert_equal 31, Regress.test_uint8(31) end it 'has a working function #test_ulong' do assert_equal 54_000_000_000_000, Regress.test_uint64(54_000_000_000_000) end it 'has a working function #test_unconventional_error_quark' do skip unless get_introspection_data 'Regress', 'test_unconventional_error_quark' result = Regress.test_unconventional_error_quark GLib.quark_to_string(result).must_equal 'regress-test-other-error' end it 'has a working function #test_unichar' do assert_equal 120, Regress.test_unichar(120) assert_equal 540_000, Regress.test_unichar(540_000) end it 'has a working function #test_unsigned_enum_param' do assert_equal 'value1', Regress.test_unsigned_enum_param(:value1) assert_equal 'value2', Regress.test_unsigned_enum_param(:value2) end it 'has a working function #test_ushort' do assert_equal 54_000_000, Regress.test_uint64(54_000_000) end it 'has a working function #test_utf8_const_in' do Regress.test_utf8_const_in("const \xe2\x99\xa5 utf8") pass end it 'has a working function #test_utf8_const_return' do result = Regress.test_utf8_const_return assert_equal "const \xe2\x99\xa5 utf8", result end it 'has a working function #test_utf8_inout' do result = Regress.test_utf8_inout "const \xe2\x99\xa5 utf8" assert_equal "nonconst \xe2\x99\xa5 utf8", result end it 'has a working function #test_utf8_nonconst_return' do result = Regress.test_utf8_nonconst_return assert_equal "nonconst \xe2\x99\xa5 utf8", result end it 'has a working function #test_utf8_null_in' do Regress.test_utf8_null_in nil pass end it 'has a working function #test_utf8_null_out' do Regress.test_utf8_null_out.must_be_nil end it 'has a working function #test_utf8_out' do result = Regress.test_utf8_out assert_equal "nonconst \xe2\x99\xa5 utf8", result end it 'has a working function #test_utf8_out_nonconst_return' do r, out = Regress.test_utf8_out_nonconst_return assert_equal %w(first second), [r, out] end it 'has a working function #test_utf8_out_out' do out0, out1 = Regress.test_utf8_out_nonconst_return assert_equal %w(first second), [out0, out1] end it 'has a working function #test_value_return' do result = Regress.test_value_return 3423 result.must_equal 3423 end it 'has a working function #test_versioning' do skip unless get_introspection_data 'Regress', 'test_versioning' Regress.test_versioning pass end it 'raises an appropriate NoMethodError when a function is not found' do proc { Regress.this_method_does_not_exist }. must_raise(NoMethodError). message.must_match(/^undefined method `this_method_does_not_exist' (for Regress:Module|on Regress \(Module\))$/) end end gir_ffi-0.11.4/test/integration/generated_everything_test.rb0000644000004100000410000003110613170036060024317 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' GirFFI.setup :Everything describe Everything do it 'has a working function #const_return_GType' do Everything.const_return_GType.must_equal GObject::TYPE_OBJECT end it 'has a working function #const_return_filename' do Everything.const_return_filename.must_equal '' end it 'has a working function #const_return_gboolean' do Everything.const_return_gboolean.must_equal false end it 'has a working function #const_return_gchar' do Everything.const_return_gchar.must_equal 0 end it 'has a working function #const_return_gdouble' do Everything.const_return_gdouble.must_equal 0 end it 'has a working function #const_return_gfloat' do Everything.const_return_gfloat.must_equal 0 end it 'has a working function #const_return_gint' do Everything.const_return_gint.must_equal 0 end it 'has a working function #const_return_gint16' do Everything.const_return_gint16.must_equal 0 end it 'has a working function #const_return_gint32' do Everything.const_return_gint32.must_equal 0 end it 'has a working function #const_return_gint64' do Everything.const_return_gint64.must_equal 0 end it 'has a working function #const_return_gint8' do Everything.const_return_gint8.must_equal 0 end it 'has a working function #const_return_gintptr' do Everything.const_return_gintptr.must_equal 0 end it 'has a working function #const_return_glong' do Everything.const_return_glong.must_equal 0 end it 'has a working function #const_return_gpointer' do skip unless get_introspection_data 'Everything', 'const_return_gpointer' Everything.const_return_gpointer.must_be :null? end it 'has a working function #const_return_gshort' do Everything.const_return_gshort.must_equal 0 end it 'has a working function #const_return_gsize' do Everything.const_return_gsize.must_equal 0 end it 'has a working function #const_return_gssize' do Everything.const_return_gssize.must_equal 0 end it 'has a working function #const_return_guint' do Everything.const_return_guint.must_equal 0 end it 'has a working function #const_return_guint16' do Everything.const_return_guint16.must_equal 0 end it 'has a working function #const_return_guint32' do Everything.const_return_guint32.must_equal 0 end it 'has a working function #const_return_guint64' do Everything.const_return_guint64.must_equal 0 end it 'has a working function #const_return_guint8' do Everything.const_return_guint8.must_equal 0 end it 'has a working function #const_return_guintptr' do Everything.const_return_guintptr.must_equal 0 end it 'has a working function #const_return_gulong' do Everything.const_return_gulong.must_equal 0 end it 'has a working function #const_return_gunichar' do Everything.const_return_gunichar.must_equal 0 end it 'has a working function #const_return_gushort' do Everything.const_return_gushort.must_equal 0 end it 'has a working function #const_return_utf8' do Everything.const_return_utf8.must_equal '' end it 'has a working function #nullfunc' do Everything.nullfunc.must_be_nil end it 'has a working function #one_outparam_GType' do Everything.one_outparam_GType.must_equal 0 end it 'has a working function #one_outparam_filename' do # NOTE: This function stores a null pointer in its output parameter. Everything.one_outparam_filename.must_be_nil end it 'has a working function #one_outparam_gboolean' do Everything.one_outparam_gboolean.must_equal false end it 'has a working function #one_outparam_gchar' do skip 'GIR gives the incorrect type: utf8 instead of gchar' Everything.one_outparam_gchar.must_equal 0 end it 'has a working function #one_outparam_gdouble' do Everything.one_outparam_gdouble.must_equal 0 end it 'has a working function #one_outparam_gfloat' do Everything.one_outparam_gfloat.must_equal 0 end it 'has a working function #one_outparam_gint' do Everything.one_outparam_gint.must_equal 0 end it 'has a working function #one_outparam_gint16' do Everything.one_outparam_gint16.must_equal 0 end it 'has a working function #one_outparam_gint32' do Everything.one_outparam_gint32.must_equal 0 end it 'has a working function #one_outparam_gint64' do Everything.one_outparam_gint64.must_equal 0 end it 'has a working function #one_outparam_gint8' do Everything.one_outparam_gint8.must_equal 0 end it 'has a working function #one_outparam_gintptr' do Everything.one_outparam_gintptr.must_equal 0 end it 'has a working function #one_outparam_glong' do Everything.one_outparam_glong.must_equal 0 end it 'has a working function #one_outparam_gpointer' do skip unless get_introspection_data 'Everything', 'one_outparam_gpointer' Everything.one_outparam_gpointer.must_be :null? end it 'has a working function #one_outparam_gshort' do Everything.one_outparam_gshort.must_equal 0 end it 'has a working function #one_outparam_gsize' do Everything.one_outparam_gsize.must_equal 0 end it 'has a working function #one_outparam_gssize' do Everything.one_outparam_gssize.must_equal 0 end it 'has a working function #one_outparam_guint' do Everything.one_outparam_guint.must_equal 0 end it 'has a working function #one_outparam_guint16' do Everything.one_outparam_guint16.must_equal 0 end it 'has a working function #one_outparam_guint32' do Everything.one_outparam_guint32.must_equal 0 end it 'has a working function #one_outparam_guint64' do Everything.one_outparam_guint64.must_equal 0 end it 'has a working function #one_outparam_guint8' do Everything.one_outparam_guint8.must_equal 0 end it 'has a working function #one_outparam_guintptr' do Everything.one_outparam_guintptr.must_equal 0 end it 'has a working function #one_outparam_gulong' do Everything.one_outparam_gulong.must_equal 0 end it 'has a working function #one_outparam_gunichar' do Everything.one_outparam_gunichar.must_equal 0 end it 'has a working function #one_outparam_gushort' do Everything.one_outparam_gushort.must_equal 0 end it 'has a working function #one_outparam_utf8' do # NOTE: This function stores a null pointer in its output parameter. Everything.one_outparam_utf8.must_be_nil end it 'has a working function #oneparam_GType' do Everything.oneparam_GType(0).must_be_nil end it 'has a working function #oneparam_filename' do Everything.oneparam_filename('').must_be_nil end it 'has a working function #oneparam_gboolean' do Everything.oneparam_gboolean(false).must_be_nil end it 'has a working function #oneparam_gchar' do Everything.oneparam_gchar(0).must_be_nil end it 'has a working function #oneparam_gdouble' do Everything.oneparam_gdouble(0.0).must_be_nil end it 'has a working function #oneparam_gfloat' do Everything.oneparam_gfloat(0.0).must_be_nil end it 'has a working function #oneparam_gint' do Everything.oneparam_gint(0).must_be_nil end it 'has a working function #oneparam_gint16' do Everything.oneparam_gint16(0).must_be_nil end it 'has a working function #oneparam_gint32' do Everything.oneparam_gint32(0).must_be_nil end it 'has a working function #oneparam_gint64' do Everything.oneparam_gint64(0).must_be_nil end it 'has a working function #oneparam_gint8' do Everything.oneparam_gint8(0).must_be_nil end it 'has a working function #oneparam_gintptr' do Everything.oneparam_gintptr(0).must_be_nil end it 'has a working function #oneparam_glong' do Everything.oneparam_glong(0).must_be_nil end it 'has a working function #oneparam_gpointer' do skip unless get_introspection_data 'Everything', 'oneparam_gpointer' Everything.oneparam_gpointer(FFI::MemoryPointer.new(:int)).must_be_nil end it 'has a working function #oneparam_gshort' do Everything.oneparam_gshort(0).must_be_nil end it 'has a working function #oneparam_gsize' do Everything.oneparam_gsize(0).must_be_nil end it 'has a working function #oneparam_gssize' do Everything.oneparam_gssize(0).must_be_nil end it 'has a working function #oneparam_guint' do Everything.oneparam_guint(0).must_be_nil end it 'has a working function #oneparam_guint16' do Everything.oneparam_guint16(0).must_be_nil end it 'has a working function #oneparam_guint32' do Everything.oneparam_guint32(0).must_be_nil end it 'has a working function #oneparam_guint64' do Everything.oneparam_guint64(0).must_be_nil end it 'has a working function #oneparam_guint8' do Everything.oneparam_guint8(0).must_be_nil end it 'has a working function #oneparam_guintptr' do Everything.oneparam_guintptr(0).must_be_nil end it 'has a working function #oneparam_gulong' do Everything.oneparam_gulong(0).must_be_nil end it 'has a working function #oneparam_gunichar' do Everything.oneparam_gunichar(0).must_be_nil end it 'has a working function #oneparam_gushort' do Everything.oneparam_gushort(0).must_be_nil end it 'has a working function #oneparam_utf8' do Everything.oneparam_utf8('').must_be_nil end it 'has a working function #passthrough_one_GType' do Everything.passthrough_one_GType(GObject::TYPE_OBJECT).must_equal GObject::TYPE_OBJECT end it 'has a working function #passthrough_one_filename' do Everything.passthrough_one_filename('foo').must_equal 'foo' end it 'has a working function #passthrough_one_gboolean' do Everything.passthrough_one_gboolean(true).must_equal true end it 'has a working function #passthrough_one_gchar' do Everything.passthrough_one_gchar(42).must_equal 42 end it 'has a working function #passthrough_one_gdouble' do Everything.passthrough_one_gdouble(23.42).must_equal 23.42 end it 'has a working function #passthrough_one_gfloat' do Everything.passthrough_one_gfloat(23.42).must_be_close_to 23.42 end it 'has a working function #passthrough_one_gint' do Everything.passthrough_one_gint(42).must_equal 42 end it 'has a working function #passthrough_one_gint16' do Everything.passthrough_one_gint16(42).must_equal 42 end it 'has a working function #passthrough_one_gint32' do Everything.passthrough_one_gint32(42).must_equal 42 end it 'has a working function #passthrough_one_gint64' do Everything.passthrough_one_gint64(42).must_equal 42 end it 'has a working function #passthrough_one_gint8' do Everything.passthrough_one_gint8(42).must_equal 42 end it 'has a working function #passthrough_one_gintptr' do Everything.passthrough_one_gintptr(42).must_equal 42 end it 'has a working function #passthrough_one_glong' do Everything.passthrough_one_glong(42).must_equal 42 end it 'has a working function #passthrough_one_gpointer' do skip unless get_introspection_data 'Everything', 'passthrough_one_gpointer' ptr = FFI::MemoryPointer.new(:int) result = Everything.passthrough_one_gpointer(ptr) result.must_be :==, ptr end it 'has a working function #passthrough_one_gshort' do Everything.passthrough_one_gshort(42).must_equal 42 end it 'has a working function #passthrough_one_gsize' do Everything.passthrough_one_gsize(42).must_equal 42 end it 'has a working function #passthrough_one_gssize' do Everything.passthrough_one_gssize(42).must_equal 42 end it 'has a working function #passthrough_one_guint' do Everything.passthrough_one_guint(42).must_equal 42 end it 'has a working function #passthrough_one_guint16' do Everything.passthrough_one_guint16(42).must_equal 42 end it 'has a working function #passthrough_one_guint32' do Everything.passthrough_one_guint32(42).must_equal 42 end it 'has a working function #passthrough_one_guint64' do Everything.passthrough_one_guint64(42).must_equal 42 end it 'has a working function #passthrough_one_guint8' do Everything.passthrough_one_guint8(42).must_equal 42 end it 'has a working function #passthrough_one_guintptr' do Everything.passthrough_one_guintptr(42).must_equal 42 end it 'has a working function #passthrough_one_gulong' do Everything.passthrough_one_gulong(42).must_equal 42 end it 'has a working function #passthrough_one_gunichar' do Everything.passthrough_one_gunichar(42).must_equal 42 end it 'has a working function #passthrough_one_gushort' do Everything.passthrough_one_gushort(42).must_equal 42 end it 'has a working function #passthrough_one_utf8' do Everything.passthrough_one_utf8('42').must_equal '42' end end gir_ffi-0.11.4/test/base_test_helper.rb0000644000004100000410000000337713170036060020054 0ustar www-datawww-data# frozen_string_literal: true require 'rubygems' if RUBY_PLATFORM == 'java' begin require 'simplecov' SimpleCov.start do track_files 'lib/**/*.rb' add_filter '/test/' end if ENV['CI'] require 'coveralls' Coveralls.wear! end rescue LoadError end require 'minitest/autorun' require 'rspec/mocks/minitest_integration' Thread.abort_on_exception = true module BaseTestExtensions def assert_defines_singleton_method(klass, method, msg = nil) method = method.to_sym methods = klass.singleton_methods(false).map(&:to_sym) msg = message(msg) do "Expected #{mu_pp(klass)} to define singleton method #{mu_pp(method)}, " \ "but only found #{mu_pp(methods)}" end assert_includes methods, method, msg end def refute_defines_singleton_method(klass, method, msg = nil) method = method.to_sym methods = klass.singleton_methods(false).map(&:to_sym) msg = message(msg) do "Expected #{mu_pp(klass)} not to define singleton method #{mu_pp(method)}" end refute_includes methods, method, msg end def assert_defines_instance_method(klass, method, msg = nil) method = method.to_sym methods = klass.instance_methods(false).map(&:to_sym) msg = message(msg) do "Expected #{mu_pp(klass)} to define instance method #{mu_pp(method)}, " \ "but only found #{mu_pp(methods)}" end assert_includes methods, method, msg end def refute_defines_instance_method(klass, method, msg = nil) method = method.to_sym methods = klass.instance_methods(false).map(&:to_sym) msg = message(msg) do "Expected #{mu_pp(klass)} not to define instance method #{mu_pp(method)}" end refute_includes methods, method, msg end end Minitest::Test.send :include, BaseTestExtensions gir_ffi-0.11.4/test/ffi-glib/0000755000004100000410000000000013170036060015664 5ustar www-datawww-datagir_ffi-0.11.4/test/ffi-glib/closure_test.rb0000644000004100000410000000163713170036060020733 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GObject::Closure do describe '.new' do it 'updates the ref_count of the created object' do # Tested on a subclass ... c = GObject::RubyClosure.new {} c.ref_count.must_equal 1 end end describe '#invoke' do it 'invokes the closure' do a = 0 c = GObject::RubyClosure.new { a = 2 } c2 = GObject::Closure.wrap(c.to_ptr) c2.invoke nil, [] a.must_equal 2 end it 'returns the closure result' do c = GObject::RubyClosure.new { 3 } c2 = GObject::Closure.wrap(c.to_ptr) result = c2.invoke GObject::Value.for_gtype(GObject::TYPE_INT), [] result.must_equal 3 end it 'passes arguments' do a = 0 c = GObject::RubyClosure.new { |val| a = val } c2 = GObject::Closure.wrap(c.to_ptr) c2.invoke nil, [5] a.must_equal 5 end end end gir_ffi-0.11.4/test/ffi-glib/bytes_test.rb0000644000004100000410000000261413170036060020401 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GLib::Bytes do it 'can succesfully be created with GLib::Bytes.new' do bytes = GLib::Bytes.new [1, 2, 3] bytes.must_be_instance_of GLib::Bytes end it 'has a working #get_size method' do bytes = GLib::Bytes.new [1, 2, 3] bytes.get_size.must_equal 3 end it 'has a working #get_data method' do bytes = GLib::Bytes.new [1, 2, 3] bytes.get_data.to_a.must_equal [1, 2, 3] end it 'has a working #each method' do a = [] bytes = GLib::Bytes.new [1, 2, 3] bytes.each do |v| a.unshift v end a.must_equal [3, 2, 1] end it 'has a working #to_a method' do bytes = GLib::Bytes.new [1, 2, 3] bytes.to_a.must_equal [1, 2, 3] end describe '.from' do it 'creates a GLib::Bytes object form an array of small integers' do bytes = GLib::Bytes.from [1, 2, 3] bytes.must_be_instance_of GLib::Bytes bytes.to_a.must_equal [1, 2, 3] end it 'returns its argument if given a GLib::Bytes object' do bytes = GLib::Bytes.new [1, 2, 3] result = GLib::Bytes.from bytes assert result.equal?(bytes) end it 'wraps its argument if given a pointer' do bytes = GLib::Bytes.new [1, 2, 3] ptr = bytes.to_ptr result = GLib::Bytes.from ptr result.to_a.must_equal [1, 2, 3] result.to_ptr.must_equal ptr end end end gir_ffi-0.11.4/test/ffi-glib/main_loop_test.rb0000644000004100000410000000221613170036060021226 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' class MainLoopTestException < RuntimeError; end describe GLib::MainLoop do describe '#run' do it 'allows other threads to run' do main_loop = GLib::MainLoop.new nil, false a = [] GLib.timeout_add GLib::PRIORITY_DEFAULT, 150 do main_loop.quit end slow_thread = Thread.new do sleep 0.001 a << 'During run' end a << 'Before run' main_loop.run a << 'After run' slow_thread.join a.must_equal ['Before run', 'During run', 'After run'] end it 'raises and quits on exceptions in callbacks' do main_loop = GLib::MainLoop.new nil, false a = 'expected' # This timeout shouldn't get called guard = GLib.timeout_add GLib::PRIORITY_DEFAULT, 150 do a = 'unexpected' main_loop.quit end GLib.timeout_add GLib::PRIORITY_DEFAULT, 10 do raise MainLoopTestException end -> { main_loop.run }.must_raise MainLoopTestException a.must_equal 'expected' # Clean up uncalled timeout GLib.source_remove guard end end end gir_ffi-0.11.4/test/ffi-glib/hash_table_test.rb0000644000004100000410000000365513170036060021353 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GLib::HashTable do it 'knows its key and value types' do hsh = GLib::HashTable.new :gint32, :utf8 assert_equal :gint32, hsh.key_type assert_equal :utf8, hsh.value_type end describe '::from' do it 'creates a GHashTable from a Ruby hash' do hsh = GLib::HashTable.from [:utf8, :gint32], 'foo' => 23, 'bar' => 32 assert_equal({ 'foo' => 23, 'bar' => 32 }, hsh.to_hash) end it 'return its argument if given a GHashTable' do hsh = GLib::HashTable.from [:utf8, :gint32], 'foo' => 23, 'bar' => 32 hsh2 = GLib::HashTable.from [:utf8, :gint32], hsh assert hsh2.equal? hsh end it 'wraps its argument if given a pointer' do hsh = GLib::HashTable.from [:utf8, :gint32], 'foo' => 23, 'bar' => 32 pointer = hsh.to_ptr assert_instance_of FFI::Pointer, pointer hsh2 = GLib::HashTable.from [:utf8, :gint32], pointer assert_instance_of GLib::HashTable, hsh2 refute hsh2.equal? hsh hsh2.to_hash.must_equal hsh.to_hash end end it 'allows key-value pairs to be inserted' do h = GLib::HashTable.new :utf8, :utf8 h.insert 'foo', 'bar' h.to_hash.must_equal 'foo' => 'bar' end it 'includes Enumerable' do GLib::HashTable.must_include Enumerable end describe 'a HashTable provided by the system' do before do GirFFI.setup :Regress @hash = Regress.test_ghash_container_return end it 'has a working #each method' do a = {} @hash.each { |k, v| a[k] = v } a.must_be :==, 'foo' => 'bar', 'baz' => 'bat', 'qux' => 'quux' end it 'has a working #to_hash method' do @hash.to_hash.must_be :==, 'foo' => 'bar', 'baz' => 'bat', 'qux' => 'quux' end end end gir_ffi-0.11.4/test/ffi-glib/s_list_test.rb0000644000004100000410000000360013170036060020544 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GLib::SList do it 'knows its element type' do arr = GLib::SList.new :gint32 assert_equal :gint32, arr.element_type end describe '#prepend' do it 'prepends integer values' do lst = GLib::SList.new :gint32 res = lst.prepend 1 assert_equal 1, res.data end it 'prepends string values' do lst = GLib::SList.new :utf8 res = lst.prepend 'bla' assert_equal 'bla', res.data end it 'prepends multiple values into a single list' do lst = GLib::SList.new :gint32 res = lst.prepend 1 res2 = res.prepend 2 assert_equal 2, res2.data assert_equal 1, res.data assert_equal res.to_ptr, res2.next.to_ptr end end describe '::from' do it 'creates a GSList from a Ruby array' do lst = GLib::SList.from :gint32, [3, 2, 1] assert_equal [3, 2, 1], lst.to_a end it 'return its argument if given a GSList' do lst = GLib::SList.from :gint32, [3, 2, 1] lst2 = GLib::SList.from :gint32, lst assert_equal lst, lst2 end end describe '#==' do it 'returns true when comparing to an array with the same elements' do list = GLib::SList.from :gint32, [1, 2, 3] list.must_be :==, [1, 2, 3] end it 'returns false when comparing to an array with different elements' do list = GLib::SList.from :gint32, [1, 2, 3] list.wont_be :==, [1, 2] end it 'returns true when comparing to a list with the same elements' do list = GLib::SList.from :gint32, [1, 2, 3] other = GLib::SList.from :gint32, [1, 2, 3] list.must_be :==, other end it 'returns false when comparing to a list with different elements' do list = GLib::SList.from :gint32, [1, 2, 3] other = GLib::SList.from :gint32, [1, 2] list.wont_be :==, other end end end gir_ffi-0.11.4/test/ffi-glib/array_test.rb0000644000004100000410000001217213170036060020371 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GLib::Array do it 'knows its element type' do arr = GLib::Array.new :gint32 assert_equal :gint32, arr.element_type end describe '#append_vals' do before do @arr = GLib::Array.new :gint32 @result = @arr.append_vals [1, 2, 3] end it 'appends values' do assert_equal 3, @arr.len end it 'returns self' do assert_equal @result, @arr end end describe '#each' do before do @arr = GLib::Array.new(:gint32).append_vals [1, 2, 3] end it 'iterates over the values' do a = [] @arr.each { |v| a << v } assert_equal [1, 2, 3], a end end describe '::wrap' do it 'wraps a pointer, taking the element type as the first argument' do arr = GLib::Array.new :gint32 arr.append_vals [1, 2, 3] arr2 = GLib::Array.wrap :gint32, arr.to_ptr assert_equal arr.to_a, arr2.to_a end it "warns the element sizes don't match" do arr = GLib::Array.new :gint32 arr.append_vals [1, 2, 3] proc { GLib::Array.wrap :gint8, arr.to_ptr }.must_output nil, /sizes do not match/ end it 'handles a struct as the element type' do vals = [1, 2, 3].map { |i| GObject::EnumValue.new.tap { |ev| ev.value = i } } arr = GLib::Array.new GObject::EnumValue arr.append_vals vals arr2 = GLib::Array.wrap GObject::EnumValue, arr.to_ptr arr2.to_a.must_equal arr.to_a end end it 'includes Enumerable' do GLib::Array.must_include Enumerable end it 'has a working #to_a method' do arr = GLib::Array.new :gint32 arr.append_vals [1, 2, 3] assert_equal [1, 2, 3], arr.to_a end describe '.from' do it 'creates a GArray from an array of :gint32' do arr = GLib::Array.from :gint32, [3, 2, 1] arr.must_be_instance_of GLib::Array arr.to_a.must_equal [3, 2, 1] end it 'creates a GArray from an array of :gboolean' do arr = GLib::Array.from :gboolean, [true, false, true] arr.must_be_instance_of GLib::Array arr.to_a.must_equal [true, false, true] end it 'return its argument if given a GArray' do arr = GLib::Array.new :gint32 arr.append_vals [3, 2, 1] arr2 = GLib::Array.from :gint32, arr assert arr2.equal? arr end it 'wraps its argument if given a pointer' do arr = GLib::Array.new :gint32 arr.append_vals [3, 2, 1] pointer = arr.to_ptr assert_instance_of FFI::Pointer, pointer arr2 = GLib::Array.from :gint32, pointer assert_instance_of GLib::Array, arr2 refute arr2.equal? arr arr2.to_a.must_equal arr.to_a end end describe '#==' do it 'returns true when comparing to an array with the same elements' do arr = GLib::Array.from :gint32, [1, 2, 3] arr.must_be :==, [1, 2, 3] end it 'returns false when comparing to an array with different elements' do arr = GLib::Array.from :gint32, [1, 2, 3] arr.wont_be :==, [1, 2] end it 'returns true when comparing to a GArray with the same elements' do arr = GLib::Array.from :gint32, [1, 2, 3] other = GLib::Array.from :gint32, [1, 2, 3] arr.must_be :==, other end it 'returns false when comparing to a GArray with different elements' do arr = GLib::Array.from :gint32, [1, 2, 3] other = GLib::Array.from :gint32, [1, 2] arr.wont_be :==, other end end describe '#index' do it 'returns the proper element for an array of :gint32' do arr = GLib::Array.from :gint32, [1, 2, 3] arr.index(2).must_equal 3 end it 'returns the proper element for an array of :utf8' do arr = GLib::Array.from :utf8, %w(a b c) arr.index(1).must_equal 'b' end it 'returns the proper element for an array of :gboolean' do arr = GLib::Array.from :gboolean, [true, false, true] arr.index(1).must_equal false end it 'returns the proper element for an array of struct' do vals = [1, 2, 3].map { |i| GObject::EnumValue.new.tap { |ev| ev.value = i } } arr = GLib::Array.from GObject::EnumValue, vals arr.index(1).value.must_equal 2 end it 'raises an error if the index is out of bounds' do arr = GLib::Array.from :gint32, [1, 2, 3] proc { arr.index(16) }.must_raise IndexError proc { arr.index(-1) }.must_raise IndexError end end describe '#reset_typespec' do describe 'when it needs to guess the type' do it 'guesses :uint8 for size 1' do arr = GLib::Array.from :int8, [1, 2, 3] arr.reset_typespec arr.element_type.must_equal :uint8 end it 'guesses :uint16 for size 2' do arr = GLib::Array.from :int16, [1, 2, 3] arr.reset_typespec arr.element_type.must_equal :uint16 end it 'guesses :uint32 for size 4' do arr = GLib::Array.from :int32, [1, 2, 3] arr.reset_typespec arr.element_type.must_equal :uint32 end it 'guesses :uint64 for size 8' do arr = GLib::Array.from :int64, [1, 2, 3] arr.reset_typespec arr.element_type.must_equal :uint64 end end end end gir_ffi-0.11.4/test/ffi-glib/list_test.rb0000644000004100000410000000423013170036060020222 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GLib::List do it 'knows its element type' do arr = GLib::List.new :gint32 assert_equal :gint32, arr.element_type end describe '#append' do it 'appends integer values' do lst = GLib::List.new :gint32 res = lst.append 1 assert_equal 1, res.data end it 'appends string values' do lst = GLib::List.new :utf8 res = lst.append 'bla' assert_equal 'bla', res.data end it 'appends multiple values into a single list' do lst = GLib::List.new :gint32 lst = lst.append 1 lst = lst.append 2 assert_equal 1, lst.data nxt = lst.next assert_equal 2, nxt.data end end describe '::from' do it 'creates a GList from a Ruby array' do lst = GLib::List.from :gint32, [3, 2, 1] assert_equal [3, 2, 1], lst.to_a end it 'return its argument if given a GList' do lst = GLib::List.from :gint32, [3, 2, 1] lst2 = GLib::List.from :gint32, lst assert lst2.equal? lst end it 'wraps its argument if given a pointer' do lst = GLib::List.from :gint32, [3, 2, 1] pointer = lst.to_ptr assert_instance_of FFI::Pointer, pointer lst2 = GLib::List.from :gint32, pointer assert_instance_of GLib::List, lst2 refute lst2.equal? lst lst2.to_a.must_equal lst.to_a end end describe '#==' do it 'returns true when comparing to an array with the same elements' do list = GLib::List.from :gint32, [1, 2, 3] list.must_be :==, [1, 2, 3] end it 'returns false when comparing to an array with different elements' do list = GLib::List.from :gint32, [1, 2, 3] list.wont_be :==, [1, 2] end it 'returns true when comparing to a list with the same elements' do list = GLib::List.from :gint32, [1, 2, 3] other = GLib::List.from :gint32, [1, 2, 3] list.must_be :==, other end it 'returns false when comparing to a list with different elements' do list = GLib::List.from :gint32, [1, 2, 3] other = GLib::List.from :gint32, [1, 2] list.wont_be :==, other end end end gir_ffi-0.11.4/test/ffi-glib/strv_test.rb0000644000004100000410000000272413170036060020253 0ustar www-datawww-data# frozen_string_literal: true require 'base_test_helper' describe GLib::Strv do describe '::from' do it 'creates a Strv from a Ruby array' do strv = GLib::Strv.from %w(1 2 3) strv.must_be_instance_of GLib::Strv strv.to_a.must_equal %w(1 2 3) end it 'return its argument if given a Strv' do strv = GLib::Strv.from %w(1 2 3) strv2 = GLib::Strv.from strv assert strv2.equal? strv end it 'wraps its argument if given a pointer' do strv = GLib::Strv.from %w(1 2 3) pointer = strv.to_ptr pointer.must_be_kind_of FFI::Pointer strv2 = GLib::Strv.from pointer strv2.must_be_kind_of GLib::Strv refute strv2.equal? strv strv2.to_a.must_equal strv.to_a end end describe '#==' do it 'returns true when comparing to an array with the same elements' do strv = GLib::Strv.from %w(1 2 3) strv.must_be :==, %w(1 2 3) end it 'returns false when comparing to an array with different elements' do strv = GLib::Strv.from %w(1 2 3) strv.wont_be :==, %w(1 2) end it 'returns true when comparing to a strv with the same elements' do strv = GLib::Strv.from %w(1 2 3) other = GLib::Strv.from %w(1 2 3) strv.must_be :==, other end it 'returns false when comparing to a strv with different elements' do strv = GLib::Strv.from %w(1 2 3) other = GLib::Strv.from %w(1 2) strv.wont_be :==, other end end end gir_ffi-0.11.4/test/ffi-glib/ruby_closure_test.rb0000644000004100000410000000314313170036060021766 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GObject::RubyClosure do describe '.new' do it 'takes a mandatory block argument' do assert_raises ArgumentError do GObject::RubyClosure.new end end it 'returns a kind of Closure' do c = GObject::RubyClosure.new {} assert_kind_of GObject::Closure, c end end describe '.wrap' do it 'returns a fully functional object that can invoke the original block' do a = 0 c = GObject::RubyClosure.new { a = 2 } c2 = GObject::RubyClosure.wrap(c.to_ptr) c2.invoke_block assert_equal 2, a end end describe '.marshaller' do it "invokes its closure argument's block" do a = 0 c = GObject::RubyClosure.new { a = 2 } GObject::RubyClosure.marshaller(c, nil, nil, nil, nil) assert_equal 2, a end it 'works when its closure argument is a GObject::Closure' do a = 0 c = GObject::RubyClosure.new { a = 2 } c2 = GObject::Closure.wrap(c.to_ptr) GObject::RubyClosure.marshaller(c2, nil, nil, nil, nil) assert_equal 2, a end it "stores the closure's return value in the proper gvalue" do c = GObject::RubyClosure.new { 2 } gv = GObject::Value.new.init GObject::TYPE_INT GObject::RubyClosure.marshaller(c, gv, nil, nil, nil) assert_equal 2, gv.get_value end end describe '#invoke' do it 'invokes the ruby block' do a = 0 c = GObject::RubyClosure.new { a = 2 } c2 = GObject::Closure.wrap(c.to_ptr) c2.invoke nil, [] assert_equal 2, a end end end gir_ffi-0.11.4/test/ffi-glib/byte_array_test.rb0000644000004100000410000000075013170036060021413 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GLib::ByteArray do it 'can succesfully be created with GLib::ByteArray.new' do ba = GLib::ByteArray.new assert_instance_of GLib::ByteArray, ba end it 'allows strings to be appended to it' do ba = GLib::ByteArray.new ba.append 'abdc' pass end it 'has a working #to_string method' do ba = GLib::ByteArray.new ba = ba.append 'abdc' assert_equal 'abdc', ba.to_string end end gir_ffi-0.11.4/test/ffi-glib/destroy_notify_test.rb0000644000004100000410000000102713170036060022331 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GLib::DestroyNotify do describe '.default' do it 'removes the passed-in key from the callback store' do dummy_proc = 'some-callback' GirFFI::CallbackBase.store_callback dummy_proc GirFFI::CallbackBase::CALLBACKS[dummy_proc.object_id].wont_be_nil user_data = GirFFI::ArgHelper.store dummy_proc GLib::DestroyNotify.default.call user_data GirFFI::CallbackBase::CALLBACKS[dummy_proc.object_id].must_be_nil end end end gir_ffi-0.11.4/test/ffi-glib/ptr_array_test.rb0000644000004100000410000000525013170036060021255 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GLib::PtrArray do it 'knows its element type' do arr = GLib::PtrArray.new :utf8 assert_equal :utf8, arr.element_type end describe '::add' do it 'correctly takes the type into account' do arr = GLib::PtrArray.new :utf8 str = 'test' GLib::PtrArray.add arr, str assert_equal str, arr.pdata.read_pointer.read_string end end describe '#each' do it 'works normally' do arr = GLib::PtrArray.new :utf8 GLib::PtrArray.add arr, 'test1' GLib::PtrArray.add arr, 'test2' GLib::PtrArray.add arr, 'test3' a = [] arr.each { |v| a << v } assert_equal %w(test1 test2 test3), a end it 'works when exiting the loop prematurely' do arr = GLib::PtrArray.new :utf8 GLib::PtrArray.add arr, 'test1' GLib::PtrArray.add arr, 'test2' GLib::PtrArray.add arr, 'test3' a = [] arr.each do |v| a << v break if v == 'test2' end assert_equal %w(test1 test2), a end end it 'includes Enumerable' do GLib::PtrArray.must_include Enumerable end it 'has a working #to_a method' do arr = GLib::PtrArray.new :utf8 GLib::PtrArray.add arr, 'test1' GLib::PtrArray.add arr, 'test2' GLib::PtrArray.add arr, 'test3' assert_equal %w(test1 test2 test3), arr.to_a end it 'has #add as an instance method too' do arr = GLib::PtrArray.new :utf8 arr.add 'test1' assert_equal ['test1'], arr.to_a end describe '#==' do it 'returns true when comparing to an array with the same elements' do arr = GLib::PtrArray.from :utf8, %w(1 2 3) arr.must_be :==, %w(1 2 3) end it 'returns false when comparing to an array with different elements' do arr = GLib::PtrArray.from :utf8, %w(1 2 3) arr.wont_be :==, %w(1 2) end it 'returns true when comparing to a GPtrArray with the same elements' do arr = GLib::PtrArray.from :utf8, %w(1 2 3) other = GLib::PtrArray.from :utf8, %w(1 2 3) arr.must_be :==, other end it 'returns false when comparing to a GPtrArray with different elements' do arr = GLib::PtrArray.from :utf8, %w(1 2 3) other = GLib::PtrArray.from :utf8, %w(1 2) arr.wont_be :==, other end end describe '#index' do it 'returns the correct element' do arr = GLib::PtrArray.from :utf8, %w(1 2 3) arr.index(1).must_equal '2' end it 'raises an error if the index is out of bounds' do arr = GLib::PtrArray.from :utf8, %w(1 2 3) proc { arr.index(16) }.must_raise IndexError proc { arr.index(-1) }.must_raise IndexError end end end gir_ffi-0.11.4/test/ffi-glib/iconv_test.rb0000644000004100000410000000065213170036060020371 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GLib::IConv do let(:instance) { GLib::IConv.open('ascii', 'utf-8') } describe '.open' do it 'creates a new instance of GLib::Iconv' do instance.must_be_instance_of GLib::IConv end end describe '#setup_and_call' do it "works for the method called ''" do instance.setup_and_call :'', [nil, nil, nil, nil] end end end gir_ffi-0.11.4/test/ffi-glib/variant_test.rb0000644000004100000410000000040613170036060020714 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GLib::Variant do describe '#get_string' do it 'returns just the contained string' do var = GLib::Variant.new_string('Foo') var.get_string.must_equal 'Foo' end end end gir_ffi-0.11.4/test/ffi-gobject_test.rb0000644000004100000410000001021613170036060017750 0ustar www-datawww-data# frozen_string_literal: true require 'gir_ffi_test_helper' describe GObject do before do GirFFI.setup :Regress end describe '::signal_emit' do it 'emits a signal' do a = 1 o = Regress::TestSubObj.new prc = proc { a = 2 } callback = GObject::Callback.from prc ::GObject::Lib.g_signal_connect_data o, 'test', callback, nil, nil, 0 GObject.signal_emit o, 'test' assert_equal 2, a end it 'handles return values' do s = Gio::SocketService.new argtypes = [:pointer, :pointer, :pointer, :pointer] callback = FFI::Function.new(:bool, argtypes) { |_a, _b, _c, _d| true } ::GObject::Lib.g_signal_connect_data s, 'incoming', callback, nil, nil, 0 rv = GObject.signal_emit s, 'incoming' assert_equal true, rv end it 'passes in extra arguments' do o = Regress::TestSubObj.new sb = Regress::TestSimpleBoxedA.new sb.some_int8 = 31 sb.some_double = 2.42 sb.some_enum = :value2 b2 = nil argtypes = [:pointer, :pointer, :pointer] callback = FFI::Function.new(:void, argtypes) do |_a, b, _c| b2 = b end ::GObject::Lib.g_signal_connect_data o, 'test-with-static-scope-arg', callback, nil, nil, 0 GObject.signal_emit o, 'test-with-static-scope-arg', sb sb2 = Regress::TestSimpleBoxedA.wrap b2 assert sb.equals(sb2) end it 'allows specifying signal detail' do a = 1 o = Regress::TestSubObj.new callback = FFI::Function.new(:void, [:pointer, :pointer, :pointer]) { a = 2 } ::GObject::Lib.g_signal_connect_data o, 'notify::detail', callback, nil, nil, 0 GObject.signal_emit o, 'notify::detail' a.must_equal 2 end end describe '::signal_connect' do it 'installs a signal handler' do a = 1 o = Regress::TestSubObj.new GObject.signal_connect(o, 'test') { a = 2 } GObject.signal_emit o, 'test' assert_equal 2, a end it 'passes user data to handler' do a = 1 o = Regress::TestSubObj.new GObject.signal_connect(o, 'test', 2) { |_i, d| a = d } GObject.signal_emit o, 'test' assert_equal 2, a end it 'passes object to handler' do o = Regress::TestSubObj.new o2 = nil GObject.signal_connect(o, 'test') { |i, _d| o2 = i } GObject.signal_emit o, 'test' assert_instance_of Regress::TestSubObj, o2 assert_equal o.to_ptr, o2.to_ptr end it 'does not allow connecting an invalid signal' do o = Regress::TestSubObj.new proc { GObject.signal_connect(o, 'not-really-a-signal') {} }. must_raise GirFFI::SignalNotFoundError end it 'handles return values' do s = Gio::SocketService.new GObject.signal_connect(s, 'incoming') { true } rv = GObject.signal_emit s, 'incoming' assert_equal true, rv end it 'requires a block' do o = Regress::TestSubObj.new proc { GObject.signal_connect o, 'test' }.must_raise ArgumentError end it 'allows specifying signal detail' do a = 1 o = Regress::TestSubObj.new GObject.signal_connect(o, 'notify::detail', 2) { |_i, _, d| a = d } GObject.signal_emit o, 'notify::detail' assert_equal 2, a end describe 'connecting a signal with extra arguments' do before do @a = nil @b = 2 o = Regress::TestSubObj.new sb = Regress::TestSimpleBoxedA.new sb.some_int = 23 GObject.signal_connect(o, 'test-with-static-scope-arg', 2) do |_instance, object, user_data| @a = user_data @b = object end GObject.signal_emit o, 'test-with-static-scope-arg', sb end it 'passes on the user data argument' do assert_equal 2, @a end it 'passes on the extra arguments' do assert_instance_of Regress::TestSimpleBoxedA, @b assert_equal 23, @b.some_int end end end describe '::signal_connect_after' do it 'installs a signal handler' do a = 1 o = Regress::TestSubObj.new GObject.signal_connect_after(o, 'test') { a = 2 } GObject.signal_emit o, 'test' assert_equal 2, a end end end gir_ffi-0.11.4/test/minitest/0000755000004100000410000000000013170036060016041 5ustar www-datawww-datagir_ffi-0.11.4/test/minitest/stats_plugin.rb0000644000004100000410000000103513170036060021101 0ustar www-datawww-data# frozen_string_literal: true module Minitest class StatsReporter < AbstractReporter def initialize(_options) @results = [] end def start @current_time = Time.now end def record(result) @results << result end def report slowest = @results.sort_by(&:time).reverse.first(10) slowest.each do |result| puts format('%10.4f %s', result.time, result.location) end end end def self.plugin_stats_init(options) reporter << StatsReporter.new(options) end end gir_ffi-0.11.4/DESIGN.md0000644000004100000410000000647413170036060014534 0ustar www-datawww-data# Design of Gir-FFI ## Basic Idea Gir-FFI uses FFI to read information from the GObject Introspection Repository. Based on that it creates bindings for the information read. ## Class and method creation GirFFI::Builder creates classes and modules at runtime and adds appropriate method_missing methods to them to generate methods and perhaps other classes when required. The following options were discarded, at least for now. * Create classes and all of their methods at runtime. This would be very similar to the method chosen, but would concentrate all the overhead at start-up, some of which would be used for creating methods that will never get called. * Allow offline creation of ruby source generated from the GIR. This is still in interesting idea, but off-line source code generation is not really the Ruby way. ## Method Naming Probably, get_x/set_x pairs should become x and x= to be more Ruby-like. This should be done either by defining them as such directly, or by aliasing. Blindly going by the name leads to weird results thoough, like having x, x= and x_full= as a set. Also, some get_ or set_ methods take extra arguments. These probably shouldn't become accessors either. Boolean-valued methods could get a ? at the end. This requires a lot more thought. For now, the full method names as defined in the GIR are used. ## Ruby-GNOME Compatibility Full Ruby-GNOME compatibility cannot be achieved automatically, since its object hierarchy differs from that of standard GObject: It puts Object in the GLib namespace, and defines signal_connect and friends as methods of GLib::Instantiable; In standard GObject they are functions. Possibly, compatibility enhancing code can be added for these specific exceptions. ## Reference Counting Because we can always make sure GObjects are unref'd when the Ruby object is GC'd, the mechanism of floating references actually gets in the way a bit. Therefore, when floating GObjects are constructed, GirFFI will sink them. All GObjects can then safely be unref'd using a Ruby finalizer. GObjects obtained through other mechanisms than with a constructor will be ref'd once when wrapping them in a ruby object. ## Bootstrapping Class Design The interface to the GObject Introspection Repository itself is also introspectable. The interface is specified in terms of structs and functions rather than objects and methods. For now, the hard-coded Ruby bindings for this don't follow the introspected specification: Gir-FFI cannot bootstrap itself. ## Object initialization Each constructor method is implemented in Ruby by a pair of new/initialize methods. For example, a constructor `new_from_file` is implemented as a combination of the singleton method `new_from_file` and the instance method `initialize_from_file`. User-created subclasses override the appropriate initializer method and must call super with the appropriate arguments. Here is an example of the generated pair of methods: ```ruby class Regress::TestObj def self.new_from_file(*args) obj = allocate obj.__send__ :initialize_from_file, *args obj end def initialize_from_file(x) _v1 = GirFFI::InPointer.from(:utf8, x) _v2 = FFI::MemoryPointer.new(:pointer).write_pointer nil _v3 = Regress::Lib.regress_test_obj_new_from_file _v1, _v2 GirFFI::ArgHelper.check_error(_v2) store_pointer(_v3) end end gir_ffi-0.11.4/tasks/0000755000004100000410000000000013170036060014353 5ustar www-datawww-datagir_ffi-0.11.4/tasks/test.rake0000644000004100000410000001311113170036060016173 0ustar www-datawww-datarequire 'rake/testtask' require 'cucumber/rake/task' require 'rexml/document' require 'rexml/streamlistener' # Listener class used to process GIR xml data, for creating test stubs. class Listener include REXML::StreamListener def initialize @inside_class = false @stack = [] @skip_state = [] end attr_accessor :result attr_accessor :namespace def tag_start name, attrs @stack.push [name, attrs] if @skip_state.last || skippable?(attrs) @skip_state.push true return else @skip_state.push false end obj_name = attrs['name'] case name when "constant" result.puts " it 'has the constant #{obj_name}' do" when "record", "class", "enumeration", "bitfield", "interface", "union" result.puts " describe '#{namespace}::#{obj_name}' do" @inside_class = name when "constructor" result.puts " it 'creates an instance using ##{obj_name}' do" when "field" if @inside_class != 'class' if attrs['private'] == "1" result.puts " it 'has a private field #{obj_name}' do" elsif attrs['writable'] == "1" result.puts " it 'has a writable field #{obj_name}' do" else result.puts " it 'has a read-only field #{obj_name}' do" end end when "function", "method" spaces = @inside_class ? " " : "" result.puts " #{spaces}it 'has a working #{name} ##{obj_name}' do" when "member" result.puts " it 'has the member :#{obj_name}' do" when "namespace" result.puts "describe #{obj_name} do" when "property" accessor_name = obj_name.gsub(/-/, '_') result.puts " describe \"its '#{obj_name}' property\" do" result.puts " it 'can be retrieved with #get_property' do" result.puts " end" result.puts " it 'can be retrieved with ##{accessor_name}' do" result.puts " end" if attrs['writable'] == '1' result.puts " it 'can be set with #set_property' do" result.puts " end" result.puts " it 'can be set with ##{accessor_name}=' do" result.puts " end" end when "glib:signal" result.puts " it \"handles the '#{obj_name}' signal\" do" when "type", "alias", "return-value", "parameters", "instance-parameter", "parameter", "doc", "array", "repository", "include", "package" # Not printed" else puts "Skipping #{name}: #{attrs}" end end def tag_end name org_name, _ = *@stack.pop skipping = @skip_state.pop raise "Expected #{org_name}, got #{name}" if org_name != name return if skipping case name when "constant" result.puts " end" when "record", "class", "enumeration", "bitfield", "interface", "union" result.puts " end" @inside_class = false when "function", "method" if @inside_class result.puts " end" else result.puts " end" end when "constructor", "member", "property", "glib:signal" result.puts " end" when "field" if @inside_class != 'class' result.puts " end" end when "namespace" result.puts "end" end end def skippable? attrs return true if attrs['disguised'] == '1' return true if attrs['introspectable'] == '0' return true if attrs['glib:is-gtype-struct-for'] false end end namespace :test do def define_test_task name Rake::TestTask.new(name) do |t| t.libs = ['lib'] t.ruby_opts += ["-w -Itest"] yield t end end define_test_task(:base) do |t| t.test_files = FileList['test/gir_ffi-base/**/*_test.rb'] end define_test_task(:introspection) do |t| t.test_files = FileList['test/ffi-gobject_introspection/**/*_test.rb'] end define_test_task(:main) do |t| t.test_files = FileList['test/gir_ffi/**/*_test.rb'] end define_test_task(:overrides) do |t| t.test_files = FileList['test/ffi-gobject_test.rb', 'test/ffi-glib/**/*_test.rb', 'test/ffi-gobject/**/*_test.rb'] end define_test_task(:integration) do |t| t.test_files = FileList['test/integration/**/*_test.rb'] end desc 'Build test libraries and typelibs' task :lib => "test/lib/Makefile" do sh %{cd test/lib && make} end task :introspection => :lib task :main => :lib task :overrides => :lib task :integration => :lib desc 'Run the entire test suite as one' define_test_task(:all) do |t| t.test_files = FileList['test/**/*_test.rb'] end task :all => :lib desc 'Run all individual test suites separately' task :suites => [:base, :introspection, :main, :overrides, :integration] def make_stub_file(libname) file = File.new "test/lib/#{libname}-1.0.gir" listener = Listener.new listener.result = File.open("tmp/#{libname.downcase}_lines.rb", 'w') listener.namespace = libname REXML::Document.parse_stream file, listener end desc "Create stubs for integration tests" task :stub => :lib do make_stub_file 'Everything' make_stub_file 'GIMarshallingTests' make_stub_file 'Regress' make_stub_file 'Utility' make_stub_file 'WarnLib' end Cucumber::Rake::Task.new(:features) do |t| t.cucumber_opts = 'features --format pretty' end end file "test/lib/Makefile" => "test/lib/configure" do sh %{cd test/lib && ./configure --enable-maintainer-mode} end file "test/lib/configure" => ["test/lib/autogen.sh", "test/lib/configure.ac"] do sh %{cd test/lib && ./autogen.sh} end task test: 'test:all' gir_ffi-0.11.4/TODO.md0000644000004100000410000001072513170036060014322 0ustar www-datawww-data# TODO ## Memory managment GirFFI does not ~~attempt to free any memory at the moment, or~~ lower the reference count of any objects it gets from GObject. This task therefore involves two parts: - Free non-GObject pointers as needed (at garbage-collection time) - [Done!] Lower reference count of GObjects (at garbage-collection time) **Use memory_profiler to check memory use (https://github.com/SamSaffron/memory_profiler)** ## Refactorings These in the order they occured to me, and may therefore be fixed in any order. - Create Type objects for all FFI types, including the ones currently represented by a single symbol, so we can always do stuff like > `GirFFI::Types::UInt8.get_value_from_pointer(ptr)` rather than having awkward dynamic method dispatch inside GirFFI::InOutPointer. - Move to a single Pointer class, rather than InPointer, InOutPointer and Pointer monkeypatching. ## Derived types Derived classes can now be registered with GObject, but the way to do this is not very nice: class Derived < Base end GirFFI.define_type Derived do |info| info.install_property GObject.param_spec_int("foo", "foo bar", "The Foo Bar Property", 10, 20, 15, 3) # assume Base defines a virtual function called 'some_vfunc' info.install_vfunc_implementation :some_vfunc, proc {|obj| #implementation goes here } end or class Derived < Base def some_vfunc #implementation goes here end end GirFFI.define_type Derived do |info| info.install_property GObject.param_spec_int("foo", "foo bar", "The Foo Bar Property", 10, 20, 15, 3) info.install_vfunc_implementation :some_vfunc end It would be good to replace this with something that's easier to use: * Perhaps auto-register types, like Gtk# does * Perhaps automagically find vfunc implementations, like PyGObject and Ruby-GNOME do * What about properties? How about: class Derived < Base include SomeGObjectInterface register_type 'Derived' install_property ... install_vfunc_implementation ... end This needs issue #63 to be resolved. NOTE: When adding an interface module to a derived class, its prerequisites should be checked. ## Persistent Ruby GObject identity GirFFI should make sure that if it gets a pointer to a GObject for which a Ruby object already exists, the existing object is returned. This involves the use of WeakRef, no doubt. ## Handle fundamental objects that are not GObject. This is a big one. See commit 1e9822c7817062a9b853269b9418fd78782090b5 in gobject-introspection, and TestFundamentalObject in Regress. The tests for TestFundamentalObject accidentally pass, but there may be hidden issues. ## Check binding of GObject: (11:37:03 PM) walters: the basic story is that GObject should be manually bound (11:47:02 PM) ebassi: the really necessary bits are: GObject/GInitiallyUnowned memory management; properties accessors; GSignal connection API (11:47:15 PM) ebassi: the rest is "nice to have" (11:47:37 PM) ebassi: oh, and probably GBinding - but that's just because I wrote it ;-) ## Use FFI::DataConverter to automatically convert GObject types GirFFI now generates loads of Something.wrap(ptr) calls; Perhaps these can be replace by implementing to_native and from_native in ClassBase and including FFI::DataConverter. ## Handle Variants more nicely Currently, GirFFI requires the user to create GVariant objects by hand, and retrieve values from them by hand as well. Ideally, we would have `.from_ruby` and `#to_ruby` methods or somesuch that do this for us. Some classes, like GAction, require a specifice VariantType to be used consistently. Special logic will have to be put in place for that. ## Handle ownership-transfer correctly For how to handle objects, see https://bugzilla.gnome.org/show_bug.cgi?id=657202#c1 ## Miscellaneous * Move GObjectIntrospection to GIRepository, and allow generating its own members. * Do something useful with the versioning info in the GIR ## External dependencies Things that I think GirFFI cannot fix: * gobject-introspection should correctly mark private fields as not readable. * gobject-introspection should ignore functions that are only defined but not implemented, or implement those cases in GIMarshallingTests. ## See Also dnote gir_ffi-0.11.4/README.md0000644000004100000410000001032313170036060014504 0ustar www-datawww-data# GirFFI by Matijs van Zuijlen ## Description Ruby bindings for GNOME using the GObject Introspection Repository. ## Status [![Gem Version](https://badge.fury.io/rb/gir_ffi.svg)](http://badge.fury.io/rb/gir_ffi) [![Dependency Status](https://gemnasium.com/mvz/gir_ffi.svg)](https://gemnasium.com/mvz/gir_ffi) [![Build Status](https://travis-ci.org/mvz/gir_ffi.svg?branch=master)](https://travis-ci.org/mvz/gir_ffi) [![Code Climate](https://codeclimate.com/github/mvz/gir_ffi/badges/gpa.svg)](https://codeclimate.com/github/mvz/gir_ffi) [![Coverage Status](https://coveralls.io/repos/mvz/gir_ffi/badge.svg?branch=master&service=github)](https://coveralls.io/github/mvz/gir_ffi?branch=master) [![Documentation Status](https://inch-ci.org/github/mvz/gir_ffi.svg?branch=master)](https://inch-ci.org/github/mvz/gir_ffi/branch/master) ## Features * Create bindings to any GObject-based library. * Bindings are generated at runtime. * Provides overridden bindings for selected methods. * Install `gir_ffi-gtk` and require `gir_ffi-gtk2` or `gir_ffi-gtk3` to load overrides for Gtk2 or Gtk3. ## Usage require 'gir_ffi' # Set up the namespace you wish to use GirFFI.setup :Gio # Create an object inet_address = Gio::InetAddress.new_from_string "127.0.0.1" # Call some methods on the object inet_address.is_loopback # => true inet_address.is_multicast # => false # Call a function in the namespace Gio.dbus_is_name "foo" # => false See the [documentation](docs/Documentation.md) for more usage information. ## Examples Have a look in the `examples/` directory for some simple examples. More examples can be found in `gir_ffi-gtk` and `gir_ffi-gst`. ## Install gem install gir_ffi ## Requirements GirFFI is tested on CRuby 2.1, 2.2, 2.3 and 2.4, JRuby 9.1, and on Rubinius 3. You will also need gobject-introspection installed with some introspection data. Depending on the GIR data, GirFFI needs the actual libraries to be available under the name ending in plain `.so`. If GirFFI complains that it cannot find the library, try installing development packages for those libraries. GirFFI should work with gobject-introspection 1.32.0 and up. On Debian and Ubuntu, installing `libgirepository1.0-1` and `gir1.2-glib-2.0` should be enough to use GirFFI in your application. To run the tests, you should additionally install `libgirepository1.0-dev`, `libcairo2-dev`, `gobject-introspection`, `gir1.2-gtop-2.0`, `gir1.2-gtk-3.0`, `gir1.2-pango-1.0`, `gir1.2-secret-1` and `gir1.2-gstreamer-1.0`. This should be enough to get `rake test` working. GirFFI has not been tested on Mac OS X or Microsoft Windows. YMMV. ## Overrides Sometimes, the GIR data is incorrect, or not detailed enough, and a reasonable binding cannot be created automatically. For these cases, overrides can be defined. The following gems with overrides already exist: * `gir_ffi-gtk`: overrides for Gtk+ 2 and 3. * `gir_ffi-gnome_keyring`: overrides for GnomeKeyring * `gir_ffi-cairo`: overrides for Cairo * `gir_ffi-pango`: overrides for Pango * `gir_ffi-tracker`: overrides for Tracker * `gir_ffi-gst`: overrides for GStreamer ## Hacking and contributing Please feel free to file bugs or send pull requests! If you just want to help out but don't know where to start, have a look at TODO.md, and check the notes in the code (e.g., using `dnote`). If you want to send pull requests or patches, please try to follow these instructions. If you get stuck, make a pull request anyway and I'll try to help out. * Make sure `rake test` runs without reporting any failures. * Add tests for your feature. Otherwise, I can't see if it works or if I break it later. * Make sure latest master merges cleanly with your branch. Things might have moved around since you forked. * Try not to include changes that are irrelevant to your feature in the same commit. ## Contributors The following people have contributed to GirFFI over the years: * John Cupitt * Marius Hanne * Antonio Terceiro * Matijs van Zuijlen ## License Copyright © 2009–2016 [Matijs van Zuijlen](http://www.matijs.net) GirFFI is free software, distributed under the terms of the GNU Lesser General Public License, version 2.1 or later. See the file COPYING.LIB for more information.