summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortduehr <tduehr@gmail.com>2014-01-21 15:50:23 -0600
committertduehr <tduehr@gmail.com>2014-06-05 21:33:39 -0500
commitc79e9f5d1a622751226b82e302e20f734c1a4291 (patch)
tree385eb2ad96a1f399b80b14e2ffa38cba00f3a23d
parent3223054a9400ba356bf38ffe606ac58210319888 (diff)
downloadffi-c79e9f5d1a622751226b82e302e20f734c1a4291.tar.gz
merge specs w/ JRuby and correct syntax to use rspec
-rw-r--r--Rakefile8
-rw-r--r--spec/ffi/LICENSE.SPECS22
-rw-r--r--spec/ffi/async_callback_spec.rb3
-rw-r--r--spec/ffi/bool_spec.rb4
-rw-r--r--spec/ffi/buffer_spec.rb3
-rw-r--r--spec/ffi/callback_spec.rb14
-rw-r--r--spec/ffi/custom_param_type.rb3
-rw-r--r--spec/ffi/custom_type_spec.rb3
-rw-r--r--spec/ffi/dup_spec.rb4
-rw-r--r--spec/ffi/enum_spec.rb3
-rw-r--r--spec/ffi/errno_spec.rb4
-rw-r--r--spec/ffi/ffi_spec.rb3
-rw-r--r--spec/ffi/fixtures/.gitignore10
-rw-r--r--spec/ffi/fixtures/Benchmark.c52
-rw-r--r--spec/ffi/fixtures/BoolTest.c34
-rw-r--r--spec/ffi/fixtures/BufferTest.c31
-rw-r--r--spec/ffi/fixtures/ClosureTest.c190
-rw-r--r--spec/ffi/fixtures/EnumTest.c34
-rw-r--r--spec/ffi/fixtures/FunctionTest.c58
-rw-r--r--spec/ffi/fixtures/GNUmakefile149
-rw-r--r--spec/ffi/fixtures/GlobalVariable.c62
-rw-r--r--spec/ffi/fixtures/LastErrorTest.c21
-rw-r--r--spec/ffi/fixtures/NumberTest.c132
-rw-r--r--spec/ffi/fixtures/PointerTest.c63
-rw-r--r--spec/ffi/fixtures/ReferenceTest.c23
-rw-r--r--spec/ffi/fixtures/StringTest.c34
-rw-r--r--spec/ffi/fixtures/StructTest.c243
-rw-r--r--spec/ffi/fixtures/UnionTest.c43
-rw-r--r--spec/ffi/fixtures/VariadicTest.c62
-rw-r--r--spec/ffi/fixtures/classes.rb438
-rw-r--r--spec/ffi/function_spec.rb8
-rw-r--r--spec/ffi/io_spec.rb16
-rw-r--r--spec/ffi/library_spec.rb4
-rw-r--r--spec/ffi/long_double.rb3
-rw-r--r--spec/ffi/managed_struct_spec.rb4
-rw-r--r--spec/ffi/memorypointer_spec.rb71
-rw-r--r--spec/ffi/number_spec.rb4
-rw-r--r--spec/ffi/platform_spec.rb97
-rw-r--r--spec/ffi/pointer_spec.rb5
-rw-r--r--spec/ffi/rbx/attach_function_spec.rb8
-rw-r--r--spec/ffi/rbx/memory_pointer_spec.rb12
-rw-r--r--spec/ffi/rbx/spec_helper.rb8
-rw-r--r--spec/ffi/rbx/struct_spec.rb10
-rw-r--r--spec/ffi/spec_helper.rb78
-rw-r--r--spec/ffi/string_spec.rb6
-rw-r--r--spec/ffi/strptr_spec.rb3
-rw-r--r--spec/ffi/struct_by_ref_spec.rb7
-rw-r--r--spec/ffi/struct_callback_spec.rb5
-rw-r--r--spec/ffi/struct_initialize_spec.rb3
-rw-r--r--spec/ffi/struct_packed_spec.rb3
-rw-r--r--spec/ffi/struct_spec.rb128
-rw-r--r--spec/ffi/typedef_spec.rb4
-rw-r--r--spec/ffi/union_spec.rb3
-rw-r--r--spec/ffi/variadic_spec.rb4
-rw-r--r--spec/spec.opts3
55 files changed, 2152 insertions, 98 deletions
diff --git a/Rakefile b/Rakefile
index 8e766dc..08309ba 100644
--- a/Rakefile
+++ b/Rakefile
@@ -10,6 +10,11 @@ end
require 'date'
require 'fileutils'
require 'rbconfig'
+require 'rspec/core/rake_task'
+
+RSpec::Core::RakeTask.new(:spec) do |config|
+ config.rspec_opts = YAML.load_file 'spec/spec.opts'
+end
LIBEXT = case RbConfig::CONFIG['host_os'].downcase
@@ -100,7 +105,6 @@ end
desc "Build all packages"
task :package => 'gem:package'
-
CLOBBER.include 'build'
CLOBBER.include FileList['lib/**/ffi_c.so']
CLOBBER.include FileList["lib/**/ffi_c.#{RbConfig::CONFIG['DLEXT']}"]
@@ -120,7 +124,7 @@ desc "Build test helper lib"
task :libtest => "build/libtest.#{LIBEXT}"
desc "Test the extension"
-task :test => [ :specs, :rbxspecs ]
+task :test => [ :spec ]
namespace :bench do
diff --git a/spec/ffi/LICENSE.SPECS b/spec/ffi/LICENSE.SPECS
new file mode 100644
index 0000000..561dd8c
--- /dev/null
+++ b/spec/ffi/LICENSE.SPECS
@@ -0,0 +1,22 @@
+Copyright (c) 2008-2014 Ruby-FFI contributors
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/spec/ffi/async_callback_spec.rb b/spec/ffi/async_callback_spec.rb
index 8a11558..5ba16a5 100644
--- a/spec/ffi/async_callback_spec.rb
+++ b/spec/ffi/async_callback_spec.rb
@@ -3,7 +3,8 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
describe "async callback" do
module LibTest
diff --git a/spec/ffi/bool_spec.rb b/spec/ffi/bool_spec.rb
index 9124657..989d493 100644
--- a/spec/ffi/bool_spec.rb
+++ b/spec/ffi/bool_spec.rb
@@ -3,7 +3,9 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
+
describe "Function with primitive boolean arguments and return values" do
module LibTest
extend FFI::Library
diff --git a/spec/ffi/buffer_spec.rb b/spec/ffi/buffer_spec.rb
index 219641b..4039556 100644
--- a/spec/ffi/buffer_spec.rb
+++ b/spec/ffi/buffer_spec.rb
@@ -3,7 +3,8 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
describe "Buffer#total" do
[1,2,3].each do |i|
diff --git a/spec/ffi/callback_spec.rb b/spec/ffi/callback_spec.rb
index d3151b4..396f91f 100644
--- a/spec/ffi/callback_spec.rb
+++ b/spec/ffi/callback_spec.rb
@@ -3,7 +3,8 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
describe "Callback" do
# module LibC
@@ -253,6 +254,9 @@ describe "Callback" do
s2[:f32] = struct[:f32]
s2[:s32] = struct[:s32]
end
+ expect(s2[:s8]).to eql 0x12
+ expect(s2[:s32]).to eql 0x1eefbeef
+ expect(s2[:f32]).to be_within(0.0000001).of 1.234567
end
@@ -264,7 +268,7 @@ describe "Callback" do
describe "When the callback is considered optional by the underlying library" do
it "should handle receiving 'nil' in place of the closure" do
- LibTest.testOptionalCallbackCrV(nil, 13)
+ LibTest.testOptionalCallbackCrV(nil, 13).should be_nil
end
end
@@ -288,7 +292,7 @@ describe "Callback" do
callback :cb_return_type_1, [ :short ], :short
callback :cb_lookup_1, [ :short ], :cb_return_type_1
attach_function :testReturnsCallback_1, :testReturnsClosure, [ :cb_lookup_1, :short ], :cb_return_type_1
- end
+ end.should be_an_instance_of FFI::Function
end
it "should return a callback" do
@@ -345,7 +349,7 @@ describe "Callback" do
callback :cb_argument, [ :int ], :int
callback :cb_with_cb_argument, [ :cb_argument, :int ], :int
attach_function :testCallbackAsArgument_2, :testArgumentClosure, [ :cb_with_cb_argument, :int ], :int
- end
+ end.should be_an_instance_of FFI::Function
end
it 'should be able to use the callback argument' do
module LibTest
@@ -644,7 +648,7 @@ describe "Callback with " do
magic = LibTest::S8F32S32.new
LibTest.testCallbackYrV(magic) { |i| v = i }
v.class.should == magic.class
- v.pointer == magic.pointer
+ v.pointer.should == magic.pointer
end
it "struct by reference argument with nil value" do
diff --git a/spec/ffi/custom_param_type.rb b/spec/ffi/custom_param_type.rb
index ddb7c95..55db32f 100644
--- a/spec/ffi/custom_param_type.rb
+++ b/spec/ffi/custom_param_type.rb
@@ -3,7 +3,8 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
describe "functions with custom parameter types" do
before :each do
diff --git a/spec/ffi/custom_type_spec.rb b/spec/ffi/custom_type_spec.rb
index 0f8d36b..d3a36dc 100644
--- a/spec/ffi/custom_type_spec.rb
+++ b/spec/ffi/custom_type_spec.rb
@@ -3,7 +3,8 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
describe "functions with custom types" do
class Custom_enum
diff --git a/spec/ffi/dup_spec.rb b/spec/ffi/dup_spec.rb
index 32baf2b..c04f24e 100644
--- a/spec/ffi/dup_spec.rb
+++ b/spec/ffi/dup_spec.rb
@@ -3,8 +3,8 @@
# For licensing, see LICENSE.SPECS
#
-
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
describe "Pointer#dup" do
it "clone should be independent" do
diff --git a/spec/ffi/enum_spec.rb b/spec/ffi/enum_spec.rb
index f9b3e64..b7abbbf 100644
--- a/spec/ffi/enum_spec.rb
+++ b/spec/ffi/enum_spec.rb
@@ -3,7 +3,8 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
module TestEnum0
extend FFI::Library
diff --git a/spec/ffi/errno_spec.rb b/spec/ffi/errno_spec.rb
index 36c0992..99d1e13 100644
--- a/spec/ffi/errno_spec.rb
+++ b/spec/ffi/errno_spec.rb
@@ -3,7 +3,9 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
+
describe "FFI.errno" do
module LibTest
extend FFI::Library
diff --git a/spec/ffi/ffi_spec.rb b/spec/ffi/ffi_spec.rb
index 6ff01b6..b592b85 100644
--- a/spec/ffi/ffi_spec.rb
+++ b/spec/ffi/ffi_spec.rb
@@ -3,7 +3,8 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
describe "FFI" do
diff --git a/spec/ffi/fixtures/.gitignore b/spec/ffi/fixtures/.gitignore
new file mode 100644
index 0000000..dfd9b3f
--- /dev/null
+++ b/spec/ffi/fixtures/.gitignore
@@ -0,0 +1,10 @@
+# signature of implementation that
+# last compiled an extension
+*.sig
+
+# build artifacts
+*.o
+*.so
+*.bundle
+*.dylib
+*.dll
diff --git a/spec/ffi/fixtures/Benchmark.c b/spec/ffi/fixtures/Benchmark.c
new file mode 100644
index 0000000..55a7380
--- /dev/null
+++ b/spec/ffi/fixtures/Benchmark.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2007 Wayne Meissner. All rights reserved.
+ *
+ * For licensing, see LICENSE.SPECS
+ */
+#include <sys/types.h>
+#include <stdint.h>
+
+void returnVoid() {
+
+}
+
+void returnVoidI(int arg) {
+
+}
+int returnInt() {
+ return 0;
+}
+
+int returnIntI(int arg) {
+ return arg;
+}
+
+typedef int8_t s8;
+typedef uint8_t u8;
+typedef int16_t s16;
+typedef uint16_t u16;
+typedef int32_t s32;
+typedef uint32_t u32;
+typedef int64_t s64;
+typedef uint64_t u64;
+typedef float f32;
+typedef double f64;
+typedef void v;
+typedef char* S;
+typedef void* P;
+
+#define B6(R, T1, T2, T3, T4, T5, T6) R bench_##T1##T2##T3##T4##T5##T6##_##R(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) {}
+#define B5(R, T1, T2, T3, T4, T5) R bench_##T1##T2##T3##T4##T5##_##R(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) {}
+#define B4(R, T1, T2, T3, T4) R bench_##T1##T2##T3##T4##_##R(T1 a1, T2 a2, T3 a3, T4 a4) {}
+#define B3(R, T1, T2, T3) R bench_##T1##T2##T3##_##R(T1 a1, T2 a2, T3 a3) {}
+#define B2(R, T1, T2) R bench_##T1##T2##_##R(T1 a1, T2 a2) {}
+#define B1(R, T1) R bench_##T1##_##R(T1 a1) {}
+#define BrV(T) B1(v, T); B2(v, T, T); B3(v, T, T, T); B4(v, T, T, T, T); B5(v, T, T, T, T, T); B6(v, T, T, T, T, T, T);
+BrV(u32);
+BrV(s32);
+BrV(s64);
+BrV(u64);
+BrV(f32);
+BrV(f64);
+BrV(S);
+BrV(P);
diff --git a/spec/ffi/fixtures/BoolTest.c b/spec/ffi/fixtures/BoolTest.c
new file mode 100644
index 0000000..04cb6c6
--- /dev/null
+++ b/spec/ffi/fixtures/BoolTest.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007 Wayne Meissner.
+ * Copyright (c) 2009 Aman Gupta.
+ *
+ * All rights reserved.
+ *
+ * For licensing, see LICENSE.SPECS
+ */
+
+#include <stdbool.h>
+
+bool
+bool_return_true()
+{
+ return true;
+}
+
+bool
+bool_return_false()
+{
+ return false;
+}
+
+bool
+bool_return_val(bool value)
+{
+ return value;
+}
+
+bool
+bool_reverse_val(bool value)
+{
+ return value ? false : true;
+}
diff --git a/spec/ffi/fixtures/BufferTest.c b/spec/ffi/fixtures/BufferTest.c
new file mode 100644
index 0000000..3e95ebc
--- /dev/null
+++ b/spec/ffi/fixtures/BufferTest.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007 Wayne Meissner. All rights reserved.
+ *
+ * For licensing, see LICENSE.SPECS
+ */
+
+
+#define MEMSET(buf, value, size) do { \
+ int i; for (i = 0; i < size; ++i) buf[i] = value; \
+} while(0)
+#define MEMCPY(dst, src, size) do { \
+ int i; for (i = 0; i < size; ++i) dst[i] = src[i]; \
+} while(0)
+
+#define FILL(JTYPE, CTYPE) \
+void fill##JTYPE##Buffer(CTYPE* buf, CTYPE value, int size) { MEMSET(buf, value, size); }
+
+#define COPY(JTYPE, CTYPE) \
+void copy##JTYPE##Buffer(CTYPE* dst, CTYPE* src, int size) { MEMCPY(dst, src, size); }
+
+#define FUNC(JTYPE, CTYPE) \
+ FILL(JTYPE, CTYPE); \
+ COPY(JTYPE, CTYPE)
+
+FUNC(Byte, char);
+FUNC(Short, short);
+FUNC(Int, int);
+FUNC(Long, long long);
+FUNC(Float, float);
+FUNC(Double, double);
+
diff --git a/spec/ffi/fixtures/ClosureTest.c b/spec/ffi/fixtures/ClosureTest.c
new file mode 100644
index 0000000..64ea2b4
--- /dev/null
+++ b/spec/ffi/fixtures/ClosureTest.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2007 Wayne Meissner. All rights reserved.
+ *
+ * For licensing, see LICENSE.SPECS
+ */
+
+#include <stdlib.h>
+#include <stdbool.h>
+#ifndef _WIN32
+# include <pthread.h>
+#else
+# include <windows.h>
+# include <process.h>
+#endif
+
+#define R(T, rtype) rtype testClosureVr##T(rtype (*closure)(void)) { \
+ return closure != NULL ? (*closure)() : (rtype) 0; \
+}
+
+#define P(T, ptype) void testClosure##T##rV(void (*closure)(ptype), ptype a1) { \
+ if (closure != NULL) (*closure)(a1); \
+}
+
+void testClosureVrV(void (*closure)(void))
+{
+ (*closure)();
+}
+
+R(Z, bool);
+R(B, char);
+R(S, short);
+R(I, int);
+R(L, long);
+R(J, long long);
+R(LL, long long);
+R(F, float);
+R(D, double);
+R(P, const void*);
+
+
+P(Z, bool);
+P(B, char);
+P(S, short);
+P(I, int);
+P(L, long);
+P(J, long long);
+P(LL, long long);
+P(F, float);
+P(D, double);
+P(P, const void*);
+P(UL, unsigned long);
+
+void testOptionalClosureBrV(void (*closure)(char), char a1)
+{
+ if (closure) {
+ (*closure)(a1);
+ }
+}
+
+
+struct ThreadVrV {
+ void (*closure)(void);
+ int count;
+};
+
+static void *
+threadVrV(void *arg)
+{
+ struct ThreadVrV* t = (struct ThreadVrV *) arg;
+
+ int i;
+ for (i = 0; i < t->count; i++) {
+ (*t->closure)();
+ }
+
+ return NULL;
+}
+
+void testThreadedClosureVrV(void (*closure)(void), int n)
+{
+ struct ThreadVrV arg = {closure, n};
+#ifndef _WIN32
+ pthread_t t;
+ pthread_create(&t, NULL, threadVrV, &arg);
+ pthread_join(t, NULL);
+#else
+ HANDLE hThread = (HANDLE) _beginthread((void (*)(void *))threadVrV, 0, &arg);
+ WaitForSingleObject(hThread, INFINITE);
+#endif
+}
+
+struct s8f32s32 {
+ char s8;
+ float f32;
+ int s32;
+};
+
+// Takes a struct argument
+void testClosureTrV(void (*closure)(struct s8f32s32 s), struct s8f32s32* s)
+{
+ (*closure)(*s);
+}
+
+// Returns a struct value
+struct s8f32s32 testClosureVrT(struct s8f32s32 (*closure)())
+{
+ return (*closure)();
+}
+
+typedef int (*returnTypeClosure_t)(int) ;
+typedef returnTypeClosure_t (*lookupClosure_t)();
+
+int testReturnsClosure(lookupClosure_t lookup, int val)
+{
+ returnTypeClosure_t func = lookup ? (*lookup)() : NULL;
+ return func ? (*func)(val) : 0;
+}
+
+static int multiplyByTwo(int value)
+{
+ return value * 2;
+}
+
+returnTypeClosure_t testReturnsFunctionPointer()
+{
+ return multiplyByTwo;
+}
+
+typedef int (*argumentClosure_t)(int);
+typedef int (*withArgumentClosure_t)(argumentClosure_t, int);
+
+int testArgumentClosure(withArgumentClosure_t closure_with, argumentClosure_t closure_arg, int val)
+{
+ return (*closure_with)(closure_arg, val);
+}
+
+
+//
+// These macros produce functions of the form:
+// testClosureBIrV(void (*closure)(char, int), char a1, int a2) {}
+//
+#define C2_(J1, J2, N1, N2) \
+void testClosure##J1##J2##rV(void (*closure)(N1, N2), N1 a1, N2 a2) \
+{ \
+ if (closure != NULL) (*closure)(a1, a2); \
+}
+
+#define C2(J, N) \
+ C2_(B, J, char, N) \
+ C2_(S, J, short, N) \
+ C2_(I, J, int, N) \
+ C2_(LL, J, long long, N) \
+ C2_(F, J, float, N) \
+ C2_(D, J, double, N) \
+
+
+C2(B, char);
+C2(S, short);
+C2(I, int);
+C2(LL, long long);
+C2(F, float);
+C2(D, double);
+
+#define C3_(J1, J2, J3, N1, N2, N3) \
+void testClosure##J1##J2##J3##rV(void (*closure)(N1, N2, N3), N1 a1, N2 a2, N3 a3) \
+{ \
+ (*closure)(a1, a2, a3); \
+}
+
+
+#define C3(J, N) \
+ C3_(B, J, B, char, N, char) \
+ C3_(S, J, S, short, N, short) \
+ C3_(I, J, I, int, N, int) \
+ C3_(LL, J, LL, long long, N, long long) \
+ C3_(F, J, F, float, N, float) \
+ C3_(D, J, D, double, N, double) \
+
+C3(B, char);
+C3(S, short);
+C3(I, int);
+C3(LL, long long);
+C3(F, float);
+C3(D, double);
+C3_(B, S, I, char, short, int);
+C3_(B, S, LL, char, short, long long);
+C3_(LL, S, B, long long, short, char);
+C3_(LL, B, S, long long, char, short);
+
+
diff --git a/spec/ffi/fixtures/EnumTest.c b/spec/ffi/fixtures/EnumTest.c
new file mode 100644
index 0000000..4c9dda9
--- /dev/null
+++ b/spec/ffi/fixtures/EnumTest.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007 Wayne Meissner. All rights reserved.
+ *
+ * For licensing, see LICENSE.SPECS
+ */
+
+int test_untagged_enum(int val) {
+ return val;
+}
+
+int test_untagged_typedef_enum(int val) {
+ return val;
+}
+
+typedef enum {c1, c2, c3, c4} enum_type1;
+enum_type1 test_tagged_typedef_enum1(enum_type1 val) {
+ return val;
+}
+
+typedef enum {c5 = 42, c6, c7, c8} enum_type2;
+enum_type2 test_tagged_typedef_enum2(enum_type2 val) {
+ return val;
+}
+
+typedef enum {c9 = 42, c10, c11 = 4242, c12} enum_type3;
+enum_type3 test_tagged_typedef_enum3(enum_type3 val) {
+ return val;
+}
+
+typedef enum {c13 = 42, c14 = 4242, c15 = 424242, c16 = 42424242} enum_type4;
+enum_type4 test_tagged_typedef_enum4(enum_type4 val) {
+ return val;
+}
+
diff --git a/spec/ffi/fixtures/FunctionTest.c b/spec/ffi/fixtures/FunctionTest.c
new file mode 100644
index 0000000..b4d45bb
--- /dev/null
+++ b/spec/ffi/fixtures/FunctionTest.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2007 Wayne Meissner. All rights reserved.
+ *
+ * For licensing, see LICENSE.SPECS
+ */
+
+#ifdef _WIN32
+#include <windows.h>
+#define sleep(x) Sleep(x)
+#endif
+
+#ifndef _WIN32
+#include <unistd.h>
+#include <pthread.h>
+#endif
+
+int testAdd(int a, int b)
+{
+ return a + b;
+};
+
+int testFunctionAdd(int a, int b, int (*f)(int, int))
+{
+ return f(a, b);
+};
+
+void testBlocking(int seconds) {
+ sleep(seconds);
+};
+
+struct async_data {
+ void (*fn)(int);
+ int value;
+};
+
+static void* asyncThreadCall(void *data)
+{
+ struct async_data* d = (struct async_data *) data;
+ if (d != NULL && d->fn != NULL) {
+ (*d->fn)(d->value);
+ }
+
+ return NULL;
+}
+
+void testAsyncCallback(void (*fn)(int), int value)
+{
+#ifndef _WIN32
+ pthread_t t;
+ struct async_data d;
+ d.fn = fn;
+ d.value = value;
+ pthread_create(&t, NULL, asyncThreadCall, &d);
+ pthread_join(t, NULL);
+#else
+ (*fn)(value);
+#endif
+}
diff --git a/spec/ffi/fixtures/GNUmakefile b/spec/ffi/fixtures/GNUmakefile
new file mode 100644
index 0000000..d730419
--- /dev/null
+++ b/spec/ffi/fixtures/GNUmakefile
@@ -0,0 +1,149 @@
+# -*- makefile -*-
+
+ifeq ($(OS),)
+ BUILD_OS := $(shell uname -s | tr '[:upper:]' '[:lower:]')
+ OS := $(BUILD_OS)
+endif
+
+ifeq ($(CPU),)
+ CPU := $(shell uname -m | sed -e 's/i[345678]86/i386/')
+endif
+
+PLATFORM = $(CPU)-$(OS)
+
+ifeq ($(OS), sunos)
+ OS = solaris
+endif
+
+SRC_DIR = .
+BUILD_DIR ?= .
+TEST_BUILD_DIR = .
+# Set defaults to unix (linux/solaris/bsd)
+PREFIX = lib
+LIBEXT ?= so
+LIBNAME = $(PREFIX)test.$(LIBEXT)
+
+export MACOSX_DEPLOYMENT_TARGET=10.4
+
+CCACHE := $(strip $(realpath $(shell which ccache 2> /dev/null)))
+
+TEST_SRCS = $(wildcard $(SRC_DIR)/*.c)
+TEST_OBJS := $(patsubst $(SRC_DIR)/%.c, $(TEST_BUILD_DIR)/%.o, $(TEST_SRCS))
+
+#
+# Compiler/linker flags from:
+# http://weblogs.java.net/blog/kellyohair/archive/2006/01/compilation_of_1.html
+JFLAGS = -fno-omit-frame-pointer -fno-strict-aliasing
+OFLAGS = -O2 $(JFLAGS)
+WFLAGS = -W -Wall -Wno-unused -Wno-parentheses
+PICFLAGS = -fPIC
+SOFLAGS = -shared
+LDFLAGS += $(SOFLAGS)
+
+IFLAGS = -I"$(BUILD_DIR)"
+CFLAGS = $(OFLAGS) $(WFLAGS) $(IFLAGS) $(PICFLAGS) -D_REENTRANT
+
+ifneq ($(strip $(findstring $(OS), win32, mingw, cygwin)),)
+ # For cygwin => win32-native builds, strip out cygwin deps
+ ifneq ($(findstring cygwin, $(BUILD_OS)),)
+ CC += -mno-cygwin -mwin32
+ LDFLAGS += -mno-cygwin -Wl,--add-stdcall-alias
+ endif
+ PICFLAGS=
+ LIBEXT=dll
+ CC = gcc
+endif
+
+ifeq ($(OS), darwin)
+ ifneq ($(findstring $(CPU),ppc),)
+ ARCHFLAGS += -arch ppc
+ endif
+ ifneq ($(findstring $(CPU),i386 x86_64),)
+ ARCHFLAGS += -arch i386 -arch x86_64
+ endif
+ CFLAGS += $(ARCHFLAGS) -DTARGET_RT_MAC_CFM=0
+ CFLAGS += -fno-common
+ LDFLAGS = $(ARCHFLAGS) -dynamiclib
+ # link against the universal libraries on ppc machines
+ LDFLAGS += -L$(MACSDK)/usr/lib
+ LIBEXT = dylib
+ FFI_CFLAGS += -isysroot $(MACSDK)
+ PICFLAGS =
+ SOFLAGS =
+endif
+
+ifeq ($(OS), linux)
+ SOFLAGS += -Wl,-soname,$(LIBNAME)
+endif
+
+ifeq ($(OS), solaris)
+ CC = /usr/sfw/bin/gcc -std=c99
+ LD = /usr/ccs/bin/ld
+ SOFLAGS = -shared -static-libgcc
+endif
+
+ifeq ($(OS), aix)
+ LIBEXT = a
+ SOFLAGS = -shared -static-libgcc
+ PICFLAGS += -pthread
+endif
+
+ifneq ($(findstring bsd, $(OS)),)
+ SOFLAGS = -shared -static-libgcc
+ CFLAGS += -pthread
+ LDFLAGS += -pthread
+endif
+
+ifeq ($(CPU), i386)
+ MODEL = 32
+endif
+
+ifeq ($(CPU), sparcv9)
+ MODEL = 64
+endif
+
+ifeq ($(CPU), amd64)
+ MODEL = 64
+endif
+
+ifeq ($(CPU), x86_64)
+ MODEL = 64
+endif
+
+ifeq ($(CPU), ppc64)
+ MODEL = 64
+endif
+
+ifeq ($(CPU), powerpc64)
+ MODEL = 64
+endif
+
+MODELFLAG =
+ifneq ($(MODEL),)
+ MODELFLAG = -m$(MODEL)
+endif
+
+# On platforms (linux, solaris) that support both 32bit and 64bit, force building for one or the other
+ifneq ($(or $(findstring linux, $(OS)), $(findstring solaris, $(OS))),)
+ # Change the CC/LD instead of CFLAGS/LDFLAGS, incase other things in the flags
+ # makes the libffi build choke
+ CC += $(MODELFLAG)
+ LD += $(MODELFLAG)
+endif
+
+LIBTEST = $(LIBNAME)
+
+all: $(LIBTEST)
+
+$(TEST_BUILD_DIR)/%.o : $(SRC_DIR)/%.c
+ @mkdir -p $(@D)
+ $(CCACHE) $(CC) $(CFLAGS) -c $< -o $@
+
+$(LIBTEST): $(TEST_OBJS)
+ $(CC) -o $@ $(LDFLAGS) $(TEST_OBJS) -lm
+
+clean::
+ # nothing to do - ant will delete the build dir
+
+debug::
+ @echo "SRCS=$(TEST_SRCS)"
diff --git a/spec/ffi/fixtures/GlobalVariable.c b/spec/ffi/fixtures/GlobalVariable.c
new file mode 100644
index 0000000..39c12a2
--- /dev/null
+++ b/spec/ffi/fixtures/GlobalVariable.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007 Wayne Meissner. All rights reserved.
+ *
+ * For licensing, see LICENSE.SPECS
+ */
+
+#include <sys/types.h>
+#include <stdint.h>
+
+typedef int8_t s8;
+typedef uint8_t u8;
+typedef int16_t s16;
+typedef uint16_t u16;
+typedef int32_t s32;
+typedef uint32_t u32;
+typedef int64_t s64;
+typedef uint64_t u64;
+typedef signed long sL;
+typedef unsigned long uL;
+typedef float f32;
+typedef double f64;
+#if !defined(__OpenBSD__)
+typedef unsigned long ulong;
+#endif
+typedef void* pointer;
+typedef void* P;
+
+#define GVAR(T) \
+ extern T gvar_##T; \
+ T gvar_##T = (T) -1; \
+ T gvar_##T##_get() { return gvar_##T; }; \
+ void gvar_##T##_set(T v) { gvar_##T = v; }
+
+GVAR(s8);
+GVAR(u8);
+GVAR(s16);
+GVAR(u16);
+GVAR(s32);
+GVAR(u32);
+GVAR(s64);
+GVAR(u64);
+GVAR(long);
+GVAR(ulong);
+GVAR(pointer);
+
+struct gstruct {
+ long data;
+};
+
+struct gstruct gvar_gstruct = { -1 };
+
+struct gstruct*
+gvar_gstruct_get(void)
+{
+ return &gvar_gstruct;
+}
+
+void
+gvar_gstruct_set(const struct gstruct* val)
+{
+ gvar_gstruct = *val;
+}
diff --git a/spec/ffi/fixtures/LastErrorTest.c b/spec/ffi/fixtures/LastErrorTest.c
new file mode 100644
index 0000000..02ce4a8
--- /dev/null
+++ b/spec/ffi/fixtures/LastErrorTest.c
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2007 Wayne Meissner. All rights reserved.
+ *
+ * For licensing, see LICENSE.SPECS
+ */
+
+#if defined(_WIN32) || defined(__WIN32__)
+# include <windows.h>
+#else
+# include <errno.h>
+#endif
+
+int setLastError(int error) {
+#if defined(_WIN32) || defined(__WIN32__)
+ SetLastError(error);
+#else
+ errno = error;
+#endif
+ return -1;
+}
+
diff --git a/spec/ffi/fixtures/NumberTest.c b/spec/ffi/fixtures/NumberTest.c
new file mode 100644
index 0000000..3fa25a8
--- /dev/null
+++ b/spec/ffi/fixtures/NumberTest.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2007 Wayne Meissner. All rights reserved.
+ *
+ * For licensing, see LICENSE.SPECS
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#if defined(__sparc) && defined(__sun__)
+ #define fix_mem_access __asm("ta 6")
+#else
+ #define fix_mem_access
+#endif
+
+typedef int8_t s8;
+typedef uint8_t u8;
+typedef int16_t s16;
+typedef uint16_t u16;
+typedef int32_t s32;
+typedef uint32_t u32;
+typedef int64_t s64;
+typedef uint64_t u64;
+typedef signed long sL;
+typedef unsigned long uL;
+typedef float f32;
+typedef double f64;
+typedef long double f128;
+#if !defined(__OpenBSD__)
+typedef unsigned long ulong;
+#endif
+
+#define ADD(T) T add_##T(T arg1, T arg2) { return arg1 + arg2; }
+#define SUB(T) T sub_##T(T arg1, T arg2) { return arg1 - arg2; }
+#define MUL(T) T mul_##T(T arg1, T arg2) { return arg1 * arg2; }
+#define DIV(T) T div_##T(T arg1, T arg2) { return arg1 / arg2; }
+#define RET(T) T ret_##T(T arg1) { return arg1; }
+#define SET(T) static T T##_;void set_##T(T arg1) { T##_ = arg1; }
+#define GET(T) T get_##T() { return T##_; }
+typedef char* ptr;
+#define TEST(T) ADD(T) SUB(T) MUL(T) DIV(T) RET(T) SET(T) GET(T)
+TEST(s8);
+TEST(u8);
+TEST(s16);
+TEST(u16);
+TEST(s32);
+TEST(u32);
+TEST(s64);
+TEST(u64);
+TEST(float);
+TEST(double);
+TEST(long);
+TEST(ulong);
+TEST(f128);
+
+#define ADD2(R, T1, T2) R add_##T1##T2##_##R(T1 arg1, T2 arg2) { return arg1 + arg2; }
+#define SUB2(R, T1, T2) R sub_##T1##T2##_##R(T1 arg1, T2 arg2) { return arg1 - arg2; }
+#define MUL2(R, T1, T2) R mul_##T1##T2##_##R(T1 arg1, T2 arg2) { return arg1 * arg2; }
+#define DIV2(R, T1, T2) R div_##T1##T2##_##R(T1 arg1, T2 arg2) { return arg1 / arg2; }
+
+#define T2__(R, T1, T2) ADD2(R, T1, T2) SUB2(R, T1, T2) MUL2(R, T1, T2) DIV2(R, T1, T2)
+#define T2_(R, T1) \
+ T2__(R, T1, s8) T2__(R, T1, u8) \
+ T2__(R, T1, s16) T2__(R, T1, u16) \
+ T2__(R, T1, s32) T2__(R, T1, u32) \
+ T2__(R, T1, sL) T2__(R, T1, uL) \
+ T2__(R, T1, s64) T2__(R, T1, u64) \
+
+#define TEST2(R) \
+ T2_(R, s8) T2_(R, u8) T2_(R, s16) T2_(R, u16) T2_(R, s32) T2_(R, u32) \
+ T2_(R, sL) T2_(R, uL) T2_(R, s64) T2_(R, u64)
+
+#ifdef notyet
+TEST2(s32)
+TEST2(u32)
+TEST2(s64)
+TEST2(u64)
+#endif
+
+#define ADD3(R, T1, T2, T3) R add_##T1##T2##T3##_##R(T1 arg1, T2 arg2, T3 arg3) { return arg1 + arg2 + arg3; }
+#define pack_f32(buf, v) do { float f = v; memcpy((buf), &f, sizeof(f)); } while(0)
+#define pack_f64(buf, v) do { double f = v; memcpy((buf), &f, sizeof(f)); } while(0)
+#define pack_int(buf, v) do { *(buf) = v; } while(0)
+#define pack_s8 pack_int
+#define pack_u8 pack_int
+#define pack_s16 pack_int
+#define pack_u16 pack_int
+#define pack_s32 pack_int
+#define pack_u32 pack_int
+#define pack_s64 pack_int
+#define pack_u64 pack_int
+#define pack_sL pack_int
+#define pack_uL pack_int
+
+#define PACK3(R, T1, T2, T3) void pack_##T1##T2##T3##_##R(T1 arg1, T2 arg2, T3 arg3, R* r) { \
+ fix_mem_access; \
+ pack_##T1(&r[0], arg1); \
+ pack_##T2(&r[1], arg2); \
+ pack_##T3(&r[2], arg3); \
+}
+
+#define T3___(R, T1, T2, T3) PACK3(R, T1, T2, T3) /* SUB2(R, T1, T2) MUL2(R, T1, T2) DIV2(R, T1, T2) */
+#define T3__(R, T1, T2) \
+ T3___(R, T1, T2, s8) T3___(R, T1, T2, u8) \
+ T3___(R, T1, T2, s16) T3___(R, T1, T2, u16) \
+ T3___(R, T1, T2, s32) T3___(R, T1, T2, u32) \
+ T3___(R, T1, T2, sL) T3___(R, T1, T2, uL) \
+ T3___(R, T1, T2, s64) T3___(R, T1, T2, u64) \
+ T3___(R, T1, T2, f32) T3___(R, T1, T2, f64) \
+
+#define T3_(R, T1) \
+ T3__(R, T1, s8) T3__(R, T1, u8) \
+ T3__(R, T1, s16) T3__(R, T1, u16) \
+ T3__(R, T1, s32) T3__(R, T1, u32) \
+ T3__(R, T1, sL) T3__(R, T1, uL) \
+ T3__(R, T1, s64) T3__(R, T1, u64) \
+ T3__(R, T1, f32) T3__(R, T1, f64) \
+
+#define TEST3(R) \
+ T3_(R, s8) T3_(R, u8) T3_(R, s16) T3_(R, u16) T3_(R, s32) T3_(R, u32) \
+ T3_(R, sL) T3_(R, uL) T3_(R, s64) T3_(R, u64) T3_(R, f32) T3_(R, f64)
+
+TEST3(s64)
+
+void
+foo6(intptr_t i1, intptr_t i2, intptr_t i3, intptr_t i4, intptr_t i5, intptr_t i6) { }
+
+void
+foo5(intptr_t i1, intptr_t i2, intptr_t i3, intptr_t i4, intptr_t i5) { }
+
diff --git a/spec/ffi/fixtures/PointerTest.c b/spec/ffi/fixtures/PointerTest.c
new file mode 100644
index 0000000..7237ab2
--- /dev/null
+++ b/spec/ffi/fixtures/PointerTest.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2007 Wayne Meissner. All rights reserved.
+ *
+ * For licensing, see LICENSE.SPECS
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+typedef void* ptr;
+typedef void* pointer;
+#ifdef _WIN32
+typedef char* caddr_t;
+#endif
+
+#define RET(T) T ptr_ret_##T(void* arg1, int offset) { \
+ T tmp; memcpy(&tmp, (caddr_t) arg1 + offset, sizeof(tmp)); return tmp; \
+}
+#define SET(T) void ptr_set_##T(void* arg1, int offset, T value) { \
+ memcpy((caddr_t) arg1 + offset, &value, sizeof(value)); \
+}
+#define TEST(T) SET(T) RET(T)
+
+TEST(int8_t);
+TEST(int16_t);
+TEST(int32_t);
+TEST(int64_t);
+TEST(float);
+TEST(double);
+TEST(pointer);
+
+void*
+ptr_return_array_element(void **ptrArray, int arrayIndex)
+{
+ return ptrArray[arrayIndex];
+}
+
+void
+ptr_set_array_element(void **ptrArray, int arrayIndex, void *value)
+{
+ ptrArray[arrayIndex] = value;
+}
+
+void*
+ptr_malloc(int size)
+{
+ return calloc(1, size);
+}
+void
+ptr_free(void* ptr)
+{
+ free(ptr);
+}
+
+void*
+ptr_from_address(uintptr_t addr)
+{
+ return (void *) addr;
+}
+
diff --git a/spec/ffi/fixtures/ReferenceTest.c b/spec/ffi/fixtures/ReferenceTest.c
new file mode 100644
index 0000000..d1dd88b
--- /dev/null
+++ b/spec/ffi/fixtures/ReferenceTest.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2007 Wayne Meissner. All rights reserved.
+ *
+ * For licensing, see LICENSE.SPECS
+ */
+
+#include <stdint.h>
+
+#define REF(T) void ref_##T(T arg, T* result) { *result = arg; }
+#define ADD(T) void ref_add_##T(T arg1, T arg2, T* result) { *result = arg1 + arg2; }
+#define SUB(T) void ref_sub_##T(T arg1, T arg2, T* result) { *result = arg1 - arg2; }
+#define MUL(T) void ref_mul_##T(T arg1, T arg2, T* result) { *result = arg1 * arg2; }
+#define DIV(T) void ref_div_##T(T arg1, T arg2, T* result) { *result = arg1 / arg2; }
+#define TEST(T) ADD(T) SUB(T) MUL(T) DIV(T) REF(T)
+
+TEST(int8_t);
+TEST(int16_t);
+TEST(int32_t);
+TEST(int64_t);
+TEST(float);
+TEST(double);
+
+
diff --git a/spec/ffi/fixtures/StringTest.c b/spec/ffi/fixtures/StringTest.c
new file mode 100644
index 0000000..292242b
--- /dev/null
+++ b/spec/ffi/fixtures/StringTest.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007 Wayne Meissner. All rights reserved.
+ *
+ * For licensing, see LICENSE.SPECS
+ */
+
+#include <string.h>
+
+int
+string_equals(const char* s1, const char* s2)
+{
+ return strcmp(s1, s2) == 0;
+}
+
+void
+string_set(char* s1, const char* s2)
+{
+ strcpy(s1, s2);
+}
+void
+string_concat(char* dst, const char* src)
+{
+ strcat(dst, src);
+}
+void
+string_dummy(char* dummy)
+{
+}
+const char*
+string_null(void)
+{
+ return NULL;
+}
+
diff --git a/spec/ffi/fixtures/StructTest.c b/spec/ffi/fixtures/StructTest.c
new file mode 100644
index 0000000..25683d3
--- /dev/null
+++ b/spec/ffi/fixtures/StructTest.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2007 Wayne Meissner.
+ * Copyright (c) 2009 Andrea Fazzi <andrea.fazzi@alcacoop.it>.
+ *
+ * All rights reserved.
+ *
+ * For licensing, see LICENSE.SPECS
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdarg.h>
+
+typedef char s8;
+typedef short s16;
+typedef int s32;
+typedef long long s64;
+typedef float f32;
+typedef double f64;
+
+typedef struct bugged_struct {
+ unsigned char visible;
+ unsigned int x;
+ unsigned int y;
+ short rx;
+ short ry;
+ unsigned char order;
+ unsigned char size;
+} bugged_struct_t;
+
+unsigned int
+bugged_struct_size() {
+ return sizeof(bugged_struct_t);
+}
+
+struct test1 {
+ char b;
+ short s;
+ int i;
+ long long j;
+ long l;
+ float f;
+ double d;
+ char string[32];
+};
+
+struct struct_with_array {
+ char c;
+ int a[5];
+};
+
+struct nested {
+ int i;
+};
+
+struct container {
+ char first;
+ struct nested s;
+};
+
+int
+struct_align_nested_struct(struct container* a) { return a->s.i; }
+
+void*
+struct_field_array(struct struct_with_array* s) { return &s->a; }
+
+struct container*
+struct_make_container_struct(int i)
+{
+ static struct container cs;
+ memset(&cs, 0, sizeof(cs));
+ cs.first = 1;
+ cs.s.i = i;
+ return &cs;
+}
+
+#define T(x, type) \
+ type struct_field_##type(struct test1* t) { return t->x; } \
+ struct type##_align { char first; type value; }; \
+ type struct_align_##type(struct type##_align* a) { return a->value; }
+
+T(b, s8);
+T(s, s16);
+T(i, s32);
+T(j, s64);
+T(f, f32);
+T(d, f64);
+T(l, long);
+
+void
+struct_set_string(struct test1* t, char* s)
+{
+ strcpy(t->string, s);
+}
+
+struct test1*
+struct_make_struct(char b, short s, int i, long long ll, float f, double d)
+{
+ static struct test1 t;
+ memset(&t, 0, sizeof(t));
+ t.b = b;
+ t.s = s;
+ t.i = i;
+ t.j = ll;
+ t.f = f;
+ t.d = d;
+ return &t;
+}
+
+typedef int (*add_cb)(int a1, int a2);
+typedef int (*sub_cb)(int a1, int a2);
+struct test2 {
+ add_cb add_callback;
+ sub_cb sub_callback;
+};
+
+int
+struct_call_add_cb(struct test2* t, int a1, int a2)
+{
+ return t->add_callback(a1, a2);
+}
+
+int
+struct_call_sub_cb(struct test2* t, int a1, int a2)
+{
+ return t->sub_callback(a1, a2);
+}
+
+
+struct struct_with_array*
+struct_make_struct_with_array(int a_0, int a_1, int a_2, int a_3, int a_4)
+{
+ static struct struct_with_array s;
+
+ memset(&s, 0, sizeof(s));
+
+ s.a[0] = a_0;
+ s.a[1] = a_1;
+ s.a[2] = a_2;
+ s.a[3] = a_3;
+ s.a[4] = a_4;
+
+ return &s;
+
+}
+
+struct s8s32 {
+ char s8;
+ int s32;
+};
+
+struct s8s32
+struct_return_s8s32()
+{
+ struct s8s32 s;
+ s.s8 = 0x7f;
+ s.s32 = 0x12345678;
+
+ return s;
+}
+
+struct s8s32
+struct_s8s32_set(char s8, int s32)
+{
+ struct s8s32 s;
+
+ s.s8 = s8;
+ s.s32 = s32;
+
+ return s;
+}
+
+int
+struct_s8s32_get_s8(struct s8s32 s)
+{
+ return s.s8;
+}
+
+int
+struct_s8s32_get_s32(struct s8s32 s)
+{
+ return s.s32;
+}
+
+struct s8s32
+struct_s8s32_ret_s8s32(struct s8s32 s)
+{
+ return s;
+}
+
+// Pass a struct and an int arg, ensure the int arg is passed correctly
+int
+struct_s8s32_s32_ret_s32(struct s8s32 s, int s32)
+{
+ return s32;
+}
+
+// Pass a struct and a long long arg, ensure the long long arg is passed correctly
+long long
+struct_s8s32_s64_ret_s64(struct s8s32 s, long long s64)
+{
+ return s64;
+}
+
+// Pass a struct and a long long arg, ensure the long long arg is passed correctly
+int
+struct_s32_ptr_s32_s8s32_ret_s32(int s32a, void *ptr, int s32b, struct s8s32 s)
+{
+ if (ptr != NULL) *(struct s8s32 *) ptr = s;
+ return s.s32;
+}
+
+// Pass a char *, copy into buffer length struct
+struct struct_string {
+ char *bytes;
+ int len;
+};
+
+struct struct_string
+struct_varargs_ret_struct_string(int len, ...)
+{
+ struct struct_string ss;
+ va_list vl;
+ char* cp = NULL;
+
+ va_start(vl, len);
+
+ ss.len = len;
+ ss.bytes = va_arg(vl, char *);
+ if (ss.bytes != NULL) {
+ cp = malloc(strlen(ss.bytes) + 1);
+ strcpy(cp, ss.bytes);
+ ss.bytes = cp;
+ }
+
+ va_end(vl);
+
+ return ss;
+}
+
diff --git a/spec/ffi/fixtures/UnionTest.c b/spec/ffi/fixtures/UnionTest.c
new file mode 100644
index 0000000..0929a31
--- /dev/null
+++ b/spec/ffi/fixtures/UnionTest.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2007 Wayne Meissner. All rights reserved.
+ *
+ * For licensing, see LICENSE.SPECS
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
+typedef char s8;
+typedef short s16;
+typedef int s32;
+typedef long long s64;
+typedef float f32;
+typedef double f64;
+
+typedef union union_test {
+ char b;
+ short s;
+ int i;
+ long long j;
+ long l;
+ float f;
+ double d;
+ s8 a[10];
+} union_test_t;
+
+#define T(x, type) \
+ type union_align_##type(union_test_t* u) { return u->x; } \
+ union_test_t* union_make_union_with_##type(type value) { static union_test_t u; u.x = value; return &u; }
+
+T(b, s8);
+T(s, s16);
+T(i, s32);
+T(j, s64);
+T(f, f32);
+T(d, f64);
+T(l, long);
+
+unsigned int union_size() { return sizeof(union_test_t); }
diff --git a/spec/ffi/fixtures/VariadicTest.c b/spec/ffi/fixtures/VariadicTest.c
new file mode 100644
index 0000000..fea6c3b
--- /dev/null
+++ b/spec/ffi/fixtures/VariadicTest.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007 Wayne Meissner. All rights reserved.
+ *
+ * For licensing, see LICENSE.SPECS
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdarg.h>
+
+typedef int8_t s8;
+typedef uint8_t u8;
+typedef int16_t s16;
+typedef uint16_t u16;
+typedef int32_t s32;
+typedef uint32_t u32;
+typedef int64_t s64;
+typedef uint64_t u64;
+typedef signed long sL;
+typedef unsigned long uL;
+typedef float F;
+typedef double D;
+
+void pack_varargs(s64* buf, const char* fmt, ...)
+{
+ va_list ap;
+ int c;
+ double d;
+ va_start(ap, fmt);
+ while ((c = *fmt++)) {
+ switch (c) {
+ case 'c':
+ case 's':
+ case 'i':
+ *buf++ = va_arg(ap, s32);
+ break;
+ case 'l':
+ *buf++ = va_arg(ap, long);
+ break;
+ case 'j':
+ *buf++ = va_arg(ap, s64);
+ break;
+ case 'f':
+ case 'd':
+ d = va_arg(ap, double);
+ memcpy(buf++, &d, sizeof(d));
+ break;
+ case 'C':
+ case 'S':
+ case 'I':
+ *buf++ = va_arg(ap, u32);
+ break;
+ case 'L':
+ *buf++ = va_arg(ap, unsigned long);
+ break;
+ }
+ }
+ va_end(ap);
+}
+
diff --git a/spec/ffi/fixtures/classes.rb b/spec/ffi/fixtures/classes.rb
new file mode 100644
index 0000000..581768c
--- /dev/null
+++ b/spec/ffi/fixtures/classes.rb
@@ -0,0 +1,438 @@
+module FFISpecs
+ #
+ # Callback fixtures
+ #
+ module LibTest
+ callback :cbVrS8, [ ], :char
+ callback :cbVrU8, [ ], :uchar
+ callback :cbVrS16, [ ], :short
+ callback :cbVrU16, [ ], :ushort
+ callback :cbVrS32, [ ], :int
+ callback :cbVrU32, [ ], :uint
+ callback :cbVrL, [ ], :long
+ callback :cbVrUL, [ ], :ulong
+ callback :cbVrS64, [ ], :long_long
+ callback :cbVrU64, [ ], :ulong_long
+ callback :cbVrP, [], :pointer
+ callback :cbCrV, [ :char ], :void
+ callback :cbSrV, [ :short ], :void
+ callback :cbIrV, [ :int ], :void
+ callback :cbLrV, [ :long ], :void
+ callback :cbULrV, [ :ulong ], :void
+ callback :cbLrV, [ :long_long ], :void
+
+ attach_function :testCallbackVrS8, :testClosureVrB, [ :cbVrS8 ], :char
+ attach_function :testCallbackVrU8, :testClosureVrB, [ :cbVrU8 ], :uchar
+ attach_function :testCallbackVrS16, :testClosureVrS, [ :cbVrS16 ], :short
+ attach_function :testCallbackVrU16, :testClosureVrS, [ :cbVrU16 ], :ushort
+ attach_function :testCallbackVrS32, :testClosureVrI, [ :cbVrS32 ], :int
+ attach_function :testCallbackVrU32, :testClosureVrI, [ :cbVrU32 ], :uint
+ attach_function :testCallbackVrL, :testClosureVrL, [ :cbVrL ], :long
+ attach_function :testCallbackVrUL, :testClosureVrL, [ :cbVrUL ], :ulong
+ attach_function :testCallbackVrS64, :testClosureVrLL, [ :cbVrS64 ], :long_long
+ attach_function :testCallbackVrU64, :testClosureVrLL, [ :cbVrU64 ], :ulong_long
+ attach_function :testCallbackVrP, :testClosureVrP, [ :cbVrP ], :pointer
+ attach_function :testCallbackCrV, :testClosureBrV, [ :cbCrV, :char ], :void
+ attach_variable :cbVrS8, :gvar_pointer, :cbVrS8
+ attach_variable :pVrS8, :gvar_pointer, :pointer
+ attach_function :testGVarCallbackVrS8, :testClosureVrB, [ :pointer ], :char
+ attach_function :testOptionalCallbackCrV, :testOptionalClosureBrV, [ :cbCrV, :char ], :void
+
+ attach_function :testCallbackVrS8, :testClosureVrB, [ callback([ ], :char) ], :char
+
+ callback :cb_return_type, [ :int ], :int
+ callback :cb_lookup, [ ], :cb_return_type
+ attach_function :testReturnsCallback, :testReturnsClosure, [ :cb_lookup, :int ], :int
+
+ callback :funcptr, [ :int ], :int
+ attach_function :testReturnsFunctionPointer, [ ], :funcptr
+
+ callback :cbS8rV, [ :char ], :void
+ callback :cbU8rV, [ :uchar ], :void
+ callback :cbS16rV, [ :short ], :void
+ callback :cbU16rV, [ :ushort ], :void
+
+ callback :cbS32rV, [ :int ], :void
+ callback :cbU32rV, [ :uint ], :void
+
+ callback :cbLrV, [ :long ], :void
+ callback :cbULrV, [ :ulong ], :void
+
+ callback :cbS64rV, [ :long_long ], :void
+ attach_function :testCallbackCrV, :testClosureBrV, [ :cbS8rV, :char ], :void
+ attach_function :testCallbackU8rV, :testClosureBrV, [ :cbU8rV, :uchar ], :void
+ attach_function :testCallbackSrV, :testClosureSrV, [ :cbS16rV, :short ], :void
+ attach_function :testCallbackU16rV, :testClosureSrV, [ :cbU16rV, :ushort ], :void
+ attach_function :testCallbackIrV, :testClosureIrV, [ :cbS32rV, :int ], :void
+ attach_function :testCallbackU32rV, :testClosureIrV, [ :cbU32rV, :uint ], :void
+
+ attach_function :testCallbackLrV, :testClosureLrV, [ :cbLrV, :long ], :void
+ attach_function :testCallbackULrV, :testClosureULrV, [ :cbULrV, :ulong ], :void
+
+ attach_function :testCallbackLLrV, :testClosureLLrV, [ :cbS64rV, :long_long ], :void
+ end
+
+ #
+ # Enum fixtures
+ #
+ module TestEnum0
+ extend FFI::Library
+ end
+
+ module TestEnum1
+ extend FFI::Library
+ ffi_lib LIBRARY
+
+ enum [:c1, :c2, :c3, :c4]
+ enum [:c5, 42, :c6, :c7, :c8]
+ enum [:c9, 42, :c10, :c11, 4242, :c12]
+ enum [:c13, 42, :c14, 4242, :c15, 424242, :c16, 42424242]
+
+ attach_function :test_untagged_enum, [:int], :int
+ end
+
+ module TestEnum3
+ extend FFI::Library
+ ffi_lib LIBRARY
+
+ enum :enum_type1, [:c1, :c2, :c3, :c4]
+ enum :enum_type2, [:c5, 42, :c6, :c7, :c8]
+ enum :enum_type3, [:c9, 42, :c10, :c11, 4242, :c12]
+ enum :enum_type4, [:c13, 42, :c14, 4242, :c15, 424242, :c16, 42424242]
+
+ attach_function :test_tagged_typedef_enum1, [:enum_type1], :enum_type1
+ attach_function :test_tagged_typedef_enum2, [:enum_type2], :enum_type2
+ attach_function :test_tagged_typedef_enum3, [:enum_type3], :enum_type3
+ attach_function :test_tagged_typedef_enum4, [:enum_type4], :enum_type4
+ end
+
+ #
+ # Errno fixtures
+ #
+ module LibTest
+ attach_function :setLastError, [ :int ], :void
+ end
+
+ #
+ # ManagedStruct fixtures
+ #
+ module LibTest
+ attach_function :ptr_from_address, [ FFI::Platform::ADDRESS_SIZE == 32 ? :uint : :ulong_long ], :pointer
+ end
+
+ class NoRelease < ManagedStruct
+ layout :i, :int
+ end
+
+ class WhatClassAmI < ManagedStruct
+ layout :i, :int
+ def self.release; end
+ end
+
+ class PleaseReleaseMe < ManagedStruct
+ layout :i, :int
+ @@count = 0
+ def self.release
+ @@count += 1
+ end
+ def self.wait_gc(count)
+ loop = 5
+ while loop > 0 && @@count < count
+ loop -= 1
+ if RUBY_PLATFORM =~ /java/
+ require 'java'
+ java.lang.System.gc
+ else
+ GC.start
+ end
+ sleep 0.05 if @@count < count
+ end
+ end
+ end
+
+ #
+ # Number fixtures
+ #
+ module LibTest
+ attach_function :ret_s8, [ :char ], :char
+ attach_function :ret_u8, [ :uchar ], :uchar
+ attach_function :ret_s16, [ :short ], :short
+ attach_function :ret_u16, [ :ushort ], :ushort
+ attach_function :ret_s32, [ :int ], :int
+ attach_function :ret_u32, [ :uint ], :uint
+ attach_function :ret_s64, [ :long_long ], :long_long
+ attach_function :ret_u64, [ :ulong_long ], :ulong_long
+ attach_function :ret_long, [ :long ], :long
+ attach_function :ret_ulong, [ :ulong ], :ulong
+ attach_function :set_s8, [ :char ], :void
+ attach_function :get_s8, [ ], :char
+ attach_function :set_float, [ :float ], :void
+ attach_function :get_float, [ ], :float
+ attach_function :set_double, [ :double ], :void
+ attach_function :get_double, [ ], :double
+ end
+
+ PACK_VALUES = {
+ 's8' => [ 0x12 ],
+ 'u8' => [ 0x34 ],
+ 's16' => [ 0x5678 ],
+ 'u16' => [ 0x9abc ],
+ 's32' => [ 0x7654321f ],
+ 'u32' => [ 0xfee1babe ],
+ 'sL' => [ 0x1f2e3d4c ],
+ 'uL' => [ 0xf7e8d9ca ],
+ 's64' => [ 0x1eafdeadbeefa1b2 ],
+ #'f32' => [ 1.234567 ], # TODO: Why is this disabled?
+ 'f64' => [ 9.87654321 ]
+ }
+
+ TYPE_MAP = {
+ 's8' => :char, 'u8' => :uchar, 's16' => :short, 'u16' => :ushort,
+ 's32' => :int, 'u32' => :uint, 's64' => :long_long, 'u64' => :ulong_long,
+ 'sL' => :long, 'uL' => :ulong, 'f32' => :float, 'f64' => :double
+ }
+ TYPES = TYPE_MAP.keys
+
+ module LibTest
+ [ 's32', 'u32', 's64', 'u64' ].each do |rt|
+ TYPES.each do |t1|
+ TYPES.each do |t2|
+ TYPES.each do |t3|
+ begin
+ attach_function "pack_#{t1}#{t2}#{t3}_#{rt}",
+ [ TYPE_MAP[t1], TYPE_MAP[t2], TYPE_MAP[t3], :buffer_out ], :void
+ rescue FFI::NotFoundError
+ end
+ end
+ end
+ end
+ end
+ end
+
+ #
+ # Pointer fixtures
+ #
+ module LibTest
+ attach_function :ptr_ret_int32_t, [ :pointer, :int ], :int
+ attach_function :ptr_from_address, [ FFI::Platform::ADDRESS_SIZE == 32 ? :uint : :ulong_long ], :pointer
+ attach_function :ptr_set_pointer, [ :pointer, :int, :pointer ], :void
+ end
+
+ class ToPtrTest
+ def initialize(ptr)
+ @ptr = ptr
+ end
+ def to_ptr
+ @ptr
+ end
+ end
+
+ require 'delegate'
+ class PointerDelegate < DelegateClass(FFI::Pointer)
+ def initialize(ptr)
+ super
+ @ptr = ptr
+ end
+ def to_ptr
+ @ptr
+ end
+ end
+
+ class AutoPointerTestHelper
+ @@count = 0
+ def self.release
+ @@count += 1 if @@count > 0
+ end
+ def self.reset
+ @@count = 0
+ end
+ def self.gc_everything(count)
+ loop = 5
+ while @@count < count && loop > 0
+ loop -= 1
+ if RUBY_PLATFORM =~ /java/
+ require "java"
+ java.lang.System.gc
+ else
+ GC.start
+ end
+ sleep 0.05 unless @@count == count
+ end
+ @@count = 0
+ end
+ def self.finalizer
+ self.method(:release).to_proc
+ end
+ end
+
+ #
+ # String fixtures
+ #
+ module LibTest
+ attach_function :ptr_ret_pointer, [ :pointer, :int], :string
+ attach_function :string_equals, [ :string, :string ], :int
+ attach_function :string_dummy, [ :string ], :void
+ end
+
+ #
+ # Struct initialize fixtures
+ #
+ class StructWithInitialize < FFI::Struct
+ layout :string, :string
+ attr_accessor :magic
+ def initialize
+ super
+ self.magic = 42
+ end
+ end
+
+ #
+ # Struct fixtures
+ #
+ StructTypes = {
+ 's8' => :char,
+ 's16' => :short,
+ 's32' => :int,
+ 's64' => :long_long,
+ 'long' => :long,
+ 'f32' => :float,
+ 'f64' => :double
+ }
+
+ module LibTest
+ attach_function :ptr_ret_pointer, [ :pointer, :int], :string
+ attach_function :ptr_ret_int32_t, [ :pointer, :int ], :int
+ attach_function :ptr_from_address, [ :ulong ], :pointer
+ attach_function :string_equals, [ :string, :string ], :int
+ [ 's8', 's16', 's32', 's64', 'f32', 'f64', 'long' ].each do |t|
+ attach_function "struct_align_#{t}", [ :pointer ], StructTypes[t]
+ end
+ end
+
+ class PointerMember < FFI::Struct
+ layout :pointer, :pointer
+ end
+
+ class StringMember < FFI::Struct
+ layout :string, :string
+ end
+
+ module CallbackMember
+ extend FFI::Library
+ ffi_lib LIBRARY
+ callback :add, [ :int, :int ], :int
+ callback :sub, [ :int, :int ], :int
+
+ class TestStruct < FFI::Struct
+ layout :add, :add,
+ :sub, :sub
+ end
+
+ attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
+ attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
+ end
+
+ module LibTest
+ class NestedStruct < FFI::Struct
+ layout :i, :int
+ end
+
+ class ContainerStruct < FFI::Struct
+ layout :first, :char, :ns, NestedStruct
+ end
+
+ attach_function :struct_align_nested_struct, [ :pointer ], :int
+ attach_function :struct_make_container_struct, [ :int ], :pointer
+
+ class StructWithArray < FFI::Struct
+ layout :first, :char, :a, [:int, 5]
+ end
+
+ attach_function :struct_make_struct_with_array, [:int, :int, :int, :int, :int], :pointer
+ attach_function :struct_field_array, [:pointer], :pointer
+
+ class BuggedStruct < FFI::Struct
+ layout :visible, :uchar,
+ :x, :uint,
+ :y, :uint,
+ :rx, :short,
+ :ry, :short,
+ :order, :uchar,
+ :size, :uchar
+ end
+
+ attach_function :bugged_struct_size, [], :uint
+ end
+
+ module StructCustomTypedef
+ extend FFI::Library
+ ffi_lib LIBRARY
+ typedef :uint, :fubar3_t
+
+ class S < FFI::Struct
+ layout :a, :fubar3_t
+ end
+ end
+
+ #
+ # Union fixtures
+ #
+ module LibTest
+ Types = {
+ 's8' => [:char, :c, 1],
+ 's16' => [:short, :s, 0xff0],
+ 's32' => [:int, :i, 0xff00],
+ 's64' => [:long_long, :j, 0xffff00],
+ 'long' => [:long, :l, 0xffff],
+ 'f32' => [:float, :f, 1.0001],
+ 'f64' => [:double, :d, 1.000000001]
+ }
+
+ class TestUnion < FFI::Union
+ layout( :a, [:char, 10],
+ :i, :int,
+ :f, :float,
+ :d, :double,
+ :s, :short,
+ :l, :long,
+ :j, :long_long,
+ :c, :char )
+ end
+
+ Types.keys.each do |k|
+ attach_function "union_align_#{k}", [ :pointer ], Types[k][0]
+ attach_function "union_make_union_with_#{k}", [ Types[k][0] ], :pointer
+ end
+
+ attach_function :union_size, [], :uint
+ end
+
+ #
+ # Variadic fixtures
+ #
+ module LibTest
+ attach_function :pack_varargs, [ :buffer_out, :string, :varargs ], :void
+ 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
+end
diff --git a/spec/ffi/function_spec.rb b/spec/ffi/function_spec.rb
index 21ad09c..c011787 100644
--- a/spec/ffi/function_spec.rb
+++ b/spec/ffi/function_spec.rb
@@ -3,7 +3,8 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
describe FFI::Function do
module LibTest
@@ -16,13 +17,14 @@ describe FFI::Function do
FFI::DynamicLibrary::RTLD_LAZY | FFI::DynamicLibrary::RTLD_GLOBAL)
end
it 'is initialized with a signature and a block' do
- FFI::Function.new(:int, []) { }
+ fn = FFI::Function.new(:int, []) { 5 }
+ expect(fn.call).to eql 5
end
it 'raises an error when passing a wrong signature' do
lambda { FFI::Function.new([], :int).new { } }.should raise_error TypeError
end
it 'returns a native pointer' do
- FFI::Function.new(:int, []) { }.kind_of? FFI::Pointer
+ expect(FFI::Function.new(:int, []) { }).to be_a_kind_of FFI::Pointer
end
it 'can be used as callback from C passing to it a block' do
function_add = FFI::Function.new(:int, [:int, :int]) { |a, b| a + b }
diff --git a/spec/ffi/io_spec.rb b/spec/ffi/io_spec.rb
new file mode 100644
index 0000000..ccc8d19
--- /dev/null
+++ b/spec/ffi/io_spec.rb
@@ -0,0 +1,16 @@
+#
+# This file is part of ruby-ffi.
+# For licensing, see LICENSE.SPECS
+#
+
+require 'ffi'
+
+if false # disabled for #390
+ describe "FFI::IO.for_fd" do
+ it "produces an IO wrapping the specified file descriptor" do
+ expect do
+ FFI::IO.for_fd(2, "r")
+ end.to_not raise_error
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/ffi/library_spec.rb b/spec/ffi/library_spec.rb
index d5831a0..5b182f7 100644
--- a/spec/ffi/library_spec.rb
+++ b/spec/ffi/library_spec.rb
@@ -3,7 +3,9 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
+
describe "Library" do
describe "#ffi_convention" do
it "defaults to :default" do
diff --git a/spec/ffi/long_double.rb b/spec/ffi/long_double.rb
index b76344a..0cc4105 100644
--- a/spec/ffi/long_double.rb
+++ b/spec/ffi/long_double.rb
@@ -3,7 +3,8 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
require 'bigdecimal'
describe ":long_double arguments and return values" do
diff --git a/spec/ffi/managed_struct_spec.rb b/spec/ffi/managed_struct_spec.rb
index 43902c1..df6a5e1 100644
--- a/spec/ffi/managed_struct_spec.rb
+++ b/spec/ffi/managed_struct_spec.rb
@@ -3,8 +3,8 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
-require 'java' if RUBY_PLATFORM =~ /java/
+require 'ffi'
+require_relative 'spec_helper'
describe "Managed Struct" do
include FFI
diff --git a/spec/ffi/memorypointer_spec.rb b/spec/ffi/memorypointer_spec.rb
new file mode 100644
index 0000000..084c77e
--- /dev/null
+++ b/spec/ffi/memorypointer_spec.rb
@@ -0,0 +1,71 @@
+#
+# This file is part of ruby-ffi.
+# For licensing, see LICENSE.SPECS
+#
+
+require 'ffi'
+
+MemoryPointer = FFI::MemoryPointer
+
+describe "MemoryPointer#total" do
+ it "MemoryPointer.new(:char, 1).total == 1" do
+ expect(MemoryPointer.new(:char, 1).total).to eq 1
+ end
+ it "MemoryPointer.new(:short, 1).total == 2" do
+ expect(MemoryPointer.new(:short, 1).total).to eq 2
+ end
+ it "MemoryPointer.new(:int, 1).total == 4" do
+ expect(MemoryPointer.new(:int, 1).total).to eq 4
+ end
+ it "MemoryPointer.new(:long_long, 1).total == 8" do
+ expect(MemoryPointer.new(:long_long, 1).total).to eq 8
+ end
+ it "MemoryPointer.new(1024).total == 1024" do
+ expect(MemoryPointer.new(1024).total).to eq 1024
+ end
+end
+describe "MemoryPointer#read_array_of_long" do
+ it "foo" do
+ ptr = MemoryPointer.new(:long, 1024)
+ ptr[0].write_long 1234
+ ptr[1].write_long 5678
+ l = ptr.read_array_of_long(2)
+ expect(l[0]).to eq 1234
+ expect(l[1]).to eq 5678
+ end
+end
+describe "MemoryPointer argument" do
+ module Ptr
+ extend FFI::Library
+ ffi_lib FFI::Platform::LIBC
+ attach_function :memset, [ :pointer, :int, :ulong ], :pointer
+ attach_function :memcpy, [ :pointer, :pointer, :ulong ], :pointer
+ end
+ it "Pointer passed correctly" do
+ p = MemoryPointer.new :int, 1
+ ret = Ptr.memset(p, 0, p.total)
+ expect(ret).to eq p
+ end
+ it "Data passed to native function" do
+ p = MemoryPointer.new :int, 1
+ p2 = MemoryPointer.new :int, 1
+ p2.put_int(0, 0x5eadbeef)
+ Ptr.memcpy(p, p2, p.total)
+ expect(p.get_int(0)).to eq p2.get_int(0)
+ expect(p2.get_int(0)).not_to eql 0
+ end
+end
+describe "MemoryPointer return value" do
+ module Stdio
+ extend FFI::Library
+ ffi_lib FFI::Platform::LIBC
+ attach_function :fopen, [ :string, :string ], :pointer
+ attach_function :fclose, [ :pointer ], :int
+ attach_function :fwrite, [ :pointer, :ulong, :ulong, :string ], :ulong
+ end
+ it "fopen returns non-nil" do
+ fp = Stdio.fopen("/dev/null", "w")
+ expect(fp).to_not be_nil
+ expect(Stdio.fclose(fp)).to eq 0 unless fp.nil? or fp.null?
+ end
+end
diff --git a/spec/ffi/number_spec.rb b/spec/ffi/number_spec.rb
index 6087cce..0dbc3cb 100644
--- a/spec/ffi/number_spec.rb
+++ b/spec/ffi/number_spec.rb
@@ -3,7 +3,9 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
+
describe "Function with primitive integer arguments" do
module LibTest
extend FFI::Library
diff --git a/spec/ffi/platform_spec.rb b/spec/ffi/platform_spec.rb
new file mode 100644
index 0000000..67539df
--- /dev/null
+++ b/spec/ffi/platform_spec.rb
@@ -0,0 +1,97 @@
+#
+# This file is part of ruby-ffi.
+# For licensing, see LICENSE.SPECS
+#
+
+require 'ffi'
+require_relative 'spec_helper'
+
+describe "FFI::Platform::LIBSUFFIX" do
+ it "returns 'so'", if: RbConfig::CONFIG['host_os'].match('linux') do
+ FFI::Platform::LIBSUFFIX.should == 'so'
+ end
+
+ it "returns 'dll'", if: RbConfig::CONFIG['host_os'].match('windows') do
+ FFI::Platform::LIBSUFFIX.should == 'dll'
+ end
+
+ it "returns 'dylib'", if: RbConfig::CONFIG['host_os'].match('darwin') do
+ FFI::Platform::LIBSUFFIX.should == 'dylib'
+ end
+end
+
+describe "FFI::Platform::IS_WINDOWS" do
+ it "returns false", if: RbConfig::CONFIG['host_os'].match('linux') do
+ FFI::Platform::IS_WINDOWS.should == false
+ end
+
+ it "returns true", if: RbConfig::CONFIG['host_os'].match('windows') do
+ FFI::Platform::IS_WINDOWS.should == true
+ end
+
+ it "returns false", if: RbConfig::CONFIG['host_os'].match('darwin') do
+ FFI::Platform::IS_WINDOWS.should == false
+ end
+end
+
+describe "FFI::Platform::ARCH" do
+ it "returns the architecture type" do
+ FFI::Platform::ARCH.should == RbConfig::CONFIG["target_cpu"]
+ end
+end
+
+describe "FFI::Platform::OS" do
+ it "returns 'linux' as a string", if: RbConfig::CONFIG['host_os'].match('linux') do
+ FFI::Platform::OS.should == 'linux'
+ end
+
+ it "returns 'windows' as a string", if: RbConfig::CONFIG['host_os'].match('windows') do
+ FFI::Platform::OS.should == 'windows'
+ end
+
+ it "returns 'darwin' as a string", if: RbConfig::CONFIG['host_os'].match('darwin') do
+ FFI::Platform::OS.should == 'darwin'
+ end
+
+ describe "FFI::Platform.windows?" do
+ it "returns false", if: RbConfig::CONFIG['host_os'].match('linux') do
+ FFI::Platform.windows?.should == false
+ end
+
+ it "returns true", if: RbConfig::CONFIG['host_os'].match('windows') do
+ FFI::Platform.windows?.should == true
+ end
+
+ it "returns false", if: RbConfig::CONFIG['host_os'].match('darwin') do
+ FFI::Platform.windows?.should == false
+ end
+ end
+
+ describe "FFI::Platform.mac?" do
+ it "returns false", if: RbConfig::CONFIG['host_os'].match('linux') do
+ FFI::Platform.mac?.should == false
+ end
+
+ it "returns false", if: RbConfig::CONFIG['host_os'].match('windows') do
+ FFI::Platform.mac?.should == false
+ end
+
+ it "returns true", if: RbConfig::CONFIG['host_os'].match('darwin') do
+ FFI::Platform.mac?.should == true
+ end
+ end
+
+ describe "FFI::Platform.unix?" do
+ it "returns true", if: RbConfig::CONFIG['host_os'].match('linux') do
+ FFI::Platform.unix?.should == true
+ end
+
+ it "returns false", if: RbConfig::CONFIG['host_os'].match('windows') do
+ FFI::Platform.unix?.should == false
+ end
+
+ it "returns true", if: RbConfig::CONFIG['host_os'].match('darwin') do
+ FFI::Platform.unix?.should == true
+ end
+ end
+end
diff --git a/spec/ffi/pointer_spec.rb b/spec/ffi/pointer_spec.rb
index ee4068d..2ddec39 100644
--- a/spec/ffi/pointer_spec.rb
+++ b/spec/ffi/pointer_spec.rb
@@ -2,9 +2,10 @@
# This file is part of ruby-ffi.
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+
+require 'ffi'
+require_relative 'spec_helper'
require 'delegate'
-require 'java' if RUBY_PLATFORM =~ /java/
module PointerTestLib
extend FFI::Library
diff --git a/spec/ffi/rbx/attach_function_spec.rb b/spec/ffi/rbx/attach_function_spec.rb
index 488414e..9099509 100644
--- a/spec/ffi/rbx/attach_function_spec.rb
+++ b/spec/ffi/rbx/attach_function_spec.rb
@@ -1,4 +1,10 @@
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+#
+# This file is part of ruby-ffi.
+# For licensing, see LICENSE.SPECS
+#
+
+require 'ffi'
+require_relative 'spec_helper'
class Timeval < FFI::Struct
layout :tv_sec, :ulong, 0, :tv_usec, :ulong, 4
diff --git a/spec/ffi/rbx/memory_pointer_spec.rb b/spec/ffi/rbx/memory_pointer_spec.rb
index 8162198..a868d3f 100644
--- a/spec/ffi/rbx/memory_pointer_spec.rb
+++ b/spec/ffi/rbx/memory_pointer_spec.rb
@@ -1,6 +1,10 @@
-# coding: utf-8
-require "rubygems"
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+#
+# This file is part of ruby-ffi.
+# For licensing, see LICENSE.SPECS
+#
+
+require 'ffi'
+require_relative 'spec_helper'
module CTest
extend FFI::Library
@@ -17,7 +21,7 @@ describe "MemoryPointer" do
end
it "does not make a pointer from non-strings" do
- expect { FFI::MemoryPointer.from_string(nil) }.to raise_error(TypeError)
+ expect {FFI::MemoryPointer.from_string(nil)}.to raise_error(TypeError)
end
it "makes a pointer from a string with multibyte characters" do
diff --git a/spec/ffi/rbx/spec_helper.rb b/spec/ffi/rbx/spec_helper.rb
index c8b41a1..a05eda6 100644
--- a/spec/ffi/rbx/spec_helper.rb
+++ b/spec/ffi/rbx/spec_helper.rb
@@ -1 +1,7 @@
-require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
+#
+# This file is part of ruby-ffi.
+# For licensing, see LICENSE.SPECS
+#
+
+require_relative File.join("..", "spec_helper")
+require 'ffi' \ No newline at end of file
diff --git a/spec/ffi/rbx/struct_spec.rb b/spec/ffi/rbx/struct_spec.rb
index 092a1a5..0e7cf3f 100644
--- a/spec/ffi/rbx/struct_spec.rb
+++ b/spec/ffi/rbx/struct_spec.rb
@@ -1,4 +1,10 @@
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+#
+# This file is part of ruby-ffi.
+# For licensing, see LICENSE.SPECS
+#
+
+require 'ffi'
+require_relative 'spec_helper'
class Timeval < FFI::Struct
layout :tv_sec, :ulong, 0, :tv_usec, :ulong, 4
@@ -10,4 +16,4 @@ describe FFI::Struct do
t[:tv_sec] = 12
t[:tv_sec].should == 12
end
-end \ No newline at end of file
+end
diff --git a/spec/ffi/spec_helper.rb b/spec/ffi/spec_helper.rb
index fb9d141..291157d 100644
--- a/spec/ffi/spec_helper.rb
+++ b/spec/ffi/spec_helper.rb
@@ -2,21 +2,81 @@
# This file is part of ruby-ffi.
# For licensing, see LICENSE.SPECS
#
-require 'rubygems'
+
require 'rbconfig'
+require 'ffi'
+
+CPU = case RbConfig::CONFIG['host_cpu'].downcase
+ when /i[3456]86/
+ # Darwin always reports i686, even when running in 64bit mode
+ if RbConfig::CONFIG['host_os'] =~ /darwin/ && 0xfee1deadbeef.is_a?(Fixnum)
+ "x86_64"
+ else
+ "i386"
+ end
+
+ when /amd64|x86_64/
+ "x86_64"
+
+ when /ppc64|powerpc64/
+ "powerpc64"
+
+ when /ppc|powerpc/
+ "powerpc"
+
+ when /^arm/
+ "arm"
+
+ else
+ RbConfig::CONFIG['host_cpu']
+ end
+
+OS = case RbConfig::CONFIG['host_os'].downcase
+ when /linux/
+ "linux"
+ when /darwin/
+ "darwin"
+ when /freebsd/
+ "freebsd"
+ when /openbsd/
+ "openbsd"
+ when /sunos|solaris/
+ "solaris"
+ when /mswin|mingw/
+ "win32"
+ else
+ RbConfig::CONFIG['host_os'].downcase
+ end
+
+def compile_library(path, lib)
+
+ dir = File.expand_path(path, File.dirname(__FILE__))
+ lib = "#{dir}/#{lib}"
+ if !File.exists?(lib)
+ ldshared = RbConfig::CONFIG["LDSHARED"]
+ libs = RbConfig::CONFIG["LIBS"]
+ dldflags = RbConfig::CONFIG["DLDFLAGS"]
+
+ puts Dir.pwd, dir, File.dirname(__FILE__)
+
+ FileUtils.cd(dir) do
+ output = system(*%{#{system('which gmake >/dev/null') && 'gmake' || 'make'} CPU=#{CPU} OS=#{OS} }.tap{|x| puts x.inspect})
+ end
-if RUBY_PLATFORM =~/java/
- libdir = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "lib"))
- $:.reject! { |p| p == libdir }
-else
- $:.unshift File.join(File.dirname(__FILE__), "..", "..", "lib"),
- File.join(File.dirname(__FILE__), "..", "..", "build", "#{RbConfig::CONFIG['host_cpu''arch']}", "ffi_c", RUBY_VERSION)
+ if $?.exitstatus != 0
+ puts "ERROR:\n#{output}"
+ raise "Unable to compile \"#{lib}\""
+ end
+ end
+
+ lib
end
-# puts "loadpath=#{$:.join(':')}"
+
require "ffi"
module TestLibrary
- PATH = "build/libtest.#{FFI::Platform::LIBSUFFIX}"
+ PATH = compile_library("fixtures", "libtest.#{FFI::Platform::LIBSUFFIX}")
+
def self.force_gc
if RUBY_PLATFORM =~ /java/
java.lang.System.gc
diff --git a/spec/ffi/string_spec.rb b/spec/ffi/string_spec.rb
index c76bcba..05ae20d 100644
--- a/spec/ffi/string_spec.rb
+++ b/spec/ffi/string_spec.rb
@@ -3,7 +3,9 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
+
describe "String tests" do
include FFI
module StrLibTest
@@ -43,7 +45,7 @@ describe "String tests" do
end
end if false
it "casts nil as NULL pointer" do
- StrLibTest.string_dummy(nil)
+ StrLibTest.string_dummy(nil).should == nil
end
it "return nil for NULL char*" do
StrLibTest.string_null.should == nil
diff --git a/spec/ffi/strptr_spec.rb b/spec/ffi/strptr_spec.rb
index 1e6f474..b837613 100644
--- a/spec/ffi/strptr_spec.rb
+++ b/spec/ffi/strptr_spec.rb
@@ -3,7 +3,8 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
describe "functions returning :strptr" do
diff --git a/spec/ffi/struct_by_ref_spec.rb b/spec/ffi/struct_by_ref_spec.rb
index 94dda98..1b73cad 100644
--- a/spec/ffi/struct_by_ref_spec.rb
+++ b/spec/ffi/struct_by_ref_spec.rb
@@ -3,7 +3,8 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
describe FFI::Struct, ' by_ref' do
before :all do
@@ -11,7 +12,7 @@ describe FFI::Struct, ' by_ref' do
layout :a, :pointer
end
- @api = Module.new do
+ @api = Module.new do
extend FFI::Library
ffi_lib TestLibrary::PATH
fn = FFI::Type::POINTER.size == FFI::Type::LONG.size ? :ret_ulong : :ret_u64
@@ -23,7 +24,7 @@ describe FFI::Struct, ' by_ref' do
s = @struct_class.new
@api.struct_test(s).should == s.pointer
end
-
+
it "should accept nil" do
@api.struct_test(nil).should == nil
end
diff --git a/spec/ffi/struct_callback_spec.rb b/spec/ffi/struct_callback_spec.rb
index 8ba9773..5fc1b38 100644
--- a/spec/ffi/struct_callback_spec.rb
+++ b/spec/ffi/struct_callback_spec.rb
@@ -3,7 +3,8 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
describe FFI::Struct, ' with inline callback functions' do
it 'should be able to define inline callback field' do
@@ -19,7 +20,7 @@ describe FFI::Struct, ' with inline callback functions' do
end
attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
- end
+ end.should be_an_instance_of FFI::Function
end
it 'should take methods as callbacks' do
module CallbackMember2
diff --git a/spec/ffi/struct_initialize_spec.rb b/spec/ffi/struct_initialize_spec.rb
index a340781..796a584 100644
--- a/spec/ffi/struct_initialize_spec.rb
+++ b/spec/ffi/struct_initialize_spec.rb
@@ -3,7 +3,8 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
describe FFI::Struct, ' with an initialize function' do
it "should call the initialize function" do
diff --git a/spec/ffi/struct_packed_spec.rb b/spec/ffi/struct_packed_spec.rb
index 2c35f0b..68979ad 100644
--- a/spec/ffi/struct_packed_spec.rb
+++ b/spec/ffi/struct_packed_spec.rb
@@ -3,7 +3,8 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
describe FFI::Struct do
it "packed :char followed by :int should have size of 5" do
diff --git a/spec/ffi/struct_spec.rb b/spec/ffi/struct_spec.rb
index 7cf24d8..6fe2378 100644
--- a/spec/ffi/struct_spec.rb
+++ b/spec/ffi/struct_spec.rb
@@ -3,7 +3,9 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
+
describe "Struct tests" do
StructTypes = {
's8' => :char,
@@ -61,7 +63,7 @@ describe "Struct tests" do
it "Struct#[:pointer]=struct" do
smp = FFI::MemoryPointer.new :pointer
s = PointerMember.new smp
- lambda { s[:pointer] = s }.should_not raise_error
+ lambda { s[:pointer] = s }.should_not raise_error Exception
end
it "Struct#[:pointer]=nil" do
smp = FFI::MemoryPointer.new :pointer
@@ -121,21 +123,19 @@ describe "Struct tests" do
s[:b] = 0xfee1deadbeef
mp.get_int64(4).should == 0xfee1deadbeef
end
- rb_maj, rb_min = RUBY_VERSION.split('.')
- if rb_maj.to_i >= 1 && rb_min.to_i >= 9 || RUBY_PLATFORM =~ /java/
- it "Struct#layout withs with a hash of :name => type" do
- class HashLayout < FFI::Struct
- layout :a => :int, :b => :long_long
- end
- ll_off = (FFI::TYPE_UINT64.alignment == 4? 4 : 8)
- HashLayout.size.should == (ll_off + 8)
- mp = FFI::MemoryPointer.new(HashLayout.size)
- s = HashLayout.new mp
- s[:a] = 0x12345678
- mp.get_int(0).should == 0x12345678
- s[:b] = 0xfee1deadbeef
- mp.get_int64(ll_off).should == 0xfee1deadbeef
- end
+
+ it "Struct#layout withs with a hash of :name => type" do
+ class HashLayout < FFI::Struct
+ layout :a => :int, :b => :long_long
+ end
+ ll_off = (FFI::TYPE_UINT64.alignment == 4? 4 : 8)
+ HashLayout.size.should == (ll_off + 8)
+ mp = FFI::MemoryPointer.new(HashLayout.size)
+ s = HashLayout.new mp
+ s[:a] = 0x12345678
+ mp.get_int(0).should == 0x12345678
+ s[:b] = 0xfee1deadbeef
+ mp.get_int64(ll_off).should == 0xfee1deadbeef
end
it "subclass overrides initialize without calling super" do
@@ -163,7 +163,7 @@ describe "Struct tests" do
layout :c, :char
end
attach_function :struct_field_s8, [ TestStruct.in ], :char
- end
+ end.should be_an_instance_of FFI::Function
end
it "Can use Struct subclass as IN parameter type" do
module StructParam2
@@ -173,7 +173,7 @@ describe "Struct tests" do
layout :c, :char
end
attach_function :struct_field_s8, [ TestStruct.in ], :char
- end
+ end.should be_an_instance_of FFI::Function
end
it "Can use Struct subclass as OUT parameter type" do
module StructParam3
@@ -183,7 +183,7 @@ describe "Struct tests" do
layout :c, :char
end
attach_function :struct_field_s8, [ TestStruct.out ], :char
- end
+ end.should be_an_instance_of FFI::Function
end
it "can be passed directly as a :pointer parameter" do
class TestStruct < FFI::Struct
@@ -261,7 +261,7 @@ describe "Struct tests" do
def test_num_field(type, v)
klass = Class.new(FFI::Struct)
klass.layout :v, type, :dummy, :long
-
+
s = klass.new
s[:v] = v
s.pointer.send("get_#{type.to_s}", 0).should == v
@@ -312,11 +312,11 @@ describe "Struct tests" do
extend FFI::Library
TestEnum = enum :test_enum, [:c1, 10, :c2, 20, :c3, 30, :c4, 40]
class TestStruct < FFI::Struct
- layout :a, :int, :c, :test_enum,
+ layout :a, :int, :c, :test_enum,
:d, [ TestEnum, TestEnum.symbols.length ]
end
end
-
+
it ":enum field r/w" do
s = EnumFields::TestStruct.new
s[:c] = :c3
@@ -324,22 +324,22 @@ describe "Struct tests" do
s.pointer.get_uint(FFI::Type::INT32.size).should == 30
s[:c].should == :c3
end
-
+
it "array of :enum field" do
s = EnumFields::TestStruct.new
EnumFields::TestEnum.symbols.each_with_index do |val, i|
s[:d][i] = val
end
-
+
EnumFields::TestEnum.symbols.each_with_index do |val, i|
s.pointer.get_uint(FFI::Type::INT32.size * (2 + i)).should == EnumFields::TestEnum[val]
end
-
+
s[:d].each_with_index do |val, i|
val.should == EnumFields::TestEnum.symbols[i]
end
end
-
+
module CallbackMember
extend FFI::Library
ffi_lib TestLibrary::PATH
@@ -396,6 +396,53 @@ describe "Struct tests" do
end
end
+describe FFI::Struct, ".layout" do
+ module FFISpecs
+ module LibTest
+ extend FFI::Library
+ ffi_lib TestLibrary::PATH
+ attach_function :ptr_ret_int32_t, [ :pointer, :int ], :int
+ end
+ end
+
+ describe "when derived class is not assigned to any constant" do
+ it "resolves a built-in type" do
+ klass = Class.new FFI::Struct
+ klass.layout :number, :int
+
+ instance = klass.new
+ instance[:number] = 0xA1
+ FFISpecs::LibTest.ptr_ret_int32_t(instance, 0).should == 0xA1
+ end
+ end
+
+ describe "when derived class is assigned to a constant" do
+ it "resolves a built-in type" do
+ class FFISpecs::TestStruct < FFI::Struct
+ layout :number, :int
+ end
+
+ instance = FFISpecs::TestStruct.new
+ instance[:number] = 0xA1
+ FFISpecs::LibTest.ptr_ret_int32_t(instance, 0).should == 0xA1
+ end
+
+ it "resolves a type from the enclosing module" do
+ module FFISpecs::LibTest
+ typedef :uint, :custom_int
+
+ class TestStruct < FFI::Struct
+ layout :number, :custom_int
+ end
+ end
+
+ instance = FFISpecs::LibTest::TestStruct.new
+ instance[:number] = 0xA1
+ FFISpecs::LibTest.ptr_ret_int32_t(instance, 0).should == 0xA1
+ end
+ end
+end
+
describe FFI::Struct, ' with a nested struct field' do
module LibTest
extend FFI::Library
@@ -420,7 +467,7 @@ describe FFI::Struct, ' with a nested struct field' do
LibTest::ContainerStruct.size.should == 8
end
it 'should return a Struct object when the field is accessed' do
- @cs[:ns].is_a?(FFI::Struct).should be_true
+ @cs[:ns].is_a?(FFI::Struct).should be_true
end
it 'should read a value from memory' do
@cs = LibTest::ContainerStruct.new(LibTest.struct_make_container_struct(123))
@@ -432,7 +479,7 @@ describe FFI::Struct, ' with a nested struct field' do
LibTest.struct_align_nested_struct(@cs.to_ptr).should == 456
end
- it 'should be able to assign struct instance to nested field' do
+ it 'should be able to assign struct instance to nested field' do
cs = LibTest::ContainerStruct.new(LibTest.struct_make_container_struct(123))
ns = LibTest::NestedStruct.new
ns[:i] = 567
@@ -540,15 +587,18 @@ describe FFI::Struct, ' by value' do
s = LibTest::S8S32.new
s[:s8] = 0x12
s[:s32] = 0x34567890
-
+
LibTest.struct_s8s32_s32_ret_s32(s, 0x1eefdead).should == 0x1eefdead
end
- it 'parameter with following s64' do
- s = LibTest::S8S32.new
- s[:s8] = 0x12
- s[:s32] = 0x34567890
- end
+ # it 'parameter with following s64' do
+ # s = LibTest::S8S64.new
+ # s[:s8] = 0x12
+ # s[:s64] = 0x34567890
+ #
+ #
+ # LibTest.struct_s8s64_s64_ret_s64(s, 0x1eefdead1eefdead).should == 0x1eefdead1eefdead
+ # end
it 'parameter with preceding s32,ptr,s32' do
s = LibTest::S8S32.new
@@ -615,7 +665,7 @@ describe FFI::Struct, ' with an array field' do
end
it 'should allow iteration through the array elements' do
@s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
- @s[:a].each_with_index { |elem, i| elem.should == i }
+ @s[:a].each_with_index { |elem, i| elem.should == i }
end
it 'should return the pointer to the array' do
@s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
@@ -652,7 +702,7 @@ describe 'BuggedStruct' do
end
it 'should return correct field/offset pairs' do
LibTest::BuggedStruct.offsets.sort do |a, b|
- a[1] <=> b[1]
+ a[1] <=> b[1]
end.should == [[:visible, 0], [:x, 4], [:y, 8], [:rx, 12], [:ry, 14], [:order, 16], [:size, 17]]
end
end
@@ -702,7 +752,7 @@ describe "Struct allocation" do
end
struct = c.new
struct[:b] = ! struct[:b]
- end.should_not raise_error
+ end.should_not raise_error Exception
end
end
@@ -713,7 +763,7 @@ describe "variable-length arrays" do
Class.new(FFI::Struct) do
layout :count, :int, :data, [ :char, 0 ]
end
- }.should_not raise_error
+ }.should_not raise_error Exception
end
it "zero length array before last element should raise error" do
diff --git a/spec/ffi/typedef_spec.rb b/spec/ffi/typedef_spec.rb
index 7c3b569..412030b 100644
--- a/spec/ffi/typedef_spec.rb
+++ b/spec/ffi/typedef_spec.rb
@@ -3,7 +3,9 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
+
describe "Custom type definitions" do
it "attach_function with custom typedef" do
module CustomTypedef
diff --git a/spec/ffi/union_spec.rb b/spec/ffi/union_spec.rb
index 2b3cf44..4e52470 100644
--- a/spec/ffi/union_spec.rb
+++ b/spec/ffi/union_spec.rb
@@ -3,7 +3,8 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
module LibTest
Types = {
diff --git a/spec/ffi/variadic_spec.rb b/spec/ffi/variadic_spec.rb
index a19cf59..1d08e4d 100644
--- a/spec/ffi/variadic_spec.rb
+++ b/spec/ffi/variadic_spec.rb
@@ -3,7 +3,9 @@
# For licensing, see LICENSE.SPECS
#
-require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+require 'ffi'
+require_relative 'spec_helper'
+
describe "Function with variadic arguments" do
module LibTest
extend FFI::Library
diff --git a/spec/spec.opts b/spec/spec.opts
index 81b5382..4cc9a8a 100644
--- a/spec/spec.opts
+++ b/spec/spec.opts
@@ -1,4 +1,3 @@
--color
--format
-specdoc
-
+documentation