1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 package ifc.i18n;
25 
26 import java.util.Vector;
27 
28 import lib.MultiMethodTest;
29 import lib.Status;
30 import lib.StatusException;
31 
32 import com.sun.star.i18n.Boundary;
33 import com.sun.star.i18n.LineBreakHyphenationOptions;
34 import com.sun.star.i18n.LineBreakResults;
35 import com.sun.star.i18n.LineBreakUserOptions;
36 import com.sun.star.i18n.ScriptType;
37 import com.sun.star.i18n.WordType;
38 import com.sun.star.i18n.XBreakIterator;
39 import com.sun.star.lang.Locale;
40 
41 /**
42 * Testing <code>com.sun.star.i18n.XBreakIterator</code>
43 * interface methods :
44 * <ul>
45 *  <li><code> nextCharacters()</code></li>
46 *  <li><code> previousCharacters()</code></li>
47 *  <li><code> nextWord()</code></li>
48 *  <li><code> previousWord()</code></li>
49 *  <li><code> getWordBoundary()</code></li>
50 *  <li><code> getWordType()</code></li>
51 *  <li><code> isBeginWord()</code></li>
52 *  <li><code> isEndWord()</code></li>
53 *  <li><code> beginOfSentence()</code></li>
54 *  <li><code> endOfSentence()</code></li>
55 *  <li><code> getLineBreak()</code></li>
56 *  <li><code> beginOfScript()</code></li>
57 *  <li><code> endOfScript()</code></li>
58 *  <li><code> nextScript()</code></li>
59 *  <li><code> previousScript()</code></li>
60 *  <li><code> getScriptType()</code></li>
61 *  <li><code> beginOfCharBlock()</code></li>
62 *  <li><code> endOfCharBlock()</code></li>
63 *  <li><code> nextCharBlock()</code></li>
64 *  <li><code> previousCharBlock()</code></li>
65 * </ul> <p>
66 * This test needs the following object relations :
67 * <ul>
68 *  <li> <code>'Locale'</code>
69 *   (of type <code>com.sun.star.lang.Locale</code>):
70 *   this locale is used as locale argument for tested methods.
71 *  </li>
72 *  <li> <code>'UnicodeString'</code>
73 *   (of type <code>String</code>): Unicode string which is passed
74 *   to methods except 'CharacterBlock' methods.
75 *  </li>
76 * <ul> <p>
77 * @see com.sun.star.i18n.XBreakIterator
78 */
79 public class _XBreakIterator extends MultiMethodTest {
80 
81     public XBreakIterator oObj = null;
82 
83     Locale locale = null;
84     String UnicodeString = null;
85 
86     short wordType = WordType.ANYWORD_IGNOREWHITESPACES;
87 
88     /**
89      * Retrieves object relations.
90      * @throws StatusException If one of relations not found.
91      */
before()92     protected void before() {
93         locale = (Locale)tEnv.getObjRelation("Locale");
94         if (locale == null) {
95             throw new StatusException
96                 (Status.failed("Relation 'Locale' not found")) ;
97         }
98 
99         UnicodeString = (String)tEnv.getObjRelation("UnicodeString");
100         if (UnicodeString == null) {
101             throw new StatusException(Status.failed
102                 ("Relation 'UnicodeString' not found")) ;
103         }
104     }
105 
106     /**
107      * Compares returned next character positions with expected values. <p>
108      *
109      * Has <b>OK</b> status if position after travel and traveled length
110      * has expected values.
111      */
_nextCharacters()112     public void _nextCharacters() {
113         short nCharacterIteratorMode =
114             com.sun.star.i18n.CharacterIteratorMode.SKIPCHARACTER;
115 
116         int strLength = UnicodeString.length();
117 
118         //Start from position : Travel ... chars :
119         // Actual position after : How many chars traveled
120         int[][] nextCharacters = {
121             { 1, 5000, strLength , strLength - 1 },
122             { 10, 6, 16, 6}};
123 
124         boolean bRes = true;
125 
126         for(int i = 0; i < nextCharacters.length; i++) {
127             int[] lDone = new int[1];
128             long lRes = oObj.nextCharacters(UnicodeString, nextCharacters[i][0],
129                 locale, nCharacterIteratorMode, nextCharacters[i][1], lDone);
130             log.println("Expected result is: lRes = " + nextCharacters[i][2] +
131                         "; lDone = " + nextCharacters[i][3] );
132             log.println("Actual result is: lRes = " + lRes +
133                         "; lDone = " + lDone[0] );
134 
135             bRes = bRes && lRes == nextCharacters[i][2];
136             bRes = bRes && lDone[0] == nextCharacters[i][3];
137         }
138 
139         tRes.tested("nextCharacters()", bRes);
140     }
141 
142     /**
143      * Compares returned previous character positions with expected values. <p>
144      *
145      * Has <b>OK</b> status if position after travel and traveled length
146      * has expected values.
147      */
_previousCharacters()148     public void _previousCharacters() {
149         short nCharacterIteratorMode =
150             com.sun.star.i18n.CharacterIteratorMode.SKIPCHARACTER;
151 
152 
153         //Start from position : Travel ... chars : Actual position after :
154         //How many chars traveled
155         int[][] previousCharacters = {
156             {5, 5000, 0, 5},
157             {10, 6, 4, 6}};
158 
159         boolean bRes = true;
160         for(int i = 0; i < previousCharacters.length; i++) {
161             int[] lDone = new int[1];
162             int lRes = oObj.previousCharacters(UnicodeString,
163                 previousCharacters[i][0],
164                 locale, nCharacterIteratorMode,
165                 previousCharacters[i][1], lDone);
166             log.println("Expected result is: lRes = " + previousCharacters[i][2]
167                 + "; lDone = " + previousCharacters[i][3] );
168             log.println("Actual result is: lRes = " + lRes
169                 + "; lDone = " + lDone[0]);
170 
171             bRes = bRes && lRes == previousCharacters[i][2];
172             bRes = bRes && lDone[0] == previousCharacters[i][3];
173         }
174 
175         tRes.tested("previousCharacters()", bRes);
176     }
177 
178     Vector vBounds = new Vector();
179 
180     /**
181     * Saves bounds of all returned words for the future tests. <p>
182     * Has <b>OK</b> status.
183     */
_nextWord()184     public void _nextWord() {
185         int i = 0;
186 
187         while( i < UnicodeString.length() - 1 ) {
188             Boundary bounds = oObj.nextWord
189                 (UnicodeString, i, locale, wordType);
190             if (bounds.endPos - bounds.startPos > 3) {
191                 vBounds.add( bounds );
192                 log.println("Word " + vBounds.size() + "("
193                     + bounds.startPos + "," + bounds.endPos + "): '" +
194                     UnicodeString.substring(bounds.startPos,
195                                             bounds.endPos) + "'");
196             }
197             i = bounds.endPos - 1;
198         }
199         log.println("In text there are " + vBounds.size()
200             + " words, if count from left to right");
201         tRes.tested("nextWord()", true);
202     }
203 
204     /**
205     * Compares number of word bounds with number of word bounds saved
206     * by the method _nextWord().<p>
207     * Has <b>OK</b> status if number of word bounds are equal.
208     */
_previousWord()209     public void _previousWord() {
210         requiredMethod("nextWord()");
211 
212         int i = UnicodeString.length() - 1;
213         Vector vPrevBounds = new Vector();
214         while( i > 0  ) {
215             Boundary bounds =
216                 oObj.previousWord(UnicodeString, i, locale, wordType);
217             if (bounds.endPos - bounds.startPos > 3) {
218                 vPrevBounds.add( bounds );
219                 log.println("Word " + vPrevBounds.size() + "("
220                     + bounds.startPos + "," + bounds.endPos + "): '"
221                     + UnicodeString.substring(bounds.startPos, bounds.endPos)
222                     + "'");
223             }
224             i = bounds.startPos;
225         }
226         log.println("In text there are " + vPrevBounds.size()
227             + " words, if count from right to left");
228         tRes.tested("previousWord()", vPrevBounds.size() == vBounds.size() );
229     }
230 
231     /**
232      * For every word in array obtained by <code>nextWord</code> method test
233      * computes bounds of the word, passing its internal character position.<p>
234      *
235      * Has <b>OK</b> status if bounds calculated by <code>getWordBoundary()</code>
236      * method are the same as bounds obtained by <code>nextWord</code> method.
237      */
_getWordBoundary()238     public void _getWordBoundary() {
239         requiredMethod("nextWord()");
240 
241         boolean bRes = true;
242 
243         for(int i = 0; i < vBounds.size(); i++) {
244             // calculate middle of the word
245             Boundary iBounds = (Boundary)vBounds.get(i);
246             int iPos = (iBounds.endPos - iBounds.startPos) / 2
247                         + iBounds.startPos;
248             Boundary bounds = oObj.getWordBoundary(UnicodeString, iPos,
249                 locale, wordType, true);
250             log.println("Expected result is: startPos = " + iBounds.startPos +
251                                  "; endPos = " + iBounds.endPos);
252             log.println("Actual result is: startPos = " + bounds.startPos
253                 + "; endPos = " + bounds.endPos + " Word is: '"
254                 + UnicodeString.substring(bounds.startPos, bounds.endPos) + "'");
255 
256             bRes = bRes && iBounds.startPos == bounds.startPos;
257             bRes = bRes && iBounds.endPos == bounds.endPos;
258         }
259 
260         tRes.tested("getWordBoundary()", bRes);
261     }
262 
263     /**
264      * For every word in array obtained by <code>nextWord</code> method test
265      * get its type, passing its internal character position.<p>
266      *
267      * Has <b>OK</b> status if every word has type <code>WordType.ANY_WORD</code>
268      */
_getWordType()269     public void _getWordType() {
270         requiredMethod("nextWord()");
271 
272         boolean bRes = true;
273 
274         for(int i = 0; i < vBounds.size(); i++) {
275             // calculate middle of the word
276             Boundary iBounds = (Boundary)vBounds.get(i);
277             int iPos = (iBounds.endPos - iBounds.startPos) / 2
278                         + iBounds.startPos;
279 
280             short type = oObj.getWordType(UnicodeString, iPos, locale);
281 
282             bRes = bRes && type == WordType.ANY_WORD;
283         }
284 
285         tRes.tested("getWordType()", bRes);
286     }
287 
288     /**
289      * For every word in array obtained by <code>nextWord</code> method test
290      * tries to determine if the character at a position starts a word.
291      * First word starting position is passed, then internal character
292      * position is passed. <p>
293      * Has <b>OK</b> status if in the first case <code>true</code>
294      * returned and in the second - <code>false</code> for every word.
295      */
_isBeginWord()296     public void _isBeginWord() {
297         requiredMethod("nextWord()");
298 
299         boolean bRes = true;
300 
301         for(int i = 0; i < vBounds.size(); i++) {
302             Boundary iBounds = (Boundary)vBounds.get(i);
303             boolean isBegin = oObj.isBeginWord(UnicodeString, iBounds.startPos,
304                                                locale, WordType.ANY_WORD);
305             bRes = bRes && isBegin;
306             boolean isNotBegin = !oObj.isBeginWord(UnicodeString,
307                     iBounds.startPos + 1, locale, WordType.ANY_WORD);
308             bRes = bRes && isNotBegin;
309 
310             log.println("At position + " + iBounds.startPos
311                 + " isBeginWord? " + isBegin);
312             log.println("At position + " + (iBounds.startPos + 1)
313                 + " isBeginWord? " + !isNotBegin);
314         }
315 
316         tRes.tested("isBeginWord()", bRes);
317     }
318 
319     /**
320      * For every word in array obtained by <code>nextWord</code> method test
321      * tries to determine if the character at a position ends a word.
322      * First word ending position is passed, then internal character
323      * position is passed. <p>
324      *
325      * Has <b>OK</b> status if in the first case <code>true</code>
326      * returned and in the second - <code>false</code> for every word.
327      */
_isEndWord()328     public void _isEndWord() {
329         requiredMethod("nextWord()");
330 
331         boolean bRes = true;
332 
333         for(int i = 0; i < vBounds.size(); i++) {
334             Boundary iBounds = (Boundary)vBounds.get(i);
335             boolean isEnd = oObj.isEndWord(UnicodeString, iBounds.endPos,
336                 locale, WordType.ANY_WORD);
337             bRes = bRes && isEnd;
338             boolean isNotEnd = !oObj.isEndWord(UnicodeString,
339                 iBounds.endPos - 1, locale, WordType.ANY_WORD);
340             bRes = bRes && isNotEnd;
341 
342             log.println("At position + " + iBounds.endPos
343                 + " isEndWord? " + isEnd);
344             log.println("At position + " + (iBounds.endPos - 1)
345                 + " isEndWord? " + !isNotEnd);
346         }
347 
348         tRes.tested("isEndWord()", bRes);
349     }
350 
351     Vector vSentenceStart = new Vector();
352     /**
353      * Tries to find all sentences starting positions passing every character
354      * as position parameter and stores them. Then tries to pass invalid
355      * position parameters.
356      *
357      * Has <b>OK</b> status if -1 is returned for wrong position arguments.
358      */
_beginOfSentence()359     public void _beginOfSentence() {
360         int iPos = 0;
361         while( iPos < UnicodeString.length() ) {
362             Integer start = new Integer( oObj.beginOfSentence(UnicodeString,
363                 iPos, locale) );
364             if (start.intValue() >= 0 && !vSentenceStart.contains(start) ) {
365                 vSentenceStart.add( start );
366                 log.println("Sentence " + vSentenceStart.size()
367                     + " : start from position " + start);
368             }
369             iPos++;
370         }
371 
372         //test for invalid nStartPosition
373         boolean bRes = oObj.beginOfSentence(UnicodeString, -10, locale) == -1;
374         bRes &= oObj.beginOfSentence(UnicodeString,
375             UnicodeString.length() + 1, locale) == -1;
376 
377         if (!bRes) {
378             log.println("When invalid position, returned value isn't equal to -1");
379         }
380 
381         tRes.tested("beginOfSentence()", bRes);
382     }
383 
384     /**
385      * For every sentence starting position found in
386      * <code>beginOfSentence()</code> test tries to compute end
387      * position of a sentence and checks that the end position is
388      * greater than starting.
389      * Then wrong position arguments are passed.
390      *
391      * Has <b>OK</b> status if the end position of every sentence
392      * greater than starting and -1 returned for invalid arguments.
393      */
_endOfSentence()394     public void _endOfSentence() {
395         boolean bRes = true;
396         for(int i = 0; i < vSentenceStart.size(); i++) {
397             int start = ((Integer)vSentenceStart.get(i)).intValue();
398             int end = oObj.endOfSentence(UnicodeString, start, locale);
399             bRes &= end > start;
400             log.println("Sentence " + i + " range is [" + start + ", "
401                 + end + "]");
402         }
403 
404         //test for invalid nStartPosition
405         boolean bInvRes = oObj.endOfSentence(UnicodeString, -10, locale) == -1;
406         bInvRes &= oObj.endOfSentence(UnicodeString,
407             UnicodeString.length() + 1, locale) == -1;
408 
409         if (!bInvRes) {
410             log.println("When invalid position, returned value isn't equal to -1");
411         }
412 
413         tRes.tested("endOfSentence()", bRes && bInvRes);
414     }
415 
416     /**
417     * Tries to break a string in position other than 0 iterating characters
418     * from the string beginning (Hyphenation is not used for a while). <p>
419     *
420     * Has <b>OK</b> status if non-zero break position was found and it is
421     * less or equal than position we trying to break.
422     */
_getLineBreak()423     public void _getLineBreak() {
424         boolean bRes = true;
425         LineBreakResults lineBreakResults;
426         LineBreakHyphenationOptions lineBreakHyphenationOptions =
427             new LineBreakHyphenationOptions();
428         LineBreakUserOptions lineBreakUserOptions = new LineBreakUserOptions();
429 
430         lineBreakUserOptions.applyForbiddenRules = false;
431         lineBreakUserOptions.allowHyphenateEnglish = false;
432 
433         int breakPos = 0;
434         int pos = 0;
435 
436         while(breakPos == 0 && pos < UnicodeString.length() ) {
437             lineBreakResults = oObj.getLineBreak(UnicodeString, pos,
438                 locale, 0, lineBreakHyphenationOptions, lineBreakUserOptions);
439             breakPos = lineBreakResults.breakIndex;
440             pos++;
441         }
442 
443         // finally the position of break must be found in the middle and
444         // it must be before the break position specified
445         bRes = breakPos <= pos && breakPos > 0;
446 
447         if (!bRes) {
448             log.println("The last position was: " + pos
449                 + ", and the break position was: " + breakPos);
450         }
451 
452         tRes.tested("getLineBreak()", bRes);
453     }
454 
455     // Asian type script
456     private static String katakana = new String(new char[] {0x30A1, 0x30A2}) ;
457     // Weak type script
458     private static String arrows = new String(new char[] {0x2190, 0x2191}) ;
459     // Complex type script
460     private static String arabic = new String(new char[] {0x0641, 0x0642}) ;
461 
462     /**
463     * Tries to find the begining of the nearest script specified
464     * relatively to position passed. <p>
465     * Has <b>OK</b> status if the starting position of script is returned.
466     */
_beginOfScript()467     public void _beginOfScript() {
468         String multiScript = "ab" + katakana  ;
469 
470         int pos = oObj.beginOfScript(multiScript, 3, ScriptType.ASIAN) ;
471 
472         log.println("Position = " + pos) ;
473 
474         tRes.tested("beginOfScript()", pos == 2) ;
475     }
476 
477     /**
478     * Tries to find the end of the nearest script specified
479     * relatively to position passed. <p>
480     * Has <b>OK</b> status if the end position of script is returned.
481     */
_endOfScript()482     public void _endOfScript() {
483         String multiScript = "ab" + katakana + "cd" ;
484 
485         int pos = oObj.endOfScript(multiScript, 2, ScriptType.ASIAN) ;
486 
487         log.println("Position = " + pos) ;
488 
489         tRes.tested("endOfScript()", pos == 4) ;
490     }
491 
492     /**
493     * Tries to find the next script starting position specified
494     * relatively to position passed. <p>
495     * Has <b>OK</b> status if the appropriate position is returned.
496     */
_nextScript()497     public void _nextScript() {
498         String multiScript = "ab" + katakana + "cd"  ;
499 
500         int pos = oObj.nextScript(multiScript, 0, ScriptType.LATIN) ;
501 
502         log.println("Position = " + pos) ;
503 
504         tRes.tested("nextScript()", pos == 4) ;
505     }
506 
507     /**
508     * Tries to find the previous script starting position specified
509     * relatively to position passed. <p>
510     * Has <b>OK</b> status if the appropriate position is returned.
511     */
_previousScript()512     public void _previousScript() {
513         String multiScript = "ab" + katakana + "cd"  ;
514 
515         int pos = oObj.previousScript(multiScript, 5, ScriptType.ASIAN) ;
516 
517         log.println("Position = " + pos) ;
518 
519         tRes.tested("previousScript()", pos == 2) ;
520     }
521 
522     /**
523     * Tries to determine script type (of all four types). <p>
524     * Has <b>OK</b> status if <code>LATIN</code> type returned
525     * for ACSII character, <code>ASIAN</code> for Katakana Unicode
526     * codepoints, <code>COMPLEX</code> for Arabic Unicode
527     * codepoints and <code>WEAK</code> for codepoints from Arrows
528     * Unicode block.
529     */
_getScriptType()530     public void _getScriptType() {
531         boolean res = true ;
532 
533         res &= oObj.getScriptType("abcd", 0) == ScriptType.LATIN ;
534         res &= oObj.getScriptType(katakana, 0) == ScriptType.ASIAN;
535         res &= oObj.getScriptType(arabic, 0) == ScriptType.COMPLEX ;
536         res &= oObj.getScriptType(arrows, 0) == ScriptType.WEAK ;
537 
538         tRes.tested("getScriptType()", res) ;
539     }
540 
541     boolean bCharBlockRes = true;
542 
getCharBlockType(int pos)543     protected short getCharBlockType(int pos) {
544         short i = 1;
545         short cType = 0;
546         while (i < 31) {
547             if (oObj.beginOfCharBlock(UnicodeString, pos, locale, i) != -1) {
548                 cType = i;
549                 i = 100;
550             }
551             i++;
552         }
553 
554         return cType;
555     }
556 
557     Vector vCharBlockBounds = new Vector();
558     Vector vCharBlockTypes = new Vector();
559 
560     /**
561      * Creates array of all char blocks with their boundaries and
562      * types using <code>beginOfCharBlock()</code> and
563      * <code>endOfCharBlock()</code> methods. <p>
564      *
565      * Has <b>OK</b> status if the end of each boundary is the same
566      * as start of the next one and if the start of the first block
567      * has position 0 and the end of the last block is at the end
568      * of the whole string.
569      */
_beginOfCharBlock()570     public void _beginOfCharBlock() {
571         int iPos = 0;
572 
573         while( iPos < UnicodeString.length() && iPos > -1) {
574             short charType = getCharBlockType(iPos);
575             int startPos = oObj.beginOfCharBlock(UnicodeString, iPos,
576                 locale, charType);
577             int endPos = oObj.endOfCharBlock(UnicodeString, iPos,
578                 locale, charType);
579             iPos = endPos;
580             vCharBlockBounds.add(new Boundary(startPos, endPos));
581             log.println("" + vCharBlockBounds.size() + "). Bounds: ["
582                 + startPos + "," + endPos + "]; Type = " + charType);
583             vCharBlockTypes.add(new Short(charType));
584         }
585 
586         for(int i = 0; i < vCharBlockBounds.size() - 1; i++) {
587             int endPos = ((Boundary)vCharBlockBounds.get(i)).endPos;
588             int startPos = ((Boundary)vCharBlockBounds.get(i + 1)).startPos;
589             bCharBlockRes &= endPos == startPos;
590         }
591 
592         log.println("Testing for no intersections : " + bCharBlockRes);
593         int startPos = ((Boundary)vCharBlockBounds.get(0)).startPos;
594         bCharBlockRes &= startPos == 0;
595         int endPos = ((Boundary)vCharBlockBounds.get
596             (vCharBlockBounds.size() - 1)).endPos;
597         bCharBlockRes &= endPos == UnicodeString.length();
598         log.println("Regions should starts with 0 and ends with "
599             + UnicodeString.length());
600 
601         tRes.tested("beginOfCharBlock()", bCharBlockRes);
602     }
603 
604     /**
605      * Testing of this method is performed in <code>beginOfCharBlock()</code>
606      * method test. <p>
607      *
608      * Has the status same as <code>beginOfCharBlock()</code> method status.
609      */
_endOfCharBlock()610     public void _endOfCharBlock() {
611         requiredMethod("beginOfCharBlock()");
612         tRes.tested("endOfCharBlock()", bCharBlockRes);
613     }
614 
615     /**
616      * For every character block obtained in <code>beginOfCharBlock()</code>
617      * method test (except the first) tries to find its starting position
618      * by mean of <code>nextCharBlock()</code> method passing as position
619      * argument the position before the start of a block. <p>
620      *
621      * Has <b>OK</b> status if the start of every block was found and it's
622      * equal to this block boundary start.
623      */
_nextCharBlock()624     public void _nextCharBlock() {
625         requiredMethod("beginOfCharBlock()");
626 
627         boolean bRes = true;
628         for(int i = 0; i < vCharBlockBounds.size(); i++) {
629             Boundary bounds = (Boundary)vCharBlockBounds.get(i);
630             Short type = (Short)vCharBlockTypes.get(i);
631             if (bounds.startPos - 1 < 0) continue;
632             int iPos = oObj.nextCharBlock(UnicodeString, bounds.startPos - 1,
633                 locale, type.shortValue());
634             if (iPos != bounds.startPos) {
635                 bRes = false;
636                 log.println("nextCharBlock(UnicodeString, "
637                     + (bounds.startPos - 1) + ", locale, " + type
638                     + ") should return " + bounds.startPos);
639                 log.println("... and actual value is " + iPos);
640             }
641         }
642 
643         tRes.tested("nextCharBlock()", bRes);
644     }
645 
646     /**
647      * For every character block obtained in <code>beginOfCharBlock()</code>
648      * method test (except the first) tries to find its starting position
649      * by mean of <code>previousCharBlock()</code> method passing as position
650      * argument the position after the end of a block. <p>
651      *
652      * Has <b>OK</b> status if the start of every block was found and it's
653      * equal to this block boundary start.
654      */
_previousCharBlock()655     public void _previousCharBlock() {
656         requiredMethod("beginOfCharBlock()");
657 
658         boolean bRes = true;
659         for(int i = 0; i < vCharBlockBounds.size(); i++) {
660             Boundary bounds = (Boundary)vCharBlockBounds.get(i);
661             Short type = (Short)vCharBlockTypes.get(i);
662             int iPos = oObj.previousCharBlock(UnicodeString,
663                 bounds.endPos + 1, locale, type.shortValue());
664             if (iPos != bounds.startPos) {
665                 bRes = false;
666                 log.println("previousCharBlock(UnicodeString, "
667                     + (bounds.endPos + 1) + ", locale, " + type
668                     + ") should return " + bounds.startPos);
669                 log.println("... and actual value is " + iPos);
670             }
671         }
672 
673         tRes.tested("previousCharBlock()", bRes);
674     }
675 
676 }
677 
678