summaryrefslogtreecommitdiff
path: root/test/fiddle
diff options
context:
space:
mode:
authorKenta Murata <mrkn@users.noreply.github.com>2020-12-11 09:41:12 +0900
committerGitHub <noreply@github.com>2020-12-11 09:41:12 +0900
commit9b0c36b39032cffff3c62a2b0e1fc38fa429f5ea (patch)
tree667648b7563a97e5d5270baccd5654d5de91358c /test/fiddle
parent6b1d2de6cc2e85fda7885fe77dbd7c99c4eb1ef2 (diff)
Import fiddle-1.0.4 (#3860)
I don't use tool/sync_default_gem.rb because the last sync was incomplete. Co-authored-by: Hiroshi SHIBATA <hsbt@ruby-lang.org> Co-authored-by: Alan Wu <XrXr@users.noreply.github.com> Co-authored-by: sinisterchipmunk <sinisterchipmunk@gmail.com> Co-authored-by: Sutou Kouhei <kou@clear-code.com>
Notes
Notes: Merged-By: mrkn <mrkn@ruby-lang.org>
Diffstat (limited to 'test/fiddle')
-rw-r--r--test/fiddle/test_c_struct_entry.rb130
-rw-r--r--test/fiddle/test_c_union_entity.rb15
-rw-r--r--test/fiddle/test_cparser.rb113
-rw-r--r--test/fiddle/test_function.rb14
-rw-r--r--test/fiddle/test_import.rb324
-rw-r--r--test/fiddle/test_memory_view.rb115
-rw-r--r--test/fiddle/test_pointer.rb85
7 files changed, 707 insertions, 89 deletions
diff --git a/test/fiddle/test_c_struct_entry.rb b/test/fiddle/test_c_struct_entry.rb
index 33bfee6218..9fd16d7101 100644
--- a/test/fiddle/test_c_struct_entry.rb
+++ b/test/fiddle/test_c_struct_entry.rb
@@ -43,35 +43,123 @@ module Fiddle
end
def test_set_ctypes
- union = CStructEntity.malloc [TYPE_INT, TYPE_LONG], Fiddle::RUBY_FREE
- union.assign_names %w[int long]
+ CStructEntity.malloc([TYPE_INT, TYPE_LONG], Fiddle::RUBY_FREE) do |struct|
+ struct.assign_names %w[int long]
- # this test is roundabout because the stored ctypes are not accessible
- union['long'] = 1
- union['int'] = 2
+ # this test is roundabout because the stored ctypes are not accessible
+ struct['long'] = 1
+ struct['int'] = 2
- assert_equal 1, union['long']
- assert_equal 2, union['int']
+ assert_equal 1, struct['long']
+ assert_equal 2, struct['int']
+ end
end
def test_aref_pointer_array
- team = CStructEntity.malloc([[TYPE_VOIDP, 2]], Fiddle::RUBY_FREE)
- team.assign_names(["names"])
- alice = Fiddle::Pointer.malloc(6, Fiddle::RUBY_FREE)
- alice[0, 6] = "Alice\0"
- bob = Fiddle::Pointer.malloc(4, Fiddle::RUBY_FREE)
- bob[0, 4] = "Bob\0"
- team["names"] = [alice, bob]
- assert_equal(["Alice", "Bob"], team["names"].map(&:to_s))
+ CStructEntity.malloc([[TYPE_VOIDP, 2]], Fiddle::RUBY_FREE) do |team|
+ team.assign_names(["names"])
+ Fiddle::Pointer.malloc(6, Fiddle::RUBY_FREE) do |alice|
+ alice[0, 6] = "Alice\0"
+ Fiddle::Pointer.malloc(4, Fiddle::RUBY_FREE) do |bob|
+ bob[0, 4] = "Bob\0"
+ team["names"] = [alice, bob]
+ assert_equal(["Alice", "Bob"], team["names"].map(&:to_s))
+ end
+ end
+ end
end
def test_aref_pointer
- user = CStructEntity.malloc([TYPE_VOIDP], Fiddle::RUBY_FREE)
- user.assign_names(["name"])
- alice = Fiddle::Pointer.malloc(6, Fiddle::RUBY_FREE)
- alice[0, 6] = "Alice\0"
- user["name"] = alice
- assert_equal("Alice", user["name"].to_s)
+ CStructEntity.malloc([TYPE_VOIDP], Fiddle::RUBY_FREE) do |user|
+ user.assign_names(["name"])
+ Fiddle::Pointer.malloc(6, Fiddle::RUBY_FREE) do |alice|
+ alice[0, 6] = "Alice\0"
+ user["name"] = alice
+ assert_equal("Alice", user["name"].to_s)
+ end
+ end
+ end
+
+ def test_new_double_free
+ types = [TYPE_INT]
+ Pointer.malloc(CStructEntity.size(types), Fiddle::RUBY_FREE) do |pointer|
+ assert_raise ArgumentError do
+ CStructEntity.new(pointer, types, Fiddle::RUBY_FREE)
+ end
+ end
+ end
+
+ def test_malloc_block
+ escaped_struct = nil
+ returned = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) do |struct|
+ assert_equal Fiddle::SIZEOF_INT, struct.size
+ assert_equal Fiddle::RUBY_FREE, struct.free.to_i
+ escaped_struct = struct
+ :returned
+ end
+ assert_equal :returned, returned
+ assert escaped_struct.freed?
+ end
+
+ def test_malloc_block_no_free
+ assert_raise ArgumentError do
+ CStructEntity.malloc([TYPE_INT]) { |struct| }
+ end
+ end
+
+ def test_free
+ struct = CStructEntity.malloc([TYPE_INT])
+ begin
+ assert_nil struct.free
+ ensure
+ Fiddle.free struct
+ end
+ end
+
+ def test_free_with_func
+ struct = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE)
+ refute struct.freed?
+ struct.call_free
+ assert struct.freed?
+ struct.call_free # you can safely run it again
+ assert struct.freed?
+ GC.start # you can safely run the GC routine
+ assert struct.freed?
+ end
+
+ def test_free_with_no_func
+ struct = CStructEntity.malloc([TYPE_INT])
+ refute struct.freed?
+ struct.call_free
+ refute struct.freed?
+ struct.call_free # you can safely run it again
+ refute struct.freed?
+ end
+
+ def test_freed?
+ struct = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE)
+ refute struct.freed?
+ struct.call_free
+ assert struct.freed?
+ end
+
+ def test_null?
+ struct = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE)
+ refute struct.null?
+ end
+
+ def test_size
+ CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) do |struct|
+ assert_equal Fiddle::SIZEOF_INT, struct.size
+ end
+ end
+
+ def test_size=
+ CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) do |struct|
+ assert_raise NoMethodError do
+ struct.size = 1
+ end
+ end
end
end
end if defined?(Fiddle)
diff --git a/test/fiddle/test_c_union_entity.rb b/test/fiddle/test_c_union_entity.rb
index 9310084733..e0a3757562 100644
--- a/test/fiddle/test_c_union_entity.rb
+++ b/test/fiddle/test_c_union_entity.rb
@@ -21,15 +21,16 @@ module Fiddle
end
def test_set_ctypes
- union = CUnionEntity.malloc [TYPE_INT, TYPE_LONG], Fiddle::RUBY_FREE
- union.assign_names %w[int long]
+ CUnionEntity.malloc([TYPE_INT, TYPE_LONG], Fiddle::RUBY_FREE) do |union|
+ union.assign_names %w[int long]
- # this test is roundabout because the stored ctypes are not accessible
- union['long'] = 1
- assert_equal 1, union['long']
+ # this test is roundabout because the stored ctypes are not accessible
+ union['long'] = 1
+ assert_equal 1, union['long']
- union['int'] = 1
- assert_equal 1, union['int']
+ union['int'] = 1
+ assert_equal 1, union['int']
+ end
end
end
end if defined?(Fiddle)
diff --git a/test/fiddle/test_cparser.rb b/test/fiddle/test_cparser.rb
index 5d9ac3c815..ef8cec5daa 100644
--- a/test/fiddle/test_cparser.rb
+++ b/test/fiddle/test_cparser.rb
@@ -2,6 +2,7 @@
begin
require_relative 'helper'
require 'fiddle/cparser'
+ require 'fiddle/import'
rescue LoadError
end
@@ -68,6 +69,19 @@ module Fiddle
assert_equal(-TYPE_LONG, parse_ctype('DWORD', {"DWORD" => "unsigned long"}))
end
+ def expand_struct_types(types)
+ types.collect do |type|
+ case type
+ when Class
+ [expand_struct_types(type.types)]
+ when Array
+ [expand_struct_types([type[0]])[0][0], type[1]]
+ else
+ type
+ end
+ end
+ end
+
def test_struct_basic
assert_equal [[TYPE_INT, TYPE_CHAR], ['i', 'c']], parse_struct_signature(['int i', 'char c'])
end
@@ -76,6 +90,93 @@ module Fiddle
assert_equal [[[TYPE_CHAR,80],[TYPE_INT,5]], ['buffer','x']], parse_struct_signature(['char buffer[80]', 'int[5] x'])
end
+ def test_struct_nested_struct
+ types, members = parse_struct_signature([
+ 'int x',
+ {inner: ['int i', 'char c']},
+ ])
+ assert_equal([[TYPE_INT, [[TYPE_INT, TYPE_CHAR]]],
+ ['x', ['inner', ['i', 'c']]]],
+ [expand_struct_types(types),
+ members])
+ end
+
+ def test_struct_nested_defined_struct
+ inner = Fiddle::Importer.struct(['int i', 'char c'])
+ assert_equal([[TYPE_INT, inner],
+ ['x', ['inner', ['i', 'c']]]],
+ parse_struct_signature([
+ 'int x',
+ {inner: inner},
+ ]))
+ end
+
+ def test_struct_double_nested_struct
+ types, members = parse_struct_signature([
+ 'int x',
+ {
+ outer: [
+ 'int y',
+ {inner: ['int i', 'char c']},
+ ],
+ },
+ ])
+ assert_equal([[TYPE_INT, [[TYPE_INT, [[TYPE_INT, TYPE_CHAR]]]]],
+ ['x', ['outer', ['y', ['inner', ['i', 'c']]]]]],
+ [expand_struct_types(types),
+ members])
+ end
+
+ def test_struct_nested_struct_array
+ types, members = parse_struct_signature([
+ 'int x',
+ {
+ 'inner[2]' => [
+ 'int i',
+ 'char c',
+ ],
+ },
+ ])
+ assert_equal([[TYPE_INT, [[TYPE_INT, TYPE_CHAR], 2]],
+ ['x', ['inner', ['i', 'c']]]],
+ [expand_struct_types(types),
+ members])
+ end
+
+ def test_struct_double_nested_struct_inner_array
+ types, members = parse_struct_signature(outer: [
+ 'int x',
+ {
+ 'inner[2]' => [
+ 'int i',
+ 'char c',
+ ],
+ },
+ ])
+ assert_equal([[[[TYPE_INT, [[TYPE_INT, TYPE_CHAR], 2]]]],
+ [['outer', ['x', ['inner', ['i', 'c']]]]]],
+ [expand_struct_types(types),
+ members])
+ end
+
+ def test_struct_double_nested_struct_outer_array
+ types, members = parse_struct_signature([
+ 'int x',
+ {
+ 'outer[2]' => {
+ inner: [
+ 'int i',
+ 'char c',
+ ],
+ },
+ },
+ ])
+ assert_equal([[TYPE_INT, [[[[TYPE_INT, TYPE_CHAR]]], 2]],
+ ['x', ['outer', [['inner', ['i', 'c']]]]]],
+ [expand_struct_types(types),
+ members])
+ end
+
def test_struct_array_str
assert_equal [[[TYPE_CHAR,80],[TYPE_INT,5]], ['buffer','x']], parse_struct_signature('char buffer[80], int[5] x')
end
@@ -179,6 +280,18 @@ module Fiddle
assert_equal [TYPE_VOIDP, TYPE_INT, TYPE_INT], args
end
+ def test_signature_variadic_arguments
+ unless Fiddle.const_defined?("TYPE_VARIADIC")
+ skip "libffi doesn't support variadic arguments"
+ end
+ assert_equal([
+ "printf",
+ TYPE_INT,
+ [TYPE_VOIDP, TYPE_VARIADIC],
+ ],
+ parse_signature('int printf(const char *format, ...)'))
+ end
+
def test_signature_return_pointer
func, ret, args = parse_signature('void* malloc(size_t)')
assert_equal 'malloc', func
diff --git a/test/fiddle/test_function.rb b/test/fiddle/test_function.rb
index 0bb66f9b8d..742615a56b 100644
--- a/test/fiddle/test_function.rb
+++ b/test/fiddle/test_function.rb
@@ -21,6 +21,17 @@ module Fiddle
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)
@@ -111,8 +122,7 @@ module Fiddle
n1 = f.call(nil, 0, msec)
n2 = th.value
t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
- delta = EnvUtil.apply_timeout_scale(180)
- assert_in_delta(msec, t1 - t0, delta, 'slept amount of time')
+ 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
diff --git a/test/fiddle/test_import.rb b/test/fiddle/test_import.rb
index 4afd8e5562..afa8df9e00 100644
--- a/test/fiddle/test_import.rb
+++ b/test/fiddle/test_import.rb
@@ -36,6 +36,29 @@ module Fiddle
"char c",
"unsigned char buff[7]",
]
+ StructNestedStruct = struct [
+ {
+ "vertices[2]" => {
+ position: ["float x", "float y", "float z"],
+ texcoord: ["float u", "float v"]
+ },
+ object: ["int id", "void *user_data"],
+ },
+ "int id"
+ ]
+ UnionNestedStruct = union [
+ {
+ keyboard: [
+ 'unsigned int state',
+ 'char key'
+ ],
+ mouse: [
+ 'unsigned int button',
+ 'unsigned short x',
+ 'unsigned short y'
+ ]
+ }
+ ]
CallCallback = bind("void call_callback(void*, void*)"){ | ptr1, ptr2|
f = Function.new(ptr1.to_i, [TYPE_VOIDP], TYPE_VOID)
@@ -56,22 +79,18 @@ module Fiddle
def test_struct_memory_access()
# check memory operations performed directly on struct
- my_struct = Fiddle::Importer.struct(['int id']).malloc
- begin
+ Fiddle::Importer.struct(['int id']).malloc(Fiddle::RUBY_FREE) do |my_struct|
my_struct[0, Fiddle::SIZEOF_INT] = "\x01".b * Fiddle::SIZEOF_INT
assert_equal 0x01010101, my_struct.id
my_struct.id = 0
assert_equal "\x00".b * Fiddle::SIZEOF_INT, my_struct[0, Fiddle::SIZEOF_INT]
- ensure
- Fiddle.free my_struct.to_ptr
end
end
def test_struct_ptr_array_subscript_multiarg()
# check memory operations performed on struct#to_ptr
- struct = Fiddle::Importer.struct([ 'int x' ]).malloc
- begin
+ Fiddle::Importer.struct([ 'int x' ]).malloc(Fiddle::RUBY_FREE) do |struct|
ptr = struct.to_ptr
struct.x = 0x02020202
@@ -79,35 +98,25 @@ module Fiddle
ptr[0, Fiddle::SIZEOF_INT] = "\x01".b * Fiddle::SIZEOF_INT
assert_equal 0x01010101, struct.x
- ensure
- Fiddle.free struct.to_ptr
end
end
def test_malloc()
- s1 = LIBC::Timeval.malloc()
- begin
- s2 = LIBC::Timeval.malloc()
- begin
+ LIBC::Timeval.malloc(Fiddle::RUBY_FREE) do |s1|
+ LIBC::Timeval.malloc(Fiddle::RUBY_FREE) do |s2|
refute_equal(s1.to_ptr.to_i, s2.to_ptr.to_i)
- ensure
- Fiddle.free s2.to_ptr
end
- ensure
- Fiddle.free s1.to_ptr
end
end
def test_sizeof()
assert_equal(SIZEOF_VOIDP, LIBC.sizeof("FILE*"))
assert_equal(LIBC::MyStruct.size(), LIBC.sizeof(LIBC::MyStruct))
- my_struct = LIBC::MyStruct.malloc()
- begin
+ LIBC::MyStruct.malloc(Fiddle::RUBY_FREE) do |my_struct|
assert_equal(LIBC::MyStruct.size(), LIBC.sizeof(my_struct))
- ensure
- Fiddle.free my_struct.to_ptr
end
assert_equal(SIZEOF_LONG_LONG, LIBC.sizeof("long long")) if defined?(SIZEOF_LONG_LONG)
+ assert_equal(LIBC::StructNestedStruct.size(), LIBC.sizeof(LIBC::StructNestedStruct))
end
Fiddle.constants.grep(/\ATYPE_(?!VOID|VARIADIC\z)(.*)/) do
@@ -158,8 +167,7 @@ module Fiddle
end
def test_struct_array_assignment()
- instance = Fiddle::Importer.struct(["unsigned int stages[3]"]).malloc
- begin
+ Fiddle::Importer.struct(["unsigned int stages[3]"]).malloc(Fiddle::RUBY_FREE) do |instance|
instance.stages[0] = 1024
instance.stages[1] = 10
instance.stages[2] = 100
@@ -170,39 +178,279 @@ module Fiddle
instance.to_ptr[0, 3 * Fiddle::SIZEOF_INT]
assert_raise(IndexError) { instance.stages[-1] = 5 }
assert_raise(IndexError) { instance.stages[3] = 5 }
- ensure
- Fiddle.free instance.to_ptr
+ end
+ end
+
+ def test_nested_struct_reusing_other_structs()
+ position_struct = Fiddle::Importer.struct(['float x', 'float y', 'float z'])
+ texcoord_struct = Fiddle::Importer.struct(['float u', 'float v'])
+ vertex_struct = Fiddle::Importer.struct(position: position_struct, texcoord: texcoord_struct)
+ mesh_struct = Fiddle::Importer.struct([
+ {
+ "vertices[2]" => vertex_struct,
+ object: [
+ "int id",
+ "void *user_data",
+ ],
+ },
+ "int id",
+ ])
+ assert_equal LIBC::StructNestedStruct.size, mesh_struct.size
+
+
+ keyboard_event_struct = Fiddle::Importer.struct(['unsigned int state', 'char key'])
+ mouse_event_struct = Fiddle::Importer.struct(['unsigned int button', 'unsigned short x', 'unsigned short y'])
+ event_union = Fiddle::Importer.union([{ keboard: keyboard_event_struct, mouse: mouse_event_struct}])
+ assert_equal LIBC::UnionNestedStruct.size, event_union.size
+ end
+
+ def test_nested_struct_alignment_is_not_its_size()
+ inner = Fiddle::Importer.struct(['int x', 'int y', 'int z', 'int w'])
+ outer = Fiddle::Importer.struct(['char a', { 'nested' => inner }, 'char b'])
+ outer.malloc(Fiddle::RUBY_FREE) do |instance|
+ offset = instance.to_ptr.instance_variable_get(:"@offset")
+ assert_equal Fiddle::SIZEOF_INT * 5, offset.last
+ assert_equal Fiddle::SIZEOF_INT * 6, outer.size
+ assert_equal instance.to_ptr.size, outer.size
+ end
+ end
+
+ def test_struct_nested_struct_members()
+ LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s|
+ Fiddle::Pointer.malloc(24, Fiddle::RUBY_FREE) do |user_data|
+ s.vertices[0].position.x = 1
+ s.vertices[0].position.y = 2
+ s.vertices[0].position.z = 3
+ s.vertices[0].texcoord.u = 4
+ s.vertices[0].texcoord.v = 5
+ s.vertices[1].position.x = 6
+ s.vertices[1].position.y = 7
+ s.vertices[1].position.z = 8
+ s.vertices[1].texcoord.u = 9
+ s.vertices[1].texcoord.v = 10
+ s.object.id = 100
+ s.object.user_data = user_data
+ s.id = 101
+ assert_equal({
+ "vertices" => [
+ {
+ "position" => {
+ "x" => 1,
+ "y" => 2,
+ "z" => 3,
+ },
+ "texcoord" => {
+ "u" => 4,
+ "v" => 5,
+ },
+ },
+ {
+ "position" => {
+ "x" => 6,
+ "y" => 7,
+ "z" => 8,
+ },
+ "texcoord" => {
+ "u" => 9,
+ "v" => 10,
+ },
+ },
+ ],
+ "object" => {
+ "id" => 100,
+ "user_data" => user_data,
+ },
+ "id" => 101,
+ },
+ s.to_h)
+ end
+ end
+ end
+
+ def test_union_nested_struct_members()
+ LIBC::UnionNestedStruct.malloc(Fiddle::RUBY_FREE) do |s|
+ s.keyboard.state = 100
+ s.keyboard.key = 101
+ assert_equal(100, s.mouse.button)
+ refute_equal( 0, s.mouse.x)
+ end
+ end
+
+ def test_struct_nested_struct_replace_array_element()
+ LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s|
+ s.vertices[0].position.x = 5
+
+ vertex_struct = Fiddle::Importer.struct [{
+ position: ["float x", "float y", "float z"],
+ texcoord: ["float u", "float v"]
+ }]
+ vertex_struct.malloc(Fiddle::RUBY_FREE) do |vertex|
+ vertex.position.x = 100
+ s.vertices[0] = vertex
+
+ # make sure element was copied by value, but things like memory address
+ # should not be changed
+ assert_equal(100, s.vertices[0].position.x)
+ refute_equal(vertex.object_id, s.vertices[0].object_id)
+ refute_equal(vertex.to_ptr, s.vertices[0].to_ptr)
+ end
+ end
+ end
+
+ def test_struct_nested_struct_replace_array_element_nil()
+ LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s|
+ s.vertices[0].position.x = 5
+ s.vertices[0] = nil
+ assert_equal({
+ "position" => {
+ "x" => 0.0,
+ "y" => 0.0,
+ "z" => 0.0,
+ },
+ "texcoord" => {
+ "u" => 0.0,
+ "v" => 0.0,
+ },
+ },
+ s.vertices[0].to_h)
+ end
+ end
+
+ def test_struct_nested_struct_replace_array_element_hash()
+ LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s|
+ s.vertices[0] = {
+ position: {
+ x: 10,
+ y: 100,
+ }
+ }
+ assert_equal({
+ "position" => {
+ "x" => 10.0,
+ "y" => 100.0,
+ "z" => 0.0,
+ },
+ "texcoord" => {
+ "u" => 0.0,
+ "v" => 0.0,
+ },
+ },
+ s.vertices[0].to_h)
+ end
+ end
+
+ def test_struct_nested_struct_replace_entire_array()
+ LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s|
+ vertex_struct = Fiddle::Importer.struct [{
+ position: ["float x", "float y", "float z"],
+ texcoord: ["float u", "float v"]
+ }]
+
+ vertex_struct.malloc(Fiddle::RUBY_FREE) do |same0|
+ vertex_struct.malloc(Fiddle::RUBY_FREE) do |same1|
+ same = [same0, same1]
+ same[0].position.x = 1; same[1].position.x = 6
+ same[0].position.y = 2; same[1].position.y = 7
+ same[0].position.z = 3; same[1].position.z = 8
+ same[0].texcoord.u = 4; same[1].texcoord.u = 9
+ same[0].texcoord.v = 5; same[1].texcoord.v = 10
+ s.vertices = same
+ assert_equal([
+ {
+ "position" => {
+ "x" => 1.0,
+ "y" => 2.0,
+ "z" => 3.0,
+ },
+ "texcoord" => {
+ "u" => 4.0,
+ "v" => 5.0,
+ },
+ },
+ {
+ "position" => {
+ "x" => 6.0,
+ "y" => 7.0,
+ "z" => 8.0,
+ },
+ "texcoord" => {
+ "u" => 9.0,
+ "v" => 10.0,
+ },
+ }
+ ],
+ s.vertices.collect(&:to_h))
+ end
+ end
+ end
+ end
+
+ def test_struct_nested_struct_replace_entire_array_with_different_struct()
+ LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s|
+ different_struct_same_size = Fiddle::Importer.struct [{
+ a: ['float i', 'float j', 'float k'],
+ b: ['float l', 'float m']
+ }]
+
+ different_struct_same_size.malloc(Fiddle::RUBY_FREE) do |different0|
+ different_struct_same_size.malloc(Fiddle::RUBY_FREE) do |different1|
+ different = [different0, different1]
+ different[0].a.i = 11; different[1].a.i = 16
+ different[0].a.j = 12; different[1].a.j = 17
+ different[0].a.k = 13; different[1].a.k = 18
+ different[0].b.l = 14; different[1].b.l = 19
+ different[0].b.m = 15; different[1].b.m = 20
+ s.vertices[0][0, s.vertices[0].class.size] = different[0].to_ptr
+ s.vertices[1][0, s.vertices[1].class.size] = different[1].to_ptr
+ assert_equal([
+ {
+ "position" => {
+ "x" => 11.0,
+ "y" => 12.0,
+ "z" => 13.0,
+ },
+ "texcoord" => {
+ "u" => 14.0,
+ "v" => 15.0,
+ },
+ },
+ {
+ "position" => {
+ "x" => 16.0,
+ "y" => 17.0,
+ "z" => 18.0,
+ },
+ "texcoord" => {
+ "u" => 19.0,
+ "v" => 20.0,
+ },
+ }
+ ],
+ s.vertices.collect(&:to_h))
+ end
+ end
end
end
def test_struct()
- s = LIBC::MyStruct.malloc()
- begin
+ LIBC::MyStruct.malloc(Fiddle::RUBY_FREE) do |s|
s.num = [0,1,2,3,4]
s.c = ?a.ord
s.buff = "012345\377"
assert_equal([0,1,2,3,4], s.num)
assert_equal(?a.ord, s.c)
assert_equal([?0.ord,?1.ord,?2.ord,?3.ord,?4.ord,?5.ord,?\377.ord], s.buff)
- ensure
- Fiddle.free s.to_ptr
end
end
def test_gettimeofday()
if( defined?(LIBC.gettimeofday) )
- timeval = LIBC::Timeval.malloc()
- begin
- timezone = LIBC::Timezone.malloc()
- begin
+ LIBC::Timeval.malloc(Fiddle::RUBY_FREE) do |timeval|
+ LIBC::Timezone.malloc(Fiddle::RUBY_FREE) do |timezone|
LIBC.gettimeofday(timeval, timezone)
- ensure
- Fiddle.free timezone.to_ptr
end
cur = Time.now()
assert(cur.to_i - 2 <= timeval.tv_sec && timeval.tv_sec <= cur.to_i)
- ensure
- Fiddle.free timeval.to_ptr
end
end
end
@@ -227,9 +475,5 @@ module Fiddle
r = LIBC.atof("12.34")
assert_includes(12.00..13.00, r)
end
-
- def test_no_message_with_debug
- assert_in_out_err(%w[--debug --disable=gems -rfiddle/import], 'p Fiddle::Importer', ['Fiddle::Importer'])
- end
end
end if defined?(Fiddle)
diff --git a/test/fiddle/test_memory_view.rb b/test/fiddle/test_memory_view.rb
new file mode 100644
index 0000000000..3c310c2d68
--- /dev/null
+++ b/test/fiddle/test_memory_view.rb
@@ -0,0 +1,115 @@
+# frozen_string_literal: true
+begin
+ require_relative 'helper'
+rescue LoadError
+end
+
+begin
+ require '-test-/memory_view'
+rescue LoadError
+end
+
+module Fiddle
+ class TestMemoryView < TestCase
+ def setup
+ skip "MemoryView is unavailable" unless defined? Fiddle::MemoryView
+ end
+
+ def test_null_ptr
+ assert_raise(ArgumentError) do
+ MemoryView.new(Fiddle::NULL)
+ end
+ end
+
+ def test_memory_view_from_unsupported_obj
+ obj = Object.new
+ assert_raise(ArgumentError) do
+ MemoryView.new(obj)
+ end
+ end
+
+ def test_memory_view_from_pointer
+ str = Marshal.load(Marshal.dump("hello world"))
+ ptr = Pointer[str]
+ mview = MemoryView.new(ptr)
+ assert_same(ptr, mview.obj)
+ assert_equal(str.length, mview.length)
+ assert_equal(true, mview.readonly?)
+ assert_equal(nil, mview.format)
+ assert_equal(1, mview.item_size)
+ assert_equal(1, mview.ndim)
+ assert_equal(nil, mview.shape)
+ assert_equal(nil, mview.strides)
+ assert_equal(nil, mview.sub_offsets)
+
+ codes = str.codepoints
+ assert_equal(codes, (0...str.length).map {|i| mview[i] })
+ end
+
+ def test_memory_view_multi_dimensional
+ skip "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils
+
+ buf = [ 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12 ].pack("l!*")
+ shape = [3, 4]
+ md = MemoryViewTestUtils::MultiDimensionalView.new(buf, "l!", shape, nil)
+ mview = Fiddle::MemoryView.new(md)
+ assert_equal(buf.length, mview.length)
+ assert_equal("l!", mview.format)
+ assert_equal(Fiddle::SIZEOF_LONG, mview.item_size)
+ assert_equal(2, mview.ndim)
+ assert_equal(shape, mview.shape)
+ assert_equal([Fiddle::SIZEOF_LONG*4, Fiddle::SIZEOF_LONG], mview.strides)
+ assert_equal(nil, mview.sub_offsets)
+ assert_equal(1, mview[0, 0])
+ assert_equal(4, mview[0, 3])
+ assert_equal(6, mview[1, 1])
+ assert_equal(10, mview[2, 1])
+ end
+
+ def test_memory_view_multi_dimensional_with_strides
+ skip "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils
+
+ buf = [ 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16 ].pack("l!*")
+ shape = [2, 8]
+ strides = [4*Fiddle::SIZEOF_LONG*2, Fiddle::SIZEOF_LONG*2]
+ md = MemoryViewTestUtils::MultiDimensionalView.new(buf, "l!", shape, strides)
+ mview = Fiddle::MemoryView.new(md)
+ assert_equal("l!", mview.format)
+ assert_equal(Fiddle::SIZEOF_LONG, mview.item_size)
+ assert_equal(buf.length, mview.length)
+ assert_equal(2, mview.ndim)
+ assert_equal(shape, mview.shape)
+ assert_equal(strides, mview.strides)
+ assert_equal(nil, mview.sub_offsets)
+ assert_equal(1, mview[0, 0])
+ assert_equal(5, mview[0, 2])
+ assert_equal(9, mview[1, 0])
+ assert_equal(15, mview[1, 3])
+ end
+
+ def test_memory_view_multi_dimensional_with_multiple_members
+ skip "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils
+
+ buf = [ 1, 2, 3, 4, 5, 6, 7, 8,
+ -1, -2, -3, -4, -5, -6, -7, -8].pack("s*")
+ shape = [2, 4]
+ strides = [4*Fiddle::SIZEOF_SHORT*2, Fiddle::SIZEOF_SHORT*2]
+ md = MemoryViewTestUtils::MultiDimensionalView.new(buf, "ss", shape, strides)
+ mview = Fiddle::MemoryView.new(md)
+ assert_equal("ss", mview.format)
+ assert_equal(Fiddle::SIZEOF_SHORT*2, mview.item_size)
+ assert_equal(buf.length, mview.length)
+ assert_equal(2, mview.ndim)
+ assert_equal(shape, mview.shape)
+ assert_equal(strides, mview.strides)
+ assert_equal(nil, mview.sub_offsets)
+ assert_equal([1, 2], mview[0, 0])
+ assert_equal([5, 6], mview[0, 2])
+ assert_equal([-1, -2], mview[1, 0])
+ assert_equal([-7, -8], mview[1, 3])
+ end
+ end
+end
diff --git a/test/fiddle/test_pointer.rb b/test/fiddle/test_pointer.rb
index c69e4f7142..e685fea5dc 100644
--- a/test/fiddle/test_pointer.rb
+++ b/test/fiddle/test_pointer.rb
@@ -32,6 +32,31 @@ module Fiddle
assert_equal free.to_i, ptr.free.to_i
end
+ def test_malloc_block
+ escaped_ptr = nil
+ returned = Pointer.malloc(10, Fiddle::RUBY_FREE) do |ptr|
+ assert_equal 10, ptr.size
+ assert_equal Fiddle::RUBY_FREE, ptr.free.to_i
+ escaped_ptr = ptr
+ :returned
+ end
+ assert_equal :returned, returned
+ assert escaped_ptr.freed?
+ end
+
+ def test_malloc_block_no_free
+ assert_raise ArgumentError do
+ Pointer.malloc(10) { |ptr| }
+ end
+ end
+
+ def test_malloc_subclass
+ subclass = Class.new(Pointer)
+ subclass.malloc(10, Fiddle::RUBY_FREE) do |ptr|
+ assert ptr.is_a?(subclass)
+ end
+ end
+
def test_to_str
str = Marshal.load(Marshal.dump("hello world"))
ptr = Pointer[str]
@@ -84,17 +109,18 @@ module Fiddle
end
def test_to_ptr_io
- buf = Pointer.malloc(10, Fiddle::RUBY_FREE)
- File.open(__FILE__, 'r') do |f|
- ptr = Pointer.to_ptr f
- fread = Function.new(@libc['fread'],
- [TYPE_VOIDP, TYPE_INT, TYPE_INT, TYPE_VOIDP],
- TYPE_INT)
- fread.call(buf.to_i, Fiddle::SIZEOF_CHAR, buf.size - 1, ptr.to_i)
- end
-
- File.open(__FILE__, 'r') do |f|
- assert_equal f.read(9), buf.to_s
+ Pointer.malloc(10, Fiddle::RUBY_FREE) do |buf|
+ File.open(__FILE__, 'r') do |f|
+ ptr = Pointer.to_ptr f
+ fread = Function.new(@libc['fread'],
+ [TYPE_VOIDP, TYPE_INT, TYPE_INT, TYPE_VOIDP],
+ TYPE_INT)
+ fread.call(buf.to_i, Fiddle::SIZEOF_CHAR, buf.size - 1, ptr.to_i)
+ end
+
+ File.open(__FILE__, 'r') do |f|
+ assert_equal f.read(9), buf.to_s
+ end
end
end
@@ -170,27 +196,48 @@ module Fiddle
assert_equal free.ptr, ptr.free.ptr
end
+ def test_free_with_func
+ ptr = Pointer.malloc(4, Fiddle::RUBY_FREE)
+ refute ptr.freed?
+ ptr.call_free
+ assert ptr.freed?
+ ptr.call_free # you can safely run it again
+ assert ptr.freed?
+ GC.start # you can safely run the GC routine
+ assert ptr.freed?
+ end
+
+ def test_free_with_no_func
+ ptr = Pointer.malloc(4)
+ refute ptr.freed?
+ ptr.call_free
+ refute ptr.freed?
+ ptr.call_free # you can safely run it again
+ refute ptr.freed?
+ end
+
+ def test_freed?
+ ptr = Pointer.malloc(4, Fiddle::RUBY_FREE)
+ refute ptr.freed?
+ ptr.call_free
+ assert ptr.freed?
+ end
+
def test_null?
ptr = Pointer.new(0)
assert ptr.null?
end
def test_size
- ptr = Pointer.malloc(4)
- begin
+ Pointer.malloc(4, Fiddle::RUBY_FREE) do |ptr|
assert_equal 4, ptr.size
- ensure
- Fiddle.free ptr
end
end
def test_size=
- ptr = Pointer.malloc(4)
- begin
+ Pointer.malloc(4, Fiddle::RUBY_FREE) do |ptr|
ptr.size = 10
assert_equal 10, ptr.size
- ensure
- Fiddle.free ptr
end
end