// // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_LOCALE_WITH_ICU #include int main() { std::cout << "ICU is not build... Skipping" << std::endl; } #else #ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS // Disable this "security crap" #endif #include #include #include #include #include "test_locale.hpp" #include "test_locale_tools.hpp" #include #include #include #include #include using namespace boost::locale; //#define TEST_DEBUG #ifdef BOOST_MSVC #define _CRT_SECURE_NO_WARNINGS #endif #ifdef TEST_DEBUG #undef BOOST_LOCALE_ENABLE_CHAR16_T #undef BOOST_LOCALE_ENABLE_CHAR32_T template void print_diff(T const &,T const &,int) { } template<> void print_diff(std::string const &l,std::string const &r,int line) { if(l!=r) { std::cerr << "----[" << l <<"]!=\n----["< ss; \ ss.imbue(loc); \ ss << manip << value; \ TESTEQ(ss.str(),to_correct_string(expected,loc)); \ }while(0) #ifndef _LIBCPP_VERSION static bool parsing_fails() { return true; } #else static bool parsing_fails() { static bool checked=false; static bool fails; if(!checked) { try { std::istringstream ss("x"); ss.exceptions(std::ios_base::failbit); int x; ss>>x; fails =false; } catch(std::ios_base::failure const &) { fails=true; } catch(...) { fails=false; } checked=true; if(!fails) { std::cerr << "!!! Warning: libc++ library does not throw an exception on failbit !!!" << std::endl; } } return fails; } #endif #define TEST_NOPAR(manip,actual,type) \ do{ \ type v; \ std::basic_string act= \ to_correct_string(actual,loc); \ { \ std::basic_istringstream ss; \ ss.imbue(loc); \ ss.str(act); \ ss >> manip >> v ; \ TEST(ss.fail()); \ } \ if(parsing_fails()){ \ std::basic_istringstream ss; \ ss.imbue(loc); \ ss.str(act); \ ss.exceptions(std::ios_base::failbit); \ ss >> manip; \ TEST_THROWS(ss >> v,std::ios_base::failure); \ } \ }while(0) #define TEST_PAR(manip,type,actual,expected) \ do{ \ type v; \ {std::basic_istringstream ss; \ ss.imbue(loc); \ ss.str(to_correct_string(actual,loc)); \ ss >> manip >> v >> std::ws; \ TESTEQ(v,expected); \ TEST(ss.eof()); }\ {std::basic_istringstream ss; \ ss.imbue(loc); \ ss.str(to_correct_string(std::string(actual)+"@",loc)); \ CharType tmp_c; \ ss >> manip >> v >> std::skipws >> tmp_c; \ TESTEQ(v,expected); \ TEST(tmp_c=='@'); } \ }while(0) #define TEST_FP1(manip,value_in,str,type,value_out) \ do { \ TEST_FMT(manip,value_in,str); \ TEST_PAR(manip,type,str,value_out); \ }while(0) #define TEST_FP2(m1,m2,value_in,str,type,value_out) \ do { \ TEST_FMT(m1<>m2,type,str,value_out); \ }while(0) #define TEST_FP3(m1,m2,m3,value_in,str,type,value_out) \ do { \ TEST_FMT(m1<>m2>>m3,type,str,value_out); \ }while(0) #define TEST_FP4(m1,m2,m3,m4,value_in,str,type,value_out) \ do { \ TEST_FMT(m1<>m2>>m3>>m4,type,str,value_out); \ }while(0) #define FORMAT(f,v,exp) \ do{\ std::basic_ostringstream ss; \ ss.imbue(loc); \ std::basic_string fmt = to_correct_string(f,loc); \ ss << boost::locale::basic_format(fmt) % v; \ TESTEQ(ss.str(),to_correct_string(exp,loc)); \ ss.str(to_correct_string("",loc)); \ ss << boost::locale::basic_format(boost::locale::translate(fmt.c_str())) % v; \ /*ss << boost::locale::basic_format(fmt) % v; */ \ TESTEQ(ss.str(),to_correct_string(exp,loc)); \ TESTEQ( (boost::locale::basic_format(fmt) % v).str(loc),to_correct_string(exp,loc)); \ } while(0) #define TEST_MIN_MAX_FMT(type,minval,maxval) \ do { \ TEST_FMT(as::number,std::numeric_limits::min(),minval); \ TEST_FMT(as::number,std::numeric_limits::max(),maxval); \ }while(0) #define TEST_MIN_MAX_PAR(type,minval,maxval) \ do {\ TEST_PAR(as::number,type,minval,std::numeric_limits::min()); \ TEST_PAR(as::number,type,maxval,std::numeric_limits::max()); \ }while(0) #define TEST_MIN_MAX(type,minval,maxval) \ do { \ TEST_MIN_MAX_FMT(type,minval,maxval); \ TEST_MIN_MAX_PAR(type,minval,maxval); \ }while(0) #define BOOST_ICU_VER (U_ICU_VERSION_MAJOR_NUM*100 + U_ICU_VERSION_MINOR_NUM) #define BOOST_ICU_EXACT_VER (U_ICU_VERSION_MAJOR_NUM*10000 + U_ICU_VERSION_MINOR_NUM * 100 + U_ICU_VERSION_PATCHLEVEL_NUM) bool short_parsing_fails() { static bool fails = false; static bool get_result = false; if(get_result) return fails; std::stringstream ss("65000"); ss.imbue(std::locale::classic()); short v=0; ss >> v; fails = ss.fail(); get_result = true; return fails; } template void test_manip(std::string e_charset="UTF-8") { boost::locale::generator g; std::locale loc=g("en_US."+e_charset); TEST_FP1(as::posix,1200.1,"1200.1",double,1200.1); TEST_FP1(as::number,1200.1,"1,200.1",double,1200.1); TEST_FMT(as::number<= 402 TEST_FP2(as::currency,as::currency_national,1345,"$1,345.00",int,1345); TEST_FP2(as::currency,as::currency_national,1345.34,"$1,345.34",double,1345.34); TEST_FP2(as::currency,as::currency_iso,1345,"USD1,345.00",int,1345); TEST_FP2(as::currency,as::currency_iso,1345.34,"USD1,345.34",double,1345.34); #endif TEST_FP1(as::spellout,10,"ten",int,10); #if 402 <= BOOST_ICU_VER && BOOST_ICU_VER < 408 if(e_charset=="UTF-8") { TEST_FMT(as::ordinal,1,"1\xcb\xa2\xe1\xb5\x97"); // 1st with st as ligatures } #else TEST_FMT(as::ordinal,1,"1st"); #endif time_t a_date = 3600*24*(31+4); // Feb 5th time_t a_time = 3600*15+60*33; // 15:33:05 time_t a_timesec = 13; time_t a_datetime = a_date + a_time + a_timesec; TEST_FP2(as::date, as::gmt,a_datetime,"Feb 5, 1970",time_t,a_date); TEST_FP3(as::date,as::date_short ,as::gmt,a_datetime,"2/5/70",time_t,a_date); TEST_FP3(as::date,as::date_medium,as::gmt,a_datetime,"Feb 5, 1970",time_t,a_date); TEST_FP3(as::date,as::date_long ,as::gmt,a_datetime,"February 5, 1970",time_t,a_date); TEST_FP3(as::date,as::date_full ,as::gmt,a_datetime,"Thursday, February 5, 1970",time_t,a_date); TEST_NOPAR(as::date>>as::date_short,"aa/bb/cc",double); #if BOOST_ICU_VER >= 5901 #define GMT_FULL "Greenwich Mean Time" #else #define GMT_FULL "GMT" #endif TEST_FP2(as::time, as::gmt,a_datetime,"3:33:13 PM",time_t,a_time+a_timesec); TEST_FP3(as::time,as::time_short ,as::gmt,a_datetime,"3:33 PM",time_t,a_time); TEST_FP3(as::time,as::time_medium,as::gmt,a_datetime,"3:33:13 PM",time_t,a_time+a_timesec); #if BOOST_ICU_VER >= 408 TEST_FP3(as::time,as::time_long ,as::gmt,a_datetime,"3:33:13 PM GMT",time_t,a_time+a_timesec); #if BOOST_ICU_EXACT_VER != 40800 // know bug #8675 TEST_FP3(as::time,as::time_full ,as::gmt,a_datetime,"3:33:13 PM " GMT_FULL,time_t,a_time+a_timesec); #endif #else TEST_FP3(as::time,as::time_long ,as::gmt,a_datetime,"3:33:13 PM GMT+00:00",time_t,a_time+a_timesec); TEST_FP3(as::time,as::time_full ,as::gmt,a_datetime,"3:33:13 PM GMT+00:00",time_t,a_time+a_timesec); #endif TEST_NOPAR(as::time,"AM",double); TEST_FP2(as::time, as::time_zone("GMT+01:00"),a_datetime,"4:33:13 PM",time_t,a_time+a_timesec); TEST_FP3(as::time,as::time_short ,as::time_zone("GMT+01:00"),a_datetime,"4:33 PM",time_t,a_time); TEST_FP3(as::time,as::time_medium,as::time_zone("GMT+01:00"),a_datetime,"4:33:13 PM",time_t,a_time+a_timesec); #if U_ICU_VERSION_MAJOR_NUM >= 52 #define GMT_P100 "GMT+1" #else #define GMT_P100 "GMT+01:00" #endif #if U_ICU_VERSION_MAJOR_NUM >= 50 #define PERIOD "," #define ICUAT " at" #else #define PERIOD "" #define ICUAT "" #endif TEST_FP3(as::time,as::time_long ,as::time_zone("GMT+01:00"),a_datetime,"4:33:13 PM " GMT_P100,time_t,a_time+a_timesec); #if BOOST_ICU_VER == 308 && defined(__CYGWIN__) // Known faliture ICU issue #else TEST_FP3(as::time,as::time_full ,as::time_zone("GMT+01:00"),a_datetime,"4:33:13 PM GMT+01:00",time_t,a_time+a_timesec); #endif TEST_FP2(as::datetime, as::gmt,a_datetime,"Feb 5, 1970" PERIOD " 3:33:13 PM",time_t,a_datetime); TEST_FP4(as::datetime,as::date_short ,as::time_short ,as::gmt,a_datetime,"2/5/70" PERIOD " 3:33 PM",time_t,a_date+a_time); TEST_FP4(as::datetime,as::date_medium,as::time_medium,as::gmt,a_datetime,"Feb 5, 1970" PERIOD " 3:33:13 PM",time_t,a_datetime); #if BOOST_ICU_VER >= 408 TEST_FP4(as::datetime,as::date_long ,as::time_long ,as::gmt,a_datetime,"February 5, 1970" ICUAT " 3:33:13 PM GMT",time_t,a_datetime); #if BOOST_ICU_EXACT_VER != 40800 // know bug #8675 TEST_FP4(as::datetime,as::date_full ,as::time_full ,as::gmt,a_datetime,"Thursday, February 5, 1970" ICUAT " 3:33:13 PM " GMT_FULL,time_t,a_datetime); #endif #else TEST_FP4(as::datetime,as::date_long ,as::time_long ,as::gmt,a_datetime,"February 5, 1970" PERIOD " 3:33:13 PM GMT+00:00",time_t,a_datetime); TEST_FP4(as::datetime,as::date_full ,as::time_full ,as::gmt,a_datetime,"Thursday, February 5, 1970" PERIOD " 3:33:13 PM GMT+00:00",time_t,a_datetime); #endif time_t now=time(0); time_t lnow = now + 3600 * 4; char local_time_str[256]; std::string format="%H:%M:%S"; std::basic_string format_string(format.begin(),format.end()); strftime(local_time_str,sizeof(local_time_str),format.c_str(),gmtime(&lnow)); TEST_FMT(as::ftime(format_string),now,local_time_str); TEST_FMT(as::ftime(format_string)<= 408 "Thursday, February 5, 1970" ICUAT " 3:33:13 PM " GMT_FULL, // c #else "Thursday, February 5, 1970 3:33:13 PM GMT+00:00", // c #endif "05","5","Feb", // deh "15","03","36","02", // HIjm "33","\n","PM", "03:33:13 PM",// Mnpr "15:33","13","\t","15:33:13", // RStT "Feb 5, 1970","3:33:13 PM","70","1970", // xXyY #if BOOST_ICU_VER >= 408 GMT_FULL // Z #else "GMT+00:00" // Z #endif ,"%" }; // % for(unsigned i=0;i('%'); format_string+=static_cast(marks[i]); TEST_FMT(as::ftime(format_string)< void test_format(std::string charset="UTF-8") { boost::locale::generator g; std::locale loc=g("en_US."+charset); FORMAT("{3} {1} {2}", 1 % 2 % 3,"3 1 2"); FORMAT("{1} {2}", "hello" % 2,"hello 2"); FORMAT("{1}",1200.1,"1200.1"); FORMAT("Test {1,num}",1200.1,"Test 1,200.1"); FORMAT("{{}} {1,number}",1200.1,"{} 1,200.1"); #if BOOST_ICU_VER < 5601 // bug #13276 FORMAT("{1,num=sci,p=3}",13.1,"1.310E1"); FORMAT("{1,num=scientific,p=3}",13.1,"1.310E1"); #endif FORMAT("{1,num=fix,p=3}",13.1,"13.100"); FORMAT("{1,num=fixed,p=3}",13.1,"13.100"); FORMAT("{1,<,w=3,num}",-1,"-1 "); FORMAT("{1,>,w=3,num}",1," 1"); FORMAT("{per,1}",0.1,"10%"); FORMAT("{percent,1}",0.1,"10%"); FORMAT("{1,cur}",1234,"$1,234.00"); FORMAT("{1,currency}",1234,"$1,234.00"); if(charset=="UTF-8") { if(U_ICU_VERSION_MAJOR_NUM >=4) FORMAT("{1,cur,locale=de_DE}",10,"10,00\xC2\xA0€"); else FORMAT("{1,cur,locale=de_DE}",10,"10,00 €"); } #if BOOST_ICU_VER >= 402 FORMAT("{1,cur=nat}",1234,"$1,234.00"); FORMAT("{1,cur=national}",1234,"$1,234.00"); FORMAT("{1,cur=iso}",1234,"USD1,234.00"); #endif FORMAT("{1,spell}",10,"ten"); FORMAT("{1,spellout}",10,"ten"); #if 402 <= BOOST_ICU_VER && BOOST_ICU_VER < 408 if(charset=="UTF-8") { FORMAT("{1,ord}",1,"1\xcb\xa2\xe1\xb5\x97"); FORMAT("{1,ordinal}",1,"1\xcb\xa2\xe1\xb5\x97"); } #else FORMAT("{1,ord}",1,"1st"); FORMAT("{1,ordinal}",1,"1st"); #endif time_t now=time(0); time_t lnow = now + 3600 * 4; char local_time_str[256]; std::string format="'%H:%M:%S'"; std::basic_string format_string(format.begin(),format.end()); strftime(local_time_str,sizeof(local_time_str),format.c_str(),gmtime(&lnow)); FORMAT("{1,ftime='''%H:%M:%S'''}",now,local_time_str); FORMAT("{1,local,ftime='''%H:%M:%S'''}",now,local_time_str); FORMAT("{1,ftime='''%H:%M:%S'''}",now,local_time_str); time_t a_date = 3600*24*(31+4); // Feb 5th time_t a_time = 3600*15+60*33; // 15:33:05 time_t a_timesec = 13; time_t a_datetime = a_date + a_time + a_timesec; FORMAT("{1,date,gmt};{1,time,gmt};{1,datetime,gmt};{1,dt,gmt}",a_datetime, "Feb 5, 1970;3:33:13 PM;Feb 5, 1970" PERIOD " 3:33:13 PM;Feb 5, 1970" PERIOD " 3:33:13 PM"); #if BOOST_ICU_VER >= 408 FORMAT("{1,time=short,gmt};{1,time=medium,gmt};{1,time=long,gmt};{1,date=full,gmt}",a_datetime, "3:33 PM;3:33:13 PM;3:33:13 PM GMT;Thursday, February 5, 1970"); FORMAT("{1,time=s,gmt};{1,time=m,gmt};{1,time=l,gmt};{1,date=f,gmt}",a_datetime, "3:33 PM;3:33:13 PM;3:33:13 PM GMT;Thursday, February 5, 1970"); #else FORMAT("{1,time=short,gmt};{1,time=medium,gmt};{1,time=long,gmt};{1,date=full,gmt}",a_datetime, "3:33 PM;3:33:13 PM;3:33:13 PM GMT+00:00;Thursday, February 5, 1970"); FORMAT("{1,time=s,gmt};{1,time=m,gmt};{1,time=l,gmt};{1,date=f,gmt}",a_datetime, "3:33 PM;3:33:13 PM;3:33:13 PM GMT+00:00;Thursday, February 5, 1970"); #endif FORMAT("{1,time=s,tz=GMT+01:00}",a_datetime,"4:33 PM"); FORMAT("{1,time=s,timezone=GMT+01:00}",a_datetime,"4:33 PM"); FORMAT("{1,gmt,ftime='%H'''}",a_datetime,"15'"); FORMAT("{1,gmt,ftime='''%H'}",a_datetime,"'15"); FORMAT("{1,gmt,ftime='%H o''clock'}",a_datetime,"15 o'clock"); // Test not a year of the week a_datetime=1388491200; // 2013-12-31 12:00 - check we don't use week of year FORMAT("{1,gmt,ftime='%Y'}",a_datetime,"2013"); FORMAT("{1,gmt,ftime='%y'}",a_datetime,"13"); FORMAT("{1,gmt,ftime='%D'}",a_datetime,"12/31/13"); } int main() { try { boost::locale::time_zone::global("GMT+4:00"); std::cout << "Testing char, UTF-8" << std::endl; test_manip(); test_format(); std::cout << "Testing char, ISO8859-1" << std::endl; test_manip("ISO8859-1"); test_format("ISO8859-1"); std::cout << "Testing wchar_t" << std::endl; test_manip(); test_format(); #ifdef BOOST_LOCALE_ENABLE_CHAR16_T std::cout << "Testing char16_t" << std::endl; test_manip(); test_format(); #endif #ifdef BOOST_LOCALE_ENABLE_CHAR32_T std::cout << "Testing char32_t" << std::endl; test_manip(); test_format(); #endif } catch(std::exception const &e) { std::cerr << "Failed " << e.what() << std::endl; return EXIT_FAILURE; } FINALIZE(); } #endif // NOICU // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 // boostinspect:noascii