ffi 1.2.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ffi might be problematic. Click here for more details.
- data/README.md +10 -5
- data/ext/ffi_c/ArrayType.c +6 -2
- data/ext/ffi_c/Buffer.c +3 -1
- data/ext/ffi_c/Call.c +12 -21
- data/ext/ffi_c/FunctionInfo.c +27 -2
- data/ext/ffi_c/MappedType.c +1 -2
- data/ext/ffi_c/MemoryPointer.c +35 -4
- data/ext/ffi_c/Pointer.c +5 -4
- data/ext/ffi_c/Struct.c +125 -8
- data/ext/ffi_c/StructByReference.c +33 -0
- data/ext/ffi_c/StructByValue.c +2 -2
- data/ext/ffi_c/StructLayout.c +135 -1
- data/ext/ffi_c/Type.c +1 -0
- data/ext/ffi_c/extconf.rb +1 -1
- data/ffi.gemspec +1 -1
- data/lib/ffi.rb +2 -1
- data/lib/ffi/library.rb +2 -0
- data/lib/ffi/managedstruct.rb +37 -37
- data/lib/ffi/struct.rb +74 -1
- data/lib/ffi/struct_layout_builder.rb +50 -1
- data/lib/ffi/tools/generator.rb +2 -0
- data/lib/ffi/tools/generator_task.rb +1 -0
- data/lib/ffi/tools/types_generator.rb +2 -0
- data/libtest/Benchmark.c +1 -15
- data/libtest/BoolTest.c +2 -16
- data/libtest/BufferTest.c +3 -17
- data/libtest/ClosureTest.c +1 -15
- data/libtest/EnumTest.c +1 -15
- data/libtest/FunctionTest.c +2 -16
- data/libtest/GlobalVariable.c +2 -16
- data/libtest/LastErrorTest.c +2 -16
- data/libtest/NumberTest.c +1 -15
- data/libtest/PointerTest.c +1 -15
- data/libtest/ReferenceTest.c +1 -15
- data/libtest/StringTest.c +1 -15
- data/libtest/StructTest.c +1 -15
- data/libtest/UnionTest.c +1 -15
- data/libtest/VariadicTest.c +2 -16
- data/spec/ffi/async_callback_spec.rb +3 -14
- data/spec/ffi/bool_spec.rb +7 -18
- data/spec/ffi/buffer_spec.rb +26 -37
- data/spec/ffi/callback_spec.rb +96 -107
- data/spec/ffi/custom_param_type.rb +2 -13
- data/spec/ffi/custom_type_spec.rb +1 -12
- data/spec/ffi/dup_spec.rb +7 -18
- data/spec/ffi/enum_spec.rb +128 -139
- data/spec/ffi/errno_spec.rb +2 -13
- data/spec/ffi/ffi_spec.rb +4 -15
- data/spec/ffi/function_spec.rb +6 -17
- data/spec/ffi/library_spec.rb +26 -26
- data/spec/ffi/long_double.rb +1 -12
- data/spec/ffi/managed_struct_spec.rb +3 -18
- data/spec/ffi/number_spec.rb +32 -43
- data/spec/ffi/pointer_spec.rb +7 -22
- data/spec/ffi/rbx/memory_pointer_spec.rb +17 -17
- data/spec/ffi/rbx/struct_spec.rb +2 -2
- data/spec/ffi/spec_helper.rb +10 -12
- data/spec/ffi/string_spec.rb +9 -20
- data/spec/ffi/strptr_spec.rb +2 -13
- data/spec/ffi/struct_callback_spec.rb +3 -14
- data/spec/ffi/struct_initialize_spec.rb +3 -14
- data/spec/ffi/struct_packed_spec.rb +7 -18
- data/spec/ffi/struct_spec.rb +93 -104
- data/spec/ffi/typedef_spec.rb +5 -16
- data/spec/ffi/union_spec.rb +4 -15
- data/spec/ffi/variadic_spec.rb +7 -18
- metadata +73 -58
data/spec/ffi/struct_spec.rb
CHANGED
@@ -1,17 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# This file is part of ruby-ffi.
|
3
|
-
#
|
4
|
-
# This code is free software: you can redistribute it and/or modify it under
|
5
|
-
# the terms of the GNU Lesser General Public License version 3 only, as
|
6
|
-
# published by the Free Software Foundation.
|
7
|
-
#
|
8
|
-
# This code is distributed in the hope that it will be useful, but WITHOUT
|
9
|
-
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
10
|
-
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
11
|
-
# version 3 for more details.
|
12
|
-
#
|
13
|
-
# You should have received a copy of the GNU Lesser General Public License
|
14
|
-
# version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
|
3
|
+
# For licensing, see LICENSE.SPECS
|
15
4
|
#
|
16
5
|
|
17
6
|
require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
|
@@ -49,7 +38,7 @@ describe "Struct tests" do
|
|
49
38
|
smp = FFI::MemoryPointer.new :pointer
|
50
39
|
smp.put_pointer(0, mp)
|
51
40
|
s = PointerMember.new smp
|
52
|
-
s[:pointer].should
|
41
|
+
s[:pointer].should == mp
|
53
42
|
end
|
54
43
|
it "Struct#[:pointer].nil? for NULL value" do
|
55
44
|
magic = 0x12345678
|
@@ -58,7 +47,7 @@ describe "Struct tests" do
|
|
58
47
|
smp = FFI::MemoryPointer.new :pointer
|
59
48
|
smp.put_pointer(0, nil)
|
60
49
|
s = PointerMember.new smp
|
61
|
-
s[:pointer].null?.should
|
50
|
+
s[:pointer].null?.should == true
|
62
51
|
end
|
63
52
|
it "Struct#[:pointer]=" do
|
64
53
|
magic = 0x12345678
|
@@ -67,7 +56,7 @@ describe "Struct tests" do
|
|
67
56
|
smp = FFI::MemoryPointer.new :pointer
|
68
57
|
s = PointerMember.new smp
|
69
58
|
s[:pointer] = mp
|
70
|
-
smp.get_pointer(0).should
|
59
|
+
smp.get_pointer(0).should == mp
|
71
60
|
end
|
72
61
|
it "Struct#[:pointer]=struct" do
|
73
62
|
smp = FFI::MemoryPointer.new :pointer
|
@@ -78,7 +67,7 @@ describe "Struct tests" do
|
|
78
67
|
smp = FFI::MemoryPointer.new :pointer
|
79
68
|
s = PointerMember.new smp
|
80
69
|
s[:pointer] = nil
|
81
|
-
smp.get_pointer(0).null?.should
|
70
|
+
smp.get_pointer(0).null?.should == true
|
82
71
|
end
|
83
72
|
it "Struct#[:string]" do
|
84
73
|
magic = "test"
|
@@ -87,50 +76,50 @@ describe "Struct tests" do
|
|
87
76
|
smp = FFI::MemoryPointer.new :pointer
|
88
77
|
smp.put_pointer(0, mp)
|
89
78
|
s = StringMember.new smp
|
90
|
-
s[:string].should
|
79
|
+
s[:string].should == magic
|
91
80
|
end
|
92
81
|
it "Struct#[:string].nil? for NULL value" do
|
93
82
|
smp = FFI::MemoryPointer.new :pointer
|
94
83
|
smp.put_pointer(0, nil)
|
95
84
|
s = StringMember.new smp
|
96
|
-
s[:string].nil?.should
|
85
|
+
s[:string].nil?.should == true
|
97
86
|
end
|
98
87
|
it "Struct#layout works with :name, :type pairs" do
|
99
88
|
class PairLayout < FFI::Struct
|
100
89
|
layout :a, :int, :b, :long_long
|
101
90
|
end
|
102
91
|
ll_off = (FFI::TYPE_UINT64.alignment == 4 ? 4 : 8)
|
103
|
-
PairLayout.size.should
|
92
|
+
PairLayout.size.should == (ll_off + 8)
|
104
93
|
mp = FFI::MemoryPointer.new(PairLayout.size)
|
105
94
|
s = PairLayout.new mp
|
106
95
|
s[:a] = 0x12345678
|
107
|
-
mp.get_int(0).should
|
96
|
+
mp.get_int(0).should == 0x12345678
|
108
97
|
s[:b] = 0xfee1deadbeef
|
109
|
-
mp.get_int64(ll_off).should
|
98
|
+
mp.get_int64(ll_off).should == 0xfee1deadbeef
|
110
99
|
end
|
111
100
|
it "Struct#layout works with :name, :type, offset tuples" do
|
112
101
|
class PairLayout < FFI::Struct
|
113
102
|
layout :a, :int, 0, :b, :long_long, 4
|
114
103
|
end
|
115
|
-
PairLayout.size.should
|
104
|
+
PairLayout.size.should == (FFI::TYPE_UINT64.alignment == 4 ? 12 : 16)
|
116
105
|
mp = FFI::MemoryPointer.new(PairLayout.size)
|
117
106
|
s = PairLayout.new mp
|
118
107
|
s[:a] = 0x12345678
|
119
|
-
mp.get_int(0).should
|
108
|
+
mp.get_int(0).should == 0x12345678
|
120
109
|
s[:b] = 0xfee1deadbeef
|
121
|
-
mp.get_int64(4).should
|
110
|
+
mp.get_int64(4).should == 0xfee1deadbeef
|
122
111
|
end
|
123
112
|
it "Struct#layout works with mixed :name,:type and :name,:type,offset" do
|
124
113
|
class MixedLayout < FFI::Struct
|
125
114
|
layout :a, :int, :b, :long_long, 4
|
126
115
|
end
|
127
|
-
MixedLayout.size.should
|
116
|
+
MixedLayout.size.should == (FFI::TYPE_UINT64.alignment == 4 ? 12 : 16)
|
128
117
|
mp = FFI::MemoryPointer.new(MixedLayout.size)
|
129
118
|
s = MixedLayout.new mp
|
130
119
|
s[:a] = 0x12345678
|
131
|
-
mp.get_int(0).should
|
120
|
+
mp.get_int(0).should == 0x12345678
|
132
121
|
s[:b] = 0xfee1deadbeef
|
133
|
-
mp.get_int64(4).should
|
122
|
+
mp.get_int64(4).should == 0xfee1deadbeef
|
134
123
|
end
|
135
124
|
rb_maj, rb_min = RUBY_VERSION.split('.')
|
136
125
|
if rb_maj.to_i >= 1 && rb_min.to_i >= 9 || RUBY_PLATFORM =~ /java/
|
@@ -139,13 +128,13 @@ describe "Struct tests" do
|
|
139
128
|
layout :a => :int, :b => :long_long
|
140
129
|
end
|
141
130
|
ll_off = (FFI::TYPE_UINT64.alignment == 4? 4 : 8)
|
142
|
-
HashLayout.size.should
|
131
|
+
HashLayout.size.should == (ll_off + 8)
|
143
132
|
mp = FFI::MemoryPointer.new(HashLayout.size)
|
144
133
|
s = HashLayout.new mp
|
145
134
|
s[:a] = 0x12345678
|
146
|
-
mp.get_int(0).should
|
135
|
+
mp.get_int(0).should == 0x12345678
|
147
136
|
s[:b] = 0xfee1deadbeef
|
148
|
-
mp.get_int64(ll_off).should
|
137
|
+
mp.get_int64(ll_off).should == 0xfee1deadbeef
|
149
138
|
end
|
150
139
|
end
|
151
140
|
|
@@ -162,8 +151,8 @@ describe "Struct tests" do
|
|
162
151
|
|
163
152
|
end
|
164
153
|
s = InitializeWithoutSuper.new(0x1eefbeef, 0xdeadcafebabe)
|
165
|
-
s[:a].should
|
166
|
-
s[:b].should
|
154
|
+
s[:a].should == 0x1eefbeef
|
155
|
+
s[:b].should == 0xdeadcafebabe
|
167
156
|
end
|
168
157
|
|
169
158
|
it "Can use Struct subclass as parameter type" do
|
@@ -202,7 +191,7 @@ describe "Struct tests" do
|
|
202
191
|
end
|
203
192
|
s = TestStruct.new
|
204
193
|
s[:i] = 0x12
|
205
|
-
LibTest.ptr_ret_int32_t(s, 0).should
|
194
|
+
LibTest.ptr_ret_int32_t(s, 0).should == 0x12
|
206
195
|
end
|
207
196
|
it ":char member aligned correctly" do
|
208
197
|
class AlignChar < FFI::Struct
|
@@ -210,7 +199,7 @@ describe "Struct tests" do
|
|
210
199
|
end
|
211
200
|
s = AlignChar.new
|
212
201
|
s[:v] = 0x12
|
213
|
-
LibTest.struct_align_s8(s.pointer).should
|
202
|
+
LibTest.struct_align_s8(s.pointer).should == 0x12
|
214
203
|
end
|
215
204
|
it ":short member aligned correctly" do
|
216
205
|
class AlignShort < FFI::Struct
|
@@ -218,7 +207,7 @@ describe "Struct tests" do
|
|
218
207
|
end
|
219
208
|
s = AlignShort.alloc_in
|
220
209
|
s[:v] = 0x1234
|
221
|
-
LibTest.struct_align_s16(s.pointer).should
|
210
|
+
LibTest.struct_align_s16(s.pointer).should == 0x1234
|
222
211
|
end
|
223
212
|
it ":int member aligned correctly" do
|
224
213
|
class AlignInt < FFI::Struct
|
@@ -226,7 +215,7 @@ describe "Struct tests" do
|
|
226
215
|
end
|
227
216
|
s = AlignInt.alloc_in
|
228
217
|
s[:v] = 0x12345678
|
229
|
-
LibTest.struct_align_s32(s.pointer).should
|
218
|
+
LibTest.struct_align_s32(s.pointer).should == 0x12345678
|
230
219
|
end
|
231
220
|
it ":long_long member aligned correctly" do
|
232
221
|
class AlignLongLong < FFI::Struct
|
@@ -234,7 +223,7 @@ describe "Struct tests" do
|
|
234
223
|
end
|
235
224
|
s = AlignLongLong.alloc_in
|
236
225
|
s[:v] = 0x123456789abcdef0
|
237
|
-
LibTest.struct_align_s64(s.pointer).should
|
226
|
+
LibTest.struct_align_s64(s.pointer).should == 0x123456789abcdef0
|
238
227
|
end
|
239
228
|
it ":long member aligned correctly" do
|
240
229
|
class AlignLong < FFI::Struct
|
@@ -242,7 +231,7 @@ describe "Struct tests" do
|
|
242
231
|
end
|
243
232
|
s = AlignLong.alloc_in
|
244
233
|
s[:v] = 0x12345678
|
245
|
-
LibTest.struct_align_long(s.pointer).should
|
234
|
+
LibTest.struct_align_long(s.pointer).should == 0x12345678
|
246
235
|
end
|
247
236
|
it ":float member aligned correctly" do
|
248
237
|
class AlignFloat < FFI::Struct
|
@@ -267,7 +256,7 @@ describe "Struct tests" do
|
|
267
256
|
s = ULPStruct.alloc_in
|
268
257
|
s[:ul] = 0xdeadbeef
|
269
258
|
s[:p] = LibTest.ptr_from_address(0x12345678)
|
270
|
-
s.pointer.get_ulong(0).should
|
259
|
+
s.pointer.get_ulong(0).should == 0xdeadbeef
|
271
260
|
end
|
272
261
|
def test_num_field(type, v)
|
273
262
|
klass = Class.new(FFI::Struct)
|
@@ -275,9 +264,9 @@ describe "Struct tests" do
|
|
275
264
|
|
276
265
|
s = klass.new
|
277
266
|
s[:v] = v
|
278
|
-
s.pointer.send("get_#{type.to_s}", 0).should
|
267
|
+
s.pointer.send("get_#{type.to_s}", 0).should == v
|
279
268
|
s.pointer.send("put_#{type.to_s}", 0, 0)
|
280
|
-
s[:v].should
|
269
|
+
s[:v].should == 0
|
281
270
|
end
|
282
271
|
def self.int_field_test(type, values)
|
283
272
|
values.each do |v|
|
@@ -332,8 +321,8 @@ describe "Struct tests" do
|
|
332
321
|
s = EnumFields::TestStruct.new
|
333
322
|
s[:c] = :c3
|
334
323
|
|
335
|
-
s.pointer.get_uint(FFI::Type::INT32.size).should
|
336
|
-
s[:c].should
|
324
|
+
s.pointer.get_uint(FFI::Type::INT32.size).should == 30
|
325
|
+
s[:c].should == :c3
|
337
326
|
end
|
338
327
|
|
339
328
|
it "array of :enum field" do
|
@@ -343,11 +332,11 @@ describe "Struct tests" do
|
|
343
332
|
end
|
344
333
|
|
345
334
|
EnumFields::TestEnum.symbols.each_with_index do |val, i|
|
346
|
-
s.pointer.get_uint(FFI::Type::INT32.size * (2 + i)).should
|
335
|
+
s.pointer.get_uint(FFI::Type::INT32.size * (2 + i)).should == EnumFields::TestEnum[val]
|
347
336
|
end
|
348
337
|
|
349
338
|
s[:d].each_with_index do |val, i|
|
350
|
-
val.should
|
339
|
+
val.should == EnumFields::TestEnum.symbols[i]
|
351
340
|
end
|
352
341
|
end
|
353
342
|
|
@@ -369,8 +358,8 @@ describe "Struct tests" do
|
|
369
358
|
sub_proc = lambda { |a, b| a-b }
|
370
359
|
s[:add] = add_proc
|
371
360
|
s[:sub] = sub_proc
|
372
|
-
CallbackMember.struct_call_add_cb(s, 40, 2).should
|
373
|
-
CallbackMember.struct_call_sub_cb(s, 44, 2).should
|
361
|
+
CallbackMember.struct_call_add_cb(s, 40, 2).should == 42
|
362
|
+
CallbackMember.struct_call_sub_cb(s, 44, 2).should == 42
|
374
363
|
end
|
375
364
|
it "Can return its members as a list" do
|
376
365
|
class TestStruct < FFI::Struct
|
@@ -394,16 +383,16 @@ describe "Struct tests" do
|
|
394
383
|
layout :a, :int, :b, :int, :c, :int
|
395
384
|
end
|
396
385
|
s = TestStruct.new
|
397
|
-
s.offsets.should
|
398
|
-
TestStruct.offsets.should
|
386
|
+
s.offsets.should == [[:a, 0], [:b, 4], [:c, 8]]
|
387
|
+
TestStruct.offsets.should == [[:a, 0], [:b, 4], [:c, 8]]
|
399
388
|
end
|
400
389
|
it "Struct#offset_of returns offset of field within struct" do
|
401
390
|
class TestStruct < FFI::Struct
|
402
391
|
layout :a, :int, :b, :int, :c, :int
|
403
392
|
end
|
404
|
-
TestStruct.offset_of(:a).should
|
405
|
-
TestStruct.offset_of(:b).should
|
406
|
-
TestStruct.offset_of(:c).should
|
393
|
+
TestStruct.offset_of(:a).should == 0
|
394
|
+
TestStruct.offset_of(:b).should == 4
|
395
|
+
TestStruct.offset_of(:c).should == 8
|
407
396
|
end
|
408
397
|
end
|
409
398
|
|
@@ -425,22 +414,22 @@ describe FFI::Struct, ' with a nested struct field' do
|
|
425
414
|
end
|
426
415
|
it 'should align correctly nested struct field' do
|
427
416
|
@cs[:ns][:i] = 123
|
428
|
-
LibTest.struct_align_nested_struct(@cs.to_ptr).should
|
417
|
+
LibTest.struct_align_nested_struct(@cs.to_ptr).should == 123
|
429
418
|
end
|
430
419
|
it 'should correctly calculate Container size (in bytes)' do
|
431
|
-
LibTest::ContainerStruct.size.should
|
420
|
+
LibTest::ContainerStruct.size.should == 8
|
432
421
|
end
|
433
422
|
it 'should return a Struct object when the field is accessed' do
|
434
423
|
@cs[:ns].is_a?(FFI::Struct).should be_true
|
435
424
|
end
|
436
425
|
it 'should read a value from memory' do
|
437
426
|
@cs = LibTest::ContainerStruct.new(LibTest.struct_make_container_struct(123))
|
438
|
-
@cs[:ns][:i].should
|
427
|
+
@cs[:ns][:i].should == 123
|
439
428
|
end
|
440
429
|
it 'should write a value to memory' do
|
441
430
|
@cs = LibTest::ContainerStruct.new(LibTest.struct_make_container_struct(123))
|
442
431
|
@cs[:ns][:i] = 456
|
443
|
-
LibTest.struct_align_nested_struct(@cs.to_ptr).should
|
432
|
+
LibTest.struct_align_nested_struct(@cs.to_ptr).should == 456
|
444
433
|
end
|
445
434
|
|
446
435
|
it 'should be able to assign struct instance to nested field' do
|
@@ -448,8 +437,8 @@ describe FFI::Struct, ' with a nested struct field' do
|
|
448
437
|
ns = LibTest::NestedStruct.new
|
449
438
|
ns[:i] = 567
|
450
439
|
cs[:ns] = ns
|
451
|
-
cs[:ns][:i].should
|
452
|
-
LibTest.struct_align_nested_struct(cs.to_ptr).should
|
440
|
+
cs[:ns][:i].should == 567
|
441
|
+
LibTest.struct_align_nested_struct(cs.to_ptr).should == 567
|
453
442
|
end
|
454
443
|
end
|
455
444
|
|
@@ -473,11 +462,11 @@ describe FFI::Struct, ' with a nested array of structs' do
|
|
473
462
|
|
474
463
|
it 'should align correctly nested struct field' do
|
475
464
|
@cs[:ns][0][:i] = 123
|
476
|
-
InlineArrayOfStructs.struct_align_nested_struct(@cs.to_ptr).should
|
465
|
+
InlineArrayOfStructs.struct_align_nested_struct(@cs.to_ptr).should == 123
|
477
466
|
end
|
478
467
|
|
479
468
|
it 'should correctly calculate Container size (in bytes)' do
|
480
|
-
InlineArrayOfStructs::ContainerStruct.size.should
|
469
|
+
InlineArrayOfStructs::ContainerStruct.size.should == 8
|
481
470
|
end
|
482
471
|
|
483
472
|
it 'should return a Struct object when the field is accessed' do
|
@@ -486,20 +475,20 @@ describe FFI::Struct, ' with a nested array of structs' do
|
|
486
475
|
|
487
476
|
it 'should read a value from memory' do
|
488
477
|
@cs = InlineArrayOfStructs::ContainerStruct.new(InlineArrayOfStructs.struct_make_container_struct(123))
|
489
|
-
@cs[:ns][0][:i].should
|
478
|
+
@cs[:ns][0][:i].should == 123
|
490
479
|
end
|
491
480
|
|
492
481
|
it 'should write a value to memory' do
|
493
482
|
@cs = InlineArrayOfStructs::ContainerStruct.new(InlineArrayOfStructs.struct_make_container_struct(123))
|
494
483
|
@cs[:ns][0][:i] = 456
|
495
|
-
InlineArrayOfStructs.struct_align_nested_struct(@cs.to_ptr).should
|
484
|
+
InlineArrayOfStructs.struct_align_nested_struct(@cs.to_ptr).should == 456
|
496
485
|
end
|
497
486
|
|
498
487
|
it 'should support Enumerable#each' do
|
499
488
|
@cs = InlineArrayOfStructs::ContainerStruct.new(InlineArrayOfStructs.struct_make_container_struct(123))
|
500
489
|
ints = []
|
501
490
|
@cs[:ns].each { |s| ints << s[:i] }
|
502
|
-
ints[0].should
|
491
|
+
ints[0].should == 123
|
503
492
|
end
|
504
493
|
end
|
505
494
|
|
@@ -529,22 +518,22 @@ describe FFI::Struct, ' by value' do
|
|
529
518
|
|
530
519
|
it 'return using pre-set values' do
|
531
520
|
s = LibTest.struct_return_s8s32
|
532
|
-
s[:s8].should
|
533
|
-
s[:s32].should
|
521
|
+
s[:s8].should == 0x7f
|
522
|
+
s[:s32].should == 0x12345678
|
534
523
|
end
|
535
524
|
|
536
525
|
it 'return using passed in values' do
|
537
526
|
s = LibTest.struct_s8s32_set(123, 456789)
|
538
|
-
s[:s8].should
|
539
|
-
s[:s32].should
|
527
|
+
s[:s8].should == 123
|
528
|
+
s[:s32].should == 456789
|
540
529
|
end
|
541
530
|
|
542
531
|
it 'parameter' do
|
543
532
|
s = LibTest::S8S32.new
|
544
533
|
s[:s8] = 0x12
|
545
534
|
s[:s32] = 0x34567890
|
546
|
-
LibTest.struct_s8s32_get_s8(s).should
|
547
|
-
LibTest.struct_s8s32_get_s32(s).should
|
535
|
+
LibTest.struct_s8s32_get_s8(s).should == 0x12
|
536
|
+
LibTest.struct_s8s32_get_s32(s).should == 0x34567890
|
548
537
|
end
|
549
538
|
|
550
539
|
it 'parameter with following s32' do
|
@@ -552,7 +541,7 @@ describe FFI::Struct, ' by value' do
|
|
552
541
|
s[:s8] = 0x12
|
553
542
|
s[:s32] = 0x34567890
|
554
543
|
|
555
|
-
LibTest.struct_s8s32_s32_ret_s32(s, 0x1eefdead).should
|
544
|
+
LibTest.struct_s8s32_s32_ret_s32(s, 0x1eefdead).should == 0x1eefdead
|
556
545
|
end
|
557
546
|
|
558
547
|
it 'parameter with following s64' do
|
@@ -566,9 +555,9 @@ describe FFI::Struct, ' by value' do
|
|
566
555
|
s[:s8] = 0x12
|
567
556
|
s[:s32] = 0x34567890
|
568
557
|
out = LibTest::S8S32.new
|
569
|
-
LibTest.struct_s32_ptr_s32_s8s32_ret_s32(0x1000000, out, 0x1eafbeef, s).should
|
570
|
-
out[:s8].should
|
571
|
-
out[:s32].should
|
558
|
+
LibTest.struct_s32_ptr_s32_s8s32_ret_s32(0x1000000, out, 0x1eafbeef, s).should == 0x34567890
|
559
|
+
out[:s8].should == s[:s8]
|
560
|
+
out[:s32].should == s[:s32]
|
572
561
|
end
|
573
562
|
|
574
563
|
it 'parameter with preceding s32,string,s32' do
|
@@ -576,7 +565,7 @@ describe FFI::Struct, ' by value' do
|
|
576
565
|
s[:s8] = 0x12
|
577
566
|
s[:s32] = 0x34567890
|
578
567
|
out = 0.chr * 32
|
579
|
-
LibTest.struct_s32_ptr_s32_s8s32_ret_s32(0x1000000, out, 0x1eafbeef, s).should
|
568
|
+
LibTest.struct_s32_ptr_s32_s8s32_ret_s32(0x1000000, out, 0x1eafbeef, s).should == 0x34567890
|
580
569
|
end
|
581
570
|
|
582
571
|
it 'parameter, returning struct by value' do
|
@@ -585,15 +574,15 @@ describe FFI::Struct, ' by value' do
|
|
585
574
|
s[:s32] = 0x34567890
|
586
575
|
|
587
576
|
ret = LibTest.struct_s8s32_ret_s8s32(s)
|
588
|
-
ret[:s8].should
|
589
|
-
ret[:s32].should
|
577
|
+
ret[:s8].should == s[:s8]
|
578
|
+
ret[:s32].should == s[:s32]
|
590
579
|
end
|
591
580
|
|
592
581
|
it 'varargs returning a struct' do
|
593
582
|
string = "test"
|
594
583
|
s = LibTest.struct_varargs_ret_struct_string(4, :string, string)
|
595
|
-
s[:len].should
|
596
|
-
s[:bytes].should
|
584
|
+
s[:len].should == string.length
|
585
|
+
s[:bytes].should == string
|
597
586
|
end
|
598
587
|
end
|
599
588
|
|
@@ -611,26 +600,26 @@ describe FFI::Struct, ' with an array field' do
|
|
611
600
|
@s = LibTest::StructWithArray.new
|
612
601
|
end
|
613
602
|
it 'should correctly calculate StructWithArray size (in bytes)' do
|
614
|
-
LibTest::StructWithArray.size.should
|
603
|
+
LibTest::StructWithArray.size.should == 24
|
615
604
|
end
|
616
605
|
it 'should read values from memory' do
|
617
606
|
@s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
|
618
|
-
@s[:a].to_a.should
|
607
|
+
@s[:a].to_a.should == [0, 1, 2, 3, 4]
|
619
608
|
end
|
620
609
|
# it 'should cache array object for successive calls' do
|
621
|
-
# @s[:a].object_id.should
|
610
|
+
# @s[:a].object_id.should == @s[:a].object_id
|
622
611
|
# end
|
623
612
|
it 'should return the number of elements in the array field' do
|
624
613
|
@s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
|
625
|
-
@s[:a].size.should
|
614
|
+
@s[:a].size.should == 5
|
626
615
|
end
|
627
616
|
it 'should allow iteration through the array elements' do
|
628
617
|
@s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
|
629
|
-
@s[:a].each_with_index { |elem, i| elem.should
|
618
|
+
@s[:a].each_with_index { |elem, i| elem.should == i }
|
630
619
|
end
|
631
620
|
it 'should return the pointer to the array' do
|
632
621
|
@s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
|
633
|
-
@s[:a].to_ptr.should
|
622
|
+
@s[:a].to_ptr.should == LibTest::struct_field_array(@s.to_ptr)
|
634
623
|
end
|
635
624
|
end
|
636
625
|
|
@@ -650,21 +639,21 @@ describe 'BuggedStruct' do
|
|
650
639
|
attach_function :bugged_struct_size, [], :uint
|
651
640
|
end
|
652
641
|
it 'should return its correct size' do
|
653
|
-
LibTest::BuggedStruct.size.should
|
642
|
+
LibTest::BuggedStruct.size.should == LibTest.bugged_struct_size
|
654
643
|
end
|
655
644
|
it "offsets within struct should be correct" do
|
656
|
-
LibTest::BuggedStruct.offset_of(:visible).should
|
657
|
-
LibTest::BuggedStruct.offset_of(:x).should
|
658
|
-
LibTest::BuggedStruct.offset_of(:y).should
|
659
|
-
LibTest::BuggedStruct.offset_of(:rx).should
|
660
|
-
LibTest::BuggedStruct.offset_of(:ry).should
|
661
|
-
LibTest::BuggedStruct.offset_of(:order).should
|
662
|
-
LibTest::BuggedStruct.offset_of(:size).should
|
645
|
+
LibTest::BuggedStruct.offset_of(:visible).should == 0
|
646
|
+
LibTest::BuggedStruct.offset_of(:x).should == 4
|
647
|
+
LibTest::BuggedStruct.offset_of(:y).should == 8
|
648
|
+
LibTest::BuggedStruct.offset_of(:rx).should == 12
|
649
|
+
LibTest::BuggedStruct.offset_of(:ry).should == 14
|
650
|
+
LibTest::BuggedStruct.offset_of(:order).should == 16
|
651
|
+
LibTest::BuggedStruct.offset_of(:size).should == 17
|
663
652
|
end
|
664
653
|
it 'should return correct field/offset pairs' do
|
665
654
|
LibTest::BuggedStruct.offsets.sort do |a, b|
|
666
655
|
a[1] <=> b[1]
|
667
|
-
end.should
|
656
|
+
end.should == [[:visible, 0], [:x, 4], [:y, 8], [:rx, 12], [:ry, 14], [:order, 16], [:size, 17]]
|
668
657
|
end
|
669
658
|
end
|
670
659
|
|
@@ -674,11 +663,11 @@ describe "Struct allocation" do
|
|
674
663
|
layout :i, :uint
|
675
664
|
end
|
676
665
|
p = FFI::MemoryPointer.new(S, 2)
|
677
|
-
p.total.should
|
678
|
-
p.type_size.should
|
666
|
+
p.total.should == 8
|
667
|
+
p.type_size.should == 4
|
679
668
|
p.put_uint(4, 0xdeadbeef)
|
680
|
-
S.new(p[1])[:i].should
|
681
|
-
p[1].address.should
|
669
|
+
S.new(p[1])[:i].should == 0xdeadbeef
|
670
|
+
p[1].address.should == (p[0].address + 4)
|
682
671
|
end
|
683
672
|
|
684
673
|
it "Buffer.new(Struct, 2)" do
|
@@ -686,10 +675,10 @@ describe "Struct allocation" do
|
|
686
675
|
layout :i, :uint
|
687
676
|
end
|
688
677
|
p = FFI::Buffer.new(S, 2)
|
689
|
-
p.total.should
|
690
|
-
p.type_size.should
|
678
|
+
p.total.should == 8
|
679
|
+
p.type_size.should == 4
|
691
680
|
p.put_uint(4, 0xdeadbeef)
|
692
|
-
S.new(p[1])[:i].should
|
681
|
+
S.new(p[1])[:i].should == 0xdeadbeef
|
693
682
|
end
|
694
683
|
|
695
684
|
it "null? should be true when initialized with NULL pointer" do
|
@@ -742,8 +731,8 @@ describe "variable-length arrays" do
|
|
742
731
|
s = struct_class.new(FFI::MemoryPointer.new(1024))
|
743
732
|
s[:data][0] = 0x1eadbeef
|
744
733
|
s[:data][1] = 0x12345678
|
745
|
-
s[:data][0].should
|
746
|
-
s[:data][1].should
|
734
|
+
s[:data][0].should == 0x1eadbeef
|
735
|
+
s[:data][1].should == 0x12345678
|
747
736
|
end
|
748
737
|
|
749
738
|
it "non-variable length array is bounds checked" do
|
@@ -753,7 +742,7 @@ describe "variable-length arrays" do
|
|
753
742
|
s = struct_class.new(FFI::MemoryPointer.new(1024))
|
754
743
|
s[:data][0] = 0x1eadbeef
|
755
744
|
lambda { s[:data][1] = 0x12345678 }.should raise_error
|
756
|
-
s[:data][0].should
|
757
|
-
lambda { s[:data][1].should
|
745
|
+
s[:data][0].should == 0x1eadbeef
|
746
|
+
lambda { s[:data][1].should == 0x12345678 }.should raise_error
|
758
747
|
end
|
759
748
|
end
|