1 require File.dirname(__FILE__) + '/abstract_unit'
5 class CharsTest < Test::Unit::TestCase
9 :utf8 => "Abcd Блå ffi блa 埋",
10 :ascii => "asci ias c iia s",
11 :bytes => "\270\236\010\210\245"
17 assert s.respond_to?(:chars), "All string should have the chars method (#{t})"
18 assert s.respond_to?(:to_s), "All string should have the to_s method (#{t})"
19 assert_kind_of ActiveSupport::Multibyte::Chars, s.chars, "#chars should return an instance of Chars (#{t})"
23 def test_comparability
25 assert_equal s, s.chars.to_s, "Chars#to_s should return enclosed string unchanged"
27 assert_nothing_raised do
28 assert_equal "a", "a", "Normal string comparisons should be unaffected"
29 assert_not_equal "a", "b", "Normal string comparisons should be unaffected"
30 assert_not_equal "a".chars, "b".chars, "Chars objects should be comparable"
31 assert_equal "a".chars, "A".downcase.chars, "Chars objects should be comparable to each other"
32 assert_equal "a".chars, "A".downcase, "Chars objects should be comparable to strings coming from elsewhere"
35 assert !@s[:utf8].eql?(@s[:utf8].chars), "Strict comparison is not supported"
36 assert_equal @s[:utf8], @s[:utf8].chars, "Chars should be compared by their enclosed string"
38 other_string = @s[:utf8].dup
39 assert_equal other_string, @s[:utf8].chars, "Chars should be compared by their enclosed string"
40 assert_equal other_string.chars, @s[:utf8].chars, "Chars should be compared by their enclosed string"
42 strings = ['builder'.chars, 'armor'.chars, 'zebra'.chars]
44 assert_equal ['armor', 'builder', 'zebra'], strings, "Chars should be sortable based on their enclosed string"
46 # This leads to a StackLevelTooDeep exception if the comparison is not wired properly
47 assert_raise(NameError) do
53 assert @s[:utf8].is_utf8?, "UTF-8 strings are UTF-8"
54 assert @s[:ascii].is_utf8?, "All ASCII strings are also valid UTF-8"
55 assert !@s[:bytes].is_utf8?, "This bytestring isn't UTF-8"
58 # The test for the following methods are defined here because they can only be defined on the Chars class for
62 assert_equal 'éxa', 'éda'.chars.gsub(/d/, 'x')
64 assert_equal 'éxa', 'éda'.chars.gsub(/d/, 'x')
70 chars = ["e", "ffi", "c", "i", "e", "n", "t"]
71 assert_equal chars, word.split(//)
72 assert_equal chars, word.chars.split(//)
73 assert_kind_of ActiveSupport::Multibyte::Chars, word.chars.split(//).first, "Split should return Chars instances"
78 assert_equal 12, (@s[:utf8].chars =~ /ffi/),
79 "Regex matching should be bypassed to String"
82 assert_equal 9, (@s[:utf8].chars =~ /ffi/),
83 "Regex matching should be unicode aware"
84 assert_nil((''.chars =~ /\d+/),
85 "Non-matching regular expressions should return nil")
91 assert " ".chars.send(:utf8_pragma?), "UTF8 pragma should be on because KCODE is UTF8"
94 assert !" ".chars.send(:utf8_pragma?), "UTF8 pragma should be off"
98 def test_handler_setting
99 handler = ''.chars.handler
101 ActiveSupport::Multibyte::Chars.handler = :first
102 assert_equal :first, ''.chars.handler
103 ActiveSupport::Multibyte::Chars.handler = :second
104 assert_equal :second, ''.chars.handler
105 assert_raise(NoMethodError) do
106 ''.chars.handler.split
109 ActiveSupport::Multibyte::Chars.handler = handler
112 def test_method_chaining
113 assert_kind_of ActiveSupport::Multibyte::Chars, ''.chars.downcase
114 assert_kind_of ActiveSupport::Multibyte::Chars, ''.chars.strip, "Strip should return a Chars object"
115 assert_kind_of ActiveSupport::Multibyte::Chars, ''.chars.downcase.strip, "The Chars object should be " +
116 "forwarded down the call path for chaining"
117 assert_equal 'foo', " FOO ".chars.normalize.downcase.strip, "The Chars that results from the " +
118 " operations should be comparable to the string value of the result"
121 def test_passthrough_on_kcode
122 # The easiest way to check if the passthrough is in place is through #size
123 with_kcode('none') do
124 assert_equal 26, @s[:utf8].chars.size
126 with_kcode('UTF8') do
127 assert_equal 17, @s[:utf8].chars.size
131 def test_destructiveness
132 # Note that we're testing the destructiveness here and not the correct behaviour of the methods
134 str.chars.insert(1, 'b')
135 assert_equal 'abc', str, 'Insert should be destructive for a string'
139 assert_equal 'ca', str, 'reverse! should be destructive for a string'
143 assert_nothing_raised do
144 assert_equal 5, @s[:bytes].chars.size, "The sequence contains five interpretable bytes"
146 reversed = [0xb8, 0x17e, 0x8, 0x2c6, 0xa5].reverse.pack('U*')
147 assert_nothing_raised do
148 assert_equal reversed, @s[:bytes].chars.reverse.to_s, "Reversing the string should only yield interpretable bytes"
150 assert_nothing_raised do
151 @s[:bytes].chars.reverse!
152 assert_equal reversed, @s[:bytes].to_s, "Reversing the string should only yield interpretable bytes"
157 assert_equal true, 'test'.chars.respond_to?(:strip)
158 assert_equal true, 'test'.chars.respond_to?(:normalize)
159 assert_equal true, 'test'.chars.respond_to?(:normalize!)
160 assert_equal false, 'test'.chars.respond_to?(:a_method_that_doesnt_exist)
165 def with_kcode(kcode)
166 old_kcode, $KCODE = $KCODE, kcode