blob: e771404e0f279548e4fa6838dae0d08be6c1b848 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define __STDC_CONSTANT_MACROS
#include <log4cxx/logstring.h>
#include <log4cxx/helpers/datetimedateformat.h>
#include "../logunit.h"
#include <log4cxx/helpers/pool.h>
#include "../insertwide.h"
#include <apr.h>
#include <apr_time.h>
#include <sstream>
using namespace log4cxx;
using namespace log4cxx::helpers;
using namespace std;
#define LOCALE_US "C"
#if defined(_WIN32)
#define LOCALE_FR "French_france"
#else
#define LOCALE_FR "fr_FR"
#endif
#define LOG4CXX_TEST 1
#include <log4cxx/private/log4cxx_private.h>
#if LOG4CXX_HAS_STD_LOCALE
#include <locale>
#include "localechanger.h"
#define MAKE_LOCALE(ptr, id) \
std::locale loco(id); \
std::locale* ptr = &loco;
#else
#define MAKE_LOCALE(ptr, id) \
std::locale* ptr = NULL;
#endif
/**
Unit test {@link DateTimeDateFormat}.
*/
LOGUNIT_CLASS(DateTimeDateFormatTestCase)
{
LOGUNIT_TEST_SUITE( DateTimeDateFormatTestCase );
LOGUNIT_TEST( test1 );
LOGUNIT_TEST( test2 );
LOGUNIT_TEST( test3 );
LOGUNIT_TEST( test4 );
LOGUNIT_TEST( test5 );
LOGUNIT_TEST( test6 );
#if LOG4CXX_HAS_STD_LOCALE
LOGUNIT_TEST( test7 );
LOGUNIT_TEST( test8 );
#endif
LOGUNIT_TEST_SUITE_END();
private:
#define MICROSECONDS_PER_DAY APR_INT64_C(86400000000)
/**
Asserts that formatting the provided date results in the expected string.
@param date Date date
@param timeZone TimeZone timezone for conversion
@param expected String expected string
*/
void assertFormattedTime( apr_time_t date, const std::locale * locale,
const TimeZonePtr & timeZone, const LogString & expected )
{
DateTimeDateFormat formatter(locale);
formatter.setTimeZone(timeZone);
LogString actual;
Pool p;
formatter.format(actual, date, p);
LOGUNIT_ASSERT_EQUAL( expected, actual );
}
public:
/** Convert 02 Jan 2004 00:00:00 GMT for GMT. */
void test1()
{
//
// 02 Jan 2004 00:00 GMT
//
apr_time_t jan2 = MICROSECONDS_PER_DAY * 12419;
MAKE_LOCALE(localeUS, LOCALE_US);
assertFormattedTime( jan2, localeUS, TimeZone::getGMT(), LOG4CXX_STR("02 Jan 2004 00:00:00,000"));
}
/** Convert 03 Jan 2004 00:00:00 GMT for America/Chicago. */
void test2()
{
//
// 03 Jan 2004 00:00 GMT
apr_time_t jan3 = MICROSECONDS_PER_DAY * 12420;
MAKE_LOCALE(localeUS, LOCALE_US);
assertFormattedTime( jan3, localeUS,
TimeZone::getTimeZone(LOG4CXX_STR("GMT-6")),
LOG4CXX_STR("02 Jan 2004 18:00:00,000"));
}
/** Convert 30 Jun 2004 00:00:00 GMT for GMT. */
void test3()
{
apr_time_t jun30 = MICROSECONDS_PER_DAY * 12599;
MAKE_LOCALE(localeUS, LOCALE_US);
assertFormattedTime( jun30, localeUS, TimeZone::getGMT(),
LOG4CXX_STR("30 Jun 2004 00:00:00,000"));
}
/** Convert 29 Jun 2004 00:00:00 GMT for Chicago, daylight savings in effect. */
void test4()
{
apr_time_t jul1 = MICROSECONDS_PER_DAY * 12600;
MAKE_LOCALE(localeUS, LOCALE_US);
assertFormattedTime( jul1, localeUS,
TimeZone::getTimeZone(LOG4CXX_STR("GMT-5")),
LOG4CXX_STR("30 Jun 2004 19:00:00,000"));
}
/** Test multiple calls in close intervals. */
void test5()
{
// subsequent calls within one minute
// are optimized to reuse previous formatted value
// make a couple of nearly spaced calls
apr_time_t ticks = MICROSECONDS_PER_DAY * 12601;
MAKE_LOCALE(localeUS, LOCALE_US);
assertFormattedTime( ticks, localeUS, TimeZone::getGMT(),
LOG4CXX_STR("02 Jul 2004 00:00:00,000"));
assertFormattedTime( ticks + 8000, localeUS, TimeZone::getGMT(),
LOG4CXX_STR("02 Jul 2004 00:00:00,008"));
assertFormattedTime( ticks + 17000, localeUS, TimeZone::getGMT(),
LOG4CXX_STR("02 Jul 2004 00:00:00,017"));
assertFormattedTime( ticks + 237000, localeUS, TimeZone::getGMT(),
LOG4CXX_STR("02 Jul 2004 00:00:00,237"));
assertFormattedTime( ticks + 1415000, localeUS, TimeZone::getGMT(),
LOG4CXX_STR("02 Jul 2004 00:00:01,415"));
}
/** Check that caching does not disregard timezone. This test would fail for revision 1.4 of DateTimeDateFormat.java. */
void test6()
{
apr_time_t jul3 = MICROSECONDS_PER_DAY * 12602;
MAKE_LOCALE(localeUS, LOCALE_US);
assertFormattedTime( jul3, localeUS, TimeZone::getGMT(),
LOG4CXX_STR("03 Jul 2004 00:00:00,000"));
assertFormattedTime( jul3, localeUS,
TimeZone::getTimeZone(LOG4CXX_STR("GMT-5")),
LOG4CXX_STR("02 Jul 2004 19:00:00,000"));
assertFormattedTime( jul3, localeUS, TimeZone::getGMT(),
LOG4CXX_STR("03 Jul 2004 00:00:00,000"));
}
#if LOG4CXX_HAS_STD_LOCALE
LogString formatDate(const std::locale & locale, const tm & date, const LogString & fmt)
{
//
// output the using STL
//
std::basic_ostringstream<logchar> buffer;
#if defined(_MSC_VER) && _MSC_VER < 1300
_USEFAC(locale, std::time_put<logchar>)
.put(buffer, buffer, &date, fmt.c_str(), fmt.c_str() + fmt.length());
#else
#if defined(_RWSTD_NO_TEMPLATE_ON_RETURN_TYPE)
const std::time_put<logchar>& facet = std::use_facet(locale, (std::time_put<logchar>*) 0);
#else
const std::time_put<logchar>& facet = std::use_facet<std::time_put<logchar> >(locale);
#endif
facet.put(buffer, buffer, buffer.fill(), &date, fmt.c_str(), fmt.c_str() + fmt.length());
#endif
return buffer.str();
}
/** Check that format is locale sensitive. */
void test7()
{
apr_time_t avr11 = MICROSECONDS_PER_DAY * 12519;
LocaleChanger localeChange(LOCALE_FR);
if (localeChange.isEffective())
{
LogString formatted;
Pool p;
SimpleDateFormat formatter(LOG4CXX_STR("MMM"));
formatter.format(formatted, avr11, p);
std::locale localeFR(LOCALE_FR);
struct tm avr11tm = { 0, 0, 0, 11, 03, 104 };
LogString expected(formatDate(localeFR, avr11tm, LOG4CXX_STR("%b")));
LOGUNIT_ASSERT_EQUAL(expected, formatted);
}
}
/** Check that format is locale sensitive. */
void test8()
{
apr_time_t apr11 = MICROSECONDS_PER_DAY * 12519;
LocaleChanger localeChange(LOCALE_US);
if (localeChange.isEffective())
{
LogString formatted;
Pool p;
SimpleDateFormat formatter(LOG4CXX_STR("MMM"));
formatter.setTimeZone(TimeZone::getGMT());
formatter.format(formatted, apr11, p);
std::locale localeUS(LOCALE_US);
struct tm apr11tm = { 0, 0, 0, 11, 03, 104 };
LogString expected(formatDate(localeUS, apr11tm, LOG4CXX_STR("%b")));
LOGUNIT_ASSERT_EQUAL(expected, formatted);
}
}
#endif
};
LOGUNIT_TEST_SUITE_REGISTRATION(DateTimeDateFormatTestCase);