summaryrefslogtreecommitdiff
path: root/spec/ruby/optional
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/optional')
-rw-r--r--spec/ruby/optional/capi/encoding_spec.rb30
-rw-r--r--spec/ruby/optional/capi/ext/encoding_spec.c5
-rw-r--r--spec/ruby/optional/capi/ext/kernel_spec.c11
-rw-r--r--spec/ruby/optional/capi/ext/string_spec.c10
-rw-r--r--spec/ruby/optional/capi/io_spec.rb240
-rw-r--r--spec/ruby/optional/capi/kernel_spec.rb6
-rw-r--r--spec/ruby/optional/capi/object_spec.rb2
-rw-r--r--spec/ruby/optional/capi/spec_helper.rb6
-rw-r--r--spec/ruby/optional/capi/string_spec.rb125
-rw-r--r--spec/ruby/optional/capi/struct_spec.rb142
10 files changed, 381 insertions, 196 deletions
diff --git a/spec/ruby/optional/capi/encoding_spec.rb b/spec/ruby/optional/capi/encoding_spec.rb
index c14983c7ea..734b5f1253 100644
--- a/spec/ruby/optional/capi/encoding_spec.rb
+++ b/spec/ruby/optional/capi/encoding_spec.rb
@@ -745,4 +745,34 @@ describe "C-API Encoding function" do
ruby_exe(code, args: "2>&1", exit_status: 1).should.include?('too many encoding (> 256) (EncodingError)')
end
end
+
+ describe "ONIGENC_IS_UNICODE" do
+ it "is true only for select UTF-related encodings" do
+ unicode = [
+ Encoding::UTF_8,
+ Encoding::UTF8_DOCOMO,
+ Encoding::UTF8_KDDI,
+ Encoding::UTF8_MAC,
+ Encoding::UTF8_SOFTBANK,
+ Encoding::CESU_8,
+ Encoding::UTF_16LE,
+ Encoding::UTF_16BE,
+ Encoding::UTF_32LE,
+ Encoding::UTF_32BE
+ ]
+ unicode.each do |enc|
+ @s.should.ONIGENC_IS_UNICODE(enc)
+ end
+
+ (Encoding.list - unicode).each { |enc|
+ @s.should_not.ONIGENC_IS_UNICODE(enc)
+ }
+ end
+
+ # Redundant with the above but more explicit
+ it "is false for the dummy UTF-16 and UTF-32 encodings" do
+ @s.should_not.ONIGENC_IS_UNICODE(Encoding::UTF_16)
+ @s.should_not.ONIGENC_IS_UNICODE(Encoding::UTF_32)
+ end
+ end
end
diff --git a/spec/ruby/optional/capi/ext/encoding_spec.c b/spec/ruby/optional/capi/ext/encoding_spec.c
index aa8662cfbd..98d4e2e3b7 100644
--- a/spec/ruby/optional/capi/ext/encoding_spec.c
+++ b/spec/ruby/optional/capi/ext/encoding_spec.c
@@ -324,6 +324,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*));
@@ -384,6 +388,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/kernel_spec.c b/spec/ruby/optional/capi/ext/kernel_spec.c
index a8fed21b59..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>
@@ -337,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));
}
@@ -434,6 +444,7 @@ 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);
diff --git a/spec/ruby/optional/capi/ext/string_spec.c b/spec/ruby/optional/capi/ext/string_spec.c
index 094013e049..74aa9e56e8 100644
--- a/spec/ruby/optional/capi/ext/string_spec.c
+++ b/spec/ruby/optional/capi/ext/string_spec.c
@@ -581,6 +581,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);
@@ -681,6 +689,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/io_spec.rb b/spec/ruby/optional/capi/io_spec.rb
index ab7a7fc8f6..dc4ac3e374 100644
--- a/spec/ruby/optional/capi/io_spec.rb
+++ b/spec/ruby/optional/capi/io_spec.rb
@@ -494,166 +494,164 @@ describe "C-API IO function" do
end
end
- ruby_version_is "3.3" do
- describe "rb_io_mode" do
- it "returns the mode" do
- (@o.rb_io_mode(@r_io) & 0b11).should == 0b01
- (@o.rb_io_mode(@w_io) & 0b11).should == 0b10
- (@o.rb_io_mode(@rw_io) & 0b11).should == 0b11
- end
+ describe "rb_io_mode" do
+ it "returns the mode" do
+ (@o.rb_io_mode(@r_io) & 0b11).should == 0b01
+ (@o.rb_io_mode(@w_io) & 0b11).should == 0b10
+ (@o.rb_io_mode(@rw_io) & 0b11).should == 0b11
end
+ end
- describe "rb_io_path" do
- it "returns the IO#path" do
- @o.rb_io_path(@r_io).should == @r_io.path
- @o.rb_io_path(@rw_io).should == @rw_io.path
- @o.rb_io_path(@rw_io).should == @name
- end
+ describe "rb_io_path" do
+ it "returns the IO#path" do
+ @o.rb_io_path(@r_io).should == @r_io.path
+ @o.rb_io_path(@rw_io).should == @rw_io.path
+ @o.rb_io_path(@rw_io).should == @name
end
+ end
- describe "rb_io_closed_p" do
- it "returns false when io is not closed" do
- @o.rb_io_closed_p(@r_io).should == false
- @r_io.closed?.should == false
- end
+ describe "rb_io_closed_p" do
+ it "returns false when io is not closed" do
+ @o.rb_io_closed_p(@r_io).should == false
+ @r_io.closed?.should == false
+ end
- it "returns true when io is closed" do
- @r_io.close
+ it "returns true when io is closed" do
+ @r_io.close
- @o.rb_io_closed_p(@r_io).should == true
- @r_io.closed?.should == true
- end
+ @o.rb_io_closed_p(@r_io).should == true
+ @r_io.closed?.should == true
end
+ end
- quarantine! do # "Errno::EBADF: Bad file descriptor" at closing @r_io, @rw_io etc in the after :each hook
- describe "rb_io_open_descriptor" do
- it "creates a new IO instance" do
- io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
- io.should.is_a?(IO)
- end
-
- it "return an instance of the specified class" do
- io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
- io.class.should == File
+ quarantine! do # "Errno::EBADF: Bad file descriptor" at closing @r_io, @rw_io etc in the after :each hook
+ describe "rb_io_open_descriptor" do
+ it "creates a new IO instance" do
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.should.is_a?(IO)
+ end
- io = @o.rb_io_open_descriptor(IO, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
- io.class.should == IO
- end
+ it "return an instance of the specified class" do
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.class.should == File
- it "sets the specified file descriptor" do
- io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
- io.fileno.should == @r_io.fileno
- end
+ io = @o.rb_io_open_descriptor(IO, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.class.should == IO
+ end
- it "sets the specified path" do
- io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
- io.path.should == "a.txt"
- end
+ it "sets the specified file descriptor" do
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.fileno.should == @r_io.fileno
+ end
- it "sets the specified mode" do
- io = @o.rb_io_open_descriptor(File, @r_io.fileno, CApiIOSpecs::FMODE_BINMODE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
- io.should.binmode?
+ it "sets the specified path" do
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.path.should == "a.txt"
+ end
- io = @o.rb_io_open_descriptor(File, @r_io.fileno, CApiIOSpecs::FMODE_TEXTMODE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
- io.should_not.binmode?
- end
+ it "sets the specified mode" do
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, CApiIOSpecs::FMODE_BINMODE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.should.binmode?
- it "sets the specified timeout" do
- io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
- io.timeout.should == 60
- end
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, CApiIOSpecs::FMODE_TEXTMODE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.should_not.binmode?
+ end
- it "sets the specified internal encoding" do
- io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
- io.internal_encoding.should == Encoding::US_ASCII
- end
+ it "sets the specified timeout" do
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.timeout.should == 60
+ end
- it "sets the specified external encoding" do
- io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
- io.external_encoding.should == Encoding::UTF_8
- end
+ it "sets the specified internal encoding" do
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.internal_encoding.should == Encoding::US_ASCII
+ end
- it "does not apply the specified encoding flags" do
- name = tmp("rb_io_open_descriptor_specs")
- File.write(name, "123\r\n456\n89")
- file = File.open(name, "r")
+ it "sets the specified external encoding" do
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.external_encoding.should == Encoding::UTF_8
+ end
- io = @o.rb_io_open_descriptor(File, file.fileno, CApiIOSpecs::FMODE_READABLE, "a.txt", 60, "US-ASCII", "UTF-8", CApiIOSpecs::ECONV_UNIVERSAL_NEWLINE_DECORATOR, {})
- io.read_nonblock(20).should == "123\r\n456\n89"
- ensure
- file.close
- rm_r name
- end
+ it "does not apply the specified encoding flags" do
+ name = tmp("rb_io_open_descriptor_specs")
+ File.write(name, "123\r\n456\n89")
+ file = File.open(name, "r")
- it "ignores the IO open options" do
- io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {external_encoding: "windows-1251"})
- io.external_encoding.should == Encoding::UTF_8
+ io = @o.rb_io_open_descriptor(File, file.fileno, CApiIOSpecs::FMODE_READABLE, "a.txt", 60, "US-ASCII", "UTF-8", CApiIOSpecs::ECONV_UNIVERSAL_NEWLINE_DECORATOR, {})
+ io.read_nonblock(20).should == "123\r\n456\n89"
+ ensure
+ file.close
+ rm_r name
+ end
- io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {internal_encoding: "windows-1251"})
- io.internal_encoding.should == Encoding::US_ASCII
+ it "ignores the IO open options" do
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {external_encoding: "windows-1251"})
+ io.external_encoding.should == Encoding::UTF_8
- io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {encoding: "windows-1251:binary"})
- io.external_encoding.should == Encoding::UTF_8
- io.internal_encoding.should == Encoding::US_ASCII
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {internal_encoding: "windows-1251"})
+ io.internal_encoding.should == Encoding::US_ASCII
- io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {textmode: false})
- io.should_not.binmode?
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {encoding: "windows-1251:binary"})
+ io.external_encoding.should == Encoding::UTF_8
+ io.internal_encoding.should == Encoding::US_ASCII
- io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {binmode: true})
- io.should_not.binmode?
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {textmode: false})
+ io.should_not.binmode?
- io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {autoclose: false})
- io.should.autoclose?
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {binmode: true})
+ io.should_not.binmode?
- io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {path: "a.txt"})
- io.path.should == "a.txt"
- end
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {autoclose: false})
+ io.should.autoclose?
- it "ignores the IO encoding options" do
- io = @o.rb_io_open_descriptor(File, @w_io.fileno, CApiIOSpecs::FMODE_WRITABLE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {crlf_newline: true})
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {path: "a.txt"})
+ io.path.should == "a.txt"
+ end
- io.write("123\r\n456\n89")
- io.flush
+ it "ignores the IO encoding options" do
+ io = @o.rb_io_open_descriptor(File, @w_io.fileno, CApiIOSpecs::FMODE_WRITABLE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {crlf_newline: true})
- @r_io.read_nonblock(20).should == "123\r\n456\n89"
- end
+ io.write("123\r\n456\n89")
+ io.flush
- it "allows wrong mode" do
- io = @o.rb_io_open_descriptor(File, @w_io.fileno, CApiIOSpecs::FMODE_READABLE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
- io.should.is_a?(File)
+ @r_io.read_nonblock(20).should == "123\r\n456\n89"
+ end
- platform_is_not :windows do
- -> { io.read_nonblock(1) }.should raise_error(Errno::EBADF)
- end
+ it "allows wrong mode" do
+ io = @o.rb_io_open_descriptor(File, @w_io.fileno, CApiIOSpecs::FMODE_READABLE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.should.is_a?(File)
- platform_is :windows do
- -> { io.read_nonblock(1) }.should raise_error(IO::EWOULDBLOCKWaitReadable)
- end
+ platform_is_not :windows do
+ -> { io.read_nonblock(1) }.should raise_error(Errno::EBADF)
end
- it "tolerates NULL as rb_io_encoding *encoding parameter" do
- io = @o.rb_io_open_descriptor_without_encoding(File, @r_io.fileno, 0, "a.txt", 60)
- io.should.is_a?(File)
+ platform_is :windows do
+ -> { io.read_nonblock(1) }.should raise_error(IO::EWOULDBLOCKWaitReadable)
end
+ end
- it "deduplicates path String" do
- path = "a.txt".dup
- io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, path, 60, "US-ASCII", "UTF-8", 0, {})
- io.path.should_not equal(path)
+ it "tolerates NULL as rb_io_encoding *encoding parameter" do
+ io = @o.rb_io_open_descriptor_without_encoding(File, @r_io.fileno, 0, "a.txt", 60)
+ io.should.is_a?(File)
+ end
- path = "a.txt".freeze
- io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, path, 60, "US-ASCII", "UTF-8", 0, {})
- io.path.should_not equal(path)
- end
+ it "deduplicates path String" do
+ path = "a.txt".dup
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, path, 60, "US-ASCII", "UTF-8", 0, {})
+ io.path.should_not equal(path)
+
+ path = "a.txt".freeze
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, path, 60, "US-ASCII", "UTF-8", 0, {})
+ io.path.should_not equal(path)
+ end
- it "calls #to_str to convert a path to a String" do
- path = Object.new
- def path.to_str; "a.txt"; end
+ it "calls #to_str to convert a path to a String" do
+ path = Object.new
+ def path.to_str; "a.txt"; end
- io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, path, 60, "US-ASCII", "UTF-8", 0, {})
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, path, 60, "US-ASCII", "UTF-8", 0, {})
- io.path.should == "a.txt"
- end
+ io.path.should == "a.txt"
end
end
end
diff --git a/spec/ruby/optional/capi/kernel_spec.rb b/spec/ruby/optional/capi/kernel_spec.rb
index 6633ee50c1..0a2362fb30 100644
--- a/spec/ruby/optional/capi/kernel_spec.rb
+++ b/spec/ruby/optional/capi/kernel_spec.rb
@@ -703,6 +703,12 @@ describe "C-API Kernel function" do
end
end
+ describe "ruby_vm_at_exit" do
+ it "runs a C function after the VM is terminated" do
+ ruby_exe("require #{kernel_path.inspect}; CApiKernelSpecs.new.ruby_vm_at_exit").should == "ruby_vm_at_exit hook ran\n"
+ end
+ end
+
describe "rb_f_sprintf" do
it "returns a string according to format and arguments" do
@s.rb_f_sprintf(["%d %f %s", 10, 2.5, "test"]).should == "10 2.500000 test"
diff --git a/spec/ruby/optional/capi/object_spec.rb b/spec/ruby/optional/capi/object_spec.rb
index 8b4d8a9bba..6716fd9e33 100644
--- a/spec/ruby/optional/capi/object_spec.rb
+++ b/spec/ruby/optional/capi/object_spec.rb
@@ -1004,7 +1004,6 @@ describe "CApiObject" do
it "calls the callback function for each cvar and ivar on a class" do
exp = [:@@cvar, :foo, :@@cvar2, :bar, :@ivar, :baz]
- exp.unshift(:__classpath__, 'CApiObjectSpecs::CVars') if RUBY_VERSION < "3.3"
ary = @o.rb_ivar_foreach(CApiObjectSpecs::CVars)
ary.should == exp
@@ -1012,7 +1011,6 @@ describe "CApiObject" do
it "calls the callback function for each cvar and ivar on a module" do
exp = [:@@mvar, :foo, :@@mvar2, :bar, :@ivar, :baz]
- exp.unshift(:__classpath__, 'CApiObjectSpecs::MVars') if RUBY_VERSION < "3.3"
ary = @o.rb_ivar_foreach(CApiObjectSpecs::MVars)
ary.should == exp
diff --git a/spec/ruby/optional/capi/spec_helper.rb b/spec/ruby/optional/capi/spec_helper.rb
index e7abf46e6c..d937c967d0 100644
--- a/spec/ruby/optional/capi/spec_helper.rb
+++ b/spec/ruby/optional/capi/spec_helper.rb
@@ -59,7 +59,11 @@ def compile_extension(name)
tmpdir = tmp("cext_#{name}")
Dir.mkdir(tmpdir)
begin
- ["#{core_ext_dir}/rubyspec.h", "#{spec_ext_dir}/#{ext}.c"].each do |file|
+ files = ["#{core_ext_dir}/rubyspec.h", "#{spec_ext_dir}/#{ext}.c"]
+ if spec_ext_dir != core_ext_dir
+ files += Dir.glob("#{spec_ext_dir}/*.h")
+ end
+ files.each do |file|
if cxx and file.end_with?('.c')
cp file, "#{tmpdir}/#{File.basename(file, '.c')}.cpp"
else
diff --git a/spec/ruby/optional/capi/string_spec.rb b/spec/ruby/optional/capi/string_spec.rb
index 72f20ee6a5..889f0a6cfe 100644
--- a/spec/ruby/optional/capi/string_spec.rb
+++ b/spec/ruby/optional/capi/string_spec.rb
@@ -1369,8 +1369,133 @@ describe "C-API String function" do
result1.should_not.equal?(result2)
end
+ it "preserves the encoding of the original string" do
+ result1 = @s.rb_str_to_interned_str("hello".dup.force_encoding(Encoding::US_ASCII))
+ result2 = @s.rb_str_to_interned_str("hello".dup.force_encoding(Encoding::UTF_8))
+ result1.encoding.should == Encoding::US_ASCII
+ result2.encoding.should == Encoding::UTF_8
+ end
+
it "returns the same string as String#-@" do
@s.rb_str_to_interned_str("hello").should.equal?(-"hello")
end
end
+
+ describe "rb_interned_str" do
+ it "returns a frozen string" do
+ str = "hello"
+ result = @s.rb_interned_str(str, str.bytesize)
+ result.should.is_a?(String)
+ result.should.frozen?
+ result.encoding.should == Encoding::US_ASCII
+ end
+
+ it "returns the same frozen string" do
+ str = "hello"
+ result1 = @s.rb_interned_str(str, str.bytesize)
+ result2 = @s.rb_interned_str(str, str.bytesize)
+ result1.should.equal?(result2)
+ end
+
+ it "supports strings with embedded null bytes" do
+ str = "foo\x00bar\x00baz".b
+ result = @s.rb_interned_str(str, str.bytesize)
+ result.should == str
+ end
+
+ it "return US_ASCII encoding for an empty string" do
+ result = @s.rb_interned_str("", 0)
+ result.should == ""
+ result.encoding.should == Encoding::US_ASCII
+ end
+
+ it "returns US_ASCII encoding for strings of only 7 bit ASCII" do
+ 0x00.upto(0x7f).each do |char|
+ result = @s.rb_interned_str(char.chr, 1)
+ result.encoding.should == Encoding::US_ASCII
+ end
+ end
+
+ ruby_bug "21842", ""..."4.1" do
+ it "returns BINARY encoding for strings that use the 8th bit" do
+ 0x80.upto(0xff) do |char|
+ result = @s.rb_interned_str(char.chr, 1)
+ result.encoding.should == Encoding::BINARY
+ end
+ end
+ end
+
+ it 'returns the same string when using non-ascii characters' do
+ str = 'こんにちは'
+ result1 = @s.rb_interned_str(str, str.bytesize)
+ result2 = @s.rb_interned_str(str, str.bytesize)
+ result1.should.equal?(result2)
+ end
+
+ ruby_bug "21842", ""..."4.1" do
+ it "returns the same string as String#-@" do
+ str = "hello".dup.force_encoding(Encoding::US_ASCII)
+ @s.rb_interned_str(str, str.bytesize).should.equal?(-str)
+ end
+ end
+ end
+
+ describe "rb_interned_str_cstr" do
+ it "returns a frozen string" do
+ str = "hello"
+ result = @s.rb_interned_str_cstr(str)
+ result.should.is_a?(String)
+ result.should.frozen?
+ result.encoding.should == Encoding::US_ASCII
+ end
+
+ it "returns the same frozen string" do
+ str = "hello"
+ result1 = @s.rb_interned_str_cstr(str)
+ result2 = @s.rb_interned_str_cstr(str)
+ result1.should.equal?(result2)
+ end
+
+ it "does not support strings with embedded null bytes" do
+ str = "foo\x00bar\x00baz".b
+ result = @s.rb_interned_str_cstr(str)
+ result.should == "foo"
+ end
+
+ it "return US_ASCII encoding for an empty string" do
+ result = @s.rb_interned_str_cstr("")
+ result.should == ""
+ result.encoding.should == Encoding::US_ASCII
+ end
+
+ it "returns US_ASCII encoding for strings of only 7 bit ASCII" do
+ 0x01.upto(0x7f).each do |char|
+ result = @s.rb_interned_str_cstr(char.chr)
+ result.encoding.should == Encoding::US_ASCII
+ end
+ end
+
+ ruby_bug "21842", ""..."4.1" do
+ it "returns BINARY encoding for strings that use the 8th bit" do
+ 0x80.upto(0xff) do |char|
+ result = @s.rb_interned_str_cstr(char.chr)
+ result.encoding.should == Encoding::BINARY
+ end
+ end
+ end
+
+ it 'returns the same string when using non-ascii characters' do
+ str = 'こんにちは'
+ result1 = @s.rb_interned_str_cstr(str)
+ result2 = @s.rb_interned_str_cstr(str)
+ result1.should.equal?(result2)
+ end
+
+ ruby_bug "21842", ""..."4.1" do
+ it "returns the same string as String#-@" do
+ str = "hello".dup.force_encoding(Encoding::US_ASCII)
+ @s.rb_interned_str_cstr(str).should.equal?(-str)
+ end
+ end
+ end
end
diff --git a/spec/ruby/optional/capi/struct_spec.rb b/spec/ruby/optional/capi/struct_spec.rb
index cc8d7f932e..3f9eff52bc 100644
--- a/spec/ruby/optional/capi/struct_spec.rb
+++ b/spec/ruby/optional/capi/struct_spec.rb
@@ -239,78 +239,76 @@ describe "C-API Struct function" do
end
end
-ruby_version_is "3.3" do
- describe "C-API Data function" do
- before :all do
- @s = CApiStructSpecs.new
- @klass = @s.rb_data_define(nil, "a", "b", "c")
- end
-
- describe "rb_data_define" do
- it "returns a subclass of Data class when passed nil as the first argument" do
- @klass.should.is_a? Class
- @klass.superclass.should == Data
- end
-
- it "returns a subclass of a class when passed as the first argument" do
- superclass = Class.new(Data)
- klass = @s.rb_data_define(superclass, "a", "b", "c")
-
- klass.should.is_a? Class
- klass.superclass.should == superclass
- end
-
- it "creates readers for the members" do
- obj = @klass.new(1, 2, 3)
-
- obj.a.should == 1
- obj.b.should == 2
- obj.c.should == 3
- end
-
- it "returns the member names as Symbols" do
- obj = @klass.new(0, 0, 0)
-
- obj.members.should == [:a, :b, :c]
- end
-
- it "raises an ArgumentError if arguments contain duplicate member name" do
- -> { @s.rb_data_define(nil, "a", "b", "a") }.should raise_error(ArgumentError)
- end
-
- it "raises when first argument is not a class" do
- -> { @s.rb_data_define([], "a", "b", "c") }.should raise_error(TypeError, "wrong argument type Array (expected Class)")
- end
- end
-
- describe "rb_struct_initialize" do
- it "sets all members for a Data instance" do
- data = @klass.allocate
- @s.rb_struct_initialize(data, [1, 2, 3]).should == nil
- data.a.should == 1
- data.b.should == 2
- data.c.should == 3
- end
-
- it "freezes the Data instance" do
- data = @klass.allocate
- @s.rb_struct_initialize(data, [1, 2, 3]).should == nil
- data.should.frozen?
- -> { @s.rb_struct_initialize(data, [1, 2, 3]) }.should raise_error(FrozenError)
- end
-
- it "raises ArgumentError if too many values" do
- data = @klass.allocate
- -> { @s.rb_struct_initialize(data, [1, 2, 3, 4]) }.should raise_error(ArgumentError, "struct size differs")
- end
-
- it "treats missing values as nil" do
- data = @klass.allocate
- @s.rb_struct_initialize(data, [1, 2]).should == nil
- data.a.should == 1
- data.b.should == 2
- data.c.should == nil
- end
+describe "C-API Data function" do
+ before :all do
+ @s = CApiStructSpecs.new
+ @klass = @s.rb_data_define(nil, "a", "b", "c")
+ end
+
+ describe "rb_data_define" do
+ it "returns a subclass of Data class when passed nil as the first argument" do
+ @klass.should.is_a? Class
+ @klass.superclass.should == Data
+ end
+
+ it "returns a subclass of a class when passed as the first argument" do
+ superclass = Class.new(Data)
+ klass = @s.rb_data_define(superclass, "a", "b", "c")
+
+ klass.should.is_a? Class
+ klass.superclass.should == superclass
+ end
+
+ it "creates readers for the members" do
+ obj = @klass.new(1, 2, 3)
+
+ obj.a.should == 1
+ obj.b.should == 2
+ obj.c.should == 3
+ end
+
+ it "returns the member names as Symbols" do
+ obj = @klass.new(0, 0, 0)
+
+ obj.members.should == [:a, :b, :c]
+ end
+
+ it "raises an ArgumentError if arguments contain duplicate member name" do
+ -> { @s.rb_data_define(nil, "a", "b", "a") }.should raise_error(ArgumentError)
+ end
+
+ it "raises when first argument is not a class" do
+ -> { @s.rb_data_define([], "a", "b", "c") }.should raise_error(TypeError, "wrong argument type Array (expected Class)")
+ end
+ end
+
+ describe "rb_struct_initialize" do
+ it "sets all members for a Data instance" do
+ data = @klass.allocate
+ @s.rb_struct_initialize(data, [1, 2, 3]).should == nil
+ data.a.should == 1
+ data.b.should == 2
+ data.c.should == 3
+ end
+
+ it "freezes the Data instance" do
+ data = @klass.allocate
+ @s.rb_struct_initialize(data, [1, 2, 3]).should == nil
+ data.should.frozen?
+ -> { @s.rb_struct_initialize(data, [1, 2, 3]) }.should raise_error(FrozenError)
+ end
+
+ it "raises ArgumentError if too many values" do
+ data = @klass.allocate
+ -> { @s.rb_struct_initialize(data, [1, 2, 3, 4]) }.should raise_error(ArgumentError, "struct size differs")
+ end
+
+ it "treats missing values as nil" do
+ data = @klass.allocate
+ @s.rb_struct_initialize(data, [1, 2]).should == nil
+ data.a.should == 1
+ data.b.should == 2
+ data.c.should == nil
end
end
end