| /* | |
| * 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; | |
| formatter.format(actual, date); | |
| 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; | |
| SimpleDateFormat formatter(LOG4CXX_STR("MMM")); | |
| formatter.format(formatted, avr11); | |
| 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; | |
| SimpleDateFormat formatter(LOG4CXX_STR("MMM")); | |
| formatter.setTimeZone(TimeZone::getGMT()); | |
| formatter.format(formatted, apr11); | |
| 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); | |