185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/*
285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho*******************************************************************************
3b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho* Copyright (C) 2007-2011, International Business Machines Corporation and
485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho* others. All Rights Reserved.
585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho********************************************************************************
685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho* File PLURRULTS.cpp
885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho*
985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho********************************************************************************
1085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho*/
1185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
1285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "unicode/utypes.h"
1385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
1485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#if !UCONFIG_NO_FORMATTING
1585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
16b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include <stdlib.h> // for strtod
1785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "plurults.h"
1885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "unicode/plurrule.h"
1985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
20b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof(array[0]))
2185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
2285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hovoid setupResult(const int32_t testSource[], char result[], int32_t* max);
2385bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoUBool checkEqual(PluralRules *test, char *result, int32_t max);
2485bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoUBool testEquality(PluralRules *test);
2585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
2685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// This is an API test, not a unit test.  It doesn't test very many cases, and doesn't
2785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// try to test the full functionality.  It just calls each function in the class and
2885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// verifies that it works on a basic level.
2985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
3085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hovoid PluralRulesTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
3185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho{
3285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (exec) logln("TestSuite PluralRulesAPI");
3385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    switch (index) {
3485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        TESTCASE(0, testAPI);
35b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        TESTCASE(1, testGetUniqueKeywordValue);
36b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        TESTCASE(2, testGetSamples);
37b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        TESTCASE(3, testWithin);
38b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        TESTCASE(4, testGetAllKeywordValues);
3985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        default: name = ""; break;
4085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
4185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
4285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
4385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#define PLURAL_TEST_NUM    18
4485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho/**
4585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Test various generic API methods of PluralRules for API coverage.
4685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho */
4785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hovoid PluralRulesTest::testAPI(/*char *par*/)
4885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho{
4985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UnicodeString pluralTestData[PLURAL_TEST_NUM] = {
5085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE("a: n is 1"),
5185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE("a: n mod 10 is 2"),
5285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE("a: n is not 1"),
5385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE("a: n mod 3 is not 1"),
5485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE("a: n in 2..5"),
5585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE("a: n within 2..5"),
5685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE("a: n not in 2..5"),
5785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE("a: n not within 2..5"),
5885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE("a: n mod 10 in 2..5"),
5985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE("a: n mod 10 within 2..5"),
6085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE("a: n mod 10 is 2 and n is not 12"),
6185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE("a: n mod 10 in 2..3 or n mod 10 is 5"),
6285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE("a: n mod 10 within 2..3 or n mod 10 is 5"),
6385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE("a: n is 1 or n is 4 or n is 23"),
6485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE("a: n mod 2 is 1 and n is not 3 and n in 1..11"),
6585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE("a: n mod 2 is 1 and n is not 3 and n within 1..11"),
6685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE("a: n mod 2 is 1 or n mod 5 is 1 and n is not 6"),
6785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "",
6885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    };
6985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    static const int32_t pluralTestResult[PLURAL_TEST_NUM][30] = {
7085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {1, 0},
7185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {2,12,22, 0},
7285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {0,2,3,4,5,0},
7385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {0,2,3,5,6,8,9,0},
7485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {2,3,4,5,0},
7585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {2,3,4,5,0},
7685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {0,1,6,7,8, 0},
7785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {0,1,6,7,8, 0},
7885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {2,3,4,5,12,13,14,15,22,23,24,25,0},
7985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {2,3,4,5,12,13,14,15,22,23,24,25,0},
8085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {2,22,32,42,0},
8185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {2,3,5,12,13,15,22,23,25,0},
8285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {2,3,5,12,13,15,22,23,25,0},
8385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {1,4,23,0},
8485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {1,5,7,9,11,0},
8585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {1,5,7,9,11,0},
8685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {1,3,5,7,9,11,13,15,16,0},
8785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    };
8885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UErrorCode status = U_ZERO_ERROR;
8985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
9085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // ======= Test constructors
9185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    logln("Testing PluralRules constructors");
92b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
93b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
9485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    logln("\n start default locale test case ..\n");
95b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
96b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    PluralRules defRule(status);
9785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    PluralRules* test=new PluralRules(status);
9885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    PluralRules* newEnPlural= test->forLocale(Locale::getEnglish(), status);
9985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(U_FAILURE(status)) {
10085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        dataerrln("ERROR: Could not create PluralRules (default) - exitting");
10185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        delete test;
10285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return;
10385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
104b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
10585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // ======= Test clone, assignment operator && == operator.
10685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    PluralRules *dupRule = defRule.clone();
107b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (dupRule==NULL) {
108b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln("ERROR: clone plural rules test failed!");
109b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete test;
110b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
111b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
11285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if ( *dupRule != defRule ) {
11385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            errln("ERROR:  clone plural rules test failed!");
11485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
11585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
11685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    *dupRule = *newEnPlural;
11785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (dupRule!=NULL) {
11885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if ( *dupRule != *newEnPlural ) {
11985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            errln("ERROR:  clone plural rules test failed!");
12085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
12185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        delete dupRule;
12285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
12385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
12485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    delete newEnPlural;
12585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
126b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // ======= Test empty plural rules
12785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    logln("Testing Simple PluralRules");
128b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
12985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    PluralRules* empRule = test->createRules(UNICODE_STRING_SIMPLE("a:n"), status);
13085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UnicodeString key;
13185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    for (int32_t i=0; i<10; ++i) {
13285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        key = empRule->select(i);
13385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if ( key.charAt(0)!= 0x61 ) { // 'a'
13485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            errln("ERROR:  empty plural rules test failed! - exitting");
13585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
13685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
13785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (empRule!=NULL) {
13885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        delete empRule;
13985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
140b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
141b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // ======= Test simple plural rules
14285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    logln("Testing Simple PluralRules");
143b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
14485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    char result[100];
14585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t max;
146b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
14785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    for (int32_t i=0; i<PLURAL_TEST_NUM-1; ++i) {
14885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho       PluralRules *newRules = test->createRules(pluralTestData[i], status);
14985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho       setupResult(pluralTestResult[i], result, &max);
15085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho       if ( !checkEqual(newRules, result, max) ) {
15185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            errln("ERROR:  simple plural rules failed! - exitting");
15285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            delete test;
15385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return;
15485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
15585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho       if (newRules!=NULL) {
15685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           delete newRules;
15785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho       }
15885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
15985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
160b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // ======= Test complex plural rules
16285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    logln("Testing Complex PluralRules");
163b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // TODO: the complex test data is hard coded. It's better to implement
16485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // a parser to parse the test data.
16585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UnicodeString complexRule = UNICODE_STRING_SIMPLE("a: n in 2..5; b: n in 5..8; c: n mod 2 is 1");
166b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString complexRule2 = UNICODE_STRING_SIMPLE("a: n within 2..5; b: n within 5..8; c: n mod 2 is 1");
167b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    char cRuleResult[] =
16885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    {
16985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho       0x6F, // 'o'
17085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho       0x63, // 'c'
17185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho       0x61, // 'a'
17285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho       0x61, // 'a'
17385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho       0x61, // 'a'
17485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho       0x61, // 'a'
17585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho       0x62, // 'b'
17685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho       0x62, // 'b'
17785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho       0x62, // 'b'
17885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho       0x63, // 'c'
17985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho       0x6F, // 'o'
18085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho       0x63  // 'c'
18185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    };
18285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    PluralRules *newRules = test->createRules(complexRule, status);
18385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if ( !checkEqual(newRules, cRuleResult, 12) ) {
18485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho         errln("ERROR:  complex plural rules failed! - exitting");
18585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho         delete test;
18685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho         return;
18785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     }
18885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (newRules!=NULL) {
18985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        delete newRules;
19085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        newRules=NULL;
19185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
19285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    newRules = test->createRules(complexRule2, status);
19385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if ( !checkEqual(newRules, cRuleResult, 12) ) {
19485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho         errln("ERROR:  complex plural rules failed! - exitting");
19585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho         delete test;
19685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho         return;
19785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     }
19885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (newRules!=NULL) {
19985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        delete newRules;
20085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        newRules=NULL;
20185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
202b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
20385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // ======= Test decimal fractions plural rules
20485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UnicodeString decimalRule= UNICODE_STRING_SIMPLE("a: n not in 0..100;");
20585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UnicodeString KEYWORD_A = UNICODE_STRING_SIMPLE("a");
20685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    status = U_ZERO_ERROR;
20785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    newRules = test->createRules(decimalRule, status);
20885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (U_FAILURE(status)) {
20985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        dataerrln("ERROR: Could not create PluralRules for testing fractions - exitting");
21085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        delete test;
21185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return;
21285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
21385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    double fData[10] = {-100, -1, -0.0, 0, 0.1, 1, 1.999, 2.0, 100, 100.001 };
214b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UBool isKeywordA[10] = {
21585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE };
21685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    for (int32_t i=0; i<10; i++) {
21785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if ((newRules->select(fData[i])== KEYWORD_A) != isKeywordA[i]) {
21885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho             errln("ERROR: plural rules for decimal fractions test failed!");
21985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
22085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
22185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (newRules!=NULL) {
22285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        delete newRules;
22385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        newRules=NULL;
22485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
225b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
226b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
227b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
22885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // ======= Test Equality
22985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    logln("Testing Equality of PluralRules");
230b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
23185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
23285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if ( !testEquality(test) ) {
23385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho         errln("ERROR:  complex plural rules failed! - exitting");
23485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho         delete test;
23585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho         return;
23685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho     }
23785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
238b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
23985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // ======= Test getStaticClassID()
24085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    logln("Testing getStaticClassID()");
241b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
24285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if(test->getDynamicClassID() != PluralRules::getStaticClassID()) {
24385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        errln("ERROR: getDynamicClassID() didn't return the expected value");
24485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
24585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    // ====== Test fallback to parent locale
24685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    PluralRules *en_UK = test->forLocale(Locale::getUK(), status);
24785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    PluralRules *en = test->forLocale(Locale::getEnglish(), status);
24885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (en_UK != NULL && en != NULL) {
24985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if ( *en_UK != *en ) {
25085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            errln("ERROR:  test locale fallback failed!");
25185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
25285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
25385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    delete en;
25485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    delete en_UK;
25585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
25685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    PluralRules *zh_Hant = test->forLocale(Locale::getTaiwan(), status);
25785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    PluralRules *zh = test->forLocale(Locale::getChinese(), status);
25885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (zh_Hant != NULL && zh != NULL) {
25985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if ( *zh_Hant != *zh ) {
26085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            errln("ERROR:  test locale fallback failed!");
26185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
26285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
26385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    delete zh_Hant;
26485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    delete zh;
26585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    delete test;
26685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
26785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
26885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hovoid setupResult(const int32_t testSource[], char result[], int32_t* max) {
26985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t i=0;
27085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t curIndex=0;
271b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
27285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    do {
27385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        while (curIndex < testSource[i]) {
27485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            result[curIndex++]=0x6F; //'o' other
27585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
27685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        result[curIndex++]=0x61; // 'a'
277b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
27885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    } while(testSource[++i]>0);
27985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    *max=curIndex;
28085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
28185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
28285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
28385bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoUBool checkEqual(PluralRules *test, char *result, int32_t max) {
28485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UnicodeString key;
28585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UBool isEqual = TRUE;
28685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    for (int32_t i=0; i<max; ++i) {
28785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        key= test->select(i);
28885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if ( key.charAt(0)!=result[i] ) {
28985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            isEqual = FALSE;
29085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
29185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
29285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return isEqual;
29385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
29485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
29585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#define MAX_EQ_ROW  2
29685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#define MAX_EQ_COL  5
29785bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoUBool testEquality(PluralRules *test) {
29885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UnicodeString testEquRules[MAX_EQ_ROW][MAX_EQ_COL] = {
29985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {   UNICODE_STRING_SIMPLE("a: n in 2..3"),
300b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UNICODE_STRING_SIMPLE("a: n is 2 or n is 3"),
30185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE( "a:n is 3 and n in 2..5 or n is 2"),
30285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "",
30385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        },
30485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        {   UNICODE_STRING_SIMPLE("a: n is 12; b:n mod 10 in 2..3"),
30585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE("b: n mod 10 in 2..3 and n is not 12; a: n in 12..12"),
30685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            UNICODE_STRING_SIMPLE("b: n is 13; a: n in 12..13; b: n mod 10 is 2 or n mod 10 is 3"),
30785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            "",
30885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
30985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    };
31085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UErrorCode status = U_ZERO_ERROR;
31185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UnicodeString key[MAX_EQ_COL];
31285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UBool ret=TRUE;
31385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    for (int32_t i=0; i<MAX_EQ_ROW; ++i) {
31485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        PluralRules* rules[MAX_EQ_COL];
315b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
31685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        for (int32_t j=0; j<MAX_EQ_COL; ++j) {
31785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            rules[j]=NULL;
31885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
31985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        int32_t totalRules=0;
32085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        while((totalRules<MAX_EQ_COL) && (testEquRules[i][totalRules].length()>0) ) {
32185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            rules[totalRules]=test->createRules(testEquRules[i][totalRules], status);
32285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            totalRules++;
32385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
32485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        for (int32_t n=0; n<300 && ret ; ++n) {
32585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            for(int32_t j=0; j<totalRules;++j) {
32685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                key[j] = rules[j]->select(n);
32785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
32885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            for(int32_t j=0; j<totalRules-1;++j) {
32985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                if (key[j]!=key[j+1]) {
33085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    ret= FALSE;
33185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
33285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
33385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
334b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
33585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
33685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        for (int32_t j=0; j<MAX_EQ_COL; ++j) {
33785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (rules[j]!=NULL) {
33885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                delete rules[j];
33985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
34085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
34185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
342b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
34385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return ret;
34485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
34585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
346b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
347b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoPluralRulesTest::assertRuleValue(const UnicodeString& rule, double expected) {
348b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  assertRuleKeyValue("a:" + rule, "a", expected);
349b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
350b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
351b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
352b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoPluralRulesTest::assertRuleKeyValue(const UnicodeString& rule,
353b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                    const UnicodeString& key, double expected) {
354b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  UErrorCode status = U_ZERO_ERROR;
355b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  PluralRules *pr = PluralRules::createRules(rule, status);
356b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  double result = pr->getUniqueKeywordValue(key);
357b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  delete pr;
358b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  if (expected != result) {
359b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    errln("expected %g but got %g", expected, result);
360b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  }
361b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
362b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
363b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid PluralRulesTest::testGetUniqueKeywordValue() {
364b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  assertRuleValue("n is 1", 1);
365b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  assertRuleValue("n in 2..2", 2);
366b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  assertRuleValue("n within 2..2", 2);
367b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  assertRuleValue("n in 3..4", UPLRULES_NO_UNIQUE_VALUE);
368b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  assertRuleValue("n within 3..4", UPLRULES_NO_UNIQUE_VALUE);
369b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  assertRuleValue("n is 2 or n is 2", 2);
370b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  assertRuleValue("n is 2 and n is 2", 2);
371b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  assertRuleValue("n is 2 or n is 3", UPLRULES_NO_UNIQUE_VALUE);
372b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  assertRuleValue("n is 2 and n is 3", UPLRULES_NO_UNIQUE_VALUE);
373b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  assertRuleValue("n is 2 or n in 2..3", UPLRULES_NO_UNIQUE_VALUE);
374b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  assertRuleValue("n is 2 and n in 2..3", 2);
375b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  assertRuleKeyValue("a: n is 1", "not_defined", UPLRULES_NO_UNIQUE_VALUE); // key not defined
376b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  assertRuleKeyValue("a: n is 1", "other", UPLRULES_NO_UNIQUE_VALUE); // key matches default rule
377b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
378b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
379b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid PluralRulesTest::testGetSamples() {
380b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  // no get functional equivalent API in ICU4C, so just
381b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  // test every locale...
382b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  UErrorCode status = U_ZERO_ERROR;
383b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  int32_t numLocales;
384b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  const Locale* locales = Locale::getAvailableLocales(numLocales);
385b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
386b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  double values[4];
387b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  for (int32_t i = 0; U_SUCCESS(status) && i < numLocales; ++i) {
388b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    PluralRules *rules = PluralRules::forLocale(locales[i], status);
389b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
390b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      break;
391b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
392b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    StringEnumeration *keywords = rules->getKeywords(status);
393b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
394b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      delete rules;
395b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      break;
396b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
397b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UnicodeString* keyword;
398b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    while (NULL != (keyword = keywords->snext(status))) {
399b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      int32_t count = rules->getSamples(*keyword, values, 4, status);
400b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      if (U_FAILURE(status)) {
401b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln(UNICODE_STRING_SIMPLE("getSamples() failed for locale ") +
402b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho              locales[i].getName() +
403b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho              UNICODE_STRING_SIMPLE(", keyword ") + *keyword);
404b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        continue;
405b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      }
406b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      if (count == 0) {
407b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln("no samples for keyword");
408b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      }
409b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      if (count > LENGTHOF(values)) {
410b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        errln(UNICODE_STRING_SIMPLE("getSamples()=") + count +
411b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho              UNICODE_STRING_SIMPLE(", too many values, for locale ") +
412b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho              locales[i].getName() +
413b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho              UNICODE_STRING_SIMPLE(", keyword ") + *keyword);
414b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        count = LENGTHOF(values);
415b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      }
416b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      for (int32_t j = 0; j < count; ++j) {
417b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (values[j] == UPLRULES_NO_UNIQUE_VALUE) {
418b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          errln("got 'no unique value' among values");
419b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
420b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          UnicodeString resultKeyword = rules->select(values[j]);
421b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          if (*keyword != resultKeyword) {
422b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            errln("keywords don't match");
423b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          }
424b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
425b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      }
426b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
427b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    delete keywords;
428b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    delete rules;
429b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  }
430b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
431b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
432b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid PluralRulesTest::testWithin() {
433b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  // goes to show you what lack of testing will do.
434b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  // of course, this has been broken for two years and no one has noticed...
435b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  UErrorCode status = U_ZERO_ERROR;
436b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  PluralRules *rules = PluralRules::createRules("a: n mod 10 in 5..8", status);
437b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  if (!rules) {
438b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    errln("couldn't instantiate rules");
439b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return;
440b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  }
441b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
442b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  UnicodeString keyword = rules->select((int32_t)26);
443b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  if (keyword != "a") {
444b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    errln("expected 'a' for 26 but didn't get it.");
445b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  }
446b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
447b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  keyword = rules->select(26.5);
448b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  if (keyword != "other") {
449b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    errln("expected 'other' for 26.5 but didn't get it.");
450b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  }
451b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
452b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  delete rules;
453b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
454b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
455b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
456b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoPluralRulesTest::testGetAllKeywordValues() {
457b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const char* data[] = {
458b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        "a: n in 2..5", "a: 2,3,4,5; other: null; b:",
459b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        "a: n not in 2..5", "a: null; other: null",
460b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        "a: n within 2..5", "a: null; other: null",
461b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        "a: n not within 2..5", "a: null; other: null",
462b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        "a: n in 2..5 or n within 6..8", "a: null", // ignore 'other' here on out, always null
463b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        "a: n in 2..5 and n within 6..8", "a:",
464b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        "a: n in 2..5 and n within 5..8", "a: 5",
465b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        "a: n within 2..5 and n within 6..8", "a:", // our sampling catches these
466b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        "a: n within 2..5 and n within 5..8", "a: 5", // ''
467b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        "a: n within 1..2 and n within 2..3 or n within 3..4 and n within 4..5", "a: 2,4",
468b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        "a: n within 1..2 and n within 2..3 or n within 3..4 and n within 4..5 "
469b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          "or n within 5..6 and n within 6..7", "a: null", // but not this...
470b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        "a: n mod 3 is 0", "a: null",
471b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        "a: n mod 3 is 0 and n within 1..2", "a:",
472b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        "a: n mod 3 is 0 and n within 0..5", "a: 0,3",
473b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        "a: n mod 3 is 0 and n within 0..6", "a: null", // similarly with mod, we don't catch...
474b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        "a: n mod 3 is 0 and n in 3..12", "a: 3,6,9,12",
475b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        NULL
476b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    };
477b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
478b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (int i = 0; data[i] != NULL; i += 2) {
479b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UErrorCode status = U_ZERO_ERROR;
480b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UnicodeString ruleDescription(data[i], -1, US_INV);
481b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const char* result = data[i+1];
482b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
483b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        logln("[%d] %s", i >> 1, data[i]);
484b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
485b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        PluralRules *p = PluralRules::createRules(ruleDescription, status);
486b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_FAILURE(status)) {
487b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            logln("could not create rules from '%s'\n", data[i]);
488b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            continue;
489b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
490b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
491b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const char* rp = result;
492b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        while (*rp) {
493b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            while (*rp == ' ') ++rp;
494b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (!rp) {
495b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                break;
496b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
497b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
498b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const char* ep = rp;
499b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            while (*ep && *ep != ':') ++ep;
500b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
501b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            status = U_ZERO_ERROR;
502b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UnicodeString keyword(rp, ep - rp, US_INV);
503b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            double samples[4]; // no test above should have more samples than 4
504b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t count = p->getAllKeywordValues(keyword, &samples[0], 4, status);
505b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_FAILURE(status)) {
506b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                errln("error getting samples for %s", rp);
507b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                break;
508b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
509b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
510b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (count > 4) {
511b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho              errln("count > 4 for keyword %s", rp);
512b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho              count = 4;
513b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
514b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
515b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (*ep) {
516b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                ++ep; // skip colon
517b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                while (*ep && *ep == ' ') ++ep; // and spaces
518b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
519b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
520b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UBool ok = TRUE;
521b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (count == -1) {
522b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (*ep != 'n') {
523b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    errln("expected values for keyword %s but got -1 (%s)", rp, ep);
524b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    ok = FALSE;
525b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
526b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else if (*ep == 'n') {
527b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                errln("expected count of -1, got %d, for keyword %s (%s)", count, rp, ep);
528b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                ok = FALSE;
529b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
530b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
531b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // We'll cheat a bit here.  The samples happend to be in order and so are our
532b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // expected values, so we'll just test in order until a failure.  If the
533b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // implementation changes to return samples in an arbitrary order, this test
534b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // must change.  There's no actual restriction on the order of the samples.
535b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
536b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            for (int j = 0; ok && j < count; ++j ) { // we've verified count < 4
537b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                double val = samples[j];
538b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (*ep == 0 || *ep == ';') {
539b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    errln("got unexpected value[%d]: %g", j, val);
540b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    ok = FALSE;
541b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    break;
542b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
543b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                char* xp;
544b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                double expectedVal = strtod(ep, &xp);
545b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (xp == ep) {
546b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // internal error
547b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    errln("yikes!");
548b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    ok = FALSE;
549b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    break;
550b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
551b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                ep = xp;
552b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (expectedVal != val) {
553b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    errln("expected %g but got %g", expectedVal, val);
554b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    ok = FALSE;
555b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    break;
556b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
557b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (*ep == ',') ++ep;
558b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
559b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
560b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (ok && count != -1) {
561b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (!(*ep == 0 || *ep == ';')) {
562b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    errln("didn't get expected value: %s", ep);
563b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    ok = FALSE;
564b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
565b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
566b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
567b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            while (*ep && *ep != ';') ++ep;
568b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (*ep == ';') ++ep;
569b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            rp = ep;
570b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
571b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete p;
572b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
573b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
574b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
575b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#endif /* #if !UCONFIG_NO_FORMATTING */
576