gir_ffi-0.9.0/0000755000004100000410000000000012654060474013165 5ustar www-datawww-datagir_ffi-0.9.0/Rakefile0000644000004100000410000000014612654060474014633 0ustar www-datawww-datarequire 'rake/clean' require 'bundler/gem_tasks' load 'tasks/test.rake' task :default => 'test:all' gir_ffi-0.9.0/Gemfile0000644000004100000410000000047712654060474014470 0ustar www-datawww-datasource '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', type: :development end else gem 'simplecov', '~> 0.11.0', type: :development, platform: :mri gem 'pry', '~> 0.10.0', type: :development end gir_ffi-0.9.0/examples/0000755000004100000410000000000012654060474015003 5ustar www-datawww-datagir_ffi-0.9.0/examples/main_loop.rb0000644000004100000410000000024112654060474017302 0ustar www-datawww-datarequire 'gir_ffi' main_loop = GLib::MainLoop.new nil, false Signal.trap("INT") do if main_loop.is_running main_loop.quit end exit end main_loop.run gir_ffi-0.9.0/Changelog.md0000644000004100000410000003624612654060474015411 0ustar www-datawww-data# Changelog ## 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.9.0/lib/0000755000004100000410000000000012654060474013733 5ustar www-datawww-datagir_ffi-0.9.0/lib/gir_ffi-base/0000755000004100000410000000000012654060474016250 5ustar www-datawww-datagir_ffi-0.9.0/lib/gir_ffi-base/gobject.rb0000644000004100000410000000026212654060474020212 0ustar www-datawww-datarequire 'gir_ffi-base/gobject/lib' # The part of the GObject namespace that is needed by GObjectIntrospection. module GObject def self.type_init Lib.g_type_init end end gir_ffi-0.9.0/lib/gir_ffi-base/gobject/0000755000004100000410000000000012654060474017665 5ustar www-datawww-datagir_ffi-0.9.0/lib/gir_ffi-base/gobject/lib.rb0000644000004100000410000000055512654060474020765 0ustar www-datawww-datarequire 'ffi/bit_masks' # NOTE: Monkey-patch BitMask to work on JRuby. class FFI::BitMasks::BitMask def reference_required? false end end 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_init, [], :void end end gir_ffi-0.9.0/lib/gir_ffi-base/glib/0000755000004100000410000000000012654060474017165 5ustar www-datawww-datagir_ffi-0.9.0/lib/gir_ffi-base/glib/boolean.rb0000644000004100000410000000107712654060474021136 0ustar www-datawww-datarequire 'ffi' module GLib # Implementation of gboolean class Boolean extend FFI::DataConverter native_type FFI::Type::INT def self.from_native(value, _context) value != 0 ? true : false end def self.to_native(value, _context) value ? 1 : 0 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.9.0/lib/gir_ffi-base/glib/strv.rb0000644000004100000410000000131012654060474020503 0ustar www-datawww-datarequire 'ffi' module GLib # 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 return if @ptr.null? reset_iterator while (ptr = next_ptr) yield ptr.read_string end end def self.wrap(ptr) new ptr end private def reset_iterator @offset = 0 end def next_ptr ptr = @ptr.get_pointer @offset @offset += POINTER_SIZE ptr unless ptr.null? end end end gir_ffi-0.9.0/lib/gir_ffi.rb0000644000004100000410000000010112654060474015655 0ustar www-datawww-datarequire 'gir_ffi/core' require 'ffi-glib' require 'ffi-gobject' gir_ffi-0.9.0/lib/ffi-gobject_introspection/0000755000004100000410000000000012654060474021072 5ustar www-datawww-datagir_ffi-0.9.0/lib/ffi-gobject_introspection/i_repository.rb0000644000004100000410000001021112654060474024141 0ustar www-datawww-datarequire 'singleton' require 'ffi-gobject_introspection/lib' require 'ffi-gobject_introspection/g_error' 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 # The Gobject Introspection Repository. This class is the point of # access to the introspection typelibs. # This class wraps the GIRepository struct. class IRepository # Map info type to class. Default is IBaseInfo. # SMELL: This doesn't really belong here, since it is used by IBaseInfo and # descendants as well. 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 } 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 == 0 wrap_info Lib.g_irepository_find_by_gtype(@gobj, gtype) end def dependencies(namespace) strv_p = Lib.g_irepository_get_dependencies(@gobj, namespace) strv = GLib::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.9.0/lib/ffi-gobject_introspection/i_unresolved_info.rb0000644000004100000410000000031112654060474025123 0ustar www-datawww-datarequire '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.9.0/lib/ffi-gobject_introspection/i_object_info.rb0000644000004100000410000000456212654060474024217 0ustar www-datawww-datamodule 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 ## build_array_method :properties, :property build_finder_method :find_property, :n_properties 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.9.0/lib/ffi-gobject_introspection/i_field_info.rb0000644000004100000410000000101312654060474024020 0ustar www-datawww-datamodule 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 & 1 != 0 end def writable? flags & 2 != 0 end end end gir_ffi-0.9.0/lib/ffi-gobject_introspection/i_vfunc_info.rb0000644000004100000410000000073712654060474024072 0ustar www-datawww-datamodule GObjectIntrospection # Wraps a GIVFuncInfo struct. # Represents a virtual function. class IVFuncInfo < ICallableInfo def flags Lib.g_vfunc_info_get_flags @gobj end def throws? flags & 8 != 0 end def offset Lib.g_vfunc_info_get_offset @gobj end def signal ISignalInfo.wrap(Lib.g_vfunc_info_get_signal @gobj) end def invoker IFunctionInfo.wrap(Lib.g_vfunc_info_get_invoker @gobj) end end end gir_ffi-0.9.0/lib/ffi-gobject_introspection/lib.rb0000644000004100000410000002766112654060474022201 0ustar www-datawww-datarequire 'ffi' module GObjectIntrospection # Module for attaching functions from the girepository library module Lib extend FFI::Library ffi_lib 'girepository-1.0' # Helper class to support guessing the gobject-introspection version. # Provide several guesses to #provide_guess, and the result in #best_guess # will be the best (i.e., lowest) guess. class VersionGuesser def initialize(base) @guess = base end def provide_guess(guessed) @guess = guessed if guessed < @guess end def best_guess @guess end end version_guesser = VersionGuesser.new('1.42') # 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 attach_function :g_function_info_get_symbol, [:pointer], :string # TODO: return type is bitfield attach_function :g_function_info_get_flags, [:pointer], :int # 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_get_n_args, [:pointer], :int attach_function :g_callable_info_get_arg, [:pointer, :int], :pointer attach_function :g_callable_info_skip_return, [:pointer], :bool begin attach_function :g_callable_info_get_instance_ownership_transfer, [:pointer], :ITransfer rescue FFI::NotFoundError version_guesser.provide_guess '1.40' end # 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 enum :IFieldInfoFlags, [ :readable, (1 << 0), :writable, (1 << 1) ] # TODO: return type is bitfield :IFieldInfoFlags attach_function :g_field_info_get_flags, [:pointer], :int 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 attach_function :g_vfunc_info_get_flags, [:pointer], :int attach_function :g_vfunc_info_get_offset, [:pointer], :int attach_function :g_vfunc_info_get_signal, [:pointer], :pointer 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 # TODO: return type is bitfield attach_function :g_property_info_get_flags, [:pointer], :int ::GObjectIntrospection::VERSION = version_guesser.best_guess end end gir_ffi-0.9.0/lib/ffi-gobject_introspection/i_property_info.rb0000644000004100000410000000101512654060474024623 0ustar www-datawww-datamodule 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 & 1 != 0 end def writeable? flags & 2 != 0 end def construct? flags & 4 != 0 end def construct_only? flags & 8 != 0 end end end gir_ffi-0.9.0/lib/ffi-gobject_introspection/i_signal_info.rb0000644000004100000410000000023512654060474024217 0ustar www-datawww-datamodule GObjectIntrospection # Wraps a GISignalInfo struct. # Represents a signal. # Not implemented yet. class ISignalInfo < ICallableInfo end end gir_ffi-0.9.0/lib/ffi-gobject_introspection/i_interface_info.rb0000644000004100000410000000356112654060474024707 0ustar www-datawww-datamodule 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.9.0/lib/ffi-gobject_introspection/i_type_info.rb0000644000004100000410000000156012654060474023725 0ustar www-datawww-datamodule 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.9.0/lib/ffi-gobject_introspection/i_struct_info.rb0000644000004100000410000000166712654060474024300 0ustar www-datawww-datamodule 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.9.0/lib/ffi-gobject_introspection/i_value_info.rb0000644000004100000410000000033112654060474024053 0ustar www-datawww-datamodule 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.9.0/lib/ffi-gobject_introspection/i_callable_info.rb0000644000004100000410000000177712654060474024515 0ustar www-datawww-datarequire '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 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 if VERSION >= '1.42' Lib.g_callable_info_get_instance_ownership_transfer @gobj else :nothing end end end end gir_ffi-0.9.0/lib/ffi-gobject_introspection/i_flags_info.rb0000644000004100000410000000020212654060474024030 0ustar www-datawww-datamodule GObjectIntrospection # Wraps a GIEnumInfo struct, if it represents a flag type. class IFlagsInfo < IEnumInfo end end gir_ffi-0.9.0/lib/ffi-gobject_introspection/i_enum_info.rb0000644000004100000410000000136412654060474023712 0ustar www-datawww-datamodule 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.9.0/lib/ffi-gobject_introspection/i_function_info.rb0000644000004100000410000000113512654060474024567 0ustar www-datawww-datamodule 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 # TODO: Use some sort of bitfield def method? flags & 1 != 0 end def constructor? flags & 2 != 0 end def getter? flags & 4 != 0 end def setter? flags & 8 != 0 end def wraps_vfunc? flags & 16 != 0 end def throws? flags & 32 != 0 end end end gir_ffi-0.9.0/lib/ffi-gobject_introspection/i_callback_info.rb0000644000004100000410000000027012654060474024475 0ustar www-datawww-datamodule GObjectIntrospection # Wraps a GICallbackInfo struct. Has no methods in addition to the ones # inherited from ICallableInfo. class ICallbackInfo < ICallableInfo end end gir_ffi-0.9.0/lib/ffi-gobject_introspection/i_registered_type_info.rb0000644000004100000410000000064412654060474026144 0ustar www-datawww-datamodule 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.9.0/lib/ffi-gobject_introspection/i_base_info.rb0000644000004100000410000000624512654060474023663 0ustar www-datawww-datamodule 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.9.0/lib/ffi-gobject_introspection/i_arg_info.rb0000644000004100000410000000166212654060474023520 0ustar www-datawww-datarequire '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.9.0/lib/ffi-gobject_introspection/g_error.rb0000644000004100000410000000055612654060474023064 0ustar www-datawww-datamodule 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.9.0/lib/ffi-gobject_introspection/i_constant_info.rb0000644000004100000410000000202312654060474024570 0ustar www-datawww-datamodule 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 } def value case type_tag when :utf8 raw_value.force_encoding('utf-8') when :gboolean raw_value != 0 else raw_value end end def constant_type ITypeInfo.wrap(Lib.g_constant_info_get_type @gobj) 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 @gobj, 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.9.0/lib/ffi-gobject_introspection/i_union_info.rb0000644000004100000410000000142712654060474024076 0ustar www-datawww-datamodule 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.9.0/lib/ffi-gobject.rb0000644000004100000410000000745112654060474016446 0ustar www-datawww-datarequire 'gir_ffi/core' GirFFI.setup :GObject require 'ffi-gobject/base' 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/ruby_closure' require 'gir_ffi/builders/user_defined_builder' # 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 GirFFI::InOutPointer.new(:GType, klsptr).to_value end def self.type_from_instance(instance) type_from_instance_pointer instance.to_ptr 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 # Smells of :reek:LongParameterList: due to the C interface. # rubocop:disable Metrics/ParameterLists def self.param_spec_int(name, nick, blurb, minimum, maximum, default_value, flags) ptr = Lib.g_param_spec_int(name, nick, blurb, minimum, maximum, default_value, flags) ParamSpecInt.wrap(ptr) 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_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_set_marshal, [:pointer, ClosureMarshal], :void attach_function :g_param_spec_int, [:string, :string, :string, :int32, :int32, :int32, ParamFlags], :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.9.0/lib/ffi-gobject_introspection.rb0000644000004100000410000000013412654060474021415 0ustar www-datawww-datarequire 'gir_ffi-base' GObject.type_init require 'ffi-gobject_introspection/i_repository' gir_ffi-0.9.0/lib/ffi-glib.rb0000644000004100000410000000350612654060474015743 0ustar www-datawww-datarequire 'gir_ffi/core' GirFFI.setup :GLib 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.9.0/lib/ffi-gobject/0000755000004100000410000000000012654060474016112 5ustar www-datawww-datagir_ffi-0.9.0/lib/ffi-gobject/ruby_closure.rb0000644000004100000410000000265012654060474021157 0ustar www-datawww-datarequire '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 < FFI::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.9.0/lib/ffi-gobject/value.rb0000644000004100000410000001157512654060474017564 0ustar www-datawww-dataGObject.load_class :Value module GObject # Overrides for GValue, GObject's generic value container structure. class Value setup_instance_method 'init' def init_with_finalizer(type) return self if [TYPE_NONE, TYPE_INVALID].include? type init_without_finalizer(type) ObjectSpace.define_finalizer self, self.class.make_finalizer(to_ptr) self end alias_method :init_without_finalizer, :init alias_method :init, :init_with_finalizer def self.make_finalizer(ptr) proc do GObject::Lib.g_value_unset ptr 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] } 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 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 } 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 uninitialized? current_gtype == TYPE_INVALID 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.9.0/lib/ffi-gobject/object.rb0000644000004100000410000000766012654060474017716 0ustar www-datawww-dataGObject.load_class :Object module GObject # Overrides for GObject, GObject's generic base class. class Object setup_method 'new' def initialize_with_automatic_gtype(properties = {}) gparameters = properties.map do |name, value| name = name.to_s unless property_param_spec(name) raise ArgumentError, "Property '#{name}' not found in class #{self.class}" end GObject::Parameter.new.tap do |gparam| gparam.name = name gparam.value = value end end initialize_without_automatic_gtype(self.class.gtype, gparameters) end alias_method :initialize_without_automatic_gtype, :initialize alias_method :initialize, :initialize_with_automatic_gtype alias_method :base_initialize, :initialize private :base_initialize def store_pointer(ptr) super klass = self.class ObjectSpace.define_finalizer self, klass.make_finalizer(ptr, klass.name) end def self.make_finalizer(ptr, name) proc do rc = GObject::Object::Struct.new(ptr)[:ref_count] if rc == 0 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 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 case type_info.tag when :ghash, :glist adjust_value_to_type value, type_info else value end 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 = adjust_value_to_type(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) property_param_spec(property_name).value_type end def property_param_spec(property_name) object_class.find_property property_name end # TODO: Move to ITypeInfo def adjust_value_to_type(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 else val end end end end gir_ffi-0.9.0/lib/ffi-gobject/closure.rb0000644000004100000410000000073512654060474020120 0ustar www-datawww-dataGObject.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 # @override # # @param [Proc] marshal The marshaller to use for this closure object def set_marshal(marshal) callback = GObject::ClosureMarshal.from marshal Lib.g_closure_set_marshal self, callback end end end gir_ffi-0.9.0/lib/ffi-gobject/initially_unowned.rb0000644000004100000410000000066212654060474022200 0ustar www-datawww-dataGObject.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.9.0/lib/ffi-gobject/base.rb0000644000004100000410000000172512654060474017356 0ustar www-datawww-data# Preload type contants module GObject 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.9.0/lib/ffi-gobject/object_class.rb0000644000004100000410000000071712654060474021077 0ustar www-datawww-dataGObject.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 GirFFI::InOutPointer.new(:GType, to_ptr).to_value end end end gir_ffi-0.9.0/lib/gir_ffi/0000755000004100000410000000000012654060474015340 5ustar www-datawww-datagir_ffi-0.9.0/lib/gir_ffi/ffi_ext.rb0000644000004100000410000000004212654060474017305 0ustar www-datawww-datarequire 'gir_ffi/ffi_ext/pointer' gir_ffi-0.9.0/lib/gir_ffi/module_base.rb0000644000004100000410000000110212654060474020136 0ustar www-datawww-datamodule 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 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.9.0/lib/gir_ffi/sized_array.rb0000644000004100000410000000411212654060474020177 0ustar www-datawww-datamodule 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 = GirFFI::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 == 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), 0, size) end private def element_ffi_type @element_ffi_type ||= GirFFI::TypeMap.type_specification_to_ffi_type element_type end def element_size @element_size ||= FFI.type_size element_ffi_type end def self.wrap(element_type, size, pointer) new element_type, size, pointer unless pointer.null? 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 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 = GirFFI::InPointer.from_array element_type, arr wrap element_type, size, ptr end def check_size(expected_size, size) if expected_size > 0 && size != expected_size raise ArgumentError, "Expected size #{expected_size}, got #{size}" end end end end end gir_ffi-0.9.0/lib/gir_ffi/flags_base.rb0000644000004100000410000000224512654060474017756 0ustar www-datawww-datarequire 'gir_ffi/registered_type_base' module GirFFI # Base module for flags. module FlagsBase include FFI::DataConverter include RegisteredTypeBase 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 def wrap(arg) self[arg] end def from(arg) self[arg] 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.9.0/lib/gir_ffi/interface_base.rb0000644000004100000410000000055112654060474020620 0ustar www-datawww-datarequire 'gir_ffi/registered_type_base' module GirFFI # Base module for modules representing GLib interfaces. module InterfaceBase include RegisteredTypeBase def setup_instance_method(name) gir_ffi_builder.setup_instance_method name end def wrap(ptr) ptr.to_object end def to_ffi_type :pointer end end end gir_ffi-0.9.0/lib/gir_ffi/unintrospectable_boxed_info.rb0000644000004100000410000000112212654060474023436 0ustar www-datawww-datarequire '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' def namespace DEFAULT_BOXED_NAMESPACE end def fields [] end end end gir_ffi-0.9.0/lib/gir_ffi/g_type.rb0000644000004100000410000000067412654060474017163 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/class_base.rb0000644000004100000410000000563712654060474017777 0ustar www-datawww-datarequire '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 initialize raise NoMethodError 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.9.0/lib/gir_ffi/callback_base.rb0000644000004100000410000000374012654060474020417 0ustar www-datawww-datarequire '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 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(key) CALLBACKS.delete key 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 => 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 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.9.0/lib/gir_ffi/type_base.rb0000644000004100000410000000030312654060474017634 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/vfunc_implementation.rb0000644000004100000410000000041412654060474022112 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/receiver_argument_info.rb0000644000004100000410000000074612654060474022415 0ustar www-datawww-datamodule 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 def ownership_transfer # FIXME: Make an informed choice for this. :everything end def name '_instance' end end end gir_ffi-0.9.0/lib/gir_ffi/error_argument_info.rb0000644000004100000410000000071212654060474021733 0ustar www-datawww-datarequire 'gir_ffi/error_type_info' module GirFFI # Represents an error argument with the same interface as IArgumentInfo class ErrorArgumentInfo def skip? false end def direction :error end def argument_type @argument_type ||= ErrorTypeInfo.new end def name '_error' end def closure -1 end def destroy -1 end def caller_allocates? true end end end gir_ffi-0.9.0/lib/gir_ffi/receiver_type_info.rb0000644000004100000410000000072412654060474021550 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/builder_helper.rb0000644000004100000410000000102212654060474020645 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/object_base.rb0000644000004100000410000000275512654060474020136 0ustar www-datawww-datarequire '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 # # 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 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 end def self.object_class @object_class ||= begin ptr = GObject.type_class_ref(gtype).to_ptr gir_ffi_builder.object_class_struct.wrap ptr end end end end gir_ffi-0.9.0/lib/gir_ffi/lib_c.rb0000644000004100000410000000035212654060474016735 0ustar www-datawww-datarequire '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.9.0/lib/gir_ffi/in_out_pointer.rb0000644000004100000410000000342412654060474020725 0ustar www-datawww-datamodule GirFFI # The InOutPointer class handles conversion between ruby types and # pointers for arguments with direction :inout and :out. # # TODO: This has now become a more general extended pointer class and should be renamed. class InOutPointer < FFI::Pointer attr_reader :value_type def initialize(type, ptr = nil) @value_type = type ptr ||= AllocationHelper.safe_malloc(value_type_size) super ptr end # TODO: Create type classes that extract values from pointers. 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 set_value(value) case value_ffi_type when Module value_ffi_type.copy_value_to_pointer(value, self) when Symbol send "put_#{value_ffi_type}", 0, value else raise NotImplementedError, value_ffi_type end end def clear put_bytes 0, "\x00" * value_type_size, 0, value_type_size end def self.for(type) new(type).tap(&:clear) end def self.from(type, value) new(type).tap { |ptr| ptr.set_value value } end private def value_ffi_type @value_ffi_type ||= TypeMap.type_specification_to_ffi_type value_type end def value_type_size @value_type_size ||= FFI.type_size value_ffi_type end end end gir_ffi-0.9.0/lib/gir_ffi/method_stubber.rb0000644000004100000410000000065312654060474020677 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/boxed_base.rb0000644000004100000410000000150712654060474017763 0ustar www-datawww-datarequire 'gir_ffi/class_base' module GirFFI # Base class for generated classes representing boxed types. class BoxedBase < ClassBase extend FFI::DataConverter def self.native_type FFI::Type::Struct.new(self::Struct) end def self.to_ffi_type self end # NOTE: Needed for JRuby's FFI def self.to_native(value, _context) value.struct end def self.get_value_from_pointer(pointer, offset) pointer + offset end def self.copy_value_to_pointer(value, pointer, offset = 0) size = self::Struct.size bytes = if value value.to_ptr.read_bytes(size) else "\x00" * size end pointer.put_bytes offset, bytes, 0, size end def initialize @struct = self.class::Struct.new end end end gir_ffi-0.9.0/lib/gir_ffi/user_data_argument_info.rb0000644000004100000410000000062412654060474022553 0ustar www-datawww-datamodule GirFFI # Class to represent the info for the user data argument of a signal handler. # Implements the necessary parts of IArgumentInfo's interface. class UserDataArgumentInfo attr_reader :argument_type def initialize(type) @argument_type = type end def direction :in end def skip? false end def name '_user_data' end end end gir_ffi-0.9.0/lib/gir_ffi/glib_error.rb0000644000004100000410000000062312654060474020014 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/union_base.rb0000644000004100000410000000022312654060474020004 0ustar www-datawww-datarequire 'gir_ffi/boxed_base' module GirFFI # Base class for generated classes representing GLib unions. class UnionBase < BoxedBase end end gir_ffi-0.9.0/lib/gir_ffi/variable_name_generator.rb0000644000004100000410000000040012654060474022512 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/info_ext.rb0000644000004100000410000000112712654060474017501 0ustar www-datawww-datarequire '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.9.0/lib/gir_ffi/version.rb0000644000004100000410000000007712654060474017356 0ustar www-datawww-data# Current GirFFI version module GirFFI VERSION = '0.9.0' end gir_ffi-0.9.0/lib/gir_ffi/user_defined_type_info.rb0000644000004100000410000000251612654060474022401 0ustar www-datawww-datarequire '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. # TODO: Rename to UserDefinedObjectInfo class UserDefinedTypeInfo 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) @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 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.9.0/lib/gir_ffi/unintrospectable_type_info.rb0000644000004100000410000000217312654060474023325 0ustar www-datawww-datarequire '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.9.0/lib/gir_ffi/object_store.rb0000644000004100000410000000074412654060474020354 0ustar www-datawww-datamodule GirFFI # Helper class for storing objects for later retrieval. Used to store user # data arguments. class ObjectStore def initialize @store = {} end def store(obj) # 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.9.0/lib/gir_ffi/error_type_info.rb0000644000004100000410000000060412654060474021072 0ustar www-datawww-datarequire '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.9.0/lib/gir_ffi/core.rb0000644000004100000410000000155712654060474016625 0ustar www-datawww-datarequire 'ffi' require 'ffi/bit_masks' require 'gir_ffi-base' require 'ffi-gobject_introspection' 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/user_defined_type_info' require 'gir_ffi/builder' require 'gir_ffi/version' # Main module containing classes and modules needed for generating GLib and # GObject bindings. module GirFFI def self.setup(module_name, version = nil) module_name = module_name.to_s GirFFI::Builder.build_module module_name, version end def self.define_type(klass, &block) info = UserDefinedTypeInfo.new(klass, &block) Builders::UserDefinedBuilder.new(info).build_class klass.gtype end end gir_ffi-0.9.0/lib/gir_ffi/info_ext/0000755000004100000410000000000012654060474017153 5ustar www-datawww-datagir_ffi-0.9.0/lib/gir_ffi/info_ext/i_unresolved_info.rb0000644000004100000410000000044012654060474023207 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/info_ext/i_field_info.rb0000644000004100000410000000070012654060474022103 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/info_ext/i_vfunc_info.rb0000644000004100000410000000101312654060474022137 0ustar www-datawww-datamodule 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 end end end GObjectIntrospection::IVFuncInfo.send :include, GirFFI::InfoExt::IVFuncInfo gir_ffi-0.9.0/lib/gir_ffi/info_ext/i_property_info.rb0000644000004100000410000000053412654060474022711 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/info_ext/safe_constant_name.rb0000644000004100000410000000142012654060474023324 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/info_ext/i_signal_info.rb0000644000004100000410000000213612654060474022302 0ustar www-datawww-datamodule 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.map { |info| info.argument_type.make_g_value } arg_g_values.zip(arguments).each do |g_value, arg| g_value.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.9.0/lib/gir_ffi/info_ext/safe_function_name.rb0000644000004100000410000000052712654060474023327 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/info_ext/i_type_info.rb0000644000004100000410000001370012654060474022005 0ustar www-datawww-datarequire '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: GObject::TYPE_ARRAY, c: GObject::TYPE_POINTER, gboolean: GObject::TYPE_BOOLEAN, ghash: GObject::TYPE_HASH_TABLE, gint32: GObject::TYPE_INT, gint64: GObject::TYPE_INT64, guint64: GObject::TYPE_UINT64, strv: GObject::TYPE_STRV, utf8: GObject::TYPE_STRING, void: GObject::TYPE_NONE } end def gtype if tag == :interface return interface.gtype elsif (type = ITypeInfo.flattened_tag_to_gtype_map[flattened_tag]) return type else raise "Can't find GType for #{flattened_tag} pointer? = #{pointer?}" end 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 tag_or_class base = case tag when:interface Builder.build_class interface when :ghash [tag, *element_type] else flattened_tag end if pointer? && tag != :utf8 && tag != :filename [:pointer, base] else base end 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', void: 'GirFFI::InPointer', zero_terminated: 'GirFFI::ZeroTerminated' } # TODO: Use class rather than class name def argument_class_name if tag == :interface interface.full_type_name else TAG_TO_WRAPPER_CLASS_MAP[flattened_tag] end 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, :void, :zero_terminated ] 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 ] 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, :struct, :strv].include?(flattened_tag) end def needs_ruby_to_c_conversion_for_closures? [:array].include?(flattened_tag) end def extra_conversion_arguments case flattened_tag when :utf8, :void [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' 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.9.0/lib/gir_ffi/info_ext/i_callable_info.rb0000644000004100000410000000045612654060474022567 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/info_ext/full_type_name.rb0000644000004100000410000000110312654060474022476 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/info_ext/i_function_info.rb0000644000004100000410000000071712654060474022655 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/info_ext/i_callback_info.rb0000644000004100000410000000071012654060474022555 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/info_ext/i_registered_type_info.rb0000644000004100000410000000124312654060474024221 0ustar www-datawww-datarequire '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.9.0/lib/gir_ffi/info_ext/i_arg_info.rb0000644000004100000410000000070212654060474021573 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/user_data_type_info.rb0000644000004100000410000000060712654060474021713 0ustar www-datawww-datarequire 'gir_ffi/info_ext/i_type_info' module GirFFI # Represents the type of the user data (closure argument) of a signal or vfunc, # conforming, as needed, to the interface of GObjectIntrospection::ITypeInfo. class UserDataTypeInfo include InfoExt::ITypeInfo def tag :void end def pointer? true end def array_length -1 end end end gir_ffi-0.9.0/lib/gir_ffi/zero_terminated.rb0000644000004100000410000000262212654060474021062 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/return_value_info.rb0000644000004100000410000000070012654060474021410 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/builders/0000755000004100000410000000000012654060474017151 5ustar www-datawww-datagir_ffi-0.9.0/lib/gir_ffi/builders/mapping_method_builder.rb0000644000004100000410000000503412654060474024201 0ustar www-datawww-datarequire '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/method_template' 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. # # TODO: Inherit from BaseMethodBuilder class MappingMethodBuilder def self.for_callback(argument_infos, return_value_info) new nil, argument_infos, return_value_info, CallbackArgumentBuilder end def self.for_vfunc(receiver_info, argument_infos, return_value_info) new receiver_info, argument_infos, return_value_info, VFuncArgumentBuilder end def initialize(receiver_info, argument_infos, return_value_info, builder_class) @argument_builder_class = builder_class receiver_builder = make_argument_builder receiver_info if receiver_info argument_builders = argument_infos.map { |info| make_argument_builder info } return_value_builder = CallbackReturnValueBuilder.new(variable_generator, return_value_info) @argument_builder_collection = ArgumentBuilderCollection.new(return_value_builder, argument_builders, receiver_builder: receiver_builder) @template = MethodTemplate.new(self, @argument_builder_collection) end def method_definition @template.method_definition end def method_name 'call_with_argument_mapping' end def method_arguments @method_arguments ||= @argument_builder_collection.method_argument_names.dup.unshift('_proc') end def preparation [] 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 def variable_generator @variable_generator ||= VariableNameGenerator.new end def make_argument_builder(argument_info) @argument_builder_class.new variable_generator, argument_info end end end end gir_ffi-0.9.0/lib/gir_ffi/builders/error_argument_builder.rb0000644000004100000410000000144212654060474024240 0ustar www-datawww-datarequire 'gir_ffi/builders/base_argument_builder' module GirFFI module Builders # Implements argument processing for error handling arguments. These # arguments are not part of the introspected signature, but their # presence is indicated by the 'throws' attribute of the function. class ErrorArgumentBuilder < BaseArgumentBuilder def method_argument_name nil end def block_argument? false end def return_value_name nil end def capture_variable_name nil end def pre_conversion ["#{call_argument_name} = FFI::MemoryPointer.new(:pointer).write_pointer nil"] end def post_conversion ["GirFFI::ArgHelper.check_error(#{call_argument_name})"] end end end end gir_ffi-0.9.0/lib/gir_ffi/builders/property_builder.rb0000644000004100000410000000632612654060474023077 0ustar www-datawww-datamodule GirFFI module Builders # 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 # TODO: Fix argument builders so converting_getter_def can always be used. def getter_def case type_info.tag when :glist, :ghash converting_getter_def else simple_getter_def end end # TODO: Fix argument builders so converting_setter_def can always be used. def setter_def case type_info.flattened_tag when :glist, :ghash, :strv converting_setter_def else simple_setter_def end end private # TODO: Use a builder like MarshallingMethodBuilder def converting_getter_def capture = getter_builder.capture_variable_name <<-CODE.reset_indentation def #{getter_name} #{capture} = get_property("#{property_name}") #{getter_builder.post_conversion.join("\n")} #{getter_builder.return_value_name} end CODE end def simple_getter_def <<-CODE.reset_indentation def #{getter_name} get_property("#{property_name}") end CODE end def getter_builder @getter_builder ||= ReturnValueBuilder.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 simple_setter_def <<-CODE.reset_indentation def #{setter_name} value set_property("#{property_name}", value) end CODE end def setter_builder @setter_builder ||= ArgumentBuilder.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.9.0/lib/gir_ffi/builders/full_c_to_ruby_convertor.rb0000644000004100000410000000065512654060474024614 0ustar www-datawww-datarequire '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 base = super if @type_info.gvalue? "#{base}.get_value" else base end end end end end gir_ffi-0.9.0/lib/gir_ffi/builders/null_argument_builder.rb0000644000004100000410000000120012654060474024051 0ustar www-datawww-datamodule 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 closure_idx -1 end def destroy_idx -1 end def block_argument? false end def post_converted_name nil end end end gir_ffi-0.9.0/lib/gir_ffi/builders/unintrospectable_builder.rb0000644000004100000410000000116712654060474024572 0ustar www-datawww-datarequire 'gir_ffi/builders/object_builder' 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 end end end gir_ffi-0.9.0/lib/gir_ffi/builders/callback_return_value_builder.rb0000644000004100000410000000357212654060474025542 0ustar www-datawww-datarequire 'gir_ffi/builders/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 < 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 post_conversion if has_post_conversion? if type_info.flattened_tag == :object ["#{post_converted_name} = #{post_convertor.conversion}.to_ptr"] else ["#{post_converted_name} = #{post_convertor.conversion}"] end else [] end end 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 private def post_convertor @post_convertor ||= RubyToCConvertor.new(type_info, post_convertor_argument) end def post_convertor_argument if ownership_transfer == :everything && specialized_type_tag == :object "#{capture_variable_name}.ref" else capture_variable_name end 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.9.0/lib/gir_ffi/builders/base_method_builder.rb0000644000004100000410000000370512654060474023463 0ustar www-datawww-datarequire 'gir_ffi/builders/argument_builder' require 'gir_ffi/builders/argument_builder_collection' require 'gir_ffi/builders/error_argument_builder' 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 vargen @vargen ||= 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| ArgumentBuilder.new vargen, arg } end def return_value_info @return_value_info ||= ReturnValueInfo.new(@info.return_type, @info.caller_owns, @info.skip_return?) end def argument_builder_collection @argument_builder_collection ||= ArgumentBuilderCollection.new( @return_value_builder, argument_builders, error_argument_builder: error_argument) end def error_argument @error_argument ||= if @info.throws? ErrorArgumentBuilder.new vargen, 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 end end end gir_ffi-0.9.0/lib/gir_ffi/builders/null_class_builder.rb0000644000004100000410000000033512654060474023344 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/builders/ruby_to_c_convertor.rb0000644000004100000410000000110112654060474023555 0ustar www-datawww-datamodule 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) @type_info = type_info @argument_name = argument_name end def conversion args = conversion_arguments @argument_name "#{@type_info.argument_class_name}.from(#{args})" end def conversion_arguments(name) @type_info.extra_conversion_arguments.map(&:inspect).push(name).join(', ') end end end end gir_ffi-0.9.0/lib/gir_ffi/builders/argument_builder.rb0000644000004100000410000001227712654060474023037 0ustar www-datawww-datarequire '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/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 # TODO: Improve this so each method can only have one block argument. def block_argument? specialized_type_tag == :callback 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 = [] case direction when :in pr << fixed_array_size_check if needs_size_check? pr << array_length_assignment if array_length_parameter? pr << "#{call_argument_name} = #{ingoing_convertor.conversion}" when :inout pr << fixed_array_size_check if needs_size_check? pr << array_length_assignment if array_length_parameter? pr << out_parameter_preparation pr << "#{call_argument_name}.set_value #{ingoing_convertor.conversion}" when :out pr << out_parameter_preparation end pr end def post_conversion if has_post_conversion? value = output_value ["#{post_converted_name} = #{value}"] else [] end end private 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 = "#{call_argument_name}.to_value" if needs_out_conversion? FullCToRubyConvertor.new(@type_info, base, length_argument_name).conversion elsif allocated_by_them? "GirFFI::InOutPointer.new(#{type_info.tag_or_class[1].inspect}, #{base}).to_value" else base end 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? @arginfo.skip? || @array_arg && @array_arg.specialized_type_tag == :strv end def has_output_value? (direction == :inout || direction == :out) && !skipped? end def has_input_value? (direction == :inout || direction == :in) && !skipped? 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 "GirFFI::InOutPointer.for #{type_info.tag_or_class.inspect}" end "#{call_argument_name} = #{value}" end def caller_allocated_object? [:struct, :array].include?(specialized_type_tag) && @arginfo.caller_allocates? end DESTROY_NOTIFIER = 'GLib::DestroyNotify.default' def ingoing_convertor if skipped? 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) else NullConvertor.new(pre_convertor_argument) end end def pre_convertor_argument if ownership_transfer == :everything && specialized_type_tag == :object "#{name}.ref" else name end end end end end gir_ffi-0.9.0/lib/gir_ffi/builders/vfunc_builder.rb0000644000004100000410000000357312654060474022335 0ustar www-datawww-datarequire '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 arg_infos = info.args arg_infos << ErrorArgumentInfo.new if info.throws? receiver_info = ReceiverArgumentInfo.new receiver_type_info return_value_info = ReturnValueInfo.new(info.return_type, info.caller_owns, info.skip_return?) MappingMethodBuilder.for_vfunc(receiver_info, arg_infos, return_value_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.9.0/lib/gir_ffi/builders/interface_builder.rb0000644000004100000410000000132712654060474023147 0ustar www-datawww-datarequire '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.9.0/lib/gir_ffi/builders/signal_closure_builder.rb0000644000004100000410000000257112654060474024222 0ustar www-datawww-datarequire '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 arg_infos = info.args container_type_info = ReceiverTypeInfo.new(container_info) receiver_info = ReceiverArgumentInfo.new(container_type_info) return_value_info = ReturnValueInfo.new(info.return_type, info.caller_owns, info.skip_return?) MarshallingMethodBuilder.for_signal(receiver_info, arg_infos, return_value_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.9.0/lib/gir_ffi/builders/base_argument_builder.rb0000644000004100000410000000514012654060474024020 0ustar www-datawww-datamodule 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 ) 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 # SMELL: Law of Demeter, due to this being arginfo.argument_type.flattened_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.9.0/lib/gir_ffi/builders/vfunc_argument_builder.rb0000644000004100000410000000174612654060474024237 0ustar www-datawww-datarequire '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_ref_count_increase] else super end end private def ingoing_ref_needed direction == :in && ownership_transfer == :nothing && specialized_type_tag == :object end def pre_ref_count_increase "#{pre_converted_name}.ref" end # SMELL: Override private method def post_convertor_argument if outgoing_ref_needed "#{super}.ref" else super end end def outgoing_ref_needed direction == :out && ownership_transfer == :everything && specialized_type_tag == :object end end end end gir_ffi-0.9.0/lib/gir_ffi/builders/initializer_return_value_builder.rb0000644000004100000410000000062012654060474026320 0ustar www-datawww-datarequire 'gir_ffi/builders/base_argument_builder' module GirFFI module Builders # Implements post-conversion for initializer functions class InitializerReturnValueBuilder < BaseArgumentBuilder def capture_variable_name @capture_variable_name ||= new_variable end def post_conversion ["store_pointer(#{capture_variable_name})"] end end end end gir_ffi-0.9.0/lib/gir_ffi/builders/flags_builder.rb0000644000004100000410000000131612654060474022301 0ustar www-datawww-datarequire '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.9.0/lib/gir_ffi/builders/marshalling_method_builder.rb0000644000004100000410000000501012654060474025041 0ustar www-datawww-datarequire '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. # # TODO: Inherit from BaseMethodBuilder class MarshallingMethodBuilder def self.for_signal(receiver_info, argument_infos, return_value_info) new receiver_info, argument_infos, return_value_info end def initialize(receiver_info, argument_infos, return_value_info) receiver_builder = make_argument_builder receiver_info argument_builders = argument_infos.map { |arg| make_argument_builder arg } return_value_builder = ClosureReturnValueBuilder.new(variable_generator, return_value_info) @argument_builder_collection = ArgumentBuilderCollection.new(return_value_builder, argument_builders, receiver_builder: receiver_builder) @template = MethodTemplate.new(self, @argument_builder_collection) end def method_definition @template.method_definition end 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 def variable_generator @variable_generator ||= VariableNameGenerator.new end def make_argument_builder(argument_info) ClosureArgumentBuilder.new variable_generator, argument_info end end end end gir_ffi-0.9.0/lib/gir_ffi/builders/closure_return_value_builder.rb0000644000004100000410000000056212654060474025456 0ustar www-datawww-datarequire '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.9.0/lib/gir_ffi/builders/with_layout.rb0000644000004100000410000000231212654060474022044 0ustar www-datawww-datarequire '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 setup_field_accessors fields.each do |finfo| FieldBuilder.new(finfo).build end 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.9.0/lib/gir_ffi/builders/closure_to_pointer_convertor.rb0000644000004100000410000000075512654060474025524 0ustar www-datawww-datamodule 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::InPointer.from_closure_data(#{@callback_argument.call_argument_name}.object_id)" end end end end gir_ffi-0.9.0/lib/gir_ffi/builders/null_convertor.rb0000644000004100000410000000040112654060474022544 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/builders/base_type_builder.rb0000644000004100000410000000157612654060474023170 0ustar www-datawww-datarequire '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.9.0/lib/gir_ffi/builders/user_defined_builder.rb0000644000004100000410000001315112654060474023641 0ustar www-datawww-datarequire '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 register_type setup_layout 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 |object_class_ptr, _data| setup_properties object_class_ptr setup_vfuncs object_class_ptr end end def interface_init_proc(interface) proc do |interface_ptr, _data| setup_interface_vfuncs interface, interface_ptr end end def instance_size size = parent_gtype.instance_size properties.each do size += FFI.type_size(:int32) 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.get_name) end end def property_setter proc do |object, _property_id, value, pspec| object.send("#{pspec.get_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, 0] offset = superclass::Struct.size fields_spec = properties.flat_map do |pinfo| spec = [pinfo.name.to_sym, :int32, offset] offset += FFI.type_size(:int32) spec end parent_spec + fields_spec end def setup_property_accessors properties.each do |pinfo| setup_accessors_for_param_info pinfo end end def setup_accessors_for_param_info(pinfo) field_name = pinfo.name code = <<-CODE def #{field_name} @struct[:#{field_name}] end def #{field_name}= val @struct[:#{field_name}] = val end CODE klass.class_eval code 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.9.0/lib/gir_ffi/builders/closure_convertor.rb0000644000004100000410000000060312654060474023252 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/builders/boxed_builder.rb0000644000004100000410000000065012654060474022306 0ustar www-datawww-datarequire 'gir_ffi/builders/registered_type_builder' require 'gir_ffi/builders/with_layout' module GirFFI module Builders # Implements the creation of a class representing boxed types. class BoxedBuilder < RegisteredTypeBuilder include WithLayout private def setup_class setup_layout setup_constants stub_methods setup_field_accessors end end end end gir_ffi-0.9.0/lib/gir_ffi/builders/callback_builder.rb0000644000004100000410000000262412654060474022744 0ustar www-datawww-datarequire '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 return_value_info = ReturnValueInfo.new(info.return_type, info.caller_owns, info.skip_return?) MappingMethodBuilder.for_callback(info.args, return_value_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.9.0/lib/gir_ffi/builders/argument_builder_collection.rb0000644000004100000410000000740012654060474025242 0ustar www-datawww-datamodule 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 = nil argument_builders.each do |it| name = it.method_argument_name if !block && it.block_argument? block = "&#{name}" else base << name end end base << block if block base.compact 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 end end end gir_ffi-0.9.0/lib/gir_ffi/builders/module_builder.rb0000644000004100000410000000574012654060474022477 0ustar www-datawww-datarequire '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(namespace, version = nil) @namespace = namespace @version = version # FIXME: Pass safe namespace as an argument @safe_namespace = @namespace.gsub(/^./, &:upcase) 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 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 unless defined? @gir @gir = GObjectIntrospection::IRepository.default @gir.require @namespace, @version end @gir end end end end gir_ffi-0.9.0/lib/gir_ffi/builders/constant_builder.rb0000644000004100000410000000106012654060474023032 0ustar www-datawww-datarequire '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.9.0/lib/gir_ffi/builders/type_builder.rb0000644000004100000410000000266512654060474022176 0ustar www-datawww-datarequire '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 } 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.9.0/lib/gir_ffi/builders/union_builder.rb0000644000004100000410000000065112654060474022336 0ustar www-datawww-datarequire 'gir_ffi/builders/boxed_builder' require 'gir_ffi/union_base' module GirFFI module Builders # Implements the creation of a class representing union type. The # class will have a nested FFI::Union class to represent its C union. class UnionBuilder < BoxedBuilder def layout_superclass FFI::Union end private def superclass UnionBase end end end end gir_ffi-0.9.0/lib/gir_ffi/builders/field_builder.rb0000644000004100000410000001631712654060474022277 0ustar www-datawww-datarequire 'gir_ffi/builders/argument_builder' 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 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}", "#{typed_ptr} = GirFFI::InOutPointer.new(#{field_type_tag}, #{field_ptr})", "#{bare_value} = #{typed_ptr}.to_value" ] 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 def array_length_idx @array_length_idx end private 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.inspect 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 :everything end def caller_allocates? false end def skip? false end end # Builder for field getters 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) @info = field_info end def build setup_getter setup_setter 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 info.name end def setup_setter container_class.class_eval setter_def if info.writable? 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 typed_ptr = builder.new_variable <<-CODE.reset_indentation def #{info.name}= #{builder.method_argument_name} #{field_ptr} = @struct.to_ptr + #{info.offset} #{typed_ptr} = GirFFI::InOutPointer.new(#{field_type_tag}, #{field_ptr}) #{builder.pre_conversion.join("\n ")} #{typed_ptr}.set_value #{builder.call_argument_name} end CODE end private def field_type_tag @field_type_tag ||= info.field_type.tag_or_class.inspect 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 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 end end end gir_ffi-0.9.0/lib/gir_ffi/builders/enum_builder.rb0000644000004100000410000000240112654060474022145 0ustar www-datawww-datarequire '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 <<-EOS def self.inspect "#{@namespace}::#{@classname}" end EOS end def already_set_up klass.respond_to? :gtype end def superclass EnumBase end end end end gir_ffi-0.9.0/lib/gir_ffi/builders/callback_argument_builder.rb0000644000004100000410000001050012654060474024636 0ustar www-datawww-datarequire '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' 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 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 [outgoing_post_conversion] when :error [ "rescue => #{result_name}", outgoing_post_conversion, 'end' ] else [] end end private def result_name @result_name ||= new_variable end def pre_convertor_argument if direction == :inout "#{out_parameter_name}.to_value" else method_argument_name end end def pre_convertor @pre_convertor ||= if closure? ClosureConvertor.new(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 outgoing_post_conversion "#{out_parameter_name}.set_value #{post_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 type_spec = type_info.tag_or_class value = if allocated_by_us? "GirFFI::InOutPointer.new(#{type_spec[1].inspect})" \ ".tap { |ptr| #{method_argument_name}.put_pointer 0, ptr }" else "GirFFI::InOutPointer.new(#{type_spec.inspect}, #{method_argument_name})" end "#{out_parameter_name} = #{value}" end # Check if an out argument needs to be allocated by us, the callee. Since # caller_allocates is false by default, we must also check that the type # is a pointer. For example, an out parameter of type gint8* will always # be allocate by the caller. def allocated_by_us? 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.9.0/lib/gir_ffi/builders/unintrospectable_boxed_builder.rb0000644000004100000410000000104512654060474025746 0ustar www-datawww-datarequire 'gir_ffi/builders/boxed_builder' 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 < BoxedBuilder 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 FFI::Struct end end end end gir_ffi-0.9.0/lib/gir_ffi/builders/null_return_value_builder.rb0000644000004100000410000000053112654060474024750 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/builders/function_builder.rb0000644000004100000410000000221412654060474023030 0ustar www-datawww-datarequire '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) @info = info @return_value_builder = ReturnValueBuilder.new(vargen, return_value_info) 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 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.9.0/lib/gir_ffi/builders/object_builder.rb0000644000004100000410000000733212654060474022457 0ustar www-datawww-datarequire 'gir_ffi/builders/registered_type_builder' require 'gir_ffi/builders/with_layout' require 'gir_ffi/builders/property_builder' require 'gir_ffi/object_base' 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 } or raise "Signal #{signal_name} not found" end def find_property(property_name) seek_in_ancestor_infos { |info| info.find_property property_name } or raise "Property #{property_name} not found" 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 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 if info.fundamental? setup_field_accessors else setup_property_accessors end setup_vfunc_invokers setup_interfaces provide_initializer end # FIXME: Private method only used in subclass def layout_superclass FFI::Struct end def parent_info unless defined? @parent_info @parent_info = if (parent = info.parent) && parent != info parent end end @parent_info 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_property_accessors info.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| if (invoker = vfinfo.invoker) define_vfunc_invoker vfinfo.name, invoker.name end 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' klass.class_eval " def initialize(properties = {}) base_initialize(properties) 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.9.0/lib/gir_ffi/builders/method_template.rb0000644000004100000410000000422212654060474022651 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/builders/c_to_ruby_convertor.rb0000644000004100000410000000211312654060474023561 0ustar www-datawww-datamodule 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_name, length_arg) @type_info = type_info @argument_name = argument_name @length_arg = length_arg end def conversion case @type_info.flattened_tag when :utf8, :filename "#{@argument_name}.to_utf8" else "#{@type_info.argument_class_name}.wrap(#{conversion_argument_list})" end end private def conversion_argument_list conversion_arguments.join(', ') end def conversion_arguments if @type_info.flattened_tag == :c [@type_info.element_type.inspect, array_size, @argument_name] else @type_info.extra_conversion_arguments.map(&:inspect).push(@argument_name) end end def array_size if @length_arg @length_arg else @type_info.array_fixed_size end end end end end gir_ffi-0.9.0/lib/gir_ffi/builders/closure_argument_builder.rb0000644000004100000410000000061212654060474024561 0ustar www-datawww-datarequire '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.9.0/lib/gir_ffi/builders/initializer_builder.rb0000644000004100000410000000144412654060474023532 0ustar www-datawww-datarequire '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) @info = info @return_value_builder = InitializerReturnValueBuilder.new(vargen, return_value_info) 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.9.0/lib/gir_ffi/builders/registered_type_builder.rb0000644000004100000410000000455412654060474024412 0ustar www-datawww-datarequire '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.9.0/lib/gir_ffi/builders/constructor_builder.rb0000644000004100000410000000252112654060474023571 0ustar www-datawww-datarequire '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. 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.9.0/lib/gir_ffi/builders/return_value_builder.rb0000644000004100000410000000353312654060474023723 0ustar www-datawww-datarequire 'gir_ffi/builders/base_argument_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 < 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 post_conversion if has_post_conversion? ["#{post_converted_name} = #{post_convertor.conversion}"] else [] end end private def has_post_conversion? closure? || type_info.needs_c_to_ruby_conversion_for_functions? end def post_convertor @post_convertor ||= if closure? ClosureConvertor.new(capture_variable_name) else FullCToRubyConvertor.new(type_info, capture_variable_name, length_argument_name) end end def length_argument_name length_arg && length_arg.post_converted_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.9.0/lib/gir_ffi/builders/struct_builder.rb0000644000004100000410000000127712654060474022537 0ustar www-datawww-datarequire 'gir_ffi/builders/boxed_builder' require 'gir_ffi/struct_base' module GirFFI module Builders # Implements the creation of a class representing a Struct. class StructBuilder < BoxedBuilder def layout_superclass FFI::Struct end def superclass if info.gtype_struct? # HACK: Inheritance chain is not expressed in GObject's code correctly. if info.full_type_name == 'GObject::InitiallyUnownedClass' return GObject::ObjectClass else type = fields.first.field_type return type.tag_or_class if type.tag == :interface end end StructBase end end end end gir_ffi-0.9.0/lib/gir_ffi/ffi_ext/0000755000004100000410000000000012654060474016764 5ustar www-datawww-datagir_ffi-0.9.0/lib/gir_ffi/ffi_ext/pointer.rb0000644000004100000410000000116712654060474020776 0ustar www-datawww-datamodule GirFFI module FFIExt # Extensions to FFI::Pointer module Pointer def to_ptr self end def to_value self end def zero? null? end # FIXME: Should probably not be here. def to_object return nil if self.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 # TODO: Move use to InPointer and InOutPointer? FFI::Pointer.send :include, GirFFI::FFIExt::Pointer gir_ffi-0.9.0/lib/gir_ffi/struct_base.rb0000644000004100000410000000022512654060474020202 0ustar www-datawww-datarequire 'gir_ffi/boxed_base' module GirFFI # Base class for generated classes representing GLib structs. class StructBase < BoxedBase end end gir_ffi-0.9.0/lib/gir_ffi/field_argument_info.rb0000644000004100000410000000076012654060474021670 0ustar www-datawww-datamodule 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.9.0/lib/gir_ffi/allocation_helper.rb0000644000004100000410000000046112654060474021352 0ustar www-datawww-datarequire 'gir_ffi/lib_c' module GirFFI # Helper module providing a safe allocation method that raises an exception # if memory cannot be allocated. module AllocationHelper def self.safe_malloc(size) ptr = LibC.malloc size raise NoMemoryError if ptr.null? ptr end end end gir_ffi-0.9.0/lib/gir_ffi/arg_helper.rb0000644000004100000410000000320612654060474017776 0ustar www-datawww-datarequire '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.ptr_to_utf8_length(ptr, len) ptr.null? ? nil : ptr.read_string(len) end 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 == size raise ArgumentError, "#{name} should have size #{size}" end end def self.cast_from_pointer(type, it) case type when :utf8, :filename it.to_utf8 when :gint32, :gint8 cast_pointer_to_int32 it when Class type.wrap it when :guint32 it.address when Array main_type, subtype = *type raise "Unexpected main type #{main_type}" if main_type != :pointer case subtype when Array container_type, *element_type = *subtype raise "Unexpected container type #{container_type}" if container_type != :ghash GLib::HashTable.wrap(element_type, it) else raise "Unexpected subtype #{subtype}" end else raise "Don't know how to cast #{type}" 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 end end gir_ffi-0.9.0/lib/gir_ffi/in_pointer.rb0000644000004100000410000000613412654060474020037 0ustar www-datawww-datamodule GirFFI # The InPointer class handles conversion from ruby types to pointers for # arguments with direction :in. This is used for arguments that are # arrays, strings, or interfaces. class InPointer < FFI::Pointer 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 new val when Class, :void val.to_ptr when Module new type[val] else raise NotImplementedError, type end end class << self def from_closure_data(obj) ArgHelper::OBJECT_STORE.store(obj) end 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 = AllocationHelper.safe_malloc type_size * (length + 1) ary.each_with_index do |item, idx| type.copy_value_to_pointer item, ptr, idx * type_size end ptr.put_bytes length * type_size, "\0" * type_size, 0, type_size new ptr end def from_enum_array(type, ary) from_basic_type_array :int32, ary.map { |sym| type.to_native sym, nil } end def from_utf8(str) len = str.bytesize ptr = AllocationHelper.safe_malloc(len + 1).write_string(str).put_char(len, 0) new ptr end def from_basic_type_array(type, ary) ffi_type = TypeMap.type_specification_to_ffi_type type ary = ary.dup << null_value(ffi_type) type_size = FFI.type_size(ffi_type) block = AllocationHelper.safe_malloc type_size * ary.length block.send "put_array_of_#{ffi_type}", 0, ary new block end def null_value(ffi_type) ffi_type == :pointer ? nil : 0 end end end end gir_ffi-0.9.0/lib/gir_ffi/type_map.rb0000644000004100000410000000261212654060474017504 0ustar www-datawww-datarequire '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, object: :pointer, struct: :pointer, error: :pointer, ptr_array: :pointer, array: :pointer, c: GirFFI::SizedArray, utf8: :pointer, GType: gsize_type, gboolean: GLib::Boolean, gunichar: :uint32, gint8: :int8, guint8: :uint8, gint16: :int16, guint16: :uint16, gint: :int, gint32: :int32, guint32: :uint32, gint64: :int64, guint64: :uint64, gsize: gsize_type, gfloat: :float, gdouble: :double, void: :void } def self.map_basic_type(type) sym = type.to_sym TAG_TYPE_MAP[sym] || sym end def self.type_specification_to_ffitype(type) type_specification_to_ffi_type type 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.9.0/lib/gir_ffi/enum_base.rb0000644000004100000410000000204212654060474017621 0ustar www-datawww-datarequire 'gir_ffi/registered_type_base' module GirFFI # Base module for enums. module EnumBase include FFI::DataConverter include RegisteredTypeBase 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 def wrap(arg) self[arg] end def from(arg) self[arg] 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.9.0/lib/gir_ffi/user_defined_property_info.rb0000644000004100000410000000052212654060474023277 0ustar www-datawww-datamodule GirFFI # Represents a property of a user defined type, conforming, as needed, to the # interface of GObjectIntrospection::IPropertyInfo. class UserDefinedPropertyInfo def initialize(param_spec) @param_spec = param_spec end attr_reader :param_spec def name @param_spec.get_name end end end gir_ffi-0.9.0/lib/gir_ffi/builder.rb0000644000004100000410000000246012654060474017315 0ustar www-datawww-datarequire '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) Builders::ModuleBuilder.new(namespace, 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.9.0/lib/gir_ffi/registered_type_base.rb0000644000004100000410000000035512654060474022060 0ustar www-datawww-datarequire '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.9.0/lib/gir_ffi-base.rb0000644000004100000410000000041612654060474016576 0ustar www-datawww-data# This section contains code that is needed by GObjectIntrospection, but # belongs in modules that can only be created fully once GObjectIntrospection # is fully loaded. require 'gir_ffi-base/glib/boolean' require 'gir_ffi-base/glib/strv' require 'gir_ffi-base/gobject' gir_ffi-0.9.0/lib/ffi-glib/0000755000004100000410000000000012654060474015412 5ustar www-datawww-datagir_ffi-0.9.0/lib/ffi-glib/variant.rb0000644000004100000410000000136412654060474017407 0ustar www-datawww-dataGLib.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 # 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) super ::GLib::Lib.g_variant_ref_sink ptr end alias_method :get_string_without_override, :get_string alias_method :get_string, :get_string_with_override end end gir_ffi-0.9.0/lib/ffi-glib/s_list.rb0000644000004100000410000000066712654060474017245 0ustar www-datawww-datarequire '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.9.0/lib/ffi-glib/ptr_array.rb0000644000004100000410000000242412654060474017744 0ustar www-datawww-datarequire '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.9.0/lib/ffi-glib/destroy_notify.rb0000644000004100000410000000065412654060474021025 0ustar www-datawww-dataGLib.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.9.0/lib/ffi-glib/byte_array.rb0000644000004100000410000000074312654060474020104 0ustar www-datawww-dataGLib.load_class :ByteArray module GLib # Overrides for GByteArray, GLib's automatically growing array of bytes. class ByteArray def to_string GirFFI::ArgHelper.ptr_to_utf8_length @struct[:data], @struct[: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.9.0/lib/ffi-glib/bytes.rb0000644000004100000410000000172712654060474017074 0ustar www-datawww-dataGLib.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 def get_data length_ptr = GirFFI::InOutPointer.for :gsize data_ptr = Lib.g_bytes_get_data self, length_ptr length = length_ptr.to_value # NOTE: Needed due to mis-identification of the element-type of the # resulting sized array for the default binding. 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.9.0/lib/ffi-glib/iconv.rb0000644000004100000410000000051312654060474017054 0ustar www-datawww-dataGLib.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.9.0/lib/ffi-glib/list_methods.rb0000644000004100000410000000245412654060474020442 0ustar www-datawww-datarequire '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.9.0/lib/ffi-glib/hash_table.rb0000644000004100000410000000372012654060474020033 0ustar www-datawww-datarequire '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.9.0/lib/ffi-glib/list.rb0000644000004100000410000000065012654060474016713 0ustar www-datawww-datarequire '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.9.0/lib/ffi-glib/array.rb0000644000004100000410000000376112654060474017064 0ustar www-datawww-datarequire '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.9.0/lib/ffi-glib/container_class_methods.rb0000644000004100000410000000146412654060474022636 0ustar www-datawww-datamodule 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 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.9.0/lib/ffi-glib/main_loop.rb0000644000004100000410000000262212654060474017716 0ustar www-datawww-datarequire '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 case RUBY_ENGINE when 'jruby' when 'rbx' else # 'ruby' most likely 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 if current_loop EXCEPTIONS << ex current_loop.quit else raise ex end end alias_method :run_without_thread_enabler, :run alias_method :run, :run_with_thread_enabler end end gir_ffi-0.9.0/lib/ffi-glib/array_methods.rb0000644000004100000410000000065012654060474020601 0ustar www-datawww-datamodule 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.9.0/lib/ffi-glib/error.rb0000644000004100000410000000051112654060474017065 0ustar www-datawww-dataGLib.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.9.0/lib/ffi-glib/strv.rb0000644000004100000410000000070612654060474016740 0ustar www-datawww-datamodule GLib # Extra methods for GLib::Strv. The bulk is defined in `gir_ffi-base/glib/strv.rb` class 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.9.0/COPYING.LIB0000644000004100000410000006347612654060474014645 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.9.0/metadata.yml0000644000004100000410000003526312654060474015501 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: gir_ffi version: !ruby/object:Gem::Version version: 0.9.0 platform: ruby authors: - Matijs van Zuijlen autorequire: bindir: bin cert_chain: [] date: 2016-01-21 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: ffi requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: '1.8' type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: '1.8' - !ruby/object:Gem::Dependency name: ffi-bit_masks requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 0.1.0 type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 0.1.0 - !ruby/object:Gem::Dependency name: indentation requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 0.1.1 type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 0.1.1 - !ruby/object:Gem::Dependency name: minitest requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: '5.5' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: '5.5' - !ruby/object:Gem::Dependency name: minitest-rspec_mocks requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 0.3.0 type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 0.3.0 - !ruby/object:Gem::Dependency name: rspec-mocks requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 3.4.1 type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: 3.4.1 - !ruby/object:Gem::Dependency name: rake requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: '10.1' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version version: '10.1' description: |2 GirFFI creates bindings for GObject-based libraries at runtime based on introspection data provided by the GObject Introspection Repository (GIR) system. Bindings are created at runtime and use FFI to interface with the C libraries. In cases where the GIR does not provide enough or correct information to create sane bindings, overrides may be created. email: - matijs@matijs.net executables: [] extensions: [] extra_rdoc_files: - DESIGN.md - Changelog.md - README.md - TODO.md files: - COPYING.LIB - Changelog.md - DESIGN.md - Gemfile - README.md - Rakefile - TODO.md - 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/base.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/ruby_closure.rb - lib/ffi-gobject/value.rb - lib/ffi-gobject_introspection.rb - lib/ffi-gobject_introspection/g_error.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/gir_ffi-base.rb - lib/gir_ffi-base/glib/boolean.rb - lib/gir_ffi-base/glib/strv.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/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_type_builder.rb - lib/gir_ffi/builders/boxed_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/error_argument_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/property_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/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/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/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/sized_array.rb - lib/gir_ffi/struct_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_type_info.rb - lib/gir_ffi/union_base.rb - lib/gir_ffi/user_data_argument_info.rb - lib/gir_ffi/user_data_type_info.rb - lib/gir_ffi/user_defined_property_info.rb - lib/gir_ffi/user_defined_type_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/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/value_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/lib_test.rb - test/ffi-gobject_test.rb - test/gir_ffi-base/glib/boolean_test.rb - test/gir_ffi-base/glib/strv_test.rb - test/gir_ffi/arg_helper_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_builder_test.rb - test/gir_ffi/callback_base_test.rb - test/gir_ffi/class_base_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/sized_array_test.rb - test/gir_ffi/type_map_test.rb - test/gir_ffi/unintrospectable_type_info_test.rb - test/gir_ffi/user_defined_property_info_test.rb - test/gir_ffi/user_defined_type_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.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_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_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 homepage: http://www.github.com/mvz/ruby-gir-ffi licenses: - LGPL-2.1 metadata: {} post_install_message: rdoc_options: - "--main" - README.md require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 2.0.0 required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 2.5.1 signing_key: specification_version: 4 summary: FFI-based GObject binding using the GObject Introspection Repository test_files: [] gir_ffi-0.9.0/test/0000755000004100000410000000000012654060474014144 5ustar www-datawww-datagir_ffi-0.9.0/test/gir_ffi-base/0000755000004100000410000000000012654060474016461 5ustar www-datawww-datagir_ffi-0.9.0/test/gir_ffi-base/glib/0000755000004100000410000000000012654060474017376 5ustar www-datawww-datagir_ffi-0.9.0/test/gir_ffi-base/glib/boolean_test.rb0000644000004100000410000000142512654060474022403 0ustar www-datawww-datarequire 'gir_ffi_test_helper' describe GLib::Boolean do it 'has the same native size as an int' do FFI.type_size(GLib::Boolean).must_equal FFI.type_size :int end describe '.from_native' do it 'converts 0 to false' do GLib::Boolean.from_native(0, 'whatever').must_equal false end it 'converts 1 to true' do GLib::Boolean.from_native(1, 'whatever').must_equal true end end describe '.to_native' do it 'converts false to 0' do GLib::Boolean.to_native(false, 'whatever').must_equal 0 end it 'converts true to 1' do GLib::Boolean.to_native(true, 'whatever').must_equal 1 end end describe '.size' do it 'returns the correct type size' do GLib::Boolean.size.must_equal FFI.type_size :int end end end gir_ffi-0.9.0/test/gir_ffi-base/glib/strv_test.rb0000644000004100000410000000207612654060474021765 0ustar www-datawww-datarequire 'base_test_helper' describe GLib::Strv do it 'wraps a pointer' do strv = GLib::Strv.new :some_pointer assert_equal :some_pointer, strv.to_ptr end describe '::wrap' do it 'takes a pointer and returns a GLib::Strv wrapping it' do strv = GLib::Strv.wrap :some_pointer assert_instance_of GLib::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 = GLib::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 = GLib::Strv.new FFI::Pointer.new(0) strv.each do |_str| flunk end end end it 'includes Enumerable' do GLib::Strv.must_include Enumerable end end gir_ffi-0.9.0/test/ffi-gobject_introspection/0000755000004100000410000000000012654060474021303 5ustar www-datawww-datagir_ffi-0.9.0/test/ffi-gobject_introspection/i_enum_info_test.rb0000644000004100000410000000062512654060474025161 0ustar www-datawww-datarequire '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.9.0/test/ffi-gobject_introspection/i_repository_test.rb0000644000004100000410000000271412654060474025422 0ustar www-datawww-datarequire '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 end gir_ffi-0.9.0/test/ffi-gobject_introspection/i_registered_type_info_test.rb0000644000004100000410000000124112654060474027406 0ustar www-datawww-datarequire '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.9.0/test/ffi-gobject_introspection/i_union_info_test.rb0000644000004100000410000000060412654060474025342 0ustar www-datawww-datarequire '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.9.0/test/ffi-gobject_introspection/lib_test.rb0000644000004100000410000000043012654060474023432 0ustar www-datawww-datarequire '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.9.0/test/ffi-gobject_introspection/i_base_info_test.rb0000644000004100000410000000325212654060474025126 0ustar www-datawww-datarequire '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 defined?(RUBY_ENGINE) && %w(jruby rbx).include?(RUBY_ENGINE) 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.9.0/test/ffi-gobject_introspection/i_interface_info_test.rb0000644000004100000410000000107012654060474026150 0ustar www-datawww-datarequire '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.9.0/test/ffi-gobject_introspection/i_type_info_test.rb0000644000004100000410000000175512654060474025203 0ustar www-datawww-datarequire '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.9.0/test/ffi-gobject_introspection/i_struct_info_test.rb0000644000004100000410000000102512654060474025534 0ustar www-datawww-datarequire '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.9.0/test/ffi-gobject_introspection/i_constant_info_test.rb0000644000004100000410000000153712654060474026051 0ustar www-datawww-datarequire '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.9.0/test/ffi-gobject_introspection/i_object_info_test.rb0000644000004100000410000000141012654060474025454 0ustar www-datawww-datarequire '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 '#type_name' do it 'returns the correct name' do object_info.type_name.must_equal 'GObject' end end end gir_ffi-0.9.0/test/ffi-gobject_introspection/i_function_info_test.rb0000644000004100000410000000013112654060474026032 0ustar www-datawww-datarequire 'introspection_test_helper' describe GObjectIntrospection::IFunctionInfo do end gir_ffi-0.9.0/test/ffi-gobject_introspection/i_property_info_test.rb0000644000004100000410000000235412654060474026102 0ustar www-datawww-datarequire '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.9.0/test/introspection_test_helper.rb0000644000004100000410000000174712654060474022000 0ustar www-datawww-datarequire 'base_test_helper' require 'ffi-gobject_introspection' 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.9.0/test/lib/0000755000004100000410000000000012654060474014712 5ustar www-datawww-datagir_ffi-0.9.0/test/lib/autogen.sh0000755000004100000410000000012212654060474016706 0ustar www-datawww-data#!/bin/sh # Run this to generate all the initial makefiles, etc. autoreconf -ivf gir_ffi-0.9.0/test/lib/Makefile.am0000644000004100000410000000741312654060474016753 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 \ $(GI_DATADIR)/tests/gitestmacros.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 \ $(GI_DATADIR)/tests/gitestmacros.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 \ --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.9.0/test/lib/configure.ac0000644000004100000410000000163112654060474017201 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.9.0/test/lib/m4/0000755000004100000410000000000012654060474015232 5ustar www-datawww-datagir_ffi-0.9.0/test/lib/m4/jhflags.m40000644000004100000410000000106112654060474017110 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.9.0/test/ffi-gobject/0000755000004100000410000000000012654060474016323 5ustar www-datawww-datagir_ffi-0.9.0/test/ffi-gobject/object_class_test.rb0000644000004100000410000000161712654060474022347 0ustar www-datawww-datarequire '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.9.0/test/ffi-gobject/object_test.rb0000644000004100000410000000567712654060474021174 0ustar www-datawww-datarequire '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 ArgumentError 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 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 # FIXME: Test this some other way it 'lowers the reference count' do if defined?(RUBY_ENGINE) && %w(jruby rbx).include?(RUBY_ENGINE) skip 'cannot be reliably tested on JRuby and Rubinius' end if RUBY_VERSION >= '2.3.0' skip 'cannot be reliably tested on CRuby >= 2.3' end object = GObject::Object.new ptr = object.to_ptr ref_count(ptr).must_equal 1 # Lose reference to object to allow garbage collection object = nil # rubocop:disable Lint/UselessAssignment GC.start GC.start GC.start ref_count(ptr).must_equal 0 end end end gir_ffi-0.9.0/test/ffi-gobject/gobject_test.rb0000644000004100000410000000561112654060474021327 0ustar www-datawww-datarequire '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 assert_equal GObject.type_from_name('invalid'), GObject::TYPE_INVALID assert_equal nil, GObject.type_name(GObject::TYPE_INVALID) assert_equal 'void', GObject.type_name(GObject::TYPE_NONE) assert_equal 'GInterface', GObject.type_name(GObject::TYPE_INTERFACE) assert_equal 'gchar', GObject.type_name(GObject::TYPE_CHAR) assert_equal 'guchar', GObject.type_name(GObject::TYPE_UCHAR) assert_equal 'gboolean', GObject.type_name(GObject::TYPE_BOOLEAN) assert_equal 'gint', GObject.type_name(GObject::TYPE_INT) assert_equal 'guint', GObject.type_name(GObject::TYPE_UINT) assert_equal 'glong', GObject.type_name(GObject::TYPE_LONG) assert_equal 'gulong', GObject.type_name(GObject::TYPE_ULONG) assert_equal 'gint64', GObject.type_name(GObject::TYPE_INT64) assert_equal 'guint64', GObject.type_name(GObject::TYPE_UINT64) assert_equal 'GEnum', GObject.type_name(GObject::TYPE_ENUM) assert_equal 'GFlags', GObject.type_name(GObject::TYPE_FLAGS) assert_equal 'gfloat', GObject.type_name(GObject::TYPE_FLOAT) assert_equal 'gdouble', GObject.type_name(GObject::TYPE_DOUBLE) assert_equal 'gchararray', GObject.type_name(GObject::TYPE_STRING) assert_equal 'gpointer', GObject.type_name(GObject::TYPE_POINTER) assert_equal 'GBoxed', GObject.type_name(GObject::TYPE_BOXED) assert_equal 'GParam', GObject.type_name(GObject::TYPE_PARAM) assert_equal 'GObject', GObject.type_name(GObject::TYPE_OBJECT) assert_equal 'GType', GObject.type_name(GObject::TYPE_GTYPE) assert_equal 'GVariant', GObject.type_name(GObject::TYPE_VARIANT) assert_equal 'GStrv', GObject.type_name(GObject::TYPE_STRV) assert_equal 'GHashTable', GObject.type_name(GObject::TYPE_HASH_TABLE) 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.9.0/test/ffi-gobject/value_test.rb0000644000004100000410000002330512654060474021026 0ustar www-datawww-datarequire '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 assert_equal false, gv.get_boolean end it 'wraps a boolean true' do gv = GObject::Value.wrap_ruby_value true assert_instance_of GObject::Value, gv assert_equal true, gv.get_boolean end it 'wraps an Integer' do gv = GObject::Value.wrap_ruby_value 42 assert_equal 42, gv.get_int end it 'wraps a String' do gv = GObject::Value.wrap_ruby_value 'Some Random String' assert_equal 'Some Random String', gv.get_string end it 'wraps nil' do gv = GObject::Value.wrap_ruby_value nil assert_instance_of GObject::Value, gv assert_equal nil, gv.get_value end it 'wraps object values' do value = GObject::Object.new({}) gv = GObject::Value.wrap_ruby_value value gv.get_value.must_equal value 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 assert_equal false, result end it 'unwraps a boolean true' do gv = GObject::Value.wrap_ruby_value true result = gv.get_value assert_equal true, result 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 a 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 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_equal 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 before do GirFFI.setup :GIMarshallingTests end it 'restores the underlying GValue to its pristine state' do if defined?(RUBY_ENGINE) && %w(jruby rbx).include?(RUBY_ENGINE) 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 sleep 1 GC.start GC.start value.current_gtype_name.wont_equal 'gint' end end end gir_ffi-0.9.0/test/gir_ffi_test.rb0000644000004100000410000000560712654060474017145 0ustar www-datawww-datarequire 'gir_ffi_test_helper' GirFFI.setup :GIMarshallingTests describe GirFFI 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 '::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 it 'makes GirFFI find the new class by GType' do klass = GirFFI::Builder.build_by_gtype @gtype klass.must_equal @klass 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.9.0/test/gir_ffi/0000755000004100000410000000000012654060474015551 5ustar www-datawww-datagir_ffi-0.9.0/test/gir_ffi/version_test.rb0000644000004100000410000000023512654060474020622 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/method_stubber_test.rb0000644000004100000410000000332512654060474022146 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/type_map_test.rb0000644000004100000410000000072412654060474020756 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/unintrospectable_type_info_test.rb0000644000004100000410000000721312654060474024575 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/class_base_test.rb0000644000004100000410000001206312654060474021236 0ustar www-datawww-datarequire '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(FFI::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.9.0/test/gir_ffi/builder_test.rb0000644000004100000410000001575412654060474020577 0ustar www-datawww-datarequire 'gir_ffi_test_helper' GirFFI.setup :Regress 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 '.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 end 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 describe 'building Regress' 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 it 'does not replace existing module' do oldmodule = Regress GirFFI::Builder.build_module 'Regress' assert_equal oldmodule, Regress end it 'does not replace existing Lib module' do oldmodule = Regress::Lib GirFFI::Builder.build_module 'Regress' assert_equal oldmodule, Regress::Lib end after do restore_module :Regress end end end gir_ffi-0.9.0/test/gir_ffi/arg_helper_test.rb0000644000004100000410000000144712654060474021253 0ustar www-datawww-datarequire '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 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 it 'handles :guint32' do ptr = FFI::Pointer.new(0xffffffff) GirFFI::ArgHelper.cast_from_pointer(:guint32, ptr).must_equal(0xffffffff) end end end gir_ffi-0.9.0/test/gir_ffi/user_defined_property_info_test.rb0000644000004100000410000000117512654060474024554 0ustar www-datawww-datarequire 'gir_ffi_test_helper' require 'gir_ffi/user_defined_property_info' describe GirFFI::UserDefinedPropertyInfo do describe '#param_spec' do it 'returns the passed in parameter specification' do info = GirFFI::UserDefinedPropertyInfo.new :some_param_spec info.param_spec.must_equal :some_param_spec end end describe '#name' do it 'returns the name retrieved from the parameter specification' do expect(param_spec = Object.new).to receive(:get_name).and_return :property_name info = GirFFI::UserDefinedPropertyInfo.new param_spec info.name.must_equal :property_name end end end gir_ffi-0.9.0/test/gir_ffi/sized_array_test.rb0000644000004100000410000000702512654060474021455 0ustar www-datawww-datarequire '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 '#==' 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 it 'includes Enumerable' do GirFFI::SizedArray.must_include Enumerable end end gir_ffi-0.9.0/test/gir_ffi/in_out_pointer_test.rb0000644000004100000410000000656412654060474022205 0ustar www-datawww-datarequire 'gir_ffi_test_helper' describe GirFFI::InOutPointer do describe '.new' do it 'wraps an existing pointer and a type' do ptr = GirFFI::AllocationHelper.safe_malloc(FFI.type_size(:int32)) ptr.put_int32 0, 42 instance = GirFFI::InOutPointer.new :gint32, ptr instance.to_value.must_equal 42 end end describe 'an instance created with .from' do before do @result = GirFFI::InOutPointer.from :gint32, 23 end it 'holds a pointer to the given value' do assert_equal 23, @result.get_int32(0) end it 'is an instance of GirFFI::InOutPointer' do assert_instance_of GirFFI::InOutPointer, @result end end describe '.from' do it 'handles :gboolean false' do ptr = GirFFI::InOutPointer.from :gboolean, false ptr.read_int.must_equal 0 end it 'handles :gboolean true' do ptr = GirFFI::InOutPointer.from :gboolean, true ptr.read_int.must_equal(1) end it 'handles :utf8 pointers' do str_ptr = GirFFI::InPointer.from :utf8, 'Hello' GirFFI::InOutPointer.from :utf8, str_ptr end end describe 'in instance created with .for' do before do @result = GirFFI::InOutPointer.for :gint32 end it 'holds a pointer to a null value' do assert_equal 0, @result.get_int32(0) end it 'is an instance of GirFFI::InOutPointer' do assert_instance_of GirFFI::InOutPointer, @result end end describe '.for' do it 'handles :gboolean' do result = GirFFI::InOutPointer.for :gboolean result.to_value.must_equal false end it 'handles :utf8' do result = GirFFI::InOutPointer.for :utf8 result.to_value.must_be :null? end it 'handles GObject::Value' do result = GirFFI::InOutPointer.for GObject::Value type_size = FFI.type_size GObject::Value expected = "\x00" * type_size result.to_value.read_bytes(type_size).must_equal expected end end describe '#set_value' do it 'works setting the value to nil for GObject::Value' do pointer = GirFFI::InOutPointer.from GObject::Value, GObject::Value.from(3) pointer.set_value nil type_size = FFI.type_size GObject::Value expected = "\x00" * type_size pointer.to_value.read_bytes(type_size).must_equal expected end end describe '#to_value' do it 'returns the held value' do ptr = GirFFI::InOutPointer.from :gint32, 123 assert_equal 123, ptr.to_value end describe 'for :gboolean values' do it 'works when the value is false' do ptr = GirFFI::InOutPointer.from :gboolean, false ptr.to_value.must_equal false end it 'works when the value is true' do ptr = GirFFI::InOutPointer.from :gboolean, true ptr.to_value.must_equal true end end describe 'for :utf8 values' do it 'returns a pointer to the held value' do str_ptr = GirFFI::InPointer.from :utf8, 'Some value' ptr = GirFFI::InOutPointer.from :utf8, 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.from GObject::EnumValue, val result = ptr.to_value GObject::EnumValue.wrap(result).value.must_equal 3 end end end end gir_ffi-0.9.0/test/gir_ffi/user_defined_type_info_test.rb0000644000004100000410000000470612654060474023654 0ustar www-datawww-datarequire 'gir_ffi_test_helper' require 'gir_ffi/user_defined_type_info' describe GirFFI::UserDefinedTypeInfo do describe '#described_class' do let(:info) { GirFFI::UserDefinedTypeInfo.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::UserDefinedTypeInfo.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::UserDefinedTypeInfo.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 end describe '#initialize' do let(:foo_spec) { Object.new } let(:bar_spec) { Object.new } let(:info) do GirFFI::UserDefinedTypeInfo.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::UserDefinedTypeInfo.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::UserDefinedTypeInfo.new klass } it 'finds no methods' do info.find_method('foo').must_equal nil end end end gir_ffi-0.9.0/test/gir_ffi/object_base_test.rb0000644000004100000410000000150712654060474021400 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/in_pointer_test.rb0000644000004100000410000001247212654060474021311 0ustar www-datawww-datarequire '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(FFI::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_equal 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 GirFFI::InPointer' do assert_instance_of GirFFI::InPointer, @result 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 GirFFI::InPointer' do assert_instance_of GirFFI::InPointer, @result 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 GirFFI::InPointer' do assert_instance_of GirFFI::InPointer, @result 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 self::Enum = FFI::Enum.new [:foo, :bar, :baz], :qux def self.[](val) self::Enum[val] end 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_equal 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 describe '.from_closure_data' do describe 'when called with nil' do it 'returns a pointer pointing to nil.object_id' do GirFFI::InPointer.from_closure_data(nil).address.must_equal nil.object_id end end describe 'when called with a string' do it 'stores the string in GirFFI::ArgHelper::OBJECT_STORE' do str = 'Foo' ptr = GirFFI::InPointer.from_closure_data(str) result = GirFFI::ArgHelper::OBJECT_STORE.fetch(ptr) result.must_equal str end end end end gir_ffi-0.9.0/test/gir_ffi/error_type_info_test.rb0000644000004100000410000000220312654060474022337 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/info_ext/0000755000004100000410000000000012654060474017364 5ustar www-datawww-datagir_ffi-0.9.0/test/gir_ffi/info_ext/safe_function_name_test.rb0000644000004100000410000000104012654060474024566 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/info_ext/safe_constant_name_test.rb0000644000004100000410000000113112654060474024573 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/info_ext/i_unresolved_info_test.rb0000644000004100000410000000054212654060474024462 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/info_ext/i_field_info_test.rb0000644000004100000410000000205512654060474023360 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/info_ext/i_type_info_test.rb0000644000004100000410000005070512654060474023263 0ustar www-datawww-datarequire '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 string' do before do allow(type_info).to receive(:tag).and_return :utf8 end it 'returns an array containing :utf8' do type_info.extra_conversion_arguments.must_equal [:utf8] 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 :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 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.9.0/test/gir_ffi/info_ext/i_signal_info_test.rb0000644000004100000410000000153512654060474023554 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/info_ext/i_function_info_test.rb0000644000004100000410000000455612654060474024132 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/info_ext/i_callable_info_test.rb0000644000004100000410000000132312654060474024031 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/info_ext/i_callback_info_test.rb0000644000004100000410000000105212654060474024025 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/zero_terminated_test.rb0000644000004100000410000000454712654060474022342 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/builders/0000755000004100000410000000000012654060474017362 5ustar www-datawww-datagir_ffi-0.9.0/test/gir_ffi/builders/signal_closure_builder_test.rb0000644000004100000410000001241112654060474025464 0ustar www-datawww-datarequire '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 end end gir_ffi-0.9.0/test/gir_ffi/builders/constant_builder_test.rb0000644000004100000410000000012112654060474024277 0ustar www-datawww-datarequire 'gir_ffi_test_helper' describe GirFFI::Builders::ConstantBuilder do end gir_ffi-0.9.0/test/gir_ffi/builders/union_builder_test.rb0000644000004100000410000000203012654060474023577 0ustar www-datawww-datarequire '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 FFI::Union' do builder.layout_superclass.must_equal FFI::Union end end end gir_ffi-0.9.0/test/gir_ffi/builders/user_defined_builder_test.rb0000644000004100000410000000773512654060474025124 0ustar www-datawww-datarequire 'gir_ffi_test_helper' GirFFI.setup :GIMarshallingTests describe GirFFI::Builders::UserDefinedBuilder do let(:klass) do Object.const_set("DerivedClass#{Sequence.next}", Class.new(GIMarshallingTests::Object)) end let(:builder) { GirFFI::Builders::UserDefinedBuilder.new info } let(:info) { GirFFI::UserDefinedTypeInfo.new klass } describe '#build_class' do before do builder.build_class end describe 'with type info containing one property' do let(:info) do GirFFI::UserDefinedTypeInfo.new klass do |it| it.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 gtype = klass.gtype q = GObject.type_query gtype q.instance_size.must_be :>, GIMarshallingTests::Object::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 it 'makes the property retrievable using #get_property' do obj = klass.new obj.foo = 13 obj.get_property('foo').must_equal 13 end it 'makes the property settable using #set_property' do obj = klass.new obj.set_property('foo', 20) obj.foo.must_equal 20 end end describe 'with type info containing an overridden g_name' do let(:info) do GirFFI::UserDefinedTypeInfo.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::UserDefinedTypeInfo.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 'with type info containing a vfunc from an included Interface' do let(:info) do klass.class_eval { include GIMarshallingTests::Interface } GirFFI::UserDefinedTypeInfo.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.9.0/test/gir_ffi/builders/vfunc_builder_test.rb0000644000004100000410000001571112654060474023602 0ustar www-datawww-datarequire '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 = GirFFI::InOutPointer.new(:gint8, out) _v4 = _proc.call(_v1, _v2) _v3.set_value _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 = GirFFI::InOutPointer.new(:gint8).tap { |ptr| out.put_pointer 0, ptr } _v4 = _proc.call(_v1, _v2) _v3.set_value _v4 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 = GirFFI::InOutPointer.new([:pointer, :error], _error) begin _v4 = _proc.call(_v1, _v2) rescue => _v5 _v3.set_value 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) _v3 = GObject::Object.from(_v2.ref).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 = GirFFI::InOutPointer.new([:pointer, GObject::Object], object) _v3 = _proc.call(_v1) _v2.set_value GObject::Object.from(_v3.ref) 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.9.0/test/gir_ffi/builders/constructor_builder_test.rb0000644000004100000410000000221312654060474025037 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/builders/callback_argument_builder_test.rb0000644000004100000410000000716612654060474026124 0ustar www-datawww-datarequire '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 = GirFFI::InOutPointer.new([:pointer, :zero_terminated], a)'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v1.set_value GirFFI::ZeroTerminated.from(:gfloat, _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 = GirFFI::InOutPointer.new([:pointer, :error], _error)', 'begin' ] end it 'converts any exceptions to GLib::Error in #post_conversion' do builder.post_conversion.must_equal [ 'rescue => _v1', '_v2.set_value 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 = GirFFI::InOutPointer.new([:pointer, :c], ints)', '_v2 = GirFFI::SizedArray.wrap(:gint32, _v3, _v1.to_value)'] end it 'has the correct value for #post_conversion' do array_arg_builder.pre_conversion array_arg_builder.post_conversion. must_equal ['_v1.set_value GirFFI::SizedArray.from(:gint32, -1, _v4)'] end end describe 'for an array length argument' do it 'does not provide a call argument name' do length_arg_builder.call_argument_name.must_be_nil end it 'does not provide a capture variable name' do length_arg_builder.capture_variable_name.must_be_nil end it 'has the correct value for #pre_conversion' do length_arg_builder.pre_conversion. must_equal ['_v1 = GirFFI::InOutPointer.new(:gint32, length)', '_v2 = _v1.to_value'] end it 'has the correct value for #post_conversion' do length_arg_builder.pre_conversion length_arg_builder.post_conversion. must_equal ['_v1.set_value _v3.length'] end end end end gir_ffi-0.9.0/test/gir_ffi/builders/property_builder_test.rb0000644000004100000410000000677612654060474024360 0ustar www-datawww-datarequire '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 get_property("some-strv") 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 get_property("string") end CODE builder.getter_def.must_equal expected end it 'generates the correct setter definition' do expected = <<-CODE.reset_indentation def string= value set_property("string", value) 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.9.0/test/gir_ffi/builders/struct_builder_test.rb0000644000004100000410000000527112654060474024005 0ustar www-datawww-datarequire '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 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.send :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.send :layout_specification assert_equal [:bar, :foo, 0, :baz, [:qux, 2], 0], spec 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 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 end gir_ffi-0.9.0/test/gir_ffi/builders/field_builder_test.rb0000644000004100000410000001063312654060474023542 0ustar www-datawww-datarequire 'gir_ffi_test_helper' describe GirFFI::Builders::FieldBuilder do let(:instance) { GirFFI::Builders::FieldBuilder.new field_info } 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 = GirFFI::InOutPointer.new(:gint8, _v1) _v3 = _v2.to_value _v3 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 = GirFFI::InOutPointer.new(:gint8, _v1) _v3 = value _v2.set_value _v3 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 = GirFFI::InOutPointer.new(Regress::TestSimpleBoxedA, _v1) _v3 = _v2.to_value _v4 = Regress::TestSimpleBoxedA.wrap(_v3) _v4 end CODE instance.getter_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 = GirFFI::InOutPointer.new(Regress::TestEnum, _v1) _v3 = _v2.to_value _v3 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::InOutPointer.new(:c, _v1) _v3 = _v2.to_value _v4 = GirFFI::SizedArray.wrap(Regress::TestStructE__some_union__union, 2, _v3) _v4 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} _v2 = GirFFI::InOutPointer.new(:c, _v1) GirFFI::ArgHelper.check_fixed_array_size 2, value, \"value\" _v3 = GirFFI::SizedArray.from(Regress::TestStructE__some_union__union, 2, value) _v2.set_value _v3 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 = GirFFI::InOutPointer.new(GObject::ClassInitFunc, _v1) _v3 = GObject::ClassInitFunc.from(value) _v2.set_value _v3 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 = GirFFI::InOutPointer.new(:guint32, _v1) _v3 = _v2.to_value _v4 = @struct.to_ptr + #{field_info.offset} _v5 = GirFFI::InOutPointer.new([:pointer, :c], _v4) _v6 = _v5.to_value _v7 = GirFFI::SizedArray.wrap(:GType, _v3, _v6) _v7 end CODE instance.getter_def.must_equal expected end end end gir_ffi-0.9.0/test/gir_ffi/builders/initializer_builder_test.rb0000644000004100000410000000240312654060474024776 0ustar www-datawww-datarequire '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 end end gir_ffi-0.9.0/test/gir_ffi/builders/unintrospectable_builder_test.rb0000644000004100000410000000335512654060474026043 0ustar www-datawww-datarequire 'gir_ffi_test_helper' describe GirFFI::Builders::UnintrospectableBuilder do describe 'building the GLocalFile type' do before do # Ensure existence of GLocalFile type GirFFI.setup :Gio unless Gio::Lib.respond_to? :g_file_new_for_path Gio.setup_method 'file_new_for_path' end ptr = GirFFI::InPointer.from :utf8, '/' Gio::Lib.g_file_new_for_path(ptr) @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 "raises correct error for a signal that doesn't exist" do msg = nil begin @bldr.find_signal 'foo' rescue RuntimeError => e msg = e.message end assert_match(/^Signal/, msg) 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 end gir_ffi-0.9.0/test/gir_ffi/builders/unintrospectable_boxed_builder_test.rb0000644000004100000410000000210012654060474027207 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/builders/argument_builder_test.rb0000644000004100000410000004276612654060474024315 0ustar www-datawww-datarequire '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 :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 = GirFFI::InPointer.from(:void, 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::InPointer.from_closure_data(foo.object_id)'] 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 = GirFFI::InOutPointer.for GIMarshallingTests::GEnum'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = _v1.to_value'] 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 = GirFFI::InOutPointer.for GIMarshallingTests::Flags'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = _v1.to_value'] end end describe 'for :object' 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 = GirFFI::InOutPointer.for [:pointer, Regress::TestObj]'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = Regress::TestObj.wrap(_v1.to_value)'] 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 = GirFFI::InOutPointer.for [:pointer, GIMarshallingTests::BoxedStruct]' ] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GIMarshallingTests::BoxedStruct.wrap(_v1.to_value)'] 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 = GirFFI::InOutPointer.for [:pointer, :strv]'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GLib::Strv.wrap(_v1.to_value)'] 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 = GirFFI::InOutPointer.for [:pointer, :array]'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GLib::Array.wrap(:utf8, _v1.to_value)'] 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 = GirFFI::InOutPointer.for [:pointer, :ptr_array]'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GLib::PtrArray.wrap(:utf8, _v1.to_value)'] 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 = GirFFI::InOutPointer.for [:pointer, :error]'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GLib::Error.wrap(_v1.to_value)'] 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 = GirFFI::InOutPointer.for [:pointer, :c]'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GirFFI::SizedArray.wrap(:gint32, 4, _v1.to_value)'] 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 = GirFFI::InOutPointer.for [:pointer, :c]'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GirFFI::SizedArray.wrap(:gint32, bar, _v1.to_value)'] 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 = GirFFI::InOutPointer.for [:pointer, :glist]'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GLib::List.wrap(:utf8, _v1.to_value)'] 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 = GirFFI::InOutPointer.for [:pointer, :gslist]'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GLib::SList.wrap(:utf8, _v1.to_value)'] 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 = GirFFI::InOutPointer.for [:pointer, [:ghash, :utf8, :utf8]]'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = GLib::HashTable.wrap([:utf8, :utf8], _v1.to_value)'] 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 = GirFFI::InOutPointer.for GIMarshallingTests::Enum', "_v1.set_value #{arg_info.name}"] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = _v1.to_value'] 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 = GirFFI::InOutPointer.for GIMarshallingTests::NoTypeFlags', "_v1.set_value #{arg_info.name}"] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = _v1.to_value'] 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 = GirFFI::InOutPointer.for :gint32', "_v1.set_value #{arg_info.name}"] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = _v1.to_value'] 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 = GirFFI::InOutPointer.for :gint32', '_v1.set_value n_ints'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = _v1.to_value'] 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 = GirFFI::InOutPointer.for [:pointer, :strv]', '_v1.set_value 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.to_value)'] 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 = GirFFI::InOutPointer.for [:pointer, :ptr_array]', '_v1.set_value 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.to_value)'] 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 = GirFFI::InOutPointer.for :utf8', '_v1.set_value GirFFI::InPointer.from(:utf8, utf8)'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal ['_v2 = _v1.to_value.to_utf8'] 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 = GirFFI::InOutPointer.for [:pointer, :c]', '_v1.set_value 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.to_value)'] 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 = GirFFI::InOutPointer.for [:pointer, :c]', '_v1.set_value GirFFI::SizedArray.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.to_value)'] 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 = GirFFI::InOutPointer.for :gint32', '_v1.set_value 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 = GirFFI::InOutPointer.for :gint32'] end it 'has the correct value for #post_conversion' do builder.post_conversion.must_equal [] end end end gir_ffi-0.9.0/test/gir_ffi/builders/callback_return_value_builder_test.rb0000644000004100000410000000517712654060474027015 0ustar www-datawww-datarequire '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 ['_v2 = GObject::Object.from(_v1.ref).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.9.0/test/gir_ffi/builders/function_builder_test.rb0000644000004100000410000002266212654060474024311 0ustar www-datawww-datarequire 'gir_ffi_test_helper' describe GirFFI::Builders::FunctionBuilder do describe '#method_definition' do let(:builder) { GirFFI::Builders::FunctionBuilder.new function_info } let(:code) { builder.method_definition } describe 'for Regress:test_array_fixed_out_objects' do let(:function_info) { get_introspection_data 'Regress', 'test_array_fixed_out_objects' } it 'builds a correct definition' do skip unless function_info code.must_equal <<-CODE.reset_indentation def self.test_array_fixed_out_objects _v1 = GirFFI::InOutPointer.for [:pointer, :c] Regress::Lib.regress_test_array_fixed_out_objects _v1 _v2 = GirFFI::SizedArray.wrap([:pointer, Regress::TestObj], 2, _v1.to_value) return _v2 end CODE end end describe 'for functions having a linked length argument' do let(:function_info) { get_introspection_data 'Regress', 'test_array_gint16_in' } it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def self.test_array_gint16_in(ints) n_ints = ints.nil? ? 0 : ints.length _v1 = n_ints _v2 = GirFFI::SizedArray.from(:gint16, -1, ints) _v3 = Regress::Lib.regress_test_array_gint16_in _v1, _v2 return _v3 end CODE end end describe 'for functions with callbacks' do let(:function_info) { get_introspection_data 'Regress', 'test_callback_destroy_notify' } it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def self.test_callback_destroy_notify(&callback) _v1 = Regress::TestCallbackUserData.from(callback) _v2 = GirFFI::InPointer.from_closure_data(_v1.object_id) _v3 = GLib::DestroyNotify.default _v4 = Regress::Lib.regress_test_callback_destroy_notify _v1, _v2, _v3 return _v4 end CODE end end describe 'for functions that take a GValue' do let(:function_info) { get_introspection_data 'GIMarshallingTests', 'gvalue_in' } it 'creates a call to GObject::Value#from' do code.must_equal <<-CODE.reset_indentation def self.gvalue_in(value) _v1 = GObject::Value.from(value) GIMarshallingTests::Lib.gi_marshalling_tests_gvalue_in _v1 end CODE end end describe 'for functions that return a GValue' do let(:function_info) { get_introspection_data 'GIMarshallingTests', 'gvalue_return' } it 'creates a call to #get_value' do code.must_equal <<-CODE.reset_indentation def self.gvalue_return _v1 = GIMarshallingTests::Lib.gi_marshalling_tests_gvalue_return _v2 = GObject::Value.wrap(_v1).get_value return _v2 end CODE end end describe 'for functions that have a GValue out argument' do let(:function_info) { get_introspection_data 'GIMarshallingTests', 'gvalue_out' } it 'creates a call to #get_value' do code.must_equal <<-CODE.reset_indentation def self.gvalue_out _v1 = GirFFI::InOutPointer.for [:pointer, GObject::Value] GIMarshallingTests::Lib.gi_marshalling_tests_gvalue_out _v1 _v2 = GObject::Value.wrap(_v1.to_value).get_value return _v2 end CODE end end describe 'for functions that have a caller-allocated GValue out argument' do let(:function_info) { get_introspection_data 'GIMarshallingTests', 'gvalue_out_caller_allocates' } it 'creates a call to #get_value' do skip unless function_info code.must_equal <<-CODE.reset_indentation def self.gvalue_out_caller_allocates _v1 = GObject::Value.new GIMarshallingTests::Lib.gi_marshalling_tests_gvalue_out_caller_allocates _v1 _v2 = _v1.get_value return _v2 end CODE end end describe 'for functions with a nullable input array' do let(:function_info) { get_introspection_data 'Regress', 'test_array_int_null_in' } it 'builds correct definition' do code.must_equal <<-CODE.reset_indentation def self.test_array_int_null_in(arr) len = arr.nil? ? 0 : arr.length _v1 = len _v2 = GirFFI::SizedArray.from(:gint32, -1, arr) Regress::Lib.regress_test_array_int_null_in _v2, _v1 end CODE end end describe 'for functions with a nullable output array' do let(:function_info) { get_introspection_data 'Regress', 'test_array_int_null_out' } it 'builds correct definition' do code.must_equal <<-CODE.reset_indentation def self.test_array_int_null_out _v1 = GirFFI::InOutPointer.for :gint32 _v2 = GirFFI::InOutPointer.for [:pointer, :c] Regress::Lib.regress_test_array_int_null_out _v2, _v1 _v3 = _v1.to_value _v4 = GirFFI::SizedArray.wrap(:gint32, _v3, _v2.to_value) return _v4 end CODE end end describe 'for a method with an inout array with size argument' do let(:function_info) { get_method_introspection_data 'GIMarshallingTests', 'Object', 'method_array_inout' } it 'builds the correct definition' do code.must_equal <<-CODE.reset_indentation def method_array_inout(ints) length = ints.nil? ? 0 : ints.length _v1 = GirFFI::InOutPointer.for :gint32 _v1.set_value length _v2 = GirFFI::InOutPointer.for [:pointer, :c] _v2.set_value GirFFI::SizedArray.from(:gint32, -1, ints) GIMarshallingTests::Lib.gi_marshalling_tests_object_method_array_inout self, _v2, _v1 _v3 = _v1.to_value _v4 = GirFFI::SizedArray.wrap(:gint32, _v3, _v2.to_value) return _v4 end CODE end end describe 'for a simple method' do let(:function_info) { get_method_introspection_data 'Regress', 'TestObj', 'instance_method' } it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def instance_method _v1 = Regress::Lib.regress_test_obj_instance_method self return _v1 end CODE end end describe 'for GLib::Variant.get_strv' do let(:function_info) { get_method_introspection_data 'GLib', 'Variant', 'get_strv' } it 'builds a correct definition' do size_type = ":guint#{FFI.type_size(:size_t) * 8}" code.must_equal <<-CODE.reset_indentation def get_strv _v1 = GirFFI::InOutPointer.for #{size_type} _v2 = GLib::Lib.g_variant_get_strv self, _v1 _v3 = GLib::Strv.wrap(_v2) return _v3 end CODE end end describe 'for Regress.has_parameter_named_attrs' do let(:function_info) { get_introspection_data 'Regress', 'has_parameter_named_attrs' } it 'builds a correct definition' do skip unless function_info code.must_equal <<-CODE.reset_indentation def self.has_parameter_named_attrs(foo, attributes) _v1 = foo GirFFI::ArgHelper.check_fixed_array_size 32, attributes, \"attributes\" _v2 = GirFFI::SizedArray.from([:pointer, :guint32], 32, attributes) Regress::Lib.regress_has_parameter_named_attrs _v1, _v2 end CODE end end describe 'for GIMarshallingTests::Object#method_int8_arg_and_out_callee' do let(:function_info) do get_method_introspection_data('GIMarshallingTests', 'Object', 'method_int8_arg_and_out_callee') end it 'builds a correct definition' do skip unless function_info code.must_equal <<-CODE.reset_indentation def method_int8_arg_and_out_callee(arg) _v1 = arg _v2 = GirFFI::InOutPointer.for [:pointer, :gint8] GIMarshallingTests::Lib.gi_marshalling_tests_object_method_int8_arg_and_out_callee self, _v1, _v2 _v3 = GirFFI::InOutPointer.new(:gint8, _v2.to_value).to_value return _v3 end CODE end end describe 'for GIMarshallingTests::Object.full_inout' do let(:function_info) do get_method_introspection_data('GIMarshallingTests', 'Object', 'full_inout') end it 'builds a correct definition' do code.must_equal <<-CODE.reset_indentation def self.full_inout(object) _v1 = GirFFI::InOutPointer.for [:pointer, GIMarshallingTests::Object] _v1.set_value GIMarshallingTests::Object.from(object.ref) GIMarshallingTests::Lib.gi_marshalling_tests_object_full_inout _v1 _v2 = GIMarshallingTests::Object.wrap(_v1.to_value) return _v2 end CODE end end describe 'for Regress::TestObj#instance_method_full' do let(:function_info) do get_method_introspection_data('Regress', 'TestObj', 'instance_method_full') end it 'builds a correct definition including self.ref' do skip unless function_info code.must_equal <<-CODE.reset_indentation def instance_method_full Regress::Lib.regress_test_obj_instance_method_full self.ref end CODE end end end end gir_ffi-0.9.0/test/gir_ffi/builders/return_value_builder_test.rb0000644000004100000410000002726612654060474025204 0ustar www-datawww-datarequire 'gir_ffi_test_helper' describe GirFFI::Builders::ReturnValueBuilder do let(:var_gen) { GirFFI::VariableNameGenerator.new } let(:return_type_info) { GirFFI::ReturnValueInfo.new(type_info, :nothing, false) } let(:builder) do GirFFI::Builders::ReturnValueBuilder.new(var_gen, return_type_info) end describe 'for :gint32' do let(:type_info) do get_introspection_data('GIMarshallingTests', 'int_return_min').return_type 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 let(:type_info) do get_method_introspection_data('GIMarshallingTests', 'BoxedStruct', 'returnv').return_type end it 'wraps the result in #post_conversion' do builder.capture_variable_name.must_equal '_v1' builder.post_conversion.must_equal ['_v2 = GIMarshallingTests::BoxedStruct.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 :union' do let(:type_info) do get_method_introspection_data('GIMarshallingTests', 'Union', 'returnv').return_type 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(_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(:type_info) do get_method_introspection_data('Gio', 'File', 'new_for_commandline_arg').return_type 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 let(:type_info) do get_method_introspection_data('GIMarshallingTests', 'Object', 'full_return').return_type 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 'for :strv' do let(:type_info) do get_method_introspection_data('GLib', 'KeyFile', 'get_locale_string_list').return_type 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(:type_info) do get_method_introspection_data('GLib', 'Variant', 'dup_bytestring').return_type 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(:type_info) do get_introspection_data('GIMarshallingTests', 'bytearray_full_return').return_type 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(:type_info) do get_introspection_data('GIMarshallingTests', 'gptrarray_utf8_none_return').return_type 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(:type_info) do get_introspection_data('GIMarshallingTests', 'glist_int_none_return').return_type 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(:type_info) do get_introspection_data('GIMarshallingTests', 'gslist_int_none_return').return_type 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(:type_info) do get_introspection_data('GIMarshallingTests', 'ghashtable_int_none_return').return_type 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(:type_info) do get_introspection_data('GIMarshallingTests', 'garray_int_none_return').return_type 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(:type_info) do get_introspection_data('GIMarshallingTests', 'gerror_return').return_type 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(:type_info) do get_introspection_data('GIMarshallingTests', 'array_fixed_int_return').return_type 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(:type_info) do get_method_introspection_data('GIMarshallingTests', 'Object', 'method_array_return').return_type 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 let(:type_info) do get_introspection_data('GIMarshallingTests', 'utf8_full_return').return_type 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 'for :void pointer' do 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(:type_info) do get_method_introspection_data('Regress', 'TestObj', 'null_out').return_type 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(:type_info) do get_introspection_data('Regress', 'TestCallbackUserData').args[0].argument_type end 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(:type_info) do get_method_introspection_data('Regress', 'TestObj', 'skip_return_val').return_type 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.9.0/test/gir_ffi/builders/base_argument_builder_test.rb0000644000004100000410000000012512654060474025266 0ustar www-datawww-datarequire 'gir_ffi_test_helper' describe GirFFI::Builders::BaseArgumentBuilder do end gir_ffi-0.9.0/test/gir_ffi/builders/module_builder_test.rb0000644000004100000410000000251612654060474023745 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/builders/registered_type_builder_test.rb0000644000004100000410000000160512654060474025654 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/builders/enum_builder_test.rb0000644000004100000410000000075012654060474023422 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/builders/callback_builder_test.rb0000644000004100000410000000603712654060474024216 0ustar www-datawww-datarequire '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 = GirFFI::InOutPointer.new(:gfloat, a) _v2 = _proc.call() _v1.set_value _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 = GirFFI::InOutPointer.new(:gint32, length) _v2 = _v1.to_value _v3 = GirFFI::InOutPointer.new([:pointer, :c], ints) _v4 = GirFFI::SizedArray.wrap(:gint32, _v2, _v3.to_value) _v5 = _proc.call(_v4) _v1.set_value _v5.length _v3.set_value GirFFI::SizedArray.from(:gint32, -1, _v5) end CODE builder.mapping_method_definition.must_equal expected end end end end gir_ffi-0.9.0/test/gir_ffi/builders/interface_builder_test.rb0000644000004100000410000000146412654060474024421 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/builders/object_builder_test.rb0000644000004100000410000000546512654060474023734 0ustar www-datawww-datarequire '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 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 "raises an error for a signal that doesn't exist" do msg = nil begin obj_builder.find_signal 'foo' rescue RuntimeError => e msg = e.message end assert_match(/^Signal/, msg) 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 'raises an error if the property is not found' do proc do sub_obj_builder.find_property('this-property-does-not-exist') end.must_raise RuntimeError 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 # TODO: Improve this spec to use less mocking describe 'for a struct without defined fields' do it 'uses a single field of the parent struct type as the default layout' do @gir = GObjectIntrospection::IRepository.default @gir.require 'GObject', nil allow(info = Object.new).to receive(:parent).and_return @gir.find_by_name 'GObject', 'Object' allow(info).to receive(:fields).and_return [] allow(info).to receive(:info_type).and_return :object allow(info).to receive(:safe_name).and_return 'Bar' allow(info).to receive(:namespace).and_return 'Foo' @classbuilder = GirFFI::Builders::ObjectBuilder.new info spec = @classbuilder.send :layout_specification assert_equal [:parent, GObject::Object::Struct, 0], spec end end end gir_ffi-0.9.0/test/gir_ffi/ffi_ext/0000755000004100000410000000000012654060474017175 5ustar www-datawww-datagir_ffi-0.9.0/test/gir_ffi/ffi_ext/pointer_test.rb0000644000004100000410000000125412654060474022243 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/callback_base_test.rb0000644000004100000410000000122512654060474021663 0ustar www-datawww-datarequire '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.object_id GirFFI::CallbackBase::CALLBACKS[dummy_proc.object_id].must_be_nil end end end gir_ffi-0.9.0/test/gir_ffi/variable_name_generator_test.rb0000644000004100000410000000064512654060474023775 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/interface_base_test.rb0000644000004100000410000000073712654060474022076 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi/g_type_test.rb0000644000004100000410000000140112654060474020420 0ustar www-datawww-datarequire '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.9.0/test/gir_ffi_test_helper.rb0000644000004100000410000000306712654060474020502 0ustar www-datawww-datarequire '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(object) GObject::Object::Struct.new(object.to_ptr)[:ref_count] end def ref(object) object.ref 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.9.0/test/integration/0000755000004100000410000000000012654060474016467 5ustar www-datawww-datagir_ffi-0.9.0/test/integration/generated_secret_test.rb0000644000004100000410000000060612654060474023360 0ustar www-datawww-datarequire '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 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.9.0/test/integration/generated_warnlib_test.rb0000644000004100000410000000236012654060474023530 0ustar www-datawww-datarequire 'gir_ffi_test_helper' describe 'The generated WarnLib module' do before do begin GirFFI.setup :WarnLib rescue 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.9.0/test/integration/generated_gio_test.rb0000644000004100000410000000622412654060474022653 0ustar www-datawww-datarequire '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 proc { simple_action.state_type = nil }.must_raise NoMethodError end end end gir_ffi-0.9.0/test/integration/method_lookup_test.rb0000644000004100000410000000146612654060474022733 0ustar www-datawww-datarequire '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.9.0/test/integration/generated_glib_test.rb0000644000004100000410000000066512654060474023015 0ustar www-datawww-datarequire '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.9.0/test/integration/generated_pango_ft2_test.rb0000644000004100000410000000066312654060474023755 0ustar www-datawww-data# coding: utf-8 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.9.0/test/integration/generated_gimarshallingtests_test.rb0000644000004100000410000026337012654060474026010 0ustar www-datawww-data# coding: utf-8 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 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 res = GIMarshallingTests::BoxedStruct.inout bx # TODO: Deal with the fact that bx is now invalid (at least with # gobject-introspection 1.40). assert_equal 0, res.long_ end it 'has a working function #out' do res = GIMarshallingTests::BoxedStruct.out assert_equal 42, res.long_ end it 'has a working function #returnv' do res = GIMarshallingTests::BoxedStruct.returnv 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 instance.pointer = nested instance.pointer.must_equal nested 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 ref_count(ob).must_equal 1 res = GIMarshallingTests::Object.full_inout ob ref_count(ob).must_be :>, 0 ref_count(res).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 assert_instance_of GIMarshallingTests::Object, res end it 'has a working function #full_return' do res = GIMarshallingTests::Object.full_return assert_instance_of GIMarshallingTests::Object, res end it 'has a working function #inout_same' do skip 'This function is defined in the header but not implemented' end it 'has a working function #none_inout' do ob = GIMarshallingTests::Object.new 42 res = GIMarshallingTests::Object.none_inout ob assert_instance_of GIMarshallingTests::Object, res ob.wont_equal res end it 'has a working function #none_out' do res = GIMarshallingTests::Object.none_out assert_instance_of GIMarshallingTests::Object, res end it 'has a working function #none_return' do res = GIMarshallingTests::Object.none_return assert_instance_of GIMarshallingTests::Object, res 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 ref_count(obj).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 ref_count(obj).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 # TODO: Check if this is fixed # See https://bugzilla.gnome.org/show_bug.cgi?id=727665 it 'has a working method #int8_out' do skip 'Introspection data is not generated correctly' 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 field accessor methods' do assert_raises(NoMethodError) { instance.parent_instance } assert_raises(NoMethodError) { instance.parent_instance = nil } assert_raises(NoMethodError) { instance.long_ } assert_raises(NoMethodError) { instance.long_ = 1 } 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_equal nil end it 'can be retrieved with #some_boxed_glist' do instance.some_boxed_glist.must_equal 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_equal nil end it 'can be retrieved with #some_boxed_struct' do instance.some_boxed_struct.must_equal 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(GObject.type_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 field accessors' do assert_raises(NoMethodError) { instance.parent_instance } assert_raises(NoMethodError) { instance.parent_instance = nil } 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(GObject.type_from_instance so). must_equal 'GIMarshallingTestsSubSubObject' end let(:instance) { GIMarshallingTests::SubSubObject.new } it 'does not have field accessors' do assert_raises(NoMethodError) { instance.parent_instance } assert_raises(NoMethodError) { instance.parent_instance = nil } 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 # NOTE: Should be run with valgrind. See gimarhallingtests.c. 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 GIMarshallingTests.array_struct_take_in arr 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 assert_equal true, res end it 'has a working function #boolean_inout_true_false' do res = GIMarshallingTests.boolean_inout_true_false true assert_equal false, res end it 'has a working function #boolean_out_false' do res = GIMarshallingTests.boolean_out_false assert_equal false, res end it 'has a working function #boolean_out_true' do res = GIMarshallingTests.boolean_out_true assert_equal true, res end it 'has a working function #boolean_return_false' do res = GIMarshallingTests.boolean_return_false assert_equal false, res end it 'has a working function #boolean_return_true' do res = GIMarshallingTests.boolean_return_true assert_equal true, res end it 'has a working function #boxed_struct_inout' do bx = GIMarshallingTests::BoxedStruct.new bx.long_ = 42 res = GIMarshallingTests.boxed_struct_inout bx assert_equal 0, res.long_ end it 'has a working function #boxed_struct_out' do res = GIMarshallingTests.boxed_struct_out assert_equal 42, res.long_ end it 'has a working function #boxed_struct_returnv' do res = GIMarshallingTests.boxed_struct_returnv assert_equal 42, res.long_ 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 assert_equal Float::MAX, ret end it 'has a working function #double_return' do ret = GIMarshallingTests.double_return assert_equal Float::MAX, ret 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 assert_equal :value1, e end it 'has a working function #enum_out' do e = GIMarshallingTests.enum_out assert_equal :value3, e end it 'has a working function #enum_returnv' do e = GIMarshallingTests.enum_returnv assert_equal :value3, e end it 'has a working function #filename_list_return' do fl = GIMarshallingTests.filename_list_return assert_equal nil, fl 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 cl.invoke gv, nil, nil assert_equal 42, gv.get_value 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 assert_equal :value1, res end it 'has a working function #genum_out' do res = GIMarshallingTests.genum_out assert_equal :value3, res end it 'has a working function #genum_returnv' do res = GIMarshallingTests.genum_returnv assert_equal :value3, res 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) assert_equal '42', res res = GIMarshallingTests.gvalue_inout 42 assert_equal '42', res 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 assert_equal 42, res 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 # TODO: Wait for fixed version of param_spec_in_bool to land in Debian/Ubuntu # See https://bugzilla.gnome.org/show_bug.cgi?id=728409 it 'has a working function #param_spec_in_bool' do skip 'param_spec_in_bool tests the wrong type' ps = GObject.param_spec_boolean 'mybool', 'nick', 'blurb', true, :readable GIMarshallingTests.param_spec_in_bool ps 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.9.0/test/integration/generated_gtop_test.rb0000644000004100000410000000123512654060474023043 0ustar www-datawww-datarequire '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 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.9.0/test/integration/derived_classes_test.rb0000644000004100000410000000224512654060474023215 0ustar www-datawww-datarequire '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.9.0/test/integration/callback_exceptions_test.rb0000644000004100000410000000315712654060474024056 0ustar www-datawww-datarequire '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.9.0/test/integration/generated_pango_test.rb0000644000004100000410000000106112654060474023173 0ustar www-datawww-data# coding: utf-8 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.9.0/test/integration/generated_gobject_test.rb0000644000004100000410000000611012654060474023504 0ustar www-datawww-datarequire '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 proc { binding.target_property = 'foo' }.must_raise NoMethodError end end end end gir_ffi-0.9.0/test/integration/generated_regress_test.rb0000644000004100000410000027434312654060474023560 0ustar www-datawww-data# coding: utf-8 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 'Not implemented yet' end it 'has a writable field padding' do skip 'Not implemented yet' 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_equal 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 it 'has a working method #allow_none' do skip 'Needs testing' end it 'has a working method #calleeowns' do skip 'Needs testing' end it 'has a working method #calleesowns' do skip 'Needs testing' end it 'has a working method #compute_sum' do skip 'Needs testing' end it 'has a working method #compute_sum_n' do skip 'Needs testing' end it 'has a working method #compute_sum_nz' do skip 'Needs testing' end it 'has a working method #create_object' do skip 'Needs testing' end it 'has a working method #do_not_use' do skip 'Needs testing' end it 'has a working method #extra_annos' do skip 'Needs testing' end it 'has a working method #foreach' do skip 'Needs testing' end it 'has a working method #get_hash' do skip 'Needs testing' end it 'has a working method #get_objects' do skip 'Needs testing' end it 'has a working method #get_strings' do skip 'Needs testing' end it 'has a working method #hidden_self' do skip 'Needs testing' end it 'has a working method #in' do skip 'Needs testing' end it 'has a working method #inout' do skip 'Needs testing' end it 'has a working method #inout2' do skip 'Needs testing' end it 'has a working method #inout3' do skip 'Needs testing' end it 'has a working method #method' do skip 'Needs testing' end it 'has a working method #notrans' do skip 'Needs testing' end it 'has a working method #out' do skip 'Needs testing' end it 'has a working method #parse_args' do skip 'Needs testing' end it 'has a working method #set_data' do skip 'Needs testing' end it 'has a working method #set_data2' do skip 'Needs testing' end it 'has a working method #set_data3' do skip 'Needs testing' end it 'has a working method #string_out' do skip 'Needs testing' end it 'has a working method #use_buffer' do skip 'Needs testing' end it 'has a working method #watch_full' do skip 'Needs testing' end it 'has a working method #with_voidp' do skip 'Needs testing' end describe "its 'function-property' property" do it 'can be retrieved with #get_property' do skip 'Needs testing' end it 'can be retrieved with #function_property' do skip 'Needs testing' end it 'can be set with #set_property' do skip 'Needs testing' end it 'can be set with #function_property=' do skip 'Needs testing' end end describe "its 'string-property' property" do it 'can be retrieved with #get_property' do skip 'Needs testing' end it 'can be retrieved with #string_property' do skip 'Needs testing' end it 'can be set with #set_property' do skip 'Needs testing' end it 'can be set with #string_property=' do skip 'Needs testing' end end describe "its 'tab-property' property" do it 'can be retrieved with #get_property' do skip 'Needs testing' end it 'can be retrieved with #tab_property' do skip 'Needs testing' end it 'can be set with #set_property' do skip 'Needs testing' end it 'can be set with #tab_property=' do skip 'Needs testing' end end it "handles the 'attribute-signal' signal" do skip 'Needs testing' end it "handles the 'doc-empty-arg-parsing' signal" do skip 'Needs testing' end it "handles the 'list-signal' signal" do skip 'Needs testing' end it "handles the 'string-signal' signal" do skip 'Needs testing' end end describe 'Regress::AnnotationStruct' do it 'has a writable field objects' do skip 'Needs testing' 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 skip 'Needs testing' end it 'has the constant FOO_PIE_IS_TASTY' do skip 'Needs testing' end it 'has the constant FOO_SUCCESS_INT' do skip 'Needs testing' end describe 'Regress::FooASingle' do it 'has the member :foo_some_single_enum' do skip 'Needs testing' end end describe 'Regress::FooAddressType' do it 'has the member :invalid' do skip 'Needs testing' end it 'has the member :ipv4' do skip 'Needs testing' end it 'has the member :ipv6' do skip 'Needs testing' end end describe 'Regress::FooBRect' do it 'has a writable field x' do skip 'Needs testing' end it 'has a writable field y' do skip 'Needs testing' end it 'creates an instance using #new' do skip 'Needs testing' end it 'has a working method #add' do skip 'Needs testing' end end describe 'Regress::FooBUnion' do it 'has a writable field type' do skip 'Needs testing' end it 'has a writable field v' do skip 'Needs testing' end it 'has a writable field rect' do skip 'Needs testing' end it 'creates an instance using #new' do skip 'Needs testing' end it 'has a working method #get_contained_type' do skip 'Needs testing' end end describe 'Regress::FooBoxed' do it 'creates an instance using #new' do skip 'Needs testing' end it 'has a working method #method' do skip 'Needs testing' end end describe 'Regress::FooBuffer' do it 'has a working method #some_method' do skip 'Needs testing' end end describe 'Regress::FooDBusData' do it 'has a working method #method' do skip 'Needs testing' end end describe 'Regress::FooEnumFullname' do it 'has the member :one' do skip 'Needs testing' end it 'has the member :two' do skip 'Needs testing' end it 'has the member :three' do skip 'Needs testing' end end describe 'Regress::FooEnumNoType' do it 'has the member :un' do skip 'Needs testing' end it 'has the member :deux' do skip 'Needs testing' end it 'has the member :trois' do skip 'Needs testing' end it 'has the member :neuf' do skip 'Needs testing' end end describe 'Regress::FooEnumType' do it 'has the member :alpha' do skip 'Needs testing' end it 'has the member :beta' do skip 'Needs testing' end it 'has the member :delta' do skip 'Needs testing' end it 'has a working function #method' do skip 'Needs testing' end it 'has a working function #returnv' do skip 'Needs testing' end end describe 'Regress::FooError' do it 'has the member :good' do skip 'Needs testing' end it 'has the member :bad' do skip 'Needs testing' end it 'has the member :ugly' do skip 'Needs testing' end it 'has a working function #quark' do skip 'Needs testing' end end describe 'Regress::FooEvent' do it 'has a writable field type' do skip 'Needs testing' end it 'has a writable field any' do skip 'Needs testing' end it 'has a writable field expose' do skip 'Needs testing' end end describe 'Regress::FooEventAny' do it 'has a writable field send_event' do skip 'Needs testing' end end describe 'Regress::FooEventExpose' do it 'has a writable field send_event' do skip 'Needs testing' end it 'has a writable field count' do skip 'Needs testing' end end describe 'Regress::FooFlagsNoType' do it 'has the member :ett' do skip 'Needs testing' end it 'has the member :tva' do skip 'Needs testing' end it 'has the member :fyra' do skip 'Needs testing' end end describe 'Regress::FooFlagsType' do it 'has the member :first' do skip 'Needs testing' end it 'has the member :second' do skip 'Needs testing' end it 'has the member :third' do skip 'Needs testing' end end describe 'Regress::FooForeignStruct' do it 'has a writable field regress_foo' do skip 'Needs testing' end it 'creates an instance using #new' do skip 'Needs testing' end it 'has a working method #copy' do skip 'Needs testing' end end describe 'Regress::FooInterface' do it 'has a working function #static_method' do skip 'Needs testing' end it 'has a working method #do_regress_foo' do skip 'Needs testing' end end describe 'Regress::FooObject' do it 'creates an instance using #new' do skip 'Needs testing' end it 'creates an instance using #new_as_super' do skip 'Needs testing' end it 'has a working function #a_global_method' do skip 'Needs testing' end it 'has a working function #get_default' do skip 'Needs testing' end it 'has a working function #static_meth' do skip 'Needs testing' end it 'has a working method #append_new_stack_layer' do skip 'Needs testing' end it 'has a working method #dup_name' do skip 'Needs testing' end it 'has a working method #external_type' do skip 'Needs testing' end it 'has a working method #get_name' do skip 'Needs testing' end it 'has a working method #handle_glyph' do skip 'Needs testing' end it 'has a working method #is_it_time_yet' do skip 'Needs testing' end it 'has a working method #read' do skip 'Needs testing' end it 'has a working method #various' do skip 'Needs testing' end it 'has a working method #virtual_method' do skip 'Needs testing' end describe "its 'string' property" do it 'can be retrieved with #get_property' do skip 'Needs testing' end it 'can be retrieved with #string' do skip 'Needs testing' end it 'can be set with #set_property' do skip 'Needs testing' end it 'can be set with #string=' do skip 'Needs testing' end end it "handles the 'signal' signal" do end end describe 'Regress::FooOtherObject' do end describe 'Regress::FooRectangle' do it 'has a writable field x' do skip 'Needs testing' end it 'has a writable field y' do skip 'Needs testing' end it 'has a writable field width' do skip 'Needs testing' end it 'has a writable field height' do skip 'Needs testing' end it 'has a working method #add' do skip 'Needs testing' end end describe 'Regress::FooStackLayer' do it 'has the member :desktop' do skip 'Needs testing' end it 'has the member :bottom' do skip 'Needs testing' end it 'has the member :normal' do skip 'Needs testing' end it 'has the member :top' do skip 'Needs testing' end it 'has the member :dock' do skip 'Needs testing' end it 'has the member :fullscreen' do skip 'Needs testing' end it 'has the member :focused_window' do skip 'Needs testing' end it 'has the member :override_redirect' do skip 'Needs testing' end it 'has the member :last' do skip 'Needs testing' end end describe 'Regress::FooStruct' do it 'has a writable field priv' do skip 'Needs testing' end it 'has a writable field member' do skip 'Needs testing' end end describe 'Regress::FooSubInterface' do it 'has a working method #do_bar' do skip 'Needs testing' end it 'has a working method #do_baz' do skip 'Needs testing' end it "handles the 'destroy-event' signal" do end end describe 'Regress::FooSubobject' do it 'creates an instance using #new' do skip 'Needs testing' end end describe 'Regress::FooThingWithArray' do it 'has a writable field x' do skip 'Needs testing' end it 'has a writable field y' do skip 'Needs testing' end it 'has a writable field lines' do skip 'Needs testing' end it 'has a writable field data' do skip 'Needs testing' end end describe 'Regress::FooUnion' do it 'has a writable field regress_foo' do skip 'Needs testing' end end describe 'Regress::FooUtilityStruct' do it 'has a writable field bar' do skip 'Needs testing' 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 'has a writable field priv' do instance.priv.wont_be_nil other = Regress::TestBoxed.new instance.priv.wont_equal other.priv instance.priv = other.priv instance.priv.must_equal other.priv 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 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, ref_count(@o) 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 # NOTE: Instance methods can only be tested on the subclass, since # TestFundamentalObject is an abstract class. let(:instance) { Regress::TestFundamentalSubObject.new 'foo' } it 'has a working method #ref' do instance.refcount.must_equal 1 instance.ref instance.refcount.must_equal 2 end it 'has a working method #unref' do instance.refcount.must_equal 1 instance.unref 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 let(:instance) { ConcreteDrawable.new } it 'has a working method #do_foo' do instance.do_foo 42 pass end it 'has a working method #do_foo_maybe_throw' do instance.do_foo_maybe_throw 42 proc { instance.do_foo_maybe_throw 41 }.must_raise GirFFI::GLibError end it 'has a working method #get_origin' do instance.get_origin.must_equal [0, 0] end it 'has a working method #get_size' do 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, ref_count(instance) 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_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') ref_count(instance).must_equal 1 instance.instance_method_full ref_count(instance).must_equal 1 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_equal 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' proc { instance.this_is_private }.must_raise NoMethodError proc { instance.this_is_private = 42 }.must_raise NoMethodError 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_equal 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_equal 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 = GirFFI::InOutPointer.from(:gint32, 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 assert_raises(NoMethodError) { instance.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 skip 'Needs testing' end it 'has a working function #annotation_custom_destroy' do skip 'Needs testing' end it 'has a working function #annotation_get_source_file' do skip 'Needs testing' end it 'has a working function #annotation_init' do skip 'Needs testing' end it 'has a working function #annotation_invalid_regress_annotation' do skip 'Needs testing' end it 'has a working function #annotation_ptr_array' do skip 'Needs testing' end it 'has a working function #annotation_return_array' do skip 'Needs testing' end it 'has a working function #annotation_return_filename' do skip 'Needs testing' end it 'has a working function #annotation_set_source_file' do skip 'Needs testing' end it 'has a working function #annotation_space_after_comment_bug631690' do skip 'Needs testing' end it 'has a working function #annotation_string_array_length' do skip 'Needs testing' end it 'has a working function #annotation_string_zero_terminated' do skip 'Needs testing' end it 'has a working function #annotation_string_zero_terminated_out' do skip 'Needs testing' end it 'has a working function #annotation_test_parsing_bug630862' do skip 'Needs testing' end it 'has a working function #annotation_transfer_floating' do skip 'Needs testing' end it 'has a working function #annotation_versioned' do skip 'Needs testing' 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 'Needs testing' end it 'has a working function #foo_destroy_notify_callback' do skip 'Needs testing' end it 'has a working function #foo_enum_type_method' do skip 'Needs testing' end it 'has a working function #foo_enum_type_returnv' do skip 'Needs testing' end it 'has a working function #foo_error_quark' do skip 'Needs testing' end it 'has a working function #foo_init' do skip 'Needs testing' end it 'has a working function #foo_interface_static_method' do skip 'Needs testing' end it 'has a working function #foo_method_external_references' do skip 'Needs testing' end it 'has a working function #foo_not_a_constructor_new' do skip 'Needs testing' end it 'has a working function #foo_test_array' do skip 'Needs testing' end it 'has a working function #foo_test_const_char_param' do skip 'Needs testing' end it 'has a working function #foo_test_const_char_retval' do skip 'Needs testing' end it 'has a working function #foo_test_const_struct_param' do skip 'Needs testing' end it 'has a working function #foo_test_const_struct_retval' do skip 'Needs testing' end it 'has a working function #foo_test_string_array' do skip 'Needs testing' end it 'has a working function #foo_test_string_array_with_g' do skip 'Needs testing' end it 'has a working function #foo_test_unsigned_qualifier' do skip 'Needs testing' end it 'has a working function #foo_test_unsigned_type' do skip 'Needs testing' 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 #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 assert_equal nil, Regress.test_array_int_null_out 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_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_id = nil Regress.test_callback_async { |user_data| stored_id = user_data; a = 2 } result = Regress.test_callback_thaw_async a.must_equal 2 stored_id.wont_be_nil result.must_equal 2 # TODO: See when we can clean up the stored callback for async callbacks. GirFFI::CallbackBase::CALLBACKS[stored_id].wont_be_nil end it 'has a working function #test_callback_destroy_notify' do a = 1 stored_id = nil r1 = Regress.test_callback_destroy_notify { |user_data| stored_id = user_data; a = 2 } a.must_equal 2 GirFFI::CallbackBase::CALLBACKS[stored_id].wont_be_nil 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 } ref_count(obj).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 'Not implemented yet' Regress.test_glist_gtype_container_in %w(1 2 3) 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 assert_equal nil, result 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 assert_equal nil, result 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', nil).get_string.must_equal 'foo' result.lookup_value('timeout', nil).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_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_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 assert_equal nil, Regress.test_utf8_null_out 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' # TODO: Provide versioning info to the end user Regress.test_versioning pass end it 'raises an appropriate NoMethodError when a function is not found' do begin Regress.this_method_does_not_exist rescue => e e.message.must_match(/^undefined method `this_method_does_not_exist' (for Regress:Module|on Regress \(Module\))$/) end end end gir_ffi-0.9.0/test/integration/generated_everything_test.rb0000644000004100000410000002731512654060474024265 0ustar www-datawww-datarequire '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_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_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_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_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.9.0/test/base_test_helper.rb0000644000004100000410000000463712654060474020013 0ustar www-datawww-datarequire '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/rspec_mocks' require 'minitest/autorun' require 'gir_ffi-base' require 'ffi-gobject_introspection' GObjectIntrospection::IRepository.prepend_search_path File.join(File.dirname(__FILE__), 'lib') module GObjectIntrospection class IRepository def shared_library_with_regress(namespace) case namespace when 'Everything', 'GIMarshallingTests', 'Regress', 'Utility', 'WarnLib' return File.join(File.dirname(__FILE__), 'lib', "lib#{namespace.downcase}.so") else return shared_library_without_regress namespace end end alias_method :shared_library_without_regress, :shared_library alias_method :shared_library, :shared_library_with_regress end end 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 Minitest::Test.send :include, Minitest::RSpecMocks gir_ffi-0.9.0/test/ffi-glib/0000755000004100000410000000000012654060474015623 5ustar www-datawww-datagir_ffi-0.9.0/test/ffi-glib/bytes_test.rb0000644000004100000410000000255512654060474020344 0ustar www-datawww-datarequire '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.9.0/test/ffi-glib/main_loop_test.rb0000644000004100000410000000102312654060474021160 0ustar www-datawww-datarequire 'gir_ffi_test_helper' 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 end end gir_ffi-0.9.0/test/ffi-glib/hash_table_test.rb0000644000004100000410000000361612654060474021307 0ustar www-datawww-datarequire '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.9.0/test/ffi-glib/s_list_test.rb0000644000004100000410000000354112654060474020507 0ustar www-datawww-datarequire '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.9.0/test/ffi-glib/array_test.rb0000644000004100000410000001213312654060474020325 0ustar www-datawww-datarequire '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.9.0/test/ffi-glib/list_test.rb0000644000004100000410000000417112654060474020165 0ustar www-datawww-datarequire '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.9.0/test/ffi-glib/strv_test.rb0000644000004100000410000000266512654060474020216 0ustar www-datawww-datarequire '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.9.0/test/ffi-glib/ruby_closure_test.rb0000644000004100000410000000274512654060474021734 0ustar www-datawww-datarequire 'gir_ffi_test_helper' describe GObject::RubyClosure do it 'has a constructor with a mandatory block argument' do assert_raises ArgumentError do GObject::RubyClosure.new end end it 'is a kind of Closure' do c = GObject::RubyClosure.new {} assert_kind_of GObject::Closure, c end it 'is able to retrieve its block from its struct' do a = 0 c = GObject::RubyClosure.new { a = 2 } c2 = GObject::RubyClosure.wrap(c.to_ptr) c2.invoke_block assert_equal 2, a end describe 'its #marshaller singleton method' 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 it 'has GObject::Closure#invoke call its block' do a = 0 c = GObject::RubyClosure.new { a = 2 } c2 = GObject::Closure.wrap(c.to_ptr) c2.invoke nil, nil, nil assert_equal 2, a end end gir_ffi-0.9.0/test/ffi-glib/byte_array_test.rb0000644000004100000410000000071112654060474021347 0ustar www-datawww-datarequire '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.9.0/test/ffi-glib/destroy_notify_test.rb0000644000004100000410000000070412654060474022271 0ustar www-datawww-datarequire '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 user_data = GirFFI::InPointer.from_closure_data dummy_proc.object_id GLib::DestroyNotify.default.call user_data GirFFI::CallbackBase::CALLBACKS[dummy_proc.object_id].must_be_nil end end end gir_ffi-0.9.0/test/ffi-glib/ptr_array_test.rb0000644000004100000410000000521112654060474021211 0ustar www-datawww-datarequire '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.9.0/test/ffi-glib/iconv_test.rb0000644000004100000410000000061312654060474020325 0ustar www-datawww-datarequire '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.9.0/test/ffi-glib/variant_test.rb0000644000004100000410000000034712654060474020657 0ustar www-datawww-datarequire '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.9.0/test/ffi-gobject_test.rb0000644000004100000410000001016512654060474017712 0ustar www-datawww-datarequire '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 assert_raises RuntimeError do GObject.signal_connect(o, 'not-really-a-signal') {} end 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 assert_raises ArgumentError do GObject.signal_connect o, 'test' end 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.9.0/test/minitest/0000755000004100000410000000000012654060474016000 5ustar www-datawww-datagir_ffi-0.9.0/test/minitest/stats_plugin.rb0000644000004100000410000000077612654060474021053 0ustar www-datawww-datamodule 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.9.0/DESIGN.md0000644000004100000410000000647412654060474014473 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.9.0/tasks/0000755000004100000410000000000012654060474014312 5ustar www-datawww-datagir_ffi-0.9.0/tasks/test.rake0000644000004100000410000001274412654060474016145 0ustar www-datawww-datarequire 'rake/testtask' 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', '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 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 gir_ffi-0.9.0/TODO.md0000644000004100000410000001105212654060474014253 0ustar www-datawww-data# TODO ## Miscellaneous * MAKE CONSTRUCTOR_WRAP CHECK TYPES? This would allow GObject::Object.new to work and create the correct subtype for classes that don't define their own default constructor. * Add tests for the other test files in gobject-introspection. Currently, only regress.c and gimarshallingtests.c are used, but there are 6 other files available. * Move GObjectIntrospection to GIRepository, and allow generating its own members. * Do not remove ClassBase.new. We now remove it and then add it back for the default constructor, which is kind of silly. ## 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) - Lower reference count of GObjects (at garbage-collection time) (done!) **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. - Move special types like SizedArray to sane namespaces. Types (like GLib::List) that have actual GLib implementations go to the GLib namespace. Other types go to the GirFFI namespace. ## 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 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. ## 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 ## 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.9.0/README.md0000644000004100000410000000767212654060474014460 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. ## Install gem install gir_ffi ## Requirements GirFFI is tested on CRuby 2.0.0, 2.1, 2.2 and 2.3, JRuby 9.0.0.0, 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 is developed on Debian sid, and tested through Travis CI on Ubuntu 12.04. Older versions of gobject-introspection than the ones used there are therefore not officially supported (although they may work). On Debian and Ubuntu, installing `libgirepository1.0-dev`, `gobject-introspection` and `gir1.2-gtop-2.0` 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 ## 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.