diff options
Diffstat (limited to 'spec/ruby/core/string/shared')
| -rw-r--r-- | spec/ruby/core/string/shared/chars.rb | 12 | ||||
| -rw-r--r-- | spec/ruby/core/string/shared/codepoints.rb | 8 | ||||
| -rw-r--r-- | spec/ruby/core/string/shared/concat.rb | 1 | ||||
| -rw-r--r-- | spec/ruby/core/string/shared/dedup.rb | 6 | ||||
| -rw-r--r-- | spec/ruby/core/string/shared/each_codepoint_without_block.rb | 6 | ||||
| -rw-r--r-- | spec/ruby/core/string/shared/each_line.rb | 2 | ||||
| -rw-r--r-- | spec/ruby/core/string/shared/encode.rb | 185 | ||||
| -rw-r--r-- | spec/ruby/core/string/shared/eql.rb | 10 | ||||
| -rw-r--r-- | spec/ruby/core/string/shared/length.rb | 10 | ||||
| -rw-r--r-- | spec/ruby/core/string/shared/replace.rb | 1 | ||||
| -rw-r--r-- | spec/ruby/core/string/shared/slice.rb | 21 | ||||
| -rw-r--r-- | spec/ruby/core/string/shared/succ.rb | 3 | ||||
| -rw-r--r-- | spec/ruby/core/string/shared/to_sym.rb | 4 |
13 files changed, 235 insertions, 34 deletions
diff --git a/spec/ruby/core/string/shared/chars.rb b/spec/ruby/core/string/shared/chars.rb index e9fdf89fd6..c730643cf4 100644 --- a/spec/ruby/core/string/shared/chars.rb +++ b/spec/ruby/core/string/shared/chars.rb @@ -21,12 +21,12 @@ describe :string_chars, shared: true do end it "returns characters in the same encoding as self" do - "&%".force_encoding('Shift_JIS').send(@method).to_a.all? {|c| c.encoding.name.should == 'Shift_JIS'} + "&%".dup.force_encoding('Shift_JIS').send(@method).to_a.all? {|c| c.encoding.name.should == 'Shift_JIS'} "&%".encode('BINARY').send(@method).to_a.all? {|c| c.encoding.should == Encoding::BINARY } end it "works with multibyte characters" do - s = "\u{8987}".force_encoding("UTF-8") + s = "\u{8987}".dup.force_encoding("UTF-8") s.bytesize.should == 3 s.send(@method).to_a.should == [s] end @@ -39,14 +39,14 @@ describe :string_chars, shared: true do end it "returns a different character if the String is transcoded" do - s = "\u{20AC}".force_encoding('UTF-8') - s.encode('UTF-8').send(@method).to_a.should == ["\u{20AC}".force_encoding('UTF-8')] + s = "\u{20AC}".dup.force_encoding('UTF-8') + s.encode('UTF-8').send(@method).to_a.should == ["\u{20AC}".dup.force_encoding('UTF-8')] s.encode('iso-8859-15').send(@method).to_a.should == [[0xA4].pack('C').force_encoding('iso-8859-15')] - s.encode('iso-8859-15').encode('UTF-8').send(@method).to_a.should == ["\u{20AC}".force_encoding('UTF-8')] + s.encode('iso-8859-15').encode('UTF-8').send(@method).to_a.should == ["\u{20AC}".dup.force_encoding('UTF-8')] end it "uses the String's encoding to determine what characters it contains" do - s = "\u{24B62}" + s = +"\u{24B62}" s.force_encoding('UTF-8').send(@method).to_a.should == [ s.force_encoding('UTF-8') diff --git a/spec/ruby/core/string/shared/codepoints.rb b/spec/ruby/core/string/shared/codepoints.rb index 0b2e078e0a..1c28ba3d5e 100644 --- a/spec/ruby/core/string/shared/codepoints.rb +++ b/spec/ruby/core/string/shared/codepoints.rb @@ -1,4 +1,4 @@ -# -*- encoding: binary -*- +# encoding: binary describe :string_codepoints, shared: true do it "returns self" do s = "foo" @@ -7,7 +7,7 @@ describe :string_codepoints, shared: true do end it "raises an ArgumentError when self has an invalid encoding and a method is called on the returned Enumerator" do - s = "\xDF".force_encoding(Encoding::UTF_8) + s = "\xDF".dup.force_encoding(Encoding::UTF_8) s.valid_encoding?.should be_false -> { s.send(@method).to_a }.should raise_error(ArgumentError) end @@ -21,7 +21,7 @@ describe :string_codepoints, shared: true do end it "raises an ArgumentError if self's encoding is invalid and a block is given" do - s = "\xDF".force_encoding(Encoding::UTF_8) + s = "\xDF".dup.force_encoding(Encoding::UTF_8) s.valid_encoding?.should be_false -> { s.send(@method) { } }.should raise_error(ArgumentError) end @@ -49,7 +49,7 @@ describe :string_codepoints, shared: true do it "round-trips to the original String using Integer#chr" do s = "\u{13}\u{7711}\u{1010}" - s2 = "" + s2 = +"" s.send(@method) {|n| s2 << n.chr(Encoding::UTF_8)} s.should == s2 end diff --git a/spec/ruby/core/string/shared/concat.rb b/spec/ruby/core/string/shared/concat.rb index ee5ef2a98f..dded9a69e7 100644 --- a/spec/ruby/core/string/shared/concat.rb +++ b/spec/ruby/core/string/shared/concat.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: false describe :string_concat, shared: true do it "concatenates the given argument to self and returns self" do str = 'hello ' diff --git a/spec/ruby/core/string/shared/dedup.rb b/spec/ruby/core/string/shared/dedup.rb index 893fd1e360..1ffd6aa0fd 100644 --- a/spec/ruby/core/string/shared/dedup.rb +++ b/spec/ruby/core/string/shared/dedup.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: false describe :string_dedup, shared: true do it 'returns self if the String is frozen' do input = 'foo'.freeze @@ -47,9 +48,4 @@ describe :string_dedup, shared: true do dynamic.send(@method).should_not equal("this string is frozen".send(@method).freeze) dynamic.send(@method).should equal(dynamic) end - - it "interns the provided string if it is frozen" do - dynamic = "this string is unique and frozen #{rand}".freeze - dynamic.send(@method).should equal(dynamic) - end end diff --git a/spec/ruby/core/string/shared/each_codepoint_without_block.rb b/spec/ruby/core/string/shared/each_codepoint_without_block.rb index 92b7f76032..c88e5c54c7 100644 --- a/spec/ruby/core/string/shared/each_codepoint_without_block.rb +++ b/spec/ruby/core/string/shared/each_codepoint_without_block.rb @@ -1,4 +1,4 @@ -# -*- encoding: binary -*- +# encoding: binary describe :string_each_codepoint_without_block, shared: true do describe "when no block is given" do it "returns an Enumerator" do @@ -6,7 +6,7 @@ describe :string_each_codepoint_without_block, shared: true do end it "returns an Enumerator even when self has an invalid encoding" do - s = "\xDF".force_encoding(Encoding::UTF_8) + s = "\xDF".dup.force_encoding(Encoding::UTF_8) s.valid_encoding?.should be_false s.send(@method).should be_an_instance_of(Enumerator) end @@ -23,7 +23,7 @@ describe :string_each_codepoint_without_block, shared: true do end it "should return the size of the string even when the string has an invalid encoding" do - s = "\xDF".force_encoding(Encoding::UTF_8) + s = "\xDF".dup.force_encoding(Encoding::UTF_8) s.valid_encoding?.should be_false s.send(@method).size.should == 1 end diff --git a/spec/ruby/core/string/shared/each_line.rb b/spec/ruby/core/string/shared/each_line.rb index a14b4d7779..231a6d9d4f 100644 --- a/spec/ruby/core/string/shared/each_line.rb +++ b/spec/ruby/core/string/shared/each_line.rb @@ -106,7 +106,7 @@ describe :string_each_line, shared: true do end it "does not care if the string is modified while substituting" do - str = "hello\nworld." + str = +"hello\nworld." out = [] str.send(@method){|x| out << x; str[-1] = '!' }.should == "hello\nworld!" out.should == ["hello\n", "world."] diff --git a/spec/ruby/core/string/shared/encode.rb b/spec/ruby/core/string/shared/encode.rb index a73de5b943..9466308886 100644 --- a/spec/ruby/core/string/shared/encode.rb +++ b/spec/ruby/core/string/shared/encode.rb @@ -1,4 +1,5 @@ # -*- encoding: utf-8 -*- +# frozen_string_literal: false describe :string_encode, shared: true do describe "when passed no options" do it "transcodes to Encoding.default_internal when set" do @@ -193,6 +194,190 @@ describe :string_encode, shared: true do end end + describe "given the fallback option" do + context "given a hash" do + it "looks up the replacement value from the hash" do + encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: { "\ufffd" => "bar" }) + encoded.should == "Bbar" + end + + it "calls to_str on the returned value" do + obj = Object.new + obj.should_receive(:to_str).and_return("bar") + encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: { "\ufffd" => obj }) + encoded.should == "Bbar" + end + + it "does not call to_s on the returned value" do + obj = Object.new + obj.should_not_receive(:to_s) + -> { + "B\ufffd".encode(Encoding::US_ASCII, fallback: { "\ufffd" => obj }) + }.should raise_error(TypeError, "no implicit conversion of Object into String") + end + + it "raises an error if the key is not present in the hash" do + -> { + "B\ufffd".encode(Encoding::US_ASCII, fallback: { "foo" => "bar" }) + }.should raise_error(Encoding::UndefinedConversionError, "U+FFFD from UTF-8 to US-ASCII") + end + + it "raises an error if the value is itself invalid" do + -> { + "B\ufffd".encode(Encoding::US_ASCII, fallback: { "\ufffd" => "\uffee" }) + }.should raise_error(ArgumentError, "too big fallback string") + end + + it "uses the hash's default value if set" do + hash = {} + hash.default = "bar" + encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: hash) + encoded.should == "Bbar" + end + + it "uses the result of calling default_proc if set" do + hash = {} + hash.default_proc = -> _, _ { "bar" } + encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: hash) + encoded.should == "Bbar" + end + end + + context "given an object inheriting from Hash" do + before do + klass = Class.new(Hash) + @hash_like = klass.new + @hash_like["\ufffd"] = "bar" + end + + it "looks up the replacement value from the object" do + encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: @hash_like) + encoded.should == "Bbar" + end + end + + context "given an object responding to []" do + before do + klass = Class.new do + def [](c) = c.bytes.inspect + end + @hash_like = klass.new + end + + it "calls [] on the object, passing the invalid character" do + encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: @hash_like) + encoded.should == "B[239, 191, 189]" + end + end + + context "given an object not responding to []" do + before do + @non_hash_like = Object.new + end + + it "raises an error" do + -> { + "B\ufffd".encode(Encoding::US_ASCII, fallback: @non_hash_like) + }.should raise_error(Encoding::UndefinedConversionError, "U+FFFD from UTF-8 to US-ASCII") + end + end + + context "given a proc" do + it "calls the proc to get the replacement value, passing in the invalid character" do + encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: proc { |c| c.bytes.inspect }) + encoded.should == "B[239, 191, 189]" + end + + it "calls to_str on the returned value" do + obj = Object.new + obj.should_receive(:to_str).and_return("bar") + encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: proc { |c| obj }) + encoded.should == "Bbar" + end + + it "does not call to_s on the returned value" do + obj = Object.new + obj.should_not_receive(:to_s) + -> { + "B\ufffd".encode(Encoding::US_ASCII, fallback: proc { |c| obj }) + }.should raise_error(TypeError, "no implicit conversion of Object into String") + end + + it "raises an error if the returned value is itself invalid" do + -> { + "B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { "\uffee" }) + }.should raise_error(ArgumentError, "too big fallback string") + end + end + + context "given a lambda" do + it "calls the lambda to get the replacement value, passing in the invalid character" do + encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { c.bytes.inspect }) + encoded.should == "B[239, 191, 189]" + end + + it "calls to_str on the returned value" do + obj = Object.new + obj.should_receive(:to_str).and_return("bar") + encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { obj }) + encoded.should == "Bbar" + end + + it "does not call to_s on the returned value" do + obj = Object.new + obj.should_not_receive(:to_s) + -> { + "B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { obj }) + }.should raise_error(TypeError, "no implicit conversion of Object into String") + end + + it "raises an error if the returned value is itself invalid" do + -> { + "B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { "\uffee" }) + }.should raise_error(ArgumentError, "too big fallback string") + end + end + + context "given a method" do + def replace(c) = c.bytes.inspect + def replace_bad(c) = "\uffee" + + def replace_to_str(c) + obj = Object.new + obj.should_receive(:to_str).and_return("bar") + obj + end + + def replace_to_s(c) + obj = Object.new + obj.should_not_receive(:to_s) + obj + end + + it "calls the method to get the replacement value, passing in the invalid character" do + encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: method(:replace)) + encoded.should == "B[239, 191, 189]" + end + + it "calls to_str on the returned value" do + encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: method(:replace_to_str)) + encoded.should == "Bbar" + end + + it "does not call to_s on the returned value" do + -> { + "B\ufffd".encode(Encoding::US_ASCII, fallback: method(:replace_to_s)) + }.should raise_error(TypeError, "no implicit conversion of Object into String") + end + + it "raises an error if the returned value is itself invalid" do + -> { + "B\ufffd".encode(Encoding::US_ASCII, fallback: method(:replace_bad)) + }.should raise_error(ArgumentError, "too big fallback string") + end + end + end + describe "given the xml: :text option" do it "replaces all instances of '&' with '&'" do '& and &'.send(@method, "UTF-8", xml: :text).should == '& and &' diff --git a/spec/ruby/core/string/shared/eql.rb b/spec/ruby/core/string/shared/eql.rb index 6f268c929c..d5af337d53 100644 --- a/spec/ruby/core/string/shared/eql.rb +++ b/spec/ruby/core/string/shared/eql.rb @@ -1,4 +1,4 @@ -# -*- encoding: binary -*- +# encoding: binary require_relative '../../../spec_helper' require_relative '../fixtures/classes' @@ -13,15 +13,15 @@ describe :string_eql_value, shared: true do end it "ignores encoding difference of compatible string" do - "hello".force_encoding("utf-8").send(@method, "hello".force_encoding("iso-8859-1")).should be_true + "hello".dup.force_encoding("utf-8").send(@method, "hello".dup.force_encoding("iso-8859-1")).should be_true end it "considers encoding difference of incompatible string" do - "\xff".force_encoding("utf-8").send(@method, "\xff".force_encoding("iso-8859-1")).should be_false + "\xff".dup.force_encoding("utf-8").send(@method, "\xff".dup.force_encoding("iso-8859-1")).should be_false end it "considers encoding compatibility" do - "abcd".force_encoding("utf-8").send(@method, "abcd".force_encoding("utf-32le")).should be_false + "abcd".dup.force_encoding("utf-8").send(@method, "abcd".dup.force_encoding("utf-32le")).should be_false end it "ignores subclass differences" do @@ -33,6 +33,6 @@ describe :string_eql_value, shared: true do end it "returns true when comparing 2 empty strings but one is not ASCII-compatible" do - "".send(@method, "".force_encoding('iso-2022-jp')).should == true + "".send(@method, "".dup.force_encoding('iso-2022-jp')).should == true end end diff --git a/spec/ruby/core/string/shared/length.rb b/spec/ruby/core/string/shared/length.rb index 94e5ec135b..ae572ba755 100644 --- a/spec/ruby/core/string/shared/length.rb +++ b/spec/ruby/core/string/shared/length.rb @@ -18,7 +18,7 @@ describe :string_length, shared: true do end it "returns the length of the new self after encoding is changed" do - str = 'こにちわ' + str = +'こにちわ' str.send(@method) str.force_encoding('BINARY').send(@method).should == 12 @@ -44,12 +44,12 @@ describe :string_length, shared: true do end it "adds 1 (and not 2) for a incomplete surrogate in UTF-16" do - "\x00\xd8".force_encoding("UTF-16LE").send(@method).should == 1 - "\xd8\x00".force_encoding("UTF-16BE").send(@method).should == 1 + "\x00\xd8".dup.force_encoding("UTF-16LE").send(@method).should == 1 + "\xd8\x00".dup.force_encoding("UTF-16BE").send(@method).should == 1 end it "adds 1 for a broken sequence in UTF-32" do - "\x04\x03\x02\x01".force_encoding("UTF-32LE").send(@method).should == 1 - "\x01\x02\x03\x04".force_encoding("UTF-32BE").send(@method).should == 1 + "\x04\x03\x02\x01".dup.force_encoding("UTF-32LE").send(@method).should == 1 + "\x01\x02\x03\x04".dup.force_encoding("UTF-32BE").send(@method).should == 1 end end diff --git a/spec/ruby/core/string/shared/replace.rb b/spec/ruby/core/string/shared/replace.rb index a5108d9e7c..24dac0eb27 100644 --- a/spec/ruby/core/string/shared/replace.rb +++ b/spec/ruby/core/string/shared/replace.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: false describe :string_replace, shared: true do it "returns self" do a = "a" diff --git a/spec/ruby/core/string/shared/slice.rb b/spec/ruby/core/string/shared/slice.rb index 3ef4bc50d7..7b9b9f6a14 100644 --- a/spec/ruby/core/string/shared/slice.rb +++ b/spec/ruby/core/string/shared/slice.rb @@ -84,8 +84,8 @@ describe :string_slice_index_length, shared: true do s = "hello there" s.send(@method, 1, 9).encoding.should == s.encoding - a = "hello".force_encoding("binary") - b = " there".force_encoding("ISO-8859-1") + a = "hello".dup.force_encoding("binary") + b = " there".dup.force_encoding("ISO-8859-1") c = (a + b).force_encoding(Encoding::US_ASCII) c.send(@method, 0, 5).encoding.should == Encoding::US_ASCII @@ -119,6 +119,18 @@ describe :string_slice_index_length, shared: true do "hello there".send(@method, -4,-3).should == nil end + platform_is pointer_size: 64 do + it "returns nil if the length is negative big value" do + "hello there".send(@method, 4, -(1 << 31)).should == nil + + # by some reason length < -(1 << 31) on CI on Windows leads to + # 'RangeError: bignum too big to convert into `long'' error + platform_is_not :windows do + "hello there".send(@method, 4, -(1 << 63)).should == nil + end + end + end + it "calls to_int on the given index and the given length" do "hello".send(@method, 0.5, 1).should == "h" "hello".send(@method, 0.5, 2.5).should == "he" @@ -152,6 +164,11 @@ describe :string_slice_index_length, shared: true do -> { "hello".send(@method, 0, bignum_value) }.should raise_error(RangeError) end + it "raises a RangeError if the index or length is too small" do + -> { "hello".send(@method, -bignum_value, 1) }.should raise_error(RangeError) + -> { "hello".send(@method, 0, -bignum_value) }.should raise_error(RangeError) + end + it "returns String instances" do s = StringSpecs::MyString.new("hello") s.send(@method, 0,0).should be_an_instance_of(String) diff --git a/spec/ruby/core/string/shared/succ.rb b/spec/ruby/core/string/shared/succ.rb index 24a729ce26..7c68345f10 100644 --- a/spec/ruby/core/string/shared/succ.rb +++ b/spec/ruby/core/string/shared/succ.rb @@ -1,4 +1,4 @@ -# -*- encoding: binary -*- +# encoding: binary describe :string_succ, shared: true do it "returns an empty string for empty strings" do "".send(@method).should == "" @@ -73,6 +73,7 @@ end describe :string_succ_bang, shared: true do it "is equivalent to succ, but modifies self in place (still returns self)" do ["", "abcd", "THX1138"].each do |s| + s = +s r = s.dup.send(@method) s.send(@method).should equal(s) s.should == r diff --git a/spec/ruby/core/string/shared/to_sym.rb b/spec/ruby/core/string/shared/to_sym.rb index 52d8314211..833eae100e 100644 --- a/spec/ruby/core/string/shared/to_sym.rb +++ b/spec/ruby/core/string/shared/to_sym.rb @@ -56,9 +56,9 @@ describe :string_to_sym, shared: true do it "ignores existing symbols with different encoding" do source = "fée" - iso_symbol = source.force_encoding(Encoding::ISO_8859_1).send(@method) + iso_symbol = source.dup.force_encoding(Encoding::ISO_8859_1).send(@method) iso_symbol.encoding.should == Encoding::ISO_8859_1 - binary_symbol = source.force_encoding(Encoding::BINARY).send(@method) + binary_symbol = source.dup.force_encoding(Encoding::BINARY).send(@method) binary_symbol.encoding.should == Encoding::BINARY end |
