1/*
2 ******************************************************************************
3 * Copyright (C) 2005-2007, International Business Machines Corporation and   *
4 * others. All Rights Reserved.                                               *
5 ******************************************************************************
6 */
7#include <stdio.h>
8#include <string.h>
9#include <stdlib.h>
10#include <time.h>
11#include "rndmcoll.h"
12#include "wbnf.h"
13
14
15#if !UCONFIG_NO_COLLATION
16
17//Raymond: Following comments are copied from Java implementation
18//
19// each rule can be:
20//      "[" command "]"
21//      "& [" position "]"
22//      "&" before chars
23//      relation "[variable top]"
24//      relation (chars "|")? chars ("/" chars)?
25// plus, a reset must come before a relation
26
27
28static const char collationBNF[] =
29    "$s = ' '? 50%;"
30    "$crlf = '\r\n';"
31
32    "$alternateOptions = non'-'ignorable | shifted;"
33    "$onoff = on | off;"
34    "$caseFirstOptions = off | upper | lower;"
35    "$strengthOptions = '1' | '2' | '3' | '4' | 'I';"
36    "$commandList = '['"
37    " ( alternate ' ' $alternateOptions"
38    " | backwards' 2'"
39    " | normalization ' ' $onoff "
40    " | caseLevel ' ' $onoff "
41    " | hiraganaQ ' ' $onoff"
42    " | caseFirst ' ' $caseFirstOptions"
43    " | strength ' ' $strengthOptions"
44    " ) ']';"
45    "$command = $commandList $crlf;"
46
47    "$ignorableTypes = (tertiary | secondary | primary) ' ' ignorable;"
48    "$allTypes = variable | regular | implicit | trailing | $ignorableTypes;"
49    "$positionList = '[' (first | last) ' ' $allTypes ']';"
50
51    "$beforeList = '[before ' ('1' | '2' | '3') ']';"
52
53    "$relationList = ("
54    "   '<'"
55    " | '<<'"
56    " | ';'"
57    " | '<<<'"
58    " | ','"
59    " | '='"
60    ");"
61    "$string = $chars{1,5}~@;"
62    "$chars = a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z| '<'| '&'| '['| ']';"
63    "$rel1 = '[variable top]' $s;"
64    "$p1 = ($string $s '|' $s)? 25%;"
65    "$p2 = ('/' $s $string $s)? 25%;"
66    "$rel2 = $p1 $string $s $p2;"
67    "$relation = $relationList $s ($rel1 | $rel2) $crlf;"
68
69    "$reset = '&' $s ($beforeList $s)? 10% ($positionList 1% | $string 10%) $crlf;"
70    "$mostRules = $command 1% | $reset 5% | $relation 25%;"
71    "$root = $command{0,5} $reset $mostRules{1,20};";
72
73
74void RandomCollatorTest::Test2(){
75    // See ticket 5747 about reenabling this test.
76    errln("TestWbnf is incorrectly implemented.\nThis test should be modeled to use the existing test frame work for naming tests.\n");
77    TestWbnf();
78}
79
80
81void RandomCollatorTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* ){
82    if (exec) logln("TestSuite RandomCollatorTest: ");
83    switch (index) {
84        TESTCASE(0, Test);
85        TESTCASE(1, Test2);
86        default: name = ""; break;
87    }
88}
89
90/*
91class TestColltorCompare{
92public:
93    UBool operator()(Collator &coll, int count = 1000){
94        UnicodeString a(test_string.get_a_string());
95        UnicodeString b(test_string.get_a_string());
96        UnicodeString c(test_string.get_a_string());
97        do{
98            if (check_transitivity(coll, a, b, c)){
99                a = b;
100                b = c;
101                c = UnicodeString(test_string.get_a_string());
102            }
103        }while(count-- >= 0 );
104
105        return FALSE;
106    }
107    TestColltorCompare():test_string("$s = $c{1,8};", "$s", "$c", new Magic_SelectOneChar("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ[]&<")){
108    }
109private:
110    UBool check_transitivity(const Collator & coll, const UnicodeString &a, const UnicodeString &b, const UnicodeString &c){
111        int ab = coll.compare(a,b), ba = coll.compare(b,a);
112        int bc = coll.compare(b,c), cb = coll.compare(c,b);
113        int ca = coll.compare(c,a), ac = coll.compare(a,c);
114        //       a
115        //      / \
116        //     b - c
117        //
118        if (//counter-clockwise, maximum
119              (ab >=0 && bc >=0 && ac <0)
120            ||(bc >=0 && ca >=0 && ba <0)
121            ||(ca >=0 && ab >=0 && cb <0)
122
123            //counter-clockwise, minimum
124            ||(ab <=0 && bc <=0 && ca >0)
125            ||(bc <=0 && ca <=0 && ba >0)
126            ||(ca <=0 && ab <=0 && cb >0)
127            ){
128                return FALSE;
129            }
130          return TRUE;
131    }
132
133    LanguageGenerator test_string;
134};*/
135
136void RandomCollatorTest::Test(){
137    // See ticket 5747 about reenabling this test.
138    errln("This test needs to be fixed.\n");
139
140    LanguageGenerator test_rule;
141    if (test_rule.parseBNF(collationBNF, "$root", TRUE) != LanguageGenerator::OK){
142        errln("The test code itself is wrong.");
143        return;
144    };
145
146    //TestColltorCompare coll_test;
147
148    static const int CONSTRUCT_RANDOM_COUNT = 1000;
149    int i;
150    for (i=0; i < CONSTRUCT_RANDOM_COUNT; i++){
151        const char * rule = test_rule.next();
152        logln("\n-----------------------------------%d\n",i);
153        logln(UnicodeString(rule, strlen(rule)));
154
155        UnicodeString newRule(rule);    // potential bug
156        UErrorCode status = U_ZERO_ERROR;
157        logln(   "===========================================\n");
158        fwrite(rule, strlen(rule),1,stdout);
159        logln("\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
160
161        Collator * c = new RuleBasedCollator(newRule,status);
162
163        if (U_FAILURE(status)) {
164            errln( "Could not create Collator for the %d(th) generated rule.\n"
165                   "Error Name: %s\n"
166                   "The rule is ",
167                   i, u_errorName(status));
168            return;
169        }
170
171        delete c;
172    }
173}
174
175#endif /* #if !UCONFIG_NO_COLLATION */
176
177