1 /*
  2  * Copyright (c) 2003, 2024, 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 4533872 4640853
 27  * @summary Unit tests for supplementary character support (JSR-204) and Unicode 4.0 support
 28  * @run junit Bug4533872
 29  */
 30 
 31 import java.text.BreakIterator;
 32 import java.util.Locale;
 33 
 34 import org.junit.jupiter.api.Test;
 35 
 36 import static org.junit.jupiter.api.Assertions.fail;
 37 
 38 public class Bug4533872 {
 39 
 40     static final String[] given = {
 41       /* Lu Nd    Lu     Ll    */
 42         "XYZ12345 ABCDE  abcde",
 43       /* Nd Lo          Nd  Lu Po    Lu   Ll    */
 44         "123\uD800\uDC00345 ABC\uFF61XYZ  abc",
 45       /* Nd Lo          Nd  Lu Po          Lu   Ll    */
 46         "123\uD800\uDC00345 ABC\uD800\uDD00XYZ  abc",
 47       /* Lu Ll Cs    Ll Cs    Lu Lo          Lu  */
 48         "ABCabc\uDC00xyz\uD800ABC\uD800\uDC00XYZ",
 49     };
 50 
 51     // Golden data for TestNext(), TestBoundar() and TestPrintEach*ward()
 52     static final String[][] expected = {
 53         {"XYZ12345", " ", "ABCDE", "  ", "abcde"},
 54         {"123\uD800\uDC00345", " ", "ABC", "\uFF61", "XYZ", "  ", "abc"},
 55         {"123\uD800\uDC00345", " ", "ABC", "\uD800\uDD00", "XYZ", "  ", "abc"},
 56         {"ABCabc", "\uDC00", "xyz", "\uD800", "ABC\uD800\uDC00XYZ"},
 57     };
 58 
 59     BreakIterator iter;
 60     int start, end, current;
 61 
 62     /*
 63      * Test for next(int n)
 64      */
 65     @Test
 66     void TestNext() {
 67         iter = BreakIterator.getWordInstance(Locale.US);
 68 
 69         for (int i = 0; i < given.length; i++) {
 70             iter.setText(given[i]);
 71             start = iter.first();
 72             int j = expected[i].length - 1;
 73             start = iter.next(j);
 74             end = iter.next();
 75 
 76             if (!expected[i][j].equals(given[i].substring(start, end))) {
 77                 fail("Word break failure: printEachForward() expected:<" +
 78                       expected[i][j] + ">, got:<" +
 79                       given[i].substring(start, end) +
 80                       "> start=" + start + "  end=" + end);
 81             }
 82         }
 83     }
 84 
 85     /*
 86      * Test for isBoundary(int n)
 87      */
 88     @Test
 89     void TestIsBoundary() {
 90         iter = BreakIterator.getWordInstance(Locale.US);
 91 
 92         for (int i = 0; i < given.length; i++) {
 93             iter.setText(given[i]);
 94 
 95             start = iter.first();
 96             end = iter.next();
 97 
 98             while (end < given[i].length()) {
 99                 if (!iter.isBoundary(end)) {
100                     fail("Word break failure: isBoundary() This should be a boundary. Index=" +
101                           end + " for " + given[i]);
102                 }
103                 end = iter.next();
104             }
105         }
106     }
107 
108 
109     /*
110      * The followig test cases were made based on examples in BreakIterator's
111      * API Doc.
112      */
113 
114     /*
115      * Test mainly for next() and current()
116      */
117     @Test
118     void TestPrintEachForward() {
119         iter = BreakIterator.getWordInstance(Locale.US);
120 
121         for (int i = 0; i < given.length; i++) {
122             iter.setText(given[i]);
123             start = iter.first();
124 
125             // Check current()'s return value - should be same as first()'s.
126             current = iter.current();
127             if (start != current) {
128                 fail("Word break failure: printEachForward() Unexpected current value: current()=" +
129                       current + ", expected(=first())=" + start);
130             }
131 
132             int j = 0;
133             for (end = iter.next();
134                  end != BreakIterator.DONE;
135                  start = end, end = iter.next(), j++) {
136 
137                 // Check current()'s return value - should be same as next()'s.
138                 current = iter.current();
139                 if (end != current) {
140                     fail("Word break failure: printEachForward() Unexpected current value: current()=" +
141                           current + ", expected(=next())=" + end);
142                 }
143 
144                 if (!expected[i][j].equals(given[i].substring(start, end))) {
145                     fail("Word break failure: printEachForward() expected:<" +
146                           expected[i][j] + ">, got:<" +
147                           given[i].substring(start, end) +
148                           "> start=" + start + "  end=" + end);
149                 }
150             }
151         }
152     }
153 
154     /*
155      * Test mainly for previous() and current()
156      */
157     @Test
158     void TestPrintEachBackward() {
159         iter = BreakIterator.getWordInstance(Locale.US);
160 
161         for (int i = 0; i < given.length; i++) {
162             iter.setText(given[i]);
163             end = iter.last();
164 
165             // Check current()'s return value - should be same as last()'s.
166             current = iter.current();
167             if (end != current) {
168                 fail("Word break failure: printEachBackward() Unexpected current value: current()=" +
169                       current + ", expected(=last())=" + end);
170             }
171 
172             int j;
173             for (start = iter.previous(), j = expected[i].length-1;
174                  start != BreakIterator.DONE;
175                  end = start, start = iter.previous(), j--) {
176 
177                 // Check current()'s return value - should be same as previous()'s.
178                 current = iter.current();
179                 if (start != current) {
180                     fail("Word break failure: printEachBackward() Unexpected current value: current()=" +
181                           current + ", expected(=previous())=" + start);
182                 }
183 
184                 if (!expected[i][j].equals(given[i].substring(start, end))) {
185                     fail("Word break failure: printEachBackward() expected:<" +
186                           expected[i][j] + ">, got:<" +
187                           given[i].substring(start, end) +
188                           "> start=" + start + "  end=" + end);
189                 }
190             }
191         }
192     }
193 
194     /*
195      * Test mainly for following() and previous()
196      */
197     @Test
198     void TestPrintAt_1() {
199         iter = BreakIterator.getWordInstance(Locale.US);
200 
201         int[][] index = {
202             {2, 8, 10, 15, 17},
203             {1, 8, 10, 12, 15, 17, 20},
204             {3, 8, 10, 13, 16, 18, 20},
205             {4, 6,  9, 10, 16},
206         };
207 
208         for (int i = 0; i < given.length; i++) {
209             iter.setText(given[i]);
210             for (int j = index[i].length-1; j >= 0; j--) {
211                 end = iter.following(index[i][j]);
212                 start = iter.previous();
213 
214                 if (!expected[i][j].equals(given[i].substring(start, end))) {
215                     fail("Word break failure: printAt_1() expected:<" +
216                           expected[i][j] + ">, got:<" +
217                           given[i].substring(start, end) +
218                           "> start=" + start + "  end=" + end);
219                 }
220             }
221         }
222     }
223 
224     /*
225      * Test mainly for preceding() and next()
226      */
227     @Test
228     void TestPrintAt_2() {
229         iter = BreakIterator.getWordInstance(Locale.US);
230 
231         int[][] index = {
232             {2, 9, 10, 15, 17},
233             {1, 9, 10, 13, 16, 18, 20},
234             {4, 9, 10, 13, 16, 18, 20},
235             {6, 7, 10, 11, 15},
236         };
237 
238         for (int i = 0; i < given.length; i++) {
239             iter.setText(given[i]);
240 
241             // Check preceding(0)'s return value - should equals BreakIterator.DONE.
242             if (iter.preceding(0) != BreakIterator.DONE) {
243                  fail("Word break failure: printAt_2() expected:-1(BreakIterator.DONE), got:" +
244                        iter.preceding(0));
245             }
246 
247             for (int j = 0; j < index[i].length; j++) {
248                 start = iter.preceding(index[i][j]);
249                 end = iter.next();
250 
251                 if (!expected[i][j].equals(given[i].substring(start, end))) {
252                     fail("Word break failure: printAt_2() expected:<" +
253                           expected[i][j] + ">, got:<" +
254                           given[i].substring(start, end) +
255                           "> start=" + start + "  end=" + end);
256                 }
257             }
258 
259             // Check next()'s return value - should equals BreakIterator.DONE.
260             end = iter.last();
261             start = iter.next();
262             if (start != BreakIterator.DONE) {
263                  fail("Word break failure: printAt_2() expected:-1(BreakIterator.DONE), got:" + start);
264             }
265         }
266     }
267 }