diff options
61 files changed, 1783 insertions, 1066 deletions
@@ -1,4 +1,5 @@ doc/ +bin/ .yardoc *.orig nbproject/private @@ -16,3 +17,4 @@ lib/ffi_c.bundle lib/ffi_c.so vendor .bundle +Gemfile.lock diff --git a/.travis.yml b/.travis.yml index 5c2ef43..0f00298 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,21 @@ language: ruby script: bundle exec rake test +os: + - linux + - osx rvm: - "1.9.3" - "1.8.7" - "2.0.0" - "2.1" + - "2.2" - "ruby-head" - - "rbx-2.1.1" - "rbx" +env: + - CC=gcc + - CC=clang matrix: allow_failures: - - rvm: "rbx-2.1.1" - rvm: "rbx" - rvm: "rbx-head" - rvm: "1.8.7" @@ -2,8 +2,8 @@ source 'https://rubygems.org' group :development do gem 'rake', '~> 10.1' - gem 'rake-compiler', '~> 0.9.2', :platforms => ['ruby', 'mingw', 'mswin'] - gem 'rspec', '~> 2.14.1' + gem 'rake-compiler', '~> 0.9.5' + gem 'rspec', '~> 3.0' gem 'rubygems-tasks', '~> 0.2.4', :require => 'rubygems/tasks' gem "rubysl", "~> 2.0", :platforms => 'rbx' end diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 48ef658..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,229 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - diff-lcs (1.2.5) - ffi2-generators (0.1.1) - rake (10.3.2) - rake-compiler (0.9.2) - rake - rspec (2.14.1) - rspec-core (~> 2.14.0) - rspec-expectations (~> 2.14.0) - rspec-mocks (~> 2.14.0) - rspec-core (2.14.8) - rspec-expectations (2.14.5) - diff-lcs (>= 1.1.3, < 2.0) - rspec-mocks (2.14.6) - rubygems-tasks (0.2.4) - rubysl (2.0.15) - rubysl-abbrev (~> 2.0) - rubysl-base64 (~> 2.0) - rubysl-benchmark (~> 2.0) - rubysl-bigdecimal (~> 2.0) - rubysl-cgi (~> 2.0) - rubysl-cgi-session (~> 2.0) - rubysl-cmath (~> 2.0) - rubysl-complex (~> 2.0) - rubysl-continuation (~> 2.0) - rubysl-coverage (~> 2.0) - rubysl-csv (~> 2.0) - rubysl-curses (~> 2.0) - rubysl-date (~> 2.0) - rubysl-delegate (~> 2.0) - rubysl-digest (~> 2.0) - rubysl-drb (~> 2.0) - rubysl-e2mmap (~> 2.0) - rubysl-english (~> 2.0) - rubysl-enumerator (~> 2.0) - rubysl-erb (~> 2.0) - rubysl-etc (~> 2.0) - rubysl-expect (~> 2.0) - rubysl-fcntl (~> 2.0) - rubysl-fiber (~> 2.0) - rubysl-fileutils (~> 2.0) - rubysl-find (~> 2.0) - rubysl-forwardable (~> 2.0) - rubysl-getoptlong (~> 2.0) - rubysl-gserver (~> 2.0) - rubysl-io-console (~> 2.0) - rubysl-io-nonblock (~> 2.0) - rubysl-io-wait (~> 2.0) - rubysl-ipaddr (~> 2.0) - rubysl-irb (~> 2.0) - rubysl-logger (~> 2.0) - rubysl-mathn (~> 2.0) - rubysl-matrix (~> 2.0) - rubysl-mkmf (~> 2.0) - rubysl-monitor (~> 2.0) - rubysl-mutex_m (~> 2.0) - rubysl-net-ftp (~> 2.0) - rubysl-net-http (~> 2.0) - rubysl-net-imap (~> 2.0) - rubysl-net-pop (~> 2.0) - rubysl-net-protocol (~> 2.0) - rubysl-net-smtp (~> 2.0) - rubysl-net-telnet (~> 2.0) - rubysl-nkf (~> 2.0) - rubysl-observer (~> 2.0) - rubysl-open-uri (~> 2.0) - rubysl-open3 (~> 2.0) - rubysl-openssl (~> 2.0) - rubysl-optparse (~> 2.0) - rubysl-ostruct (~> 2.0) - rubysl-pathname (~> 2.0) - rubysl-prettyprint (~> 2.0) - rubysl-prime (~> 2.0) - rubysl-profile (~> 2.0) - rubysl-profiler (~> 2.0) - rubysl-pstore (~> 2.0) - rubysl-pty (~> 2.0) - rubysl-rational (~> 2.0) - rubysl-readline (~> 2.0) - rubysl-resolv (~> 2.0) - rubysl-rexml (~> 2.0) - rubysl-rinda (~> 2.0) - rubysl-rss (~> 2.0) - rubysl-scanf (~> 2.0) - rubysl-securerandom (~> 2.0) - rubysl-set (~> 2.0) - rubysl-shellwords (~> 2.0) - rubysl-singleton (~> 2.0) - rubysl-socket (~> 2.0) - rubysl-stringio (~> 2.0) - rubysl-strscan (~> 2.0) - rubysl-sync (~> 2.0) - rubysl-syslog (~> 2.0) - rubysl-tempfile (~> 2.0) - rubysl-thread (~> 2.0) - rubysl-thwait (~> 2.0) - rubysl-time (~> 2.0) - rubysl-timeout (~> 2.0) - rubysl-tmpdir (~> 2.0) - rubysl-tsort (~> 2.0) - rubysl-un (~> 2.0) - rubysl-uri (~> 2.0) - rubysl-weakref (~> 2.0) - rubysl-webrick (~> 2.0) - rubysl-xmlrpc (~> 2.0) - rubysl-yaml (~> 2.0) - rubysl-zlib (~> 2.0) - rubysl-abbrev (2.0.4) - rubysl-base64 (2.0.0) - rubysl-benchmark (2.0.1) - rubysl-bigdecimal (2.0.2) - rubysl-cgi (2.0.1) - rubysl-cgi-session (2.0.1) - rubysl-cmath (2.0.0) - rubysl-complex (2.0.0) - rubysl-continuation (2.0.0) - rubysl-coverage (2.0.3) - rubysl-csv (2.0.2) - rubysl-english (~> 2.0) - rubysl-curses (2.0.1) - rubysl-date (2.0.6) - rubysl-delegate (2.0.1) - rubysl-digest (2.0.3) - rubysl-drb (2.0.1) - rubysl-e2mmap (2.0.0) - rubysl-english (2.0.0) - rubysl-enumerator (2.0.0) - rubysl-erb (2.0.1) - rubysl-etc (2.0.3) - ffi2-generators (~> 0.1) - rubysl-expect (2.0.0) - rubysl-fcntl (2.0.4) - ffi2-generators (~> 0.1) - rubysl-fiber (2.0.0) - rubysl-fileutils (2.0.3) - rubysl-find (2.0.1) - rubysl-forwardable (2.0.1) - rubysl-getoptlong (2.0.0) - rubysl-gserver (2.0.0) - rubysl-socket (~> 2.0) - rubysl-thread (~> 2.0) - rubysl-io-console (2.0.0) - rubysl-io-nonblock (2.0.0) - rubysl-io-wait (2.0.0) - rubysl-ipaddr (2.0.0) - rubysl-irb (2.0.4) - rubysl-e2mmap (~> 2.0) - rubysl-mathn (~> 2.0) - rubysl-readline (~> 2.0) - rubysl-thread (~> 2.0) - rubysl-logger (2.0.0) - rubysl-mathn (2.0.0) - rubysl-matrix (2.1.0) - rubysl-e2mmap (~> 2.0) - rubysl-mkmf (2.0.1) - rubysl-fileutils (~> 2.0) - rubysl-shellwords (~> 2.0) - rubysl-monitor (2.0.0) - rubysl-mutex_m (2.0.0) - rubysl-net-ftp (2.0.1) - rubysl-net-http (2.0.4) - rubysl-cgi (~> 2.0) - rubysl-erb (~> 2.0) - rubysl-singleton (~> 2.0) - rubysl-net-imap (2.0.1) - rubysl-net-pop (2.0.1) - rubysl-net-protocol (2.0.1) - rubysl-net-smtp (2.0.1) - rubysl-net-telnet (2.0.0) - rubysl-nkf (2.0.1) - rubysl-observer (2.0.0) - rubysl-open-uri (2.0.0) - rubysl-open3 (2.0.0) - rubysl-openssl (2.1.0) - rubysl-optparse (2.0.1) - rubysl-shellwords (~> 2.0) - rubysl-ostruct (2.0.4) - rubysl-pathname (2.0.0) - rubysl-prettyprint (2.0.3) - rubysl-prime (2.0.1) - rubysl-profile (2.0.0) - rubysl-profiler (2.0.1) - rubysl-pstore (2.0.0) - rubysl-pty (2.0.2) - rubysl-rational (2.0.1) - rubysl-readline (2.0.2) - rubysl-resolv (2.1.0) - rubysl-rexml (2.0.2) - rubysl-rinda (2.0.1) - rubysl-rss (2.0.0) - rubysl-scanf (2.0.0) - rubysl-securerandom (2.0.0) - rubysl-set (2.0.1) - rubysl-shellwords (2.0.0) - rubysl-singleton (2.0.0) - rubysl-socket (2.0.1) - rubysl-stringio (2.0.0) - rubysl-strscan (2.0.0) - rubysl-sync (2.0.0) - rubysl-syslog (2.0.1) - ffi2-generators (~> 0.1) - rubysl-tempfile (2.0.1) - rubysl-thread (2.0.2) - rubysl-thwait (2.0.0) - rubysl-time (2.0.3) - rubysl-timeout (2.0.0) - rubysl-tmpdir (2.0.1) - rubysl-tsort (2.0.1) - rubysl-un (2.0.0) - rubysl-fileutils (~> 2.0) - rubysl-optparse (~> 2.0) - rubysl-uri (2.0.0) - rubysl-weakref (2.0.0) - rubysl-webrick (2.0.0) - rubysl-xmlrpc (2.0.0) - rubysl-yaml (2.0.4) - rubysl-zlib (2.0.1) - -PLATFORMS - ruby - -DEPENDENCIES - rake (~> 10.1) - rake-compiler (~> 0.9.2) - rspec (~> 2.14.1) - rubygems-tasks (~> 0.2.4) - rubysl (~> 2.0) @@ -63,7 +63,7 @@ as Rubyspec, see the LICENSE.SPECS file. ## Credits -The following people have submitted code, bug reports, or otherwide contributed to the success of this project: +The following people have submitted code, bug reports, or otherwise contributed to the success of this project: * Alban Peignier <alban.peignier@free.fr> * Aman Gupta <aman@tmm1.net> @@ -13,11 +13,6 @@ require 'rbconfig' require 'rspec/core/rake_task' require 'rubygems/package_task' -RSpec::Core::RakeTask.new(:spec => :compile) do |config| - config.rspec_opts = YAML.load_file 'spec/spec.opts' -end - - LIBEXT = case RbConfig::CONFIG['host_os'].downcase when /darwin/ "dylib" @@ -81,26 +76,15 @@ end TEST_DEPS = [ LIBTEST ] if RUBY_PLATFORM == "java" - desc "Run all specs" - task :specs => TEST_DEPS do - sh %{#{Gem.ruby} -w -S rspec #{Dir["spec/ffi/*_spec.rb"].join(" ")} -fs --color} - end - desc "Run rubinius specs" - task :rbxspecs => TEST_DEPS do - sh %{#{Gem.ruby} -w -S rspec #{Dir["spec/ffi/rbx/*_spec.rb"].join(" ")} -fs --color} + RSpec::Core::RakeTask.new(:spec) do |config| + config.rspec_opts = YAML.load_file 'spec/spec.opts' end else - TEST_DEPS.unshift :compile - desc "Run all specs" - task :specs => TEST_DEPS do - ENV["MRI_FFI"] = "1" - sh %{#{Gem.ruby} -w -Ilib -I#{BUILD_EXT_DIR} -S rspec #{Dir["spec/ffi/*_spec.rb"].join(" ")} -fs --color} - end - desc "Run rubinius specs" - task :rbxspecs => TEST_DEPS do - ENV["MRI_FFI"] = "1" - sh %{#{Gem.ruby} -w -Ilib -I#{BUILD_EXT_DIR} -S rspec #{Dir["spec/ffi/rbx/*_spec.rb"].join(" ")} -fs --color} + RSpec::Core::RakeTask.new(:spec => :compile) do |config| + config.rspec_opts = YAML.load_file 'spec/spec.opts' end + + TEST_DEPS.unshift :compile end desc "Build all packages" @@ -150,11 +134,6 @@ task 'spec:specdoc' => TEST_DEPS task :default => :specs -task 'gem:win32' do - sh("rake cross native gem RUBY_CC_VERSION='1.8.7:1.9.3:2.0.0'") || raise("win32 build failed!") -end - - namespace 'java' do java_gem_spec = Gem::Specification.new do |s| @@ -190,11 +169,23 @@ if USE_RAKE_COMPILER ext.cross_platform = %w[i386-mingw32 x64-mingw32] # forces the Windows platform instead of the default one end - ENV['RUBY_CC_VERSION'].to_s.split(':').each do |ruby_version| + task 'gem:win32' => ['gem:win32-x64', 'gem:win32-i386'] + + task 'gem:win32-i386' do + sh("rake cross native:i386-mingw32 gem RUBY_CC_VERSION='1.8.7:1.9.3:2.0.0:2.1.5:2.2.1'") || raise("win32-i386 build failed!") + end + + task 'gem:win32-x64' do + sh("rake cross native:x64-mingw32 gem RUBY_CC_VERSION='2.0.0:2.1.5:2.2.1'") || raise("win32-x64 build failed!") + end + + (ENV['RUBY_CC_VERSION'] || '1.8.7:1.9.3:2.0.0:2.1.5:2.2.1' ).to_s.split(':').each do |ruby_version| task "copy:ffi_c:i386-mingw32:#{ruby_version}" do |t| sh "i686-w64-mingw32-strip -S #{BUILD_DIR}/i386-mingw32/stage/lib/#{ruby_version[/^\d+\.\d+/]}/ffi_c.so" end + end + (ENV['RUBY_CC_VERSION'] || '2.0.0:2.1.5:2.2.1' ).to_s.split(':').each do |ruby_version| task "copy:ffi_c:x64-mingw32:#{ruby_version}" do |t| sh "x86_64-w64-mingw32-strip -S #{BUILD_DIR}/x64-mingw32/stage/lib/#{ruby_version[/^\d+\.\d+/]}/ffi_c.so" end diff --git a/ext/ffi_c/Call.c b/ext/ffi_c/Call.c index 679bfba..b028811 100644 --- a/ext/ffi_c/Call.c +++ b/ext/ffi_c/Call.c @@ -126,19 +126,30 @@ rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, Type** paramTypes, switch (paramType->nativeType) { case NATIVE_INT8: - param->s8 = NUM2INT(argv[argidx]); + if (unlikely(type == T_SYMBOL && enums != Qnil)) { + VALUE value = rb_funcall(enums, id_map_symbol, 1, argv[argidx]); + param->s8 = NUM2INT(value); + } else { + param->s8 = NUM2INT(argv[argidx]); + } + ++argidx; ADJ(param, INT8); break; - case NATIVE_INT16: - param->s16 = NUM2INT(argv[argidx]); + if (unlikely(type == T_SYMBOL && enums != Qnil)) { + VALUE value = rb_funcall(enums, id_map_symbol, 1, argv[argidx]); + param->s16 = NUM2INT(value); + + } else { + param->s16 = NUM2INT(argv[argidx]); + } + ++argidx; ADJ(param, INT16); break; - case NATIVE_INT32: if (unlikely(type == T_SYMBOL && enums != Qnil)) { VALUE value = rb_funcall(enums, id_map_symbol, 1, argv[argidx]); @@ -152,7 +163,6 @@ rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, Type** paramTypes, ADJ(param, INT32); break; - case NATIVE_BOOL: if (type != T_TRUE && type != T_FALSE) { rb_raise(rb_eTypeError, "wrong argument type (expected a boolean parameter)"); @@ -161,67 +171,122 @@ rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, Type** paramTypes, ADJ(param, INT8); break; - case NATIVE_UINT8: - param->u8 = NUM2UINT(argv[argidx]); + if (unlikely(type == T_SYMBOL && enums != Qnil)) { + VALUE value = rb_funcall(enums, id_map_symbol, 1, argv[argidx]); + param->u8 = NUM2UINT(value); + } else { + param->u8 = NUM2UINT(argv[argidx]); + } + ADJ(param, INT8); ++argidx; break; - case NATIVE_UINT16: - param->u16 = NUM2UINT(argv[argidx]); + if (unlikely(type == T_SYMBOL && enums != Qnil)) { + VALUE value = rb_funcall(enums, id_map_symbol, 1, argv[argidx]); + param->u16 = NUM2UINT(value); + } else { + param->u16 = NUM2UINT(argv[argidx]); + } + ADJ(param, INT16); ++argidx; break; - case NATIVE_UINT32: - param->u32 = NUM2UINT(argv[argidx]); + if (unlikely(type == T_SYMBOL && enums != Qnil)) { + VALUE value = rb_funcall(enums, id_map_symbol, 1, argv[argidx]); + param->u32 = NUM2UINT(value); + } else { + param->u32 = NUM2UINT(argv[argidx]); + } + ADJ(param, INT32); ++argidx; break; - case NATIVE_INT64: - param->i64 = NUM2LL(argv[argidx]); + if (unlikely(type == T_SYMBOL && enums != Qnil)) { + VALUE value = rb_funcall(enums, id_map_symbol, 1, argv[argidx]); + param->i64 = NUM2LL(value); + } else { + param->i64 = NUM2LL(argv[argidx]); + } + ADJ(param, INT64); ++argidx; break; - case NATIVE_UINT64: - param->u64 = NUM2ULL(argv[argidx]); + if (unlikely(type == T_SYMBOL && enums != Qnil)) { + VALUE value = rb_funcall(enums, id_map_symbol, 1, argv[argidx]); + param->u64 = NUM2ULL(value); + } else { + param->u64 = NUM2ULL(argv[argidx]); + } + ADJ(param, INT64); ++argidx; break; case NATIVE_LONG: - *(ffi_sarg *) param = NUM2LONG(argv[argidx]); + if (unlikely(type == T_SYMBOL && enums != Qnil)) { + VALUE value = rb_funcall(enums, id_map_symbol, 1, argv[argidx]); + *(ffi_sarg *) param = NUM2LONG(value); + } else { + *(ffi_sarg *) param = NUM2LONG(argv[argidx]); + } + ADJ(param, LONG); ++argidx; break; case NATIVE_ULONG: - *(ffi_arg *) param = NUM2ULONG(argv[argidx]); + if (unlikely(type == T_SYMBOL && enums != Qnil)) { + VALUE value = rb_funcall(enums, id_map_symbol, 1, argv[argidx]); + *(ffi_arg *) param = NUM2ULONG(value); + } else { + *(ffi_arg *) param = NUM2ULONG(argv[argidx]); + } + ADJ(param, LONG); ++argidx; break; case NATIVE_FLOAT32: - param->f32 = (float) NUM2DBL(argv[argidx]); + if (unlikely(type == T_SYMBOL && enums != Qnil)) { + VALUE value = rb_funcall(enums, id_map_symbol, 1, argv[argidx]); + param->f32 = (float) NUM2DBL(value); + } else { + param->f32 = (float) NUM2DBL(argv[argidx]); + } + ADJ(param, FLOAT32); ++argidx; break; case NATIVE_FLOAT64: - param->f64 = NUM2DBL(argv[argidx]); + if (unlikely(type == T_SYMBOL && enums != Qnil)) { + VALUE value = rb_funcall(enums, id_map_symbol, 1, argv[argidx]); + param->f64 = NUM2DBL(value); + } else { + param->f64 = NUM2DBL(argv[argidx]); + } + ADJ(param, FLOAT64); ++argidx; break; case NATIVE_LONGDOUBLE: - param->ld = rbffi_num2longdouble(argv[argidx]); + if (unlikely(type == T_SYMBOL && enums != Qnil)) { + VALUE value = rb_funcall(enums, id_map_symbol, 1, argv[argidx]); + param->ld = rbffi_num2longdouble(value); + } else { + param->ld = rbffi_num2longdouble(argv[argidx]); + } + ADJ(param, LONGDOUBLE); ++argidx; break; diff --git a/ext/ffi_c/MethodHandle.c b/ext/ffi_c/MethodHandle.c index cee1df5..b60f9cc 100644 --- a/ext/ffi_c/MethodHandle.c +++ b/ext/ffi_c/MethodHandle.c @@ -132,12 +132,6 @@ rbffi_MethodHandle_CodeAddress(MethodHandle* handle) #ifndef CUSTOM_TRAMPOLINE static void attached_method_invoke(ffi_cif* cif, void* retval, METHOD_PARAMS parameters, void* user_data); -static ffi_type* methodHandleParamTypes[] = { - &ffi_type_sint, - &ffi_type_pointer, - &ffi_type_ulong, -}; - static ffi_cif mh_cif; static bool @@ -339,7 +333,12 @@ void rbffi_MethodHandle_Init(VALUE module) { #ifndef CUSTOM_TRAMPOLINE - ffi_status ffiStatus; + ffi_status ffiStatus; + ffi_type* methodHandleParamTypes[] = { + &ffi_type_sint, + &ffi_type_pointer, + &ffi_type_ulong, + }; #endif defaultClosurePool = rbffi_ClosurePool_New((int) trampoline_size(), prep_trampoline, NULL); diff --git a/ext/ffi_c/Platform.c b/ext/ffi_c/Platform.c index c45f1eb..1305ad2 100644 --- a/ext/ffi_c/Platform.c +++ b/ext/ffi_c/Platform.c @@ -43,7 +43,7 @@ #include "rbffi_endian.h" #include "Platform.h" -#if defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) +#if defined(__GNU__) || defined(__GLIBC__) # include <gnu/lib-names.h> #endif @@ -113,7 +113,7 @@ rbffi_Platform_Init(VALUE moduleFFI) rb_define_const(PlatformModule, "LITTLE_ENDIAN", INT2FIX(LITTLE_ENDIAN)); rb_define_const(PlatformModule, "BIG_ENDIAN", INT2FIX(BIG_ENDIAN)); rb_define_const(PlatformModule, "CPU", rb_str_new2(CPU)); -#if defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) +#if defined(__GNU__) || defined(__GLIBC__) rb_define_const(PlatformModule, "GNU_LIBC", rb_str_new2(LIBC_SO)); #endif export_primitive_types(PlatformModule); diff --git a/ext/ffi_c/StructLayout.c b/ext/ffi_c/StructLayout.c index 8edc41e..483e532 100644 --- a/ext/ffi_c/StructLayout.c +++ b/ext/ffi_c/StructLayout.c @@ -510,8 +510,8 @@ struct_layout_initialize(VALUE self, VALUE fields, VALUE size, VALUE align) static VALUE struct_layout_union_bang(VALUE self) { - static const ffi_type *alignment_types[] = { &ffi_type_sint8, &ffi_type_sint16, &ffi_type_sint32, &ffi_type_sint64, - &ffi_type_float, &ffi_type_double, &ffi_type_longdouble, NULL }; + const ffi_type *alignment_types[] = { &ffi_type_sint8, &ffi_type_sint16, &ffi_type_sint32, &ffi_type_sint64, + &ffi_type_float, &ffi_type_double, &ffi_type_longdouble, NULL }; StructLayout* layout; ffi_type *t = NULL; int count, i; diff --git a/ext/ffi_c/Variadic.c b/ext/ffi_c/Variadic.c index 687e8bc..0027be2 100644 --- a/ext/ffi_c/Variadic.c +++ b/ext/ffi_c/Variadic.c @@ -170,7 +170,7 @@ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues) ffi_type* ffiReturnType; Type** paramTypes; VALUE* argv; - int paramCount = 0, i; + int paramCount = 0, fixedCount = 0, i; ffi_status ffiStatus; rbffi_frame_t frame = { 0 }; @@ -229,8 +229,12 @@ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues) if (ffiReturnType == NULL) { rb_raise(rb_eArgError, "Invalid return type"); } + + /*Get the number of fixed args from @fixed array*/ + fixedCount = RARRAY_LEN(rb_iv_get(self, "@fixed")); + #ifdef HAVE_FFI_PREP_CIF_VAR - ffiStatus = ffi_prep_cif_var(&cif, invoker->abi, paramCount, paramCount, ffiReturnType, ffiParamTypes); + ffiStatus = ffi_prep_cif_var(&cif, invoker->abi, fixedCount, paramCount, ffiReturnType, ffiParamTypes); #else ffiStatus = ffi_prep_cif(&cif, invoker->abi, paramCount, ffiReturnType, ffiParamTypes); #endif diff --git a/ext/ffi_c/extconf.rb b/ext/ffi_c/extconf.rb index 2115b00..180634f 100644 --- a/ext/ffi_c/extconf.rb +++ b/ext/ffi_c/extconf.rb @@ -9,8 +9,8 @@ if !defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'rbx' $warnflags = '' $CFLAGS.gsub!(/[\s+]-ansi/, '') $CFLAGS.gsub!(/[\s+]-std=[^\s]+/, '') - # solaris needs -c99 for <stdbool.h> - $CFLAGS << " -std=c99" if RbConfig::CONFIG['host_os'] =~ /solaris/ + # solaris 10 needs -c99 for <stdbool.h> + $CFLAGS << " -std=c99" if RbConfig::CONFIG['host_os'] =~ /solaris(!?2\.11)/ if ENV['RUBY_CC_VERSION'].nil? && (pkg_config("libffi") || have_header("ffi.h") || @@ -33,10 +33,11 @@ if !defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'rbx' $defs << "-DHAVE_EXTCONF_H" if $defs.empty? # needed so create_header works $defs << "-DUSE_INTERNAL_LIBFFI" unless libffi_ok $defs << "-DRUBY_1_9" if RUBY_VERSION >= "1.9.0" + $defs << "-DFFI_BUILDING" if RbConfig::CONFIG['host_os'] =~ /mswin/ # for compatibility with newer libffi create_header - $LOCAL_LIBS << " ./libffi/.libs/libffi_convenience.lib" if RbConfig::CONFIG['host_os'] =~ /mswin/ + $LOCAL_LIBS << " ./libffi/.libs/libffi_convenience.lib" if !libffi_ok && RbConfig::CONFIG['host_os'] =~ /mswin/ create_makefile("ffi_c") unless libffi_ok diff --git a/ext/ffi_c/libffi/src/x86/win32.S b/ext/ffi_c/libffi/src/x86/win32.S index 34ec0fd..06c893f 100644 --- a/ext/ffi_c/libffi/src/x86/win32.S +++ b/ext/ffi_c/libffi/src/x86/win32.S @@ -156,7 +156,7 @@ ca_epilogue: ret ffi_call_win32 ENDP -ffi_closure_SYSV PROC NEAR FORCEFRAME +ffi_closure_SYSV PROC NEAR <FORCEFRAME> ;; the ffi_closure ctx is passed in eax by the trampoline. sub esp, 40 @@ -314,7 +314,7 @@ ffi_closure_raw_SYSV ENDP #endif /* !FFI_NO_RAW_API */ -ffi_closure_STDCALL PROC NEAR FORCEFRAME +ffi_closure_STDCALL PROC NEAR <FORCEFRAME> ;; the ffi_closure ctx is passed in eax by the trampoline. sub esp, 40 diff --git a/ffi.gemspec b/ffi.gemspec index 4acd63a..7b5b6e3 100644 --- a/ffi.gemspec +++ b/ffi.gemspec @@ -8,7 +8,7 @@ Gem::Specification.new do |s| s.homepage = 'http://wiki.github.com/ffi/ffi' s.summary = 'Ruby FFI' s.description = 'Ruby FFI library' - s.files = %w(ffi.gemspec LICENSE COPYING README.md Rakefile) + Dir.glob("{ext,gen,lib,spec,libtest}/**/*").reject { |f| f =~ /(lib\/[12]\.[089]|\.so$|\.bundle$)/ } + s.files = %w(ffi.gemspec LICENSE COPYING README.md Rakefile) + Dir.glob("{ext,gen,lib,spec,libtest}/**/*").reject { |f| f =~ /(lib\/[12]\.[089]|\.s?[ao]$|\.bundle|\.dylib$)/ } s.extensions << 'ext/ffi_c/extconf.rb' s.has_rdoc = false s.rdoc_options = %w[--exclude=ext/ffi_c/.*\.o$ --exclude=ffi_c\.(bundle|so)$] @@ -1,12 +1,16 @@ if !defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'rbx' Object.send(:remove_const, :FFI) if defined?(::FFI) begin - if RUBY_VERSION =~ /1.8/ + if RUBY_VERSION =~ /^1\.8/ require '1.8/ffi_c' - elsif RUBY_VERSION =~ /1.9/ + elsif RUBY_VERSION =~ /^1\.9/ require '1.9/ffi_c' - elsif RUBY_VERSION =~ /2.0/ + elsif RUBY_VERSION =~ /^2\.0/ require '2.0/ffi_c' + elsif RUBY_VERSION =~ /^2\.1/ + require '2.1/ffi_c' + elsif RUBY_VERSION =~ /^2\.2/ + require '2.2/ffi_c' else require 'ffi_c' end diff --git a/lib/ffi/enum.rb b/lib/ffi/enum.rb index 9dcf4fa..0e84ba7 100644 --- a/lib/ffi/enum.rb +++ b/lib/ffi/enum.rb @@ -85,11 +85,18 @@ module FFI include DataConverter attr_reader :tag - - # @param [nil, Enumerable] info - # @param tag enum tag - def initialize(info, tag=nil) - @tag = tag + attr_reader :native_type + + # @overload initialize(info, tag=nil) + # @param [nil, Enumerable] info + # @param [nil, Symbol] tag enum tag + # @overload initialize(native_type, info, tag=nil) + # @param [FFI::Type] native_type Native type for new Enum + # @param [nil, Enumerable] info symbols and values for new Enum + # @param [nil, Symbol] tag name of new Enum + def initialize(*args) + @native_type = args.first.kind_of?(FFI::Type) ? args.shift : Type::INT + info, @tag = *args @kv_map = Hash.new unless info.nil? last_cst = nil @@ -143,12 +150,6 @@ module FFI alias to_h symbol_map alias to_hash symbol_map - # Get native type of Enum - # @return [Type::INT] - def native_type - Type::INT - end - # @param [Symbol, Integer, #to_int] val # @param ctx unused # @return [Integer] value of a enum symbol diff --git a/lib/ffi/library.rb b/lib/ffi/library.rb index 59836b8..be54b7a 100644 --- a/lib/ffi/library.rb +++ b/lib/ffi/library.rb @@ -448,9 +448,29 @@ module FFI # @example # enum [:zero, :one, :two] # unnamed enum, equivalent to above example # @param [Array] values values for enum + # @overload enum(native_type, name, values) + # Create a named enum and specify the native type. + # @example + # enum FFI::Type::UINT64, :foo, [:zero, :one, :two] # named enum + # @param [FFI::Type] native_type native type for new enum + # @param [Symbol] name name for new enum + # @param [Array] values values for enum + # @overload enum(native_type, *args) + # Create an unnamed enum and specify the native type. + # @example + # enum FFI::Type::UINT64, :zero, :one, :two # unnamed enum + # @param [FFI::Type] native_type native type for new enum + # @param args values for enum + # @overload enum(native_type, values) + # Create an unnamed enum and specify the native type. + # @example + # enum Type::UINT64, [:zero, :one, :two] # unnamed enum, equivalent to above example + # @param [FFI::Type] native_type native type for new enum + # @param [Array] values values for enum # @return [FFI::Enum] # Create a new {FFI::Enum}. def enum(*args) + native_type = args.first.kind_of?(FFI::Type) ? args.shift : nil name, values = if args[0].kind_of?(Symbol) && args[1].kind_of?(Array) [ args[0], args[1] ] elsif args[0].kind_of?(Array) @@ -459,7 +479,7 @@ module FFI [ nil, args ] end @ffi_enums = FFI::Enums.new unless defined?(@ffi_enums) - @ffi_enums << (e = FFI::Enum.new(values, name)) + @ffi_enums << (e = native_type ? FFI::Enum.new(native_type, values, name) : FFI::Enum.new(values, name)) # If called as enum :foo, [ :zero, :one, :two ], add a typedef alias typedef(e, name) if name diff --git a/lib/ffi/platform.rb b/lib/ffi/platform.rb index bba160a..ab647ef 100644 --- a/lib/ffi/platform.rb +++ b/lib/ffi/platform.rb @@ -59,6 +59,8 @@ module FFI "x86_64" when /i?86|x86|i86pc/ "i386" + when /ppc64|powerpc64/ + "powerpc64" when /ppc|powerpc/ "powerpc" else diff --git a/lib/ffi/platform/aarch64-linux/types.conf b/lib/ffi/platform/aarch64-linux/types.conf new file mode 100644 index 0000000..072c419 --- /dev/null +++ b/lib/ffi/platform/aarch64-linux/types.conf @@ -0,0 +1,104 @@ +rbx.platform.typedef.__u_char = uchar +rbx.platform.typedef.__u_short = ushort +rbx.platform.typedef.__u_int = uint +rbx.platform.typedef.__u_long = ulong +rbx.platform.typedef.__int8_t = char +rbx.platform.typedef.__uint8_t = uchar +rbx.platform.typedef.__int16_t = short +rbx.platform.typedef.__uint16_t = ushort +rbx.platform.typedef.__int32_t = int +rbx.platform.typedef.__uint32_t = uint +rbx.platform.typedef.__int64_t = long +rbx.platform.typedef.__uint64_t = ulong +rbx.platform.typedef.__quad_t = long +rbx.platform.typedef.__u_quad_t = ulong +rbx.platform.typedef.__dev_t = ulong +rbx.platform.typedef.__uid_t = uint +rbx.platform.typedef.__gid_t = uint +rbx.platform.typedef.__ino_t = ulong +rbx.platform.typedef.__ino64_t = ulong +rbx.platform.typedef.__mode_t = uint +rbx.platform.typedef.__nlink_t = uint +rbx.platform.typedef.__off_t = long +rbx.platform.typedef.__off64_t = long +rbx.platform.typedef.__pid_t = int +rbx.platform.typedef.__clock_t = long +rbx.platform.typedef.__rlim_t = ulong +rbx.platform.typedef.__rlim64_t = ulong +rbx.platform.typedef.__id_t = uint +rbx.platform.typedef.__time_t = long +rbx.platform.typedef.__useconds_t = uint +rbx.platform.typedef.__suseconds_t = long +rbx.platform.typedef.__daddr_t = int +rbx.platform.typedef.__key_t = int +rbx.platform.typedef.__clockid_t = int +rbx.platform.typedef.__timer_t = pointer +rbx.platform.typedef.__blksize_t = int +rbx.platform.typedef.__blkcnt_t = long +rbx.platform.typedef.__blkcnt64_t = long +rbx.platform.typedef.__fsblkcnt_t = ulong +rbx.platform.typedef.__fsblkcnt64_t = ulong +rbx.platform.typedef.__fsfilcnt_t = ulong +rbx.platform.typedef.__fsfilcnt64_t = ulong +rbx.platform.typedef.__fsword_t = long +rbx.platform.typedef.__ssize_t = long +rbx.platform.typedef.__syscall_slong_t = long +rbx.platform.typedef.__syscall_ulong_t = ulong +rbx.platform.typedef.__loff_t = long +rbx.platform.typedef.*__qaddr_t = long +rbx.platform.typedef.*__caddr_t = char +rbx.platform.typedef.__intptr_t = long +rbx.platform.typedef.__socklen_t = uint +rbx.platform.typedef.u_char = uchar +rbx.platform.typedef.u_short = ushort +rbx.platform.typedef.u_int = uint +rbx.platform.typedef.u_long = ulong +rbx.platform.typedef.quad_t = long +rbx.platform.typedef.u_quad_t = ulong +rbx.platform.typedef.loff_t = long +rbx.platform.typedef.ino_t = ulong +rbx.platform.typedef.dev_t = ulong +rbx.platform.typedef.gid_t = uint +rbx.platform.typedef.mode_t = uint +rbx.platform.typedef.nlink_t = uint +rbx.platform.typedef.uid_t = uint +rbx.platform.typedef.off_t = long +rbx.platform.typedef.pid_t = int +rbx.platform.typedef.id_t = uint +rbx.platform.typedef.ssize_t = long +rbx.platform.typedef.daddr_t = int +rbx.platform.typedef.key_t = int +rbx.platform.typedef.clock_t = long +rbx.platform.typedef.time_t = long +rbx.platform.typedef.clockid_t = int +rbx.platform.typedef.timer_t = pointer +rbx.platform.typedef.size_t = ulong +rbx.platform.typedef.ulong = ulong +rbx.platform.typedef.ushort = ushort +rbx.platform.typedef.uint = uint +rbx.platform.typedef.int8_t = char +rbx.platform.typedef.int16_t = short +rbx.platform.typedef.int32_t = int +rbx.platform.typedef.int64_t = long_long +rbx.platform.typedef.u_int8_t = uchar +rbx.platform.typedef.u_int16_t = ushort +rbx.platform.typedef.u_int32_t = uint +rbx.platform.typedef.u_int64_t = ulong_long +rbx.platform.typedef.register_t = long +rbx.platform.typedef.__sig_atomic_t = int +rbx.platform.typedef.suseconds_t = long +rbx.platform.typedef.__fd_mask = long +rbx.platform.typedef.fd_mask = long +rbx.platform.typedef.blksize_t = int +rbx.platform.typedef.blkcnt_t = long +rbx.platform.typedef.fsblkcnt_t = ulong +rbx.platform.typedef.fsfilcnt_t = ulong +rbx.platform.typedef.pthread_t = ulong +rbx.platform.typedef.pthread_key_t = uint +rbx.platform.typedef.pthread_once_t = int +rbx.platform.typedef.socklen_t = uint +rbx.platform.typedef.sa_family_t = ushort +rbx.platform.typedef.rlim_t = ulong +rbx.platform.typedef.__rlimit_resource_t = int +rbx.platform.typedef.__rusage_who_t = int +rbx.platform.typedef.__priority_which_t = int diff --git a/lib/ffi/platform/mips64el-linux/types.conf b/lib/ffi/platform/mips64el-linux/types.conf new file mode 100644 index 0000000..3feb704 --- /dev/null +++ b/lib/ffi/platform/mips64el-linux/types.conf @@ -0,0 +1,104 @@ +rbx.platform.typedef.__u_char = uchar +rbx.platform.typedef.__u_short = ushort +rbx.platform.typedef.__u_int = uint +rbx.platform.typedef.__u_long = ulong +rbx.platform.typedef.__int8_t = char +rbx.platform.typedef.__uint8_t = uchar +rbx.platform.typedef.__int16_t = short +rbx.platform.typedef.__uint16_t = ushort +rbx.platform.typedef.__int32_t = int +rbx.platform.typedef.__uint32_t = uint +rbx.platform.typedef.__int64_t = long +rbx.platform.typedef.__uint64_t = ulong +rbx.platform.typedef.__quad_t = long +rbx.platform.typedef.__u_quad_t = ulong +rbx.platform.typedef.__dev_t = ulong +rbx.platform.typedef.__uid_t = uint +rbx.platform.typedef.__gid_t = uint +rbx.platform.typedef.__ino_t = ulong +rbx.platform.typedef.__ino64_t = ulong +rbx.platform.typedef.__mode_t = uint +rbx.platform.typedef.__nlink_t = ulong +rbx.platform.typedef.__off_t = long +rbx.platform.typedef.__off64_t = long +rbx.platform.typedef.__pid_t = int +rbx.platform.typedef.__clock_t = long +rbx.platform.typedef.__rlim_t = ulong +rbx.platform.typedef.__rlim64_t = ulong +rbx.platform.typedef.__id_t = uint +rbx.platform.typedef.__time_t = long +rbx.platform.typedef.__useconds_t = uint +rbx.platform.typedef.__suseconds_t = long +rbx.platform.typedef.__daddr_t = int +rbx.platform.typedef.__key_t = int +rbx.platform.typedef.__clockid_t = int +rbx.platform.typedef.__timer_t = pointer +rbx.platform.typedef.__blksize_t = long +rbx.platform.typedef.__blkcnt_t = long +rbx.platform.typedef.__blkcnt64_t = long +rbx.platform.typedef.__fsblkcnt_t = ulong +rbx.platform.typedef.__fsblkcnt64_t = ulong +rbx.platform.typedef.__fsfilcnt_t = ulong +rbx.platform.typedef.__fsfilcnt64_t = ulong +rbx.platform.typedef.__fsword_t = long +rbx.platform.typedef.__ssize_t = long +rbx.platform.typedef.__syscall_slong_t = long +rbx.platform.typedef.__syscall_ulong_t = ulong +rbx.platform.typedef.__loff_t = long +rbx.platform.typedef.*__qaddr_t = long +rbx.platform.typedef.*__caddr_t = char +rbx.platform.typedef.__intptr_t = long +rbx.platform.typedef.__socklen_t = uint +rbx.platform.typedef.u_char = uchar +rbx.platform.typedef.u_short = ushort +rbx.platform.typedef.u_int = uint +rbx.platform.typedef.u_long = ulong +rbx.platform.typedef.quad_t = long +rbx.platform.typedef.u_quad_t = ulong +rbx.platform.typedef.loff_t = long +rbx.platform.typedef.ino_t = ulong +rbx.platform.typedef.dev_t = ulong +rbx.platform.typedef.gid_t = uint +rbx.platform.typedef.mode_t = uint +rbx.platform.typedef.nlink_t = ulong +rbx.platform.typedef.uid_t = uint +rbx.platform.typedef.off_t = long +rbx.platform.typedef.pid_t = int +rbx.platform.typedef.id_t = uint +rbx.platform.typedef.ssize_t = long +rbx.platform.typedef.daddr_t = int +rbx.platform.typedef.key_t = int +rbx.platform.typedef.clock_t = long +rbx.platform.typedef.time_t = long +rbx.platform.typedef.clockid_t = int +rbx.platform.typedef.timer_t = pointer +rbx.platform.typedef.size_t = ulong +rbx.platform.typedef.ulong = ulong +rbx.platform.typedef.ushort = ushort +rbx.platform.typedef.uint = uint +rbx.platform.typedef.int8_t = char +rbx.platform.typedef.int16_t = short +rbx.platform.typedef.int32_t = int +rbx.platform.typedef.int64_t = long_long +rbx.platform.typedef.u_int8_t = uchar +rbx.platform.typedef.u_int16_t = ushort +rbx.platform.typedef.u_int32_t = uint +rbx.platform.typedef.u_int64_t = ulong_long +rbx.platform.typedef.register_t = long +rbx.platform.typedef.__sig_atomic_t = int +rbx.platform.typedef.suseconds_t = long +rbx.platform.typedef.__fd_mask = long +rbx.platform.typedef.fd_mask = long +rbx.platform.typedef.blksize_t = long +rbx.platform.typedef.blkcnt_t = long +rbx.platform.typedef.fsblkcnt_t = ulong +rbx.platform.typedef.fsfilcnt_t = ulong +rbx.platform.typedef.pthread_t = ulong +rbx.platform.typedef.pthread_key_t = uint +rbx.platform.typedef.pthread_once_t = int +rbx.platform.typedef.socklen_t = uint +rbx.platform.typedef.sa_family_t = ushort +rbx.platform.typedef.rlim_t = ulong +rbx.platform.typedef.__rlimit_resource_t = int +rbx.platform.typedef.__rusage_who_t = int +rbx.platform.typedef.__priority_which_t = int diff --git a/lib/ffi/platform/powerpc64-linux/types.conf b/lib/ffi/platform/powerpc64-linux/types.conf new file mode 100644 index 0000000..3feb704 --- /dev/null +++ b/lib/ffi/platform/powerpc64-linux/types.conf @@ -0,0 +1,104 @@ +rbx.platform.typedef.__u_char = uchar +rbx.platform.typedef.__u_short = ushort +rbx.platform.typedef.__u_int = uint +rbx.platform.typedef.__u_long = ulong +rbx.platform.typedef.__int8_t = char +rbx.platform.typedef.__uint8_t = uchar +rbx.platform.typedef.__int16_t = short +rbx.platform.typedef.__uint16_t = ushort +rbx.platform.typedef.__int32_t = int +rbx.platform.typedef.__uint32_t = uint +rbx.platform.typedef.__int64_t = long +rbx.platform.typedef.__uint64_t = ulong +rbx.platform.typedef.__quad_t = long +rbx.platform.typedef.__u_quad_t = ulong +rbx.platform.typedef.__dev_t = ulong +rbx.platform.typedef.__uid_t = uint +rbx.platform.typedef.__gid_t = uint +rbx.platform.typedef.__ino_t = ulong +rbx.platform.typedef.__ino64_t = ulong +rbx.platform.typedef.__mode_t = uint +rbx.platform.typedef.__nlink_t = ulong +rbx.platform.typedef.__off_t = long +rbx.platform.typedef.__off64_t = long +rbx.platform.typedef.__pid_t = int +rbx.platform.typedef.__clock_t = long +rbx.platform.typedef.__rlim_t = ulong +rbx.platform.typedef.__rlim64_t = ulong +rbx.platform.typedef.__id_t = uint +rbx.platform.typedef.__time_t = long +rbx.platform.typedef.__useconds_t = uint +rbx.platform.typedef.__suseconds_t = long +rbx.platform.typedef.__daddr_t = int +rbx.platform.typedef.__key_t = int +rbx.platform.typedef.__clockid_t = int +rbx.platform.typedef.__timer_t = pointer +rbx.platform.typedef.__blksize_t = long +rbx.platform.typedef.__blkcnt_t = long +rbx.platform.typedef.__blkcnt64_t = long +rbx.platform.typedef.__fsblkcnt_t = ulong +rbx.platform.typedef.__fsblkcnt64_t = ulong +rbx.platform.typedef.__fsfilcnt_t = ulong +rbx.platform.typedef.__fsfilcnt64_t = ulong +rbx.platform.typedef.__fsword_t = long +rbx.platform.typedef.__ssize_t = long +rbx.platform.typedef.__syscall_slong_t = long +rbx.platform.typedef.__syscall_ulong_t = ulong +rbx.platform.typedef.__loff_t = long +rbx.platform.typedef.*__qaddr_t = long +rbx.platform.typedef.*__caddr_t = char +rbx.platform.typedef.__intptr_t = long +rbx.platform.typedef.__socklen_t = uint +rbx.platform.typedef.u_char = uchar +rbx.platform.typedef.u_short = ushort +rbx.platform.typedef.u_int = uint +rbx.platform.typedef.u_long = ulong +rbx.platform.typedef.quad_t = long +rbx.platform.typedef.u_quad_t = ulong +rbx.platform.typedef.loff_t = long +rbx.platform.typedef.ino_t = ulong +rbx.platform.typedef.dev_t = ulong +rbx.platform.typedef.gid_t = uint +rbx.platform.typedef.mode_t = uint +rbx.platform.typedef.nlink_t = ulong +rbx.platform.typedef.uid_t = uint +rbx.platform.typedef.off_t = long +rbx.platform.typedef.pid_t = int +rbx.platform.typedef.id_t = uint +rbx.platform.typedef.ssize_t = long +rbx.platform.typedef.daddr_t = int +rbx.platform.typedef.key_t = int +rbx.platform.typedef.clock_t = long +rbx.platform.typedef.time_t = long +rbx.platform.typedef.clockid_t = int +rbx.platform.typedef.timer_t = pointer +rbx.platform.typedef.size_t = ulong +rbx.platform.typedef.ulong = ulong +rbx.platform.typedef.ushort = ushort +rbx.platform.typedef.uint = uint +rbx.platform.typedef.int8_t = char +rbx.platform.typedef.int16_t = short +rbx.platform.typedef.int32_t = int +rbx.platform.typedef.int64_t = long_long +rbx.platform.typedef.u_int8_t = uchar +rbx.platform.typedef.u_int16_t = ushort +rbx.platform.typedef.u_int32_t = uint +rbx.platform.typedef.u_int64_t = ulong_long +rbx.platform.typedef.register_t = long +rbx.platform.typedef.__sig_atomic_t = int +rbx.platform.typedef.suseconds_t = long +rbx.platform.typedef.__fd_mask = long +rbx.platform.typedef.fd_mask = long +rbx.platform.typedef.blksize_t = long +rbx.platform.typedef.blkcnt_t = long +rbx.platform.typedef.fsblkcnt_t = ulong +rbx.platform.typedef.fsfilcnt_t = ulong +rbx.platform.typedef.pthread_t = ulong +rbx.platform.typedef.pthread_key_t = uint +rbx.platform.typedef.pthread_once_t = int +rbx.platform.typedef.socklen_t = uint +rbx.platform.typedef.sa_family_t = ushort +rbx.platform.typedef.rlim_t = ulong +rbx.platform.typedef.__rlimit_resource_t = int +rbx.platform.typedef.__rusage_who_t = int +rbx.platform.typedef.__priority_which_t = int diff --git a/lib/ffi/platform/x86_64-darwin/types.conf b/lib/ffi/platform/x86_64-darwin/types.conf index 0cec3bf..51637ee 100644 --- a/lib/ffi/platform/x86_64-darwin/types.conf +++ b/lib/ffi/platform/x86_64-darwin/types.conf @@ -19,12 +19,12 @@ rbx.platform.typedef.__darwin_socklen_t = uint rbx.platform.typedef.__darwin_ssize_t = long rbx.platform.typedef.__darwin_time_t = long rbx.platform.typedef.int8_t = char -rbx.platform.typedef.u_int8_t = uchar rbx.platform.typedef.int16_t = short -rbx.platform.typedef.u_int16_t = ushort rbx.platform.typedef.int32_t = int -rbx.platform.typedef.u_int32_t = uint rbx.platform.typedef.int64_t = long_long +rbx.platform.typedef.u_int8_t = uchar +rbx.platform.typedef.u_int16_t = ushort +rbx.platform.typedef.u_int32_t = uint rbx.platform.typedef.u_int64_t = ulong_long rbx.platform.typedef.register_t = long_long rbx.platform.typedef.intptr_t = long @@ -35,6 +35,7 @@ rbx.platform.typedef.user_ssize_t = long_long rbx.platform.typedef.user_long_t = long_long rbx.platform.typedef.user_ulong_t = ulong_long rbx.platform.typedef.user_time_t = long_long +rbx.platform.typedef.user_off_t = long_long rbx.platform.typedef.syscall_arg_t = ulong_long rbx.platform.typedef.__darwin_blkcnt_t = long_long rbx.platform.typedef.__darwin_blksize_t = int @@ -50,12 +51,13 @@ rbx.platform.typedef.__darwin_mach_port_t = uint rbx.platform.typedef.__darwin_mode_t = ushort rbx.platform.typedef.__darwin_off_t = long_long rbx.platform.typedef.__darwin_pid_t = int -rbx.platform.typedef.__darwin_pthread_key_t = ulong rbx.platform.typedef.__darwin_sigset_t = uint rbx.platform.typedef.__darwin_suseconds_t = int rbx.platform.typedef.__darwin_uid_t = uint rbx.platform.typedef.__darwin_useconds_t = uint rbx.platform.typedef.__darwin_uuid_t[16] = uchar +rbx.platform.typedef.__darwin_uuid_string_t[37] = char +rbx.platform.typedef.__darwin_pthread_key_t = ulong rbx.platform.typedef.u_char = uchar rbx.platform.typedef.u_short = ushort rbx.platform.typedef.u_int = uint @@ -91,10 +93,34 @@ rbx.platform.typedef.ssize_t = long rbx.platform.typedef.time_t = long rbx.platform.typedef.useconds_t = uint rbx.platform.typedef.suseconds_t = int +rbx.platform.typedef.rsize_t = ulong +rbx.platform.typedef.errno_t = int rbx.platform.typedef.fd_mask = int rbx.platform.typedef.pthread_key_t = ulong rbx.platform.typedef.fsblkcnt_t = uint rbx.platform.typedef.fsfilcnt_t = uint rbx.platform.typedef.sa_family_t = uchar rbx.platform.typedef.socklen_t = uint +rbx.platform.typedef.uint8_t = uchar +rbx.platform.typedef.uint16_t = ushort +rbx.platform.typedef.uint32_t = uint +rbx.platform.typedef.uint64_t = ulong_long +rbx.platform.typedef.int_least8_t = char +rbx.platform.typedef.int_least16_t = short +rbx.platform.typedef.int_least32_t = int +rbx.platform.typedef.int_least64_t = long_long +rbx.platform.typedef.uint_least8_t = uchar +rbx.platform.typedef.uint_least16_t = ushort +rbx.platform.typedef.uint_least32_t = uint +rbx.platform.typedef.uint_least64_t = ulong_long +rbx.platform.typedef.int_fast8_t = char +rbx.platform.typedef.int_fast16_t = short +rbx.platform.typedef.int_fast32_t = int +rbx.platform.typedef.int_fast64_t = long_long +rbx.platform.typedef.uint_fast8_t = uchar +rbx.platform.typedef.uint_fast16_t = ushort +rbx.platform.typedef.uint_fast32_t = uint +rbx.platform.typedef.uint_fast64_t = ulong_long +rbx.platform.typedef.intmax_t = long +rbx.platform.typedef.uintmax_t = ulong rbx.platform.typedef.rlim_t = ulong_long diff --git a/lib/ffi/struct.rb b/lib/ffi/struct.rb index c699e0b..599ee9b 100644 --- a/lib/ffi/struct.rb +++ b/lib/ffi/struct.rb @@ -256,6 +256,12 @@ module FFI # :field2 => :pointer, # :field3 => :string # end + # @example Creating a layout with pointers to functions + # class MyFunctionTable < Struct + # layout :function1, callback([:int, :int], :int), + # :function2, callback([:pointer], :void), + # :field3, :string + # end # @note Creating a layout from a hash +spec+ is supported only for Ruby 1.9. def layout(*spec) #raise RuntimeError, "struct layout already defined for #{self.inspect}" if defined?(@layout) diff --git a/lib/ffi/version.rb b/lib/ffi/version.rb index bf58ed5..89a36ef 100644 --- a/lib/ffi/version.rb +++ b/lib/ffi/version.rb @@ -1,4 +1,4 @@ module FFI - VERSION = '1.9.3' + VERSION = '1.9.8' end diff --git a/libtest/EnumTest.c b/libtest/EnumTest.c index 4c9dda9..4bf8d23 100644 --- a/libtest/EnumTest.c +++ b/libtest/EnumTest.c @@ -3,6 +3,7 @@ * * For licensing, see LICENSE.SPECS */ +#include <stdint.h> int test_untagged_enum(int val) { return val; @@ -12,6 +13,22 @@ int test_untagged_typedef_enum(int val) { return val; } +uint8_t test_untagged_nonint_enum(uint8_t val) { + return val; +} + +uint16_t test_tagged_nonint_enum1(uint16_t val) { + return val; +} + +uint32_t test_tagged_nonint_enum2(uint32_t val) { + return val; +} + +uint64_t test_tagged_nonint_enum3(uint64_t val) { + return val; +} + typedef enum {c1, c2, c3, c4} enum_type1; enum_type1 test_tagged_typedef_enum1(enum_type1 val) { return val; diff --git a/spec/ffi/async_callback_spec.rb b/spec/ffi/async_callback_spec.rb index 8d5d0bd..87950cc 100644 --- a/spec/ffi/async_callback_spec.rb +++ b/spec/ffi/async_callback_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' describe "async callback" do module LibTest @@ -21,8 +20,8 @@ describe "async callback" do called = false cb = Proc.new {|i| v = i; called = true } LibTest.testAsyncCallback(cb, 0x7fffffff) - called.should be_true - v.should == 0x7fffffff + expect(called).to be true + expect(v).to eq(0x7fffffff) end it "called a second time" do @@ -30,7 +29,7 @@ describe "async callback" do called = false cb = Proc.new {|i| v = i; called = true } LibTest.testAsyncCallback(cb, 0x7fffffff) - called.should be_true - v.should == 0x7fffffff + expect(called).to be true + expect(v).to eq(0x7fffffff) end end diff --git a/spec/ffi/bool_spec.rb b/spec/ffi/bool_spec.rb index a932ecd..6cd1d6f 100644 --- a/spec/ffi/bool_spec.rb +++ b/spec/ffi/bool_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' describe "Function with primitive boolean arguments and return values" do module LibTest @@ -15,17 +14,19 @@ describe "Function with primitive boolean arguments and return values" do attach_function :bool_return_val, [ :bool ], :bool attach_function :bool_reverse_val, [ :bool ], :bool end + it "bools" do - LibTest.bool_return_true.should == true - LibTest.bool_return_false.should == false + expect(LibTest.bool_return_true).to be true + expect(LibTest.bool_return_false).to be false - LibTest.bool_return_val(true).should == true - LibTest.bool_return_val(false).should == false + expect(LibTest.bool_return_val(true)).to be true + expect(LibTest.bool_return_val(false)).to be false - LibTest.bool_reverse_val(true).should == false - LibTest.bool_reverse_val(false).should == true + expect(LibTest.bool_reverse_val(true)).to be false + expect(LibTest.bool_reverse_val(false)).to be true end + it "raise error on invalid types" do - lambda { LibTest.bool_return_val(nil) }.should raise_error(::TypeError) + expect { LibTest.bool_return_val(nil) }.to raise_error(::TypeError) end end diff --git a/spec/ffi/buffer_spec.rb b/spec/ffi/buffer_spec.rb index 2c9791a..5f22a62 100644 --- a/spec/ffi/buffer_spec.rb +++ b/spec/ffi/buffer_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' describe "Buffer#total" do [1,2,3].each do |i| @@ -12,14 +11,17 @@ describe "Buffer#total" do :uint => 4, :long => FFI::Type::LONG.size, :ulong => FFI::Type::ULONG.size, :long_long => 8, :ulong_long => 8, :float => 4, :double => 8 }.each_pair do |t, s| + it "Buffer.alloc_in(#{t}, #{i}).total == #{i * s}" do - FFI::Buffer.alloc_in(t, i).total.should == i * s + expect(FFI::Buffer.alloc_in(t, i).total).to eq(i * s) end + it "Buffer.alloc_out(#{t}, #{i}).total == #{i * s}" do - FFI::Buffer.alloc_out(t, i).total.should == i * s + expect(FFI::Buffer.alloc_out(t, i).total).to eq(i * s) end + it "Buffer.alloc_inout(#{t}, #{i}).total == #{i * s}" do - FFI::Buffer.alloc_inout(t, i).total.should == i * s + expect(FFI::Buffer.alloc_inout(t, i).total).to eq(i * s) end end end @@ -30,214 +32,239 @@ describe "Buffer#put_char" do (0..127).each do |i| (0..bufsize-1).each do |offset| it "put_char(#{offset}, #{i}).get_char(#{offset}) == #{i}" do - FFI::Buffer.alloc_in(bufsize).put_char(offset, i).get_char(offset).should == i + expect(FFI::Buffer.alloc_in(bufsize).put_char(offset, i).get_char(offset)).to eq(i) end end end end + describe "Buffer#put_uchar" do bufsize = 4 (0..255).each do |i| (0..bufsize-1).each do |offset| it "Buffer.put_uchar(#{offset}, #{i}).get_uchar(#{offset}) == #{i}" do - FFI::Buffer.alloc_in(bufsize).put_uchar(offset, i).get_uchar(offset).should == i + expect(FFI::Buffer.alloc_in(bufsize).put_uchar(offset, i).get_uchar(offset)).to eq(i) end end end end + describe "Buffer#put_short" do bufsize = 4 [0, 1, 128, 32767].each do |i| (0..bufsize-2).each do |offset| it "put_short(#{offset}, #{i}).get_short(#{offset}) == #{i}" do - FFI::Buffer.alloc_in(bufsize).put_short(offset, i).get_short(offset).should == i + expect(FFI::Buffer.alloc_in(bufsize).put_short(offset, i).get_short(offset)).to eq(i) end end end end + describe "Buffer#put_ushort" do bufsize = 4 [ 0, 1, 128, 32767, 65535, 0xfee1, 0xdead, 0xbeef, 0xcafe ].each do |i| (0..bufsize-2).each do |offset| it "put_ushort(#{offset}, #{i}).get_ushort(#{offset}) == #{i}" do - FFI::Buffer.alloc_in(bufsize).put_ushort(offset, i).get_ushort(offset).should == i + expect(FFI::Buffer.alloc_in(bufsize).put_ushort(offset, i).get_ushort(offset)).to eq(i) end end end end + describe "Buffer#put_int" do bufsize = 8 [0, 1, 128, 32767, 0x7ffffff ].each do |i| (0..bufsize-4).each do |offset| it "put_int(#{offset}, #{i}).get_int(#{offset}) == #{i}" do - FFI::Buffer.alloc_in(bufsize).put_int(offset, i).get_int(offset).should == i + expect(FFI::Buffer.alloc_in(bufsize).put_int(offset, i).get_int(offset)).to eq(i) end end end end + describe "Buffer#put_uint" do bufsize = 8 [ 0, 1, 128, 32767, 65535, 0xfee1dead, 0xcafebabe, 0xffffffff ].each do |i| (0..bufsize-4).each do |offset| it "put_uint(#{offset}, #{i}).get_uint(#{offset}) == #{i}" do - FFI::Buffer.alloc_in(bufsize).put_uint(offset, i).get_uint(offset).should == i + expect(FFI::Buffer.alloc_in(bufsize).put_uint(offset, i).get_uint(offset)).to eq(i) end end end end + describe "Buffer#put_long" do bufsize = 16 [0, 1, 128, 32767, 0x7ffffff ].each do |i| (0..bufsize-FFI::Type::LONG.size).each do |offset| it "put_long(#{offset}, #{i}).get_long(#{offset}) == #{i}" do - FFI::Buffer.alloc_in(bufsize).put_long(offset, i).get_long(offset).should == i + expect(FFI::Buffer.alloc_in(bufsize).put_long(offset, i).get_long(offset)).to eq(i) end end end end + describe "Buffer#put_ulong" do bufsize = 16 [ 0, 1, 128, 32767, 65535, 0xfee1dead, 0xcafebabe, 0xffffffff ].each do |i| (0..bufsize-FFI::Type::LONG.size).each do |offset| it "put_ulong(#{offset}, #{i}).get_ulong(#{offset}) == #{i}" do - FFI::Buffer.alloc_in(bufsize).put_ulong(offset, i).get_ulong(offset).should == i + expect(FFI::Buffer.alloc_in(bufsize).put_ulong(offset, i).get_ulong(offset)).to eq(i) end end end end + describe "Buffer#put_long_long" do bufsize = 16 [0, 1, 128, 32767, 0x7ffffffffffffff ].each do |i| (0..bufsize-8).each do |offset| it "put_long_long(#{offset}, #{i}).get_long_long(#{offset}) == #{i}" do - FFI::Buffer.alloc_in(bufsize).put_long_long(offset, i).get_long_long(offset).should == i + expect(FFI::Buffer.alloc_in(bufsize).put_long_long(offset, i).get_long_long(offset)).to eq(i) end end end end + describe "Buffer#put_ulong_long" do bufsize = 16 [ 0, 1, 128, 32767, 65535, 0xdeadcafebabe, 0x7fffffffffffffff ].each do |i| (0..bufsize-8).each do |offset| it "put_ulong_long(#{offset}, #{i}).get_ulong_long(#{offset}) == #{i}" do - FFI::Buffer.alloc_in(bufsize).put_ulong_long(offset, i).get_ulong_long(offset).should == i + expect(FFI::Buffer.alloc_in(bufsize).put_ulong_long(offset, i).get_ulong_long(offset)).to eq(i) end end end end + describe "Reading/Writing binary strings" do it "Buffer#put_bytes" do str = "hello\0world" buf = FFI::Buffer.new 1024 buf.put_bytes(0, str); s2 = buf.get_bytes(0, 11); - s2.should == str + expect(s2).to eq(str) end + it "Buffer#put_bytes with index and length" do str = "hello\0world" buf = FFI::Buffer.new 1024 buf.put_bytes(0, str, 5, 6); s2 = buf.get_bytes(0, 6); - s2.should == str[5..-1] + expect(s2).to eq(str[5..-1]) end + it "Buffer#put_bytes with only index" do str = "hello\0world" buf = FFI::Buffer.new 1024 buf.put_bytes(0, str, 5); s2 = buf.get_bytes(0, 6); - s2.should == str[5..-1] + expect(s2).to eq(str[5..-1]) end + it "Buffer#put_bytes with index > str.length" do str = "hello\0world" buf = FFI::Buffer.new 1024 - lambda { buf.put_bytes(0, str, 12); }.should raise_error + expect { buf.put_bytes(0, str, 12); }.to raise_error end + it "Buffer#put_bytes with length > str.length" do str = "hello\0world" buf = FFI::Buffer.new 1024 - lambda { buf.put_bytes(0, str, 0, 12); }.should raise_error + expect { buf.put_bytes(0, str, 0, 12); }.to raise_error end - it "Buffer#put_bytes with negative index" do + + it "Buffer#put_bytes with negative index" do str = "hello\0world" buf = FFI::Buffer.new 1024 - lambda { buf.put_bytes(0, str, -1, 12); }.should raise_error - end + expect { buf.put_bytes(0, str, -1, 12); }.to raise_error + end it "Buffer#write_bytes" do str = "hello\0world" buf = FFI::Buffer.new 1024 buf.write_bytes(str) s2 = buf.get_bytes(0, 11) - s2.should == str + expect(s2).to eq(str) end + it "Buffer#write_bytes with index and length" do str = "hello\0world" buf = FFI::Buffer.new 1024 buf.write_bytes(str, 5, 6) s2 = buf.get_bytes(0, 6) - s2.should == str[5..-1] + expect(s2).to eq(str[5..-1]) end + it "Buffer#write_bytes with only index" do str = "hello\0world" buf = FFI::Buffer.new 1024 buf.write_bytes(str, 5) s2 = buf.get_bytes(0, 6) - s2.should == str[5..-1] + expect(s2).to eq(str[5..-1]) end + it "Buffer#write_bytes with index > str.length" do str = "hello\0world" buf = FFI::Buffer.new 1024 - lambda { buf.write_bytes(str, 12) }.should raise_error + expect { buf.write_bytes(str, 12) }.to raise_error end + it "Buffer#put_bytes with length > str.length" do str = "hello\0world" buf = FFI::Buffer.new 1024 - lambda { buf.put_bytes(0, str, 0, 12) }.should raise_error + expect { buf.put_bytes(0, str, 0, 12) }.to raise_error end - it "Buffer#write_bytes with negative index" do + + it "Buffer#write_bytes with negative index" do str = "hello\0world" buf = FFI::Buffer.new 1024 - lambda { buf.write_bytes(str, -1, 12) }.should raise_error + expect { buf.write_bytes(str, -1, 12) }.to raise_error end end + describe "Reading/Writing ascii strings" do it "Buffer#put_string with string containing zero byte" do str = "hello\0world" buf = FFI::Buffer.new 1024 buf.put_string(0, str); s2 = buf.get_bytes(0, 11); - s2.should == str + expect(s2).to eq(str) end + it "Buffer#get_string with string containing zero byte" do str = "hello\0world" buf = FFI::Buffer.new 1024 buf.put_bytes(0, str); s2 = buf.get_string(0, 11); - s2.should == "hello" + expect(s2).to eq("hello") end + it "Buffer#put_string without length should NUL terminate" do str = "hello" buf = FFI::Buffer.new 1024 buf.put_string(0, str); s2 = buf.get_bytes(0, 6); - s2.should == "hello\0" + expect(s2).to eq("hello\0") end end + describe "Buffer#put_pointer" do it "put_pointer(0, p).get_pointer(0) == p" do p = FFI::MemoryPointer.new :ulong_long p.put_uint(0, 0xdeadbeef) buf = FFI::Buffer.alloc_inout 8 p2 = buf.put_pointer(0, p).get_pointer(0) - p2.should_not be_nil - p2.should == p - p2.get_uint(0).should == 0xdeadbeef + expect(p2).not_to be_nil + expect(p2).to eq(p) + expect(p2.get_uint(0)).to eq(0xdeadbeef) end end + describe "Buffer#size" do it "should return size" do buf = FFI::Buffer.new 14 - buf.size.should == 14 + expect(buf.size).to eq(14) end end @@ -247,6 +274,6 @@ describe "Buffer#initialize" do FFI::Buffer.new(:pointer) do |ptr| block_executed = true end - block_executed.should be_true + expect(block_executed).to be true end end diff --git a/spec/ffi/callback_spec.rb b/spec/ffi/callback_spec.rb index 6e60d74..bc9b55a 100644 --- a/spec/ffi/callback_spec.rb +++ b/spec/ffi/callback_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' describe "Callback" do # module LibC @@ -85,161 +84,197 @@ describe "Callback" do attach_function :testOptionalCallbackCrV, :testOptionalClosureBrV, [ :cbCrV, :char ], :void end + it "returning :char (0)" do - LibTest.testCallbackVrS8 { 0 }.should == 0 + expect(LibTest.testCallbackVrS8 { 0 }).to eq(0) end + it "returning :char (127)" do - LibTest.testCallbackVrS8 { 127 }.should == 127 + expect(LibTest.testCallbackVrS8 { 127 }).to eq(127) end + it "returning :char (-128)" do - LibTest.testCallbackVrS8 { -128 }.should == -128 + expect(LibTest.testCallbackVrS8 { -128 }).to eq(-128) end # test wrap around it "returning :char (128)" do - LibTest.testCallbackVrS8 { 128 }.should == -128 + expect(LibTest.testCallbackVrS8 { 128 }).to eq(-128) end + it "returning :char (255)" do - LibTest.testCallbackVrS8 { 0xff }.should == -1 + expect(LibTest.testCallbackVrS8 { 0xff }).to eq(-1) end + it "returning :uchar (0)" do - LibTest.testCallbackVrU8 { 0 }.should == 0 + expect(LibTest.testCallbackVrU8 { 0 }).to eq(0) end + it "returning :uchar (0xff)" do - LibTest.testCallbackVrU8 { 0xff }.should == 0xff + expect(LibTest.testCallbackVrU8 { 0xff }).to eq(0xff) end + it "returning :uchar (-1)" do - LibTest.testCallbackVrU8 { -1 }.should == 0xff + expect(LibTest.testCallbackVrU8 { -1 }).to eq(0xff) end + it "returning :uchar (128)" do - LibTest.testCallbackVrU8 { 128 }.should == 128 + expect(LibTest.testCallbackVrU8 { 128 }).to eq(128) end + it "returning :uchar (-128)" do - LibTest.testCallbackVrU8 { -128 }.should == 128 + expect(LibTest.testCallbackVrU8 { -128 }).to eq(128) end + it "returning :short (0)" do - LibTest.testCallbackVrS16 { 0 }.should == 0 + expect(LibTest.testCallbackVrS16 { 0 }).to eq(0) end + it "returning :short (0x7fff)" do - LibTest.testCallbackVrS16 { 0x7fff }.should == 0x7fff + expect(LibTest.testCallbackVrS16 { 0x7fff }).to eq(0x7fff) end # test wrap around it "returning :short (0x8000)" do - LibTest.testCallbackVrS16 { 0x8000 }.should == -0x8000 + expect(LibTest.testCallbackVrS16 { 0x8000 }).to eq(-0x8000) end + it "returning :short (0xffff)" do - LibTest.testCallbackVrS16 { 0xffff }.should == -1 + expect(LibTest.testCallbackVrS16 { 0xffff }).to eq(-1) end + it "returning :ushort (0)" do - LibTest.testCallbackVrU16 { 0 }.should == 0 + expect(LibTest.testCallbackVrU16 { 0 }).to eq(0) end + it "returning :ushort (0x7fff)" do - LibTest.testCallbackVrU16 { 0x7fff }.should == 0x7fff + expect(LibTest.testCallbackVrU16 { 0x7fff }).to eq(0x7fff) end + it "returning :ushort (0x8000)" do - LibTest.testCallbackVrU16 { 0x8000 }.should == 0x8000 + expect(LibTest.testCallbackVrU16 { 0x8000 }).to eq(0x8000) end + it "returning :ushort (0xffff)" do - LibTest.testCallbackVrU16 { 0xffff }.should == 0xffff + expect(LibTest.testCallbackVrU16 { 0xffff }).to eq(0xffff) end + it "returning :ushort (-1)" do - LibTest.testCallbackVrU16 { -1 }.should == 0xffff + expect(LibTest.testCallbackVrU16 { -1 }).to eq(0xffff) end + it "returning :int (0)" do - LibTest.testCallbackVrS32 { 0 }.should == 0 + expect(LibTest.testCallbackVrS32 { 0 }).to eq(0) end + it "returning :int (0x7fffffff)" do - LibTest.testCallbackVrS32 { 0x7fffffff }.should == 0x7fffffff + expect(LibTest.testCallbackVrS32 { 0x7fffffff }).to eq(0x7fffffff) end # test wrap around it "returning :int (-0x80000000)" do - LibTest.testCallbackVrS32 { -0x80000000 }.should == -0x80000000 + expect(LibTest.testCallbackVrS32 { -0x80000000 }).to eq(-0x80000000) end + it "returning :int (-1)" do - LibTest.testCallbackVrS32 { -1 }.should == -1 + expect(LibTest.testCallbackVrS32 { -1 }).to eq(-1) end + it "returning :uint (0)" do - LibTest.testCallbackVrU32 { 0 }.should == 0 + expect(LibTest.testCallbackVrU32 { 0 }).to eq(0) end + it "returning :uint (0x7fffffff)" do - LibTest.testCallbackVrU32 { 0x7fffffff }.should == 0x7fffffff + expect(LibTest.testCallbackVrU32 { 0x7fffffff }).to eq(0x7fffffff) end # test wrap around it "returning :uint (0x80000000)" do - LibTest.testCallbackVrU32 { 0x80000000 }.should == 0x80000000 + expect(LibTest.testCallbackVrU32 { 0x80000000 }).to eq(0x80000000) end + it "returning :uint (0xffffffff)" do - LibTest.testCallbackVrU32 { 0xffffffff }.should == 0xffffffff + expect(LibTest.testCallbackVrU32 { 0xffffffff }).to eq(0xffffffff) end + it "returning :uint (-1)" do - LibTest.testCallbackVrU32 { -1 }.should == 0xffffffff + expect(LibTest.testCallbackVrU32 { -1 }).to eq(0xffffffff) end + it "returning :long (0)" do - LibTest.testCallbackVrL { 0 }.should == 0 + expect(LibTest.testCallbackVrL { 0 }).to eq(0) end + it "returning :long (0x7fffffff)" do - LibTest.testCallbackVrL { 0x7fffffff }.should == 0x7fffffff + expect(LibTest.testCallbackVrL { 0x7fffffff }).to eq(0x7fffffff) end # test wrap around it "returning :long (-0x80000000)" do - LibTest.testCallbackVrL { -0x80000000 }.should == -0x80000000 + expect(LibTest.testCallbackVrL { -0x80000000 }).to eq(-0x80000000) end + it "returning :long (-1)" do - LibTest.testCallbackVrL { -1 }.should == -1 + expect(LibTest.testCallbackVrL { -1 }).to eq(-1) end + it "returning :ulong (0)" do - LibTest.testCallbackVrUL { 0 }.should == 0 + expect(LibTest.testCallbackVrUL { 0 }).to eq(0) end + it "returning :ulong (0x7fffffff)" do - LibTest.testCallbackVrUL { 0x7fffffff }.should == 0x7fffffff + expect(LibTest.testCallbackVrUL { 0x7fffffff }).to eq(0x7fffffff) end # test wrap around it "returning :ulong (0x80000000)" do - LibTest.testCallbackVrUL { 0x80000000 }.should == 0x80000000 + expect(LibTest.testCallbackVrUL { 0x80000000 }).to eq(0x80000000) end + it "returning :ulong (0xffffffff)" do - LibTest.testCallbackVrUL { 0xffffffff }.should == 0xffffffff + expect(LibTest.testCallbackVrUL { 0xffffffff }).to eq(0xffffffff) end + it "Callback returning :ulong (-1)" do if FFI::Platform::LONG_SIZE == 32 - LibTest.testCallbackVrUL { -1 }.should == 0xffffffff + expect(LibTest.testCallbackVrUL { -1 }).to eq(0xffffffff) else - LibTest.testCallbackVrUL { -1 }.should == 0xffffffffffffffff + expect(LibTest.testCallbackVrUL { -1 }).to eq(0xffffffffffffffff) end end + it "returning :long_long (0)" do - LibTest.testCallbackVrS64 { 0 }.should == 0 + expect(LibTest.testCallbackVrS64 { 0 }).to eq(0) end + it "returning :long_long (0x7fffffffffffffff)" do - LibTest.testCallbackVrS64 { 0x7fffffffffffffff }.should == 0x7fffffffffffffff + expect(LibTest.testCallbackVrS64 { 0x7fffffffffffffff }).to eq(0x7fffffffffffffff) end # test wrap around it "returning :long_long (-0x8000000000000000)" do - LibTest.testCallbackVrS64 { -0x8000000000000000 }.should == -0x8000000000000000 + expect(LibTest.testCallbackVrS64 { -0x8000000000000000 }).to eq(-0x8000000000000000) end + it "returning :long_long (-1)" do - LibTest.testCallbackVrS64 { -1 }.should == -1 + expect(LibTest.testCallbackVrS64 { -1 }).to eq(-1) end + it "returning bool" do - LibTest.testCallbackVrZ { true }.should be_true + expect(LibTest.testCallbackVrZ { true }).to be true end + it "returning :pointer (nil)" do - LibTest.testCallbackVrP { nil }.null?.should be_true + expect(LibTest.testCallbackVrP { nil }).to be_null end + it "returning :pointer (MemoryPointer)" do p = FFI::MemoryPointer.new :long - LibTest.testCallbackVrP { p }.should == p + expect(LibTest.testCallbackVrP { p }).to eq(p) end - it "returning struct by value" do s = LibTest::S8F32S32.new s[:s8] = 0x12 s[:s32] = 0x1eefbeef s[:f32] = 1.234567 ret = LibTest.testCallbackVrT { s } - ret[:s8].should == s[:s8] - ret[:f32].should == s[:f32] - ret[:s32].should == s[:s32] + expect(ret[:s8]).to eq(s[:s8]) + expect(ret[:f32]).to eq(s[:f32]) + expect(ret[:s32]).to eq(s[:s32]) end @@ -249,11 +284,13 @@ describe "Callback" do s[:s32] = 0x1eefbeef s[:f32] = 1.234567 s2 = LibTest::S8F32S32.new + LibTest.testCallbackTrV(s) do |struct| s2[:s8] = struct[:s8] 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 @@ -263,12 +300,12 @@ describe "Callback" do it "global variable" do proc = Proc.new { 0x1e } LibTest.cbVrS8 = proc - LibTest.testGVarCallbackVrS8(LibTest.pVrS8).should == 0x1e + expect(LibTest.testGVarCallbackVrS8(LibTest.pVrS8)).to eq(0x1e) end 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).should be_nil + expect(LibTest.testOptionalCallbackCrV(nil, 13)).to be_nil end end @@ -279,20 +316,20 @@ describe "Callback" do ffi_lib TestLibrary::PATH attach_function :testAnonymousCallbackVrS8, :testClosureVrB, [ callback([ ], :char) ], :char end - LibTest.testAnonymousCallbackVrS8 { 0 }.should == 0 + expect(LibTest.testAnonymousCallbackVrS8 { 0 }).to eq(0) end end describe "as return value" do it "should not blow up when a callback is defined that returns a callback" do - module LibTest + expect(module LibTest extend FFI::Library ffi_lib TestLibrary::PATH 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.should be_an_instance_of FFI::Function + end).to be_an_instance_of FFI::Function end it "should return a callback" do @@ -317,9 +354,9 @@ describe "Callback" do end val = LibTest.testReturnsCallback(lookup_proc, 0x1234) - val.should == 0x1234 * 2 - lookup_proc_called.should be_true - return_proc_called.should be_true + expect(val).to eq(0x1234 * 2) + expect(lookup_proc_called).to be true + expect(return_proc_called).to be true end it "should return a method callback" do @@ -339,17 +376,17 @@ describe "Callback" do end end - LibTest.testReturnsCallback_2(MethodCallback.method(:lookup), 0x1234).should == 0x2468 + expect(LibTest.testReturnsCallback_2(MethodCallback.method(:lookup), 0x1234)).to eq(0x2468) end it 'should not blow up when a callback takes a callback as argument' do - module LibTest + expect(module LibTest extend FFI::Library ffi_lib TestLibrary::PATH 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.should be_an_instance_of FFI::Function + end).to be_an_instance_of FFI::Function end it 'should be able to use the callback argument' do module LibTest @@ -360,7 +397,7 @@ describe "Callback" do attach_function :testCallbackAsArgument, :testArgumentClosure, [ :cb_with_cb_argument, :cb_argument, :int ], :int end callback_arg_called = false - callback_with_callback_arg_called = false + callback_with_callback_arg_called = false callback_arg = Proc.new do |val| callback_arg_called = true val * 2 @@ -370,9 +407,9 @@ describe "Callback" do cb.call(val) end val = LibTest.testCallbackAsArgument(callback_with_callback_arg, callback_arg, 0xff1) - val.should == 0xff1 * 2 - callback_arg_called.should be_true - callback_with_callback_arg_called.should be_true + expect(val).to eq(0xff1 * 2) + expect(callback_arg_called).to be true + expect(callback_with_callback_arg_called).to be true end it 'function returns callable object' do module LibTest @@ -382,7 +419,7 @@ describe "Callback" do attach_function :testReturnsFunctionPointer, [ ], :funcptr end f = LibTest.testReturnsFunctionPointer - f.call(3).should == 6 + expect(f.call(3)).to eq(6) end end @@ -433,239 +470,281 @@ describe "Callback with " do attach_function :testCallbackPrV, :testClosurePrV, [ :cbPrV, :pointer], :void attach_function :testCallbackYrV, :testClosurePrV, [ :cbYrV, S8F32S32.in ], :void end + it "function with Callback plus another arg should raise error if no arg given" do - lambda { LibTest.testCallbackCrV { |*a| }}.should raise_error + expect { LibTest.testCallbackCrV { |*a| }}.to raise_error end + it ":char (0) argument" do v = 0xdeadbeef LibTest.testCallbackCrV(0) { |i| v = i } - v.should == 0 + expect(v).to eq(0) end + it ":char (127) argument" do v = 0xdeadbeef LibTest.testCallbackCrV(127) { |i| v = i } - v.should == 127 + expect(v).to eq(127) end + it ":char (-128) argument" do v = 0xdeadbeef LibTest.testCallbackCrV(-128) { |i| v = i } - v.should == -128 + expect(v).to eq(-128) end + it ":char (-1) argument" do v = 0xdeadbeef LibTest.testCallbackCrV(-1) { |i| v = i } - v.should == -1 + expect(v).to eq(-1) end + it ":uchar (0) argument" do v = 0xdeadbeef LibTest.testCallbackU8rV(0) { |i| v = i } - v.should == 0 + expect(v).to eq(0) end + it ":uchar (127) argument" do v = 0xdeadbeef LibTest.testCallbackU8rV(127) { |i| v = i } - v.should == 127 + expect(v).to eq(127) end + it ":uchar (128) argument" do v = 0xdeadbeef LibTest.testCallbackU8rV(128) { |i| v = i } - v.should == 128 + expect(v).to eq(128) end + it ":uchar (255) argument" do v = 0xdeadbeef LibTest.testCallbackU8rV(255) { |i| v = i } - v.should == 255 + expect(v).to eq(255) end it ":short (0) argument" do v = 0xdeadbeef LibTest.testCallbackSrV(0) { |i| v = i } - v.should == 0 + expect(v).to eq(0) end + it ":short (0x7fff) argument" do v = 0xdeadbeef LibTest.testCallbackSrV(0x7fff) { |i| v = i } - v.should == 0x7fff + expect(v).to eq(0x7fff) end + it ":short (-0x8000) argument" do v = 0xdeadbeef LibTest.testCallbackSrV(-0x8000) { |i| v = i } - v.should == -0x8000 + expect(v).to eq(-0x8000) end + it ":short (-1) argument" do v = 0xdeadbeef LibTest.testCallbackSrV(-1) { |i| v = i } - v.should == -1 + expect(v).to eq(-1) end + it ":ushort (0) argument" do v = 0xdeadbeef LibTest.testCallbackU16rV(0) { |i| v = i } - v.should == 0 + expect(v).to eq(0) end + it ":ushort (0x7fff) argument" do v = 0xdeadbeef LibTest.testCallbackU16rV(0x7fff) { |i| v = i } - v.should == 0x7fff + expect(v).to eq(0x7fff) end + it ":ushort (0x8000) argument" do v = 0xdeadbeef LibTest.testCallbackU16rV(0x8000) { |i| v = i } - v.should == 0x8000 + expect(v).to eq(0x8000) end + it ":ushort (0xffff) argument" do v = 0xdeadbeef LibTest.testCallbackU16rV(0xffff) { |i| v = i } - v.should == 0xffff + expect(v).to eq(0xffff) end + it ":bool (true) argument" do v = false LibTest.testCallbackZrV(true) { |i| v = i } - v.should be_true + expect(v).to be true end + it ":int (0) argument" do v = 0xdeadbeef LibTest.testCallbackIrV(0) { |i| v = i } - v.should == 0 + expect(v).to eq(0) end + it ":int (0x7fffffff) argument" do v = 0xdeadbeef LibTest.testCallbackIrV(0x7fffffff) { |i| v = i } - v.should == 0x7fffffff + expect(v).to eq(0x7fffffff) end + it ":int (-0x80000000) argument" do v = 0xdeadbeef LibTest.testCallbackIrV(-0x80000000) { |i| v = i } - v.should == -0x80000000 + expect(v).to eq(-0x80000000) end + it ":int (-1) argument" do v = 0xdeadbeef LibTest.testCallbackIrV(-1) { |i| v = i } - v.should == -1 + expect(v).to eq(-1) end + it ":uint (0) argument" do v = 0xdeadbeef LibTest.testCallbackU32rV(0) { |i| v = i } - v.should == 0 + expect(v).to eq(0) end + it ":uint (0x7fffffff) argument" do v = 0xdeadbeef LibTest.testCallbackU32rV(0x7fffffff) { |i| v = i } - v.should == 0x7fffffff + expect(v).to eq(0x7fffffff) end + it ":uint (0x80000000) argument" do v = 0xdeadbeef LibTest.testCallbackU32rV(0x80000000) { |i| v = i } - v.should == 0x80000000 + expect(v).to eq(0x80000000) end + it ":uint (0xffffffff) argument" do v = 0xdeadbeef LibTest.testCallbackU32rV(0xffffffff) { |i| v = i } - v.should == 0xffffffff + expect(v).to eq(0xffffffff) end + it ":long (0) argument" do v = 0xdeadbeef LibTest.testCallbackLrV(0) { |i| v = i } - v.should == 0 + expect(v).to eq(0) end + it ":long (0x7fffffff) argument" do v = 0xdeadbeef LibTest.testCallbackLrV(0x7fffffff) { |i| v = i } - v.should == 0x7fffffff + expect(v).to eq(0x7fffffff) end + it ":long (-0x80000000) argument" do v = 0xdeadbeef LibTest.testCallbackLrV(-0x80000000) { |i| v = i } - v.should == -0x80000000 + expect(v).to eq(-0x80000000) end + it ":long (-1) argument" do v = 0xdeadbeef LibTest.testCallbackLrV(-1) { |i| v = i } - v.should == -1 + expect(v).to eq(-1) end + it ":ulong (0) argument" do v = 0xdeadbeef LibTest.testCallbackULrV(0) { |i| v = i } - v.should == 0 + expect(v).to eq(0) end + it ":ulong (0x7fffffff) argument" do v = 0xdeadbeef LibTest.testCallbackULrV(0x7fffffff) { |i| v = i } - v.should == 0x7fffffff + expect(v).to eq(0x7fffffff) end + it ":ulong (0x80000000) argument" do v = 0xdeadbeef LibTest.testCallbackULrV(0x80000000) { |i| v = i } - v.should == 0x80000000 + expect(v).to eq(0x80000000) end + it ":ulong (0xffffffff) argument" do v = 0xdeadbeef LibTest.testCallbackULrV(0xffffffff) { |i| v = i } - v.should == 0xffffffff + expect(v).to eq(0xffffffff) end + it ":long_long (0) argument" do v = 0xdeadbeef LibTest.testCallbackLLrV(0) { |i| v = i } - v.should == 0 + expect(v).to eq(0) end + it ":long_long (0x7fffffffffffffff) argument" do v = 0xdeadbeef LibTest.testCallbackLLrV(0x7fffffffffffffff) { |i| v = i } - v.should == 0x7fffffffffffffff + expect(v).to eq(0x7fffffffffffffff) end + it ":long_long (-0x8000000000000000) argument" do v = 0xdeadbeef LibTest.testCallbackLLrV(-0x8000000000000000) { |i| v = i } - v.should == -0x8000000000000000 + expect(v).to eq(-0x8000000000000000) end + it ":long_long (-1) argument" do v = 0xdeadbeef LibTest.testCallbackLLrV(-1) { |i| v = i } - v.should == -1 + expect(v).to eq(-1) end + it ":string argument" do v = nil LibTest.testCallbackArV("Hello, World") { |i| v = i } - v.should == "Hello, World" + expect(v).to eq("Hello, World") end + it ":string (nil) argument" do v = "Hello, World" LibTest.testCallbackArV(nil) { |i| v = i } - v.should be_nil + expect(v).to be_nil end + it ":pointer argument" do v = nil magic = FFI::Pointer.new(0xdeadbeef) LibTest.testCallbackPrV(magic) { |i| v = i } - v.should == magic + expect(v).to eq(magic) end + it ":pointer (nil) argument" do v = "Hello, World" LibTest.testCallbackPrV(nil) { |i| v = i } - v.should == FFI::Pointer::NULL + expect(v).to eq(FFI::Pointer::NULL) end + it "struct by reference argument" do v = nil magic = LibTest::S8F32S32.new LibTest.testCallbackYrV(magic) { |i| v = i } - v.class.should == magic.class - v.pointer.should == magic.pointer + expect(v.class).to eq(magic.class) + expect(v.pointer).to eq(magic.pointer) end it "struct by reference argument with nil value" do v = LibTest::S8F32S32.new LibTest.testCallbackYrV(nil) { |i| v = i } - v.is_a?(FFI::Struct).should be_true - v.pointer.should == FFI::Pointer::NULL + expect(v.is_a?(FFI::Struct)).to be true + expect(v.pointer).to eq(FFI::Pointer::NULL) end it "varargs parameters are rejected" do - lambda { + expect { Module.new do extend FFI::Library ffi_lib TestLibrary::PATH callback :cbVrL, [ :varargs ], :long end - }.should raise_error(ArgumentError) + }.to raise_error(ArgumentError) end # @@ -687,8 +766,8 @@ describe "Callback with " do po = FFI::MemoryPointer.new :long pr = proc{|a,i| v = a,i; i } res = LibTestStdcall.testCallbackStdcall(po, pr, 0x7fffffff) - v.should == [po, 0x7fffffff] - res.should be_true + expect(v).to eq([po, 0x7fffffff]) + expect(res).to be true end end end diff --git a/spec/ffi/custom_param_type.rb b/spec/ffi/custom_param_type.rb index 4c3f73d..7d9216b 100644 --- a/spec/ffi/custom_param_type.rb +++ b/spec/ffi/custom_param_type.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' describe "functions with custom parameter types" do before :each do @@ -33,5 +32,6 @@ describe "functions with custom parameter types" do def self.to_native_called?; @to_native_called; end end + # FIXME add tests end end diff --git a/spec/ffi/custom_type_spec.rb b/spec/ffi/custom_type_spec.rb index 02313eb..d9ce2c1 100644 --- a/spec/ffi/custom_type_spec.rb +++ b/spec/ffi/custom_type_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' describe "functions with custom types" do class Custom_enum @@ -32,13 +31,13 @@ describe "functions with custom types" do end it "can attach with custom return type" do - lambda do + expect do Module.new do extend FFI::Library ffi_lib TestLibrary::PATH attach_function :ret_s32, [ :int ], Custom_enum end - end.should_not raise_error + end.not_to raise_error end it "should return object of correct type" do @@ -50,7 +49,7 @@ describe "functions with custom types" do attach_function :ret_s32, [ :int ], Custom_enum end - m.ret_s32(1).is_a?(Symbol).should be_true + expect(m.ret_s32(1).is_a?(Symbol)).to be true end it "from_native should be called for result" do @@ -60,7 +59,7 @@ describe "functions with custom types" do attach_function :ret_s32, [ :int ], Custom_enum end m.ret_s32(1) - Custom_enum.from_native_called?.should be_true + expect(Custom_enum.from_native_called?).to be true end it "to_native should be called for parameter" do @@ -70,6 +69,6 @@ describe "functions with custom types" do attach_function :ret_s32, [ Custom_enum ], :int end m.ret_s32(:a) - Custom_enum.to_native_called?.should be_true + expect(Custom_enum.to_native_called?).to be true end end diff --git a/spec/ffi/dup_spec.rb b/spec/ffi/dup_spec.rb index 9348368..ae6e523 100644 --- a/spec/ffi/dup_spec.rb +++ b/spec/ffi/dup_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' describe "Pointer#dup" do it "clone should be independent" do @@ -13,7 +12,7 @@ describe "Pointer#dup" do p2 = p1.dup p1.put_string(0, "deadbeef") - p2.get_string(0).should == "test123" + expect(p2.get_string(0)).to eq("test123") end it "sliced pointer can be cloned" do @@ -22,8 +21,8 @@ describe "Pointer#dup" do p2 = p1[1].dup # first char will be excised - p2.get_string(0).should == "est123" - p1.get_string(0).should == "test123" + expect(p2.get_string(0)).to eq("est123") + expect(p1.get_string(0)).to eq("test123") end it "sliced pointer when cloned is independent" do @@ -33,7 +32,7 @@ describe "Pointer#dup" do p1.put_string(0, "deadbeef") # first char will be excised - p2.get_string(0).should == "est123" + expect(p2.get_string(0)).to eq("est123") end end @@ -47,8 +46,7 @@ describe "Struct#dup" do s1[:i] = 0x12345 s2 = s1.dup s1[:i] = 0x98765 - s2[:i].should == 0x12345 - s1[:i].should == 0x98765 + expect(s2[:i]).to eq(0x12345) + expect(s1[:i]).to eq(0x98765) end - end diff --git a/spec/ffi/enum_spec.rb b/spec/ffi/enum_spec.rb index ae5205d..55ff13a 100644 --- a/spec/ffi/enum_spec.rb +++ b/spec/ffi/enum_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' module TestEnum0 extend FFI::Library @@ -37,185 +36,388 @@ module TestEnum3 attach_function :test_tagged_typedef_enum4, [:enum_type4], :enum_type4 end +module TestEnum4 + extend FFI::Library + ffi_lib TestLibrary::PATH + + enum [:c1, :c2, :c3, :c4] + enum :enum_type1, [:c5, 0x42, :c6, :c7, :c8] + enum :enum_type2, [:c9, 0x42, :c10, :c11, 0x4242, :c12] + enum :enum_type3, [:c13, 0x42, :c14, 0x4242, :c15, 0x42424242, :c16, 0x4242424242424242] + enum FFI::Type::UINT16, :enum_type4, [:c17, 0x42, :c18, :c19, :c20] + enum FFI::Type::UINT32, :enum_type5, [:c21, 0x42, :c22, :c23, 0x4242, :c24] + enum FFI::Type::UINT64, :enum_type6, [:c25, 0x42, :c26, 0x4242, :c27, 0x42424242, :c28, 0x4242424242424242] + enum FFI::Type::UINT64, [:c29, 0x4242424242424242, :c30, :c31, :c32] + + attach_function :test_untagged_nonint_enum, [:uint8], :uint8 + attach_function :test_tagged_nonint_enum1, [:uint16], :uint16 + attach_function :test_tagged_nonint_enum2, [:uint32], :uint32 + attach_function :test_tagged_nonint_enum3, [:uint64], :uint64 + attach_function :test_tagged_nonint_enum4, :test_tagged_nonint_enum1, [:enum_type4], :enum_type4 + attach_function :test_tagged_nonint_enum5, :test_tagged_nonint_enum2, [:enum_type5], :enum_type5 + attach_function :test_tagged_nonint_enum6, :test_tagged_nonint_enum3, [:enum_type6], :enum_type6 +end + describe "A library with no enum defined" do it "returns nil when asked for an enum" do - TestEnum0.enum_type(:foo).should == nil + expect(TestEnum0.enum_type(:foo)).to be_nil end end describe "An untagged enum" do it "constants can be used as function parameters and return value" do - TestEnum1.test_untagged_enum(:c1).should == 0 - TestEnum1.test_untagged_enum(:c2).should == 1 - TestEnum1.test_untagged_enum(:c3).should == 2 - TestEnum1.test_untagged_enum(:c4).should == 3 - TestEnum1.test_untagged_enum(:c5).should == 42 - TestEnum1.test_untagged_enum(:c6).should == 43 - TestEnum1.test_untagged_enum(:c7).should == 44 - TestEnum1.test_untagged_enum(:c8).should == 45 - TestEnum1.test_untagged_enum(:c9).should == 42 - TestEnum1.test_untagged_enum(:c10).should == 43 - TestEnum1.test_untagged_enum(:c11).should == 4242 - TestEnum1.test_untagged_enum(:c12).should == 4243 - TestEnum1.test_untagged_enum(:c13).should == 42 - TestEnum1.test_untagged_enum(:c14).should == 4242 - TestEnum1.test_untagged_enum(:c15).should == 424242 - TestEnum1.test_untagged_enum(:c16).should == 42424242 + expect(TestEnum1.test_untagged_enum(:c1)).to eq(0) + expect(TestEnum1.test_untagged_enum(:c2)).to eq(1) + expect(TestEnum1.test_untagged_enum(:c3)).to eq(2) + expect(TestEnum1.test_untagged_enum(:c4)).to eq(3) + expect(TestEnum1.test_untagged_enum(:c5)).to eq(42) + expect(TestEnum1.test_untagged_enum(:c6)).to eq(43) + expect(TestEnum1.test_untagged_enum(:c7)).to eq(44) + expect(TestEnum1.test_untagged_enum(:c8)).to eq(45) + expect(TestEnum1.test_untagged_enum(:c9)).to eq(42) + expect(TestEnum1.test_untagged_enum(:c10)).to eq(43) + expect(TestEnum1.test_untagged_enum(:c11)).to eq(4242) + expect(TestEnum1.test_untagged_enum(:c12)).to eq(4243) + expect(TestEnum1.test_untagged_enum(:c13)).to eq(42) + expect(TestEnum1.test_untagged_enum(:c14)).to eq(4242) + expect(TestEnum1.test_untagged_enum(:c15)).to eq(424242) + expect(TestEnum1.test_untagged_enum(:c16)).to eq(42424242) + expect(TestEnum4.test_untagged_nonint_enum(:c1)).to eq(0) + expect(TestEnum4.test_untagged_nonint_enum(:c2)).to eq(1) + expect(TestEnum4.test_untagged_nonint_enum(:c3)).to eq(2) + expect(TestEnum4.test_untagged_nonint_enum(:c4)).to eq(3) + expect(TestEnum4.test_tagged_nonint_enum3(:c29)).to eq(0x4242424242424242) + expect(TestEnum4.test_tagged_nonint_enum3(:c30)).to eq(0x4242424242424243) + expect(TestEnum4.test_tagged_nonint_enum3(:c31)).to eq(0x4242424242424244) + expect(TestEnum4.test_tagged_nonint_enum3(:c32)).to eq(0x4242424242424245) end end describe "A tagged typedef enum" do it "is accessible through its tag" do - TestEnum3.enum_type(:enum_type1).should_not == nil - TestEnum3.enum_type(:enum_type2).should_not == nil - TestEnum3.enum_type(:enum_type3).should_not == nil - TestEnum3.enum_type(:enum_type4).should_not == nil + expect(TestEnum3.enum_type(:enum_type1)).not_to be_nil + expect(TestEnum3.enum_type(:enum_type2)).not_to be_nil + expect(TestEnum3.enum_type(:enum_type3)).not_to be_nil + expect(TestEnum3.enum_type(:enum_type4)).not_to be_nil + expect(TestEnum4.enum_type(:enum_type1)).not_to be_nil + expect(TestEnum4.enum_type(:enum_type2)).not_to be_nil + expect(TestEnum4.enum_type(:enum_type3)).not_to be_nil + expect(TestEnum4.enum_type(:enum_type4)).not_to be_nil + expect(TestEnum4.enum_type(:enum_type5)).not_to be_nil + expect(TestEnum4.enum_type(:enum_type6)).not_to be_nil end + it "contains enum constants" do - TestEnum3.enum_type(:enum_type1).symbols.length.should == 4 - TestEnum3.enum_type(:enum_type2).symbols.length.should == 4 - TestEnum3.enum_type(:enum_type3).symbols.length.should == 4 - TestEnum3.enum_type(:enum_type4).symbols.length.should == 4 + expect(TestEnum3.enum_type(:enum_type1).symbols.length).to eq(4) + expect(TestEnum3.enum_type(:enum_type2).symbols.length).to eq(4) + expect(TestEnum3.enum_type(:enum_type3).symbols.length).to eq(4) + expect(TestEnum3.enum_type(:enum_type4).symbols.length).to eq(4) + expect(TestEnum4.enum_type(:enum_type1).symbols.length).to eq(4) + expect(TestEnum4.enum_type(:enum_type2).symbols.length).to eq(4) + expect(TestEnum4.enum_type(:enum_type3).symbols.length).to eq(4) + expect(TestEnum4.enum_type(:enum_type4).symbols.length).to eq(4) + expect(TestEnum4.enum_type(:enum_type5).symbols.length).to eq(4) + expect(TestEnum4.enum_type(:enum_type6).symbols.length).to eq(4) end + it "constants can be used as function parameters and return value" do - TestEnum3.test_tagged_typedef_enum1(:c1).should == :c1 - TestEnum3.test_tagged_typedef_enum1(:c2).should == :c2 - TestEnum3.test_tagged_typedef_enum1(:c3).should == :c3 - TestEnum3.test_tagged_typedef_enum1(:c4).should == :c4 - TestEnum3.test_tagged_typedef_enum2(:c5).should == :c5 - TestEnum3.test_tagged_typedef_enum2(:c6).should == :c6 - TestEnum3.test_tagged_typedef_enum2(:c7).should == :c7 - TestEnum3.test_tagged_typedef_enum2(:c8).should == :c8 - TestEnum3.test_tagged_typedef_enum3(:c9).should == :c9 - TestEnum3.test_tagged_typedef_enum3(:c10).should == :c10 - TestEnum3.test_tagged_typedef_enum3(:c11).should == :c11 - TestEnum3.test_tagged_typedef_enum3(:c12).should == :c12 - TestEnum3.test_tagged_typedef_enum4(:c13).should == :c13 - TestEnum3.test_tagged_typedef_enum4(:c14).should == :c14 - TestEnum3.test_tagged_typedef_enum4(:c15).should == :c15 - TestEnum3.test_tagged_typedef_enum4(:c16).should == :c16 + expect(TestEnum3.test_tagged_typedef_enum1(:c1)).to be :c1 + expect(TestEnum3.test_tagged_typedef_enum1(:c2)).to be :c2 + expect(TestEnum3.test_tagged_typedef_enum1(:c3)).to be :c3 + expect(TestEnum3.test_tagged_typedef_enum1(:c4)).to be :c4 + expect(TestEnum3.test_tagged_typedef_enum2(:c5)).to be :c5 + expect(TestEnum3.test_tagged_typedef_enum2(:c6)).to be :c6 + expect(TestEnum3.test_tagged_typedef_enum2(:c7)).to be :c7 + expect(TestEnum3.test_tagged_typedef_enum2(:c8)).to be :c8 + expect(TestEnum3.test_tagged_typedef_enum3(:c9)).to be :c9 + expect(TestEnum3.test_tagged_typedef_enum3(:c10)).to be :c10 + expect(TestEnum3.test_tagged_typedef_enum3(:c11)).to be :c11 + expect(TestEnum3.test_tagged_typedef_enum3(:c12)).to be :c12 + expect(TestEnum3.test_tagged_typedef_enum4(:c13)).to be :c13 + expect(TestEnum3.test_tagged_typedef_enum4(:c14)).to be :c14 + expect(TestEnum3.test_tagged_typedef_enum4(:c15)).to be :c15 + expect(TestEnum3.test_tagged_typedef_enum4(:c16)).to be :c16 + expect(TestEnum4.test_tagged_nonint_enum1(:c5)).to eq(0x42) + expect(TestEnum4.test_tagged_nonint_enum1(:c6)).to eq(0x43) + expect(TestEnum4.test_tagged_nonint_enum1(:c7)).to eq(0x44) + expect(TestEnum4.test_tagged_nonint_enum1(:c8)).to eq(0x45) + expect(TestEnum4.test_tagged_nonint_enum2(:c9)).to eq(0x42) + expect(TestEnum4.test_tagged_nonint_enum2(:c10)).to eq(0x43) + expect(TestEnum4.test_tagged_nonint_enum2(:c11)).to eq(0x4242) + expect(TestEnum4.test_tagged_nonint_enum2(:c12)).to eq(0x4243) + expect(TestEnum4.test_tagged_nonint_enum3(:c13)).to eq(0x42) + expect(TestEnum4.test_tagged_nonint_enum3(:c14)).to eq(0x4242) + expect(TestEnum4.test_tagged_nonint_enum3(:c15)).to eq(0x42424242) + expect(TestEnum4.test_tagged_nonint_enum3(:c16)).to eq(0x4242424242424242) + expect(TestEnum4.test_tagged_nonint_enum4(:c17)).to eq(:c17) + expect(TestEnum4.test_tagged_nonint_enum4(:c18)).to eq(:c18) + expect(TestEnum4.test_tagged_nonint_enum4(:c19)).to eq(:c19) + expect(TestEnum4.test_tagged_nonint_enum4(:c20)).to eq(:c20) + expect(TestEnum4.test_tagged_nonint_enum5(:c21)).to eq(:c21) + expect(TestEnum4.test_tagged_nonint_enum5(:c22)).to eq(:c22) + expect(TestEnum4.test_tagged_nonint_enum5(:c23)).to eq(:c23) + expect(TestEnum4.test_tagged_nonint_enum5(:c24)).to eq(:c24) + expect(TestEnum4.test_tagged_nonint_enum6(:c25)).to eq(:c25) + expect(TestEnum4.test_tagged_nonint_enum6(:c26)).to eq(:c26) + expect(TestEnum4.test_tagged_nonint_enum6(:c27)).to eq(:c27) + expect(TestEnum4.test_tagged_nonint_enum6(:c28)).to eq(:c28) end it "integers can be used instead of constants" do - TestEnum3.test_tagged_typedef_enum1(0).should == :c1 - TestEnum3.test_tagged_typedef_enum1(1).should == :c2 - TestEnum3.test_tagged_typedef_enum1(2).should == :c3 - TestEnum3.test_tagged_typedef_enum1(3).should == :c4 - TestEnum3.test_tagged_typedef_enum2(42).should == :c5 - TestEnum3.test_tagged_typedef_enum2(43).should == :c6 - TestEnum3.test_tagged_typedef_enum2(44).should == :c7 - TestEnum3.test_tagged_typedef_enum2(45).should == :c8 - TestEnum3.test_tagged_typedef_enum3(42).should == :c9 - TestEnum3.test_tagged_typedef_enum3(43).should == :c10 - TestEnum3.test_tagged_typedef_enum3(4242).should == :c11 - TestEnum3.test_tagged_typedef_enum3(4243).should == :c12 - TestEnum3.test_tagged_typedef_enum4(42).should == :c13 - TestEnum3.test_tagged_typedef_enum4(4242).should == :c14 - TestEnum3.test_tagged_typedef_enum4(424242).should == :c15 - TestEnum3.test_tagged_typedef_enum4(42424242).should == :c16 + expect(TestEnum3.test_tagged_typedef_enum1(0)).to be :c1 + expect(TestEnum3.test_tagged_typedef_enum1(1)).to be :c2 + expect(TestEnum3.test_tagged_typedef_enum1(2)).to be :c3 + expect(TestEnum3.test_tagged_typedef_enum1(3)).to be :c4 + expect(TestEnum3.test_tagged_typedef_enum2(42)).to be :c5 + expect(TestEnum3.test_tagged_typedef_enum2(43)).to be :c6 + expect(TestEnum3.test_tagged_typedef_enum2(44)).to be :c7 + expect(TestEnum3.test_tagged_typedef_enum2(45)).to be :c8 + expect(TestEnum3.test_tagged_typedef_enum3(42)).to be :c9 + expect(TestEnum3.test_tagged_typedef_enum3(43)).to be :c10 + expect(TestEnum3.test_tagged_typedef_enum3(4242)).to be :c11 + expect(TestEnum3.test_tagged_typedef_enum3(4243)).to be :c12 + expect(TestEnum3.test_tagged_typedef_enum4(42)).to be :c13 + expect(TestEnum3.test_tagged_typedef_enum4(4242)).to be :c14 + expect(TestEnum3.test_tagged_typedef_enum4(424242)).to be :c15 + expect(TestEnum3.test_tagged_typedef_enum4(42424242)).to be :c16 + expect(TestEnum4.test_tagged_nonint_enum4(0x42)).to eq(:c17) + expect(TestEnum4.test_tagged_nonint_enum4(0x43)).to eq(:c18) + expect(TestEnum4.test_tagged_nonint_enum4(0x44)).to eq(:c19) + expect(TestEnum4.test_tagged_nonint_enum4(0x45)).to eq(:c20) + expect(TestEnum4.test_tagged_nonint_enum5(0x42)).to eq(:c21) + expect(TestEnum4.test_tagged_nonint_enum5(0x43)).to eq(:c22) + expect(TestEnum4.test_tagged_nonint_enum5(0x4242)).to eq(:c23) + expect(TestEnum4.test_tagged_nonint_enum5(0x4243)).to eq(:c24) + expect(TestEnum4.test_tagged_nonint_enum6(0x42)).to eq(:c25) + expect(TestEnum4.test_tagged_nonint_enum6(0x4242)).to eq(:c26) + expect(TestEnum4.test_tagged_nonint_enum6(0x42424242)).to eq(:c27) + expect(TestEnum4.test_tagged_nonint_enum6(0x4242424242424242)).to eq(:c28) end end describe "All enums" do it "have autonumbered constants when defined with names only" do - TestEnum1.enum_value(:c1).should == 0 - TestEnum1.enum_value(:c2).should == 1 - TestEnum1.enum_value(:c3).should == 2 - TestEnum1.enum_value(:c4).should == 3 - - TestEnum3.enum_value(:c1).should == 0 - TestEnum3.enum_value(:c2).should == 1 - TestEnum3.enum_value(:c3).should == 2 - TestEnum3.enum_value(:c4).should == 3 + expect(TestEnum1.enum_value(:c1)).to eq(0) + expect(TestEnum1.enum_value(:c2)).to eq(1) + expect(TestEnum1.enum_value(:c3)).to eq(2) + expect(TestEnum1.enum_value(:c4)).to eq(3) + + expect(TestEnum3.enum_value(:c1)).to eq(0) + expect(TestEnum3.enum_value(:c2)).to eq(1) + expect(TestEnum3.enum_value(:c3)).to eq(2) + expect(TestEnum3.enum_value(:c4)).to eq(3) + + expect(TestEnum4.enum_value(:c1)).to eq(0) + expect(TestEnum4.enum_value(:c2)).to eq(1) + expect(TestEnum4.enum_value(:c3)).to eq(2) + expect(TestEnum4.enum_value(:c4)).to eq(3) end + it "can have an explicit first constant and autonumbered subsequent constants" do - TestEnum1.enum_value(:c5).should == 42 - TestEnum1.enum_value(:c6).should == 43 - TestEnum1.enum_value(:c7).should == 44 - TestEnum1.enum_value(:c8).should == 45 - - TestEnum3.enum_value(:c5).should == 42 - TestEnum3.enum_value(:c6).should == 43 - TestEnum3.enum_value(:c7).should == 44 - TestEnum3.enum_value(:c8).should == 45 + expect(TestEnum1.enum_value(:c5)).to eq(42) + expect(TestEnum1.enum_value(:c6)).to eq(43) + expect(TestEnum1.enum_value(:c7)).to eq(44) + expect(TestEnum1.enum_value(:c8)).to eq(45) + + expect(TestEnum3.enum_value(:c5)).to eq(42) + expect(TestEnum3.enum_value(:c6)).to eq(43) + expect(TestEnum3.enum_value(:c7)).to eq(44) + expect(TestEnum3.enum_value(:c8)).to eq(45) + + expect(TestEnum4.enum_value(:c5)).to eq(0x42) + expect(TestEnum4.enum_value(:c6)).to eq(0x43) + expect(TestEnum4.enum_value(:c7)).to eq(0x44) + expect(TestEnum4.enum_value(:c8)).to eq(0x45) + + expect(TestEnum4.enum_value(:c29)).to eq(0x4242424242424242) + expect(TestEnum4.enum_value(:c30)).to eq(0x4242424242424243) + expect(TestEnum4.enum_value(:c31)).to eq(0x4242424242424244) + expect(TestEnum4.enum_value(:c32)).to eq(0x4242424242424245) end + it "can have a mix of explicit and autonumbered constants" do - TestEnum1.enum_value(:c9).should == 42 - TestEnum1.enum_value(:c10).should == 43 - TestEnum1.enum_value(:c11).should == 4242 - TestEnum1.enum_value(:c12).should == 4243 - - TestEnum3.enum_value(:c9).should == 42 - TestEnum3.enum_value(:c10).should == 43 - TestEnum3.enum_value(:c11).should == 4242 - TestEnum3.enum_value(:c12).should == 4243 + expect(TestEnum1.enum_value(:c9)).to eq(42) + expect(TestEnum1.enum_value(:c10)).to eq(43) + expect(TestEnum1.enum_value(:c11)).to eq(4242) + expect(TestEnum1.enum_value(:c12)).to eq(4243) + + expect(TestEnum3.enum_value(:c9)).to eq(42) + expect(TestEnum3.enum_value(:c10)).to eq(43) + expect(TestEnum3.enum_value(:c11)).to eq(4242) + expect(TestEnum3.enum_value(:c12)).to eq(4243) + + expect(TestEnum4.enum_value(:c9)).to eq(0x42) + expect(TestEnum4.enum_value(:c10)).to eq(0x43) + expect(TestEnum4.enum_value(:c11)).to eq(0x4242) + expect(TestEnum4.enum_value(:c12)).to eq(0x4243) + + expect(TestEnum4.enum_value(:c21)).to eq(0x42) + expect(TestEnum4.enum_value(:c22)).to eq(0x43) + expect(TestEnum4.enum_value(:c23)).to eq(0x4242) + expect(TestEnum4.enum_value(:c24)).to eq(0x4243) end + it "can have all its constants explicitely valued" do - TestEnum1.enum_value(:c13).should == 42 - TestEnum1.enum_value(:c14).should == 4242 - TestEnum1.enum_value(:c15).should == 424242 - TestEnum1.enum_value(:c16).should == 42424242 + expect(TestEnum1.enum_value(:c13)).to eq(42) + expect(TestEnum1.enum_value(:c14)).to eq(4242) + expect(TestEnum1.enum_value(:c15)).to eq(424242) + expect(TestEnum1.enum_value(:c16)).to eq(42424242) - TestEnum3.enum_value(:c13).should == 42 - TestEnum3.enum_value(:c14).should == 4242 - TestEnum3.enum_value(:c15).should == 424242 - TestEnum3.enum_value(:c16).should == 42424242 + expect(TestEnum3.enum_value(:c13)).to eq(42) + expect(TestEnum3.enum_value(:c14)).to eq(4242) + expect(TestEnum3.enum_value(:c15)).to eq(424242) + expect(TestEnum3.enum_value(:c16)).to eq(42424242) + + expect(TestEnum4.enum_value(:c13)).to eq(0x42) + expect(TestEnum4.enum_value(:c14)).to eq(0x4242) + expect(TestEnum4.enum_value(:c15)).to eq(0x42424242) + expect(TestEnum4.enum_value(:c16)).to eq(0x4242424242424242) + + expect(TestEnum4.enum_value(:c25)).to eq(0x42) + expect(TestEnum4.enum_value(:c26)).to eq(0x4242) + expect(TestEnum4.enum_value(:c27)).to eq(0x42424242) + expect(TestEnum4.enum_value(:c28)).to eq(0x4242424242424242) end + it "return the constant corresponding to a specific value" do enum = TestEnum3.enum_type(:enum_type1) - enum[0].should == :c1 - enum[1].should == :c2 - enum[2].should == :c3 - enum[3].should == :c4 + expect(enum[0]).to be :c1 + expect(enum[1]).to be :c2 + expect(enum[2]).to be :c3 + expect(enum[3]).to be :c4 enum = TestEnum3.enum_type(:enum_type2) - enum[42].should == :c5 - enum[43].should == :c6 - enum[44].should == :c7 - enum[45].should == :c8 + expect(enum[42]).to be :c5 + expect(enum[43]).to be :c6 + expect(enum[44]).to be :c7 + expect(enum[45]).to be :c8 enum = TestEnum3.enum_type(:enum_type3) - enum[42].should == :c9 - enum[43].should == :c10 - enum[4242].should == :c11 - enum[4243].should == :c12 + expect(enum[42]).to be :c9 + expect(enum[43]).to be :c10 + expect(enum[4242]).to be :c11 + expect(enum[4243]).to be :c12 enum = TestEnum3.enum_type(:enum_type4) - enum[42].should == :c13 - enum[4242].should == :c14 - enum[424242].should == :c15 - enum[42424242].should == :c16 + expect(enum[42]).to be :c13 + expect(enum[4242]).to be :c14 + expect(enum[424242]).to be :c15 + expect(enum[42424242]).to be :c16 + + enum = TestEnum4.enum_type(:enum_type1) + expect(enum[0x42]).to eq(:c5) + expect(enum[0x43]).to eq(:c6) + expect(enum[0x44]).to eq(:c7) + expect(enum[0x45]).to eq(:c8) + + enum = TestEnum4.enum_type(:enum_type2) + expect(enum[0x42]).to eq(:c9) + expect(enum[0x43]).to eq(:c10) + expect(enum[0x4242]).to eq(:c11) + expect(enum[0x4243]).to eq(:c12) + + enum = TestEnum4.enum_type(:enum_type3) + expect(enum[0x42]).to eq(:c13) + expect(enum[0x4242]).to eq(:c14) + expect(enum[0x42424242]).to eq(:c15) + expect(enum[0x4242424242424242]).to eq(:c16) + + enum = TestEnum4.enum_type(:enum_type4) + expect(enum[0x42]).to eq(:c17) + expect(enum[0x43]).to eq(:c18) + expect(enum[0x44]).to eq(:c19) + expect(enum[0x45]).to eq(:c20) + + enum = TestEnum4.enum_type(:enum_type5) + expect(enum[0x42]).to eq(:c21) + expect(enum[0x43]).to eq(:c22) + expect(enum[0x4242]).to eq(:c23) + expect(enum[0x4243]).to eq(:c24) + + enum = TestEnum4.enum_type(:enum_type6) + expect(enum[0x42]).to eq(:c25) + expect(enum[0x4242]).to eq(:c26) + expect(enum[0x42424242]).to eq(:c27) + expect(enum[0x4242424242424242]).to eq(:c28) end + it "return nil for values that don't have a symbol" do enum = TestEnum3.enum_type(:enum_type1) - enum[-1].should == nil - enum[4].should == nil + expect(enum[-1]).to be_nil + expect(enum[4]).to be_nil enum = TestEnum3.enum_type(:enum_type2) - enum[0].should == nil - enum[41].should == nil - enum[46].should == nil + expect(enum[0]).to be_nil + expect(enum[41]).to be_nil + expect(enum[46]).to be_nil enum = TestEnum3.enum_type(:enum_type3) - enum[0].should == nil - enum[41].should == nil - enum[44].should == nil - enum[4241].should == nil - enum[4244].should == nil + expect(enum[0]).to be_nil + expect(enum[41]).to be_nil + expect(enum[44]).to be_nil + expect(enum[4241]).to be_nil + expect(enum[4244]).to be_nil enum = TestEnum3.enum_type(:enum_type4) - enum[0].should == nil - enum[41].should == nil - enum[43].should == nil - enum[4241].should == nil - enum[4243].should == nil - enum[424241].should == nil - enum[424243].should == nil - enum[42424241].should == nil - enum[42424243].should == nil + expect(enum[0]).to be_nil + expect(enum[41]).to be_nil + expect(enum[43]).to be_nil + expect(enum[4241]).to be_nil + expect(enum[4243]).to be_nil + expect(enum[424241]).to be_nil + expect(enum[424243]).to be_nil + expect(enum[42424241]).to be_nil + expect(enum[42424243]).to be_nil + + enum = TestEnum4.enum_type(:enum_type1) + expect(enum[0x0]).to be_nil + expect(enum[0x41]).to be_nil + expect(enum[0x46]).to be_nil + + enum = TestEnum4.enum_type(:enum_type2) + expect(enum[0x0]).to be_nil + expect(enum[0x41]).to be_nil + expect(enum[0x44]).to be_nil + expect(enum[0x4241]).to be_nil + expect(enum[0x4244]).to be_nil + + enum = TestEnum4.enum_type(:enum_type3) + expect(enum[0x0]).to be_nil + expect(enum[0x41]).to be_nil + expect(enum[0x43]).to be_nil + expect(enum[0x4241]).to be_nil + expect(enum[0x4243]).to be_nil + expect(enum[0x42424241]).to be_nil + expect(enum[0x42424243]).to be_nil + expect(enum[0x4242424242424241]).to be_nil + expect(enum[0x4242424242424243]).to be_nil + + enum = TestEnum4.enum_type(:enum_type4) + expect(enum[0x0]).to be_nil + expect(enum[0x41]).to be_nil + expect(enum[0x46]).to be_nil + + enum = TestEnum4.enum_type(:enum_type5) + expect(enum[0x0]).to be_nil + expect(enum[0x41]).to be_nil + expect(enum[0x44]).to be_nil + expect(enum[0x4241]).to be_nil + expect(enum[0x4244]).to be_nil + + enum = TestEnum4.enum_type(:enum_type6) + expect(enum[0x0]).to be_nil + expect(enum[0x41]).to be_nil + expect(enum[0x43]).to be_nil + expect(enum[0x4241]).to be_nil + expect(enum[0x4243]).to be_nil + expect(enum[0x42424241]).to be_nil + expect(enum[0x42424243]).to be_nil + expect(enum[0x4242424242424241]).to be_nil + expect(enum[0x4242424242424243]).to be_nil end it "duplicate enum keys rejected" do - lambda { enum [ :a, 0xfee1dead, :b, 0xdeadbeef, :a, 0 ] }.should raise_error + expect { enum [ :a, 0xfee1dead, :b, 0xdeadbeef, :a, 0 ] }.to raise_error + expect { enum FFI::Type::UINT64, [ :a, 0xfee1dead, :b, 0xdeadbeef, :a, 0 ] }.to raise_error end end diff --git a/spec/ffi/errno_spec.rb b/spec/ffi/errno_spec.rb index 4f29ae6..61cbda2 100644 --- a/spec/ffi/errno_spec.rb +++ b/spec/ffi/errno_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' describe "FFI.errno" do module LibTest @@ -12,9 +11,10 @@ describe "FFI.errno" do ffi_lib TestLibrary::PATH attach_function :setLastError, [ :int ], :void end + it "FFI.errno contains errno from last function" do LibTest.setLastError(0) LibTest.setLastError(0x12345678) - FFI.errno.should == 0x12345678 + expect(FFI.errno).to eq(0x12345678) end end diff --git a/spec/ffi/ffi_spec.rb b/spec/ffi/ffi_spec.rb index ab1f641..bb93f37 100644 --- a/spec/ffi/ffi_spec.rb +++ b/spec/ffi/ffi_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' describe "FFI" do @@ -12,19 +11,18 @@ describe "FFI" do let(:prefix) { FFI::Platform::LIBPREFIX } let(:suffix) { FFI::Platform::LIBSUFFIX } - + it "should add platform library extension if not present" do - FFI.map_library_name("#{prefix}dummy").should == "#{prefix}dummy.#{suffix}" + expect(FFI.map_library_name("#{prefix}dummy")).to eq("#{prefix}dummy.#{suffix}") end it "should add platform library extension even if lib suffix is present in name" do - FFI.map_library_name("#{prefix}dummy_with_#{suffix}").should == "#{prefix}dummy_with_#{suffix}.#{suffix}" + expect(FFI.map_library_name("#{prefix}dummy_with_#{suffix}")).to eq("#{prefix}dummy_with_#{suffix}.#{suffix}") end it "should return Platform::LIBC when called with 'c'" do - FFI.map_library_name('c').should == FFI::Library::LIBC + expect(FFI.map_library_name('c')).to eq(FFI::Library::LIBC) end end - end diff --git a/spec/ffi/fixtures/EnumTest.c b/spec/ffi/fixtures/EnumTest.c index 4c9dda9..4bf8d23 100644 --- a/spec/ffi/fixtures/EnumTest.c +++ b/spec/ffi/fixtures/EnumTest.c @@ -3,6 +3,7 @@ * * For licensing, see LICENSE.SPECS */ +#include <stdint.h> int test_untagged_enum(int val) { return val; @@ -12,6 +13,22 @@ int test_untagged_typedef_enum(int val) { return val; } +uint8_t test_untagged_nonint_enum(uint8_t val) { + return val; +} + +uint16_t test_tagged_nonint_enum1(uint16_t val) { + return val; +} + +uint32_t test_tagged_nonint_enum2(uint32_t val) { + return val; +} + +uint64_t test_tagged_nonint_enum3(uint64_t val) { + return val; +} + typedef enum {c1, c2, c3, c4} enum_type1; enum_type1 test_tagged_typedef_enum1(enum_type1 val) { return val; diff --git a/spec/ffi/function_spec.rb b/spec/ffi/function_spec.rb index d8c7bde..ab08f35 100644 --- a/spec/ffi/function_spec.rb +++ b/spec/ffi/function_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' describe FFI::Function do module LibTest @@ -16,33 +15,41 @@ describe FFI::Function do @libtest = FFI::DynamicLibrary.open(TestLibrary::PATH, FFI::DynamicLibrary::RTLD_LAZY | FFI::DynamicLibrary::RTLD_GLOBAL) end + it 'is initialized with a signature and a block' do 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 + expect { FFI::Function.new([], :int).new { } }.to raise_error TypeError end + it 'returns a native pointer' do 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 } - LibTest.testFunctionAdd(10, 10, function_add).should == 20 + expect(LibTest.testFunctionAdd(10, 10, function_add)).to eq(20) end + it 'can be used as callback from C passing to it a Proc object' do function_add = FFI::Function.new(:int, [:int, :int], Proc.new { |a, b| a + b }) - LibTest.testFunctionAdd(10, 10, function_add).should == 20 + expect(LibTest.testFunctionAdd(10, 10, function_add)).to eq(20) end + it 'can be used to wrap an existing function pointer' do - FFI::Function.new(:int, [:int, :int], @libtest.find_function('testAdd')).call(10, 10).should == 20 + expect(FFI::Function.new(:int, [:int, :int], @libtest.find_function('testAdd')).call(10, 10)).to eq(20) end + it 'can be attached to a module' do module Foo; end fp = FFI::Function.new(:int, [:int, :int], @libtest.find_function('testAdd')) fp.attach(Foo, 'add') - Foo.add(10, 10).should == 20 + expect(Foo.add(10, 10)).to eq(20) end + it 'can be used to extend an object' do fp = FFI::Function.new(:int, [:int, :int], @libtest.find_function('testAdd')) foo = Object.new @@ -52,27 +59,34 @@ describe FFI::Function do end end fp.attach(foo.singleton_class, 'add') - foo.add(10, 10).should == 20 + expect(foo.add(10, 10)).to eq(20) end + it 'can wrap a blocking function' do fp = FFI::Function.new(:void, [ :int ], @libtest.find_function('testBlocking'), :blocking => true) - time = Time.now - threads = [] - threads << Thread.new { fp.call(2) } - threads << Thread.new(time) { (Time.now - time).should < 1 } + threads = 10.times.map do |x| + Thread.new do + time = Time.now + fp.call(2) + expect(Time.now - time).to be >= 2 + end + end threads.each { |t| t.join } end + it 'autorelease flag is set to true by default' do fp = FFI::Function.new(:int, [:int, :int], @libtest.find_function('testAdd')) - fp.autorelease?.should be_true + expect(fp.autorelease?).to be true end + it 'can explicity free itself' do fp = FFI::Function.new(:int, []) { } fp.free - lambda { fp.free }.should raise_error RuntimeError + expect { fp.free }.to raise_error RuntimeError end + it 'can\'t explicity free itself if not previously allocated' do fp = FFI::Function.new(:int, [:int, :int], @libtest.find_function('testAdd')) - lambda { fp.free }.should raise_error RuntimeError + expect { fp.free }.to raise_error RuntimeError end end diff --git a/spec/ffi/io_spec.rb b/spec/ffi/io_spec.rb index ccae035..22c238a 100644 --- a/spec/ffi/io_spec.rb +++ b/spec/ffi/io_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' if false # disabled for #390 describe "FFI::IO.for_fd" do diff --git a/spec/ffi/library_spec.rb b/spec/ffi/library_spec.rb index 9de1684..4359b93 100644 --- a/spec/ffi/library_spec.rb +++ b/spec/ffi/library_spec.rb @@ -4,15 +4,30 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' describe "Library" do + describe ".enum_value" do + m = Module.new do + extend FFI::Library + enum :something, [:one, :two] + end + + it "should return a value for a valid key" do + expect(m.enum_value(:one)).to eq(0) + expect(m.enum_value(:two)).to eq(1) + end + + it "should return nil for an invalid key" do + expect(m.enum_value(:three)).to be nil + end + end + describe "#ffi_convention" do it "defaults to :default" do m = Module.new do extend FFI::Library end - m.ffi_convention.should == :default + expect(m.ffi_convention).to eq(:default) end it "should be settable" do @@ -20,9 +35,9 @@ describe "Library" do extend FFI::Library end - m.ffi_convention.should == :default + expect(m.ffi_convention).to eq(:default) m.ffi_convention :stdcall - m.ffi_convention.should == :stdcall + expect(m.ffi_convention).to eq(:stdcall) end end @@ -51,76 +66,83 @@ describe "Library" do describe "ffi_lib" do it "empty name list should raise error" do - lambda { + expect { Module.new do |m| m.extend FFI::Library ffi_lib end - }.should raise_error(LoadError) + }.to raise_error(LoadError) end end + unless RbConfig::CONFIG['target_os'] =~ /mswin|mingw/ it "attach_function with no library specified" do - lambda { + expect { Module.new do |m| m.extend FFI::Library attach_function :getpid, [ ], :uint end - }.should raise_error + }.to raise_error end + it "attach_function :getpid from this process" do - lambda { - Module.new do |m| + expect { + expect(Module.new do |m| m.extend FFI::Library ffi_lib FFI::Library::CURRENT_PROCESS attach_function :getpid, [ ], :uint - end.getpid.should == Process.pid - }.should_not raise_error + end.getpid).to eq(Process.pid) + }.not_to raise_error end + it "attach_function :getpid from [ 'c', 'libc.so.6'] " do - lambda { - Module.new do |m| + expect { + expect(Module.new do |m| m.extend FFI::Library ffi_lib [ 'c', 'libc.so.6' ] attach_function :getpid, [ ], :uint - end.getpid.should == Process.pid - }.should_not raise_error + end.getpid).to eq(Process.pid) + }.not_to raise_error end + it "attach_function :getpid from [ 'libc.so.6', 'c' ] " do - lambda { - Module.new do |m| + expect { + expect(Module.new do |m| m.extend FFI::Library ffi_lib [ 'libc.so.6', 'c' ] attach_function :getpid, [ ], :uint - end.getpid.should == Process.pid - }.should_not raise_error + end.getpid).to eq(Process.pid) + }.not_to raise_error end + it "attach_function :getpid from [ 'libfubar.so.0xdeadbeef', nil, 'c' ] " do - lambda { - Module.new do |m| + expect { + expect(Module.new do |m| m.extend FFI::Library ffi_lib [ 'libfubar.so.0xdeadbeef', nil, 'c' ] attach_function :getpid, [ ], :uint - end.getpid.should == Process.pid - }.should_not raise_error + end.getpid).to eq(Process.pid) + }.not_to raise_error end + it "attach_function :getpid from [ 'libfubar.so.0xdeadbeef' ] " do - lambda { - Module.new do |m| + expect { + expect(Module.new do |m| m.extend FFI::Library ffi_lib 'libfubar.so.0xdeadbeef' attach_function :getpid, [ ], :uint - end.getpid.should == Process.pid - }.should raise_error(LoadError) + end.getpid).to eq(Process.pid) + }.to raise_error(LoadError) end + it "attach_function :bool_return_true from [ File.expand_path(#{TestLibrary::PATH.inspect}) ]" do - Module.new do |m| + mod = Module.new do |m| m.extend FFI::Library ffi_lib File.expand_path(TestLibrary::PATH) attach_function :bool_return_true, [ ], :bool - m.bool_return_true.should == true end + expect(mod.bool_return_true).to be true end end @@ -133,60 +155,71 @@ describe "Library" do attach_function :set, "gvar_#{name}_set", [ type ], :void end end + def gvar_test(name, type, val) lib = gvar_lib(name, type) lib.set(val) - lib.gvar.should == val + expect(lib.gvar).to eq(val) lib.set(0) lib.gvar = val - lib.get.should == val + expect(lib.get).to eq(val) end + [ 0, 127, -128, -1 ].each do |i| it ":char variable" do gvar_test("s8", :char, i) end end + [ 0, 0x7f, 0x80, 0xff ].each do |i| it ":uchar variable" do gvar_test("u8", :uchar, i) end end + [ 0, 0x7fff, -0x8000, -1 ].each do |i| it ":short variable" do gvar_test("s16", :short, i) end end + [ 0, 0x7fff, 0x8000, 0xffff ].each do |i| it ":ushort variable" do gvar_test("u16", :ushort, i) end end + [ 0, 0x7fffffff, -0x80000000, -1 ].each do |i| it ":int variable" do gvar_test("s32", :int, i) end end + [ 0, 0x7fffffff, 0x80000000, 0xffffffff ].each do |i| it ":uint variable" do gvar_test("u32", :uint, i) end end + [ 0, 0x7fffffffffffffff, -0x8000000000000000, -1 ].each do |i| it ":long_long variable" do gvar_test("s64", :long_long, i) end end + [ 0, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff ].each do |i| it ":ulong_long variable" do gvar_test("u64", :ulong_long, i) end end + if FFI::Platform::LONG_SIZE == 32 [ 0, 0x7fffffff, -0x80000000, -1 ].each do |i| it ":long variable" do gvar_test("long", :long, i) end end + [ 0, 0x7fffffff, 0x80000000, 0xffffffff ].each do |i| it ":ulong variable" do gvar_test("ulong", :ulong, i) @@ -198,20 +231,22 @@ describe "Library" do gvar_test("long", :long, i) end end + [ 0, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff ].each do |i| it ":ulong variable" do gvar_test("ulong", :ulong, i) end end end + it "Pointer variable" do lib = gvar_lib("pointer", :pointer) val = FFI::MemoryPointer.new :long lib.set(val) - lib.gvar.should == val + expect(lib.gvar).to eq(val) lib.set(nil) lib.gvar = val - lib.get.should == val + expect(lib.get).to eq(val) end [ 0, 0x7fffffff, -0x80000000, -1 ].each do |i| @@ -231,11 +266,11 @@ describe "Library" do val = GlobalStruct.new val[:data] = i lib.set(val) - lib.gvar[:data].should == i + expect(lib.gvar[:data]).to eq(i) val[:data] = 0 lib.gvar[:data] = i val = GlobalStruct.new(lib.get) - val[:data].should == i + expect(val[:data]).to eq(i) end end end diff --git a/spec/ffi/long_double.rb b/spec/ffi/long_double.rb index 5699457..b16613b 100644 --- a/spec/ffi/long_double.rb +++ b/spec/ffi/long_double.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' require 'bigdecimal' describe ":long_double arguments and return values" do @@ -16,16 +15,16 @@ describe ":long_double arguments and return values" do end it "returns first parameter" do - LibTest.ret_f128(0.1).should be_within(0.01).of(0.1) + expect(LibTest.ret_f128(0.1)).to be_within(0.01).of(0.1) end it "returns first parameter with high precision" do ld = BigDecimal.new("1.234567890123456789") tolerance = BigDecimal.new("0.0000000000000000001") - LibTest.ret_f128(ld).should be_within(tolerance).of(ld) + expect(LibTest.ret_f128(ld)).to be_within(tolerance).of(ld) end it "add two long double numbers" do - LibTest.add_f128(0.1, 0.2).should be_within(0.01).of(0.3) + expect(LibTest.add_f128(0.1, 0.2)).to be_within(0.01).of(0.3) end end diff --git a/spec/ffi/managed_struct_spec.rb b/spec/ffi/managed_struct_spec.rb index ecd5d9b..99e0f54 100644 --- a/spec/ffi/managed_struct_spec.rb +++ b/spec/ffi/managed_struct_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' describe "Managed Struct" do include FFI @@ -13,9 +12,10 @@ describe "Managed Struct" do ffi_lib TestLibrary::PATH attach_function :ptr_from_address, [ FFI::Platform::ADDRESS_SIZE == 32 ? :uint : :ulong_long ], :pointer end + it "should raise an error if release() is not defined" do class NoRelease < FFI::ManagedStruct ; layout :i, :int; end - lambda { NoRelease.new(ManagedStructTestLib.ptr_from_address(0x12345678)) }.should raise_error(NoMethodError) + expect { NoRelease.new(ManagedStructTestLib.ptr_from_address(0x12345678)) }.to raise_error(NoMethodError) end it "should be the right class" do @@ -25,7 +25,17 @@ describe "Managed Struct" do end end - WhatClassAmI.new(ManagedStructTestLib.ptr_from_address(0x12345678)).class.should == WhatClassAmI + expect(WhatClassAmI.new(ManagedStructTestLib.ptr_from_address(0x12345678)).class).to eq(WhatClassAmI) + end + + it "should build with self reference" do + class ClassWithSelfRef < FFI::ManagedStruct + layout :data, self.ptr + def self.release + end + end + + expect(ClassWithSelfRef.new(ManagedStructTestLib.ptr_from_address(0x12345678)).class).to eq(ClassWithSelfRef) end it "should release memory properly" do @@ -48,7 +58,7 @@ describe "Managed Struct" do loop_count = 30 wiggle_room = 5 - PleaseReleaseMe.should_receive(:release).at_least(loop_count-wiggle_room).times + expect(PleaseReleaseMe).to receive(:release).at_least(loop_count-wiggle_room).times loop_count.times do PleaseReleaseMe.new(ManagedStructTestLib.ptr_from_address(0x12345678)) end diff --git a/spec/ffi/memorypointer_spec.rb b/spec/ffi/memorypointer_spec.rb index ebe23ed..d819f35 100644 --- a/spec/ffi/memorypointer_spec.rb +++ b/spec/ffi/memorypointer_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' MemoryPointer = FFI::MemoryPointer @@ -12,15 +11,19 @@ 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 @@ -42,11 +45,13 @@ describe "MemoryPointer argument" do 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 @@ -64,6 +69,7 @@ describe "MemoryPointer return value" do 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 diff --git a/spec/ffi/number_spec.rb b/spec/ffi/number_spec.rb index 6f8cd0f..acb9562 100644 --- a/spec/ffi/number_spec.rb +++ b/spec/ffi/number_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' describe "Function with primitive integer arguments" do module LibTest @@ -27,108 +26,118 @@ describe "Function with primitive integer arguments" do attach_function :set_double, [ :double ], :void attach_function :get_double, [ ], :double end + it "int8.size" do - FFI::TYPE_INT8.size.should == 1 + expect(FFI::TYPE_INT8.size).to eq(1) end + it "uint8.size" do - FFI::TYPE_UINT8.size.should == 1 + expect(FFI::TYPE_UINT8.size).to eq(1) end + it "int16.size" do - FFI::TYPE_INT16.size.should == 2 + expect(FFI::TYPE_INT16.size).to eq(2) end + it "uint16.size" do - FFI::TYPE_UINT16.size.should == 2 + expect(FFI::TYPE_UINT16.size).to eq(2) end + it "int32.size" do - FFI::TYPE_INT32.size.should == 4 + expect(FFI::TYPE_INT32.size).to eq(4) end + it "uint32.size" do - FFI::TYPE_UINT32.size.should == 4 + expect(FFI::TYPE_UINT32.size).to eq(4) end + it "int64.size" do - FFI::TYPE_INT64.size.should == 8 + expect(FFI::TYPE_INT64.size).to eq(8) end + it "uint64.size" do - FFI::TYPE_UINT64.size.should == 8 + expect(FFI::TYPE_UINT64.size).to eq(8) end + it "float.size" do - FFI::TYPE_FLOAT32.size.should == 4 + expect(FFI::TYPE_FLOAT32.size).to eq(4) end + it "double.size" do - FFI::TYPE_FLOAT64.size.should == 8 + expect(FFI::TYPE_FLOAT64.size).to eq(8) end [ 0, 127, -128, -1 ].each do |i| it ":char call(:char (#{i}))" do - LibTest.ret_s8(i).should == i + expect(LibTest.ret_s8(i)).to eq(i) end end [ 0, 0x7f, 0x80, 0xff ].each do |i| it ":uchar call(:uchar (#{i}))" do - LibTest.ret_u8(i).should == i + expect(LibTest.ret_u8(i)).to eq(i) end end [ 0, 0x7fff, -0x8000, -1 ].each do |i| it ":short call(:short (#{i}))" do - LibTest.ret_s16(i).should == i + expect(LibTest.ret_s16(i)).to eq(i) end end [ 0, 0x7fff, 0x8000, 0xffff ].each do |i| it ":ushort call(:ushort (#{i}))" do - LibTest.ret_u16(i).should == i + expect(LibTest.ret_u16(i)).to eq(i) end end [ 0, 0x7fffffff, -0x80000000, -1 ].each do |i| it ":int call(:int (#{i}))" do - LibTest.ret_s32(i).should == i + expect(LibTest.ret_s32(i)).to eq(i) end end [ 0, 0x7fffffff, 0x80000000, 0xffffffff ].each do |i| it ":uint call(:uint (#{i}))" do - LibTest.ret_u32(i).should == i + expect(LibTest.ret_u32(i)).to eq(i) end end [ 0, 0x7fffffffffffffff, -0x8000000000000000, -1 ].each do |i| it ":long_long call(:long_long (#{i}))" do - LibTest.ret_s64(i).should == i + expect(LibTest.ret_s64(i)).to eq(i) end end [ 0, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff ].each do |i| it ":ulong_long call(:ulong_long (#{i}))" do - LibTest.ret_u64(i).should == i + expect(LibTest.ret_u64(i)).to eq(i) end end if FFI::Platform::LONG_SIZE == 32 [ 0, 0x7fffffff, -0x80000000, -1 ].each do |i| it ":long call(:long (#{i}))" do - LibTest.ret_long(i).should == i + expect(LibTest.ret_long(i)).to eq(i) end end [ 0, 0x7fffffff, 0x80000000, 0xffffffff ].each do |i| it ":ulong call(:ulong (#{i}))" do - LibTest.ret_ulong(i).should == i + expect(LibTest.ret_ulong(i)).to eq(i) end end else [ 0, 0x7fffffffffffffff, -0x8000000000000000, -1 ].each do |i| it ":long call(:long (#{i}))" do - LibTest.ret_long(i).should == i + expect(LibTest.ret_long(i)).to eq(i) end end [ 0, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff ].each do |i| it ":ulong call(:ulong (#{i}))" do - LibTest.ret_ulong(i).should == i + expect(LibTest.ret_ulong(i)).to eq(i) end end [ 0.0, 0.1, 1.1, 1.23 ].each do |f| it ":float call(:double (#{f}))" do LibTest.set_float(f) - (LibTest.get_float - f).abs.should < 0.001 + expect((LibTest.get_float - f).abs).to be < 0.001 end end [ 0.0, 0.1, 1.1, 1.23 ].each do |f| it ":double call(:double (#{f}))" do LibTest.set_double(f) - (LibTest.get_double - f).abs.should < 0.001 + expect((LibTest.get_double - f).abs).to be < 0.001 end end end @@ -136,32 +145,32 @@ end describe "Integer parameter range checking" do [ 128, -129 ].each do |i| it ":char call(:char (#{i}))" do - lambda { LibTest.ret_int8_t(i).should == i }.should raise_error + expect { expect(LibTest.ret_int8_t(i)).to eq(i) }.to raise_error end end [ -1, 256 ].each do |i| it ":uchar call(:uchar (#{i}))" do - lambda { LibTest.ret_u_int8_t(i).should == i }.should raise_error + expect { expect(LibTest.ret_u_int8_t(i)).to eq(i) }.to raise_error end end [ 0x8000, -0x8001 ].each do |i| it ":short call(:short (#{i}))" do - lambda { LibTest.ret_int16_t(i).should == i }.should raise_error + expect { expect(LibTest.ret_int16_t(i)).to eq(i) }.to raise_error end end [ -1, 0x10000 ].each do |i| it ":ushort call(:ushort (#{i}))" do - lambda { LibTest.ret_u_int16_t(i).should == i }.should raise_error + expect { expect(LibTest.ret_u_int16_t(i)).to eq(i) }.to raise_error end end [ 0x80000000, -0x80000001 ].each do |i| it ":int call(:int (#{i}))" do - lambda { LibTest.ret_int32_t(i).should == i }.should raise_error + expect { expect(LibTest.ret_int32_t(i)).to eq(i) }.to raise_error end end [ -1, 0x100000000 ].each do |i| it ":ushort call(:ushort (#{i}))" do - lambda { LibTest.ret_u_int32_t(i).should == i }.should raise_error + expect { expect(LibTest.ret_u_int32_t(i)).to eq(i) }.to raise_error end end end @@ -208,11 +217,11 @@ describe "Three different size Integer arguments" do def verify(p, off, t, v) if t == 'f32' - p.get_float32(off).should == v + expect(p.get_float32(off)).to eq(v) elsif t == 'f64' - p.get_float64(off).should == v + expect(p.get_float64(off)).to eq(v) else - p.get_int64(off).should == v + expect(p.get_int64(off)).to eq(v) end end diff --git a/spec/ffi/platform_spec.rb b/spec/ffi/platform_spec.rb index 70022ab..7c56719 100644 --- a/spec/ffi/platform_spec.rb +++ b/spec/ffi/platform_spec.rb @@ -4,94 +4,111 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' 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' + case OS + when "linux" + it "returns 'so'" do + expect(FFI::Platform::LIBSUFFIX).to eq('so') + end + when "windows" + it "returns 'dll'" do + expect(FFI::Platform::LIBSUFFIX).to eq('dll') + end + when "darwin" + it "returns 'dylib'" do + expect(FFI::Platform::LIBSUFFIX).to eq('dylib') + end 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 + case OS + when "linux" + it "returns false" do + expect(FFI::Platform::IS_WINDOWS).to be false + end + when "windows" + it "returns true" do + expect(FFI::Platform::IS_WINDOWS).to be true + end + when "darwin" + it "returns false" do + expect(FFI::Platform::IS_WINDOWS).to be false + end end end describe "FFI::Platform::ARCH" do it "returns the architecture type" do - FFI::Platform::ARCH.should == RbConfig::CONFIG["target_cpu"] + expect(FFI::Platform::ARCH).to eq(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' + case OS + when "linux" + it "returns 'linux' as a string" do + expect(FFI::Platform::OS).to eq('linux') + end + when "windows" + it "returns 'windows' as a string" do + expect(FFI::Platform::OS).to eq('windows') + end + when "darwin" + it "returns 'darwin' as a string" do + expect(FFI::Platform::OS).to eq('darwin') + end end +end - describe "FFI::Platform.windows?" do - it "returns false", if: RbConfig::CONFIG['host_os'].match('linux') do - FFI::Platform.windows?.should == false +describe "FFI::Platform.windows?" do + case OS + when "linux" + it "returns false" do + expect(FFI::Platform.windows?).to be false end - - it "returns true", if: RbConfig::CONFIG['host_os'].match('windows') do - FFI::Platform.windows?.should == true + when "windows" + it "returns true" do + expect(FFI::Platform.windows?).to be true end - - it "returns false", if: RbConfig::CONFIG['host_os'].match('darwin') do - FFI::Platform.windows?.should == false + when "darwin" + it "returns false" do + expect(FFI::Platform.windows?).to be false end end +end - describe "FFI::Platform.mac?" do - it "returns false", if: RbConfig::CONFIG['host_os'].match('linux') do - FFI::Platform.mac?.should == false +describe "FFI::Platform.mac?" do + case OS + when "linux" + it "returns false" do + expect(FFI::Platform.mac?).to be false end - - it "returns false", if: RbConfig::CONFIG['host_os'].match('windows') do - FFI::Platform.mac?.should == false + when "windows" + it "returns false" do + expect(FFI::Platform.mac?).to be false end - - it "returns true", if: RbConfig::CONFIG['host_os'].match('darwin') do - FFI::Platform.mac?.should == true + when "darwin" + it "returns true" do + expect(FFI::Platform.mac?).to be true end end +end - describe "FFI::Platform.unix?" do - it "returns true", if: RbConfig::CONFIG['host_os'].match('linux') do - FFI::Platform.unix?.should == true +describe "FFI::Platform.unix?" do + case OS + when "linux" + it "returns true" do + expect(FFI::Platform.unix?).to be true end - - it "returns false", if: RbConfig::CONFIG['host_os'].match('windows') do - FFI::Platform.unix?.should == false + when "windows" + it "returns false" do + expect(FFI::Platform.unix?).to be false end - - it "returns true", if: RbConfig::CONFIG['host_os'].match('darwin') do - FFI::Platform.unix?.should == true + when "darwin" + it "returns true" do + expect(FFI::Platform.unix?).to be true end end end diff --git a/spec/ffi/pointer_spec.rb b/spec/ffi/pointer_spec.rb index 49968a5..6071c71 100644 --- a/spec/ffi/pointer_spec.rb +++ b/spec/ffi/pointer_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' require 'delegate' module PointerTestLib @@ -30,12 +29,13 @@ describe "Pointer" do @ptr end end + it "Any object implementing #to_ptr can be passed as a :pointer parameter" do memory = FFI::MemoryPointer.new :long_long magic = 0x12345678 memory.put_int32(0, magic) tp = ToPtrTest.new(memory) - PointerTestLib.ptr_ret_int32_t(tp, 0).should == magic + expect(PointerTestLib.ptr_ret_int32_t(tp, 0)).to eq(magic) end class PointerDelegate < DelegateClass(FFI::Pointer) def initialize(ptr) @@ -45,18 +45,21 @@ describe "Pointer" do @ptr end end + it "A DelegateClass(Pointer) can be passed as a :pointer parameter" do memory = FFI::MemoryPointer.new :long_long magic = 0x12345678 memory.put_int32(0, magic) ptr = PointerDelegate.new(memory) - PointerTestLib.ptr_ret_int32_t(ptr, 0).should == magic + expect(PointerTestLib.ptr_ret_int32_t(ptr, 0)).to eq(magic) end + it "Fixnum cannot be used as a Pointer argument" do - lambda { PointerTestLib.ptr_ret_int32(0, 0) }.should raise_error + expect { PointerTestLib.ptr_ret_int32(0, 0) }.to raise_error end + it "Bignum cannot be used as a Pointer argument" do - lambda { PointerTestLib.ptr_ret_int32(0xfee1deadbeefcafebabe, 0) }.should raise_error + expect { PointerTestLib.ptr_ret_int32(0xfee1deadbeefcafebabe, 0) }.to raise_error end describe "pointer type methods" do @@ -64,13 +67,13 @@ describe "Pointer" do it "#read_pointer" do memory = FFI::MemoryPointer.new :pointer PointerTestLib.ptr_set_pointer(memory, 0, PointerTestLib.ptr_from_address(0xdeadbeef)) - memory.read_pointer.address.should == 0xdeadbeef + expect(memory.read_pointer.address).to eq(0xdeadbeef) end it "#write_pointer" do memory = FFI::MemoryPointer.new :pointer memory.write_pointer(PointerTestLib.ptr_from_address(0xdeadbeef)) - PointerTestLib.ptr_ret_pointer(memory, 0).address.should == 0xdeadbeef + expect(PointerTestLib.ptr_ret_pointer(memory, 0).address).to eq(0xdeadbeef) end it "#read_array_of_pointer" do @@ -81,7 +84,7 @@ describe "Pointer" do end array = memory.read_array_of_pointer(values.size) values.each_with_index do |address, j| - array[j].address.should == address + expect(array[j].address).to eq(address) end end @@ -90,23 +93,23 @@ describe "Pointer" do describe 'NULL' do it 'should be obtained using Pointer::NULL constant' do null_ptr = FFI::Pointer::NULL - null_ptr.null?.should be_true + expect(null_ptr).to be_null end it 'should be obtained passing address 0 to constructor' do - FFI::Pointer.new(0).null?.should be_true + expect(FFI::Pointer.new(0)).to be_null end it 'should raise an error when attempting read/write operations on it' do null_ptr = FFI::Pointer::NULL - lambda { null_ptr.read_int }.should raise_error(FFI::NullPointerError) - lambda { null_ptr.write_int(0xff1) }.should raise_error(FFI::NullPointerError) + expect { null_ptr.read_int }.to raise_error(FFI::NullPointerError) + expect { null_ptr.write_int(0xff1) }.to raise_error(FFI::NullPointerError) end it 'returns true when compared with nil' do - (FFI::Pointer::NULL == nil).should be_true + expect((FFI::Pointer::NULL == nil)).to be true end end it "Pointer.size returns sizeof pointer on platform" do - FFI::Pointer.size.should == (FFI::Platform::ADDRESS_SIZE / 8) + expect(FFI::Pointer.size).to eq((FFI::Platform::ADDRESS_SIZE / 8)) end describe "#slice" do @@ -117,22 +120,22 @@ describe "Pointer" do end it "contents of sliced pointer matches original pointer at offset" do - @mptr.slice(4, 4).get_uint(0).should == 0xdeadbeef + expect(@mptr.slice(4, 4).get_uint(0)).to eq(0xdeadbeef) end it "modifying sliced pointer is reflected in original pointer" do @mptr.slice(4, 4).put_uint(0, 0xfee1dead) - @mptr.get_uint(4).should == 0xfee1dead + expect(@mptr.get_uint(4)).to eq(0xfee1dead) end it "access beyond bounds should raise IndexError" do - lambda { @mptr.slice(4, 4).get_int(4) }.should raise_error(IndexError) + expect { @mptr.slice(4, 4).get_int(4) }.to raise_error(IndexError) end end describe "#type_size" do it "should be same as FFI.type_size(type)" do - FFI::MemoryPointer.new(:int, 1).type_size.should == FFI.type_size(:int) + expect(FFI::MemoryPointer.new(:int, 1).type_size).to eq(FFI.type_size(:int)) end end end @@ -166,8 +169,9 @@ describe "AutoPointer" do class AutoPointerSubclass < FFI::AutoPointer def self.release(ptr); end end + it "cleanup via default release method" do - AutoPointerSubclass.should_receive(:release).at_least(loop_count-wiggle_room).times + expect(AutoPointerSubclass).to receive(:release).at_least(loop_count-wiggle_room).times AutoPointerTestHelper.reset loop_count.times do # note that if we called @@ -187,7 +191,7 @@ describe "AutoPointer" do # # we'd have a reference to the pointer and it would # never get GC'd. - AutoPointerTestHelper.should_receive(:release).at_least(loop_count-wiggle_room).times + expect(AutoPointerTestHelper).to receive(:release).at_least(loop_count-wiggle_room).times AutoPointerTestHelper.reset loop_count.times do FFI::AutoPointer.new(PointerTestLib.ptr_from_address(magic), @@ -197,7 +201,7 @@ describe "AutoPointer" do end it "cleanup when passed a method" do - AutoPointerTestHelper.should_receive(:release).at_least(loop_count-wiggle_room).times + expect(AutoPointerTestHelper).to receive(:release).at_least(loop_count-wiggle_room).times AutoPointerTestHelper.reset loop_count.times do FFI::AutoPointer.new(PointerTestLib.ptr_from_address(magic), @@ -207,7 +211,7 @@ describe "AutoPointer" do end it "can be used as the return type of a function" do - lambda do + expect do Module.new do extend FFI::Library ffi_lib TestLibrary::PATH @@ -216,18 +220,18 @@ describe "AutoPointer" do end attach_function :ptr_from_address, [ FFI::Platform::ADDRESS_SIZE == 32 ? :uint : :ulong_long ], CustomAutoPointer end - end.should_not raise_error + end.not_to raise_error end describe "#new" do it "MemoryPointer argument raises TypeError" do - lambda { FFI::AutoPointer.new(FFI::MemoryPointer.new(:int))}.should raise_error(::TypeError) + expect { FFI::AutoPointer.new(FFI::MemoryPointer.new(:int))}.to raise_error(::TypeError) end it "AutoPointer argument raises TypeError" do - lambda { AutoPointerSubclass.new(AutoPointerSubclass.new(PointerTestLib.ptr_from_address(0))) }.should raise_error(::TypeError) + expect { AutoPointerSubclass.new(AutoPointerSubclass.new(PointerTestLib.ptr_from_address(0))) }.to raise_error(::TypeError) end it "Buffer argument raises TypeError" do - lambda { FFI::AutoPointer.new(FFI::Buffer.new(:int))}.should raise_error(::TypeError) + expect { FFI::AutoPointer.new(FFI::Buffer.new(:int))}.to raise_error(::TypeError) end end @@ -238,13 +242,13 @@ describe "AutoPointer" do end it "should be true by default" do - ptr_class.new(FFI::Pointer.new(0xdeadbeef)).autorelease?.should be_true + expect(ptr_class.new(FFI::Pointer.new(0xdeadbeef)).autorelease?).to be true end it "should return false when autorelease=(false)" do ptr = ptr_class.new(FFI::Pointer.new(0xdeadbeef)) ptr.autorelease = false - ptr.autorelease?.should be_false + expect(ptr.autorelease?).to be false end end @@ -255,7 +259,7 @@ describe "AutoPointer" do it "type_size of AutoPointer should match wrapped Pointer" do aptr = ptr_class.new(FFI::Pointer.new(:int, 0xdeadbeef)) - aptr.type_size.should == FFI.type_size(:int) + expect(aptr.type_size).to eq(FFI.type_size(:int)) end it "[] offset should match wrapped Pointer" do @@ -263,8 +267,8 @@ describe "AutoPointer" do aptr = ptr_class.new(FFI::Pointer.new(:int, mptr)) aptr[0].write_uint(0xfee1dead) aptr[1].write_uint(0xcafebabe) - mptr[0].read_uint.should == 0xfee1dead - mptr[1].read_uint.should == 0xcafebabe + expect(mptr[0].read_uint).to eq(0xfee1dead) + expect(mptr[1].read_uint).to eq(0xcafebabe) end end end diff --git a/spec/ffi/rbx/attach_function_spec.rb b/spec/ffi/rbx/attach_function_spec.rb index ee5b341..e90f535 100644 --- a/spec/ffi/rbx/attach_function_spec.rb +++ b/spec/ffi/rbx/attach_function_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' class Timeval < FFI::Struct layout :tv_sec, :ulong, 0, :tv_usec, :ulong, 4 @@ -21,14 +20,14 @@ describe FFI::Library, "#attach_function" do it "correctly returns a value for gettimeofday" do t = Timeval.new time = LibC.gettimeofday(t.pointer, nil) - time.should be_kind_of(Integer) + expect(time).to be_kind_of(Integer) end it "correctly populates a struct for gettimeofday" do t = Timeval.new - time = LibC.gettimeofday(t.pointer, nil) - t[:tv_sec].should be_kind_of(Numeric) - t[:tv_usec].should be_kind_of(Numeric) + LibC.gettimeofday(t.pointer, nil) + expect(t[:tv_sec]).to be_kind_of(Numeric) + expect(t[:tv_usec]).to be_kind_of(Numeric) end end diff --git a/spec/ffi/rbx/memory_pointer_spec.rb b/spec/ffi/rbx/memory_pointer_spec.rb index edf5b3d..0fe3597 100644 --- a/spec/ffi/rbx/memory_pointer_spec.rb +++ b/spec/ffi/rbx/memory_pointer_spec.rb @@ -5,7 +5,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' module CTest extend FFI::Library @@ -17,58 +16,58 @@ end describe "MemoryPointer" do it "makes a pointer from a string" do m = FFI::MemoryPointer.from_string("FFI is Awesome") - m.total.should == 15 - m.type_size.should == 1 + expect(m.total).to eq(15) + expect(m.type_size).to eq(1) 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 m = FFI::MemoryPointer.from_string("ぱんだ") - m.total.should == 10 - m.type_size.should == 1 + expect(m.total).to eq(10) + expect(m.type_size).to eq(1) end it "reads back a string" do m = FFI::MemoryPointer.from_string("FFI is Awesome") - m.read_string.should == "FFI is Awesome" + expect(m.read_string).to eq("FFI is Awesome") end it "makes a pointer for a certain number of bytes" do m = FFI::MemoryPointer.new(8) m.write_array_of_int([1,2]) - m.read_array_of_int(2).should == [1,2] + expect(m.read_array_of_int(2)).to eq([1,2]) end it "allows access to an element of the pointer (as an array)" do m = FFI::MemoryPointer.new(:int, 2) m.write_array_of_int([1,2]) - m[0].read_int.should == 1 - m[1].read_int.should == 2 + expect(m[0].read_int).to eq(1) + expect(m[1].read_int).to eq(2) end it "allows writing as an int" do m = FFI::MemoryPointer.new(:int) m.write_int(1) - m.read_int.should == 1 + expect(m.read_int).to eq(1) end it "allows writing as a long" do m = FFI::MemoryPointer.new(:long) m.write_long(10) - m.read_long.should == 10 + expect(m.read_long).to eq(10) end it "raises an error if you try putting a long into a pointer of size 1" do m = FFI::MemoryPointer.new(1) - lambda { m.write_long(10) }.should raise_error + expect { m.write_long(10) }.to raise_error end it "raises an error if you try putting an int into a pointer of size 1" do m = FFI::MemoryPointer.new(1) - lambda { m.write_int(10) }.should raise_error + expect { m.write_int(10) }.to raise_error end # it "does not raise IndexError for opaque pointers" do # m = FFI::MemoryPointer.new(8) @@ -81,41 +80,44 @@ describe "MemoryPointer" do it "makes a pointer for a certain type" do m = FFI::MemoryPointer.new(:int) m.write_int(10) - m.read_int.should == 10 + expect(m.read_int).to eq(10) end it "makes a memory pointer for a number of a certain type" do m = FFI::MemoryPointer.new(:int, 2) m.write_array_of_int([1,2]) - m.read_array_of_int(2).should == [1,2] + expect(m.read_array_of_int(2)).to eq([1,2]) end it "makes a pointer for an object responding to #size" do m = FFI::MemoryPointer.new(Struct.new(:size).new(8)) m.write_array_of_int([1,2]) - m.read_array_of_int(2).should == [1,2] + expect(m.read_array_of_int(2)).to eq([1,2]) end it "makes a pointer for a number of an object responding to #size" do m = FFI::MemoryPointer.new(Struct.new(:size).new(4), 2) m.write_array_of_int([1,2]) - m.read_array_of_int(2).should == [1,2] + expect(m.read_array_of_int(2)).to eq([1,2]) end + it "MemoryPointer#address returns correct value" do m = FFI::MemoryPointer.new(:long_long) magic = 0x12345678 m.write_long(magic) - m.read_pointer.address.should == magic + expect(m.read_pointer.address).to eq(magic) end + it "MemoryPointer#null? returns true for zero value" do m = FFI::MemoryPointer.new(:long_long) m.write_long(0) - m.read_pointer.null?.should == true + expect(m.read_pointer.null?).to be true end + it "MemoryPointer#null? returns false for non-zero value" do m = FFI::MemoryPointer.new(:long_long) m.write_long(0x12345678) - m.read_pointer.null?.should == false + expect(m.read_pointer.null?).to be false end it "initialize with block should execute block" do @@ -123,6 +125,6 @@ describe "MemoryPointer" do FFI::MemoryPointer.new(:pointer) do |ptr| block_executed = true end - block_executed.should be_true + expect(block_executed).to be true end end diff --git a/spec/ffi/rbx/spec_helper.rb b/spec/ffi/rbx/spec_helper.rb index bd3a667..6e009d8 100644 --- a/spec/ffi/rbx/spec_helper.rb +++ b/spec/ffi/rbx/spec_helper.rb @@ -4,4 +4,3 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "../spec_helper")) -require 'ffi' diff --git a/spec/ffi/rbx/struct_spec.rb b/spec/ffi/rbx/struct_spec.rb index b0c2793..a7ed85b 100644 --- a/spec/ffi/rbx/struct_spec.rb +++ b/spec/ffi/rbx/struct_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' class Timeval < FFI::Struct layout :tv_sec, :ulong, 0, :tv_usec, :ulong, 4 @@ -14,6 +13,6 @@ describe FFI::Struct do it "allows setting fields" do t = Timeval.new t[:tv_sec] = 12 - t[:tv_sec].should == 12 + expect(t[:tv_sec]).to eq(12) end end diff --git a/spec/ffi/spec_helper.rb b/spec/ffi/spec_helper.rb index 3f472d8..88d269e 100644 --- a/spec/ffi/spec_helper.rb +++ b/spec/ffi/spec_helper.rb @@ -4,6 +4,7 @@ # require 'rbconfig' +require 'fileutils' require 'ffi' CPU = case RbConfig::CONFIG['host_cpu'].downcase @@ -52,18 +53,14 @@ 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__) - + if !File.exist?(lib) + output = nil FileUtils.cd(dir) do output = system(*%{#{system('which gmake >/dev/null') && 'gmake' || 'make'} CPU=#{CPU} OS=#{OS} }.tap{|x| puts x.inspect}) end if $?.exitstatus != 0 + puts "ERROR:\n#{output}" raise "Unable to compile \"#{lib}\"" end end diff --git a/spec/ffi/string_spec.rb b/spec/ffi/string_spec.rb index 36d70d2..fac11f0 100644 --- a/spec/ffi/string_spec.rb +++ b/spec/ffi/string_spec.rb @@ -4,8 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' - describe "String tests" do include FFI module StrLibTest @@ -16,40 +14,46 @@ describe "String tests" do attach_function :string_dummy, [ :string ], :void attach_function :string_null, [ ], :string end + it "MemoryPointer#get_string returns a tainted string" do mp = FFI::MemoryPointer.new 1024 mp.put_string(0, "test\0") str = mp.get_string(0) - str.tainted?.should == true + expect(str.tainted?).to be true end + it "String returned by a method is tainted" do mp = FFI::MemoryPointer.new :pointer sp = FFI::MemoryPointer.new 1024 sp.put_string(0, "test") mp.put_pointer(0, sp) str = StrLibTest.ptr_ret_pointer(mp, 0) - str.should == "test" - str.tainted?.should == true + expect(str).to eq("test") + expect(str).to be_tainted end + it "Poison null byte raises error" do s = "123\0abc" - lambda { StrLibTest.string_equals(s, s) }.should raise_error + expect { StrLibTest.string_equals(s, s) }.to raise_error end + it "Tainted String parameter should throw a SecurityError" do $SAFE = 1 str = "test" str.taint begin - LibTest.string_equals(str, str).should == false + expect(LibTest.string_equals(str, str)).to be false rescue SecurityError end end if false it "casts nil as NULL pointer" do - StrLibTest.string_dummy(nil).should == nil + expect(StrLibTest.string_dummy(nil)).to be_nil end + it "return nil for NULL char*" do - StrLibTest.string_null.should == nil + expect(StrLibTest.string_null).to be_nil end + it "reads an array of strings until encountering a NULL pointer" do strings = ["foo", "bar", "baz", "testing", "ffi"] ptrary = FFI::MemoryPointer.new(:pointer, 6) @@ -60,8 +64,9 @@ describe "String tests" do end ary.insert(3, nil) ptrary.write_array_of_pointer(ary) - ptrary.get_array_of_string(0).should == ["foo", "bar", "baz"] + expect(ptrary.get_array_of_string(0)).to eq(["foo", "bar", "baz"]) end + it "reads an array of strings of the size specified, substituting nil when a pointer is NULL" do strings = ["foo", "bar", "baz", "testing", "ffi"] ptrary = FFI::MemoryPointer.new(:pointer, 6) @@ -72,8 +77,9 @@ describe "String tests" do end ary.insert(2, nil) ptrary.write_array_of_pointer(ary) - ptrary.get_array_of_string(0, 4).should == ["foo", "bar", nil, "baz"] + expect(ptrary.get_array_of_string(0, 4)).to eq(["foo", "bar", nil, "baz"]) end + it "reads an array of strings, taking a memory offset parameter" do strings = ["foo", "bar", "baz", "testing", "ffi"] ptrary = FFI::MemoryPointer.new(:pointer, 5) @@ -83,8 +89,9 @@ describe "String tests" do a << f end ptrary.write_array_of_pointer(ary) - ptrary.get_array_of_string(2 * FFI.type_size(:pointer), 3).should == ["baz", "testing", "ffi"] + expect(ptrary.get_array_of_string(2 * FFI.type_size(:pointer), 3)).to eq(["baz", "testing", "ffi"]) end + it "raises an IndexError when trying to read an array of strings out of bounds" do strings = ["foo", "bar", "baz", "testing", "ffi"] ptrary = FFI::MemoryPointer.new(:pointer, 5) @@ -94,8 +101,9 @@ describe "String tests" do a << f end ptrary.write_array_of_pointer(ary) - lambda { ptrary.get_array_of_string(0, 6) }.should raise_error + expect { ptrary.get_array_of_string(0, 6) }.to raise_error end + it "raises an IndexError when trying to read an array of strings using a negative offset" do strings = ["foo", "bar", "baz", "testing", "ffi"] ptrary = FFI::MemoryPointer.new(:pointer, 5) @@ -105,6 +113,6 @@ describe "String tests" do a << f end ptrary.write_array_of_pointer(ary) - lambda { ptrary.get_array_of_string(-1) }.should raise_error + expect { ptrary.get_array_of_string(-1) }.to raise_error end end diff --git a/spec/ffi/strptr_spec.rb b/spec/ffi/strptr_spec.rb index 5bbcfd9..a6400f4 100644 --- a/spec/ffi/strptr_spec.rb +++ b/spec/ffi/strptr_spec.rb @@ -4,12 +4,11 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' describe "functions returning :strptr" do it "can attach function with :strptr return type" do - lambda do + expect do Module.new do extend FFI::Library ffi_lib FFI::Library::LIBC @@ -19,7 +18,7 @@ describe "functions returning :strptr" do attach_function :_strdup, [ :string ], :strptr end end - end.should_not raise_error + end.not_to raise_error end module StrPtr @@ -35,17 +34,17 @@ describe "functions returning :strptr" do it "should return [ String, Pointer ]" do result = StrPtr.strdup("test") - result[0].is_a?(String).should be_true - result[1].is_a?(FFI::Pointer).should be_true + expect(result[0].is_a?(String)).to be true + expect(result[1].is_a?(FFI::Pointer)).to be true end it "should return the correct value" do result = StrPtr.strdup("test") - result[0].should == "test" + expect(result[0]).to eq("test") end it "should return non-NULL pointer" do result = StrPtr.strdup("test") - result[1].null?.should be_false + expect(result[1]).not_to be_null end end diff --git a/spec/ffi/struct_by_ref_spec.rb b/spec/ffi/struct_by_ref_spec.rb index a13b0aa..0858423 100644 --- a/spec/ffi/struct_by_ref_spec.rb +++ b/spec/ffi/struct_by_ref_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' describe FFI::Struct, ' by_ref' do before :all do @@ -22,15 +21,15 @@ describe FFI::Struct, ' by_ref' do it "should accept instances of exact struct class" do s = @struct_class.new - @api.struct_test(s).should == s.pointer + expect(@api.struct_test(s)).to eq(s.pointer) end it "should accept nil" do - @api.struct_test(nil).should == nil + expect(@api.struct_test(nil)).to be_null end it "should reject other types" do - lambda { @api.struct_test('test').should == nil }.should raise_error(TypeError) + expect { expect(@api.struct_test('test')).to be_nil }.to raise_error(TypeError) end it "should reject instances of other struct classes" do @@ -38,7 +37,7 @@ describe FFI::Struct, ' by_ref' do layout :a, :pointer end - lambda { @api.struct_test(other_class.new) }.should raise_error(TypeError) + expect { @api.struct_test(other_class.new) }.to raise_error(TypeError) end end diff --git a/spec/ffi/struct_callback_spec.rb b/spec/ffi/struct_callback_spec.rb index 704be65..7cab301 100644 --- a/spec/ffi/struct_callback_spec.rb +++ b/spec/ffi/struct_callback_spec.rb @@ -4,11 +4,10 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' describe FFI::Struct, ' with inline callback functions' do it 'should be able to define inline callback field' do - module CallbackMember1 + expect(module CallbackMember1 extend FFI::Library ffi_lib TestLibrary::PATH DUMMY_CB = callback :dummy_cb, [ :int ], :int @@ -20,8 +19,9 @@ 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.should be_an_instance_of FFI::Function + end).to be_an_instance_of FFI::Function end + it 'should take methods as callbacks' do module CallbackMember2 extend FFI::Library @@ -43,7 +43,7 @@ describe FFI::Struct, ' with inline callback functions' do ts = CallbackMember2::TestStruct.new ts[:add] = StructCallbacks.method(:add) - CallbackMember2.struct_call_add_cb(ts, 1, 2).should == 3 + expect(CallbackMember2.struct_call_add_cb(ts, 1, 2)).to eq(3) end it 'should return callable object from []' do @@ -63,8 +63,7 @@ describe FFI::Struct, ' with inline callback functions' do add = Proc.new { |a,b| a+b} s[:add] = add fn = s[:add] - fn.respond_to?(:call).should be_true - fn.call(1, 2).should == 3 + expect(fn.respond_to?(:call)).to be true + expect(fn.call(1, 2)).to eq(3) end end - diff --git a/spec/ffi/struct_initialize_spec.rb b/spec/ffi/struct_initialize_spec.rb index e62b5e4..beb2477 100644 --- a/spec/ffi/struct_initialize_spec.rb +++ b/spec/ffi/struct_initialize_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' describe FFI::Struct, ' with an initialize function' do it "should call the initialize function" do @@ -16,7 +15,7 @@ describe FFI::Struct, ' with an initialize function' do self.magic = 42 end end - StructWithInitialize.new.magic.should == 42 + expect(StructWithInitialize.new.magic).to eq(42) end end @@ -31,6 +30,6 @@ describe FFI::ManagedStruct, ' with an initialize function' do end def self.release;end end - ManagedStructWithInitialize.new.magic.should == 42 + expect(ManagedStructWithInitialize.new.magic).to eq(42) end end diff --git a/spec/ffi/struct_packed_spec.rb b/spec/ffi/struct_packed_spec.rb index 492d175..8132be7 100644 --- a/spec/ffi/struct_packed_spec.rb +++ b/spec/ffi/struct_packed_spec.rb @@ -4,49 +4,47 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' describe FFI::Struct do it "packed :char followed by :int should have size of 5" do - Class.new(FFI::Struct) do + expect(Class.new(FFI::Struct) do packed layout :c, :char, :i, :int - end.size.should == 5 + end.size).to eq(5) end it "packed :char followed by :int should have alignment of 1" do - Class.new(FFI::Struct) do + expect(Class.new(FFI::Struct) do packed layout :c, :char, :i, :int - end.alignment.should == 1 + end.alignment).to eq(1) end it "packed(2) :char followed by :int should have size of 6" do - Class.new(FFI::Struct) do + expect(Class.new(FFI::Struct) do packed 2 layout :c, :char, :i, :int - end.size.should == 6 + end.size).to eq(6) end it "packed(2) :char followed by :int should have alignment of 2" do - Class.new(FFI::Struct) do + expect(Class.new(FFI::Struct) do packed 2 layout :c, :char, :i, :int - end.alignment.should == 2 + end.alignment).to eq(2) end it "packed :short followed by int should have size of 6" do - Class.new(FFI::Struct) do + expect(Class.new(FFI::Struct) do packed layout :s, :short, :i, :int - end.size.should == 6 + end.size).to eq(6) end it "packed :short followed by int should have alignment of 1" do - Class.new(FFI::Struct) do + expect(Class.new(FFI::Struct) do packed layout :s, :short, :i, :int - end.alignment.should == 1 + end.alignment).to eq(1) end - end diff --git a/spec/ffi/struct_spec.rb b/spec/ffi/struct_spec.rb index aa4fa40..6c03277 100644 --- a/spec/ffi/struct_spec.rb +++ b/spec/ffi/struct_spec.rb @@ -4,7 +4,36 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' + +describe "Struct aligns fields correctly" do + it "char, followed by an int" do + class CIStruct < FFI::Struct + layout :c => :char, :i => :int + end + expect(CIStruct.size).to eq(8) + end + + it "short, followed by an int" do + class SIStruct < FFI::Struct + layout :s => :short, :i => :int + end + expect(SIStruct.size).to eq(8) + end + + it "int, followed by an int" do + class IIStruct < FFI::Struct + layout :i1 => :int, :i => :int + end + expect(IIStruct.size).to eq(8) + end + + it "long long, followed by an int" do + class LLIStruct < FFI::Struct + layout :l => :long_long, :i => :int + end + expect(LLIStruct.size).to eq(FFI::TYPE_UINT64.alignment == 4 ? 12 : 16) + end +end describe "Struct tests" do StructTypes = { @@ -38,6 +67,7 @@ describe "Struct tests" do class StringMember < FFI::Struct layout :string, :string end + it "Struct#[:pointer]" do magic = 0x12345678 mp = FFI::MemoryPointer.new :long @@ -45,8 +75,9 @@ describe "Struct tests" do smp = FFI::MemoryPointer.new :pointer smp.put_pointer(0, mp) s = PointerMember.new smp - s[:pointer].should == mp + expect(s[:pointer]).to eq(mp) end + it "Struct#[:pointer].nil? for NULL value" do magic = 0x12345678 mp = FFI::MemoryPointer.new :long @@ -54,8 +85,9 @@ describe "Struct tests" do smp = FFI::MemoryPointer.new :pointer smp.put_pointer(0, nil) s = PointerMember.new smp - s[:pointer].null?.should == true + expect(s[:pointer].null?).to be true end + it "Struct#[:pointer]=" do magic = 0x12345678 mp = FFI::MemoryPointer.new :long @@ -63,19 +95,23 @@ describe "Struct tests" do smp = FFI::MemoryPointer.new :pointer s = PointerMember.new smp s[:pointer] = mp - smp.get_pointer(0).should == mp + expect(smp.get_pointer(0)).to eq(mp) end + it "Struct#[:pointer]=struct" do smp = FFI::MemoryPointer.new :pointer s = PointerMember.new smp - lambda { s[:pointer] = s }.should_not raise_error Exception + expect { s[:pointer] = s }.not_to raise_error Exception + expect { s[:pointer].nil? }.not_to raise_error Exception end + it "Struct#[:pointer]=nil" do smp = FFI::MemoryPointer.new :pointer s = PointerMember.new smp s[:pointer] = nil - smp.get_pointer(0).null?.should == true + expect(smp.get_pointer(0)).to be_null end + it "Struct#[:string]" do magic = "test" mp = FFI::MemoryPointer.new 1024 @@ -83,64 +119,71 @@ describe "Struct tests" do smp = FFI::MemoryPointer.new :pointer smp.put_pointer(0, mp) s = StringMember.new smp - s[:string].should == magic + expect(s[:string]).to eq(magic) end + it "Struct#[:string].nil? for NULL value" do smp = FFI::MemoryPointer.new :pointer smp.put_pointer(0, nil) s = StringMember.new smp - s[:string].nil?.should == true + expect(s[:string]).to be_nil end + it "Struct#layout works with :name, :type pairs" do class PairLayout < FFI::Struct layout :a, :int, :b, :long_long end ll_off = (FFI::TYPE_UINT64.alignment == 4 ? 4 : 8) - PairLayout.size.should == (ll_off + 8) + expect(PairLayout.size).to eq((ll_off + 8)) mp = FFI::MemoryPointer.new(PairLayout.size) s = PairLayout.new mp s[:a] = 0x12345678 - mp.get_int(0).should == 0x12345678 + expect(mp.get_int(0)).to eq(0x12345678) s[:b] = 0xfee1deadbeef - mp.get_int64(ll_off).should == 0xfee1deadbeef + expect(mp.get_int64(ll_off)).to eq(0xfee1deadbeef) end + it "Struct#layout works with :name, :type, offset tuples" do class PairLayout < FFI::Struct layout :a, :int, 0, :b, :long_long, 4 end - PairLayout.size.should == (FFI::TYPE_UINT64.alignment == 4 ? 12 : 16) + expect(PairLayout.size).to eq((FFI::TYPE_UINT64.alignment == 4 ? 12 : 16)) mp = FFI::MemoryPointer.new(PairLayout.size) s = PairLayout.new mp s[:a] = 0x12345678 - mp.get_int(0).should == 0x12345678 + expect(mp.get_int(0)).to eq(0x12345678) s[:b] = 0xfee1deadbeef - mp.get_int64(4).should == 0xfee1deadbeef + expect(mp.get_int64(4)).to eq(0xfee1deadbeef) end + it "Struct#layout works with mixed :name,:type and :name,:type,offset" do class MixedLayout < FFI::Struct layout :a, :int, :b, :long_long, 4 end - MixedLayout.size.should == (FFI::TYPE_UINT64.alignment == 4 ? 12 : 16) + expect(MixedLayout.size).to eq((FFI::TYPE_UINT64.alignment == 4 ? 12 : 16)) mp = FFI::MemoryPointer.new(MixedLayout.size) s = MixedLayout.new mp s[:a] = 0x12345678 - mp.get_int(0).should == 0x12345678 + expect(mp.get_int(0)).to eq(0x12345678) s[:b] = 0xfee1deadbeef - mp.get_int64(4).should == 0xfee1deadbeef + expect(mp.get_int64(4)).to eq(0xfee1deadbeef) end - it "Struct#layout withs with a hash of :name => type" do - class HashLayout < FFI::Struct - layout :a => :int, :b => :long_long + 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) + expect(HashLayout.size).to eq(ll_off + 8) + mp = FFI::MemoryPointer.new(HashLayout.size) + s = HashLayout.new mp + s[:a] = 0x12345678 + expect(mp.get_int(0)).to eq(0x12345678) + s[:b] = 0xfee1deadbeef + expect(mp.get_int64(ll_off)).to eq(0xfee1deadbeef) 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 @@ -156,104 +199,115 @@ describe "Struct tests" do end s = InitializeWithoutSuper.new(0x1eefbeef, 0xdeadcafebabe) - s[:a].should == 0x1eefbeef - s[:b].should == 0xdeadcafebabe + expect(s[:a]).to eq(0x1eefbeef) + expect(s[:b]).to eq(0xdeadcafebabe) end it "Can use Struct subclass as parameter type" do - module StructParam + expect(module StructParam extend FFI::Library ffi_lib TestLibrary::PATH class TestStruct < FFI::Struct layout :c, :char end attach_function :struct_field_s8, [ TestStruct.in ], :char - end.should be_an_instance_of FFI::Function + end).to be_an_instance_of FFI::Function end + it "Can use Struct subclass as IN parameter type" do - module StructParam2 + expect(module StructParam2 extend FFI::Library ffi_lib TestLibrary::PATH class TestStruct < FFI::Struct layout :c, :char end attach_function :struct_field_s8, [ TestStruct.in ], :char - end.should be_an_instance_of FFI::Function + end).to be_an_instance_of FFI::Function end + it "Can use Struct subclass as OUT parameter type" do - module StructParam3 + expect(module StructParam3 extend FFI::Library ffi_lib TestLibrary::PATH class TestStruct < FFI::Struct layout :c, :char end attach_function :struct_field_s8, [ TestStruct.out ], :char - end.should be_an_instance_of FFI::Function + end).to be_an_instance_of FFI::Function end + it "can be passed directly as a :pointer parameter" do class TestStruct < FFI::Struct layout :i, :int end s = TestStruct.new s[:i] = 0x12 - LibTest.ptr_ret_int32_t(s, 0).should == 0x12 + expect(LibTest.ptr_ret_int32_t(s, 0)).to eq(0x12) end + it ":char member aligned correctly" do class AlignChar < FFI::Struct layout :c, :char, :v, :char end s = AlignChar.new s[:v] = 0x12 - LibTest.struct_align_s8(s.pointer).should == 0x12 + expect(LibTest.struct_align_s8(s.pointer)).to eq(0x12) end + it ":short member aligned correctly" do class AlignShort < FFI::Struct layout :c, :char, :v, :short end s = AlignShort.alloc_in s[:v] = 0x1234 - LibTest.struct_align_s16(s.pointer).should == 0x1234 + expect(LibTest.struct_align_s16(s.pointer)).to eq(0x1234) end + it ":int member aligned correctly" do class AlignInt < FFI::Struct layout :c, :char, :v, :int end s = AlignInt.alloc_in s[:v] = 0x12345678 - LibTest.struct_align_s32(s.pointer).should == 0x12345678 + expect(LibTest.struct_align_s32(s.pointer)).to eq(0x12345678) end + it ":long_long member aligned correctly" do class AlignLongLong < FFI::Struct layout :c, :char, :v, :long_long end s = AlignLongLong.alloc_in s[:v] = 0x123456789abcdef0 - LibTest.struct_align_s64(s.pointer).should == 0x123456789abcdef0 + expect(LibTest.struct_align_s64(s.pointer)).to eq(0x123456789abcdef0) end + it ":long member aligned correctly" do class AlignLong < FFI::Struct layout :c, :char, :v, :long end s = AlignLong.alloc_in s[:v] = 0x12345678 - LibTest.struct_align_long(s.pointer).should == 0x12345678 + expect(LibTest.struct_align_long(s.pointer)).to eq(0x12345678) end + it ":float member aligned correctly" do class AlignFloat < FFI::Struct layout :c, :char, :v, :float end s = AlignFloat.alloc_in s[:v] = 1.23456 - (LibTest.struct_align_f32(s.pointer) - 1.23456).abs.should < 0.00001 + expect((LibTest.struct_align_f32(s.pointer) - 1.23456).abs).to be < 0.00001 end + it ":double member aligned correctly" do class AlignDouble < FFI::Struct layout :c, :char, :v, :double end s = AlignDouble.alloc_in s[:v] = 1.23456789 - (LibTest.struct_align_f64(s.pointer) - 1.23456789).abs.should < 0.00000001 + expect((LibTest.struct_align_f64(s.pointer) - 1.23456789).abs).to be < 0.00000001 end + it ":ulong, :pointer struct" do class ULPStruct < FFI::Struct layout :ul, :ulong, :p, :pointer @@ -261,7 +315,7 @@ describe "Struct tests" do s = ULPStruct.alloc_in s[:ul] = 0xdeadbeef s[:p] = LibTest.ptr_from_address(0x12345678) - s.pointer.get_ulong(0).should == 0xdeadbeef + expect(s.pointer.get_ulong(0)).to eq(0xdeadbeef) end def test_num_field(type, v) klass = Class.new(FFI::Struct) @@ -269,9 +323,9 @@ describe "Struct tests" do s = klass.new s[:v] = v - s.pointer.send("get_#{type.to_s}", 0).should == v + expect(s.pointer.send("get_#{type.to_s}", 0)).to eq(v) s.pointer.send("put_#{type.to_s}", 0, 0) - s[:v].should == 0 + expect(s[:v]).to eq(0) end def self.int_field_test(type, values) values.each do |v| @@ -295,6 +349,7 @@ describe "Struct tests" do int_field_test(:long, [ 0, 0x7fffffffffffffff, -0x8000000000000000, -1 ]) int_field_test(:ulong, [ 0, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff ]) end + it ":float field r/w" do klass = Class.new(FFI::Struct) klass.layout :v, :float, :dummy, :long @@ -302,8 +357,9 @@ describe "Struct tests" do s = klass.new value = 1.23456 s[:v] = value - (s.pointer.get_float(0) - value).abs.should < 0.0001 + expect((s.pointer.get_float(0) - value).abs).to be < 0.0001 end + it ":double field r/w" do klass = Class.new(FFI::Struct) klass.layout :v, :double, :dummy, :long @@ -311,7 +367,7 @@ describe "Struct tests" do s = klass.new value = 1.23456 s[:v] = value - (s.pointer.get_double(0) - value).abs.should < 0.0001 + expect((s.pointer.get_double(0) - value).abs).to be < 0.0001 end module EnumFields extend FFI::Library @@ -326,8 +382,8 @@ describe "Struct tests" do s = EnumFields::TestStruct.new s[:c] = :c3 - s.pointer.get_uint(FFI::Type::INT32.size).should == 30 - s[:c].should == :c3 + expect(s.pointer.get_uint(FFI::Type::INT32.size)).to eq(30) + expect(s[:c]).to eq(:c3) end it "array of :enum field" do @@ -337,11 +393,11 @@ describe "Struct tests" do end EnumFields::TestEnum.symbols.each_with_index do |val, i| - s.pointer.get_uint(FFI::Type::INT32.size * (2 + i)).should == EnumFields::TestEnum[val] + expect(s.pointer.get_uint(FFI::Type::INT32.size * (2 + i))).to eq(EnumFields::TestEnum[val]) end s[:d].each_with_index do |val, i| - val.should == EnumFields::TestEnum.symbols[i] + expect(val).to eq(EnumFields::TestEnum.symbols[i]) end end @@ -357,47 +413,52 @@ describe "Struct tests" do attach_function :struct_call_add_cb, [TestStruct.in, :int, :int], :int attach_function :struct_call_sub_cb, [TestStruct.in, :int, :int], :int end + it "Can have CallbackInfo struct field" do s = CallbackMember::TestStruct.new add_proc = lambda { |a, b| a+b } sub_proc = lambda { |a, b| a-b } s[:add] = add_proc s[:sub] = sub_proc - CallbackMember.struct_call_add_cb(s, 40, 2).should == 42 - CallbackMember.struct_call_sub_cb(s, 44, 2).should == 42 + expect(CallbackMember.struct_call_add_cb(s, 40, 2)).to eq(42) + expect(CallbackMember.struct_call_sub_cb(s, 44, 2)).to eq(42) end + it "Can return its members as a list" do class TestStruct < FFI::Struct layout :a, :int, :b, :int, :c, :int end - TestStruct.members.should include(:a, :b, :c) + expect(TestStruct.members).to include(:a, :b, :c) end + it "Can return its instance members and values as lists" do class TestStruct < FFI::Struct layout :a, :int, :b, :int, :c, :int end s = TestStruct.new - s.members.should include(:a, :b, :c) + expect(s.members).to include(:a, :b, :c) s[:a] = 1 s[:b] = 2 s[:c] = 3 - s.values.should include(1, 2, 3) + expect(s.values).to include(1, 2, 3) end + it 'should return an ordered field/offset pairs array' do class TestStruct < FFI::Struct layout :a, :int, :b, :int, :c, :int end s = TestStruct.new - s.offsets.should == [[:a, 0], [:b, 4], [:c, 8]] - TestStruct.offsets.should == [[:a, 0], [:b, 4], [:c, 8]] + expect(s.offsets).to eq([[:a, 0], [:b, 4], [:c, 8]]) + expect(TestStruct.offsets).to eq([[:a, 0], [:b, 4], [:c, 8]]) end + it "Struct#offset_of returns offset of field within struct" do class TestStruct < FFI::Struct layout :a, :int, :b, :int, :c, :int end - TestStruct.offset_of(:a).should == 0 - TestStruct.offset_of(:b).should == 4 - TestStruct.offset_of(:c).should == 8 + expect(TestStruct.offset_of(:a)).to eq(0) + expect(TestStruct.offset_of(:b)).to eq(4) + expect(TestStruct.offset_of(:c)).to eq(8) end end @@ -422,7 +483,7 @@ describe FFI::Struct, ".layout" do instance = klass.new instance[:number] = 0xA1 - FFISpecs::LibTest.ptr_ret_int32_t(instance, 0).should == 0xA1 + expect(FFISpecs::LibTest.ptr_ret_int32_t(instance, 0)).to eq(0xA1) end end @@ -434,7 +495,7 @@ describe FFI::Struct, ".layout" do instance = FFISpecs::TestStruct.new instance[:number] = 0xA1 - FFISpecs::LibTest.ptr_ret_int32_t(instance, 0).should == 0xA1 + expect(FFISpecs::LibTest.ptr_ret_int32_t(instance, 0)).to eq(0xA1) end it "resolves a type from the enclosing module" do @@ -448,7 +509,7 @@ describe FFI::Struct, ".layout" do instance = FFISpecs::LibTest::TestStruct.new instance[:number] = 0xA1 - FFISpecs::LibTest.ptr_ret_int32_t(instance, 0).should == 0xA1 + expect(FFISpecs::LibTest.ptr_ret_int32_t(instance, 0)).to eq(0xA1) end end end @@ -469,24 +530,29 @@ describe FFI::Struct, ' with a nested struct field' do before do @cs = LibTest::ContainerStruct.new end + it 'should align correctly nested struct field' do @cs[:ns][:i] = 123 - LibTest.struct_align_nested_struct(@cs.to_ptr).should == 123 + expect(LibTest.struct_align_nested_struct(@cs.to_ptr)).to eq(123) end + it 'should correctly calculate Container size (in bytes)' do - LibTest::ContainerStruct.size.should == 8 + expect(LibTest::ContainerStruct.size).to eq(8) end + it 'should return a Struct object when the field is accessed' do - @cs[:ns].is_a?(FFI::Struct).should be_true + expect(@cs[:ns].is_a?(FFI::Struct)).to be true end + it 'should read a value from memory' do @cs = LibTest::ContainerStruct.new(LibTest.struct_make_container_struct(123)) - @cs[:ns][:i].should == 123 + expect(@cs[:ns][:i]).to eq(123) end + it 'should write a value to memory' do @cs = LibTest::ContainerStruct.new(LibTest.struct_make_container_struct(123)) @cs[:ns][:i] = 456 - LibTest.struct_align_nested_struct(@cs.to_ptr).should == 456 + expect(LibTest.struct_align_nested_struct(@cs.to_ptr)).to eq(456) end it 'should be able to assign struct instance to nested field' do @@ -494,8 +560,8 @@ describe FFI::Struct, ' with a nested struct field' do ns = LibTest::NestedStruct.new ns[:i] = 567 cs[:ns] = ns - cs[:ns][:i].should == 567 - LibTest.struct_align_nested_struct(cs.to_ptr).should == 567 + expect(cs[:ns][:i]).to eq(567) + expect(LibTest.struct_align_nested_struct(cs.to_ptr)).to eq(567) end end @@ -519,33 +585,33 @@ describe FFI::Struct, ' with a nested array of structs' do it 'should align correctly nested struct field' do @cs[:ns][0][:i] = 123 - InlineArrayOfStructs.struct_align_nested_struct(@cs.to_ptr).should == 123 + expect(InlineArrayOfStructs.struct_align_nested_struct(@cs.to_ptr)).to eq(123) end it 'should correctly calculate Container size (in bytes)' do - InlineArrayOfStructs::ContainerStruct.size.should == 8 + expect(InlineArrayOfStructs::ContainerStruct.size).to eq(8) end it 'should return a Struct object when the field is accessed' do - @cs[:ns][0].is_a?(FFI::Struct).should be_true + expect(@cs[:ns][0].is_a?(FFI::Struct)).to be true end it 'should read a value from memory' do @cs = InlineArrayOfStructs::ContainerStruct.new(InlineArrayOfStructs.struct_make_container_struct(123)) - @cs[:ns][0][:i].should == 123 + expect(@cs[:ns][0][:i]).to eq(123) end it 'should write a value to memory' do @cs = InlineArrayOfStructs::ContainerStruct.new(InlineArrayOfStructs.struct_make_container_struct(123)) @cs[:ns][0][:i] = 456 - InlineArrayOfStructs.struct_align_nested_struct(@cs.to_ptr).should == 456 + expect(InlineArrayOfStructs.struct_align_nested_struct(@cs.to_ptr)).to eq(456) end it 'should support Enumerable#each' do @cs = InlineArrayOfStructs::ContainerStruct.new(InlineArrayOfStructs.struct_make_container_struct(123)) ints = [] @cs[:ns].each { |s| ints << s[:i] } - ints[0].should == 123 + expect(ints[0]).to eq(123) end end @@ -575,22 +641,22 @@ describe FFI::Struct, ' by value' do it 'return using pre-set values' do s = LibTest.struct_return_s8s32 - s[:s8].should == 0x7f - s[:s32].should == 0x12345678 + expect(s[:s8]).to eq(0x7f) + expect(s[:s32]).to eq(0x12345678) end it 'return using passed in values' do s = LibTest.struct_s8s32_set(123, 456789) - s[:s8].should == 123 - s[:s32].should == 456789 + expect(s[:s8]).to eq(123) + expect(s[:s32]).to eq(456789) end it 'parameter' do s = LibTest::S8S32.new s[:s8] = 0x12 s[:s32] = 0x34567890 - LibTest.struct_s8s32_get_s8(s).should == 0x12 - LibTest.struct_s8s32_get_s32(s).should == 0x34567890 + expect(LibTest.struct_s8s32_get_s8(s)).to eq(0x12) + expect(LibTest.struct_s8s32_get_s32(s)).to eq(0x34567890) end it 'parameter with following s32' do @@ -598,7 +664,7 @@ describe FFI::Struct, ' by value' do s[:s8] = 0x12 s[:s32] = 0x34567890 - LibTest.struct_s8s32_s32_ret_s32(s, 0x1eefdead).should == 0x1eefdead + expect(LibTest.struct_s8s32_s32_ret_s32(s, 0x1eefdead)).to eq(0x1eefdead) end # it 'parameter with following s64' do @@ -615,9 +681,9 @@ describe FFI::Struct, ' by value' do s[:s8] = 0x12 s[:s32] = 0x34567890 out = LibTest::S8S32.new - LibTest.struct_s32_ptr_s32_s8s32_ret_s32(0x1000000, out, 0x1eafbeef, s).should == 0x34567890 - out[:s8].should == s[:s8] - out[:s32].should == s[:s32] + expect(LibTest.struct_s32_ptr_s32_s8s32_ret_s32(0x1000000, out, 0x1eafbeef, s)).to eq(0x34567890) + expect(out[:s8]).to eq(s[:s8]) + expect(out[:s32]).to eq(s[:s32]) end it 'parameter with preceding s32,string,s32' do @@ -625,7 +691,7 @@ describe FFI::Struct, ' by value' do s[:s8] = 0x12 s[:s32] = 0x34567890 out = 0.chr * 32 - LibTest.struct_s32_ptr_s32_s8s32_ret_s32(0x1000000, out, 0x1eafbeef, s).should == 0x34567890 + expect(LibTest.struct_s32_ptr_s32_s8s32_ret_s32(0x1000000, out, 0x1eafbeef, s)).to eq(0x34567890) end it 'parameter, returning struct by value' do @@ -634,15 +700,15 @@ describe FFI::Struct, ' by value' do s[:s32] = 0x34567890 ret = LibTest.struct_s8s32_ret_s8s32(s) - ret[:s8].should == s[:s8] - ret[:s32].should == s[:s32] + expect(ret[:s8]).to eq(s[:s8]) + expect(ret[:s32]).to eq(s[:s32]) end it 'varargs returning a struct' do string = "test" s = LibTest.struct_varargs_ret_struct_string(4, :string, string) - s[:len].should == string.length - s[:bytes].should == string + expect(s[:len]).to eq(string.length) + expect(s[:bytes]).to eq(string) end end @@ -659,27 +725,32 @@ describe FFI::Struct, ' with an array field' do before do @s = LibTest::StructWithArray.new end + it 'should correctly calculate StructWithArray size (in bytes)' do - LibTest::StructWithArray.size.should == 24 + expect(LibTest::StructWithArray.size).to eq(24) end + it 'should read values from memory' do @s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4)) - @s[:a].to_a.should == [0, 1, 2, 3, 4] + expect(@s[:a].to_a).to eq([0, 1, 2, 3, 4]) end # it 'should cache array object for successive calls' do # @s[:a].object_id.should == @s[:a].object_id # end + it 'should return the number of elements in the array field' do @s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4)) - @s[:a].size.should == 5 + expect(@s[:a].size).to eq(5) 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| expect(elem).to eq(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)) - @s[:a].to_ptr.should == LibTest::struct_field_array(@s.to_ptr) + expect(@s[:a].to_ptr).to eq(LibTest::struct_field_array(@s.to_ptr)) end end @@ -698,22 +769,25 @@ describe 'BuggedStruct' do end attach_function :bugged_struct_size, [], :uint end + it 'should return its correct size' do - LibTest::BuggedStruct.size.should == LibTest.bugged_struct_size + expect(LibTest::BuggedStruct.size).to eq(LibTest.bugged_struct_size) end + it "offsets within struct should be correct" do - LibTest::BuggedStruct.offset_of(:visible).should == 0 - LibTest::BuggedStruct.offset_of(:x).should == 4 - LibTest::BuggedStruct.offset_of(:y).should == 8 - LibTest::BuggedStruct.offset_of(:rx).should == 12 - LibTest::BuggedStruct.offset_of(:ry).should == 14 - LibTest::BuggedStruct.offset_of(:order).should == 16 - LibTest::BuggedStruct.offset_of(:size).should == 17 + expect(LibTest::BuggedStruct.offset_of(:visible)).to eq(0) + expect(LibTest::BuggedStruct.offset_of(:x)).to eq(4) + expect(LibTest::BuggedStruct.offset_of(:y)).to eq(8) + expect(LibTest::BuggedStruct.offset_of(:rx)).to eq(12) + expect(LibTest::BuggedStruct.offset_of(:ry)).to eq(14) + expect(LibTest::BuggedStruct.offset_of(:order)).to eq(16) + expect(LibTest::BuggedStruct.offset_of(:size)).to eq(17) end + it 'should return correct field/offset pairs' do - LibTest::BuggedStruct.offsets.sort do |a, b| + expect(LibTest::BuggedStruct.offsets.sort do |a, b| a[1] <=> b[1] - end.should == [[:visible, 0], [:x, 4], [:y, 8], [:rx, 12], [:ry, 14], [:order, 16], [:size, 17]] + end).to eq([[:visible, 0], [:x, 4], [:y, 8], [:rx, 12], [:ry, 14], [:order, 16], [:size, 17]]) end end @@ -723,11 +797,11 @@ describe "Struct allocation" do layout :i, :uint end p = FFI::MemoryPointer.new(S, 2) - p.total.should == 8 - p.type_size.should == 4 + expect(p.total).to eq(8) + expect(p.type_size).to eq(4) p.put_uint(4, 0xdeadbeef) - S.new(p[1])[:i].should == 0xdeadbeef - p[1].address.should == (p[0].address + 4) + expect(S.new(p[1])[:i]).to eq(0xdeadbeef) + expect(p[1].address).to eq((p[0].address + 4)) end it "Buffer.new(Struct, 2)" do @@ -735,53 +809,53 @@ describe "Struct allocation" do layout :i, :uint end p = FFI::Buffer.new(S, 2) - p.total.should == 8 - p.type_size.should == 4 + expect(p.total).to eq(8) + expect(p.type_size).to eq(4) p.put_uint(4, 0xdeadbeef) - S.new(p[1])[:i].should == 0xdeadbeef + expect(S.new(p[1])[:i]).to eq(0xdeadbeef) end it "null? should be true when initialized with NULL pointer" do class S < FFI::Struct layout :i, :uint end - S.new(FFI::Pointer::NULL).null?.should be_true + expect(S.new(FFI::Pointer::NULL)).to be_null end it "null? should be false when initialized with non-NULL pointer" do class S < FFI::Struct layout :i, :uint end - S.new(FFI::MemoryPointer.new(S)).null?.should be_false + expect(S.new(FFI::MemoryPointer.new(S))).not_to be_null end it "supports :bool as a struct member" do - lambda do + expect do c = Class.new(FFI::Struct) do layout :b, :bool end struct = c.new struct[:b] = ! struct[:b] - end.should_not raise_error Exception + end.not_to raise_error Exception end end describe "variable-length arrays" do it "zero length array should be accepted as last field" do - lambda { + expect { Class.new(FFI::Struct) do layout :count, :int, :data, [ :char, 0 ] end - }.should_not raise_error Exception + }.not_to raise_error Exception end it "zero length array before last element should raise error" do - lambda { + expect { Class.new(FFI::Struct) do layout :data, [ :char, 0 ], :count, :int end - }.should raise_error + }.to raise_error end it "can access elements of array" do @@ -791,8 +865,8 @@ describe "variable-length arrays" do s = struct_class.new(FFI::MemoryPointer.new(1024)) s[:data][0] = 0x1eadbeef s[:data][1] = 0x12345678 - s[:data][0].should == 0x1eadbeef - s[:data][1].should == 0x12345678 + expect(s[:data][0]).to eq(0x1eadbeef) + expect(s[:data][1]).to eq(0x12345678) end it "non-variable length array is bounds checked" do @@ -801,8 +875,8 @@ describe "variable-length arrays" do end s = struct_class.new(FFI::MemoryPointer.new(1024)) s[:data][0] = 0x1eadbeef - lambda { s[:data][1] = 0x12345678 }.should raise_error - s[:data][0].should == 0x1eadbeef - lambda { s[:data][1].should == 0x12345678 }.should raise_error + expect { s[:data][1] = 0x12345678 }.to raise_error + expect(s[:data][0]).to eq(0x1eadbeef) + expect { expect(s[:data][1]).to == 0x12345678 }.to raise_error end end diff --git a/spec/ffi/typedef_spec.rb b/spec/ffi/typedef_spec.rb index 6595d90..d73247f 100644 --- a/spec/ffi/typedef_spec.rb +++ b/spec/ffi/typedef_spec.rb @@ -4,8 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' - describe "Custom type definitions" do it "attach_function with custom typedef" do module CustomTypedef @@ -14,8 +12,9 @@ describe "Custom type definitions" do typedef :uint, :fubar_t attach_function :ret_u32, [ :fubar_t ], :fubar_t end - CustomTypedef.ret_u32(0x12345678).should == 0x12345678 + expect(CustomTypedef.ret_u32(0x12345678)).to eq(0x12345678) end + it "variadic invoker with custom typedef" do module VariadicCustomTypedef extend FFI::Library @@ -25,8 +24,9 @@ describe "Custom type definitions" do end buf = FFI::Buffer.new :uint, 10 VariadicCustomTypedef.pack_varargs(buf, "i", :fubar_t, 0x12345678) - buf.get_int64(0).should == 0x12345678 + expect(buf.get_int64(0)).to eq(0x12345678) end + it "Callback with custom typedef parameter" do module CallbackCustomTypedef extend FFI::Library @@ -37,7 +37,7 @@ describe "Custom type definitions" do end i = 0 CallbackCustomTypedef.testCallbackU32rV(0xdeadbeef) { |v| i = v } - i.should == 0xdeadbeef + expect(i).to eq(0xdeadbeef) end module StructCustomTypedef extend FFI::Library @@ -47,14 +47,15 @@ describe "Custom type definitions" do layout :a, :fubar3_t end end + it "Struct with custom typedef field" do s = StructCustomTypedef::S.new s[:a] = 0x12345678 - s.pointer.get_uint(0).should == 0x12345678 + expect(s.pointer.get_uint(0)).to eq(0x12345678) end it "attach_function after a typedef should not reject normal types" do - lambda do + expect do Module.new do extend FFI::Library # enum() will insert a custom typedef called :foo for the enum @@ -69,11 +70,11 @@ describe "Custom type definitions" do attach_function :ptr_ret_int32_t, :ptr_ret___int32_t, [ :string, :foo ], :bar end end - end.should_not raise_error + end.not_to raise_error end it "detects the correct type for size_t" do - lambda do + expect do Module.new do extend FFI::Library ffi_lib "c" @@ -85,6 +86,6 @@ describe "Custom type definitions" do attach_function :read, [:int, :pointer, :size_t], :ssize_t end end - end.should_not raise_error + end.not_to raise_error end end diff --git a/spec/ffi/union_spec.rb b/spec/ffi/union_spec.rb index c416685..45bf7ec 100644 --- a/spec/ffi/union_spec.rb +++ b/spec/ffi/union_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' module LibTest Types = { @@ -37,16 +36,17 @@ describe 'Union' do before do @u = LibTest::TestUnion.new end + it 'should place all the fields at offset 0' do - LibTest::TestUnion.members.all? { |m| LibTest::TestUnion.offset_of(m) == 0 }.should be_true + expect(LibTest::TestUnion.members.all? { |m| LibTest::TestUnion.offset_of(m) == 0 }).to be true end LibTest::Types.each do |k, type| it "should correctly align/write a #{type[0]} value" do @u[type[1]] = type[2] if k == 'f32' or k == 'f64' - (@u[type[1]] - LibTest.send("union_align_#{k}", @u.to_ptr)).abs.should < 0.00001 + expect((@u[type[1]] - LibTest.send("union_align_#{k}", @u.to_ptr)).abs).to be < 0.00001 else - @u[type[1]].should == LibTest.send("union_align_#{k}", @u.to_ptr) + expect(@u[type[1]]).to eq(LibTest.send("union_align_#{k}", @u.to_ptr)) end end end @@ -54,13 +54,14 @@ describe 'Union' do it "should read a #{type[0]} value from memory" do @u = LibTest::TestUnion.new(LibTest.send("union_make_union_with_#{k}", type[2])) if k == 'f32' or k == 'f64' - (@u[type[1]] - type[2]).abs.should < 0.00001 + expect((@u[type[1]] - type[2]).abs).to be < 0.00001 else - @u[type[1]].should == type[2] + expect(@u[type[1]]).to eq(type[2]) end end end + it 'should return a size equals to the size of the biggest field' do - LibTest::TestUnion.size.should == LibTest.union_size + expect(LibTest::TestUnion.size).to eq(LibTest.union_size) end end diff --git a/spec/ffi/variadic_spec.rb b/spec/ffi/variadic_spec.rb index cf5c245..4138280 100644 --- a/spec/ffi/variadic_spec.rb +++ b/spec/ffi/variadic_spec.rb @@ -4,7 +4,6 @@ # require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -require 'ffi' describe "Function with variadic arguments" do module LibTest @@ -19,41 +18,44 @@ describe "Function with variadic arguments" do it "takes enum arguments" do buf = FFI::Buffer.new :long_long, 2 LibTest.pack_varargs(buf, "ii", :int, :c3, :int, :c4) - buf.get_int64(0).should == 42 - buf.get_int64(8).should == 43 + expect(buf.get_int64(0)).to eq(42) + expect(buf.get_int64(8)).to eq(43) end it "returns symbols for enums" do buf = FFI::Buffer.new :long_long, 2 - LibTest.pack_varargs2(buf, :c1, "ii", :int, :c3, :int, :c4).should eql(:c2) + expect(LibTest.pack_varargs2(buf, :c1, "ii", :int, :c3, :int, :c4)).to eq(:c2) end [ 0, 127, -128, -1 ].each do |i| it "call variadic with (:char (#{i})) argument" do buf = FFI::Buffer.new :long_long LibTest.pack_varargs(buf, "c", :char, i) - buf.get_int64(0).should == i + expect(buf.get_int64(0)).to eq(i) end end + [ 0, 0x7f, 0x80, 0xff ].each do |i| it "call variadic with (:uchar (#{i})) argument" do buf = FFI::Buffer.new :long_long LibTest.pack_varargs(buf, "C", :uchar, i) - buf.get_int64(0).should == i + expect(buf.get_int64(0)).to eq(i) end end + [ 0, 1.234567, 9.87654321 ].each do |v| it "call variadic with (:float (#{v})) argument" do buf = FFI::Buffer.new :long_long LibTest.pack_varargs(buf, "f", :float, v.to_f) - buf.get_float64(0).should == v + expect(buf.get_float64(0)).to eq(v) end end + [ 0, 1.234567, 9.87654321 ].each do |v| it "call variadic with (:double (#{v})) argument" do buf = FFI::Buffer.new :long_long LibTest.pack_varargs(buf, "f", :double, v.to_f) - buf.get_float64(0).should == v + expect(buf.get_float64(0)).to eq(v) end end @@ -71,6 +73,7 @@ describe "Function with variadic arguments" do '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, @@ -80,9 +83,9 @@ describe "Function with variadic arguments" do def verify(p, off, v) if v.kind_of?(Float) - p.get_float64(off).should == v + expect(p.get_float64(off)).to eq(v) else - p.get_int64(off).should == v + expect(p.get_int64(off)).to eq(v) end end diff --git a/spec/spec.opts b/spec/spec.opts index 4cc9a8a..60a0245 100644 --- a/spec/spec.opts +++ b/spec/spec.opts @@ -1,3 +1,4 @@ --color +-w --format documentation |