// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/***********************************************************************
* COPYRIGHT:
* Copyright (c) 1997-2011, International Business Machines Corporation
* and others. All Rights Reserved.
***********************************************************************/
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING
#include "dtfmapts.h"
#include "unicode/datefmt.h"
#include "unicode/smpdtfmt.h"
#include "unicode/decimfmt.h"
#include "unicode/choicfmt.h"
#include "unicode/msgfmt.h"
// This is an API test, not a unit test. It doesn't test very many cases, and doesn't
// try to test the full functionality. It just calls each function in the class and
// verifies that it works on a basic level.
void IntlTestDateFormatAPI::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
{
if (exec) logln("TestSuite DateFormatAPI");
switch (index) {
case 0: name = "DateFormat API test";
if (exec) {
logln("DateFormat API test---"); logln("");
UErrorCode status = U_ZERO_ERROR;
Locale saveLocale;
Locale::setDefault(Locale::getEnglish(), status);
if(U_FAILURE(status)) {
errln("ERROR: Could not set default locale, test may not give correct results");
}
testAPI(/*par*/);
Locale::setDefault(saveLocale, status);
}
break;
case 1: name = "TestEquals";
if (exec) {
logln("TestEquals---"); logln("");
TestEquals();
}
break;
case 2: name = "TestNameHiding";
if (exec) {
logln("TestNameHiding---"); logln("");
TestNameHiding();
}
break;
case 3: name = "TestCoverage";
if (exec) {
logln("TestCoverage---"); logln("");
TestCoverage();
}
break;
default: name = ""; break;
}
}
/**
* Add better code coverage.
*/
void IntlTestDateFormatAPI::TestCoverage(void)
{
const char *LOCALES[] = {
"zh_CN@calendar=chinese",
"cop_EG@calendar=coptic",
"hi_IN@calendar=indian",
"am_ET@calendar=ethiopic"
};
int32_t numOfLocales = 4;
for (int32_t i = 0; i < numOfLocales; i++) {
DateFormat *df = DateFormat::createDateTimeInstance(DateFormat::kMedium, DateFormat::kMedium, Locale(LOCALES[i]));
if (df == NULL){
dataerrln("Error creating DateFormat instances.");
return;
}
delete df;
}
}
/**
* Test that the equals method works correctly.
*/
void IntlTestDateFormatAPI::TestEquals(void)
{
UErrorCode status = U_ZERO_ERROR;
// Create two objects at different system times
DateFormat *a = DateFormat::createInstance();
UDate start = Calendar::getNow();
while (Calendar::getNow() == start) ; // Wait for time to change
DateFormat *b = DateFormat::createInstance();
if (a == NULL || b == NULL){
dataerrln("Error calling DateFormat::createInstance()");
delete a;
delete b;
return;
}
if (!(*a == *b))
errln("FAIL: DateFormat objects created at different times are unequal.");
SimpleDateFormat *sdtfmt = dynamic_cast<SimpleDateFormat *>(b);
if (sdtfmt != NULL)
{
double ONE_YEAR = 365*24*60*60*1000.0;
sdtfmt->set2DigitYearStart(start + 50*ONE_YEAR, status);
if (U_FAILURE(status))
errln("FAIL: setTwoDigitStartDate failed.");
else if (*a == *b)
errln("FAIL: DateFormat objects with different two digit start dates are equal.");
}
delete a;
delete b;
}
/**
* This test checks various generic API methods in DateFormat to achieve 100%
* API coverage.
*/
void IntlTestDateFormatAPI::testAPI(/* char* par */)
{
UErrorCode status = U_ZERO_ERROR;
// ======= Test constructors
logln("Testing DateFormat constructors");
DateFormat *def = DateFormat::createInstance();
DateFormat *fr = DateFormat::createTimeInstance(DateFormat::FULL, Locale::getFrench());
DateFormat *it = DateFormat::createDateInstance(DateFormat::MEDIUM, Locale::getItalian());
DateFormat *de = DateFormat::createDateTimeInstance(DateFormat::LONG, DateFormat::LONG, Locale::getGerman());
if (def == NULL || fr == NULL || it == NULL || de == NULL){
dataerrln("Error creating DateFormat instances.");
}
// ======= Test equality
if (fr != NULL && def != NULL)
{
logln("Testing equality operator");
if( *fr == *it ) {
errln("ERROR: == failed");
}
}
// ======= Test various format() methods
if (fr != NULL && it != NULL && de != NULL)
{
logln("Testing various format() methods");
UDate d = 837039928046.0;
Formattable fD(d, Formattable::kIsDate);
UnicodeString res1, res2, res3;
FieldPosition pos1(FieldPosition::DONT_CARE), pos2(FieldPosition::DONT_CARE);
status = U_ZERO_ERROR;
res1 = fr->format(d, res1, pos1, status);
if(U_FAILURE(status)) {
errln("ERROR: format() failed (French)");
}
logln( (UnicodeString) "" + d + " formatted to " + res1);
res2 = it->format(d, res2, pos2);
logln( (UnicodeString) "" + d + " formatted to " + res2);
res3 = de->format(d, res3);
logln( (UnicodeString) "" + d + " formatted to " + res3);
}
// ======= Test parse()
if (def != NULL)
{
logln("Testing parse()");
UnicodeString text("02/03/76 2:50 AM, CST");
Formattable result1;
UDate result2, result3;
ParsePosition pos(0), pos01(0);
def->parseObject(text, result1, pos);
if(result1.getType() != Formattable::kDate) {
errln("ERROR: parseObject() failed for " + text);
}
logln(text + " parsed into " + result1.getDate());
status = U_ZERO_ERROR;
result2 = def->parse(text, status);
if(U_FAILURE(status)) {
errln("ERROR: parse() failed, stopping testing");
return;
}
logln(text + " parsed into " + result2);
result3 = def->parse(text, pos01);
logln(text + " parsed into " + result3);
}
// ======= Test getters and setters
if (fr != NULL && it != NULL && de != NULL)
{
logln("Testing getters and setters");
int32_t count = 0;
const Locale *locales = DateFormat::getAvailableLocales(count);
logln((UnicodeString) "Got " + count + " locales" );
for(int32_t i = 0; i < count; i++) {
UnicodeString name;
name = locales[i].getName();
logln(name);
}
fr->setLenient(it->isLenient());
if(fr->isLenient() != it->isLenient()) {
errln("ERROR: setLenient() failed");
}
const Calendar *cal = def->getCalendar();
Calendar *newCal = cal->clone();
de->adoptCalendar(newCal);
it->setCalendar(*newCal);
if( *(de->getCalendar()) != *(it->getCalendar())) {
errln("ERROR: adopt or set Calendar() failed");
}
const NumberFormat *nf = def->getNumberFormat();
NumberFormat *newNf = (NumberFormat*) nf->clone();
de->adoptNumberFormat(newNf);
it->setNumberFormat(*newNf);
if( *(de->getNumberFormat()) != *(it->getNumberFormat())) {
errln("ERROR: adopt or set NumberFormat() failed");
}
const TimeZone& tz = def->getTimeZone();
TimeZone *newTz = tz.clone();
de->adoptTimeZone(newTz);
it->setTimeZone(*newTz);
if( de->getTimeZone() != it->getTimeZone()) {
errln("ERROR: adopt or set TimeZone() failed");
}
}
// ======= Test getStaticClassID()
logln("Testing getStaticClassID()");
status = U_ZERO_ERROR;
DateFormat *test = new SimpleDateFormat(status);
if(U_FAILURE(status)) {
dataerrln("ERROR: Couldn't create a DateFormat - %s", u_errorName(status));
}
if(test->getDynamicClassID() != SimpleDateFormat::getStaticClassID()) {
errln("ERROR: getDynamicClassID() didn't return the expected value");
}
delete test;
delete def;
delete fr;
delete it;
delete de;
}
/**
* Test hiding of parse() and format() APIs in the Format hierarchy.
* We test the entire hierarchy, even though this test is located in
* the DateFormat API test.
*/
void
IntlTestDateFormatAPI::TestNameHiding(void) {
// N.B.: This test passes if it COMPILES, since it's a test of
// compile-time name hiding.
UErrorCode status = U_ZERO_ERROR;
Formattable dateObj(0, Formattable::kIsDate);
Formattable numObj(3.1415926535897932384626433832795);
Formattable obj;
UnicodeString str;
FieldPosition fpos;
ParsePosition ppos;
// DateFormat calling Format API
{
logln("DateFormat");
DateFormat *dateFmt = DateFormat::createInstance();
if (dateFmt) {
dateFmt->format(dateObj, str, status);
dateFmt->format(dateObj, str, fpos, status);
delete dateFmt;
} else {
dataerrln("FAIL: Can't create DateFormat");
}
}
// SimpleDateFormat calling Format & DateFormat API
{
logln("SimpleDateFormat");
status = U_ZERO_ERROR;
SimpleDateFormat sdf(status);
if (U_SUCCESS(status)) {
// Format API
sdf.format(dateObj, str, status);
sdf.format(dateObj, str, fpos, status);
// DateFormat API
sdf.format((UDate)0, str, fpos);
sdf.format((UDate)0, str);
sdf.parse(str, status);
sdf.parse(str, ppos);
sdf.getNumberFormat();
} else {
dataerrln("FAIL: Can't create SimpleDateFormat() - %s", u_errorName(status));
}
}
// NumberFormat calling Format API
{
logln("NumberFormat");
status = U_ZERO_ERROR;
NumberFormat *fmt = NumberFormat::createInstance(status);
if (fmt) {
fmt->format(numObj, str, status);
fmt->format(numObj, str, fpos, status);
delete fmt;
} else {
dataerrln("FAIL: Can't create NumberFormat()");
}
}
// DecimalFormat calling Format & NumberFormat API
{
logln("DecimalFormat");
status = U_ZERO_ERROR;
DecimalFormat fmt(status);
if(U_SUCCESS(status)) {
// Format API
fmt.format(numObj, str, status);
fmt.format(numObj, str, fpos, status);
// NumberFormat API
fmt.format(2.71828, str);
fmt.format((int32_t)1234567, str);
fmt.format(1.41421, str, fpos);
fmt.format((int32_t)9876543, str, fpos);
fmt.parse(str, obj, ppos);
fmt.parse(str, obj, status);
} else {
errcheckln(status, "FAIL: Couldn't instantiate DecimalFormat, error %s. Quitting test", u_errorName(status));
}
}
// ChoiceFormat calling Format & NumberFormat API
{
logln("ChoiceFormat");
status = U_ZERO_ERROR;
ChoiceFormat fmt("0#foo|1#foos|2#foos", status);
// Format API
fmt.format(numObj, str, status);
fmt.format(numObj, str, fpos, status);
// NumberFormat API
fmt.format(2.71828, str);
fmt.format((int32_t)1234567, str);
fmt.format(1.41421, str, fpos);
fmt.format((int32_t)9876543, str, fpos);
fmt.parse(str, obj, ppos);
fmt.parse(str, obj, status);
}
// MessageFormat calling Format API
{
logln("MessageFormat");
status = U_ZERO_ERROR;
MessageFormat fmt("", status);
// Format API
// We use dateObj, which MessageFormat should reject.
// We're testing name hiding, not the format method.
fmt.format(dateObj, str, status);
fmt.format(dateObj, str, fpos, status);
}
}
#endif /* #if !UCONFIG_NO_FORMATTING */