#include "locale_test.h"
#if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS)
# include <sstream>
# include <locale>
# include <stdexcept>
# if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
using namespace std;
# endif
static const char* tested_locales[] = {
//name,
# if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
"fr_FR",
"ru_RU.koi8r",
"en_GB",
"en_US",
# endif
"",
"C"
};
CPPUNIT_TEST_SUITE_REGISTRATION(LocaleTest);
//
// tests implementation
//
typedef void (LocaleTest::*_Test) (const locale&);
static void test_supported_locale(LocaleTest &inst, _Test __test) {
size_t n = sizeof(tested_locales) / sizeof(tested_locales[0]);
for (size_t i = 0; i < n; ++i) {
locale loc;
# if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
try {
# endif
locale tmp(tested_locales[i]);
loc = tmp;
# if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
}
catch (runtime_error const&) {
//This locale is not supported.
continue;
}
# endif
CPPUNIT_MESSAGE( loc.name().c_str() );
(inst.*__test)(loc);
}
}
void LocaleTest::locale_by_name() {
# if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
/*
* Check of the 22.1.1.2.7 standard point. Construction of a locale
* instance from a null pointer or an unknown name should result in
* a runtime_error exception.
*/
try {
locale loc(static_cast<char const*>(0));
CPPUNIT_FAIL;
}
catch (runtime_error const&) {
}
catch (...) {
CPPUNIT_FAIL;
}
try {
locale loc("yasli_language");
CPPUNIT_FAIL;
}
catch (runtime_error const& /* e */) {
//CPPUNIT_MESSAGE( e.what() );
}
catch (...) {
CPPUNIT_FAIL;
}
try {
string very_large_locale_name(1024, '?');
locale loc(very_large_locale_name.c_str());
CPPUNIT_FAIL;
}
catch (runtime_error const& /* e */) {
//CPPUNIT_MESSAGE( e.what() );
}
catch (...) {
CPPUNIT_FAIL;
}
#if defined (STLPORT) || !defined (_MSC_VER) || (_MSC_VER > 1400)
try {
string very_large_locale_name("LC_CTYPE=");
very_large_locale_name.append(1024, '?');
locale loc(very_large_locale_name.c_str());
CPPUNIT_FAIL;
}
catch (runtime_error const& /* e */) {
//CPPUNIT_MESSAGE( e.what() );
}
catch (...) {
CPPUNIT_FAIL;
}
try {
string very_large_locale_name("LC_ALL=");
very_large_locale_name.append(1024, '?');
locale loc(very_large_locale_name.c_str());
CPPUNIT_FAIL;
}
catch (runtime_error const& /* e */) {
//CPPUNIT_MESSAGE( e.what() );
}
catch (...) {
CPPUNIT_FAIL;
}
#endif
try {
locale loc("C");
}
catch (runtime_error const& /* e */) {
/* CPPUNIT_MESSAGE( e.what() ); */
CPPUNIT_FAIL;
}
catch (...) {
CPPUNIT_FAIL;
}
try {
// On platform without real localization support we should rely on the "C" locale facet.
locale loc("");
}
catch (runtime_error const& /* e */) {
/* CPPUNIT_MESSAGE( e.what() ); */
CPPUNIT_FAIL;
}
catch (...) {
CPPUNIT_FAIL;
}
# endif
}
void LocaleTest::loc_has_facet() {
locale loc("C");
typedef numpunct<char> implemented_facet;
CPPUNIT_ASSERT( has_facet<implemented_facet>(loc) );
/*
typedef num_put<char, back_insert_iterator<string> > not_implemented_facet;
CPPUNIT_ASSERT( !has_facet<not_implemented_facet>(loc) );
*/
}
void LocaleTest::locale_init_problem() {
# if !defined (STLPORT) || !defined (_STLP_NO_MEMBER_TEMPLATES)
test_supported_locale(*this, &LocaleTest::_locale_init_problem);
# endif
}
/*
* Creation of a locale instance imply initialization of some STLport internal
* static objects first. We use a static instance of locale to check that this
* initialization is done correctly.
*/
static locale global_loc;
static locale other_loc("");
# if !defined (STLPORT) || !defined (_STLP_NO_MEMBER_TEMPLATES)
void LocaleTest::_locale_init_problem( const locale& loc)
{
# if !defined (__APPLE__) && !defined (__FreeBSD__) || \
!defined(__GNUC__) || ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__> 3)))
typedef codecvt<char,char,mbstate_t> my_facet;
# else
// std::mbstate_t required for gcc 3.3.2 on FreeBSD...
// I am not sure what key here---FreeBSD or 3.3.2...
// - ptr 2005-04-04
typedef codecvt<char,char,std::mbstate_t> my_facet;
# endif
locale loc_ref(global_loc);
{
locale gloc( loc_ref, new my_facet() );
CPPUNIT_ASSERT( has_facet<my_facet>( gloc ) );
//The following code is just here to try to confuse the reference counting underlying mecanism:
locale::global( locale::classic() );
locale::global( gloc );
}
# if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
try {
# endif
ostringstream os("test") ;
locale loc2( loc, new my_facet() );
CPPUNIT_ASSERT( has_facet<my_facet>( loc2 ) );
os.imbue( loc2 );
# if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
}
catch ( runtime_error& ) {
CPPUNIT_FAIL;
}
catch ( ... ) {
CPPUNIT_FAIL;
}
# endif
# if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
try {
# endif
ostringstream os2("test2");
# if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
}
catch ( runtime_error& ) {
CPPUNIT_FAIL;
}
catch ( ... ) {
CPPUNIT_FAIL;
}
# endif
}
#endif
void LocaleTest::default_locale()
{
locale loc( "" );
}
class dummy_facet : public locale::facet {
public:
static locale::id id;
};
locale::id dummy_facet::id;
void LocaleTest::combine()
{
# if (!defined (STLPORT) || \
(defined (_STLP_USE_EXCEPTIONS) && !defined (_STLP_NO_MEMBER_TEMPLATES) && !defined (_STLP_NO_EXPLICIT_FUNCTION_TMPL_ARGS)))
{
try {
locale loc("");
if (!has_facet<messages<char> >(loc)) {
loc.combine<messages<char> >(loc);
CPPUNIT_FAIL;
}
}
catch (const runtime_error & /* e */) {
/* CPPUNIT_MESSAGE( e.what() ); */
}
try {
locale loc;
if (!has_facet<dummy_facet>(loc)) {
loc.combine<dummy_facet>(loc);
CPPUNIT_FAIL;
}
}
catch (const runtime_error & /* e */) {
/* CPPUNIT_MESSAGE( e.what() ); */
}
}
locale loc1(locale::classic()), loc2;
size_t loc1_index = 0;
for (size_t i = 0; _get_ref_monetary(i) != 0; ++i) {
try {
{
locale loc(_get_ref_monetary_name(_get_ref_monetary(i)));
if (loc1 == locale::classic())
{
loc1 = loc;
loc1_index = i;
continue;
}
else
{
loc2 = loc;
}
}
//We can start the test
ostringstream ostr;
ostr << "combining '" << loc2.name() << "' money facets with '" << loc1.name() << "'";
CPPUNIT_MESSAGE( ostr.str().c_str() );
//We are going to combine money facets as all formats are different.
{
//We check that resulting locale has correctly acquire loc2 facets.
locale loc = loc1.combine<moneypunct<char, true> >(loc2);
loc = loc.combine<moneypunct<char, false> >(loc2);
loc = loc.combine<money_put<char> >(loc2);
loc = loc.combine<money_get<char> >(loc2);
//Check loc has the correct facets:
_money_put_get2(loc2, loc, _get_ref_monetary(i));
//Check loc1 has not been impacted:
_money_put_get2(loc1, loc1, _get_ref_monetary(loc1_index));
//Check loc2 has not been impacted:
_money_put_get2(loc2, loc2, _get_ref_monetary(i));
}
{
//We check that resulting locale has not wrongly acquire loc1 facets that hasn't been combine:
locale loc = loc2.combine<numpunct<char> >(loc1);
loc = loc.combine<time_put<char> >(loc1);
loc = loc.combine<time_get<char> >(loc1);
//Check loc has the correct facets:
_money_put_get2(loc2, loc, _get_ref_monetary(i));
//Check loc1 has not been impacted:
_money_put_get2(loc1, loc1, _get_ref_monetary(loc1_index));
//Check loc2 has not been impacted:
_money_put_get2(loc2, loc2, _get_ref_monetary(i));
}
{
// Check auto combination do not result in weird reference counting behavior
// (might generate a crash).
loc1.combine<numpunct<char> >(loc1);
}
loc1 = loc2;
loc1_index = i;
}
catch (runtime_error const&) {
//This locale is not supported.
continue;
}
}
# endif
}
#endif