diff options
Diffstat (limited to 'spec/ruby/optional/capi/ext')
21 files changed, 431 insertions, 177 deletions
diff --git a/spec/ruby/optional/capi/ext/array_spec.c b/spec/ruby/optional/capi/ext/array_spec.c index 2347798bb4..628c4df9d7 100644 --- a/spec/ruby/optional/capi/ext/array_spec.c +++ b/spec/ruby/optional/capi/ext/array_spec.c @@ -196,6 +196,7 @@ static VALUE copy_ary(RB_BLOCK_CALL_FUNC_ARGLIST(el, new_ary)) { return rb_ary_push(new_ary, el); } +#ifndef RUBY_VERSION_IS_4_0 static VALUE array_spec_rb_iterate(VALUE self, VALUE ary) { VALUE new_ary = rb_ary_new(); @@ -203,6 +204,7 @@ static VALUE array_spec_rb_iterate(VALUE self, VALUE ary) { return new_ary; } +#endif static VALUE array_spec_rb_block_call(VALUE self, VALUE ary) { VALUE new_ary = rb_ary_new(); @@ -216,6 +218,7 @@ static VALUE sub_pair(RB_BLOCK_CALL_FUNC_ARGLIST(el, holder)) { return rb_ary_push(holder, rb_ary_entry(el, 1)); } +#ifndef RUBY_VERSION_IS_4_0 static VALUE each_pair(VALUE obj) { return rb_funcall(obj, rb_intern("each_pair"), 0); } @@ -227,6 +230,7 @@ static VALUE array_spec_rb_iterate_each_pair(VALUE self, VALUE obj) { return new_ary; } +#endif static VALUE array_spec_rb_block_call_each_pair(VALUE self, VALUE obj) { VALUE new_ary = rb_ary_new(); @@ -241,10 +245,12 @@ static VALUE iter_yield(RB_BLOCK_CALL_FUNC_ARGLIST(el, ary)) { return Qnil; } +#ifndef RUBY_VERSION_IS_4_0 static VALUE array_spec_rb_iterate_then_yield(VALUE self, VALUE obj) { rb_iterate(rb_each, obj, iter_yield, obj); return Qnil; } +#endif static VALUE array_spec_rb_block_call_then_yield(VALUE self, VALUE obj) { rb_block_call(obj, rb_intern("each"), 0, 0, iter_yield, obj); @@ -308,9 +314,11 @@ void Init_array_spec(void) { rb_define_method(cls, "rb_ary_plus", array_spec_rb_ary_plus, 2); rb_define_method(cls, "rb_ary_unshift", array_spec_rb_ary_unshift, 2); rb_define_method(cls, "rb_assoc_new", array_spec_rb_assoc_new, 2); +#ifndef RUBY_VERSION_IS_4_0 rb_define_method(cls, "rb_iterate", array_spec_rb_iterate, 1); rb_define_method(cls, "rb_iterate_each_pair", array_spec_rb_iterate_each_pair, 1); rb_define_method(cls, "rb_iterate_then_yield", array_spec_rb_iterate_then_yield, 1); +#endif rb_define_method(cls, "rb_block_call", array_spec_rb_block_call, 1); rb_define_method(cls, "rb_block_call_each_pair", array_spec_rb_block_call_each_pair, 1); rb_define_method(cls, "rb_block_call_then_yield", array_spec_rb_block_call_then_yield, 1); diff --git a/spec/ruby/optional/capi/ext/class_spec.c b/spec/ruby/optional/capi/ext/class_spec.c index c13f02ecf2..8ac0e7a93f 100644 --- a/spec/ruby/optional/capi/ext/class_spec.c +++ b/spec/ruby/optional/capi/ext/class_spec.c @@ -65,11 +65,9 @@ static VALUE class_spec_rb_class_new_instance(VALUE self, VALUE args, VALUE klas return rb_class_new_instance(RARRAY_LENINT(args), RARRAY_PTR(args), klass); } -#ifdef RUBY_VERSION_IS_3_0 static VALUE class_spec_rb_class_new_instance_kw(VALUE self, VALUE args, VALUE klass) { return rb_class_new_instance_kw(RARRAY_LENINT(args), RARRAY_PTR(args), klass, RB_PASS_KEYWORDS); } -#endif static VALUE class_spec_rb_class_real(VALUE self, VALUE object) { if (rb_type_p(object, T_FIXNUM)) { @@ -160,9 +158,7 @@ void Init_class_spec(void) { rb_define_method(cls, "rb_class_private_instance_methods", class_spec_rb_class_private_instance_methods, -1); rb_define_method(cls, "rb_class_new", class_spec_rb_class_new, 1); rb_define_method(cls, "rb_class_new_instance", class_spec_rb_class_new_instance, 2); -#ifdef RUBY_VERSION_IS_3_0 rb_define_method(cls, "rb_class_new_instance_kw", class_spec_rb_class_new_instance_kw, 2); -#endif rb_define_method(cls, "rb_class_real", class_spec_rb_class_real, 1); rb_define_method(cls, "rb_class_get_superclass", class_spec_rb_class_get_superclass, 1); rb_define_method(cls, "rb_class_superclass", class_spec_rb_class_superclass, 1); diff --git a/spec/ruby/optional/capi/ext/constants_spec.c b/spec/ruby/optional/capi/ext/constants_spec.c index 9aee8db37f..05819ea476 100644 --- a/spec/ruby/optional/capi/ext/constants_spec.c +++ b/spec/ruby/optional/capi/ext/constants_spec.c @@ -14,9 +14,6 @@ defconstfunc(rb_cBinding) defconstfunc(rb_cClass) defconstfunc(rb_cComplex) defconstfunc(rb_mComparable) -#ifndef RUBY_VERSION_IS_3_0 -defconstfunc(rb_cData) -#endif defconstfunc(rb_cDir) defconstfunc(rb_cEncoding) defconstfunc(rb_mEnumerable) @@ -97,9 +94,6 @@ void Init_constants_spec(void) { rb_define_method(cls, "rb_cClass", constants_spec_rb_cClass, 0); rb_define_method(cls, "rb_cComplex", constants_spec_rb_cComplex, 0); rb_define_method(cls, "rb_mComparable", constants_spec_rb_mComparable, 0); - #ifndef RUBY_VERSION_IS_3_0 - rb_define_method(cls, "rb_cData", constants_spec_rb_cData, 0); - #endif rb_define_method(cls, "rb_cDir", constants_spec_rb_cDir, 0); rb_define_method(cls, "rb_cEncoding", constants_spec_rb_cEncoding, 0); rb_define_method(cls, "rb_mEnumerable", constants_spec_rb_mEnumerable, 0); diff --git a/spec/ruby/optional/capi/ext/digest_spec.c b/spec/ruby/optional/capi/ext/digest_spec.c new file mode 100644 index 0000000000..65c8defa20 --- /dev/null +++ b/spec/ruby/optional/capi/ext/digest_spec.c @@ -0,0 +1,168 @@ +#include "ruby.h" +#include "rubyspec.h" + +#include "ruby/digest.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define DIGEST_LENGTH 20 +#define BLOCK_LENGTH 40 + +const char *init_string = "Initialized\n"; +const char *update_string = "Updated: "; +const char *finish_string = "Finished\n"; + +#define PAYLOAD_SIZE 128 + +typedef struct CTX { + uint8_t pos; + char payload[PAYLOAD_SIZE]; +} CTX; + +void* context = NULL; + +int digest_spec_plugin_init(void *raw_ctx) { + // Make the context accessible to tests. This isn't safe, but there's no way to access the context otherwise. + context = raw_ctx; + + struct CTX *ctx = (struct CTX *)raw_ctx; + size_t len = strlen(init_string); + + // Clear the payload since this init function will be invoked as part of the `reset` operation. + memset(ctx->payload, 0, PAYLOAD_SIZE); + + // Write a simple value we can verify in tests. + // This is not what a real digest would do, but we're using a dummy digest plugin to test interactions. + memcpy(ctx->payload, init_string, len); + ctx->pos = (uint8_t) len; + + return 1; +} + +void digest_spec_plugin_update(void *raw_ctx, unsigned char *ptr, size_t size) { + struct CTX *ctx = (struct CTX *)raw_ctx; + size_t update_str_len = strlen(update_string); + + if (ctx->pos + update_str_len + size >= PAYLOAD_SIZE) { + rb_raise(rb_eRuntimeError, "update size too large; reset the digest and write fewer updates"); + } + + // Write the supplied value to the payload so it can be easily verified in test. + // This is not what a real digest would do, but we're using a dummy digest plugin to test interactions. + memcpy(ctx->payload + ctx->pos, update_string, update_str_len); + ctx->pos += update_str_len; + + memcpy(ctx->payload + ctx->pos, ptr, size); + ctx->pos += size; + + return; +} + +int digest_spec_plugin_finish(void *raw_ctx, unsigned char *ptr) { + struct CTX *ctx = (struct CTX *)raw_ctx; + size_t finish_string_len = strlen(finish_string); + + // We're always going to write DIGEST_LENGTH bytes. In a real plugin, this would be the digest value. Here we + // write out a text string in order to make validation in tests easier. + // + // In order to delineate the output more clearly from an `Digest#update` call, we always write out the + // `finish_string` message. That leaves `DIGEST_LENGTH - finish_string_len` bytes to read out of the context. + size_t context_bytes = DIGEST_LENGTH - finish_string_len; + + memcpy(ptr, ctx->payload + (ctx->pos - context_bytes), context_bytes); + memcpy(ptr + context_bytes, finish_string, finish_string_len); + + return 1; +} + +static const rb_digest_metadata_t metadata = { + // The RUBY_DIGEST_API_VERSION value comes from ruby/digest.h and may vary based on the Ruby being tested. Since + // it isn't publicly exposed in the digest gem, we ignore for these tests. Either the test hard-codes an expected + // value and is subject to breaking depending on the Ruby being run or we publicly expose `RUBY_DIGEST_API_VERSION`, + // in which case the test would pass trivially. + RUBY_DIGEST_API_VERSION, + DIGEST_LENGTH, + BLOCK_LENGTH, + sizeof(CTX), + (rb_digest_hash_init_func_t) digest_spec_plugin_init, + (rb_digest_hash_update_func_t) digest_spec_plugin_update, + (rb_digest_hash_finish_func_t) digest_spec_plugin_finish, +}; + +// The `get_metadata_ptr` function is not publicly available in the digest gem. However, we need to use +// to extract the `rb_digest_metadata_t*` value set up by the plugin so we reproduce and adjust the +// definition here. +// +// Taken and adapted from https://github.com/ruby/digest/blob/v3.2.0/ext/digest/digest.c#L558-L568 +static rb_digest_metadata_t * get_metadata_ptr(VALUE obj) { + rb_digest_metadata_t *algo; + +#ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL + // In the digest gem there is an additional data type check performed before reading the value out. + // Since the type definition isn't public, we can't use it as part of a type check here so we omit it. + // This is safe to do because this code is intended to only load digest plugins written as part of this test suite. + algo = (rb_digest_metadata_t *) RTYPEDDATA_DATA(obj); +#else +# undef RUBY_UNTYPED_DATA_WARNING +# define RUBY_UNTYPED_DATA_WARNING 0 + Data_Get_Struct(obj, rb_digest_metadata_t, algo); +#endif + + return algo; +} + +VALUE digest_spec_rb_digest_make_metadata(VALUE self) { + return rb_digest_make_metadata(&metadata); +} + +VALUE digest_spec_block_length(VALUE self, VALUE meta) { + rb_digest_metadata_t* algo = get_metadata_ptr(meta); + + return SIZET2NUM(algo->block_len); +} + +VALUE digest_spec_digest_length(VALUE self, VALUE meta) { + rb_digest_metadata_t* algo = get_metadata_ptr(meta); + + return SIZET2NUM(algo->digest_len); +} + +VALUE digest_spec_context_size(VALUE self, VALUE meta) { + rb_digest_metadata_t* algo = get_metadata_ptr(meta); + + return SIZET2NUM(algo->ctx_size); +} + +#ifndef PTR2NUM +#define PTR2NUM(x) (rb_int2inum((intptr_t)(void *)(x))) +#endif + +VALUE digest_spec_context(VALUE self, VALUE digest) { + return PTR2NUM(context); +} + +void Init_digest_spec(void) { + VALUE cls; + + cls = rb_define_class("CApiDigestSpecs", rb_cObject); + rb_define_method(cls, "rb_digest_make_metadata", digest_spec_rb_digest_make_metadata, 0); + rb_define_method(cls, "block_length", digest_spec_block_length, 1); + rb_define_method(cls, "digest_length", digest_spec_digest_length, 1); + rb_define_method(cls, "context_size", digest_spec_context_size, 1); + rb_define_method(cls, "context", digest_spec_context, 1); + + VALUE mDigest, cDigest_Base, cDigest; + + mDigest = rb_define_module("Digest"); + mDigest = rb_digest_namespace(); + cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base")); + + cDigest = rb_define_class_under(mDigest, "TestDigest", cDigest_Base); + rb_iv_set(cDigest, "metadata", rb_digest_make_metadata(&metadata)); +} + +#ifdef __cplusplus +} +#endif diff --git a/spec/ruby/optional/capi/ext/encoding_spec.c b/spec/ruby/optional/capi/ext/encoding_spec.c index aa8662cfbd..2038a5d4a8 100644 --- a/spec/ruby/optional/capi/ext/encoding_spec.c +++ b/spec/ruby/optional/capi/ext/encoding_spec.c @@ -91,6 +91,11 @@ static VALUE encoding_spec_rb_enc_compatible(VALUE self, VALUE a, VALUE b) { return rb_enc_from_encoding(enc); } +static VALUE encoding_spec_rb_enc_check(VALUE self, VALUE a, VALUE b) { + rb_encoding* enc = rb_enc_check(a, b); + return rb_enc_from_encoding(enc); +} + static VALUE encoding_spec_rb_enc_copy(VALUE self, VALUE dest, VALUE src) { rb_enc_copy(dest, src); return dest; @@ -324,6 +329,10 @@ static VALUE encoding_spec_rb_define_dummy_encoding(VALUE self, VALUE name) { return INT2NUM(rb_define_dummy_encoding(RSTRING_PTR(name))); } +static VALUE encoding_spec_ONIGENC_IS_UNICODE(VALUE self, VALUE encoding) { + return ONIGENC_IS_UNICODE(rb_to_encoding(encoding)) ? Qtrue : Qfalse; +} + void Init_encoding_spec(void) { VALUE cls; native_rb_encoding_pointer = (rb_encoding**) malloc(sizeof(rb_encoding*)); @@ -349,6 +358,7 @@ void Init_encoding_spec(void) { rb_define_method(cls, "rb_enc_associate", encoding_spec_rb_enc_associate, 2); rb_define_method(cls, "rb_enc_associate_index", encoding_spec_rb_enc_associate_index, 2); rb_define_method(cls, "rb_enc_compatible", encoding_spec_rb_enc_compatible, 2); + rb_define_method(cls, "rb_enc_check", encoding_spec_rb_enc_check, 2); rb_define_method(cls, "rb_enc_copy", encoding_spec_rb_enc_copy, 2); rb_define_method(cls, "rb_enc_codelen", encoding_spec_rb_enc_codelen, 2); rb_define_method(cls, "rb_enc_strlen", encoding_spec_rb_enc_strlen, 3); @@ -384,6 +394,7 @@ void Init_encoding_spec(void) { rb_define_method(cls, "ONIGENC_MBC_CASE_FOLD", encoding_spec_ONIGENC_MBC_CASE_FOLD, 1); rb_define_method(cls, "rb_enc_left_char_head", encoding_spec_rb_enc_left_char_head, 2); rb_define_method(cls, "rb_define_dummy_encoding", encoding_spec_rb_define_dummy_encoding, 1); + rb_define_method(cls, "ONIGENC_IS_UNICODE", encoding_spec_ONIGENC_IS_UNICODE, 1); } #ifdef __cplusplus diff --git a/spec/ruby/optional/capi/ext/exception_spec.c b/spec/ruby/optional/capi/ext/exception_spec.c index 0e8347ab0d..c3b94d7bcd 100644 --- a/spec/ruby/optional/capi/ext/exception_spec.c +++ b/spec/ruby/optional/capi/ext/exception_spec.c @@ -36,6 +36,13 @@ VALUE exception_spec_rb_set_errinfo(VALUE self, VALUE exc) { return Qnil; } +NORETURN(VALUE exception_spec_rb_error_frozen_object(VALUE self, VALUE object)); + +VALUE exception_spec_rb_error_frozen_object(VALUE self, VALUE object) { + rb_error_frozen_object(object); + UNREACHABLE_RETURN(Qnil); +} + VALUE exception_spec_rb_syserr_new(VALUE self, VALUE num, VALUE msg) { int n = NUM2INT(num); char *cstr = NULL; @@ -66,6 +73,7 @@ void Init_exception_spec(void) { rb_define_method(cls, "rb_exc_new3", exception_spec_rb_exc_new3, 1); rb_define_method(cls, "rb_exc_raise", exception_spec_rb_exc_raise, 1); rb_define_method(cls, "rb_set_errinfo", exception_spec_rb_set_errinfo, 1); + rb_define_method(cls, "rb_error_frozen_object", exception_spec_rb_error_frozen_object, 1); rb_define_method(cls, "rb_syserr_new", exception_spec_rb_syserr_new, 2); rb_define_method(cls, "rb_syserr_new_str", exception_spec_rb_syserr_new_str, 2); rb_define_method(cls, "rb_make_exception", exception_spec_rb_make_exception, 1); diff --git a/spec/ruby/optional/capi/ext/fiber_spec.c b/spec/ruby/optional/capi/ext/fiber_spec.c index f06a54494e..db54f7ad8c 100644 --- a/spec/ruby/optional/capi/ext/fiber_spec.c +++ b/spec/ruby/optional/capi/ext/fiber_spec.c @@ -44,12 +44,10 @@ VALUE fiber_spec_rb_fiber_new(VALUE self) { return rb_fiber_new(fiber_spec_rb_fiber_new_function, Qnil); } -#ifdef RUBY_VERSION_IS_3_1 VALUE fiber_spec_rb_fiber_raise(int argc, VALUE *argv, VALUE self) { VALUE fiber = argv[0]; return rb_fiber_raise(fiber, argc-1, argv+1); } -#endif void Init_fiber_spec(void) { VALUE cls = rb_define_class("CApiFiberSpecs", rb_cObject); @@ -58,10 +56,7 @@ void Init_fiber_spec(void) { rb_define_method(cls, "rb_fiber_resume", fiber_spec_rb_fiber_resume, 2); rb_define_method(cls, "rb_fiber_yield", fiber_spec_rb_fiber_yield, 1); rb_define_method(cls, "rb_fiber_new", fiber_spec_rb_fiber_new, 0); - -#ifdef RUBY_VERSION_IS_3_1 rb_define_method(cls, "rb_fiber_raise", fiber_spec_rb_fiber_raise, -1); -#endif } #ifdef __cplusplus diff --git a/spec/ruby/optional/capi/ext/finalizer_spec.c b/spec/ruby/optional/capi/ext/finalizer_spec.c index ef546aa5b1..83347da912 100644 --- a/spec/ruby/optional/capi/ext/finalizer_spec.c +++ b/spec/ruby/optional/capi/ext/finalizer_spec.c @@ -10,13 +10,7 @@ static VALUE define_finalizer(VALUE self, VALUE obj, VALUE finalizer) { } static VALUE undefine_finalizer(VALUE self, VALUE obj) { -// Ruby 3.4.0 and 3.4.1 have a bug where rb_undefine_finalizer is missing -// See: https://bugs.ruby-lang.org/issues/20981 -#if RUBY_API_VERSION_CODE == 30400 && (RUBY_VERSION_TEENY == 0 || RUBY_VERSION_TEENY == 1) - return Qnil; -#else return rb_undefine_finalizer(obj); -#endif } void Init_finalizer_spec(void) { diff --git a/spec/ruby/optional/capi/ext/hash_spec.c b/spec/ruby/optional/capi/ext/hash_spec.c index 0e5b3d1c0a..653917f2c4 100644 --- a/spec/ruby/optional/capi/ext/hash_spec.c +++ b/spec/ruby/optional/capi/ext/hash_spec.c @@ -105,11 +105,9 @@ VALUE hash_spec_rb_hash_new(VALUE self) { return rb_hash_new(); } -#ifdef RUBY_VERSION_IS_3_2 VALUE hash_spec_rb_hash_new_capa(VALUE self, VALUE capacity) { return rb_hash_new_capa(NUM2LONG(capacity)); } -#endif VALUE rb_ident_hash_new(void); /* internal.h, used in ripper */ @@ -169,9 +167,7 @@ void Init_hash_spec(void) { rb_define_method(cls, "rb_hash_lookup2", hash_spec_rb_hash_lookup2, 3); rb_define_method(cls, "rb_hash_lookup2_default_undef", hash_spec_rb_hash_lookup2_default_undef, 2); rb_define_method(cls, "rb_hash_new", hash_spec_rb_hash_new, 0); -#ifdef RUBY_VERSION_IS_3_2 rb_define_method(cls, "rb_hash_new_capa", hash_spec_rb_hash_new_capa, 1); -#endif rb_define_method(cls, "rb_ident_hash_new", hash_spec_rb_ident_hash_new, 0); rb_define_method(cls, "rb_hash_size", hash_spec_rb_hash_size, 1); rb_define_method(cls, "rb_hash_set_ifnone", hash_spec_rb_hash_set_ifnone, 2); diff --git a/spec/ruby/optional/capi/ext/io_spec.c b/spec/ruby/optional/capi/ext/io_spec.c index 3b7e8c4481..fe31cffb49 100644 --- a/spec/ruby/optional/capi/ext/io_spec.c +++ b/spec/ruby/optional/capi/ext/io_spec.c @@ -28,13 +28,7 @@ static int set_non_blocking(int fd) { } static int io_spec_get_fd(VALUE io) { -#ifdef RUBY_VERSION_IS_3_1 return rb_io_descriptor(io); -#else - rb_io_t* fp; - GetOpenFile(io, fp); - return fp->fd; -#endif } VALUE io_spec_GetOpenFile_fd(VALUE self, VALUE io) { @@ -143,11 +137,7 @@ VALUE io_spec_rb_io_wait_readable(VALUE self, VALUE io, VALUE read_p) { errno = saved_errno; } -#ifdef RUBY_VERSION_IS_3_1 ret = rb_io_maybe_wait_readable(errno, io, Qnil); -#else - ret = rb_io_wait_readable(fd); -#endif if (RTEST(read_p)) { ssize_t r = read(fd, buf, RB_IO_WAIT_READABLE_BUF); @@ -166,22 +156,15 @@ VALUE io_spec_rb_io_wait_readable(VALUE self, VALUE io, VALUE read_p) { } VALUE io_spec_rb_io_wait_writable(VALUE self, VALUE io) { -#ifdef RUBY_VERSION_IS_3_1 int ret = rb_io_maybe_wait_writable(errno, io, Qnil); -#else - int ret = rb_io_wait_writable(io_spec_get_fd(io)); -#endif return ret ? Qtrue : Qfalse; } -#ifdef RUBY_VERSION_IS_3_1 VALUE io_spec_rb_io_maybe_wait_writable(VALUE self, VALUE error, VALUE io, VALUE timeout) { int ret = rb_io_maybe_wait_writable(NUM2INT(error), io, timeout); return INT2NUM(ret); } -#endif -#ifdef RUBY_VERSION_IS_3_1 #ifdef SET_NON_BLOCKING_FAILS_ALWAYS NORETURN(VALUE io_spec_rb_io_maybe_wait_readable(VALUE self, VALUE error, VALUE io, VALUE timeout, VALUE read_p)); #endif @@ -224,13 +207,10 @@ VALUE io_spec_rb_io_maybe_wait_readable(VALUE self, VALUE error, VALUE io, VALUE UNREACHABLE_RETURN(Qnil); #endif } -#endif -#ifdef RUBY_VERSION_IS_3_1 VALUE io_spec_rb_io_maybe_wait(VALUE self, VALUE error, VALUE io, VALUE events, VALUE timeout) { return rb_io_maybe_wait(NUM2INT(error), io, events, timeout); } -#endif VALUE io_spec_rb_thread_wait_fd(VALUE self, VALUE io) { rb_thread_wait_fd(io_spec_get_fd(io)); @@ -238,23 +218,13 @@ VALUE io_spec_rb_thread_wait_fd(VALUE self, VALUE io) { } VALUE io_spec_rb_wait_for_single_fd(VALUE self, VALUE io, VALUE events, VALUE secs, VALUE usecs) { -#ifdef RUBY_VERSION_IS_3_0 VALUE timeout = Qnil; if (!NIL_P(secs)) { - timeout = rb_float_new((double)FIX2INT(secs) + (0.000001f * FIX2INT(usecs))); + timeout = rb_float_new((double)FIX2INT(secs) + (0.000001 * FIX2INT(usecs))); } VALUE result = rb_io_wait(io, events, timeout); if (result == Qfalse) return INT2FIX(0); else return result; -#else - struct timeval tv; - if (!NIL_P(secs)) { - tv.tv_sec = FIX2INT(secs); - tv.tv_usec = FIX2INT(usecs); - } - int fd = io_spec_get_fd(io); - return INT2FIX(rb_wait_for_single_fd(fd, FIX2INT(events), NIL_P(secs) ? NULL : &tv)); -#endif } VALUE io_spec_rb_thread_fd_writable(VALUE self, VALUE io) { @@ -317,6 +287,18 @@ VALUE io_spec_rb_cloexec_open(VALUE self, VALUE path, VALUE flags, VALUE mode) { return rb_funcall(rb_cIO, rb_intern("for_fd"), 1, INT2FIX(fd)); } +VALUE io_spec_rb_cloexec_dup(VALUE self, VALUE io) { + int fd = io_spec_get_fd(io); + int new_fd = rb_cloexec_dup(fd); + return rb_funcall(rb_cIO, rb_intern("for_fd"), 1, INT2FIX(new_fd)); +} + +VALUE io_spec_rb_cloexec_fcntl_dupfd(VALUE self, VALUE io, VALUE minfd) { + int fd = io_spec_get_fd(io); + int new_fd = rb_cloexec_fcntl_dupfd(fd, FIX2INT(minfd)); + return rb_funcall(rb_cIO, rb_intern("for_fd"), 1, INT2FIX(new_fd)); +} + VALUE io_spec_rb_io_close(VALUE self, VALUE io) { return rb_io_close(io); } @@ -349,13 +331,7 @@ static VALUE io_spec_errno_set(VALUE self, VALUE val) { VALUE io_spec_mode_sync_flag(VALUE self, VALUE io) { int mode; -#ifdef RUBY_VERSION_IS_3_3 mode = rb_io_mode(io); -#else - rb_io_t *fp; - GetOpenFile(io, fp); - mode = fp->mode; -#endif if (mode & FMODE_SYNC) { return Qtrue; } else { @@ -363,7 +339,6 @@ VALUE io_spec_mode_sync_flag(VALUE self, VALUE io) { } } -#if defined(RUBY_VERSION_IS_3_3) || defined(TRUFFLERUBY) static VALUE io_spec_rb_io_mode(VALUE self, VALUE io) { return INT2FIX(rb_io_mode(io)); } @@ -390,7 +365,6 @@ static VALUE io_spec_rb_io_open_descriptor(VALUE self, VALUE klass, VALUE descri static VALUE io_spec_rb_io_open_descriptor_without_encoding(VALUE self, VALUE klass, VALUE descriptor, VALUE mode, VALUE path, VALUE timeout) { return rb_io_open_descriptor(klass, FIX2INT(descriptor), FIX2INT(mode), path, timeout, NULL); } -#endif void Init_io_spec(void) { VALUE cls = rb_define_class("CApiIOSpecs", rb_cObject); @@ -409,11 +383,9 @@ void Init_io_spec(void) { rb_define_method(cls, "rb_io_taint_check", io_spec_rb_io_taint_check, 1); rb_define_method(cls, "rb_io_wait_readable", io_spec_rb_io_wait_readable, 2); rb_define_method(cls, "rb_io_wait_writable", io_spec_rb_io_wait_writable, 1); -#ifdef RUBY_VERSION_IS_3_1 rb_define_method(cls, "rb_io_maybe_wait_writable", io_spec_rb_io_maybe_wait_writable, 3); rb_define_method(cls, "rb_io_maybe_wait_readable", io_spec_rb_io_maybe_wait_readable, 4); rb_define_method(cls, "rb_io_maybe_wait", io_spec_rb_io_maybe_wait, 4); -#endif rb_define_method(cls, "rb_thread_wait_fd", io_spec_rb_thread_wait_fd, 1); rb_define_method(cls, "rb_thread_fd_writable", io_spec_rb_thread_fd_writable, 1); rb_define_method(cls, "rb_thread_fd_select_read", io_spec_rb_thread_fd_select_read, 1); @@ -423,9 +395,10 @@ void Init_io_spec(void) { rb_define_method(cls, "rb_io_binmode", io_spec_rb_io_binmode, 1); rb_define_method(cls, "rb_fd_fix_cloexec", io_spec_rb_fd_fix_cloexec, 1); rb_define_method(cls, "rb_cloexec_open", io_spec_rb_cloexec_open, 3); + rb_define_method(cls, "rb_cloexec_dup", io_spec_rb_cloexec_dup, 1); + rb_define_method(cls, "rb_cloexec_fcntl_dupfd", io_spec_rb_cloexec_fcntl_dupfd, 2); rb_define_method(cls, "errno=", io_spec_errno_set, 1); rb_define_method(cls, "rb_io_mode_sync_flag", io_spec_mode_sync_flag, 1); -#if defined(RUBY_VERSION_IS_3_3) || defined(TRUFFLERUBY) rb_define_method(cls, "rb_io_mode", io_spec_rb_io_mode, 1); rb_define_method(cls, "rb_io_path", io_spec_rb_io_path, 1); rb_define_method(cls, "rb_io_closed_p", io_spec_rb_io_closed_p, 1); @@ -436,7 +409,6 @@ void Init_io_spec(void) { rb_define_const(cls, "FMODE_BINMODE", INT2FIX(FMODE_BINMODE)); rb_define_const(cls, "FMODE_TEXTMODE", INT2FIX(FMODE_TEXTMODE)); rb_define_const(cls, "ECONV_UNIVERSAL_NEWLINE_DECORATOR", INT2FIX(ECONV_UNIVERSAL_NEWLINE_DECORATOR)); -#endif } #ifdef __cplusplus diff --git a/spec/ruby/optional/capi/ext/kernel_spec.c b/spec/ruby/optional/capi/ext/kernel_spec.c index abd8d20ff4..eee324052d 100644 --- a/spec/ruby/optional/capi/ext/kernel_spec.c +++ b/spec/ruby/optional/capi/ext/kernel_spec.c @@ -1,4 +1,5 @@ #include "ruby.h" +#include "ruby/vm.h" #include "rubyspec.h" #include <errno.h> @@ -117,9 +118,11 @@ VALUE kernel_spec_rb_eval_string(VALUE self, VALUE str) { return rb_eval_string(RSTRING_PTR(str)); } +#ifndef RUBY_VERSION_IS_4_0 VALUE kernel_spec_rb_eval_cmd_kw(VALUE self, VALUE cmd, VALUE args, VALUE kw_splat) { return rb_eval_cmd_kw(cmd, args, NUM2INT(kw_splat)); } +#endif VALUE kernel_spec_rb_raise(VALUE self, VALUE hash) { rb_hash_aset(hash, ID2SYM(rb_intern("stage")), ID2SYM(rb_intern("before"))); @@ -335,6 +338,15 @@ static VALUE kernel_spec_rb_set_end_proc(VALUE self, VALUE io) { return Qnil; } +static void at_exit_hook(ruby_vm_t *vm) { + puts("ruby_vm_at_exit hook ran"); +} + +static VALUE kernel_spec_ruby_vm_at_exit(VALUE self) { + ruby_vm_at_exit(at_exit_hook); + return self; +} + static VALUE kernel_spec_rb_f_sprintf(VALUE self, VALUE ary) { return rb_f_sprintf((int)RARRAY_LEN(ary), RARRAY_PTR(ary)); } @@ -351,7 +363,6 @@ static VALUE kernel_spec_rb_funcallv(VALUE self, VALUE obj, VALUE method, VALUE return rb_funcallv(obj, SYM2ID(method), RARRAY_LENINT(args), RARRAY_PTR(args)); } -#ifdef RUBY_VERSION_IS_3_0 static VALUE kernel_spec_rb_funcallv_kw(VALUE self, VALUE obj, VALUE method, VALUE args) { return rb_funcallv_kw(obj, SYM2ID(method), RARRAY_LENINT(args), RARRAY_PTR(args), RB_PASS_KEYWORDS); } @@ -359,7 +370,6 @@ static VALUE kernel_spec_rb_funcallv_kw(VALUE self, VALUE obj, VALUE method, VAL static VALUE kernel_spec_rb_keyword_given_p(int argc, VALUE *args, VALUE self) { return rb_keyword_given_p() ? Qtrue : Qfalse; } -#endif static VALUE kernel_spec_rb_funcallv_public(VALUE self, VALUE obj, VALUE method) { return rb_funcallv_public(obj, SYM2ID(method), 0, NULL); @@ -405,7 +415,9 @@ void Init_kernel_spec(void) { rb_define_method(cls, "rb_category_warn_deprecated_with_integer_extra_value", kernel_spec_rb_category_warn_deprecated_with_integer_extra_value, 1); rb_define_method(cls, "rb_ensure", kernel_spec_rb_ensure, 4); rb_define_method(cls, "rb_eval_string", kernel_spec_rb_eval_string, 1); +#ifndef RUBY_VERSION_IS_4_0 rb_define_method(cls, "rb_eval_cmd_kw", kernel_spec_rb_eval_cmd_kw, 3); +#endif rb_define_method(cls, "rb_raise", kernel_spec_rb_raise, 1); rb_define_method(cls, "rb_throw", kernel_spec_rb_throw, 1); rb_define_method(cls, "rb_throw_obj", kernel_spec_rb_throw_obj, 2); @@ -432,14 +444,13 @@ void Init_kernel_spec(void) { rb_define_method(cls, "rb_yield_splat", kernel_spec_rb_yield_splat, 1); rb_define_method(cls, "rb_exec_recursive", kernel_spec_rb_exec_recursive, 1); rb_define_method(cls, "rb_set_end_proc", kernel_spec_rb_set_end_proc, 1); + rb_define_method(cls, "ruby_vm_at_exit", kernel_spec_ruby_vm_at_exit, 0); rb_define_method(cls, "rb_f_sprintf", kernel_spec_rb_f_sprintf, 1); rb_define_method(cls, "rb_str_format", kernel_spec_rb_str_format, 3); rb_define_method(cls, "rb_make_backtrace", kernel_spec_rb_make_backtrace, 0); rb_define_method(cls, "rb_funcallv", kernel_spec_rb_funcallv, 3); -#ifdef RUBY_VERSION_IS_3_0 rb_define_method(cls, "rb_funcallv_kw", kernel_spec_rb_funcallv_kw, 3); rb_define_method(cls, "rb_keyword_given_p", kernel_spec_rb_keyword_given_p, -1); -#endif rb_define_method(cls, "rb_funcallv_public", kernel_spec_rb_funcallv_public, 2); rb_define_method(cls, "rb_funcall_many_args", kernel_spec_rb_funcall_many_args, 2); rb_define_method(cls, "rb_funcall_with_block", kernel_spec_rb_funcall_with_block, 4); diff --git a/spec/ruby/optional/capi/ext/object_spec.c b/spec/ruby/optional/capi/ext/object_spec.c index aa60662e1e..995bc38fcf 100644 --- a/spec/ruby/optional/capi/ext/object_spec.c +++ b/spec/ruby/optional/capi/ext/object_spec.c @@ -15,11 +15,6 @@ static VALUE object_spec_FL_ABLE(VALUE self, VALUE obj) { static int object_spec_FL_TEST_flag(VALUE flag_string) { char *flag_cstr = StringValueCStr(flag_string); -#ifndef RUBY_VERSION_IS_3_1 - if (strcmp(flag_cstr, "FL_TAINT") == 0) { - return FL_TAINT; - } -#endif if (strcmp(flag_cstr, "FL_FREEZE") == 0) { return FL_FREEZE; } @@ -30,22 +25,6 @@ static VALUE object_spec_FL_TEST(VALUE self, VALUE obj, VALUE flag) { return INT2FIX(FL_TEST(obj, object_spec_FL_TEST_flag(flag))); } -#ifndef RUBY_VERSION_IS_3_1 -static VALUE object_spec_OBJ_TAINT(VALUE self, VALUE obj) { - OBJ_TAINT(obj); - return Qnil; -} - -static VALUE object_spec_OBJ_TAINTED(VALUE self, VALUE obj) { - return OBJ_TAINTED(obj) ? Qtrue : Qfalse; -} - -static VALUE object_spec_OBJ_INFECT(VALUE self, VALUE host, VALUE source) { - OBJ_INFECT(host, source); - return Qnil; -} -#endif - static VALUE object_spec_rb_any_to_s(VALUE self, VALUE obj) { return rb_any_to_s(obj); } @@ -154,12 +133,6 @@ static VALUE object_specs_rb_obj_method(VALUE self, VALUE obj, VALUE method) { return rb_obj_method(obj, method); } -#ifndef RUBY_VERSION_IS_3_2 -static VALUE object_spec_rb_obj_taint(VALUE self, VALUE obj) { - return rb_obj_taint(obj); -} -#endif - static VALUE so_require(VALUE self) { rb_require("fixtures/foo"); return Qnil; @@ -410,15 +383,20 @@ static VALUE object_spec_custom_alloc_func_p(VALUE self, VALUE klass) { return allocator ? Qtrue : Qfalse; } +static VALUE object_spec_redefine_frozen(VALUE self) { + // The purpose of this spec is to verify that `frozen?` + // and `RB_OBJ_FROZEN` do not mutually recurse infinitely. + if (RB_OBJ_FROZEN(self)) { + return Qtrue; + } + + return Qfalse; +} + void Init_object_spec(void) { VALUE cls = rb_define_class("CApiObjectSpecs", rb_cObject); rb_define_method(cls, "FL_ABLE", object_spec_FL_ABLE, 1); rb_define_method(cls, "FL_TEST", object_spec_FL_TEST, 2); -#ifndef RUBY_VERSION_IS_3_1 - rb_define_method(cls, "OBJ_TAINT", object_spec_OBJ_TAINT, 1); - rb_define_method(cls, "OBJ_TAINTED", object_spec_OBJ_TAINTED, 1); - rb_define_method(cls, "OBJ_INFECT", object_spec_OBJ_INFECT, 2); -#endif rb_define_method(cls, "rb_any_to_s", object_spec_rb_any_to_s, 1); rb_define_method(cls, "rb_attr_get", so_attr_get, 2); rb_define_method(cls, "rb_obj_instance_variables", object_spec_rb_obj_instance_variables, 1); @@ -443,15 +421,11 @@ void Init_object_spec(void) { rb_define_method(cls, "rb_obj_is_kind_of", so_kind_of, 2); rb_define_method(cls, "rb_obj_method_arity", object_specs_rb_obj_method_arity, 2); rb_define_method(cls, "rb_obj_method", object_specs_rb_obj_method, 2); -#ifndef RUBY_VERSION_IS_3_2 - rb_define_method(cls, "rb_obj_taint", object_spec_rb_obj_taint, 1); -#endif rb_define_method(cls, "rb_require", so_require, 0); rb_define_method(cls, "rb_respond_to", so_respond_to, 2); rb_define_method(cls, "rb_method_boundp", object_spec_rb_method_boundp, 3); rb_define_method(cls, "rb_obj_respond_to", so_obj_respond_to, 3); rb_define_method(cls, "rb_special_const_p", object_spec_rb_special_const_p, 1); - rb_define_method(cls, "rb_to_id", so_to_id, 1); rb_define_method(cls, "RTEST", object_spec_RTEST, 1); rb_define_method(cls, "rb_check_type", so_check_type, 2); @@ -491,6 +465,9 @@ void Init_object_spec(void) { rb_define_method(cls, "custom_alloc_func?", object_spec_custom_alloc_func_p, 1); rb_define_method(cls, "not_implemented_method", rb_f_notimplement, -1); rb_define_method(cls, "rb_ivar_foreach", object_spec_rb_ivar_foreach, 1); + + cls = rb_define_class("CApiObjectRedefinitionSpecs", rb_cObject); + rb_define_method(cls, "frozen?", object_spec_redefine_frozen, 0); } #ifdef __cplusplus diff --git a/spec/ruby/optional/capi/ext/range_spec.c b/spec/ruby/optional/capi/ext/range_spec.c index b0cf1a8662..9faed3e5ee 100644 --- a/spec/ruby/optional/capi/ext/range_spec.c +++ b/spec/ruby/optional/capi/ext/range_spec.c @@ -25,9 +25,9 @@ VALUE range_spec_rb_range_values(VALUE self, VALUE range) { return ary; } -VALUE range_spec_rb_range_beg_len(VALUE self, VALUE range, VALUE begpv, VALUE lenpv, VALUE lenv, VALUE errv) { - long begp = FIX2LONG(begpv); - long lenp = FIX2LONG(lenpv); +VALUE range_spec_rb_range_beg_len(VALUE self, VALUE range, VALUE lenv, VALUE errv) { + long begp = 0; + long lenp = 0; long len = FIX2LONG(lenv); int err = FIX2INT(errv); VALUE ary = rb_ary_new(); @@ -38,11 +38,51 @@ VALUE range_spec_rb_range_beg_len(VALUE self, VALUE range, VALUE begpv, VALUE le return ary; } +VALUE range_spec_rb_arithmetic_sequence_extract(VALUE self, VALUE object) { + VALUE ary = rb_ary_new(); + rb_arithmetic_sequence_components_t components; + + int status = rb_arithmetic_sequence_extract(object, &components); + + if (!status) { + rb_ary_store(ary, 0, LONG2FIX(status)); + return ary; + } + + rb_ary_store(ary, 0, LONG2FIX(status)); + rb_ary_store(ary, 1, components.begin); + rb_ary_store(ary, 2, components.end); + rb_ary_store(ary, 3, components.step); + rb_ary_store(ary, 4, components.exclude_end ? Qtrue : Qfalse); + return ary; +} + +VALUE range_spec_rb_arithmetic_sequence_beg_len_step(VALUE self, VALUE aseq, VALUE lenv, VALUE errv) { + long begp = 0; + long lenp = 0; + long stepp = 0; + + long len = FIX2LONG(lenv); + int err = FIX2INT(errv); + + VALUE success = rb_arithmetic_sequence_beg_len_step(aseq, &begp, &lenp, &stepp, len, err); + + VALUE ary = rb_ary_new(); + rb_ary_store(ary, 0, success); + rb_ary_store(ary, 1, LONG2FIX(begp)); + rb_ary_store(ary, 2, LONG2FIX(lenp)); + rb_ary_store(ary, 3, LONG2FIX(stepp)); + + return ary; +} + void Init_range_spec(void) { VALUE cls = rb_define_class("CApiRangeSpecs", rb_cObject); rb_define_method(cls, "rb_range_new", range_spec_rb_range_new, -1); rb_define_method(cls, "rb_range_values", range_spec_rb_range_values, 1); - rb_define_method(cls, "rb_range_beg_len", range_spec_rb_range_beg_len, 5); + rb_define_method(cls, "rb_range_beg_len", range_spec_rb_range_beg_len, 3); + rb_define_method(cls, "rb_arithmetic_sequence_extract", range_spec_rb_arithmetic_sequence_extract, 1); + rb_define_method(cls, "rb_arithmetic_sequence_beg_len_step", range_spec_rb_arithmetic_sequence_beg_len_step, 3); } #ifdef __cplusplus diff --git a/spec/ruby/optional/capi/ext/rbasic_spec.c b/spec/ruby/optional/capi/ext/rbasic_spec.c index 26be2fed6d..5a95b92804 100644 --- a/spec/ruby/optional/capi/ext/rbasic_spec.c +++ b/spec/ruby/optional/capi/ext/rbasic_spec.c @@ -31,13 +31,6 @@ static const VALUE DATA_VISIBLE_BITS = FL_FREEZE | ~(FL_USER0 - 1); #error "unsupported" #endif - -#ifndef RUBY_VERSION_IS_3_1 -VALUE rbasic_spec_taint_flag(VALUE self) { - return VALUE2NUM(RUBY_FL_TAINT); -} -#endif - VALUE rbasic_spec_freeze_flag(VALUE self) { return VALUE2NUM(RUBY_FL_FREEZE); } @@ -93,9 +86,6 @@ static VALUE rbasic_rdata_spec_get_klass(VALUE self, VALUE structure) { void Init_rbasic_spec(void) { VALUE cls = rb_define_class("CApiRBasicSpecs", rb_cObject); -#ifndef RUBY_VERSION_IS_3_1 - rb_define_method(cls, "taint_flag", rbasic_spec_taint_flag, 0); -#endif rb_define_method(cls, "freeze_flag", rbasic_spec_freeze_flag, 0); rb_define_method(cls, "get_flags", rbasic_spec_get_flags, 1); rb_define_method(cls, "set_flags", rbasic_spec_set_flags, 2); diff --git a/spec/ruby/optional/capi/ext/rubyspec.h b/spec/ruby/optional/capi/ext/rubyspec.h index 1df274ead1..5a92645785 100644 --- a/spec/ruby/optional/capi/ext/rubyspec.h +++ b/spec/ruby/optional/capi/ext/rubyspec.h @@ -5,11 +5,7 @@ * guards to assist with version incompatibilities. */ #include <ruby.h> -#ifdef HAVE_RUBY_VERSION_H -# include <ruby/version.h> -#else -# include <version.h> -#endif +#include <ruby/version.h> /* copied from ext/-test-/cxxanyargs/cxxanyargs.cpp */ #if 0 /* Ignore deprecation warnings */ @@ -34,36 +30,21 @@ #endif -#ifndef RUBY_VERSION_MAJOR -#define RUBY_VERSION_MAJOR RUBY_API_VERSION_MAJOR -#define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR -#define RUBY_VERSION_TEENY RUBY_API_VERSION_TEENY -#endif - -#define RUBY_VERSION_BEFORE(major,minor,teeny) \ - ((RUBY_VERSION_MAJOR < (major)) || \ - (RUBY_VERSION_MAJOR == (major) && RUBY_VERSION_MINOR < (minor)) || \ - (RUBY_VERSION_MAJOR == (major) && RUBY_VERSION_MINOR == (minor) && RUBY_VERSION_TEENY < (teeny))) -#define RUBY_VERSION_SINCE(major,minor,teeny) (!RUBY_VERSION_BEFORE(major, minor, teeny)) - -#if RUBY_VERSION_SINCE(3, 4, 0) -#define RUBY_VERSION_IS_3_4 -#endif - -#if RUBY_VERSION_SINCE(3, 3, 0) -#define RUBY_VERSION_IS_3_3 -#endif +#define RUBY_VERSION_BEFORE(major,minor) \ + ((RUBY_API_VERSION_MAJOR < (major)) || \ + (RUBY_API_VERSION_MAJOR == (major) && RUBY_API_VERSION_MINOR < (minor))) +#define RUBY_VERSION_SINCE(major,minor) (!RUBY_VERSION_BEFORE(major, minor)) -#if RUBY_VERSION_SINCE(3, 2, 0) -#define RUBY_VERSION_IS_3_2 +#if RUBY_VERSION_SINCE(4, 1) +#define RUBY_VERSION_IS_4_1 #endif -#if RUBY_VERSION_SINCE(3, 1, 0) -#define RUBY_VERSION_IS_3_1 +#if RUBY_VERSION_SINCE(4, 0) +#define RUBY_VERSION_IS_4_0 #endif -#if RUBY_VERSION_SINCE(3, 0, 0) -#define RUBY_VERSION_IS_3_0 +#if RUBY_VERSION_SINCE(3, 4) +#define RUBY_VERSION_IS_3_4 #endif #endif diff --git a/spec/ruby/optional/capi/ext/set_spec.c b/spec/ruby/optional/capi/ext/set_spec.c new file mode 100644 index 0000000000..11a271b361 --- /dev/null +++ b/spec/ruby/optional/capi/ext/set_spec.c @@ -0,0 +1,65 @@ +#include "ruby.h" +#include "rubyspec.h" + +#ifdef RUBY_VERSION_IS_4_0 +#ifdef __cplusplus +extern "C" { +#endif + +#define RBOOL(x) ((x) ? Qtrue : Qfalse) + +int yield_element_and_arg(VALUE element, VALUE arg) { + return RTEST(rb_yield_values(2, element, arg)) ? ST_CONTINUE : ST_STOP; +} + +VALUE set_spec_rb_set_foreach(VALUE self, VALUE set, VALUE arg) { + rb_set_foreach(set, yield_element_and_arg, arg); + return Qnil; +} + +VALUE set_spec_rb_set_new(VALUE self) { + return rb_set_new(); +} + +VALUE set_spec_rb_set_new_capa(VALUE self, VALUE capa) { + return rb_set_new_capa(NUM2INT(capa)); +} + +VALUE set_spec_rb_set_lookup(VALUE self, VALUE set, VALUE element) { + return RBOOL(rb_set_lookup(set, element)); +} + +VALUE set_spec_rb_set_add(VALUE self, VALUE set, VALUE element) { + return RBOOL(rb_set_add(set, element)); +} + +VALUE set_spec_rb_set_clear(VALUE self, VALUE set) { + return rb_set_clear(set); +} + +VALUE set_spec_rb_set_delete(VALUE self, VALUE set, VALUE element) { + return RBOOL(rb_set_delete(set, element)); +} + +VALUE set_spec_rb_set_size(VALUE self, VALUE set) { + return SIZET2NUM(rb_set_size(set)); +} + +void Init_set_spec(void) { + VALUE cls = rb_define_class("CApiSetSpecs", rb_cObject); + + rb_define_method(cls, "rb_set_foreach", set_spec_rb_set_foreach, 2); + rb_define_method(cls, "rb_set_new", set_spec_rb_set_new, 0); + rb_define_method(cls, "rb_set_new_capa", set_spec_rb_set_new_capa, 1); + rb_define_method(cls, "rb_set_lookup", set_spec_rb_set_lookup, 2); + rb_define_method(cls, "rb_set_add", set_spec_rb_set_add, 2); + rb_define_method(cls, "rb_set_clear", set_spec_rb_set_clear, 1); + rb_define_method(cls, "rb_set_delete", set_spec_rb_set_delete, 2); + rb_define_method(cls, "rb_set_size", set_spec_rb_set_size, 1); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/spec/ruby/optional/capi/ext/string_spec.c b/spec/ruby/optional/capi/ext/string_spec.c index a140c86347..8291b73ea4 100644 --- a/spec/ruby/optional/capi/ext/string_spec.c +++ b/spec/ruby/optional/capi/ext/string_spec.c @@ -12,6 +12,13 @@ extern "C" { #endif +#ifdef PTR2NUM +#elif SIZEOF_VOIDP <= SIZEOF_LONG +# define PTR2NUM(x) (LONG2NUM((long)(x))) +#elif SIZEOF_VOIDP <= SIZEOF_LONG_LONG +# define PTR2NUM(x) (LL2NUM((LONG_LONG)(x))) +#endif + /* Make sure the RSTRING_PTR and the bytes are in native memory. * On TruffleRuby RSTRING_PTR and the bytes remain in managed memory * until they must be written to native memory. @@ -252,16 +259,6 @@ VALUE string_spec_rb_str_new5(VALUE self, VALUE str, VALUE ptr, VALUE len) { return rb_str_new5(str, RSTRING_PTR(ptr), FIX2INT(len)); } -#ifndef RUBY_VERSION_IS_3_2 -VALUE string_spec_rb_tainted_str_new(VALUE self, VALUE str, VALUE len) { - return rb_tainted_str_new(RSTRING_PTR(str), FIX2INT(len)); -} - -VALUE string_spec_rb_tainted_str_new2(VALUE self, VALUE str) { - return rb_tainted_str_new2(RSTRING_PTR(str)); -} -#endif - VALUE string_spec_rb_str_plus(VALUE self, VALUE str1, VALUE str2) { return rb_str_plus(str1, str2); } @@ -306,6 +303,26 @@ VALUE string_spec_rb_str_substr(VALUE self, VALUE str, VALUE beg, VALUE len) { return rb_str_substr(str, FIX2INT(beg), FIX2INT(len)); } +VALUE string_spec_rb_str_subpos(VALUE self, VALUE str, VALUE beg) { + char* original = RSTRING_PTR(str); + char* end = RSTRING_END(str); + long len = rb_str_strlen(str); + char *p = rb_str_subpos(str, FIX2LONG(beg), &len); + if (p == NULL) { + return Qnil; + } + + if (p >= original && p <= end) { + return rb_ary_new_from_args(2, LONG2FIX(p - RSTRING_PTR(str)), LONG2FIX(len)); + } else { + rb_raise(rb_eRuntimeError, "the returned pointer is not inside the original string buffer"); + } +} + +VALUE string_spec_rb_str_sublen(VALUE self, VALUE str, VALUE pos) { + return LONG2FIX(rb_str_sublen(str, FIX2LONG(pos))); +} + VALUE string_spec_rb_str_to_str(VALUE self, VALUE arg) { return rb_str_to_str(arg); } @@ -318,6 +335,11 @@ VALUE string_spec_RSTRING_LENINT(VALUE self, VALUE str) { return INT2FIX(RSTRING_LENINT(str)); } +VALUE string_spec_RSTRING_PTR(VALUE self, VALUE str) { + char* ptr = RSTRING_PTR(str); + return PTR2NUM(ptr); +} + VALUE string_spec_RSTRING_PTR_iterate(VALUE self, VALUE str) { int i; char* ptr; @@ -403,6 +425,7 @@ VALUE string_spec_RSTRING_PTR_read(VALUE self, VALUE str, VALUE path) { if (read(fd, buffer, 30) < 0) { rb_syserr_fail(errno, "read"); } + rb_str_set_len(str, 30); rb_str_modify_expand(str, 53); rb_ary_push(capacities, SIZET2NUM(rb_str_capacity(str))); @@ -450,6 +473,7 @@ static VALUE string_spec_rb_str_free(VALUE self, VALUE str) { static VALUE string_spec_rb_sprintf1(VALUE self, VALUE str, VALUE repl) { return rb_sprintf(RSTRING_PTR(str), RSTRING_PTR(repl)); } + static VALUE string_spec_rb_sprintf2(VALUE self, VALUE str, VALUE repl1, VALUE repl2) { return rb_sprintf(RSTRING_PTR(str), RSTRING_PTR(repl1), RSTRING_PTR(repl2)); } @@ -540,7 +564,10 @@ static VALUE string_spec_rb_str_modify(VALUE self, VALUE str) { } static VALUE string_spec_rb_utf8_str_new_static(VALUE self) { - return rb_utf8_str_new_static("nokogiri", 8); + const char* literal = "nokogiri"; + return rb_ary_new_from_args(2, + rb_utf8_str_new_static("nokogiri", 8), + PTR2NUM(literal)); } static VALUE string_spec_rb_utf8_str_new(VALUE self) { @@ -590,6 +617,14 @@ static VALUE string_spec_rb_str_to_interned_str(VALUE self, VALUE str) { return rb_str_to_interned_str(str); } +static VALUE string_spec_rb_interned_str(VALUE self, VALUE str, VALUE len) { + return rb_interned_str(RSTRING_PTR(str), FIX2LONG(len)); +} + +static VALUE string_spec_rb_interned_str_cstr(VALUE self, VALUE str) { + return rb_interned_str_cstr(RSTRING_PTR(str)); +} + void Init_string_spec(void) { VALUE cls = rb_define_class("CApiStringSpecs", rb_cObject); rb_define_method(cls, "rb_cstr2inum", string_spec_rb_cstr2inum, 2); @@ -635,10 +670,6 @@ void Init_string_spec(void) { rb_define_method(cls, "rb_str_new3", string_spec_rb_str_new3, 1); rb_define_method(cls, "rb_str_new4", string_spec_rb_str_new4, 1); rb_define_method(cls, "rb_str_new5", string_spec_rb_str_new5, 3); -#ifndef RUBY_VERSION_IS_3_2 - rb_define_method(cls, "rb_tainted_str_new", string_spec_rb_tainted_str_new, 2); - rb_define_method(cls, "rb_tainted_str_new2", string_spec_rb_tainted_str_new2, 1); -#endif rb_define_method(cls, "rb_str_plus", string_spec_rb_str_plus, 2); rb_define_method(cls, "rb_str_times", string_spec_rb_str_times, 2); rb_define_method(cls, "rb_str_modify_expand", string_spec_rb_str_modify_expand, 2); @@ -650,9 +681,12 @@ void Init_string_spec(void) { rb_define_method(cls, "rb_str_split", string_spec_rb_str_split, 1); rb_define_method(cls, "rb_str_subseq", string_spec_rb_str_subseq, 3); rb_define_method(cls, "rb_str_substr", string_spec_rb_str_substr, 3); + rb_define_method(cls, "rb_str_subpos", string_spec_rb_str_subpos, 2); + rb_define_method(cls, "rb_str_sublen", string_spec_rb_str_sublen, 2); rb_define_method(cls, "rb_str_to_str", string_spec_rb_str_to_str, 1); rb_define_method(cls, "RSTRING_LEN", string_spec_RSTRING_LEN, 1); rb_define_method(cls, "RSTRING_LENINT", string_spec_RSTRING_LENINT, 1); + rb_define_method(cls, "RSTRING_PTR", string_spec_RSTRING_PTR, 1); rb_define_method(cls, "RSTRING_PTR_iterate", string_spec_RSTRING_PTR_iterate, 1); rb_define_method(cls, "RSTRING_PTR_iterate_uint32", string_spec_RSTRING_PTR_iterate_uint32, 1); rb_define_method(cls, "RSTRING_PTR_short_memcpy", string_spec_RSTRING_PTR_short_memcpy, 1); @@ -694,6 +728,8 @@ void Init_string_spec(void) { rb_define_method(cls, "rb_enc_interned_str_cstr", string_spec_rb_enc_interned_str_cstr, 2); rb_define_method(cls, "rb_enc_interned_str", string_spec_rb_enc_interned_str, 3); rb_define_method(cls, "rb_str_to_interned_str", string_spec_rb_str_to_interned_str, 1); + rb_define_method(cls, "rb_interned_str", string_spec_rb_interned_str, 2); + rb_define_method(cls, "rb_interned_str_cstr", string_spec_rb_interned_str_cstr, 1); } #ifdef __cplusplus diff --git a/spec/ruby/optional/capi/ext/struct_spec.c b/spec/ruby/optional/capi/ext/struct_spec.c index 413249e828..1c669d153e 100644 --- a/spec/ruby/optional/capi/ext/struct_spec.c +++ b/spec/ruby/optional/capi/ext/struct_spec.c @@ -62,7 +62,10 @@ static VALUE struct_spec_rb_struct_size(VALUE self, VALUE st) { return rb_struct_size(st); } -#if defined(RUBY_VERSION_IS_3_3) +static VALUE struct_spec_rb_struct_initialize(VALUE self, VALUE st, VALUE values) { + return rb_struct_initialize(st, values); +} + /* Only allow setting three attributes, should be sufficient for testing. */ static VALUE struct_spec_rb_data_define(VALUE self, VALUE superclass, VALUE attr1, VALUE attr2, VALUE attr3) { @@ -77,7 +80,6 @@ static VALUE struct_spec_rb_data_define(VALUE self, VALUE superclass, return rb_data_define(superclass, a1, a2, a3, NULL); } -#endif void Init_struct_spec(void) { VALUE cls = rb_define_class("CApiStructSpecs", rb_cObject); @@ -90,9 +92,8 @@ void Init_struct_spec(void) { rb_define_method(cls, "rb_struct_define_under", struct_spec_rb_struct_define_under, 5); rb_define_method(cls, "rb_struct_new", struct_spec_rb_struct_new, 4); rb_define_method(cls, "rb_struct_size", struct_spec_rb_struct_size, 1); -#if defined(RUBY_VERSION_IS_3_3) + rb_define_method(cls, "rb_struct_initialize", struct_spec_rb_struct_initialize, 2); rb_define_method(cls, "rb_data_define", struct_spec_rb_data_define, 4); -#endif } #ifdef __cplusplus diff --git a/spec/ruby/optional/capi/ext/thread_spec.c b/spec/ruby/optional/capi/ext/thread_spec.c index 3511c2fbcf..ac77e4e813 100644 --- a/spec/ruby/optional/capi/ext/thread_spec.c +++ b/spec/ruby/optional/capi/ext/thread_spec.c @@ -118,7 +118,6 @@ static VALUE thread_spec_rb_thread_wait_for(VALUE self, VALUE s, VALUE ms) { return Qnil; } - VALUE thread_spec_call_proc(void *arg_ptr) { VALUE arg_array = (VALUE)arg_ptr; VALUE arg = rb_ary_pop(arg_array); @@ -167,6 +166,12 @@ static VALUE thread_spec_ruby_native_thread_p_new_thread(VALUE self) { #endif } +#ifdef RUBY_VERSION_IS_4_0 +static VALUE thread_spec_ruby_thread_has_gvl_p(VALUE self) { + return ruby_thread_has_gvl_p() ? Qtrue : Qfalse; +} +#endif + void Init_thread_spec(void) { VALUE cls = rb_define_class("CApiThreadSpecs", rb_cObject); rb_define_method(cls, "rb_thread_alone", thread_spec_rb_thread_alone, 0); @@ -180,6 +185,9 @@ void Init_thread_spec(void) { rb_define_method(cls, "rb_thread_create", thread_spec_rb_thread_create, 2); rb_define_method(cls, "ruby_native_thread_p", thread_spec_ruby_native_thread_p, 0); rb_define_method(cls, "ruby_native_thread_p_new_thread", thread_spec_ruby_native_thread_p_new_thread, 0); +#ifdef RUBY_VERSION_IS_4_0 + rb_define_method(cls, "ruby_thread_has_gvl_p", thread_spec_ruby_thread_has_gvl_p, 0); +#endif } #ifdef __cplusplus diff --git a/spec/ruby/optional/capi/ext/typed_data_spec.c b/spec/ruby/optional/capi/ext/typed_data_spec.c index 221f1c8ac4..c6fcfa3bc8 100644 --- a/spec/ruby/optional/capi/ext/typed_data_spec.c +++ b/spec/ruby/optional/capi/ext/typed_data_spec.c @@ -106,6 +106,7 @@ VALUE sws_typed_wrap_struct(VALUE self, VALUE val) { return TypedData_Wrap_Struct(rb_cObject, &sample_typed_wrapped_struct_data_type, bar); } +#ifndef RUBY_VERSION_IS_4_1 #undef RUBY_UNTYPED_DATA_WARNING #define RUBY_UNTYPED_DATA_WARNING 0 VALUE sws_untyped_wrap_struct(VALUE self, VALUE val) { @@ -113,6 +114,7 @@ VALUE sws_untyped_wrap_struct(VALUE self, VALUE val) { *data = FIX2INT(val); return Data_Wrap_Struct(rb_cObject, NULL, free, data); } +#endif VALUE sws_typed_get_struct(VALUE self, VALUE obj) { struct sample_typed_wrapped_struct* bar; @@ -173,9 +175,11 @@ VALUE sws_typed_rb_check_typeddata_different_type(VALUE self, VALUE obj) { return rb_check_typeddata(obj, &sample_typed_wrapped_struct_other_data_type) == DATA_PTR(obj) ? Qtrue : Qfalse; } +#ifndef RUBY_VERSION_IS_4_1 VALUE sws_typed_RTYPEDDATA_P(VALUE self, VALUE obj) { return RTYPEDDATA_P(obj) ? Qtrue : Qfalse; } +#endif void Init_typed_data_spec(void) { VALUE cls = rb_define_class("CApiAllocTypedSpecs", rb_cObject); @@ -183,7 +187,9 @@ void Init_typed_data_spec(void) { rb_define_method(cls, "typed_wrapped_data", sdaf_typed_get_struct, 0); cls = rb_define_class("CApiWrappedTypedStructSpecs", rb_cObject); rb_define_method(cls, "typed_wrap_struct", sws_typed_wrap_struct, 1); +#ifndef RUBY_VERSION_IS_4_1 rb_define_method(cls, "untyped_wrap_struct", sws_untyped_wrap_struct, 1); +#endif rb_define_method(cls, "typed_get_struct", sws_typed_get_struct, 1); rb_define_method(cls, "typed_get_struct_other", sws_typed_get_struct_different_type, 1); rb_define_method(cls, "typed_get_struct_parent", sws_typed_get_struct_parent_type, 1); @@ -194,10 +200,11 @@ void Init_typed_data_spec(void) { rb_define_method(cls, "rb_check_typeddata_same_type", sws_typed_rb_check_typeddata_same_type, 1); rb_define_method(cls, "rb_check_typeddata_same_type_parent", sws_typed_rb_check_typeddata_same_type_parent, 1); rb_define_method(cls, "rb_check_typeddata_different_type", sws_typed_rb_check_typeddata_different_type, 1); +#ifndef RUBY_VERSION_IS_4_1 rb_define_method(cls, "RTYPEDDATA_P", sws_typed_RTYPEDDATA_P, 1); +#endif } #ifdef __cplusplus } #endif - diff --git a/spec/ruby/optional/capi/ext/util_spec.c b/spec/ruby/optional/capi/ext/util_spec.c index b5bde420d2..043da99ace 100644 --- a/spec/ruby/optional/capi/ext/util_spec.c +++ b/spec/ruby/optional/capi/ext/util_spec.c @@ -20,15 +20,11 @@ VALUE util_spec_rb_scan_args(VALUE self, VALUE argv, VALUE fmt, VALUE expected, a1 = a2 = a3 = a4 = a5 = a6 = INT2FIX(-1); -#ifdef RB_SCAN_ARGS_KEYWORDS if (*RSTRING_PTR(fmt) == 'k') { result = rb_scan_args_kw(RB_SCAN_ARGS_KEYWORDS, argc, args, RSTRING_PTR(fmt)+1, &a1, &a2, &a3, &a4, &a5, &a6); } else { -#endif result = rb_scan_args(argc, args, RSTRING_PTR(fmt), &a1, &a2, &a3, &a4, &a5, &a6); -#ifdef RB_SCAN_ARGS_KEYWORDS } -#endif switch(NUM2INT(expected)) { case 6: |
