summaryrefslogtreecommitdiff
path: root/spec/ruby/optional
diff options
context:
space:
mode:
authorBenoit Daloze <eregontp@gmail.com>2022-08-29 15:36:29 +0200
committerBenoit Daloze <eregontp@gmail.com>2022-08-29 15:36:29 +0200
commit4ee1a687768338a1928014fc6042c320a1a1af3e (patch)
tree37c1717dcd7a2a757e343a41b827fd096397fbca /spec/ruby/optional
parenta319d3cfdc1afef8497321fee7f690052b16739c (diff)
Update to ruby/spec@d01709f
Diffstat (limited to 'spec/ruby/optional')
-rw-r--r--spec/ruby/optional/capi/encoding_spec.rb42
-rw-r--r--spec/ruby/optional/capi/ext/encoding_spec.c9
-rw-r--r--spec/ruby/optional/capi/ext/string_spec.c7
-rw-r--r--spec/ruby/optional/capi/ext/util_spec.c21
-rw-r--r--spec/ruby/optional/capi/string_spec.rb32
-rw-r--r--spec/ruby/optional/capi/util_spec.rb5
6 files changed, 105 insertions, 11 deletions
diff --git a/spec/ruby/optional/capi/encoding_spec.rb b/spec/ruby/optional/capi/encoding_spec.rb
index ae557b03d7..aa632b963b 100644
--- a/spec/ruby/optional/capi/encoding_spec.rb
+++ b/spec/ruby/optional/capi/encoding_spec.rb
@@ -63,6 +63,48 @@ describe "C-API Encoding function" do
end
end
+ describe "rb_enc_strlen" do
+ before :each do
+ @str = 'こにちわ' # Each codepoint in this string is 3 bytes in UTF-8
+ end
+
+ it "returns the correct string length for the encoding" do
+ @s.rb_enc_strlen(@str, @str.bytesize, Encoding::UTF_8).should == 4
+ @s.rb_enc_strlen(@str, @str.bytesize, Encoding::BINARY).should == 12
+ end
+
+ it "returns the string length based on a fixed-width encoding's character length, even if the encoding is incompatible" do
+ @s.rb_enc_strlen(@str, @str.bytesize, Encoding::UTF_16BE).should == 6
+ @s.rb_enc_strlen(@str, @str.bytesize, Encoding::UTF_16LE).should == 6
+ @s.rb_enc_strlen(@str, @str.bytesize, Encoding::UTF_32BE).should == 3
+ @s.rb_enc_strlen(@str, @str.bytesize, Encoding::UTF_32LE).should == 3
+ end
+
+ it "does not consider strings to be NUL-terminated" do
+ s = "abc\0def"
+ @s.rb_enc_strlen(s, s.bytesize, Encoding::US_ASCII).should == 7
+ @s.rb_enc_strlen(s, s.bytesize, Encoding::UTF_8).should == 7
+ end
+
+ describe "handles broken strings" do
+ it "combines valid character and invalid character counts in UTF-8" do
+ # The result is 3 because `rb_enc_strlen` counts the first valid character and then adds
+ # the byte count for the invalid character that follows for 1 + 2.
+ @s.rb_enc_strlen(@str, 5, Encoding::UTF_8).should == 3
+ end
+
+ it "combines valid character and invalid character counts in UTF-16" do
+ @s.rb_enc_strlen(@str, 5, Encoding::UTF_16BE).should == 3
+ end
+
+ it "rounds up for fixed-width encodings" do
+ @s.rb_enc_strlen(@str, 7, Encoding::UTF_32BE).should == 2
+ @s.rb_enc_strlen(@str, 7, Encoding::UTF_32LE).should == 2
+ @s.rb_enc_strlen(@str, 5, Encoding::BINARY).should == 5
+ end
+ end
+ end
+
describe "rb_enc_find" do
it "returns the encoding of an Encoding" do
@s.rb_enc_find("UTF-8").should == "UTF-8"
diff --git a/spec/ruby/optional/capi/ext/encoding_spec.c b/spec/ruby/optional/capi/ext/encoding_spec.c
index c49f6cde7e..865fc484be 100644
--- a/spec/ruby/optional/capi/ext/encoding_spec.c
+++ b/spec/ruby/optional/capi/ext/encoding_spec.c
@@ -301,6 +301,14 @@ static VALUE encoding_spec_rb_enc_codelen(VALUE self, VALUE code, VALUE encoding
return INT2FIX(rb_enc_codelen(c, enc));
}
+static VALUE encoding_spec_rb_enc_strlen(VALUE self, VALUE str, VALUE length, VALUE encoding) {
+ int l = FIX2INT(length);
+ char *p = RSTRING_PTR(str);
+ char *e = p + l;
+
+ return LONG2FIX(rb_enc_strlen(p, e, rb_to_encoding(encoding)));
+}
+
void Init_encoding_spec(void) {
VALUE cls;
native_rb_encoding_pointer = (rb_encoding**) malloc(sizeof(rb_encoding*));
@@ -335,6 +343,7 @@ void Init_encoding_spec(void) {
rb_define_method(cls, "rb_enc_compatible", encoding_spec_rb_enc_compatible, 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);
rb_define_method(cls, "rb_enc_find", encoding_spec_rb_enc_find, 1);
rb_define_method(cls, "rb_enc_find_index", encoding_spec_rb_enc_find_index, 1);
rb_define_method(cls, "rb_enc_isalnum", encoding_spec_rb_enc_isalnum, 2);
diff --git a/spec/ruby/optional/capi/ext/string_spec.c b/spec/ruby/optional/capi/ext/string_spec.c
index b9a4a55853..9cbb50484d 100644
--- a/spec/ruby/optional/capi/ext/string_spec.c
+++ b/spec/ruby/optional/capi/ext/string_spec.c
@@ -437,6 +437,12 @@ VALUE string_spec_RSTRING_PTR_read(VALUE self, VALUE str, VALUE path) {
return capacities;
}
+VALUE string_spec_RSTRING_PTR_null_terminate(VALUE self, VALUE str, VALUE min_length) {
+ char* ptr = RSTRING_PTR(str);
+ char* end = ptr + RSTRING_LEN(str);
+ return rb_str_new(end, FIX2LONG(min_length));
+}
+
VALUE string_spec_StringValue(VALUE self, VALUE str) {
return StringValue(str);
}
@@ -662,6 +668,7 @@ void Init_string_spec(void) {
rb_define_method(cls, "RSTRING_PTR_after_funcall", string_spec_RSTRING_PTR_after_funcall, 2);
rb_define_method(cls, "RSTRING_PTR_after_yield", string_spec_RSTRING_PTR_after_yield, 1);
rb_define_method(cls, "RSTRING_PTR_read", string_spec_RSTRING_PTR_read, 2);
+ rb_define_method(cls, "RSTRING_PTR_null_terminate", string_spec_RSTRING_PTR_null_terminate, 2);
rb_define_method(cls, "StringValue", string_spec_StringValue, 1);
rb_define_method(cls, "SafeStringValue", string_spec_SafeStringValue, 1);
rb_define_method(cls, "rb_str_hash", string_spec_rb_str_hash, 1);
diff --git a/spec/ruby/optional/capi/ext/util_spec.c b/spec/ruby/optional/capi/ext/util_spec.c
index a7269353c2..95ba71ea9d 100644
--- a/spec/ruby/optional/capi/ext/util_spec.c
+++ b/spec/ruby/optional/capi/ext/util_spec.c
@@ -7,15 +7,18 @@ extern "C" {
#endif
VALUE util_spec_rb_scan_args(VALUE self, VALUE argv, VALUE fmt, VALUE expected, VALUE acc) {
- int i, result, argc = (int)RARRAY_LEN(argv);
- VALUE args[6], failed, a1, a2, a3, a4, a5, a6;
-
- failed = rb_intern("failed");
- a1 = a2 = a3 = a4 = a5 = a6 = failed;
-
- for(i = 0; i < argc; i++) {
- args[i] = rb_ary_entry(argv, i);
- }
+ int result, argc;
+ VALUE a1, a2, a3, a4, a5, a6;
+
+ argc = (int) RARRAY_LEN(argv);
+ VALUE* args = RARRAY_PTR(argv);
+ /* the line above can be replaced with this for Ruby implementations which do not support RARRAY_PTR() yet
+ VALUE args[6];
+ for(int i = 0; i < argc; i++) {
+ args[i] = rb_ary_entry(argv, i);
+ } */
+
+ a1 = a2 = a3 = a4 = a5 = a6 = INT2FIX(-1);
#ifdef RB_SCAN_ARGS_KEYWORDS
if (*RSTRING_PTR(fmt) == 'k') {
diff --git a/spec/ruby/optional/capi/string_spec.rb b/spec/ruby/optional/capi/string_spec.rb
index 7ad4d10ee4..0558fc9f7d 100644
--- a/spec/ruby/optional/capi/string_spec.rb
+++ b/spec/ruby/optional/capi/string_spec.rb
@@ -97,6 +97,32 @@ describe "C-API String function" do
end
end
+ describe "rb_str_set_len on a UTF-16 String" do
+ before :each do
+ @str = "abcdefghij".force_encoding(Encoding::UTF_16BE)
+ # Make sure to unshare the string
+ @s.rb_str_modify(@str)
+ end
+
+ it "inserts two NULL bytes at the length" do
+ @s.rb_str_set_len(@str, 4).b.should == "abcd".b
+ @s.rb_str_set_len(@str, 8).b.should == "abcd\x00\x00gh".b
+ end
+ end
+
+ describe "rb_str_set_len on a UTF-32 String" do
+ before :each do
+ @str = "abcdefghijkl".force_encoding(Encoding::UTF_32BE)
+ # Make sure to unshare the string
+ @s.rb_str_modify(@str)
+ end
+
+ it "inserts four NULL bytes at the length" do
+ @s.rb_str_set_len(@str, 4).b.should == "abcd".b
+ @s.rb_str_set_len(@str, 12).b.should == "abcd\x00\x00\x00\x00ijkl".b
+ end
+ end
+
describe "rb_str_buf_new" do
it "returns the equivalent of an empty string" do
buf = @s.rb_str_buf_new(10, nil)
@@ -592,6 +618,12 @@ describe "C-API String function" do
capacities[0].should < capacities[1]
str.should == "fixture file contents to test read() with RSTRING_PTR"
end
+
+ it "terminates the string with at least (encoding min length) \\0 bytes" do
+ @s.RSTRING_PTR_null_terminate("abc", 1).should == "\x00"
+ @s.RSTRING_PTR_null_terminate("abc".encode("UTF-16BE"), 2).should == "\x00\x00"
+ @s.RSTRING_PTR_null_terminate("abc".encode("UTF-32BE"), 4).should == "\x00\x00\x00\x00"
+ end
end
describe "RSTRING_LEN" do
diff --git a/spec/ruby/optional/capi/util_spec.rb b/spec/ruby/optional/capi/util_spec.rb
index 64b0894087..38f6f47b1a 100644
--- a/spec/ruby/optional/capi/util_spec.rb
+++ b/spec/ruby/optional/capi/util_spec.rb
@@ -15,8 +15,9 @@ describe "C-API Util function" do
end
it "assigns the required arguments scanned" do
- @o.rb_scan_args([1, 2], "2", 2, @acc).should == 2
- ScratchPad.recorded.should == [1, 2]
+ obj = Object.new
+ @o.rb_scan_args([obj, 2], "2", 2, @acc).should == 2
+ ScratchPad.recorded.should == [obj, 2]
end
it "raises an ArgumentError if there are insufficient arguments" do