@@ -40,157 +40,214 @@ public class CollationSupportSuite {
4040 {"UTF8_BINARY" , "UTF8_LCASE" , "UNICODE" , "UNICODE_CI" };
4141
4242 /**
43- * Collation-aware UTF8String comparison.
43+ * Collation-aware UTF8String comparison and equality check .
4444 */
4545
46- private void assertStringCompare (String s1 , String s2 , String collationName , int expected )
46+ private void assertCompare (String s1 , String s2 , String collationName , int expected )
4747 throws SparkException {
4848 UTF8String l = UTF8String .fromString (s1 );
4949 UTF8String r = UTF8String .fromString (s2 );
50+ // Test the comparator, which is the most general way to compare strings with collations.
5051 int compare = CollationFactory .fetchCollation (collationName ).comparator .compare (l , r );
5152 assertEquals (Integer .signum (expected ), Integer .signum (compare ));
53+ // Test the equals function, which may be faster than the comparator for equality checks.
54+ boolean equals = CollationFactory .fetchCollation (collationName ).equalsFunction .apply (l ,r );
55+ assertEquals (expected == 0 , equals );
5256 }
5357
5458 @ Test
5559 public void testCompare () throws SparkException {
5660 for (String collationName : testSupportedCollations ) {
57- // Edge cases
58- assertStringCompare ("" , "" , collationName , 0 );
59- assertStringCompare ("a" , "" , collationName , 1 );
60- assertStringCompare ("" , "a" , collationName , -1 );
61- // Basic tests
62- assertStringCompare ("a" , "a" , collationName , 0 );
63- assertStringCompare ("a" , "b" , collationName , -1 );
64- assertStringCompare ("b" , "a" , collationName , 1 );
65- assertStringCompare ("A" , "A" , collationName , 0 );
66- assertStringCompare ("A" , "B" , collationName , -1 );
67- assertStringCompare ("B" , "A" , collationName , 1 );
68- assertStringCompare ("aa" , "a" , collationName , 1 );
69- assertStringCompare ("b" , "bb" , collationName , -1 );
70- assertStringCompare ("abc" , "a" , collationName , 1 );
71- assertStringCompare ("abc" , "b" , collationName , -1 );
72- assertStringCompare ("abc" , "ab" , collationName , 1 );
73- assertStringCompare ("abc" , "abc" , collationName , 0 );
74- // ASCII strings
75- assertStringCompare ("aaaa" , "aaa" , collationName , 1 );
76- assertStringCompare ("hello" , "world" , collationName , -1 );
77- assertStringCompare ("Spark" , "Spark" , collationName , 0 );
78- // Non-ASCII strings
79- assertStringCompare ("ü" , "ü" , collationName , 0 );
80- assertStringCompare ("ü" , "" , collationName , 1 );
81- assertStringCompare ("" , "ü" , collationName , -1 );
82- assertStringCompare ("äü" , "äü" , collationName , 0 );
83- assertStringCompare ("äxx" , "äx" , collationName , 1 );
84- assertStringCompare ("a" , "ä" , collationName , -1 );
61+ // Empty strings.
62+ assertCompare ("" , "" , collationName , 0 );
63+ assertCompare ("a" , "" , collationName , 1 );
64+ assertCompare ("" , "a" , collationName , -1 );
65+ // Basic tests.
66+ assertCompare ("a" , "a" , collationName , 0 );
67+ assertCompare ("a" , "b" , collationName , -1 );
68+ assertCompare ("b" , "a" , collationName , 1 );
69+ assertCompare ("A" , "A" , collationName , 0 );
70+ assertCompare ("A" , "B" , collationName , -1 );
71+ assertCompare ("B" , "A" , collationName , 1 );
72+ assertCompare ("aa" , "a" , collationName , 1 );
73+ assertCompare ("b" , "bb" , collationName , -1 );
74+ assertCompare ("abc" , "a" , collationName , 1 );
75+ assertCompare ("abc" , "b" , collationName , -1 );
76+ assertCompare ("abc" , "ab" , collationName , 1 );
77+ assertCompare ("abc" , "abc" , collationName , 0 );
78+ assertCompare ("aaaa" , "aaa" , collationName , 1 );
79+ assertCompare ("hello" , "world" , collationName , -1 );
80+ assertCompare ("Spark" , "Spark" , collationName , 0 );
81+ assertCompare ("ü" , "ü" , collationName , 0 );
82+ assertCompare ("ü" , "" , collationName , 1 );
83+ assertCompare ("" , "ü" , collationName , -1 );
84+ assertCompare ("äü" , "äü" , collationName , 0 );
85+ assertCompare ("äxx" , "äx" , collationName , 1 );
86+ assertCompare ("a" , "ä" , collationName , -1 );
8587 }
86- // Non-ASCII strings
87- assertStringCompare ("äü" , "bü" , "UTF8_BINARY" , 1 );
88- assertStringCompare ("bxx" , "bü" , "UTF8_BINARY" , -1 );
89- assertStringCompare ("äü" , "bü" , "UTF8_LCASE" , 1 );
90- assertStringCompare ("bxx" , "bü" , "UTF8_LCASE" , -1 );
91- assertStringCompare ("äü" , "bü" , "UNICODE" , -1 );
92- assertStringCompare ("bxx" , "bü" , "UNICODE" , 1 );
93- assertStringCompare ("äü" , "bü" , "UNICODE_CI" , -1 );
94- assertStringCompare ("bxx" , "bü" , "UNICODE_CI" , 1 );
95- // Case variation
96- assertStringCompare ("AbCd" , "aBcD" , "UTF8_BINARY" , -1 );
97- assertStringCompare ("ABCD" , "abcd" , "UTF8_LCASE" , 0 );
98- assertStringCompare ("AbcD" , "aBCd" , "UNICODE" , 1 );
99- assertStringCompare ("abcd" , "ABCD" , "UNICODE_CI" , 0 );
100- // Accent variation
101- assertStringCompare ("aBćD" , "ABĆD" , "UTF8_BINARY" , 1 );
102- assertStringCompare ("AbCδ" , "ABCΔ" , "UTF8_LCASE" , 0 );
103- assertStringCompare ("äBCd" , "ÄBCD" , "UNICODE" , -1 );
104- assertStringCompare ("Ab́cD" , "AB́CD" , "UNICODE_CI" , 0 );
105- // Case-variable character length
106- assertStringCompare ("i\u0307 " , "İ" , "UTF8_BINARY" , -1 );
107- assertStringCompare ("İ" , "i\u0307 " , "UTF8_BINARY" , 1 );
108- assertStringCompare ("i\u0307 " , "İ" , "UTF8_LCASE" , 0 );
109- assertStringCompare ("İ" , "i\u0307 " , "UTF8_LCASE" , 0 );
110- assertStringCompare ("i\u0307 " , "İ" , "UNICODE" , -1 );
111- assertStringCompare ("İ" , "i\u0307 " , "UNICODE" , 1 );
112- assertStringCompare ("i\u0307 " , "İ" , "UNICODE_CI" , 0 );
113- assertStringCompare ("İ" , "i\u0307 " , "UNICODE_CI" , 0 );
114- assertStringCompare ("i\u0307 İ" , "i\u0307 İ" , "UTF8_LCASE" , 0 );
115- assertStringCompare ("i\u0307 İ" , "İi\u0307 " , "UTF8_LCASE" , 0 );
116- assertStringCompare ("İi\u0307 " , "i\u0307 İ" , "UTF8_LCASE" , 0 );
117- assertStringCompare ("İi\u0307 " , "İi\u0307 " , "UTF8_LCASE" , 0 );
118- assertStringCompare ("i\u0307 İ" , "i\u0307 İ" , "UNICODE_CI" , 0 );
119- assertStringCompare ("i\u0307 İ" , "İi\u0307 " , "UNICODE_CI" , 0 );
120- assertStringCompare ("İi\u0307 " , "i\u0307 İ" , "UNICODE_CI" , 0 );
121- assertStringCompare ("İi\u0307 " , "İi\u0307 " , "UNICODE_CI" , 0 );
122- // Conditional case mapping
123- assertStringCompare ("ς" , "σ" , "UTF8_BINARY" , -1 );
124- assertStringCompare ("ς" , "Σ" , "UTF8_BINARY" , 1 );
125- assertStringCompare ("σ" , "Σ" , "UTF8_BINARY" , 1 );
126- assertStringCompare ("ς" , "σ" , "UTF8_LCASE" , 0 );
127- assertStringCompare ("ς" , "Σ" , "UTF8_LCASE" , 0 );
128- assertStringCompare ("σ" , "Σ" , "UTF8_LCASE" , 0 );
129- assertStringCompare ("ς" , "σ" , "UNICODE" , 1 );
130- assertStringCompare ("ς" , "Σ" , "UNICODE" , 1 );
131- assertStringCompare ("σ" , "Σ" , "UNICODE" , -1 );
132- assertStringCompare ("ς" , "σ" , "UNICODE_CI" , 0 );
133- assertStringCompare ("ς" , "Σ" , "UNICODE_CI" , 0 );
134- assertStringCompare ("σ" , "Σ" , "UNICODE_CI" , 0 );
88+ // Advanced tests.
89+ assertCompare ("äü" , "bü" , "UTF8_BINARY" , 1 );
90+ assertCompare ("bxx" , "bü" , "UTF8_BINARY" , -1 );
91+ assertCompare ("äü" , "bü" , "UTF8_LCASE" , 1 );
92+ assertCompare ("bxx" , "bü" , "UTF8_LCASE" , -1 );
93+ assertCompare ("äü" , "bü" , "UNICODE" , -1 );
94+ assertCompare ("bxx" , "bü" , "UNICODE" , 1 );
95+ assertCompare ("äü" , "bü" , "UNICODE_CI" , -1 );
96+ assertCompare ("bxx" , "bü" , "UNICODE_CI" , 1 );
97+ // Case variation.
98+ assertCompare ("AbCd" , "aBcD" , "UTF8_BINARY" , -1 );
99+ assertCompare ("ABCD" , "abcd" , "UTF8_LCASE" , 0 );
100+ assertCompare ("AbcD" , "aBCd" , "UNICODE" , 1 );
101+ assertCompare ("abcd" , "ABCD" , "UNICODE_CI" , 0 );
102+ // Accent variation.
103+ assertCompare ("aBćD" , "ABĆD" , "UTF8_BINARY" , 1 );
104+ assertCompare ("AbCδ" , "ABCΔ" , "UTF8_LCASE" , 0 );
105+ assertCompare ("äBCd" , "ÄBCD" , "UNICODE" , -1 );
106+ assertCompare ("Ab́cD" , "AB́CD" , "UNICODE_CI" , 0 );
107+ // One-to-many case mapping (e.g. Turkish dotted I).
108+ assertCompare ("i\u0307 " , "İ" , "UTF8_BINARY" , -1 );
109+ assertCompare ("İ" , "i\u0307 " , "UTF8_BINARY" , 1 );
110+ assertCompare ("i\u0307 " , "İ" , "UTF8_LCASE" , 0 );
111+ assertCompare ("İ" , "i\u0307 " , "UTF8_LCASE" , 0 );
112+ assertCompare ("i\u0307 " , "İ" , "UNICODE" , -1 );
113+ assertCompare ("İ" , "i\u0307 " , "UNICODE" , 1 );
114+ assertCompare ("i\u0307 " , "İ" , "UNICODE_CI" , 0 );
115+ assertCompare ("İ" , "i\u0307 " , "UNICODE_CI" , 0 );
116+ assertCompare ("i\u0307 İ" , "i\u0307 İ" , "UTF8_LCASE" , 0 );
117+ assertCompare ("i\u0307 İ" , "İi\u0307 " , "UTF8_LCASE" , 0 );
118+ assertCompare ("İi\u0307 " , "i\u0307 İ" , "UTF8_LCASE" , 0 );
119+ assertCompare ("İi\u0307 " , "İi\u0307 " , "UTF8_LCASE" , 0 );
120+ assertCompare ("i\u0307 İ" , "i\u0307 İ" , "UNICODE_CI" , 0 );
121+ assertCompare ("i\u0307 İ" , "İi\u0307 " , "UNICODE_CI" , 0 );
122+ assertCompare ("İi\u0307 " , "i\u0307 İ" , "UNICODE_CI" , 0 );
123+ assertCompare ("İi\u0307 " , "İi\u0307 " , "UNICODE_CI" , 0 );
124+ // Conditional case mapping (e.g. Greek sigmas).
125+ assertCompare ("ς" , "σ" , "UTF8_BINARY" , -1 );
126+ assertCompare ("ς" , "Σ" , "UTF8_BINARY" , 1 );
127+ assertCompare ("σ" , "Σ" , "UTF8_BINARY" , 1 );
128+ assertCompare ("ς" , "σ" , "UTF8_LCASE" , 0 );
129+ assertCompare ("ς" , "Σ" , "UTF8_LCASE" , 0 );
130+ assertCompare ("σ" , "Σ" , "UTF8_LCASE" , 0 );
131+ assertCompare ("ς" , "σ" , "UNICODE" , 1 );
132+ assertCompare ("ς" , "Σ" , "UNICODE" , 1 );
133+ assertCompare ("σ" , "Σ" , "UNICODE" , -1 );
134+ assertCompare ("ς" , "σ" , "UNICODE_CI" , 0 );
135+ assertCompare ("ς" , "Σ" , "UNICODE_CI" , 0 );
136+ assertCompare ("σ" , "Σ" , "UNICODE_CI" , 0 );
137+ // Surrogate pairs.
138+ assertCompare ("a🙃b🙃c" , "aaaaa" , "UTF8_BINARY" , 1 );
139+ assertCompare ("a🙃b🙃c" , "aaaaa" , "UTF8_LCASE" , 1 );
140+ assertCompare ("a🙃b🙃c" , "aaaaa" , "UNICODE" , -1 ); // != UTF8_BINARY
141+ assertCompare ("a🙃b🙃c" , "aaaaa" , "UNICODE_CI" , -1 ); // != UTF8_LCASE
142+ assertCompare ("a🙃b🙃c" , "a🙃b🙃c" , "UTF8_BINARY" , 0 );
143+ assertCompare ("a🙃b🙃c" , "a🙃b🙃c" , "UTF8_LCASE" , 0 );
144+ assertCompare ("a🙃b🙃c" , "a🙃b🙃c" , "UNICODE" , 0 );
145+ assertCompare ("a🙃b🙃c" , "a🙃b🙃c" , "UNICODE_CI" , 0 );
146+ assertCompare ("a🙃b🙃c" , "a🙃b🙃d" , "UTF8_BINARY" , -1 );
147+ assertCompare ("a🙃b🙃c" , "a🙃b🙃d" , "UTF8_LCASE" , -1 );
148+ assertCompare ("a🙃b🙃c" , "a🙃b🙃d" , "UNICODE" , -1 );
149+ assertCompare ("a🙃b🙃c" , "a🙃b🙃d" , "UNICODE_CI" , -1 );
135150 // Maximum code point.
136151 int maxCodePoint = Character .MAX_CODE_POINT ;
137152 String maxCodePointStr = new String (Character .toChars (maxCodePoint ));
138153 for (int i = 0 ; i < maxCodePoint && Character .isValidCodePoint (i ); ++i ) {
139- assertStringCompare (new String (Character .toChars (i )), maxCodePointStr , "UTF8_BINARY" , -1 );
140- assertStringCompare (new String (Character .toChars (i )), maxCodePointStr , "UTF8_LCASE" , -1 );
154+ assertCompare (new String (Character .toChars (i )), maxCodePointStr , "UTF8_BINARY" , -1 );
155+ assertCompare (new String (Character .toChars (i )), maxCodePointStr , "UTF8_LCASE" , -1 );
141156 }
142157 // Minimum code point.
143158 int minCodePoint = Character .MIN_CODE_POINT ;
144159 String minCodePointStr = new String (Character .toChars (minCodePoint ));
145160 for (int i = minCodePoint + 1 ; i <= maxCodePoint && Character .isValidCodePoint (i ); ++i ) {
146- assertStringCompare (new String (Character .toChars (i )), minCodePointStr , "UTF8_BINARY" , 1 );
147- assertStringCompare (new String (Character .toChars (i )), minCodePointStr , "UTF8_LCASE" , 1 );
161+ assertCompare (new String (Character .toChars (i )), minCodePointStr , "UTF8_BINARY" , 1 );
162+ assertCompare (new String (Character .toChars (i )), minCodePointStr , "UTF8_LCASE" , 1 );
148163 }
149164 }
150165
151- private void assertLowerCaseCodePoints (UTF8String target , UTF8String expected ,
152- Boolean useCodePoints ) {
166+ /**
167+ * Collation-aware UTF8String lowercase conversion.
168+ */
169+
170+ private void assertLowerCaseCodePoints (String string , String expected , Boolean useCodePoints ) {
171+ UTF8String str = UTF8String .fromString (string );
153172 if (useCodePoints ) {
154- assertEquals (expected , CollationAwareUTF8String .lowerCaseCodePoints (target ));
173+ UTF8String result = CollationAwareUTF8String .lowerCaseCodePoints (str );
174+ assertEquals (UTF8String .fromString (expected ), result );
155175 } else {
156- assertEquals (expected , target .toLowerCase ());
176+ UTF8String result = str .toLowerCase ();
177+ assertEquals (UTF8String .fromString (expected ), result );
157178 }
158179 }
159180
160181 @ Test
161182 public void testLowerCaseCodePoints () {
162- // Edge cases
163- assertLowerCaseCodePoints (UTF8String .fromString ("" ), UTF8String .fromString ("" ), false );
164- assertLowerCaseCodePoints (UTF8String .fromString ("" ), UTF8String .fromString ("" ), true );
165- // Basic tests
166- assertLowerCaseCodePoints (UTF8String .fromString ("abcd" ), UTF8String .fromString ("abcd" ), false );
167- assertLowerCaseCodePoints (UTF8String .fromString ("AbCd" ), UTF8String .fromString ("abcd" ), false );
168- assertLowerCaseCodePoints (UTF8String .fromString ("abcd" ), UTF8String .fromString ("abcd" ), true );
169- assertLowerCaseCodePoints (UTF8String .fromString ("aBcD" ), UTF8String .fromString ("abcd" ), true );
170- // Accent variation
171- assertLowerCaseCodePoints (UTF8String .fromString ("AbĆd" ), UTF8String .fromString ("abćd" ), false );
172- assertLowerCaseCodePoints (UTF8String .fromString ("aBcΔ" ), UTF8String .fromString ("abcδ" ), true );
173- // Case-variable character length
174- assertLowerCaseCodePoints (
175- UTF8String .fromString ("İoDiNe" ), UTF8String .fromString ("i̇odine" ), false );
176- assertLowerCaseCodePoints (
177- UTF8String .fromString ("Abi̇o12" ), UTF8String .fromString ("abi̇o12" ), false );
178- assertLowerCaseCodePoints (
179- UTF8String .fromString ("İodInE" ), UTF8String .fromString ("i̇odine" ), true );
180- assertLowerCaseCodePoints (
181- UTF8String .fromString ("aBi̇o12" ), UTF8String .fromString ("abi̇o12" ), true );
182- // Conditional case mapping
183- assertLowerCaseCodePoints (
184- UTF8String .fromString ("ΘΑΛΑΣΣΙΝΟΣ" ), UTF8String .fromString ("θαλασσινος" ), false );
185- assertLowerCaseCodePoints (
186- UTF8String .fromString ("ΘΑΛΑΣΣΙΝΟΣ" ), UTF8String .fromString ("θαλασσινοσ" ), true );
187- // Surrogate pairs are treated as invalid UTF8 sequences
188- assertLowerCaseCodePoints (UTF8String .fromBytes (new byte []
189- {(byte ) 0xED , (byte ) 0xA0 , (byte ) 0x80 , (byte ) 0xED , (byte ) 0xB0 , (byte ) 0x80 }),
190- UTF8String .fromString ("\uFFFD \uFFFD " ), false );
191- assertLowerCaseCodePoints (UTF8String .fromBytes (new byte []
192- {(byte ) 0xED , (byte ) 0xA0 , (byte ) 0x80 , (byte ) 0xED , (byte ) 0xB0 , (byte ) 0x80 }),
193- UTF8String .fromString ("\uFFFD \uFFFD \uFFFD \uFFFD \uFFFD \uFFFD " ), true ); // != Java toLowerCase
183+ // Empty strings.
184+ assertLowerCaseCodePoints ("" , "" , false );
185+ assertLowerCaseCodePoints ("" , "" , true );
186+ // Basic tests.
187+ assertLowerCaseCodePoints ("xyz" , "xyz" , false );
188+ assertLowerCaseCodePoints ("xyz" , "xyz" , true );
189+ assertLowerCaseCodePoints ("abcd" , "abcd" , false );
190+ assertLowerCaseCodePoints ("abcd" , "abcd" , true );
191+ // Advanced tests.
192+ assertLowerCaseCodePoints ("你好" , "你好" , false );
193+ assertLowerCaseCodePoints ("你好" , "你好" , true );
194+ assertLowerCaseCodePoints ("Γειά" , "γειά" , false );
195+ assertLowerCaseCodePoints ("Γειά" , "γειά" , true );
196+ assertLowerCaseCodePoints ("Здраво" , "здраво" , false );
197+ assertLowerCaseCodePoints ("Здраво" , "здраво" , true );
198+ // Case variation.
199+ assertLowerCaseCodePoints ("xYz" , "xyz" , false );
200+ assertLowerCaseCodePoints ("xYz" , "xyz" , true );
201+ assertLowerCaseCodePoints ("AbCd" , "abcd" , false );
202+ assertLowerCaseCodePoints ("aBcD" , "abcd" , true );
203+ // Accent variation.
204+ assertLowerCaseCodePoints ("äbć" , "äbć" , false );
205+ assertLowerCaseCodePoints ("äbć" , "äbć" , true );
206+ assertLowerCaseCodePoints ("AbĆd" , "abćd" , false );
207+ assertLowerCaseCodePoints ("aBcΔ" , "abcδ" , true );
208+ // One-to-many case mapping (e.g. Turkish dotted I).
209+ assertLowerCaseCodePoints ("i\u0307 " , "i\u0307 " , false );
210+ assertLowerCaseCodePoints ("i\u0307 " , "i\u0307 " , true );
211+ assertLowerCaseCodePoints ("I\u0307 " , "i\u0307 " , false );
212+ assertLowerCaseCodePoints ("I\u0307 " , "i\u0307 " , true );
213+ assertLowerCaseCodePoints ("İ" , "i\u0307 " , false );
214+ assertLowerCaseCodePoints ("İ" , "i\u0307 " , true );
215+ assertLowerCaseCodePoints ("İİİ" , "i\u0307 i\u0307 i\u0307 " , false );
216+ assertLowerCaseCodePoints ("İİİ" , "i\u0307 i\u0307 i\u0307 " , true );
217+ assertLowerCaseCodePoints ("İiIi\u0307 " , "i\u0307 iii\u0307 " , false );
218+ assertLowerCaseCodePoints ("İiIi\u0307 " , "i\u0307 iii\u0307 " , true );
219+ assertLowerCaseCodePoints ("İoDiNe" , "i\u0307 odine" , false );
220+ assertLowerCaseCodePoints ("İodInE" , "i\u0307 odine" , true );
221+ assertLowerCaseCodePoints ("Abi\u0307 o12" , "abi\u0307 o12" , false );
222+ assertLowerCaseCodePoints ("aBi\u0307 o12" , "abi\u0307 o12" , true );
223+ // Conditional case mapping (e.g. Greek sigmas).
224+ assertLowerCaseCodePoints ("ς" , "ς" , false );
225+ assertLowerCaseCodePoints ("ς" , "σ" , true );
226+ assertLowerCaseCodePoints ("σ" , "σ" , false );
227+ assertLowerCaseCodePoints ("σ" , "σ" , true );
228+ assertLowerCaseCodePoints ("Σ" , "σ" , false );
229+ assertLowerCaseCodePoints ("Σ" , "σ" , true );
230+ assertLowerCaseCodePoints ("ςΑΛΑΤΑ" , "ςαλατα" , false );
231+ assertLowerCaseCodePoints ("ςΑΛΑΤΑ" , "σαλατα" , true );
232+ assertLowerCaseCodePoints ("σΑΛΑΤΑ" , "σαλατα" , false );
233+ assertLowerCaseCodePoints ("σΑΛΑΤΑ" , "σαλατα" , true );
234+ assertLowerCaseCodePoints ("ΣΑΛΑΤΑ" , "σαλατα" , false );
235+ assertLowerCaseCodePoints ("ΣΑΛΑΤΑ" , "σαλατα" , true );
236+ assertLowerCaseCodePoints ("ΘΑΛΑΣΣΙΝΟς" , "θαλασσινος" , false );
237+ assertLowerCaseCodePoints ("ΘΑΛΑΣΣΙΝΟς" , "θαλασσινοσ" , true );
238+ assertLowerCaseCodePoints ("ΘΑΛΑΣΣΙΝΟσ" , "θαλασσινοσ" , false );
239+ assertLowerCaseCodePoints ("ΘΑΛΑΣΣΙΝΟσ" , "θαλασσινοσ" , true );
240+ assertLowerCaseCodePoints ("ΘΑΛΑΣΣΙΝΟΣ" , "θαλασσινος" , false );
241+ assertLowerCaseCodePoints ("ΘΑΛΑΣΣΙΝΟΣ" , "θαλασσινοσ" , true );
242+ // Surrogate pairs.
243+ assertLowerCaseCodePoints ("a🙃b🙃c" , "a🙃b🙃c" , false );
244+ assertLowerCaseCodePoints ("a🙃b🙃c" , "a🙃b🙃c" , true );
245+ assertLowerCaseCodePoints ("😀😆😃😄😄😆" , "😀😆😃😄😄😆" , false );
246+ assertLowerCaseCodePoints ("😀😆😃😄😄😆" , "😀😆😃😄😄😆" , true );
247+ assertLowerCaseCodePoints ("𐐅" , "𐐭" , false );
248+ assertLowerCaseCodePoints ("𐐅" , "𐐭" , true );
249+ assertLowerCaseCodePoints ("𝔸" , "𝔸" , false );
250+ assertLowerCaseCodePoints ("𝔸" , "𝔸" , true );
194251 }
195252
196253 /**
0 commit comments