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
|
#
# This file is part of ruby-ffi.
# For licensing, see LICENSE.SPECS
#
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
describe "Function with variadic arguments" do
module LibTest
extend FFI::Library
ffi_lib TestLibrary::PATH
enum :enum_type1, [:c1, :c2]
enum :enum_type2, [:c3, 42, :c4]
attach_function :pack_varargs, [ :buffer_out, :string, :varargs ], :void
attach_function :pack_varargs2, [ :buffer_out, :enum_type1, :string, :varargs ], :enum_type1
attach_function :testBlockingOpen, [ ], :pointer
attach_function :testBlockingRWva, [ :pointer, :char, :varargs ], :char, :blocking => true
attach_function :testBlockingWRva, [ :pointer, :char, :varargs ], :char, :blocking => true
attach_function :testBlockingClose, [ :pointer ], :void
end
it "takes enum arguments" do
buf = FFI::Buffer.new :long_long, 2
LibTest.pack_varargs(buf, "ii", :int, :c3, :int, :c4)
expect(buf.get_int64(0)).to eq(42)
expect(buf.get_int64(8)).to eq(43)
end
it "returns symbols for enums" do
buf = FFI::Buffer.new :long_long, 2
expect(LibTest.pack_varargs2(buf, :c1, "ii", :int, :c3, :int, :c4)).to eq(:c2)
end
it 'can wrap a blocking function with varargs' do
pending("not supported in 1.8") if RUBY_VERSION =~ /^1\.8\..*/
handle = LibTest.testBlockingOpen
expect(handle).not_to be_null
begin
thWR = Thread.new { LibTest.testBlockingWRva(handle, 63, :int, 40, :int, 23, :int, 0) }
thRW = Thread.new { LibTest.testBlockingRWva(handle, 64, :int, 40, :int, 24, :int, 0) }
expect(thWR.value).to eq(64)
expect(thRW.value).to eq(63)
ensure
LibTest.testBlockingClose(handle)
end
end
[ 0, 127, -128, -1 ].each do |i|
it "call variadic with (:char (#{i})) argument" do
buf = FFI::Buffer.new :long_long
LibTest.pack_varargs(buf, "c", :char, i)
expect(buf.get_int64(0)).to eq(i)
end
end
[ 0, 0x7f, 0x80, 0xff ].each do |i|
it "call variadic with (:uchar (#{i})) argument" do
buf = FFI::Buffer.new :long_long
LibTest.pack_varargs(buf, "C", :uchar, i)
expect(buf.get_int64(0)).to eq(i)
end
end
[ 0, 1.234567, 9.87654321 ].each do |v|
it "call variadic with (:float (#{v})) argument" do
buf = FFI::Buffer.new :long_long
LibTest.pack_varargs(buf, "f", :float, v.to_f)
expect(buf.get_float64(0)).to eq(v)
end
end
[ 0, 1.234567, 9.87654321 ].each do |v|
it "call variadic with (:double (#{v})) argument" do
buf = FFI::Buffer.new :long_long
LibTest.pack_varargs(buf, "f", :double, v.to_f)
expect(buf.get_float64(0)).to eq(v)
end
end
module Varargs
PACK_VALUES = {
'c' => [ 0x12 ],
'C' => [ 0x34 ],
's' => [ 0x5678 ],
'S' => [ 0x9abc ],
'i' => [ 0x7654321f ],
'I' => [ 0xfee1babe ],
'l' => [ 0x1f2e3d4c ],
'L' => [ 0xf7e8d9ca ],
'j' => [ 0x1eafdeadbeefa1b2 ],
'f' => [ 1.23456789 ],
'd' => [ 9.87654321 ]
}
TYPE_MAP = {
'c' => :char, 'C' => :uchar, 's' => :short, 'S' => :ushort,
'i' => :int, 'I' => :uint, 'j' => :long_long, 'J' => :ulong_long,
'l' => :long, 'L' => :ulong, 'f' => :float, 'd' => :double
}
end
def verify(p, off, v)
if v.kind_of?(Float)
expect(p.get_float64(off)).to eq(v)
else
expect(p.get_int64(off)).to eq(v)
end
end
Varargs::PACK_VALUES.keys.each do |t1|
Varargs::PACK_VALUES.keys.each do |t2|
Varargs::PACK_VALUES.keys.each do |t3|
Varargs::PACK_VALUES[t1].each do |v1|
Varargs::PACK_VALUES[t2].each do |v2|
Varargs::PACK_VALUES[t3].each do |v3|
fmt = "#{t1}#{t2}#{t3}"
params = [ Varargs::TYPE_MAP[t1], v1, Varargs::TYPE_MAP[t2], v2, Varargs::TYPE_MAP[t3], v3 ]
it "call(#{fmt}, #{params.join(',')})" do
buf = FFI::Buffer.new :long_long, 3
LibTest.pack_varargs(buf, fmt, *params)
verify(buf, 0, v1)
verify(buf, 8, v2)
verify(buf, 16, v3)
end
end
end
end
end
end
end
end
|