1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
# 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
if RUBY_ENGINE == "jruby"
omit("Function that returns string doesn't work with JRuby")
end
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
if RUBY_ENGINE == "jruby"
omit("The untouched sanity check is broken on JRuby: https://github.com/jruby/jruby/issues/8365")
end
closure_class = Class.new(Closure) do
def call(x, y)
Pointer.new(x)[0] <=> Pointer.new(y)[0]
end
end
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)
untouched = "9341"
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, callback)
end
assert_equal("1349", buff, bug4929)
# Ensure the test didn't mutate String literals
assert_equal("93" + "41", untouched)
end
ensure
# We can't use ObjectSpace with JRuby.
unless RUBY_ENGINE == "jruby"
# 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
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)
Pointer.malloc(1024, Fiddle::RUBY_FREE) do |output|
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[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[0, written])
end
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)
|