diff options
Diffstat (limited to 'spec/ruby/core')
27 files changed, 274 insertions, 18 deletions
diff --git a/spec/ruby/core/enumerable/compact_spec.rb b/spec/ruby/core/enumerable/compact_spec.rb new file mode 100644 index 0000000000..86e95dce08 --- /dev/null +++ b/spec/ruby/core/enumerable/compact_spec.rb @@ -0,0 +1,11 @@ +require_relative '../../spec_helper' +require_relative 'fixtures/classes' + +ruby_version_is '3.1' do + describe "Enumerable#compact" do + it 'returns array without nil elements' do + arr = EnumerableSpecs::Numerous.new(nil, 1, 2, nil, true) + arr.compact.should == [1, 2, true] + end + end +end diff --git a/spec/ruby/core/enumerator/lazy/lazy_spec.rb b/spec/ruby/core/enumerator/lazy/lazy_spec.rb index cde9b31066..683dfb81d7 100644 --- a/spec/ruby/core/enumerator/lazy/lazy_spec.rb +++ b/spec/ruby/core/enumerator/lazy/lazy_spec.rb @@ -16,6 +16,10 @@ describe "Enumerator::Lazy" do ] lazy_methods += [:chunk_while, :uniq] + ruby_version_is '3.1' do + lazy_methods += [:compact] + end + Enumerator::Lazy.instance_methods(false).should include(*lazy_methods) end end @@ -26,3 +30,13 @@ describe "Enumerator::Lazy#lazy" do lazy.lazy.should equal(lazy) end end + +ruby_version_is '3.1' do + describe "Enumerator::Lazy#compact" do + it 'returns array without nil elements' do + arr = [1, nil, 3, false, 5].to_enum.lazy.compact + arr.should be_an_instance_of(Enumerator::Lazy) + arr.force.should == [1, 3, false, 5] + end + end +end diff --git a/spec/ruby/core/file/shared/fnmatch.rb b/spec/ruby/core/file/shared/fnmatch.rb index 00682bb64c..94f22144b0 100644 --- a/spec/ruby/core/file/shared/fnmatch.rb +++ b/spec/ruby/core/file/shared/fnmatch.rb @@ -159,10 +159,10 @@ describe :file_fnmatch, shared: true do end it "does not match leading periods in filenames with wildcards by default" do - File.send(@method, '*', '.profile').should == false - File.send(@method, '*', 'home/.profile').should == true - File.send(@method, '*/*', 'home/.profile').should == true - File.send(@method, '*/*', 'dave/.profile', File::FNM_PATHNAME).should == false + File.should_not.send(@method, '*', '.profile') + File.should.send(@method, '*', 'home/.profile') + File.should.send(@method, '*/*', 'home/.profile') + File.should_not.send(@method, '*/*', 'dave/.profile', File::FNM_PATHNAME) end it "matches patterns with leading periods to dotfiles by default" do diff --git a/spec/ruby/core/range/clone_spec.rb b/spec/ruby/core/range/clone_spec.rb new file mode 100644 index 0000000000..cf6ce74da0 --- /dev/null +++ b/spec/ruby/core/range/clone_spec.rb @@ -0,0 +1,26 @@ +require_relative '../../spec_helper' + +describe "Range#clone" do + it "duplicates the range" do + original = (1..3) + copy = original.clone + copy.begin.should == 1 + copy.end.should == 3 + copy.should_not.exclude_end? + copy.should_not.equal? original + + original = ("a"..."z") + copy = original.clone + copy.begin.should == "a" + copy.end.should == "z" + copy.should.exclude_end? + copy.should_not.equal? original + end + + it "maintains the frozen state" do + (1..2).clone.frozen?.should == (1..2).frozen? + (1..).clone.frozen?.should == (1..).frozen? + Range.new(1, 2).clone.frozen?.should == Range.new(1, 2).frozen? + Class.new(Range).new(1, 2).clone.frozen?.should == Class.new(Range).new(1, 2).frozen? + end +end diff --git a/spec/ruby/core/range/dup_spec.rb b/spec/ruby/core/range/dup_spec.rb index 976d4fd1d0..fab3c3f1b2 100644 --- a/spec/ruby/core/range/dup_spec.rb +++ b/spec/ruby/core/range/dup_spec.rb @@ -2,10 +2,12 @@ require_relative '../../spec_helper' describe "Range#dup" do it "duplicates the range" do - copy = (1..3).dup + original = (1..3) + copy = original.dup copy.begin.should == 1 copy.end.should == 3 copy.should_not.exclude_end? + copy.should_not.equal?(original) copy = ("a"..."z").dup copy.begin.should == "a" diff --git a/spec/ruby/core/range/new_spec.rb b/spec/ruby/core/range/new_spec.rb index 85e99babff..40df914b83 100644 --- a/spec/ruby/core/range/new_spec.rb +++ b/spec/ruby/core/range/new_spec.rb @@ -65,5 +65,15 @@ describe "Range.new" do range_exclude.should_not == range_include end + + ruby_version_is "3.0" do + it "creates a frozen range if the class is Range.class" do + Range.new(1, 2).should.frozen? + end + + it "does not create a frozen range if the class is not Range.class" do + Class.new(Range).new(1, 2).should_not.frozen? + end + end end end diff --git a/spec/ruby/core/regexp/shared/quote.rb b/spec/ruby/core/regexp/shared/quote.rb index 33bdfd9979..9533102766 100644 --- a/spec/ruby/core/regexp/shared/quote.rb +++ b/spec/ruby/core/regexp/shared/quote.rb @@ -17,6 +17,11 @@ describe :regexp_quote, shared: true do Regexp.send(@method, str).should == '\+\[\]\(' end + it "works for broken strings" do + Regexp.send(@method, "a.\x85b.".force_encoding("US-ASCII")).should =="a\\.\x85b\\.".force_encoding("US-ASCII") + Regexp.send(@method, "a.\x80".force_encoding("UTF-8")).should == "a\\.\x80".force_encoding("UTF-8") + end + it "sets the encoding of the result to US-ASCII if there are only US-ASCII characters present in the input String" do str = "abc".force_encoding("euc-jp") Regexp.send(@method, str).encoding.should == Encoding::US_ASCII diff --git a/spec/ruby/core/regexp/source_spec.rb b/spec/ruby/core/regexp/source_spec.rb index 709fee49b3..5f253da9ea 100644 --- a/spec/ruby/core/regexp/source_spec.rb +++ b/spec/ruby/core/regexp/source_spec.rb @@ -9,8 +9,26 @@ describe "Regexp#source" do /x(.)xz/.source.should == "x(.)xz" end - it "will remove escape characters" do - /foo\/bar/.source.should == "foo/bar" + it "keeps escape sequences as is" do + /\x20\+/.source.should == '\x20\+' + end + + describe "escaping" do + it "keeps escaping of metacharacter" do + /\$/.source.should == "\\$" + end + + it "keeps escaping of metacharacter used as a terminator" do + %r+\++.source.should == "\\+" + end + + it "removes escaping of non-metacharacter used as a terminator" do + %r@\@@.source.should == "@" + end + + it "keeps escaping of non-metacharacter not used as a terminator" do + /\@/.source.should == "\\@" + end end not_supported_on :opal do diff --git a/spec/ruby/core/string/capitalize_spec.rb b/spec/ruby/core/string/capitalize_spec.rb index 8afaefc021..751f4160a6 100644 --- a/spec/ruby/core/string/capitalize_spec.rb +++ b/spec/ruby/core/string/capitalize_spec.rb @@ -10,6 +10,7 @@ describe "String#capitalize" do "hello".capitalize.should == "Hello" "HELLO".capitalize.should == "Hello" "123ABC".capitalize.should == "123abc" + "abcdef"[1...-1].capitalize.should == "Bcde" end describe "full Unicode case mapping" do @@ -37,7 +38,7 @@ describe "String#capitalize" do end it "handles non-ASCII substrings properly" do - "garçon"[1..-1].capitalize(:ascii).should == "Arçon" + "garçon"[1...-1].capitalize(:ascii).should == "Arço" end end diff --git a/spec/ruby/core/string/delete_prefix_spec.rb b/spec/ruby/core/string/delete_prefix_spec.rb index a063e443d8..17ce18bcca 100644 --- a/spec/ruby/core/string/delete_prefix_spec.rb +++ b/spec/ruby/core/string/delete_prefix_spec.rb @@ -21,6 +21,10 @@ describe "String#delete_prefix" do r.should == s end + it "does not remove partial bytes, only full characters" do + "\xe3\x81\x82".delete_prefix("\xe3").should == "\xe3\x81\x82" + end + it "doesn't set $~" do $~ = nil diff --git a/spec/ruby/core/string/delete_suffix_spec.rb b/spec/ruby/core/string/delete_suffix_spec.rb index 3d3274bc5b..0705c73246 100644 --- a/spec/ruby/core/string/delete_suffix_spec.rb +++ b/spec/ruby/core/string/delete_suffix_spec.rb @@ -21,6 +21,10 @@ describe "String#delete_suffix" do r.should == s end + it "does not remove partial bytes, only full characters" do + "\xe3\x81\x82".delete_suffix("\x82").should == "\xe3\x81\x82" + end + it "doesn't set $~" do $~ = nil diff --git a/spec/ruby/core/string/downcase_spec.rb b/spec/ruby/core/string/downcase_spec.rb index 86d8480889..f0a15f1e25 100644 --- a/spec/ruby/core/string/downcase_spec.rb +++ b/spec/ruby/core/string/downcase_spec.rb @@ -27,6 +27,10 @@ describe "String#downcase" do it "does not downcase non-ASCII characters" do "CÅR".downcase(:ascii).should == "cÅr" end + + it "works with substrings" do + "prefix TÉ"[-2..-1].downcase(:ascii).should == "tÉ" + end end describe "full Unicode case mapping adapted for Turkic languages" do diff --git a/spec/ruby/core/string/encoding_spec.rb b/spec/ruby/core/string/encoding_spec.rb index 4d17a39f29..574a1e2f92 100644 --- a/spec/ruby/core/string/encoding_spec.rb +++ b/spec/ruby/core/string/encoding_spec.rb @@ -10,6 +10,7 @@ describe "String#encoding" do it "is equal to the source encoding by default" do s = StringSpecs::ISO88599Encoding.new s.cedilla.encoding.should == s.source_encoding + s.cedilla.encode("utf-8").should == 350.chr(Encoding::UTF_8) # S-cedilla end it "returns the given encoding if #force_encoding has been called" do diff --git a/spec/ruby/core/string/fixtures/iso-8859-9-encoding.rb b/spec/ruby/core/string/fixtures/iso-8859-9-encoding.rb index 61a691ff78..cfa91dedc3 100644 --- a/spec/ruby/core/string/fixtures/iso-8859-9-encoding.rb +++ b/spec/ruby/core/string/fixtures/iso-8859-9-encoding.rb @@ -4,6 +4,6 @@ module StringSpecs def source_encoding; __ENCODING__; end def x_escape; [0xDF].pack('C').force_encoding("iso-8859-9"); end def ascii_only; "glark"; end - def cedilla; "Ş"; end + def cedilla; "�"; end # S-cedilla end end diff --git a/spec/ruby/core/string/include_spec.rb b/spec/ruby/core/string/include_spec.rb index e32eb17c29..23e1e134ec 100644 --- a/spec/ruby/core/string/include_spec.rb +++ b/spec/ruby/core/string/include_spec.rb @@ -13,6 +13,20 @@ describe "String#include? with String" do StringSpecs::MyString.new("hello").include?(StringSpecs::MyString.new("lo")).should == true end + it "returns true if both strings are empty" do + "".should.include?("") + "".force_encoding("EUC-JP").should.include?("") + "".should.include?("".force_encoding("EUC-JP")) + "".force_encoding("EUC-JP").should.include?("".force_encoding("EUC-JP")) + end + + it "returns true if the RHS is empty" do + "a".should.include?("") + "a".force_encoding("EUC-JP").should.include?("") + "a".should.include?("".force_encoding("EUC-JP")) + "a".force_encoding("EUC-JP").should.include?("".force_encoding("EUC-JP")) + end + it "tries to convert other to string using to_str" do other = mock('lo') other.should_receive(:to_str).and_return("lo") diff --git a/spec/ruby/core/string/inspect_spec.rb b/spec/ruby/core/string/inspect_spec.rb index 8bfd465144..8bf3d3161f 100644 --- a/spec/ruby/core/string/inspect_spec.rb +++ b/spec/ruby/core/string/inspect_spec.rb @@ -19,6 +19,21 @@ describe "String#inspect" do ].should be_computed_by(:inspect) end + it "returns a string with special characters replaced with \\<char> notation for UTF-16" do + pairs = [ + ["\a", '"\\a"'], + ["\b", '"\\b"'], + ["\t", '"\\t"'], + ["\n", '"\\n"'], + ["\v", '"\\v"'], + ["\f", '"\\f"'], + ["\r", '"\\r"'], + ["\e", '"\\e"'] + ].map { |str, result| [str.encode('UTF-16LE'), result] } + + pairs.should be_computed_by(:inspect) + end + it "returns a string with \" and \\ escaped with a backslash" do [ ["\"", '"\\""'], ["\\", '"\\\\"'] @@ -311,6 +326,11 @@ describe "String#inspect" do "\xF0\x9F".inspect.should == '"\\xF0\\x9F"' end + it "works for broken US-ASCII strings" do + s = "©".force_encoding("US-ASCII") + s.inspect.should == '"\xC2\xA9"' + end + describe "when default external is UTF-8" do before :each do @extenc, Encoding.default_external = Encoding.default_external, Encoding::UTF_8 diff --git a/spec/ruby/core/string/lstrip_spec.rb b/spec/ruby/core/string/lstrip_spec.rb index 02bc6b4322..75434613f1 100644 --- a/spec/ruby/core/string/lstrip_spec.rb +++ b/spec/ruby/core/string/lstrip_spec.rb @@ -10,6 +10,14 @@ describe "String#lstrip" do " hello world ".lstrip.should == "hello world " "\n\r\t\n\v\r hello world ".lstrip.should == "hello world " "hello".lstrip.should == "hello" + " こにちわ".lstrip.should == "こにちわ" + end + + it "works with lazy substrings" do + " hello "[1...-1].lstrip.should == "hello " + " hello world "[1...-1].lstrip.should == "hello world " + "\n\r\t\n\v\r hello world "[1...-1].lstrip.should == "hello world " + " こにちわ "[1...-1].lstrip.should == "こにちわ" end ruby_version_is '3.0' do @@ -27,20 +35,26 @@ describe "String#lstrip!" do a.should == "hello " end + it "returns nil if no modifications were made" do + a = "hello" + a.lstrip!.should == nil + a.should == "hello" + end + + it "makes a string empty if it is only whitespace" do + "".lstrip!.should == nil + " ".lstrip.should == "" + " ".lstrip.should == "" + end + ruby_version_is '3.0' do - it "strips leading \\0" do + it "removes leading NULL bytes and whitespace" do a = "\000 \000hello\000 \000" a.lstrip! a.should == "hello\000 \000" end end - it "returns nil if no modifications were made" do - a = "hello" - a.lstrip!.should == nil - a.should == "hello" - end - it "raises a FrozenError on a frozen instance that is modified" do -> { " hello ".freeze.lstrip! }.should raise_error(FrozenError) end @@ -51,9 +65,13 @@ describe "String#lstrip!" do -> { "".freeze.lstrip! }.should raise_error(FrozenError) end - it "raises an ArgumentError if the first codepoint is invalid" do + it "raises an ArgumentError if the first non-space codepoint is invalid" do s = "\xDFabc".force_encoding(Encoding::UTF_8) s.valid_encoding?.should be_false -> { s.lstrip! }.should raise_error(ArgumentError) + + s = " \xDFabc".force_encoding(Encoding::UTF_8) + s.valid_encoding?.should be_false + -> { s.lstrip! }.should raise_error(ArgumentError) end end diff --git a/spec/ruby/core/string/ord_spec.rb b/spec/ruby/core/string/ord_spec.rb index cfc630a124..4cf26990fe 100644 --- a/spec/ruby/core/string/ord_spec.rb +++ b/spec/ruby/core/string/ord_spec.rb @@ -25,4 +25,9 @@ describe "String#ord" do it "raises an ArgumentError if called on an empty String" do -> { ''.ord }.should raise_error(ArgumentError) end + + it "raises ArgumentError if the character is broken" do + s = "©".force_encoding("US-ASCII") + -> { s.ord }.should raise_error(ArgumentError, "invalid byte sequence in US-ASCII") + end end diff --git a/spec/ruby/core/string/reverse_spec.rb b/spec/ruby/core/string/reverse_spec.rb index bade4685d9..4206b8af90 100644 --- a/spec/ruby/core/string/reverse_spec.rb +++ b/spec/ruby/core/string/reverse_spec.rb @@ -29,6 +29,14 @@ describe "String#reverse" do it "reverses a string with multi byte characters" do "微軟正黑體".reverse.should == "體黑正軟微" end + + it "works with a broken string" do + str = "微軟\xDF\xDE正黑體".force_encoding(Encoding::UTF_8) + + str.valid_encoding?.should be_false + + str.reverse.should == "體黑正\xDE\xDF軟微" + end end describe "String#reverse!" do @@ -55,4 +63,13 @@ describe "String#reverse!" do str.reverse! str.should == "體黑正軟微" end + + it "works with a broken string" do + str = "微軟\xDF\xDE正黑體".force_encoding(Encoding::UTF_8) + + str.valid_encoding?.should be_false + str.reverse! + + str.should == "體黑正\xDE\xDF軟微" + end end diff --git a/spec/ruby/core/string/rstrip_spec.rb b/spec/ruby/core/string/rstrip_spec.rb index dc34b12719..4332b33b20 100644 --- a/spec/ruby/core/string/rstrip_spec.rb +++ b/spec/ruby/core/string/rstrip_spec.rb @@ -11,6 +11,14 @@ describe "String#rstrip" do " hello world \n\r\t\n\v\r".rstrip.should == " hello world" "hello".rstrip.should == "hello" "hello\x00".rstrip.should == "hello" + "こにちわ ".rstrip.should == "こにちわ" + end + + it "works with lazy substrings" do + " hello "[1...-1].rstrip.should == " hello" + " hello world "[1...-1].rstrip.should == " hello world" + " hello world \n\r\t\n\v\r"[1...-1].rstrip.should == " hello world" + " こにちわ "[1...-1].rstrip.should == "こにちわ" end it "returns a copy of self with all trailing whitespace and NULL bytes removed" do @@ -37,6 +45,20 @@ describe "String#rstrip!" do a.should == "hello" end + it "makes a string empty if it is only whitespace" do + "".rstrip!.should == nil + " ".rstrip.should == "" + " ".rstrip.should == "" + end + + ruby_version_is '3.0' do + it "removes trailing NULL bytes and whitespace" do + a = "\000 goodbye \000" + a.rstrip! + a.should == "\000 goodbye" + end + end + it "raises a FrozenError on a frozen instance that is modified" do -> { " hello ".freeze.rstrip! }.should raise_error(FrozenError) end @@ -47,9 +69,13 @@ describe "String#rstrip!" do -> { "".freeze.rstrip! }.should raise_error(FrozenError) end - it "raises an ArgumentError if the last codepoint is invalid" do + it "raises an ArgumentError if the last non-space codepoint is invalid" do s = "abc\xDF".force_encoding(Encoding::UTF_8) s.valid_encoding?.should be_false -> { s.rstrip! }.should raise_error(ArgumentError) + + s = "abc\xDF ".force_encoding(Encoding::UTF_8) + s.valid_encoding?.should be_false + -> { s.rstrip! }.should raise_error(ArgumentError) end end diff --git a/spec/ruby/core/string/setbyte_spec.rb b/spec/ruby/core/string/setbyte_spec.rb index 03e5bad88b..77bff64038 100644 --- a/spec/ruby/core/string/setbyte_spec.rb +++ b/spec/ruby/core/string/setbyte_spec.rb @@ -36,6 +36,12 @@ describe "String#setbyte" do str.valid_encoding?.should be_true str.setbyte(2,253) str.valid_encoding?.should be_false + + str = "ABC" + str.setbyte(0, 0x20) # ' ' + str.should.valid_encoding? + str.setbyte(0, 0xE3) + str.should_not.valid_encoding? end it "regards a negative index as counting from the end of the String" do diff --git a/spec/ruby/core/string/shared/dedup.rb b/spec/ruby/core/string/shared/dedup.rb index 345e874583..6ffcb9b045 100644 --- a/spec/ruby/core/string/shared/dedup.rb +++ b/spec/ruby/core/string/shared/dedup.rb @@ -38,6 +38,16 @@ describe :string_dedup, shared: true do dynamic.send(@method).should equal("this string is frozen".send(@method).freeze) end + it "does not deduplicate a frozen string when it has instance variables" do + dynamic = %w(this string is frozen).join(' ') + dynamic.instance_variable_set(:@a, 1) + dynamic.freeze + + dynamic.send(@method).should_not equal("this string is frozen".freeze) + dynamic.send(@method).should_not equal("this string is frozen".send(@method).freeze) + dynamic.send(@method).should equal(dynamic) + end + ruby_version_is "3.0" do it "interns the provided string if it is frozen" do dynamic = "this string is unique and frozen #{rand}".freeze diff --git a/spec/ruby/core/string/split_spec.rb b/spec/ruby/core/string/split_spec.rb index 7ef34c65da..b57f660816 100644 --- a/spec/ruby/core/string/split_spec.rb +++ b/spec/ruby/core/string/split_spec.rb @@ -455,6 +455,14 @@ describe "String#split with Regexp" do a.should == ["Chunky", "Bacon"] end + it "yields each split substring with default pattern for a lazy substring" do + a = [] + returned_object = "chunky bacon"[1...-1].split { |str| a << str.capitalize } + + returned_object.should == "hunky baco" + a.should == ["Hunky", "Baco"] + end + it "yields each split substring with default pattern for a non-ASCII string" do a = [] returned_object = "l'été arrive bientôt".split { |str| a << str } @@ -463,6 +471,14 @@ describe "String#split with Regexp" do a.should == ["l'été", "arrive", "bientôt"] end + it "yields each split substring with default pattern for a non-ASCII lazy substring" do + a = [] + returned_object = "l'été arrive bientôt"[1...-1].split { |str| a << str } + + returned_object.should == "'été arrive bientô" + a.should == ["'été", "arrive", "bientô"] + end + it "yields the string when limit is 1" do a = [] returned_object = "chunky bacon".split("", 1) { |str| a << str.capitalize } diff --git a/spec/ruby/core/string/start_with_spec.rb b/spec/ruby/core/string/start_with_spec.rb index aaed197ff3..3833289f96 100644 --- a/spec/ruby/core/string/start_with_spec.rb +++ b/spec/ruby/core/string/start_with_spec.rb @@ -5,4 +5,14 @@ require_relative '../../shared/string/start_with' describe "String#start_with?" do it_behaves_like :start_with, :to_s + + # Here and not in the shared examples because this is invalid as a Symbol + it "does not check that we are not starting to match at the head of a character" do + "\xA9".should.start_with?("\xA9") # A9 is not a character head for UTF-8 + end + + it "does not check we are matching only part of a character" do + "\xe3\x81\x82".size.should == 1 + "\xe3\x81\x82".should.start_with?("\xe3") + end end diff --git a/spec/ruby/core/string/strip_spec.rb b/spec/ruby/core/string/strip_spec.rb index e841db54ce..662f13b032 100644 --- a/spec/ruby/core/string/strip_spec.rb +++ b/spec/ruby/core/string/strip_spec.rb @@ -35,6 +35,12 @@ describe "String#strip!" do a.should == "hello" end + it "makes a string empty if it is only whitespace" do + "".strip!.should == nil + " ".strip.should == "" + " ".strip.should == "" + end + ruby_version_is '3.0' do it "removes leading and trailing NULL bytes and whitespace" do a = "\000 goodbye \000" diff --git a/spec/ruby/core/string/swapcase_spec.rb b/spec/ruby/core/string/swapcase_spec.rb index 417f6c6d8d..6307a1eaaf 100644 --- a/spec/ruby/core/string/swapcase_spec.rb +++ b/spec/ruby/core/string/swapcase_spec.rb @@ -28,6 +28,10 @@ describe "String#swapcase" do it "does not swapcase non-ASCII characters" do "aßet".swapcase(:ascii).should == "AßET" end + + it "works with substrings" do + "prefix aTé"[-3..-1].swapcase(:ascii).should == "Até" + end end describe "full Unicode case mapping adapted for Turkic languages" do diff --git a/spec/ruby/core/string/upcase_spec.rb b/spec/ruby/core/string/upcase_spec.rb index b2b34190fe..209fe73b6e 100644 --- a/spec/ruby/core/string/upcase_spec.rb +++ b/spec/ruby/core/string/upcase_spec.rb @@ -27,6 +27,10 @@ describe "String#upcase" do it "does not upcase non-ASCII characters" do "aßet".upcase(:ascii).should == "AßET" end + + it "works with substrings" do + "prefix té"[-2..-1].upcase(:ascii).should == "Té" + end end describe "full Unicode case mapping adapted for Turkic languages" do |