2015-12-16 00:07:31 -05:00
|
|
|
# frozen_string_literal: false
|
2011-01-23 08:20:58 -05:00
|
|
|
begin
|
|
|
|
require_relative 'helper'
|
|
|
|
rescue LoadError
|
|
|
|
end
|
2010-05-06 02:59:24 -04:00
|
|
|
|
|
|
|
module Fiddle
|
|
|
|
class TestFunction < Fiddle::TestCase
|
2014-03-08 23:51:38 -05:00
|
|
|
include Test::Unit::Assertions
|
|
|
|
|
2010-05-06 02:59:24 -04:00
|
|
|
def setup
|
|
|
|
super
|
|
|
|
Fiddle.last_error = nil
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_default_abi
|
|
|
|
func = Function.new(@libm['sin'], [TYPE_DOUBLE], TYPE_DOUBLE)
|
|
|
|
assert_equal Function::DEFAULT, func.abi
|
|
|
|
end
|
|
|
|
|
2012-12-11 05:41:00 -05:00
|
|
|
def test_name
|
|
|
|
func = Function.new(@libm['sin'], [TYPE_DOUBLE], TYPE_DOUBLE, name: 'sin')
|
|
|
|
assert_equal 'sin', func.name
|
|
|
|
end
|
|
|
|
|
2010-05-06 02:59:24 -04:00
|
|
|
def test_argument_errors
|
2015-10-30 00:37:13 -04:00
|
|
|
assert_raise(TypeError) do
|
2010-05-06 02:59:24 -04:00
|
|
|
Function.new(@libm['sin'], TYPE_DOUBLE, TYPE_DOUBLE)
|
|
|
|
end
|
|
|
|
|
2015-10-30 00:37:13 -04:00
|
|
|
assert_raise(TypeError) do
|
2010-05-06 02:59:24 -04:00
|
|
|
Function.new(@libm['sin'], ['foo'], TYPE_DOUBLE)
|
|
|
|
end
|
|
|
|
|
2015-10-30 00:37:13 -04:00
|
|
|
assert_raise(TypeError) do
|
2010-05-06 02:59:24 -04:00
|
|
|
Function.new(@libm['sin'], [TYPE_DOUBLE], 'foo')
|
|
|
|
end
|
|
|
|
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)
|
|
|
|
|
2015-10-30 00:37:13 -04:00
|
|
|
assert_raise(ArgumentError) do
|
2010-05-06 02:59:24 -04:00
|
|
|
func.call(1,2,3)
|
|
|
|
end
|
2015-10-30 00:37:13 -04:00
|
|
|
assert_raise(ArgumentError) do
|
2010-05-06 02:59:24 -04:00
|
|
|
func.call
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_last_error
|
|
|
|
func = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP)
|
|
|
|
|
|
|
|
assert_nil Fiddle.last_error
|
2014-02-24 04:12:18 -05:00
|
|
|
func.call("000", "123")
|
2010-05-06 02:59:24 -04:00
|
|
|
refute_nil Fiddle.last_error
|
|
|
|
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
|
2014-03-08 23:51:38 -05:00
|
|
|
|
2015-11-23 16:20:56 -05:00
|
|
|
def test_nogvl_poll
|
|
|
|
begin
|
|
|
|
poll = @libc['poll']
|
|
|
|
rescue Fiddle::DLError
|
|
|
|
skip '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, 100, 'slept correct amount of time')
|
|
|
|
assert_equal(0, n1, 'poll(2) called correctly main-thread')
|
|
|
|
assert_equal(0, n2, 'poll(2) called correctly in sub-thread')
|
|
|
|
end
|
|
|
|
|
2014-03-08 23:51:38 -05:00
|
|
|
def test_no_memory_leak
|
|
|
|
prep = 'r = Fiddle::Function.new(Fiddle.dlopen(nil)["rb_obj_tainted"], [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
|
2010-05-06 02:59:24 -04:00
|
|
|
end
|
2011-01-23 08:20:58 -05:00
|
|
|
end if defined?(Fiddle)
|