diff options
Diffstat (limited to 'test/fiddle')
-rw-r--r-- | test/fiddle/helper.rb | 10 | ||||
-rw-r--r-- | test/fiddle/test_c_struct_entry.rb | 8 | ||||
-rw-r--r-- | test/fiddle/test_closure.rb | 123 | ||||
-rw-r--r-- | test/fiddle/test_cparser.rb | 40 | ||||
-rw-r--r-- | test/fiddle/test_fiddle.rb | 41 | ||||
-rw-r--r-- | test/fiddle/test_func.rb | 53 | ||||
-rw-r--r-- | test/fiddle/test_function.rb | 28 | ||||
-rw-r--r-- | test/fiddle/test_handle.rb | 10 | ||||
-rw-r--r-- | test/fiddle/test_import.rb | 23 | ||||
-rw-r--r-- | test/fiddle/test_pack.rb | 37 | ||||
-rw-r--r-- | test/fiddle/test_pointer.rb | 19 |
11 files changed, 322 insertions, 70 deletions
diff --git a/test/fiddle/helper.rb b/test/fiddle/helper.rb index 0ea3bf57f4..e470f5a276 100644 --- a/test/fiddle/helper.rb +++ b/test/fiddle/helper.rb @@ -49,8 +49,14 @@ when /linux/ libm_so = libc_so else # glibc - libc_so = "libc.so.6" - libm_so = "libm.so.6" + case RUBY_PLATFORM + when /alpha-linux/, /ia64-linux/ + libc_so = "libc.so.6.1" + libm_so = "libm.so.6.1" + else + libc_so = "libc.so.6" + libm_so = "libm.so.6" + end end when /mingw/, /mswin/ require "rbconfig" diff --git a/test/fiddle/test_c_struct_entry.rb b/test/fiddle/test_c_struct_entry.rb index 9fd16d7101..45de2efe21 100644 --- a/test/fiddle/test_c_struct_entry.rb +++ b/test/fiddle/test_c_struct_entry.rb @@ -8,7 +8,7 @@ end module Fiddle class TestCStructEntity < TestCase def test_class_size - types = [TYPE_DOUBLE, TYPE_CHAR] + types = [TYPE_DOUBLE, TYPE_CHAR, TYPE_DOUBLE, TYPE_BOOL] size = CStructEntity.size types @@ -20,6 +20,12 @@ module Fiddle expected = PackInfo.align expected, alignments[1] expected += PackInfo::SIZE_MAP[TYPE_CHAR] + expected = PackInfo.align expected, alignments[2] + expected += PackInfo::SIZE_MAP[TYPE_DOUBLE] + + expected = PackInfo.align expected, alignments[3] + expected += PackInfo::SIZE_MAP[TYPE_BOOL] + expected = PackInfo.align expected, alignments.max assert_equal expected, size diff --git a/test/fiddle/test_closure.rb b/test/fiddle/test_closure.rb index 9e748bf5ee..abb6bdbd32 100644 --- a/test/fiddle/test_closure.rb +++ b/test/fiddle/test_closure.rb @@ -6,6 +6,17 @@ end module Fiddle class TestClosure < Fiddle::TestCase + def teardown + super + # Ensure freeing all closures. + # See https://github.com/ruby/fiddle/issues/102#issuecomment-1241763091 . + not_freed_closures = [] + ObjectSpace.each_object(Fiddle::Closure) do |closure| + not_freed_closures << closure unless closure.freed? + end + assert_equal([], not_freed_closures) + end + def test_argument_errors assert_raise(TypeError) do Closure.new(TYPE_INT, TYPE_INT) @@ -21,37 +32,40 @@ module Fiddle 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), - ]) + Closure.create(:int, [:void]) do |closure| + assert_equal([ + TYPE_INT, + [TYPE_VOID], + ], + [ + closure.instance_variable_get(:@ctype), + closure.instance_variable_get(:@args), + ]) + end end def test_call - closure = Class.new(Closure) { + closure_class = Class.new(Closure) do def call 10 end - }.new(TYPE_INT, []) - - func = Function.new(closure, [], TYPE_INT) - assert_equal 10, func.call + end + closure_class.create(TYPE_INT, []) do |closure| + func = Function.new(closure, [], TYPE_INT) + assert_equal 10, func.call + end end def test_returner - closure = Class.new(Closure) { + closure_class = Class.new(Closure) do 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 + closure_class.create(TYPE_INT, [TYPE_INT]) do |closure| + func = Function.new(closure, [TYPE_INT], TYPE_INT) + assert_equal 10, func.call(10) + end end def test_const_string @@ -61,25 +75,53 @@ module Fiddle @return_string end end - closure = closure_class.new(:const_string, [:const_string]) + closure_class.create(:const_string, [:const_string]) do |closure| + func = Function.new(closure, [:const_string], :const_string) + assert_equal("Hello! World!", func.call("World!")) + end + end - func = Function.new(closure, [:const_string], :const_string) - assert_equal("Hello! World!", func.call("World!")) + def test_bool + closure_class = Class.new(Closure) do + def call(bool) + not bool + end + end + closure_class.create(:bool, [:bool]) do |closure| + func = Function.new(closure, [:bool], :bool) + assert_equal(false, func.call(true)) + end + end + + def test_free + Closure.create(:int, [:void]) do |closure| + assert(!closure.freed?) + closure.free + assert(closure.freed?) + closure.free + end 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) + begin + func = Function.new(cb, [TYPE_INT], TYPE_INT) + assert_equal 11, func.call(11) + ensure + cb.free + end end - def test_memsize + def test_memsize_ruby_dev_42480 require 'objspace' - bug = '[ruby-dev:42480]' n = 10000 - assert_equal(n, n.times {ObjectSpace.memsize_of(Closure.allocate)}, bug) + n.times do + Closure.create(:int, [:void]) do |closure| + ObjectSpace.memsize_of(closure) + end + end end %w[INT SHORT CHAR LONG LONG_LONG].each do |name| @@ -89,20 +131,21 @@ module Fiddle define_method("test_conversion_#{n.downcase}") do arg = nil - clos = Class.new(Closure) do + closure_class = 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 + closure_class.create(t, [t]) do |closure| + v = ~(~0 << (8*s)) + + arg = nil + assert_equal(v, closure.call(v)) + assert_equal(arg, v, n) + + arg = nil + func = Function.new(closure, [t], t) + assert_equal(v, func.call(v)) + assert_equal(arg, v, n) + end end end end diff --git a/test/fiddle/test_cparser.rb b/test/fiddle/test_cparser.rb index ae319197a4..f1b67476ba 100644 --- a/test/fiddle/test_cparser.rb +++ b/test/fiddle/test_cparser.rb @@ -24,14 +24,32 @@ module Fiddle 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('int short')) + assert_equal(TYPE_SHORT, parse_ctype('const int short')) assert_equal(TYPE_SHORT, parse_ctype('signed short')) assert_equal(TYPE_SHORT, parse_ctype('const signed short')) + assert_equal(TYPE_SHORT, parse_ctype('short signed')) + assert_equal(TYPE_SHORT, parse_ctype('const short signed')) 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('signed int short')) + assert_equal(TYPE_SHORT, parse_ctype('const signed int short')) + assert_equal(TYPE_SHORT, parse_ctype('int signed short')) + assert_equal(TYPE_SHORT, parse_ctype('const int signed short')) + assert_equal(TYPE_SHORT, parse_ctype('int short signed')) + assert_equal(TYPE_SHORT, parse_ctype('const int short signed')) 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')) + assert_equal(-TYPE_SHORT, parse_ctype('unsigned int short')) + assert_equal(-TYPE_SHORT, parse_ctype('const unsigned int short')) + assert_equal(-TYPE_SHORT, parse_ctype('short int unsigned')) + assert_equal(-TYPE_SHORT, parse_ctype('const short int unsigned')) + assert_equal(-TYPE_SHORT, parse_ctype('int unsigned short')) + assert_equal(-TYPE_SHORT, parse_ctype('const int unsigned short')) + assert_equal(-TYPE_SHORT, parse_ctype('int short unsigned')) + assert_equal(-TYPE_SHORT, parse_ctype('const int short unsigned')) end def test_int_ctype @@ -50,14 +68,32 @@ module Fiddle 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('int long')) + assert_equal(TYPE_LONG, parse_ctype('const int long')) 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('signed int long')) + assert_equal(TYPE_LONG, parse_ctype('const signed int long')) + assert_equal(TYPE_LONG, parse_ctype('long signed')) + assert_equal(TYPE_LONG, parse_ctype('const long signed')) + assert_equal(TYPE_LONG, parse_ctype('long int signed')) + assert_equal(TYPE_LONG, parse_ctype('const long int signed')) + assert_equal(TYPE_LONG, parse_ctype('int long signed')) + assert_equal(TYPE_LONG, parse_ctype('const int long signed')) 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')) + assert_equal(-TYPE_LONG, parse_ctype('long int unsigned')) + assert_equal(-TYPE_LONG, parse_ctype('const long int unsigned')) + assert_equal(-TYPE_LONG, parse_ctype('unsigned int long')) + assert_equal(-TYPE_LONG, parse_ctype('const unsigned int long')) + assert_equal(-TYPE_LONG, parse_ctype('int unsigned long')) + assert_equal(-TYPE_LONG, parse_ctype('const int unsigned long')) + assert_equal(-TYPE_LONG, parse_ctype('int long unsigned')) + assert_equal(-TYPE_LONG, parse_ctype('const int long unsigned')) end def test_size_t_ctype @@ -85,6 +121,10 @@ module Fiddle assert_equal(TYPE_UINTPTR_T, parse_ctype("const uintptr_t")) end + def test_bool_ctype + assert_equal(TYPE_BOOL, parse_ctype('bool')) + end + def test_undefined_ctype assert_raise(DLError) { parse_ctype('DWORD') } end diff --git a/test/fiddle/test_fiddle.rb b/test/fiddle/test_fiddle.rb index 8751d96920..9bddb056c9 100644 --- a/test/fiddle/test_fiddle.rb +++ b/test/fiddle/test_fiddle.rb @@ -5,6 +5,13 @@ rescue LoadError end class TestFiddle < Fiddle::TestCase + def test_nil_true_etc + assert_equal Fiddle::Qtrue, Fiddle.dlwrap(true) + assert_equal Fiddle::Qfalse, Fiddle.dlwrap(false) + assert_equal Fiddle::Qnil, Fiddle.dlwrap(nil) + assert Fiddle::Qundef + end + def test_windows_constant require 'rbconfig' if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ @@ -14,4 +21,38 @@ class TestFiddle < Fiddle::TestCase end end + def test_dlopen_linker_script_input_linux + omit("This is only for Linux") unless RUBY_PLATFORM.match?("linux") + if Dir.glob("/usr/lib/*/libncurses.so").empty? + omit("libncurses.so is needed") + end + # libncurses.so uses INPUT() on Debian GNU/Linux + # $ cat /usr/lib/x86_64-linux-gnu/libncurses.so + # INPUT(libncurses.so.6 -ltinfo) + handle = Fiddle.dlopen("libncurses.so") + begin + assert_equal("libncurses.so", + File.basename(handle.file_name, ".*")) + ensure + handle.close + end + end + + def test_dlopen_linker_script_group_linux + omit("This is only for Linux") unless RUBY_PLATFORM.match?("linux") + # libc.so uses GROUP() on Debian GNU/Linux + # $ cat /usr/lib/x86_64-linux-gnu/libc.so + # /* GNU ld script + # Use the shared library, but some functions are only in + # the static library, so try that secondarily. */ + # OUTPUT_FORMAT(elf64-x86-64) + # GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED ( /lib64/ld-linux-x86-64.so.2 ) ) + handle = Fiddle.dlopen("libc.so") + begin + assert_equal("libc.so", + File.basename(handle.file_name, ".*")) + ensure + handle.close + end + end end if defined?(Fiddle) diff --git a/test/fiddle/test_func.rb b/test/fiddle/test_func.rb index 44893017e8..df79539e76 100644 --- a/test/fiddle/test_func.rb +++ b/test/fiddle/test_func.rb @@ -60,25 +60,35 @@ module Fiddle end def test_qsort1 - cb = Class.new(Closure) { + closure_class = Class.new(Closure) do def call(x, y) Pointer.new(x)[0] <=> Pointer.new(y)[0] end - }.new(TYPE_INT, [TYPE_VOIDP, TYPE_VOIDP]) + end - 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) + closure_class.create(TYPE_INT, [TYPE_VOIDP, TYPE_VOIDP]) do |callback| + 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, callback) + assert_equal("1349", buff) - bug4929 = '[ruby-core:37395]' - buff = "9341" - under_gc_stress do - qsort.call(buff, buff.size, 1, cb) + bug4929 = '[ruby-core:37395]' + buff = "9341" + under_gc_stress do + qsort.call(buff, buff.size, 1, callback) + end + assert_equal("1349", buff, bug4929) + end + ensure + # Ensure freeing all closures. + # See https://github.com/ruby/fiddle/issues/102#issuecomment-1241763091 . + not_freed_closures = [] + ObjectSpace.each_object(Fiddle::Closure) do |closure| + not_freed_closures << closure unless closure.freed? end - assert_equal("1349", buff, bug4929) + assert_equal([], not_freed_closures) end def test_snprintf @@ -135,5 +145,22 @@ module Fiddle assert_equal("string: He, const string: World, uint: 29\n", output_buffer[0, written]) end + + def test_rb_memory_view_available_p + omit "MemoryView is unavailable" unless defined? Fiddle::MemoryView + libruby = Fiddle.dlopen(nil) + case Fiddle::SIZEOF_VOIDP + when Fiddle::SIZEOF_LONG_LONG + value_type = -Fiddle::TYPE_LONG_LONG + else + value_type = -Fiddle::TYPE_LONG + end + rb_memory_view_available_p = + Function.new(libruby["rb_memory_view_available_p"], + [value_type], + :bool, + need_gvl: true) + assert_equal(false, rb_memory_view_available_p.call(Fiddle::Qnil)) + end end end if defined?(Fiddle) diff --git a/test/fiddle/test_function.rb b/test/fiddle/test_function.rb index 8ac4f60aa3..847df3793a 100644 --- a/test/fiddle/test_function.rb +++ b/test/fiddle/test_function.rb @@ -15,6 +15,16 @@ module Fiddle end end + def teardown + # Ensure freeing all closures. + # See https://github.com/ruby/fiddle/issues/102#issuecomment-1241763091 . + not_freed_closures = [] + ObjectSpace.each_object(Fiddle::Closure) do |closure| + not_freed_closures << closure unless closure.freed? + end + assert_equal([], not_freed_closures) + end + def test_default_abi func = Function.new(@libm['sin'], [TYPE_DOUBLE], TYPE_DOUBLE) assert_equal Function::DEFAULT, func.abi @@ -75,18 +85,20 @@ module Fiddle end def test_argument_count - closure = Class.new(Closure) { + closure_class = Class.new(Closure) do 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 + closure_class.create(TYPE_INT, [TYPE_INT]) do |closure| + 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 end diff --git a/test/fiddle/test_handle.rb b/test/fiddle/test_handle.rb index 7e3ff9d844..412c10e09d 100644 --- a/test/fiddle/test_handle.rb +++ b/test/fiddle/test_handle.rb @@ -22,12 +22,14 @@ module Fiddle def test_static_sym_unknown assert_raise(DLError) { Fiddle::Handle.sym('fooo') } assert_raise(DLError) { Fiddle::Handle['fooo'] } + refute Fiddle::Handle.sym_defined?('fooo') end def test_static_sym begin # Linux / Darwin / FreeBSD refute_nil Fiddle::Handle.sym('dlopen') + assert Fiddle::Handle.sym_defined?('dlopen') assert_equal Fiddle::Handle.sym('dlopen'), Fiddle::Handle['dlopen'] return rescue @@ -54,6 +56,7 @@ module Fiddle handle = Fiddle::Handle.new(LIBC_SO) assert_raise(DLError) { handle.sym('fooo') } assert_raise(DLError) { handle['fooo'] } + refute handle.sym_defined?('fooo') end def test_sym_with_bad_args @@ -66,6 +69,7 @@ module Fiddle handle = Handle.new(LIBC_SO) refute_nil handle.sym('calloc') refute_nil handle['calloc'] + assert handle.sym_defined?('calloc') end def test_handle_close @@ -179,12 +183,18 @@ module Fiddle # 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. + verbose, $VERBOSE = $VERBOSE, nil require 'socket' Socket.gethostbyname("localhost") Fiddle.dlopen("/lib/libc.so.7").sym('strcpy') + ensure + $VERBOSE = verbose end if /freebsd/=~ RUBY_PLATFORM def test_no_memory_leak + # https://github.com/ruby/fiddle/actions/runs/3202406059/jobs/5231356410 + omit if RUBY_VERSION >= '3.2' + if respond_to?(:assert_nothing_leaked_memory) n_tries = 100_000 assert_nothing_leaked_memory(SIZEOF_VOIDP * (n_tries / 100)) do diff --git a/test/fiddle/test_import.rb b/test/fiddle/test_import.rb index afa8df9e00..090ace620d 100644 --- a/test/fiddle/test_import.rb +++ b/test/fiddle/test_import.rb @@ -22,7 +22,6 @@ module Fiddle 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", @@ -59,11 +58,6 @@ module Fiddle ] } ] - - 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 @@ -130,11 +124,28 @@ module Fiddle name = $1.sub(/P\z/,"*").gsub(/_(?!T\z)/, " ").downcase type_name = name end + type_name = "unsigned #{$1}" if type_name =~ /\Au(long|short|char|int|long long)\z/ + define_method("test_sizeof_#{name}") do assert_equal(size, Fiddle::Importer.sizeof(type_name), type) end end + # Assert that the unsigned constants are equal to the "negative" signed ones + # for backwards compatibility + def test_unsigned_equals_negative_signed + Fiddle.constants.grep(/\ATYPE_(?!VOID|VARIADIC\z)(U.*)/) do |unsigned| + assert_equal(-Fiddle.const_get(unsigned.to_s.sub(/U/, '')), + Fiddle.const_get(unsigned)) + end + end + + def test_type_constants + Fiddle::Types.constants.each do |const| + assert_equal Fiddle::Types.const_get(const), Fiddle.const_get("TYPE_#{const}") + end + end + def test_unsigned_result() d = (2 ** 31) + 1 diff --git a/test/fiddle/test_pack.rb b/test/fiddle/test_pack.rb new file mode 100644 index 0000000000..ade1dd5040 --- /dev/null +++ b/test/fiddle/test_pack.rb @@ -0,0 +1,37 @@ +begin + require_relative 'helper' + require 'fiddle/pack' +rescue LoadError + return +end + +module Fiddle + class TestPack < TestCase + def test_pack_map + if defined?(TYPE_LONG_LONG) + assert_equal [0xffff_ffff_ffff_ffff], [0xffff_ffff_ffff_ffff].pack(PackInfo::PACK_MAP[-TYPE_LONG_LONG]).unpack(PackInfo::PACK_MAP[-TYPE_LONG_LONG]) + end + + case Fiddle::SIZEOF_VOIDP + when 8 + assert_equal [0xffff_ffff_ffff_ffff], [0xffff_ffff_ffff_ffff].pack(PackInfo::PACK_MAP[TYPE_VOIDP]).unpack(PackInfo::PACK_MAP[TYPE_VOIDP]) + when 4 + assert_equal [0xffff_ffff], [0xffff_ffff].pack(PackInfo::PACK_MAP[TYPE_VOIDP]).unpack(PackInfo::PACK_MAP[TYPE_VOIDP]) + end + + case Fiddle::SIZEOF_LONG + when 8 + assert_equal [0xffff_ffff_ffff_ffff], [0xffff_ffff_ffff_ffff].pack(PackInfo::PACK_MAP[-TYPE_LONG]).unpack(PackInfo::PACK_MAP[-TYPE_LONG]) + when 4 + assert_equal [0xffff_ffff], [0xffff_ffff].pack(PackInfo::PACK_MAP[-TYPE_LONG]).unpack(PackInfo::PACK_MAP[-TYPE_LONG]) + end + + if Fiddle::SIZEOF_INT == 4 + assert_equal [0xffff_ffff], [0xffff_ffff].pack(PackInfo::PACK_MAP[-TYPE_INT]).unpack(PackInfo::PACK_MAP[-TYPE_INT]) + end + + assert_equal [0xffff], [0xffff].pack(PackInfo::PACK_MAP[-TYPE_SHORT]).unpack(PackInfo::PACK_MAP[-TYPE_SHORT]) + assert_equal [0xff], [0xff].pack(PackInfo::PACK_MAP[-TYPE_CHAR]).unpack(PackInfo::PACK_MAP[-TYPE_CHAR]) + end + end +end diff --git a/test/fiddle/test_pointer.rb b/test/fiddle/test_pointer.rb index 7d708ee417..f2c1d285ad 100644 --- a/test/fiddle/test_pointer.rb +++ b/test/fiddle/test_pointer.rb @@ -10,6 +10,22 @@ module Fiddle Fiddle.dlwrap arg end + def test_can_read_write_memory + # Allocate some memory + address = Fiddle.malloc(Fiddle::SIZEOF_VOIDP) + + bytes_to_write = Fiddle::SIZEOF_VOIDP.times.to_a.pack("C*") + + # Write to the memory + Fiddle::Pointer.write(address, bytes_to_write) + + # Read the bytes out again + bytes = Fiddle::Pointer.read(address, Fiddle::SIZEOF_VOIDP) + assert_equal bytes_to_write, bytes + ensure + Fiddle.free address + end + def test_cptr_to_int null = Fiddle::NULL assert_equal(null.to_i, null.to_int) @@ -272,6 +288,9 @@ module Fiddle end def test_no_memory_leak + # https://github.com/ruby/fiddle/actions/runs/3202406059/jobs/5231356410 + omit if RUBY_VERSION >= '3.2' + if respond_to?(:assert_nothing_leaked_memory) n_tries = 100_000 assert_nothing_leaked_memory(SIZEOF_VOIDP * (n_tries / 100)) do |