1 /*
  2  * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /*
 25  * @test
 26  * @bug 4221795 8174270
 27  * @summary Confirm Normalizer's fundamental behavior
 28  * @modules java.base/sun.text java.base/jdk.internal.icu.text
 29  * @compile -XDignore.symbol.file NormalizerAPITest.java
 30  * @run junit/timeout=30 NormalizerAPITest
 31  */
 32 
 33 import java.text.Normalizer;
 34 import java.nio.CharBuffer;
 35 
 36 import org.junit.jupiter.api.Test;
 37 
 38 import static org.junit.jupiter.api.Assertions.fail;
 39 
 40 
 41 /*
 42  * Tests around null/"" arguments for public methods.
 43  *
 44  * You may think that so elaborate testing for such a part is not necessary.
 45  * But I actually detected a bug by this program during my porting work.
 46  */
 47 public class NormalizerAPITest {
 48 
 49     //
 50     // Shortcuts
 51     //
 52 
 53     /*
 54      * Normalization forms
 55      */
 56     static final Normalizer.Form NFC  = Normalizer.Form.NFC;
 57     static final Normalizer.Form NFD  = Normalizer.Form.NFD;
 58     static final Normalizer.Form NFKC = Normalizer.Form.NFKC;
 59     static final Normalizer.Form NFKD = Normalizer.Form.NFKD;
 60     static final Normalizer.Form[] forms = {NFC, NFD, NFKC, NFKD};
 61 
 62     static final Normalizer.Form NULL = null;
 63 
 64     /*
 65      * Option
 66      */
 67     static final int[] options = {
 68         0x00,
 69         sun.text.Normalizer.UNICODE_3_2,
 70         jdk.internal.icu.text.NormalizerBase.UNICODE_3_2,
 71         jdk.internal.icu.text.NormalizerBase.UNICODE_LATEST,
 72     };
 73 
 74     static final String nonNullStr = "testdata";
 75 
 76 
 77     /*
 78      * Check if normalize(null) throws NullPointerException as expected.
 79      */
 80     @Test
 81     public void Test_NullPointerException_java_normalize() {
 82         boolean error = false;
 83 
 84         /* Check null as String to be normalized */
 85         for (int i = 0; i < forms.length; i++) {
 86             try {
 87                 String s = Normalizer.normalize(null, forms[i]);
 88                 error = true;
 89             }
 90             catch (NullPointerException e) {
 91             }
 92         }
 93 
 94         /* Check null as a Normalization form */
 95         try {
 96             String s = Normalizer.normalize(nonNullStr, NULL);
 97             error = true;
 98         }
 99         catch (NullPointerException e) {
100         }
101 
102         if (error) {
103              fail("normalize(null) should throw NullPointerException.");
104         }
105     }
106 
107     /*
108      * Check if normalize(null) throws NullPointerException as expected.
109      */
110     @Test
111     public void Test_NullPointerException_sun_normalize() {
112         boolean error = false;
113 
114         for (int j = 0; j < options.length; j++) {
115             for (int i = 0; i < forms.length; i++) {
116                 /* Check null as a String to be normalized */
117                 try {
118                     String s = sun.text.Normalizer.normalize(null, forms[i], options[j]);
119                     error = true;
120                 }
121                 catch (NullPointerException e) {
122                 }
123             }
124 
125             /* Check null as a Normalization form */
126             try {
127                 String s = sun.text.Normalizer.normalize(nonNullStr, NULL, options[j]);
128                 error = true;
129             }
130             catch (NullPointerException e) {
131             }
132         }
133 
134         if (error) {
135              fail("normalize(null) should throw NullPointerException.");
136         }
137     }
138 
139     /*
140      * Check if isNormalized(null) throws NullPointerException as expected.
141      */
142     @Test
143     public void Test_NullPointerException_java_isNormalized() {
144         boolean error = false;
145 
146         for (int i = 0; i < forms.length; i++) {
147             try {
148                 /* Check null as a String to be scanned */
149                 boolean b = Normalizer.isNormalized(null, forms[i]);
150                 error = true;
151             }
152             catch (NullPointerException e) {
153             }
154         }
155 
156         /* Check null as a String to be scanned */
157         try {
158             boolean b = Normalizer.isNormalized(nonNullStr, NULL);
159             error = true;
160         }
161 
162         catch (NullPointerException e) {
163         }
164         if (error) {
165              fail("isNormalized(null) should throw NullPointerException.");
166         }
167     }
168 
169     /*
170      * Check if isNormalized(null) throws NullPointerException as expected.
171      */
172     @Test
173     public void Test_NullPointerException_sun_isNormalized() {
174         boolean error = false;
175 
176         for (int j = 0; j < options.length; j++) {
177             for (int i = 0; i < forms.length; i++) {
178                 try {
179                     /* Check null as a String to be scanned */
180                     boolean b = sun.text.Normalizer.isNormalized(null, forms[i], options[j]);
181                     error = true;
182                 }
183                 catch (NullPointerException e) {
184                 }
185             }
186 
187             /* Check null as a String to be scanned */
188             try {
189                 boolean b = sun.text.Normalizer.isNormalized(nonNullStr, NULL, options[j]);
190                 error = true;
191             }
192             catch (NullPointerException e) {
193             }
194         }
195 
196         if (error) {
197              fail("isNormalized(null) should throw NullPointerException.");
198         }
199     }
200 
201     /*
202      * Check if isNormalized("") doesn't throw NullPointerException and returns
203      * "" as expected.
204      */
205     @Test
206     public void Test_No_NullPointerException_java_normalize() {
207         boolean error = false;
208 
209         for (int i = 0; i < forms.length; i++) {
210             try {
211                 String s = Normalizer.normalize("", forms[i]);
212                 if (!s.equals("")) {
213                     error = true;
214                 }
215             }
216             catch (NullPointerException e) {
217                 error = true;
218             }
219         }
220 
221         if (error) {
222              fail("normalize() for String(\"\") should return \"\".");
223         }
224     }
225 
226     /*
227      * Check if isNormalized("") doesn't throw NullPointerException and returns
228      * "" as expected.
229      */
230     @Test
231     public void Test_No_NullPointerException_sun_normalize() {
232         boolean error = false;
233 
234         for (int j = 0; j < options.length; j++) {
235             for (int i = 0; i < forms.length; i++) {
236                 try {
237                     String s = sun.text.Normalizer.normalize("", forms[i], options[j]);
238                     if (!s.equals("")) {
239                         error = true;
240                     }
241                 }
242                 catch (NullPointerException e) {
243                     error = true;
244                 }
245             }
246         }
247         if (error) {
248              fail("normalize() for String(\"\") should return \"\".");
249         }
250     }
251 
252     /*
253      * Check if isNormalized("") doesn't throw NullPointerException and returns
254      * "" as expected.
255      */
256     @Test
257     public void Test_No_NullPointerException_java_isNormalized() {
258         boolean error = false;
259 
260         for (int i = 0; i < forms.length; i++) {
261             try {
262                 boolean b = Normalizer.isNormalized("", forms[i]);
263                 if (!b) {
264                     error = true;
265                 }
266             }
267             catch (NullPointerException e) {
268                 error = true;
269             }
270         }
271         if (error) {
272              fail("isNormalized() for String(\"\") should not return true.");
273         }
274     }
275 
276     /*
277      * Check if isNormalized("") doesn't throw NullPointerException and returns
278      * "" as expected.
279      */
280     @Test
281     public void Test_No_NullPointerException_sun_isNormalized() {
282         boolean error = false;
283 
284         for (int j = 0; j < options.length; j++) {
285             for (int i = 0; i < forms.length; i++) {
286                 try {
287                     boolean b = sun.text.Normalizer.isNormalized("", forms[i], options[j]);
288                     if (!b) {
289                         error = true;
290                     }
291                 }
292                 catch (NullPointerException e) {
293                     error = true;
294                 }
295             }
296         }
297         if (error) {
298              fail("isNormalized() for String(\"\") should not return true.");
299         }
300     }
301 
302     /*
303      * Check if normalize() and isNormalized() work as expected for every
304      * known class which implement CharSequence Interface.
305      */
306     @Test
307     public void Test_CharSequence() {
308 
309         check_CharSequence(String.valueOf(inputData),
310                            String.valueOf(outputData));
311 
312         check_CharSequence(new StringBuffer(original),
313                            new StringBuffer(expected));
314 
315         check_CharSequence(new StringBuilder(original),
316                            new StringBuilder(expected));
317 
318         check_CharSequence(CharBuffer.wrap(inputData),
319                            CharBuffer.wrap(outputData));
320     }
321 
322 
323     void check_CharSequence(CharSequence in, CharSequence expected) {
324         String out = Normalizer.normalize(in, NFD);
325         if (!out.equals(expected.toString())) {
326             fail("java.text.Normalizer.normalize(" +
327                   in.getClass().getSimpleName() + ") failed.");
328         }
329         out = sun.text.Normalizer.normalize(in, NFD,
330                              jdk.internal.icu.text.NormalizerBase.UNICODE_LATEST);
331         if (!out.equals(expected.toString())) {
332             fail("sun.text.Normalizer.normalize(" +
333                   in.getClass().getSimpleName() + ") failed.");
334         }
335 
336         if (!Normalizer.isNormalized(expected, NFD)) {
337             fail("java.text.Normalizer.isNormalize(" +
338                   in.getClass().getSimpleName() + ") failed.");
339         }
340         if (!sun.text.Normalizer.isNormalized(expected, NFD,
341                            jdk.internal.icu.text.NormalizerBase.UNICODE_LATEST)) {
342             fail("sun.text.Normalizer.isNormalize(" +
343                   in.getClass().getSimpleName() + ") failed.");
344         }
345     }
346 
347     static final char[] inputData  = {'T', 's', 'c', 'h', 'u', '\u1e9b'};
348     static final char[] outputData = {'T', 's', 'c', 'h', 'u', '\u017f', '\u0307'};
349     static final String original   = String.valueOf(inputData);
350     static final String expected   = String.valueOf(outputData);
351 }