blob: b8cb855191fd912fc5346c86b6e822e3fc8c759c [file] [log] [blame]
/*
*******************************************************************************
* Copyright (C) 2009-2014, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
package com.ibm.icu.dev.test.format;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
import java.util.Random;
import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.impl.text.RbnfScannerProviderImpl;
import com.ibm.icu.text.RbnfLenientScannerProvider;
import com.ibm.icu.text.RuleBasedNumberFormat;
import com.ibm.icu.util.ULocale;
public class RbnfLenientScannerTest extends TestFmwk {
private static final RbnfLenientScannerProvider provider = new RbnfScannerProviderImpl();
public static void main(String[] args) {
try {
new RbnfLenientScannerTest().run(args);
}
catch (Throwable e) {
System.out.println("Entire test failed because of exception: "
+ e.toString());
e.printStackTrace();
}
}
/**
* Ensure that the default provider is instantiated and used if none is set
* and lenient parse is on.
*/
public void TestDefaultProvider() {
RuleBasedNumberFormat formatter
= new RuleBasedNumberFormat(Locale.US,
RuleBasedNumberFormat.SPELLOUT);
formatter.setLenientScannerProvider(null);
formatter.setLenientParseMode(true);
String[][] lpTestData = {
{ "2 thousand six HUNDRED fifty-7", "2,657" },
};
if (logKnownIssue("9503", "Lenient parse problems with English RBNF")) {
logln("Can't do lenient parse test due to http://bugs.icu-project.org/trac/ticket/9503");
} else {
doLenientParseTest(formatter, lpTestData);
}
}
/**
* Perform a simple spot check on the English spellout rules
*/
public void TestEnglishSpellout() {
RuleBasedNumberFormat formatter
= new RuleBasedNumberFormat(Locale.US,
RuleBasedNumberFormat.SPELLOUT);
formatter.setLenientScannerProvider(provider);
formatter.setLenientParseMode(true);
String[][] lpTestData = {
{ "FOurhundred thiRTY six", "436" },
// test spaces before fifty-7 causing lenient parse match of "fifty-" to " fifty"
// leaving "-7" for remaining parse, resulting in 2643 as the parse result.
{ "fifty-7", "57" },
{ " fifty-7", "57" },
{ " fifty-7", "57" },
{ "2 thousand six HUNDRED fifty-7", "2,657" },
{ "fifteen hundred and zero", "1,500" }
};
if (logKnownIssue("9503", null)) {
logln("Can't do lenient parse test due to http://bugs.icu-project.org/trac/ticket/9503");
} else {
doLenientParseTest(formatter, lpTestData);
}
}
/**
* Perform a simple spot check on the duration-formatting rules
*/
public void TestDurations() {
RuleBasedNumberFormat formatter
= new RuleBasedNumberFormat(Locale.US,
RuleBasedNumberFormat.DURATION);
formatter.setLenientScannerProvider(provider);
formatter.setLenientParseMode(true);
String[][] lpTestData = {
{ "2-51-33", "10,293" }
};
doLenientParseTest(formatter, lpTestData);
}
/**
* Perform a simple spot check on the French spellout rules
*/
public void TestFrenchSpellout() {
RuleBasedNumberFormat formatter
= new RuleBasedNumberFormat(Locale.FRANCE,
RuleBasedNumberFormat.SPELLOUT);
formatter.setLenientScannerProvider(provider);
formatter.setLenientParseMode(true);
String[][] lpTestData = {
{ "trente-et-un", "31" },
{ "un cent quatre vingt dix huit", "198" }
};
doLenientParseTest(formatter, lpTestData);
}
/**
* Perform a simple spot check on the German spellout rules
*/
public void TestGermanSpellout() {
RuleBasedNumberFormat formatter
= new RuleBasedNumberFormat(Locale.GERMANY,
RuleBasedNumberFormat.SPELLOUT);
formatter.setLenientScannerProvider(provider);
formatter.setLenientParseMode(true);
String[][] lpTestData = {
{ "ein Tausend sechs Hundert fuenfunddreissig", "1,635" }
};
doLenientParseTest(formatter, lpTestData);
}
public void TestAllLocales() {
StringBuffer errors = null;
ULocale[] locales = ULocale.getAvailableLocales();
String[] names = {
" (spellout) ",
" (ordinal) ",
" (duration) "
};
double[] numbers = {45.678, 1, 2, 10, 11, 100, 110, 200, 1000, 1111, -1111};
Random r = null;
// RBNF parse is extremely slow when lenient option is enabled.
// For non-exhaustive mode, we only test a few locales.
// "nl_NL", "be" had crash problem reported by #6534
String[] parseLocales = {"en_US", "nl_NL", "be"};
for (int i = 0; i < locales.length; ++i) {
ULocale loc = locales[i];
int count = numbers.length;
boolean testParse = true;
if (getInclusion() <= 5) {
testParse = false;
for (int k = 0; k < parseLocales.length; k++) {
if (loc.toString().equals(parseLocales[k])) {
testParse = true;
break;
}
}
} else {
//RBNF parse is too slow. Increase count only for debugging purpose for now.
//count = 100;
}
for (int j = 0; j < 3; ++j) {
RuleBasedNumberFormat fmt = new RuleBasedNumberFormat(loc, j+1);
for (int c = 0; c < count; c++) {
double n;
if (c < numbers.length) {
n = numbers[c];
} else {
if (r == null) {
r = createRandom();
}
n = ((int)(r.nextInt(10000) - 3000)) / 16d;
}
String s = fmt.format(n);
logln(loc.getName() + names[j] + "success format: " + n + " -> " + s);
if (testParse) {
// We do not validate the result in this test case,
// because there are cases which do not round trip by design.
try {
// non-lenient parse
fmt.setLenientParseMode(false);
Number num = fmt.parse(s);
logln(loc.getName() + names[j] + "success parse: " + s + " -> " + num);
// lenient parse
fmt.setLenientScannerProvider(provider);
fmt.setLenientParseMode(true);
num = fmt.parse(s);
logln(loc.getName() + names[j] + "success parse (lenient): " + s + " -> " + num);
} catch (ParseException pe) {
String msg = loc.getName() + names[j] + "ERROR:" + pe.getMessage();
logln(msg);
if (errors == null) {
errors = new StringBuffer();
}
errors.append("\n" + msg);
}
}
}
}
}
if (errors != null) {
//TODO: We need to fix parse problems - see #6895 / #6896
//errln(errors.toString());
logln(errors.toString());
}
}
void doLenientParseTest(RuleBasedNumberFormat formatter,
String[][] testData) {
NumberFormat decFmt = NumberFormat.getInstance(Locale.US);
try {
for (int i = 0; i < testData.length; i++) {
String words = testData[i][0];
String expectedNumber = testData[i][1];
String actualNumber = decFmt.format(formatter.parse(words));
if (!actualNumber.equals(expectedNumber)) {
errln("Lenient-parse spot check failed: for "
+ words + ", expected " + expectedNumber
+ ", but got " + actualNumber);
}
}
}
catch (Throwable e) {
errln("Test failed with exception: " + e.toString());
e.printStackTrace();
}
}
}