diff options
Diffstat (limited to 'test/fiddle')
| -rw-r--r-- | test/fiddle/helper.rb | 178 | ||||
| -rw-r--r-- | test/fiddle/test_c_struct_builder.rb | 69 | ||||
| -rw-r--r-- | test/fiddle/test_c_struct_entry.rb | 165 | ||||
| -rw-r--r-- | test/fiddle/test_c_union_entity.rb | 36 | ||||
| -rw-r--r-- | test/fiddle/test_closure.rb | 110 | ||||
| -rw-r--r-- | test/fiddle/test_cparser.rb | 374 | ||||
| -rw-r--r-- | test/fiddle/test_fiddle.rb | 17 | ||||
| -rw-r--r-- | test/fiddle/test_func.rb | 139 | ||||
| -rw-r--r-- | test/fiddle/test_function.rb | 227 | ||||
| -rw-r--r-- | test/fiddle/test_handle.rb | 208 | ||||
| -rw-r--r-- | test/fiddle/test_import.rb | 479 | ||||
| -rw-r--r-- | test/fiddle/test_memory_view.rb | 143 | ||||
| -rw-r--r-- | test/fiddle/test_pinned.rb | 28 | ||||
| -rw-r--r-- | test/fiddle/test_pointer.rb | 287 |
14 files changed, 0 insertions, 2460 deletions
diff --git a/test/fiddle/helper.rb b/test/fiddle/helper.rb deleted file mode 100644 index 0ea3bf57f4..0000000000 --- a/test/fiddle/helper.rb +++ /dev/null @@ -1,178 +0,0 @@ -# frozen_string_literal: true - -require 'rbconfig/sizeof' -require 'test/unit' -require 'fiddle' - -# FIXME: this is stolen from DL and needs to be refactored. - -libc_so = libm_so = nil - -case RUBY_PLATFORM -when /cygwin/ - libc_so = "cygwin1.dll" - libm_so = "cygwin1.dll" -when /android/ - libdir = '/system/lib' - if [0].pack('L!').size == 8 - libdir = '/system/lib64' - end - libc_so = File.join(libdir, "libc.so") - libm_so = File.join(libdir, "libm.so") -when /linux-musl/ - Dir.glob('/lib/ld-musl-*.so.1') do |ld| - libc_so = libm_so = ld - end -when /linux/ - libdir = '/lib' - case RbConfig::SIZEOF['void*'] - when 4 - # 32-bit ruby - case RUBY_PLATFORM - when /armv\w+-linux/ - # In the ARM 32-bit libc package such as libc6:armhf libc6:armel, - # libc.so and libm.so are installed to /lib/arm-linux-gnu*. - # It's not installed to /lib32. - dir, = Dir.glob('/lib/arm-linux-gnu*') - libdir = dir if dir && File.directory?(dir) - else - libdir = '/lib32' if File.directory? '/lib32' - end - when 8 - # 64-bit ruby - libdir = '/lib64' if File.directory? '/lib64' - end - - # Handle musl libc - libc_so, = Dir.glob(File.join(libdir, "libc.musl*.so*")) - if libc_so - libm_so = libc_so - else - # glibc - libc_so = "libc.so.6" - libm_so = "libm.so.6" - end -when /mingw/, /mswin/ - require "rbconfig" - crtname = RbConfig::CONFIG["RUBY_SO_NAME"][/msvc\w+/] || 'ucrtbase' - libc_so = libm_so = "#{crtname}.dll" -when /darwin/ - libc_so = libm_so = "/usr/lib/libSystem.B.dylib" - # macOS 11.0+ removed libSystem.B.dylib from /usr/lib. But It works with dlopen. - rigid_path = true -when /kfreebsd/ - libc_so = "/lib/libc.so.0.1" - libm_so = "/lib/libm.so.1" -when /gnu/ #GNU/Hurd - libc_so = "/lib/libc.so.0.3" - libm_so = "/lib/libm.so.6" -when /mirbsd/ - libc_so = "/usr/lib/libc.so.41.10" - libm_so = "/usr/lib/libm.so.7.0" -when /freebsd/ - libc_so = "/lib/libc.so.7" - libm_so = "/lib/libm.so.5" -when /bsd|dragonfly/ - libc_so = "/usr/lib/libc.so" - libm_so = "/usr/lib/libm.so" -when /solaris/ - libdir = '/lib' - case RbConfig::SIZEOF['void*'] - when 4 - # 32-bit ruby - libdir = '/lib' if File.directory? '/lib' - when 8 - # 64-bit ruby - libdir = '/lib/64' if File.directory? '/lib/64' - end - libc_so = File.join(libdir, "libc.so") - libm_so = File.join(libdir, "libm.so") -when /aix/ - pwd=Dir.pwd - libc_so = libm_so = "#{pwd}/libaixdltest.so" - unless File.exist? libc_so - cobjs=%w!strcpy.o! - mobjs=%w!floats.o sin.o! - funcs=%w!sin sinf strcpy strncpy! - expfile='dltest.exp' - require 'tmpdir' - Dir.mktmpdir do |_dir| - begin - Dir.chdir _dir - %x!/usr/bin/ar x /usr/lib/libc.a #{cobjs.join(' ')}! - %x!/usr/bin/ar x /usr/lib/libm.a #{mobjs.join(' ')}! - %x!echo "#{funcs.join("\n")}\n" > #{expfile}! - require 'rbconfig' - if RbConfig::CONFIG["GCC"] = 'yes' - lflag='-Wl,' - else - lflag='' - end - flags="#{lflag}-bE:#{expfile} #{lflag}-bnoentry -lm" - %x!#{RbConfig::CONFIG["LDSHARED"]} -o #{libc_so} #{(cobjs+mobjs).join(' ')} #{flags}! - ensure - Dir.chdir pwd - end - end - end -when /haiku/ - libdir = '/system/lib' - case [0].pack('L!').size - when 4 - # 32-bit ruby - libdir = '/system/lib/x86' if File.directory? '/system/lib/x86' - when 8 - # 64-bit ruby - libdir = '/system/lib/' if File.directory? '/system/lib/' - end - libc_so = File.join(libdir, "libroot.so") - libm_so = File.join(libdir, "libroot.so") -else - libc_so = ARGV[0] if ARGV[0] && ARGV[0][0] == ?/ - libm_so = ARGV[1] if ARGV[1] && ARGV[1][0] == ?/ - if( !(libc_so && libm_so) ) - $stderr.puts("libc and libm not found: #{$0} <libc> <libm>") - end -end - -unless rigid_path - libc_so = nil if libc_so && libc_so[0] == ?/ && !File.file?(libc_so) - libm_so = nil if libm_so && libm_so[0] == ?/ && !File.file?(libm_so) -end - -if !libc_so || !libm_so - ruby = EnvUtil.rubybin - # When the ruby binary is 32-bit and the host is 64-bit, - # `ldd ruby` outputs "not a dynamic executable" message. - # libc_so and libm_so are not set. - ldd = `ldd #{ruby}` - #puts ldd - libc_so = $& if !libc_so && %r{/\S*/libc\.so\S*} =~ ldd - libm_so = $& if !libm_so && %r{/\S*/libm\.so\S*} =~ ldd - #p [libc_so, libm_so] -end - -Fiddle::LIBC_SO = libc_so -Fiddle::LIBM_SO = libm_so - -module Fiddle - class TestCase < Test::Unit::TestCase - def setup - @libc = Fiddle.dlopen(LIBC_SO) - @libm = Fiddle.dlopen(LIBM_SO) - end - - def teardown - if /linux/ =~ RUBY_PLATFORM - GC.start - end - end - - def under_gc_stress - stress, GC.stress = GC.stress, true - yield - ensure - GC.stress = stress - end - end -end diff --git a/test/fiddle/test_c_struct_builder.rb b/test/fiddle/test_c_struct_builder.rb deleted file mode 100644 index ca44c6cf7a..0000000000 --- a/test/fiddle/test_c_struct_builder.rb +++ /dev/null @@ -1,69 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' - require 'fiddle/struct' - require 'fiddle/cparser' - require 'fiddle/import' -rescue LoadError -end - -module Fiddle - class TestCStructBuilder < TestCase - include Fiddle::CParser - extend Fiddle::Importer - - RBasic = struct ['void * flags', - 'void * klass' ] - - - RObject = struct [ - { 'basic' => RBasic }, - { 'as' => union([ - { 'heap'=> struct([ 'uint32_t numiv', - 'void * ivptr', - 'void * iv_index_tbl' ]) }, - 'void *ary[3]' ])} - ] - - - def test_basic_embedded_members - assert_equal 0, RObject.offsetof("basic.flags") - assert_equal Fiddle::SIZEOF_VOIDP, RObject.offsetof("basic.klass") - end - - def test_embedded_union_members - assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as") - assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap") - assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap.numiv") - assert_equal 3 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap.ivptr") - assert_equal 4 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap.iv_index_tbl") - end - - def test_as_ary - assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.ary") - end - - def test_offsetof - types, members = parse_struct_signature(['int64_t i','char c']) - my_struct = Fiddle::CStructBuilder.create(Fiddle::CStruct, types, members) - assert_equal 0, my_struct.offsetof("i") - assert_equal Fiddle::SIZEOF_INT64_T, my_struct.offsetof("c") - end - - def test_offset_with_gap - types, members = parse_struct_signature(['void *p', 'char c', 'long x']) - my_struct = Fiddle::CStructBuilder.create(Fiddle::CStruct, types, members) - - assert_equal PackInfo.align(0, ALIGN_VOIDP), my_struct.offsetof("p") - assert_equal PackInfo.align(SIZEOF_VOIDP, ALIGN_CHAR), my_struct.offsetof("c") - assert_equal SIZEOF_VOIDP + PackInfo.align(SIZEOF_CHAR, ALIGN_LONG), my_struct.offsetof("x") - end - - def test_union_offsetof - types, members = parse_struct_signature(['int64_t i','char c']) - my_struct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members) - assert_equal 0, my_struct.offsetof("i") - assert_equal 0, my_struct.offsetof("c") - end - end -end if defined?(Fiddle) diff --git a/test/fiddle/test_c_struct_entry.rb b/test/fiddle/test_c_struct_entry.rb deleted file mode 100644 index 9fd16d7101..0000000000 --- a/test/fiddle/test_c_struct_entry.rb +++ /dev/null @@ -1,165 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' - require 'fiddle/struct' -rescue LoadError -end - -module Fiddle - class TestCStructEntity < TestCase - def test_class_size - types = [TYPE_DOUBLE, TYPE_CHAR] - - size = CStructEntity.size types - - alignments = types.map { |type| PackInfo::ALIGN_MAP[type] } - - expected = PackInfo.align 0, alignments[0] - expected += PackInfo::SIZE_MAP[TYPE_DOUBLE] - - expected = PackInfo.align expected, alignments[1] - expected += PackInfo::SIZE_MAP[TYPE_CHAR] - - expected = PackInfo.align expected, alignments.max - - assert_equal expected, size - end - - def test_class_size_with_count - size = CStructEntity.size([[TYPE_DOUBLE, 2], [TYPE_CHAR, 20]]) - - types = [TYPE_DOUBLE, TYPE_CHAR] - alignments = types.map { |type| PackInfo::ALIGN_MAP[type] } - - expected = PackInfo.align 0, alignments[0] - expected += PackInfo::SIZE_MAP[TYPE_DOUBLE] * 2 - - expected = PackInfo.align expected, alignments[1] - expected += PackInfo::SIZE_MAP[TYPE_CHAR] * 20 - - expected = PackInfo.align expected, alignments.max - - assert_equal expected, size - end - - def test_set_ctypes - CStructEntity.malloc([TYPE_INT, TYPE_LONG], Fiddle::RUBY_FREE) do |struct| - struct.assign_names %w[int long] - - # this test is roundabout because the stored ctypes are not accessible - struct['long'] = 1 - struct['int'] = 2 - - assert_equal 1, struct['long'] - assert_equal 2, struct['int'] - end - end - - def test_aref_pointer_array - CStructEntity.malloc([[TYPE_VOIDP, 2]], Fiddle::RUBY_FREE) do |team| - team.assign_names(["names"]) - Fiddle::Pointer.malloc(6, Fiddle::RUBY_FREE) do |alice| - alice[0, 6] = "Alice\0" - Fiddle::Pointer.malloc(4, Fiddle::RUBY_FREE) do |bob| - bob[0, 4] = "Bob\0" - team["names"] = [alice, bob] - assert_equal(["Alice", "Bob"], team["names"].map(&:to_s)) - end - end - end - end - - def test_aref_pointer - CStructEntity.malloc([TYPE_VOIDP], Fiddle::RUBY_FREE) do |user| - user.assign_names(["name"]) - Fiddle::Pointer.malloc(6, Fiddle::RUBY_FREE) do |alice| - alice[0, 6] = "Alice\0" - user["name"] = alice - assert_equal("Alice", user["name"].to_s) - end - end - end - - def test_new_double_free - types = [TYPE_INT] - Pointer.malloc(CStructEntity.size(types), Fiddle::RUBY_FREE) do |pointer| - assert_raise ArgumentError do - CStructEntity.new(pointer, types, Fiddle::RUBY_FREE) - end - end - end - - def test_malloc_block - escaped_struct = nil - returned = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) do |struct| - assert_equal Fiddle::SIZEOF_INT, struct.size - assert_equal Fiddle::RUBY_FREE, struct.free.to_i - escaped_struct = struct - :returned - end - assert_equal :returned, returned - assert escaped_struct.freed? - end - - def test_malloc_block_no_free - assert_raise ArgumentError do - CStructEntity.malloc([TYPE_INT]) { |struct| } - end - end - - def test_free - struct = CStructEntity.malloc([TYPE_INT]) - begin - assert_nil struct.free - ensure - Fiddle.free struct - end - end - - def test_free_with_func - struct = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) - refute struct.freed? - struct.call_free - assert struct.freed? - struct.call_free # you can safely run it again - assert struct.freed? - GC.start # you can safely run the GC routine - assert struct.freed? - end - - def test_free_with_no_func - struct = CStructEntity.malloc([TYPE_INT]) - refute struct.freed? - struct.call_free - refute struct.freed? - struct.call_free # you can safely run it again - refute struct.freed? - end - - def test_freed? - struct = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) - refute struct.freed? - struct.call_free - assert struct.freed? - end - - def test_null? - struct = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) - refute struct.null? - end - - def test_size - CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) do |struct| - assert_equal Fiddle::SIZEOF_INT, struct.size - end - end - - def test_size= - CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) do |struct| - assert_raise NoMethodError do - struct.size = 1 - end - end - end - end -end if defined?(Fiddle) diff --git a/test/fiddle/test_c_union_entity.rb b/test/fiddle/test_c_union_entity.rb deleted file mode 100644 index e0a3757562..0000000000 --- a/test/fiddle/test_c_union_entity.rb +++ /dev/null @@ -1,36 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' - require 'fiddle/struct' -rescue LoadError -end - - -module Fiddle - class TestCUnionEntity < TestCase - def test_class_size - size = CUnionEntity.size([TYPE_DOUBLE, TYPE_CHAR]) - - assert_equal SIZEOF_DOUBLE, size - end - - def test_class_size_with_count - size = CUnionEntity.size([[TYPE_DOUBLE, 2], [TYPE_CHAR, 20]]) - - assert_equal SIZEOF_CHAR * 20, size - end - - def test_set_ctypes - CUnionEntity.malloc([TYPE_INT, TYPE_LONG], Fiddle::RUBY_FREE) do |union| - union.assign_names %w[int long] - - # this test is roundabout because the stored ctypes are not accessible - union['long'] = 1 - assert_equal 1, union['long'] - - union['int'] = 1 - assert_equal 1, union['int'] - end - end - end -end if defined?(Fiddle) diff --git a/test/fiddle/test_closure.rb b/test/fiddle/test_closure.rb deleted file mode 100644 index 9e748bf5ee..0000000000 --- a/test/fiddle/test_closure.rb +++ /dev/null @@ -1,110 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' -rescue LoadError -end - -module Fiddle - class TestClosure < Fiddle::TestCase - def test_argument_errors - assert_raise(TypeError) do - Closure.new(TYPE_INT, TYPE_INT) - end - - assert_raise(TypeError) do - Closure.new('foo', [TYPE_INT]) - end - - assert_raise(TypeError) do - Closure.new(TYPE_INT, ['meow!']) - end - end - - def test_type_symbol - closure = Closure.new(:int, [:void]) - assert_equal([ - TYPE_INT, - [TYPE_VOID], - ], - [ - closure.instance_variable_get(:@ctype), - closure.instance_variable_get(:@args), - ]) - end - - def test_call - closure = Class.new(Closure) { - def call - 10 - end - }.new(TYPE_INT, []) - - func = Function.new(closure, [], TYPE_INT) - assert_equal 10, func.call - end - - def test_returner - closure = Class.new(Closure) { - def call thing - thing - end - }.new(TYPE_INT, [TYPE_INT]) - - func = Function.new(closure, [TYPE_INT], TYPE_INT) - assert_equal 10, func.call(10) - end - - def test_const_string - closure_class = Class.new(Closure) do - def call(string) - @return_string = "Hello! #{string}" - @return_string - end - end - closure = closure_class.new(:const_string, [:const_string]) - - func = Function.new(closure, [:const_string], :const_string) - assert_equal("Hello! World!", func.call("World!")) - end - - def test_block_caller - cb = Closure::BlockCaller.new(TYPE_INT, [TYPE_INT]) do |one| - one - end - func = Function.new(cb, [TYPE_INT], TYPE_INT) - assert_equal 11, func.call(11) - end - - def test_memsize - require 'objspace' - bug = '[ruby-dev:42480]' - n = 10000 - assert_equal(n, n.times {ObjectSpace.memsize_of(Closure.allocate)}, bug) - end - - %w[INT SHORT CHAR LONG LONG_LONG].each do |name| - type = Fiddle.const_get("TYPE_#{name}") rescue next - size = Fiddle.const_get("SIZEOF_#{name}") - [[type, size-1, name], [-type, size, "unsigned_"+name]].each do |t, s, n| - define_method("test_conversion_#{n.downcase}") do - arg = nil - - clos = Class.new(Closure) do - define_method(:call) {|x| arg = x} - end.new(t, [t]) - - v = ~(~0 << (8*s)) - - arg = nil - assert_equal(v, clos.call(v)) - assert_equal(arg, v, n) - - arg = nil - func = Function.new(clos, [t], t) - assert_equal(v, func.call(v)) - assert_equal(arg, v, n) - end - end - end - end -end if defined?(Fiddle) diff --git a/test/fiddle/test_cparser.rb b/test/fiddle/test_cparser.rb deleted file mode 100644 index ae319197a4..0000000000 --- a/test/fiddle/test_cparser.rb +++ /dev/null @@ -1,374 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' - require 'fiddle/cparser' - require 'fiddle/import' -rescue LoadError -end - -module Fiddle - class TestCParser < TestCase - include CParser - - def test_char_ctype - assert_equal(TYPE_CHAR, parse_ctype('char')) - assert_equal(TYPE_CHAR, parse_ctype('const char')) - assert_equal(TYPE_CHAR, parse_ctype('signed char')) - assert_equal(TYPE_CHAR, parse_ctype('const signed char')) - assert_equal(-TYPE_CHAR, parse_ctype('unsigned char')) - assert_equal(-TYPE_CHAR, parse_ctype('const unsigned char')) - end - - def test_short_ctype - assert_equal(TYPE_SHORT, parse_ctype('short')) - assert_equal(TYPE_SHORT, parse_ctype('const short')) - assert_equal(TYPE_SHORT, parse_ctype('short int')) - assert_equal(TYPE_SHORT, parse_ctype('const short int')) - assert_equal(TYPE_SHORT, parse_ctype('signed short')) - assert_equal(TYPE_SHORT, parse_ctype('const signed short')) - assert_equal(TYPE_SHORT, parse_ctype('signed short int')) - assert_equal(TYPE_SHORT, parse_ctype('const signed short int')) - assert_equal(-TYPE_SHORT, parse_ctype('unsigned short')) - assert_equal(-TYPE_SHORT, parse_ctype('const unsigned short')) - assert_equal(-TYPE_SHORT, parse_ctype('unsigned short int')) - assert_equal(-TYPE_SHORT, parse_ctype('const unsigned short int')) - end - - def test_int_ctype - assert_equal(TYPE_INT, parse_ctype('int')) - assert_equal(TYPE_INT, parse_ctype('const int')) - assert_equal(TYPE_INT, parse_ctype('signed int')) - assert_equal(TYPE_INT, parse_ctype('const signed int')) - assert_equal(-TYPE_INT, parse_ctype('uint')) - assert_equal(-TYPE_INT, parse_ctype('const uint')) - assert_equal(-TYPE_INT, parse_ctype('unsigned int')) - assert_equal(-TYPE_INT, parse_ctype('const unsigned int')) - end - - def test_long_ctype - assert_equal(TYPE_LONG, parse_ctype('long')) - assert_equal(TYPE_LONG, parse_ctype('const long')) - assert_equal(TYPE_LONG, parse_ctype('long int')) - assert_equal(TYPE_LONG, parse_ctype('const long int')) - assert_equal(TYPE_LONG, parse_ctype('signed long')) - assert_equal(TYPE_LONG, parse_ctype('const signed long')) - assert_equal(TYPE_LONG, parse_ctype('signed long int')) - assert_equal(TYPE_LONG, parse_ctype('const signed long int')) - assert_equal(-TYPE_LONG, parse_ctype('unsigned long')) - assert_equal(-TYPE_LONG, parse_ctype('const unsigned long')) - assert_equal(-TYPE_LONG, parse_ctype('unsigned long int')) - assert_equal(-TYPE_LONG, parse_ctype('const unsigned long int')) - end - - def test_size_t_ctype - assert_equal(TYPE_SIZE_T, parse_ctype("size_t")) - assert_equal(TYPE_SIZE_T, parse_ctype("const size_t")) - end - - def test_ssize_t_ctype - assert_equal(TYPE_SSIZE_T, parse_ctype("ssize_t")) - assert_equal(TYPE_SSIZE_T, parse_ctype("const ssize_t")) - end - - def test_ptrdiff_t_ctype - assert_equal(TYPE_PTRDIFF_T, parse_ctype("ptrdiff_t")) - assert_equal(TYPE_PTRDIFF_T, parse_ctype("const ptrdiff_t")) - end - - def test_intptr_t_ctype - assert_equal(TYPE_INTPTR_T, parse_ctype("intptr_t")) - assert_equal(TYPE_INTPTR_T, parse_ctype("const intptr_t")) - end - - def test_uintptr_t_ctype - assert_equal(TYPE_UINTPTR_T, parse_ctype("uintptr_t")) - assert_equal(TYPE_UINTPTR_T, parse_ctype("const uintptr_t")) - end - - def test_undefined_ctype - assert_raise(DLError) { parse_ctype('DWORD') } - end - - def test_undefined_ctype_with_type_alias - assert_equal(-TYPE_LONG, - parse_ctype('DWORD', {"DWORD" => "unsigned long"})) - assert_equal(-TYPE_LONG, - parse_ctype('const DWORD', {"DWORD" => "unsigned long"})) - end - - def expand_struct_types(types) - types.collect do |type| - case type - when Class - [expand_struct_types(type.types)] - when Array - [expand_struct_types([type[0]])[0][0], type[1]] - else - type - end - end - end - - def test_struct_basic - assert_equal([[TYPE_INT, TYPE_CHAR], ['i', 'c']], - parse_struct_signature(['int i', 'char c'])) - assert_equal([[TYPE_INT, TYPE_CHAR], ['i', 'c']], - parse_struct_signature(['const int i', 'const char c'])) - end - - def test_struct_array - assert_equal([[[TYPE_CHAR, 80], [TYPE_INT, 5]], - ['buffer', 'x']], - parse_struct_signature(['char buffer[80]', - 'int[5] x'])) - assert_equal([[[TYPE_CHAR, 80], [TYPE_INT, 5]], - ['buffer', 'x']], - parse_struct_signature(['const char buffer[80]', - 'const int[5] x'])) - end - - def test_struct_nested_struct - types, members = parse_struct_signature([ - 'int x', - {inner: ['int i', 'char c']}, - ]) - assert_equal([[TYPE_INT, [[TYPE_INT, TYPE_CHAR]]], - ['x', ['inner', ['i', 'c']]]], - [expand_struct_types(types), - members]) - end - - def test_struct_nested_defined_struct - inner = Fiddle::Importer.struct(['int i', 'char c']) - assert_equal([[TYPE_INT, inner], - ['x', ['inner', ['i', 'c']]]], - parse_struct_signature([ - 'int x', - {inner: inner}, - ])) - end - - def test_struct_double_nested_struct - types, members = parse_struct_signature([ - 'int x', - { - outer: [ - 'int y', - {inner: ['int i', 'char c']}, - ], - }, - ]) - assert_equal([[TYPE_INT, [[TYPE_INT, [[TYPE_INT, TYPE_CHAR]]]]], - ['x', ['outer', ['y', ['inner', ['i', 'c']]]]]], - [expand_struct_types(types), - members]) - end - - def test_struct_nested_struct_array - types, members = parse_struct_signature([ - 'int x', - { - 'inner[2]' => [ - 'int i', - 'char c', - ], - }, - ]) - assert_equal([[TYPE_INT, [[TYPE_INT, TYPE_CHAR], 2]], - ['x', ['inner', ['i', 'c']]]], - [expand_struct_types(types), - members]) - end - - def test_struct_double_nested_struct_inner_array - types, members = parse_struct_signature(outer: [ - 'int x', - { - 'inner[2]' => [ - 'int i', - 'char c', - ], - }, - ]) - assert_equal([[[[TYPE_INT, [[TYPE_INT, TYPE_CHAR], 2]]]], - [['outer', ['x', ['inner', ['i', 'c']]]]]], - [expand_struct_types(types), - members]) - end - - def test_struct_double_nested_struct_outer_array - types, members = parse_struct_signature([ - 'int x', - { - 'outer[2]' => { - inner: [ - 'int i', - 'char c', - ], - }, - }, - ]) - assert_equal([[TYPE_INT, [[[[TYPE_INT, TYPE_CHAR]]], 2]], - ['x', ['outer', [['inner', ['i', 'c']]]]]], - [expand_struct_types(types), - members]) - end - - def test_struct_array_str - assert_equal([[[TYPE_CHAR, 80], [TYPE_INT, 5]], - ['buffer', 'x']], - parse_struct_signature('char buffer[80], int[5] x')) - assert_equal([[[TYPE_CHAR, 80], [TYPE_INT, 5]], - ['buffer', 'x']], - parse_struct_signature('const char buffer[80], const int[5] x')) - end - - def test_struct_function_pointer - assert_equal([[TYPE_VOIDP], ['cb']], - parse_struct_signature(['void (*cb)(const char*)'])) - end - - def test_struct_function_pointer_str - assert_equal([[TYPE_VOIDP, TYPE_VOIDP], ['cb', 'data']], - parse_struct_signature('void (*cb)(const char*), const char* data')) - end - - def test_struct_string - assert_equal [[TYPE_INT,TYPE_VOIDP,TYPE_VOIDP], ['x', 'cb', 'name']], parse_struct_signature('int x; void (*cb)(); const char* name') - end - - def test_struct_undefined - assert_raise(DLError) { parse_struct_signature(['int i', 'DWORD cb']) } - end - - def test_struct_undefined_with_type_alias - assert_equal [[TYPE_INT,-TYPE_LONG], ['i', 'cb']], parse_struct_signature(['int i', 'DWORD cb'], {"DWORD" => "unsigned long"}) - end - - def test_signature_basic - func, ret, args = parse_signature('void func()') - assert_equal 'func', func - assert_equal TYPE_VOID, ret - assert_equal [], args - end - - def test_signature_semi - func, ret, args = parse_signature('void func();') - assert_equal 'func', func - assert_equal TYPE_VOID, ret - assert_equal [], args - end - - def test_signature_void_arg - func, ret, args = parse_signature('void func(void)') - assert_equal 'func', func - assert_equal TYPE_VOID, ret - assert_equal [], args - end - - def test_signature_type_args - types = [ - 'char', 'unsigned char', - 'short', 'unsigned short', - 'int', 'unsigned int', - 'long', 'unsigned long', - defined?(TYPE_LONG_LONG) && \ - [ - 'long long', 'unsigned long long', - ], - 'float', 'double', - 'const char*', 'void*', - ].flatten.compact - func, ret, args = parse_signature("void func(#{types.join(',')})") - assert_equal 'func', func - assert_equal TYPE_VOID, ret - assert_equal [ - TYPE_CHAR, -TYPE_CHAR, - TYPE_SHORT, -TYPE_SHORT, - TYPE_INT, -TYPE_INT, - TYPE_LONG, -TYPE_LONG, - defined?(TYPE_LONG_LONG) && \ - [ - TYPE_LONG_LONG, -TYPE_LONG_LONG, - ], - TYPE_FLOAT, TYPE_DOUBLE, - TYPE_VOIDP, TYPE_VOIDP, - ].flatten.compact, args - end - - def test_signature_single_variable - func, ret, args = parse_signature('void func(int x)') - assert_equal 'func', func - assert_equal TYPE_VOID, ret - assert_equal [TYPE_INT], args - end - - def test_signature_multiple_variables - func, ret, args = parse_signature('void func(int x, const char* s)') - assert_equal 'func', func - assert_equal TYPE_VOID, ret - assert_equal [TYPE_INT, TYPE_VOIDP], args - end - - def test_signature_array_variable - func, ret, args = parse_signature('void func(int x[], int y[40])') - assert_equal 'func', func - assert_equal TYPE_VOID, ret - assert_equal [TYPE_VOIDP, TYPE_VOIDP], args - end - - def test_signature_function_pointer - func, ret, args = parse_signature('int func(int (*sum)(int x, int y), int x, int y)') - assert_equal 'func', func - assert_equal TYPE_INT, ret - assert_equal [TYPE_VOIDP, TYPE_INT, TYPE_INT], args - end - - def test_signature_variadic_arguments - unless Fiddle.const_defined?("TYPE_VARIADIC") - omit "libffi doesn't support variadic arguments" - end - assert_equal([ - "printf", - TYPE_INT, - [TYPE_VOIDP, TYPE_VARIADIC], - ], - parse_signature('int printf(const char *format, ...)')) - end - - def test_signature_return_pointer - func, ret, args = parse_signature('void* malloc(size_t)') - assert_equal 'malloc', func - assert_equal TYPE_VOIDP, ret - assert_equal [TYPE_SIZE_T], args - end - - def test_signature_return_array - func, ret, args = parse_signature('int (*func())[32]') - assert_equal 'func', func - assert_equal TYPE_VOIDP, ret - assert_equal [], args - end - - def test_signature_return_array_with_args - func, ret, args = parse_signature('int (*func(const char* s))[]') - assert_equal 'func', func - assert_equal TYPE_VOIDP, ret - assert_equal [TYPE_VOIDP], args - end - - def test_signature_return_function_pointer - func, ret, args = parse_signature('int (*func())(int x, int y)') - assert_equal 'func', func - assert_equal TYPE_VOIDP, ret - assert_equal [], args - end - - def test_signature_return_function_pointer_with_args - func, ret, args = parse_signature('int (*func(int z))(int x, int y)') - assert_equal 'func', func - assert_equal TYPE_VOIDP, ret - assert_equal [TYPE_INT], args - end - end -end if defined?(Fiddle) diff --git a/test/fiddle/test_fiddle.rb b/test/fiddle/test_fiddle.rb deleted file mode 100644 index 8751d96920..0000000000 --- a/test/fiddle/test_fiddle.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' -rescue LoadError -end - -class TestFiddle < Fiddle::TestCase - def test_windows_constant - require 'rbconfig' - if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ - assert Fiddle::WINDOWS, "Fiddle::WINDOWS should be 'true' on Windows platforms" - else - refute Fiddle::WINDOWS, "Fiddle::WINDOWS should be 'false' on non-Windows platforms" - end - end - -end if defined?(Fiddle) diff --git a/test/fiddle/test_func.rb b/test/fiddle/test_func.rb deleted file mode 100644 index 44893017e8..0000000000 --- a/test/fiddle/test_func.rb +++ /dev/null @@ -1,139 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' -rescue LoadError -end - -module Fiddle - class TestFunc < TestCase - def test_random - f = Function.new(@libc['srand'], [-TYPE_LONG], TYPE_VOID) - assert_nil f.call(10) - end - - def test_sinf - begin - f = Function.new(@libm['sinf'], [TYPE_FLOAT], TYPE_FLOAT) - rescue Fiddle::DLError - omit "libm may not have sinf()" - end - assert_in_delta 1.0, f.call(90 * Math::PI / 180), 0.0001 - end - - def test_sin - f = Function.new(@libm['sin'], [TYPE_DOUBLE], TYPE_DOUBLE) - assert_in_delta 1.0, f.call(90 * Math::PI / 180), 0.0001 - end - - def test_string - under_gc_stress do - f = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP) - buff = +"000" - str = f.call(buff, "123") - assert_equal("123", buff) - assert_equal("123", str.to_s) - end - end - - def test_isdigit - f = Function.new(@libc['isdigit'], [TYPE_INT], TYPE_INT) - r1 = f.call(?1.ord) - r2 = f.call(?2.ord) - rr = f.call(?r.ord) - assert_operator r1, :>, 0 - assert_operator r2, :>, 0 - assert_equal 0, rr - end - - def test_atof - f = Function.new(@libc['atof'], [TYPE_VOIDP], TYPE_DOUBLE) - r = f.call("12.34") - assert_includes(12.00..13.00, r) - end - - def test_strtod - f = Function.new(@libc['strtod'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_DOUBLE) - buff1 = Pointer["12.34"] - buff2 = buff1 + 4 - r = f.call(buff1, - buff2) - assert_in_delta(12.34, r, 0.001) - end - - def test_qsort1 - cb = Class.new(Closure) { - def call(x, y) - Pointer.new(x)[0] <=> Pointer.new(y)[0] - end - }.new(TYPE_INT, [TYPE_VOIDP, TYPE_VOIDP]) - - qsort = Function.new(@libc['qsort'], - [TYPE_VOIDP, TYPE_SIZE_T, TYPE_SIZE_T, TYPE_VOIDP], - TYPE_VOID) - buff = "9341" - qsort.call(buff, buff.size, 1, cb) - assert_equal("1349", buff) - - bug4929 = '[ruby-core:37395]' - buff = "9341" - under_gc_stress do - qsort.call(buff, buff.size, 1, cb) - end - assert_equal("1349", buff, bug4929) - end - - def test_snprintf - unless Fiddle.const_defined?("TYPE_VARIADIC") - omit "libffi doesn't support variadic arguments" - end - if Fiddle::WINDOWS - snprintf_name = "_snprintf" - else - snprintf_name = "snprintf" - end - begin - snprintf_pointer = @libc[snprintf_name] - rescue Fiddle::DLError - omit "Can't find #{snprintf_name}: #{$!.message}" - end - snprintf = Function.new(snprintf_pointer, - [ - :voidp, - :size_t, - :const_string, - :variadic, - ], - :int) - output_buffer = " " * 1024 - output = Pointer[output_buffer] - - written = snprintf.call(output, - output.size, - "int: %d, string: %.*s, const string: %s\n", - :int, -29, - :int, 4, - :voidp, "Hello", - :const_string, "World") - assert_equal("int: -29, string: Hell, const string: World\n", - output_buffer[0, written]) - - string_like_class = Class.new do - def initialize(string) - @string = string - end - - def to_str - @string - end - end - written = snprintf.call(output, - output.size, - "string: %.*s, const string: %s, uint: %u\n", - :int, 2, - :voidp, "Hello", - :const_string, string_like_class.new("World"), - :int, 29) - assert_equal("string: He, const string: World, uint: 29\n", - output_buffer[0, written]) - end - end -end if defined?(Fiddle) diff --git a/test/fiddle/test_function.rb b/test/fiddle/test_function.rb deleted file mode 100644 index 8ac4f60aa3..0000000000 --- a/test/fiddle/test_function.rb +++ /dev/null @@ -1,227 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' -rescue LoadError -end - -module Fiddle - class TestFunction < Fiddle::TestCase - def setup - super - Fiddle.last_error = nil - if WINDOWS - Fiddle.win32_last_error = nil - Fiddle.win32_last_socket_error = nil - end - end - - def test_default_abi - func = Function.new(@libm['sin'], [TYPE_DOUBLE], TYPE_DOUBLE) - assert_equal Function::DEFAULT, func.abi - end - - def test_name - func = Function.new(@libm['sin'], [TYPE_DOUBLE], TYPE_DOUBLE, name: 'sin') - assert_equal 'sin', func.name - end - - def test_need_gvl? - libruby = Fiddle.dlopen(nil) - rb_str_dup = Function.new(libruby['rb_str_dup'], - [:voidp], - :voidp, - need_gvl: true) - assert(rb_str_dup.need_gvl?) - assert_equal('Hello', - Fiddle.dlunwrap(rb_str_dup.call(Fiddle.dlwrap('Hello')))) - end - - def test_argument_errors - assert_raise(TypeError) do - Function.new(@libm['sin'], TYPE_DOUBLE, TYPE_DOUBLE) - end - - assert_raise(TypeError) do - Function.new(@libm['sin'], ['foo'], TYPE_DOUBLE) - end - - assert_raise(TypeError) do - Function.new(@libm['sin'], [TYPE_DOUBLE], 'foo') - end - end - - def test_argument_type_conversion - type = Struct.new(:int, :call_count) do - def initialize(int) - super(int, 0) - end - def to_int - raise "exhausted" if (self.call_count += 1) > 1 - self.int - end - end - type_arg = type.new(TYPE_DOUBLE) - type_result = type.new(TYPE_DOUBLE) - assert_nothing_raised(RuntimeError) do - Function.new(@libm['sin'], [type_arg], type_result) - end - assert_equal(1, type_arg.call_count) - assert_equal(1, type_result.call_count) - end - - def test_call - func = Function.new(@libm['sin'], [TYPE_DOUBLE], TYPE_DOUBLE) - assert_in_delta 1.0, func.call(90 * Math::PI / 180), 0.0001 - end - - def test_argument_count - closure = Class.new(Closure) { - def call one - 10 + one - end - }.new(TYPE_INT, [TYPE_INT]) - func = Function.new(closure, [TYPE_INT], TYPE_INT) - - assert_raise(ArgumentError) do - func.call(1,2,3) - end - assert_raise(ArgumentError) do - func.call - end - end - - def test_last_error - func = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP) - - assert_nil Fiddle.last_error - func.call(+"000", "123") - refute_nil Fiddle.last_error - end - - if WINDOWS - def test_win32_last_error - kernel32 = Fiddle.dlopen("kernel32") - args = [kernel32["SetLastError"], [-TYPE_LONG], TYPE_VOID] - args << Function::STDCALL if Function.const_defined?(:STDCALL) - set_last_error = Function.new(*args) - assert_nil(Fiddle.win32_last_error) - n = 1 << 29 | 1 - set_last_error.call(n) - assert_equal(n, Fiddle.win32_last_error) - end - - def test_win32_last_socket_error - ws2_32 = Fiddle.dlopen("ws2_32") - args = [ws2_32["WSASetLastError"], [TYPE_INT], TYPE_VOID] - args << Function::STDCALL if Function.const_defined?(:STDCALL) - wsa_set_last_error = Function.new(*args) - assert_nil(Fiddle.win32_last_socket_error) - n = 1 << 29 | 1 - wsa_set_last_error.call(n) - assert_equal(n, Fiddle.win32_last_socket_error) - end - end - - def test_strcpy - f = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP) - buff = +"000" - str = f.call(buff, "123") - assert_equal("123", buff) - assert_equal("123", str.to_s) - end - - def call_proc(string_to_copy) - buff = +"000" - str = yield(buff, string_to_copy) - [buff, str] - end - - def test_function_as_proc - f = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP) - buff, str = call_proc("123", &f) - assert_equal("123", buff) - assert_equal("123", str.to_s) - end - - def test_function_as_method - f = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP) - klass = Class.new do - define_singleton_method(:strcpy, &f) - end - buff = +"000" - str = klass.strcpy(buff, "123") - assert_equal("123", buff) - assert_equal("123", str.to_s) - end - - def test_nogvl_poll - # XXX hack to quiet down CI errors on EINTR from r64353 - # [ruby-core:88360] [Misc #14937] - # Making pipes (and sockets) non-blocking by default would allow - # us to get rid of POSIX timers / timer pthread - # https://bugs.ruby-lang.org/issues/14968 - IO.pipe { |r,w| IO.select([r], [w]) } - begin - poll = @libc['poll'] - rescue Fiddle::DLError - omit 'poll(2) not available' - end - f = Function.new(poll, [TYPE_VOIDP, TYPE_INT, TYPE_INT], TYPE_INT) - - msec = 200 - t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) - th = Thread.new { f.call(nil, 0, msec) } - n1 = f.call(nil, 0, msec) - n2 = th.value - t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) - assert_in_delta(msec, t1 - t0, 180, 'slept amount of time') - assert_equal(0, n1, perror("poll(2) in main-thread")) - assert_equal(0, n2, perror("poll(2) in sub-thread")) - end - - def test_no_memory_leak - if respond_to?(:assert_nothing_leaked_memory) - rb_obj_frozen_p_symbol = Fiddle.dlopen(nil)["rb_obj_frozen_p"] - rb_obj_frozen_p = Fiddle::Function.new(rb_obj_frozen_p_symbol, - [Fiddle::TYPE_UINTPTR_T], - Fiddle::TYPE_UINTPTR_T) - a = "a" - n_tries = 100_000 - n_tries.times do - begin - a + 1 - rescue TypeError - end - end - n_arguments = 1 - sizeof_fiddle_generic = Fiddle::SIZEOF_VOIDP # Rough - size_per_try = - (sizeof_fiddle_generic * n_arguments) + - (Fiddle::SIZEOF_VOIDP * (n_arguments + 1)) - assert_nothing_leaked_memory(size_per_try * n_tries) do - n_tries.times do - begin - rb_obj_frozen_p.call(a) - rescue TypeError - end - end - end - else - prep = 'r = Fiddle::Function.new(Fiddle.dlopen(nil)["rb_obj_frozen_p"], [Fiddle::TYPE_UINTPTR_T], Fiddle::TYPE_UINTPTR_T); a = "a"' - code = 'begin r.call(a); rescue TypeError; end' - assert_no_memory_leak(%w[-W0 -rfiddle], "#{prep}\n1000.times{#{code}}", "10_000.times {#{code}}", limit: 1.2) - end - end - - private - - def perror(m) - proc do - if e = Fiddle.last_error - m = "#{m}: #{SystemCallError.new(e).message}" - end - m - end - end - end -end if defined?(Fiddle) diff --git a/test/fiddle/test_handle.rb b/test/fiddle/test_handle.rb deleted file mode 100644 index 7e3ff9d844..0000000000 --- a/test/fiddle/test_handle.rb +++ /dev/null @@ -1,208 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' -rescue LoadError -end - -module Fiddle - class TestHandle < TestCase - include Fiddle - - def test_to_i - handle = Fiddle::Handle.new(LIBC_SO) - assert_kind_of Integer, handle.to_i - end - - def test_to_ptr - handle = Fiddle::Handle.new(LIBC_SO) - ptr = handle.to_ptr - assert_equal ptr.to_i, handle.to_i - end - - def test_static_sym_unknown - assert_raise(DLError) { Fiddle::Handle.sym('fooo') } - assert_raise(DLError) { Fiddle::Handle['fooo'] } - end - - def test_static_sym - begin - # Linux / Darwin / FreeBSD - refute_nil Fiddle::Handle.sym('dlopen') - assert_equal Fiddle::Handle.sym('dlopen'), Fiddle::Handle['dlopen'] - return - rescue - end - - begin - # NetBSD - require '-test-/dln/empty' - refute_nil Fiddle::Handle.sym('Init_empty') - assert_equal Fiddle::Handle.sym('Init_empty'), Fiddle::Handle['Init_empty'] - return - rescue - end - end unless /mswin|mingw/ =~ RUBY_PLATFORM - - def test_sym_closed_handle - handle = Fiddle::Handle.new(LIBC_SO) - handle.close - assert_raise(DLError) { handle.sym("calloc") } - assert_raise(DLError) { handle["calloc"] } - end - - def test_sym_unknown - handle = Fiddle::Handle.new(LIBC_SO) - assert_raise(DLError) { handle.sym('fooo') } - assert_raise(DLError) { handle['fooo'] } - end - - def test_sym_with_bad_args - handle = Handle.new(LIBC_SO) - assert_raise(TypeError) { handle.sym(nil) } - assert_raise(TypeError) { handle[nil] } - end - - def test_sym - handle = Handle.new(LIBC_SO) - refute_nil handle.sym('calloc') - refute_nil handle['calloc'] - end - - def test_handle_close - handle = Handle.new(LIBC_SO) - assert_equal 0, handle.close - end - - def test_handle_close_twice - handle = Handle.new(LIBC_SO) - handle.close - assert_raise(DLError) do - handle.close - end - end - - def test_dlopen_returns_handle - assert_instance_of Handle, dlopen(LIBC_SO) - end - - def test_initialize_noargs - handle = Handle.new - refute_nil handle['rb_str_new'] - end - - def test_initialize_flags - handle = Handle.new(LIBC_SO, RTLD_LAZY | RTLD_GLOBAL) - refute_nil handle['calloc'] - end - - def test_enable_close - handle = Handle.new(LIBC_SO) - assert !handle.close_enabled?, 'close is enabled' - - handle.enable_close - assert handle.close_enabled?, 'close is not enabled' - end - - def test_disable_close - handle = Handle.new(LIBC_SO) - - handle.enable_close - assert handle.close_enabled?, 'close is enabled' - handle.disable_close - assert !handle.close_enabled?, 'close is enabled' - end - - def test_file_name - file_name = Handle.new(LIBC_SO).file_name - if file_name - assert_kind_of String, file_name - expected = [File.basename(LIBC_SO)] - begin - expected << File.basename(File.realpath(LIBC_SO, File.dirname(file_name))) - rescue Errno::ENOENT - end - basename = File.basename(file_name) - unless File::FNM_SYSCASE.zero? - basename.downcase! - expected.each(&:downcase!) - end - assert_include expected, basename - end - end - - def test_NEXT - begin - # Linux / Darwin - # - # There are two special pseudo-handles, RTLD_DEFAULT and RTLD_NEXT. The former will find - # the first occurrence of the desired symbol using the default library search order. The - # latter will find the next occurrence of a function in the search order after the current - # library. This allows one to provide a wrapper around a function in another shared - # library. - # --- Ubuntu Linux 8.04 dlsym(3) - handle = Handle::NEXT - refute_nil handle['malloc'] - return - rescue - end - - begin - # BSD - # - # If dlsym() is called with the special handle RTLD_NEXT, then the search - # for the symbol is limited to the shared objects which were loaded after - # the one issuing the call to dlsym(). Thus, if the function is called - # from the main program, all the shared libraries are searched. If it is - # called from a shared library, all subsequent shared libraries are - # searched. RTLD_NEXT is useful for implementing wrappers around library - # functions. For example, a wrapper function getpid() could access the - # "real" getpid() with dlsym(RTLD_NEXT, "getpid"). (Actually, the dlfunc() - # interface, below, should be used, since getpid() is a function and not a - # data object.) - # --- FreeBSD 8.0 dlsym(3) - require '-test-/dln/empty' - handle = Handle::NEXT - refute_nil handle['Init_empty'] - return - rescue - end - end unless /mswin|mingw/ =~ RUBY_PLATFORM - - def test_DEFAULT - handle = Handle::DEFAULT - refute_nil handle['malloc'] - end unless /mswin|mingw/ =~ RUBY_PLATFORM - - def test_dlerror - # FreeBSD (at least 7.2 to 7.2) calls nsdispatch(3) when it calls - # getaddrinfo(3). And nsdispatch(3) doesn't call dlerror(3) even if - # it calls _nss_cache_cycle_prevention_function with dlsym(3). - # So our Fiddle::Handle#sym must call dlerror(3) before call dlsym. - # In general uses of dlerror(3) should call it before use it. - require 'socket' - Socket.gethostbyname("localhost") - Fiddle.dlopen("/lib/libc.so.7").sym('strcpy') - end if /freebsd/=~ RUBY_PLATFORM - - def test_no_memory_leak - if respond_to?(:assert_nothing_leaked_memory) - n_tries = 100_000 - assert_nothing_leaked_memory(SIZEOF_VOIDP * (n_tries / 100)) do - n_tries.times do - Fiddle::Handle.allocate - end - end - else - assert_no_memory_leak(%w[-W0 -rfiddle.so], '', '100_000.times {Fiddle::Handle.allocate}; GC.start', rss: true) - end - end - - if /cygwin|mingw|mswin/ =~ RUBY_PLATFORM - def test_fallback_to_ansi - k = Fiddle::Handle.new("kernel32.dll") - ansi = k["GetFileAttributesA"] - assert_equal(ansi, k["GetFileAttributes"], "should fallback to ANSI version") - end - end - end -end if defined?(Fiddle) diff --git a/test/fiddle/test_import.rb b/test/fiddle/test_import.rb deleted file mode 100644 index afa8df9e00..0000000000 --- a/test/fiddle/test_import.rb +++ /dev/null @@ -1,479 +0,0 @@ -# coding: US-ASCII -# frozen_string_literal: true -begin - require_relative 'helper' - require 'fiddle/import' -rescue LoadError -end - -module Fiddle - module LIBC - extend Importer - dlload LIBC_SO, LIBM_SO - - typealias 'string', 'char*' - typealias 'FILE*', 'void*' - - extern "void *strcpy(char*, char*)" - extern "int isdigit(int)" - extern "double atof(string)" - extern "unsigned long strtoul(char*, char **, int)" - extern "int qsort(void*, unsigned long, unsigned long, void*)" - extern "int fprintf(FILE*, char*)" rescue nil - extern "int gettimeofday(timeval*, timezone*)" rescue nil - - BoundQsortCallback = bind("void *bound_qsort_callback(void*, void*)"){|ptr1,ptr2| ptr1[0] <=> ptr2[0]} - Timeval = struct [ - "long tv_sec", - "long tv_usec", - ] - Timezone = struct [ - "int tz_minuteswest", - "int tz_dsttime", - ] - MyStruct = struct [ - "short num[5]", - "char c", - "unsigned char buff[7]", - ] - StructNestedStruct = struct [ - { - "vertices[2]" => { - position: ["float x", "float y", "float z"], - texcoord: ["float u", "float v"] - }, - object: ["int id", "void *user_data"], - }, - "int id" - ] - UnionNestedStruct = union [ - { - keyboard: [ - 'unsigned int state', - 'char key' - ], - mouse: [ - 'unsigned int button', - 'unsigned short x', - 'unsigned short y' - ] - } - ] - - CallCallback = bind("void call_callback(void*, void*)"){ | ptr1, ptr2| - f = Function.new(ptr1.to_i, [TYPE_VOIDP], TYPE_VOID) - f.call(ptr2) - } - end - - class TestImport < TestCase - def test_ensure_call_dlload - err = assert_raise(RuntimeError) do - Class.new do - extend Importer - extern "void *strcpy(char*, char*)" - end - end - assert_match(/call dlload before/, err.message) - end - - def test_struct_memory_access() - # check memory operations performed directly on struct - Fiddle::Importer.struct(['int id']).malloc(Fiddle::RUBY_FREE) do |my_struct| - my_struct[0, Fiddle::SIZEOF_INT] = "\x01".b * Fiddle::SIZEOF_INT - assert_equal 0x01010101, my_struct.id - - my_struct.id = 0 - assert_equal "\x00".b * Fiddle::SIZEOF_INT, my_struct[0, Fiddle::SIZEOF_INT] - end - end - - def test_struct_ptr_array_subscript_multiarg() - # check memory operations performed on struct#to_ptr - Fiddle::Importer.struct([ 'int x' ]).malloc(Fiddle::RUBY_FREE) do |struct| - ptr = struct.to_ptr - - struct.x = 0x02020202 - assert_equal("\x02".b * Fiddle::SIZEOF_INT, ptr[0, Fiddle::SIZEOF_INT]) - - ptr[0, Fiddle::SIZEOF_INT] = "\x01".b * Fiddle::SIZEOF_INT - assert_equal 0x01010101, struct.x - end - end - - def test_malloc() - LIBC::Timeval.malloc(Fiddle::RUBY_FREE) do |s1| - LIBC::Timeval.malloc(Fiddle::RUBY_FREE) do |s2| - refute_equal(s1.to_ptr.to_i, s2.to_ptr.to_i) - end - end - end - - def test_sizeof() - assert_equal(SIZEOF_VOIDP, LIBC.sizeof("FILE*")) - assert_equal(LIBC::MyStruct.size(), LIBC.sizeof(LIBC::MyStruct)) - LIBC::MyStruct.malloc(Fiddle::RUBY_FREE) do |my_struct| - assert_equal(LIBC::MyStruct.size(), LIBC.sizeof(my_struct)) - end - assert_equal(SIZEOF_LONG_LONG, LIBC.sizeof("long long")) if defined?(SIZEOF_LONG_LONG) - assert_equal(LIBC::StructNestedStruct.size(), LIBC.sizeof(LIBC::StructNestedStruct)) - end - - Fiddle.constants.grep(/\ATYPE_(?!VOID|VARIADIC\z)(.*)/) do - type = $& - const_type_name = $1 - size = Fiddle.const_get("SIZEOF_#{const_type_name}") - if const_type_name == "CONST_STRING" - name = "const_string" - type_name = "const char*" - else - name = $1.sub(/P\z/,"*").gsub(/_(?!T\z)/, " ").downcase - type_name = name - end - define_method("test_sizeof_#{name}") do - assert_equal(size, Fiddle::Importer.sizeof(type_name), type) - end - end - - def test_unsigned_result() - d = (2 ** 31) + 1 - - r = LIBC.strtoul(d.to_s, 0, 0) - assert_equal(d, r) - end - - def test_io() - if( RUBY_PLATFORM != BUILD_RUBY_PLATFORM ) || !defined?(LIBC.fprintf) - return - end - io_in,io_out = IO.pipe() - LIBC.fprintf(io_out, "hello") - io_out.flush() - io_out.close() - str = io_in.read() - io_in.close() - assert_equal("hello", str) - end - - def test_value() - i = LIBC.value('int', 2) - assert_equal(2, i.value) - - d = LIBC.value('double', 2.0) - assert_equal(2.0, d.value) - - ary = LIBC.value('int[3]', [0,1,2]) - assert_equal([0,1,2], ary.value) - end - - def test_struct_array_assignment() - Fiddle::Importer.struct(["unsigned int stages[3]"]).malloc(Fiddle::RUBY_FREE) do |instance| - instance.stages[0] = 1024 - instance.stages[1] = 10 - instance.stages[2] = 100 - assert_equal 1024, instance.stages[0] - assert_equal 10, instance.stages[1] - assert_equal 100, instance.stages[2] - assert_equal [1024, 10, 100].pack(Fiddle::PackInfo::PACK_MAP[-Fiddle::TYPE_INT] * 3), - instance.to_ptr[0, 3 * Fiddle::SIZEOF_INT] - assert_raise(IndexError) { instance.stages[-1] = 5 } - assert_raise(IndexError) { instance.stages[3] = 5 } - end - end - - def test_nested_struct_reusing_other_structs() - position_struct = Fiddle::Importer.struct(['float x', 'float y', 'float z']) - texcoord_struct = Fiddle::Importer.struct(['float u', 'float v']) - vertex_struct = Fiddle::Importer.struct(position: position_struct, texcoord: texcoord_struct) - mesh_struct = Fiddle::Importer.struct([ - { - "vertices[2]" => vertex_struct, - object: [ - "int id", - "void *user_data", - ], - }, - "int id", - ]) - assert_equal LIBC::StructNestedStruct.size, mesh_struct.size - - - keyboard_event_struct = Fiddle::Importer.struct(['unsigned int state', 'char key']) - mouse_event_struct = Fiddle::Importer.struct(['unsigned int button', 'unsigned short x', 'unsigned short y']) - event_union = Fiddle::Importer.union([{ keboard: keyboard_event_struct, mouse: mouse_event_struct}]) - assert_equal LIBC::UnionNestedStruct.size, event_union.size - end - - def test_nested_struct_alignment_is_not_its_size() - inner = Fiddle::Importer.struct(['int x', 'int y', 'int z', 'int w']) - outer = Fiddle::Importer.struct(['char a', { 'nested' => inner }, 'char b']) - outer.malloc(Fiddle::RUBY_FREE) do |instance| - offset = instance.to_ptr.instance_variable_get(:"@offset") - assert_equal Fiddle::SIZEOF_INT * 5, offset.last - assert_equal Fiddle::SIZEOF_INT * 6, outer.size - assert_equal instance.to_ptr.size, outer.size - end - end - - def test_struct_nested_struct_members() - LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| - Fiddle::Pointer.malloc(24, Fiddle::RUBY_FREE) do |user_data| - s.vertices[0].position.x = 1 - s.vertices[0].position.y = 2 - s.vertices[0].position.z = 3 - s.vertices[0].texcoord.u = 4 - s.vertices[0].texcoord.v = 5 - s.vertices[1].position.x = 6 - s.vertices[1].position.y = 7 - s.vertices[1].position.z = 8 - s.vertices[1].texcoord.u = 9 - s.vertices[1].texcoord.v = 10 - s.object.id = 100 - s.object.user_data = user_data - s.id = 101 - assert_equal({ - "vertices" => [ - { - "position" => { - "x" => 1, - "y" => 2, - "z" => 3, - }, - "texcoord" => { - "u" => 4, - "v" => 5, - }, - }, - { - "position" => { - "x" => 6, - "y" => 7, - "z" => 8, - }, - "texcoord" => { - "u" => 9, - "v" => 10, - }, - }, - ], - "object" => { - "id" => 100, - "user_data" => user_data, - }, - "id" => 101, - }, - s.to_h) - end - end - end - - def test_union_nested_struct_members() - LIBC::UnionNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| - s.keyboard.state = 100 - s.keyboard.key = 101 - assert_equal(100, s.mouse.button) - refute_equal( 0, s.mouse.x) - end - end - - def test_struct_nested_struct_replace_array_element() - LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| - s.vertices[0].position.x = 5 - - vertex_struct = Fiddle::Importer.struct [{ - position: ["float x", "float y", "float z"], - texcoord: ["float u", "float v"] - }] - vertex_struct.malloc(Fiddle::RUBY_FREE) do |vertex| - vertex.position.x = 100 - s.vertices[0] = vertex - - # make sure element was copied by value, but things like memory address - # should not be changed - assert_equal(100, s.vertices[0].position.x) - refute_equal(vertex.object_id, s.vertices[0].object_id) - refute_equal(vertex.to_ptr, s.vertices[0].to_ptr) - end - end - end - - def test_struct_nested_struct_replace_array_element_nil() - LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| - s.vertices[0].position.x = 5 - s.vertices[0] = nil - assert_equal({ - "position" => { - "x" => 0.0, - "y" => 0.0, - "z" => 0.0, - }, - "texcoord" => { - "u" => 0.0, - "v" => 0.0, - }, - }, - s.vertices[0].to_h) - end - end - - def test_struct_nested_struct_replace_array_element_hash() - LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| - s.vertices[0] = { - position: { - x: 10, - y: 100, - } - } - assert_equal({ - "position" => { - "x" => 10.0, - "y" => 100.0, - "z" => 0.0, - }, - "texcoord" => { - "u" => 0.0, - "v" => 0.0, - }, - }, - s.vertices[0].to_h) - end - end - - def test_struct_nested_struct_replace_entire_array() - LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| - vertex_struct = Fiddle::Importer.struct [{ - position: ["float x", "float y", "float z"], - texcoord: ["float u", "float v"] - }] - - vertex_struct.malloc(Fiddle::RUBY_FREE) do |same0| - vertex_struct.malloc(Fiddle::RUBY_FREE) do |same1| - same = [same0, same1] - same[0].position.x = 1; same[1].position.x = 6 - same[0].position.y = 2; same[1].position.y = 7 - same[0].position.z = 3; same[1].position.z = 8 - same[0].texcoord.u = 4; same[1].texcoord.u = 9 - same[0].texcoord.v = 5; same[1].texcoord.v = 10 - s.vertices = same - assert_equal([ - { - "position" => { - "x" => 1.0, - "y" => 2.0, - "z" => 3.0, - }, - "texcoord" => { - "u" => 4.0, - "v" => 5.0, - }, - }, - { - "position" => { - "x" => 6.0, - "y" => 7.0, - "z" => 8.0, - }, - "texcoord" => { - "u" => 9.0, - "v" => 10.0, - }, - } - ], - s.vertices.collect(&:to_h)) - end - end - end - end - - def test_struct_nested_struct_replace_entire_array_with_different_struct() - LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s| - different_struct_same_size = Fiddle::Importer.struct [{ - a: ['float i', 'float j', 'float k'], - b: ['float l', 'float m'] - }] - - different_struct_same_size.malloc(Fiddle::RUBY_FREE) do |different0| - different_struct_same_size.malloc(Fiddle::RUBY_FREE) do |different1| - different = [different0, different1] - different[0].a.i = 11; different[1].a.i = 16 - different[0].a.j = 12; different[1].a.j = 17 - different[0].a.k = 13; different[1].a.k = 18 - different[0].b.l = 14; different[1].b.l = 19 - different[0].b.m = 15; different[1].b.m = 20 - s.vertices[0][0, s.vertices[0].class.size] = different[0].to_ptr - s.vertices[1][0, s.vertices[1].class.size] = different[1].to_ptr - assert_equal([ - { - "position" => { - "x" => 11.0, - "y" => 12.0, - "z" => 13.0, - }, - "texcoord" => { - "u" => 14.0, - "v" => 15.0, - }, - }, - { - "position" => { - "x" => 16.0, - "y" => 17.0, - "z" => 18.0, - }, - "texcoord" => { - "u" => 19.0, - "v" => 20.0, - }, - } - ], - s.vertices.collect(&:to_h)) - end - end - end - end - - def test_struct() - LIBC::MyStruct.malloc(Fiddle::RUBY_FREE) do |s| - s.num = [0,1,2,3,4] - s.c = ?a.ord - s.buff = "012345\377" - assert_equal([0,1,2,3,4], s.num) - assert_equal(?a.ord, s.c) - assert_equal([?0.ord,?1.ord,?2.ord,?3.ord,?4.ord,?5.ord,?\377.ord], s.buff) - end - end - - def test_gettimeofday() - if( defined?(LIBC.gettimeofday) ) - LIBC::Timeval.malloc(Fiddle::RUBY_FREE) do |timeval| - LIBC::Timezone.malloc(Fiddle::RUBY_FREE) do |timezone| - LIBC.gettimeofday(timeval, timezone) - end - cur = Time.now() - assert(cur.to_i - 2 <= timeval.tv_sec && timeval.tv_sec <= cur.to_i) - end - end - end - - def test_strcpy() - buff = +"000" - str = LIBC.strcpy(buff, "123") - assert_equal("123", buff) - assert_equal("123", str.to_s) - end - - def test_isdigit - r1 = LIBC.isdigit(?1.ord) - r2 = LIBC.isdigit(?2.ord) - rr = LIBC.isdigit(?r.ord) - assert_operator(r1, :>, 0) - assert_operator(r2, :>, 0) - assert_equal(0, rr) - end - - def test_atof - r = LIBC.atof("12.34") - assert_includes(12.00..13.00, r) - end - end -end if defined?(Fiddle) diff --git a/test/fiddle/test_memory_view.rb b/test/fiddle/test_memory_view.rb deleted file mode 100644 index 240cda37df..0000000000 --- a/test/fiddle/test_memory_view.rb +++ /dev/null @@ -1,143 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' -rescue LoadError - return -end - -begin - require '-test-/memory_view' -rescue LoadError - return -end - -module Fiddle - class TestMemoryView < TestCase - def setup - omit "MemoryView is unavailable" unless defined? Fiddle::MemoryView - end - - def test_null_ptr - assert_raise(ArgumentError) do - MemoryView.new(Fiddle::NULL) - end - end - - def test_memory_view_from_unsupported_obj - obj = Object.new - assert_raise(ArgumentError) do - MemoryView.new(obj) - end - end - - def test_memory_view_from_pointer - str = Marshal.load(Marshal.dump("hello world")) - ptr = Pointer[str] - mview = MemoryView.new(ptr) - assert_same(ptr, mview.obj) - assert_equal(str.bytesize, mview.byte_size) - assert_equal(true, mview.readonly?) - assert_equal(nil, mview.format) - assert_equal(1, mview.item_size) - assert_equal(1, mview.ndim) - assert_equal(nil, mview.shape) - assert_equal(nil, mview.strides) - assert_equal(nil, mview.sub_offsets) - - codes = str.codepoints - assert_equal(codes, (0...str.bytesize).map {|i| mview[i] }) - end - - def test_memory_view_multi_dimensional - omit "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils - - buf = [ 1, 2, 3, 4, - 5, 6, 7, 8, - 9, 10, 11, 12 ].pack("l!*") - shape = [3, 4] - md = MemoryViewTestUtils::MultiDimensionalView.new(buf, "l!", shape, nil) - mview = Fiddle::MemoryView.new(md) - assert_equal(buf.bytesize, mview.byte_size) - assert_equal("l!", mview.format) - assert_equal(Fiddle::SIZEOF_LONG, mview.item_size) - assert_equal(2, mview.ndim) - assert_equal(shape, mview.shape) - assert_equal([Fiddle::SIZEOF_LONG*4, Fiddle::SIZEOF_LONG], mview.strides) - assert_equal(nil, mview.sub_offsets) - assert_equal(1, mview[0, 0]) - assert_equal(4, mview[0, 3]) - assert_equal(6, mview[1, 1]) - assert_equal(10, mview[2, 1]) - end - - def test_memory_view_multi_dimensional_with_strides - omit "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils - - buf = [ 1, 2, 3, 4, 5, 6, 7, 8, - 9, 10, 11, 12, 13, 14, 15, 16 ].pack("l!*") - shape = [2, 8] - strides = [4*Fiddle::SIZEOF_LONG*2, Fiddle::SIZEOF_LONG*2] - md = MemoryViewTestUtils::MultiDimensionalView.new(buf, "l!", shape, strides) - mview = Fiddle::MemoryView.new(md) - assert_equal("l!", mview.format) - assert_equal(Fiddle::SIZEOF_LONG, mview.item_size) - assert_equal(buf.bytesize, mview.byte_size) - assert_equal(2, mview.ndim) - assert_equal(shape, mview.shape) - assert_equal(strides, mview.strides) - assert_equal(nil, mview.sub_offsets) - assert_equal(1, mview[0, 0]) - assert_equal(5, mview[0, 2]) - assert_equal(9, mview[1, 0]) - assert_equal(15, mview[1, 3]) - end - - def test_memory_view_multi_dimensional_with_multiple_members - omit "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils - - buf = [ 1, 2, 3, 4, 5, 6, 7, 8, - -1, -2, -3, -4, -5, -6, -7, -8].pack("s*") - shape = [2, 4] - strides = [4*Fiddle::SIZEOF_SHORT*2, Fiddle::SIZEOF_SHORT*2] - md = MemoryViewTestUtils::MultiDimensionalView.new(buf, "ss", shape, strides) - mview = Fiddle::MemoryView.new(md) - assert_equal("ss", mview.format) - assert_equal(Fiddle::SIZEOF_SHORT*2, mview.item_size) - assert_equal(buf.bytesize, mview.byte_size) - assert_equal(2, mview.ndim) - assert_equal(shape, mview.shape) - assert_equal(strides, mview.strides) - assert_equal(nil, mview.sub_offsets) - assert_equal([1, 2], mview[0, 0]) - assert_equal([5, 6], mview[0, 2]) - assert_equal([-1, -2], mview[1, 0]) - assert_equal([-7, -8], mview[1, 3]) - end - - def test_export - str = "hello world" - mview_str = MemoryView.export(Pointer[str]) do |mview| - mview.to_s - end - assert_equal(str, mview_str) - end - - def test_release - ptr = Pointer["hello world"] - mview = MemoryView.new(ptr) - assert_same(ptr, mview.obj) - mview.release - assert_nil(mview.obj) - end - - def test_to_s - # U+3042 HIRAGANA LETTER A - data = "\u{3042}" - ptr = Pointer[data] - mview = MemoryView.new(ptr) - string = mview.to_s - assert_equal([data.b, true], - [string, string.frozen?]) - end - end -end diff --git a/test/fiddle/test_pinned.rb b/test/fiddle/test_pinned.rb deleted file mode 100644 index f0d375b1cc..0000000000 --- a/test/fiddle/test_pinned.rb +++ /dev/null @@ -1,28 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' -rescue LoadError - return -end - -module Fiddle - class TestPinned < Fiddle::TestCase - def test_pin_object - x = Object.new - pinner = Pinned.new x - assert_same x, pinner.ref - end - - def test_clear - pinner = Pinned.new Object.new - refute pinner.cleared? - pinner.clear - assert pinner.cleared? - ex = assert_raise(Fiddle::ClearedReferenceError) do - pinner.ref - end - assert_match "called on", ex.message - end - end -end - diff --git a/test/fiddle/test_pointer.rb b/test/fiddle/test_pointer.rb deleted file mode 100644 index 7d708ee417..0000000000 --- a/test/fiddle/test_pointer.rb +++ /dev/null @@ -1,287 +0,0 @@ -# frozen_string_literal: true -begin - require_relative 'helper' -rescue LoadError -end - -module Fiddle - class TestPointer < TestCase - def dlwrap arg - Fiddle.dlwrap arg - end - - def test_cptr_to_int - null = Fiddle::NULL - assert_equal(null.to_i, null.to_int) - end - - def test_malloc_free_func_int - free = Fiddle::Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID) - assert_equal free.to_i, Fiddle::RUBY_FREE.to_i - - ptr = Pointer.malloc(10, free.to_i) - assert_equal 10, ptr.size - assert_equal free.to_i, ptr.free.to_i - end - - def test_malloc_free_func - free = Fiddle::Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID) - - ptr = Pointer.malloc(10, free) - assert_equal 10, ptr.size - assert_equal free.to_i, ptr.free.to_i - end - - def test_malloc_block - escaped_ptr = nil - returned = Pointer.malloc(10, Fiddle::RUBY_FREE) do |ptr| - assert_equal 10, ptr.size - assert_equal Fiddle::RUBY_FREE, ptr.free.to_i - escaped_ptr = ptr - :returned - end - assert_equal :returned, returned - assert escaped_ptr.freed? - end - - def test_malloc_block_no_free - assert_raise ArgumentError do - Pointer.malloc(10) { |ptr| } - end - end - - def test_malloc_subclass - subclass = Class.new(Pointer) - subclass.malloc(10, Fiddle::RUBY_FREE) do |ptr| - assert ptr.is_a?(subclass) - end - end - - def test_to_str - str = Marshal.load(Marshal.dump("hello world")) - ptr = Pointer[str] - - assert_equal 3, ptr.to_str(3).length - assert_equal str, ptr.to_str - - ptr[5] = 0 - assert_equal "hello\0world", ptr.to_str - end - - def test_to_s - str = Marshal.load(Marshal.dump("hello world")) - ptr = Pointer[str] - - assert_equal 3, ptr.to_s(3).length - assert_equal str, ptr.to_s - - ptr[5] = 0 - assert_equal 'hello', ptr.to_s - end - - def test_minus - str = "hello world" - ptr = Pointer[str] - assert_equal ptr.to_s, (ptr + 3 - 3).to_s - end - - # TODO: what if the pointer size is 0? raise an exception? do we care? - def test_plus - str = "hello world" - ptr = Pointer[str] - new_str = ptr + 3 - assert_equal 'lo world', new_str.to_s - end - - def test_inspect - ptr = Pointer.new(0) - inspect = ptr.inspect - assert_match(/size=#{ptr.size}/, inspect) - assert_match(/free=#{sprintf("%#x", ptr.free.to_i)}/, inspect) - assert_match(/ptr=#{sprintf("%#x", ptr.to_i)}/, inspect) - end - - def test_to_ptr_string - str = "hello world" - ptr = Pointer[str] - assert_equal str.length, ptr.size - assert_equal 'hello', ptr[0,5] - end - - def test_to_ptr_io - Pointer.malloc(10, Fiddle::RUBY_FREE) do |buf| - File.open(__FILE__, 'r') do |f| - ptr = Pointer.to_ptr f - fread = Function.new(@libc['fread'], - [TYPE_VOIDP, TYPE_INT, TYPE_INT, TYPE_VOIDP], - TYPE_INT) - fread.call(buf.to_i, Fiddle::SIZEOF_CHAR, buf.size - 1, ptr.to_i) - end - - File.open(__FILE__, 'r') do |f| - assert_equal f.read(9), buf.to_s - end - end - end - - def test_to_ptr_with_ptr - ptr = Pointer.new 0 - ptr2 = Pointer.to_ptr Struct.new(:to_ptr).new(ptr) - assert_equal ptr, ptr2 - - assert_raise(Fiddle::DLError) do - Pointer.to_ptr Struct.new(:to_ptr).new(nil) - end - end - - def test_to_ptr_with_num - ptr = Pointer.new 0 - assert_equal ptr, Pointer[0] - end - - def test_equals - ptr = Pointer.new 0 - ptr2 = Pointer.new 0 - assert_equal ptr2, ptr - end - - def test_not_equals - ptr = Pointer.new 0 - refute_equal 10, ptr, '10 should not equal the pointer' - end - - def test_cmp - ptr = Pointer.new 0 - assert_nil(ptr <=> 10, '10 should not be comparable') - end - - def test_ref_ptr - ary = [0,1,2,4,5] - addr = Pointer.new(dlwrap(ary)) - assert_equal addr.to_i, addr.ref.ptr.to_i - - assert_equal addr.to_i, (+ (- addr)).to_i - end - - def test_to_value - ary = [0,1,2,4,5] - addr = Pointer.new(dlwrap(ary)) - assert_equal ary, addr.to_value - end - - def test_free - ptr = Pointer.malloc(4) - begin - assert_nil ptr.free - ensure - Fiddle.free ptr - end - end - - def test_free= - free = Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID) - ptr = Pointer.malloc(4) - ptr.free = free - - assert_equal free.ptr, ptr.free.ptr - end - - def test_free_with_func - ptr = Pointer.malloc(4, Fiddle::RUBY_FREE) - refute ptr.freed? - ptr.call_free - assert ptr.freed? - ptr.call_free # you can safely run it again - assert ptr.freed? - GC.start # you can safely run the GC routine - assert ptr.freed? - end - - def test_free_with_no_func - ptr = Pointer.malloc(4) - refute ptr.freed? - ptr.call_free - refute ptr.freed? - ptr.call_free # you can safely run it again - refute ptr.freed? - end - - def test_freed? - ptr = Pointer.malloc(4, Fiddle::RUBY_FREE) - refute ptr.freed? - ptr.call_free - assert ptr.freed? - end - - def test_null? - ptr = Pointer.new(0) - assert ptr.null? - end - - def test_size - Pointer.malloc(4, Fiddle::RUBY_FREE) do |ptr| - assert_equal 4, ptr.size - end - end - - def test_size= - Pointer.malloc(4, Fiddle::RUBY_FREE) do |ptr| - ptr.size = 10 - assert_equal 10, ptr.size - end - end - - def test_aref_aset - check = Proc.new{|str,ptr| - assert_equal(str.size(), ptr.size()) - assert_equal(str, ptr.to_s()) - assert_equal(str[0,2], ptr.to_s(2)) - assert_equal(str[0,2], ptr[0,2]) - assert_equal(str[1,2], ptr[1,2]) - assert_equal(str[1,0], ptr[1,0]) - assert_equal(str[0].ord, ptr[0]) - assert_equal(str[1].ord, ptr[1]) - } - str = Marshal.load(Marshal.dump('abc')) - ptr = Pointer[str] - check.call(str, ptr) - - str[0] = "c" - assert_equal 'c'.ord, ptr[0] = "c".ord - check.call(str, ptr) - - str[0,2] = "aa" - assert_equal 'aa', ptr[0,2] = "aa" - check.call(str, ptr) - - ptr2 = Pointer['cdeeee'] - str[0,2] = "cd" - assert_equal ptr2, ptr[0,2] = ptr2 - check.call(str, ptr) - - ptr3 = Pointer['vvvv'] - str[0,2] = "vv" - assert_equal ptr3.to_i, ptr[0,2] = ptr3.to_i - check.call(str, ptr) - end - - def test_null_pointer - nullpo = Pointer.new(0) - assert_raise(DLError) {nullpo[0]} - assert_raise(DLError) {nullpo[0] = 1} - end - - def test_no_memory_leak - if respond_to?(:assert_nothing_leaked_memory) - n_tries = 100_000 - assert_nothing_leaked_memory(SIZEOF_VOIDP * (n_tries / 100)) do - n_tries.times do - Fiddle::Pointer.allocate - end - end - else - assert_no_memory_leak(%w[-W0 -rfiddle.so], '', '100_000.times {Fiddle::Pointer.allocate}', rss: true) - end - end - end -end if defined?(Fiddle) |
