001: //##header
002: /*
003: *******************************************************************************
004: * Copyright (C) 2002-2006, International Business Machines Corporation and *
005: * others. All Rights Reserved. *
006: *******************************************************************************
007: */
008: //#ifndef FOUNDATION
009: package com.ibm.icu.dev.test.collator;
010:
011: import com.ibm.icu.text.Collator;
012: import com.ibm.icu.text.RuleBasedCollator;
013: import com.ibm.icu.text.UnicodeSet;
014:
015: import com.ibm.icu.dev.test.TestFmwk;
016: import com.ibm.icu.dev.test.util.BNF;
017: import com.ibm.icu.dev.test.util.BagFormatter;
018: import com.ibm.icu.dev.test.util.Quoter;
019:
020: import java.io.File;
021: import java.io.IOException;
022: import java.io.PrintWriter;
023: import java.text.ParseException;
024: import java.util.Random;
025:
026: public class RandomCollator extends TestFmwk {
027: public static void main(String[] args) throws Exception {
028: new RandomCollator().run(args);
029: //new CollationAPITest().TestGetTailoredSet();
030: }
031:
032: static final int CONSTRUCT_RANDOM_COUNT = 100;
033: static final int FORMAL_TEST_COUNT = 1000;
034:
035: static final String POSITION = "{$$$}";
036:
037: /*
038: class Shower extends BagFormatter.Shower {
039: public void print(String arg) {
040: log(arg);
041: }
042: }
043:
044: public Shower LOG = new Shower();
045: */
046:
047: public void TestRandom() throws IOException {
048: // int year
049: // = java.util.Calendar.getInstance().get(java.util.Calendar.YEAR);
050: // if (year < 2004) {
051: // System.out.println("\nTestRandom skipped for 2003");
052: // return;
053: // }
054: if (skipIfBeforeICU(3, 6))
055: return;
056: //String fileName;
057: PrintWriter pw = BagFormatter.openUTF8Writer(System
058: .getProperty("user.dir")
059: + File.separator, "RandomCollationTestLog.txt");
060: TestCollator tc = new TestCollator(chars);
061: pw.println("Collation Test Run");
062: pw.println("Note: For parse-exception, " + POSITION
063: + " indicates the errorOffset");
064: pw.println("Rules:");
065: pw.println(currentRules);
066: String rules = "<unknown>";
067: int sCount = 0;
068: int peCount = 0;
069: int oeCount = 0;
070: for (int i = 0; i < CONSTRUCT_RANDOM_COUNT; ++i) {
071: try {
072: rules = get();
073: if (true) {
074: Collator c = new RuleBasedCollator(rules.toString());
075: tc.test(c, FORMAL_TEST_COUNT);
076: } else {
077: pw.println(rules);
078: }
079: logln("ok");
080: sCount++;
081: } catch (ParseException pe) {
082: peCount++;
083: pw.println("========PARSE EXCEPTION======== (" + i
084: + ")");
085: int errorOffset = pe.getErrorOffset();
086: pw.print(rules.substring(0, errorOffset));
087: pw.print(POSITION);
088: pw.println(rules.substring(errorOffset));
089: //pw.println("========ERROR======== (" + i + ")");
090: //pe.printStackTrace(pw);
091: //pw.println("========END======== (" + i + ")");
092: errln("ParseException");
093: } catch (Exception e) {
094: oeCount++;
095: pw.println("========OTHER EXCEPTION======== (" + i
096: + ")");
097: e.printStackTrace(pw);
098: pw.println("========RULES======== (" + i + ")");
099: pw.println(rules);
100: //pw.println("========END======== (" + i + ")");
101: errln("ParseException");
102: }
103: }
104: pw.println("Successful: " + sCount + ",\tParseException: "
105: + peCount + ",\tOther Exception: " + oeCount);
106: logln("Successful: " + sCount + ",\tParseException: " + peCount
107: + ",\tOther Exception: " + oeCount);
108: pw.close();
109:
110: }
111:
112: public static class TestCollator extends TestComparator {
113: BNF rs;
114:
115: TestCollator(UnicodeSet chars) {
116: rs = new BNF(new Random(0), new Quoter.RuleQuoter())
117: .addRules("$root = " + chars + "{1,8};").complete();
118: }
119:
120: public Object newObject(Object c) {
121: return rs.next();
122: }
123:
124: public String format(Object c) {
125: return BagFormatter.hex.transliterate(c.toString());
126: }
127: }
128:
129: private BNF bnf;
130: String currentRules = null;
131: UnicodeSet chars;
132:
133: public String get() {
134: return bnf.next();
135: }
136:
137: public RandomCollator() {
138:
139: }
140:
141: protected void init() throws Exception {
142: init(1, 10, new UnicodeSet("[AZa-z<\\&\\[\\]]"));
143: }
144:
145: private void init(int minRuleCount, int maxRuleCount,
146: UnicodeSet chars) {
147: this .chars = chars;
148: bnf = new BNF(new Random(0), new Quoter.RuleQuoter()).addSet(
149: "$chars", chars).addRules(collationBNF).complete();
150: }
151:
152: private static String collationBNF = "$s = ' '? 50%;\r\n"
153: + "$relationList = ("
154: + " '<'"
155: + " | ' <<'"
156: + " | ' ;'"
157: + " | ' <<<'"
158: + " | ' ,'"
159: + " | ' ='"
160: + ");\r\n"
161: + "$alternateOptions = non'-'ignorable | shifted;\r\n"
162: + "$caseFirstOptions = off | upper | lower;\r\n"
163: + "$strengthOptions = '1' | '2' | '3' | '4' | 'I';\r\n"
164: + "$commandList = '['"
165: + " ( alternate ' ' $alternateOptions"
166: + " | backwards' 2'"
167: + " | normalization ' ' $onoff "
168: + " | caseLevel ' ' $onoff "
169: + " | hiraganaQ ' ' $onoff"
170: + " | caseFirst ' ' $caseFirstOptions"
171: + " | strength ' ' $strengthOptions"
172: + " ) ']';\r\n"
173: + "$ignorableTypes = (tertiary | secondary | primary) ' ' ignorable;\r\n"
174: + "$allTypes = variable | regular | implicit | trailing | $ignorableTypes;\r\n"
175: + "$onoff = on | off;\r\n"
176: + "$positionList = '[' (first | last) ' ' $allTypes ']';\r\n"
177: + "$beforeList = '[before ' ('1' | '2' | '3') ']';\r\n"
178: + "$string = $chars{1,5}~@;\r\n"
179: + "$crlf = '\r\n';\r\n"
180: + "$rel1 = '[variable top]' $s ;\r\n"
181: + "$p1 = ($string $s '|' $s)? 25%;\r\n"
182: + "$p2 = ('\\' $s $string $s)? 25%;\r\n"
183: + "$rel2 = $p1 $string $s $p2;\r\n"
184: + "$relation = $relationList $s ($rel1 | $rel2) $crlf;\r\n"
185: + "$command = $commandList $crlf;\r\n"
186: + "$reset = '&' $s ($beforeList $s)? 10% ($positionList | $string 10%) $crlf;\r\n"
187: + "$mostRules = $command 1% | $reset 5% | $relation 25%;\r\n"
188: + "$root = $command{0,5} $reset $mostRules{1,20};\r\n";
189:
190: /*
191:
192:
193: gc ; C ; Other # Cc | Cf | Cn | Co | Cs
194: gc ; Cc ; Control
195: gc ; Cf ; Format
196: gc ; Cn ; Unassigned
197: gc ; Co ; Private_Use
198: gc ; Cs ; Surrogate
199: gc ; L ; Letter # Ll | Lm | Lo | Lt | Lu
200: gc ; LC ; Cased_Letter # Ll | Lt | Lu
201: gc ; Ll ; Lowercase_Letter
202: gc ; Lm ; Modifier_Letter
203: gc ; Lo ; Other_Letter
204: gc ; Lt ; Titlecase_Letter
205: gc ; Lu ; Uppercase_Letter
206: gc ; M ; Mark # Mc | Me | Mn
207: gc ; Mc ; Spacing_Mark
208: gc ; Me ; Enclosing_Mark
209: gc ; Mn ; Nonspacing_Mark
210: gc ; N ; Number # Nd | Nl | No
211: gc ; Nd ; Decimal_Number
212: gc ; Nl ; Letter_Number
213: gc ; No ; Other_Number
214: gc ; P ; Punctuation # Pc | Pd | Pe | Pf | Pi | Po | Ps
215: gc ; Pc ; Connector_Punctuation
216: gc ; Pd ; Dash_Punctuation
217: gc ; Pe ; Close_Punctuation
218: gc ; Pf ; Final_Punctuation
219: gc ; Pi ; Initial_Punctuation
220: gc ; Po ; Other_Punctuation
221: gc ; Ps ; Open_Punctuation
222: gc ; S ; Symbol # Sc | Sk | Sm | So
223: gc ; Sc ; Currency_Symbol
224: gc ; Sk ; Modifier_Symbol
225: gc ; Sm ; Math_Symbol
226: gc ; So ; Other_Symbol
227: gc ; Z ; Separator # Zl | Zp | Zs
228: gc ; Zl ; Line_Separator
229: gc ; Zp ; Paragraph_Separator
230: gc ; Zs ; Space_Separator
231: */
232:
233: /*
234: // each rule can be:
235: // "[" command "]"
236: // "& [" position "]"
237: // "&" before chars
238: // relation "[variable top]"
239: // relation (chars "|")? chars ("/" chars)?
240: // plus, a reset must come before a relation
241:
242: // the following reflects the above rules, plus allows whitespace.
243: Pick chars = Pick.string(1, 5, Pick.codePoint(uSet)); // insert something needing quotes
244: Pick s = Pick.maybe(0.8, Pick.unquoted(" ")).name("Space"); // optional space
245: Pick CRLF = Pick.unquoted("\r\n");
246:
247: Pick rel1 = Pick.and(Pick.unquoted("[variable top]")).and2(s);
248: Pick p1 = Pick.maybe(0.25, Pick.and(chars).and2(s).and2("|").and2(s));
249: Pick p2 = Pick.maybe(0.25, Pick.and("/").and2(s).and2(chars).and2(s));
250: Pick rel2 = Pick.and(p1).and2(chars).and2(s).and2(p2);
251: Pick relation = Pick.and(Pick.or(relationList)).and2(s)
252: .and2(Pick.or(1, rel1).or2(10, rel2))
253: .and2(CRLF).name("Relation");
254:
255: Pick command = Pick.and(Pick.or(commandList)).and2(CRLF).name("Command");
256:
257: Pick reset = Pick.and("&").and2(s)
258: .and2(0.1, Pick.or(beforeList)).and2(s)
259: .and2(Pick.or(0.1, Pick.or(positionList)).or2(1.0, chars))
260: .and2(CRLF).name("Reset");
261: Pick rule = Pick.and(Pick.or(1, command).or2(5, reset).or2(25, relation)).name("Rule");
262: Pick rules2 = Pick.and(Pick.repeat(0,5,command))
263: .and2(reset)
264: .and2(Pick.repeat(1,20,rule)).name("Rules");
265: rules = Pick.Target.make(rules2);
266:
267: static final String[] relationList = {" <", " <<", " <<<", " =", " ;", " ,"};
268:
269: static final String[] commandList = {
270: "[alternate non-ignorable]", "[alternate shifted]",
271: "[backwards 2]",
272: "[normalization off]",
273: "[normalization on]",
274: "[caseLevel off]",
275: "[caseLevel on]",
276: "[caseFirst off]",
277: "[caseFirst upper]",
278: "[caseFirst lower]",
279: "[strength 1]",
280: "[strength 2]",
281: "[strength 3]",
282: "[strength 4]",
283: "[strength I]",
284: "[hiraganaQ off]",
285: "[hiraganaQ on]"
286: };
287:
288: static final String[] positionList = {
289: "[first tertiary ignorable]",
290: "[last tertiary ignorable]",
291: "[first secondary ignorable]",
292: "[last secondary ignorable]",
293: "[first primary ignorable]",
294: "[last primary ignorable]",
295: "[first variable]",
296: "[last variable]",
297: "[first regular]",
298: "[last regular]",
299: "[first implicit]",
300: "[last implicit]",
301: "[first trailing]",
302: "[last trailing]"
303: };
304:
305: static final String[] beforeList = {
306: "[before 1]",
307: "[before 2]",
308: "[before 3]"
309: };
310: */
311: }
312: //#endif
|