diff options
Diffstat (limited to 'test/fiddle/test_function.rb')
| -rw-r--r-- | test/fiddle/test_function.rb | 239 |
1 files changed, 0 insertions, 239 deletions
diff --git a/test/fiddle/test_function.rb b/test/fiddle/test_function.rb deleted file mode 100644 index 847df3793a..0000000000 --- a/test/fiddle/test_function.rb +++ /dev/null @@ -1,239 +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 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 - 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 = Class.new(Closure) do - def call one - 10 + one - end - end - 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 - - 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) |
