1 #include "locale_test.h"
2 
3 #if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS)
4 #  include <sstream>
5 #  include <locale>
6 #  include <stdexcept>
7 
8 #  if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
9 using namespace std;
10 #  endif
11 
12 static const char* tested_locales[] = {
13 //name,
14 #  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
15   "fr_FR",
16   "ru_RU.koi8r",
17   "en_GB",
18   "en_US",
19 #  endif
20   "",
21   "C"
22 };
23 
24 CPPUNIT_TEST_SUITE_REGISTRATION(LocaleTest);
25 
26 //
27 // tests implementation
28 //
29 typedef void (LocaleTest::*_Test) (const locale&);
test_supported_locale(LocaleTest & inst,_Test __test)30 static void test_supported_locale(LocaleTest &inst, _Test __test) {
31   size_t n = sizeof(tested_locales) / sizeof(tested_locales[0]);
32   for (size_t i = 0; i < n; ++i) {
33     locale loc;
34 #  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
35     try {
36 #  endif
37       locale tmp(tested_locales[i]);
38       loc = tmp;
39 #  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
40     }
41     catch (runtime_error const&) {
42       //This locale is not supported.
43       continue;
44     }
45 #  endif
46     CPPUNIT_MESSAGE( loc.name().c_str() );
47     (inst.*__test)(loc);
48   }
49 }
50 
locale_by_name()51 void LocaleTest::locale_by_name() {
52 #  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
53   /*
54    * Check of the 22.1.1.2.7 standard point. Construction of a locale
55    * instance from a null pointer or an unknown name should result in
56    * a runtime_error exception.
57    */
58   try {
59     locale loc(static_cast<char const*>(0));
60     CPPUNIT_FAIL;
61   }
62   catch (runtime_error const&) {
63   }
64   catch (...) {
65     CPPUNIT_FAIL;
66   }
67 
68   try {
69     locale loc("yasli_language");
70     CPPUNIT_FAIL;
71   }
72   catch (runtime_error const& /* e */) {
73     //CPPUNIT_MESSAGE( e.what() );
74   }
75   catch (...) {
76     CPPUNIT_FAIL;
77   }
78 
79   try {
80     string very_large_locale_name(1024, '?');
81     locale loc(very_large_locale_name.c_str());
82     CPPUNIT_FAIL;
83   }
84   catch (runtime_error const& /* e */) {
85     //CPPUNIT_MESSAGE( e.what() );
86   }
87   catch (...) {
88     CPPUNIT_FAIL;
89   }
90 
91 #if defined (STLPORT) || !defined (_MSC_VER) || (_MSC_VER > 1400)
92   try {
93     string very_large_locale_name("LC_CTYPE=");
94     very_large_locale_name.append(1024, '?');
95     locale loc(very_large_locale_name.c_str());
96     CPPUNIT_FAIL;
97   }
98   catch (runtime_error const& /* e */) {
99     //CPPUNIT_MESSAGE( e.what() );
100   }
101   catch (...) {
102     CPPUNIT_FAIL;
103   }
104 
105   try {
106     string very_large_locale_name("LC_ALL=");
107     very_large_locale_name.append(1024, '?');
108     locale loc(very_large_locale_name.c_str());
109     CPPUNIT_FAIL;
110   }
111   catch (runtime_error const& /* e */) {
112     //CPPUNIT_MESSAGE( e.what() );
113   }
114   catch (...) {
115     CPPUNIT_FAIL;
116   }
117 #endif
118 
119   try {
120     locale loc("C");
121   }
122   catch (runtime_error const& /* e */) {
123     /* CPPUNIT_MESSAGE( e.what() ); */
124     CPPUNIT_FAIL;
125   }
126   catch (...) {
127     CPPUNIT_FAIL;
128   }
129 
130   try {
131     // On platform without real localization support we should rely on the "C" locale facet.
132     locale loc("");
133   }
134   catch (runtime_error const& /* e */) {
135     /* CPPUNIT_MESSAGE( e.what() ); */
136     CPPUNIT_FAIL;
137   }
138   catch (...) {
139     CPPUNIT_FAIL;
140   }
141 
142 #  endif
143 }
144 
loc_has_facet()145 void LocaleTest::loc_has_facet() {
146   locale loc("C");
147   typedef numpunct<char> implemented_facet;
148   CPPUNIT_ASSERT( has_facet<implemented_facet>(loc) );
149   /*
150   typedef num_put<char, back_insert_iterator<string> > not_implemented_facet;
151   CPPUNIT_ASSERT( !has_facet<not_implemented_facet>(loc) );
152   */
153 }
154 
locale_init_problem()155 void LocaleTest::locale_init_problem() {
156 #  if !defined (STLPORT) || !defined (_STLP_NO_MEMBER_TEMPLATES)
157   test_supported_locale(*this, &LocaleTest::_locale_init_problem);
158 #  endif
159 }
160 
161 /*
162  * Creation of a locale instance imply initialization of some STLport internal
163  * static objects first. We use a static instance of locale to check that this
164  * initialization is done correctly.
165  */
166 static locale global_loc;
167 static locale other_loc("");
168 
169 #  if !defined (STLPORT) || !defined (_STLP_NO_MEMBER_TEMPLATES)
_locale_init_problem(const locale & loc)170 void LocaleTest::_locale_init_problem( const locale& loc)
171 {
172 #    if !defined (__APPLE__) && !defined (__FreeBSD__) || \
173         !defined(__GNUC__) || ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__> 3)))
174   typedef codecvt<char,char,mbstate_t> my_facet;
175 #    else
176 // std::mbstate_t required for gcc 3.3.2 on FreeBSD...
177 // I am not sure what key here---FreeBSD or 3.3.2...
178 //      - ptr 2005-04-04
179   typedef codecvt<char,char,std::mbstate_t> my_facet;
180 #    endif
181 
182   locale loc_ref(global_loc);
183   {
184     locale gloc( loc_ref, new my_facet() );
185     CPPUNIT_ASSERT( has_facet<my_facet>( gloc ) );
186     //The following code is just here to try to confuse the reference counting underlying mecanism:
187     locale::global( locale::classic() );
188     locale::global( gloc );
189   }
190 
191 #      if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
192   try {
193 #      endif
194     ostringstream os("test") ;
195     locale loc2( loc, new my_facet() );
196     CPPUNIT_ASSERT( has_facet<my_facet>( loc2 ) );
197     os.imbue( loc2 );
198 #      if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
199   }
200   catch ( runtime_error& ) {
201     CPPUNIT_FAIL;
202   }
203   catch ( ... ) {
204    CPPUNIT_FAIL;
205   }
206 #      endif
207 
208 #      if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
209   try {
210 #      endif
211     ostringstream os2("test2");
212 #      if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
213   }
214   catch ( runtime_error& ) {
215     CPPUNIT_FAIL;
216   }
217   catch ( ... ) {
218     CPPUNIT_FAIL;
219   }
220 #  endif
221 }
222 #endif
223 
default_locale()224 void LocaleTest::default_locale()
225 {
226   locale loc( "" );
227 }
228 
229 class dummy_facet : public locale::facet {
230 public:
231   static locale::id id;
232 };
233 
234 locale::id dummy_facet::id;
235 
combine()236 void LocaleTest::combine()
237 {
238 #  if (!defined (STLPORT) || \
239        (defined (_STLP_USE_EXCEPTIONS) && !defined (_STLP_NO_MEMBER_TEMPLATES) && !defined (_STLP_NO_EXPLICIT_FUNCTION_TMPL_ARGS)))
240   {
241     try {
242       locale loc("");
243       if (!has_facet<messages<char> >(loc)) {
244         loc.combine<messages<char> >(loc);
245         CPPUNIT_FAIL;
246       }
247     }
248     catch (const runtime_error & /* e */) {
249       /* CPPUNIT_MESSAGE( e.what() ); */
250     }
251 
252     try {
253       locale loc;
254       if (!has_facet<dummy_facet>(loc)) {
255         loc.combine<dummy_facet>(loc);
256         CPPUNIT_FAIL;
257       }
258     }
259     catch (const runtime_error & /* e */) {
260       /* CPPUNIT_MESSAGE( e.what() ); */
261     }
262   }
263 
264   locale loc1(locale::classic()), loc2;
265   size_t loc1_index = 0;
266   for (size_t i = 0; _get_ref_monetary(i) != 0; ++i) {
267     try {
268       {
269         locale loc(_get_ref_monetary_name(_get_ref_monetary(i)));
270         if (loc1 == locale::classic())
271         {
272           loc1 = loc;
273           loc1_index = i;
274           continue;
275         }
276         else
277         {
278           loc2 = loc;
279         }
280       }
281 
282       //We can start the test
283       ostringstream ostr;
284       ostr << "combining '" << loc2.name() << "' money facets with '" << loc1.name() << "'";
285       CPPUNIT_MESSAGE( ostr.str().c_str() );
286 
287       //We are going to combine money facets as all formats are different.
288       {
289         //We check that resulting locale has correctly acquire loc2 facets.
290         locale loc = loc1.combine<moneypunct<char, true> >(loc2);
291         loc = loc.combine<moneypunct<char, false> >(loc2);
292         loc = loc.combine<money_put<char> >(loc2);
293         loc = loc.combine<money_get<char> >(loc2);
294 
295         //Check loc has the correct facets:
296         _money_put_get2(loc2, loc, _get_ref_monetary(i));
297 
298         //Check loc1 has not been impacted:
299         _money_put_get2(loc1, loc1, _get_ref_monetary(loc1_index));
300 
301         //Check loc2 has not been impacted:
302         _money_put_get2(loc2, loc2, _get_ref_monetary(i));
303       }
304       {
305         //We check that resulting locale has not wrongly acquire loc1 facets that hasn't been combine:
306         locale loc = loc2.combine<numpunct<char> >(loc1);
307         loc = loc.combine<time_put<char> >(loc1);
308         loc = loc.combine<time_get<char> >(loc1);
309 
310         //Check loc has the correct facets:
311         _money_put_get2(loc2, loc, _get_ref_monetary(i));
312 
313         //Check loc1 has not been impacted:
314         _money_put_get2(loc1, loc1, _get_ref_monetary(loc1_index));
315 
316         //Check loc2 has not been impacted:
317         _money_put_get2(loc2, loc2, _get_ref_monetary(i));
318       }
319 
320       {
321         // Check auto combination do not result in weird reference counting behavior
322         // (might generate a crash).
323         loc1.combine<numpunct<char> >(loc1);
324       }
325 
326       loc1 = loc2;
327       loc1_index = i;
328     }
329     catch (runtime_error const&) {
330       //This locale is not supported.
331       continue;
332     }
333   }
334 #  endif
335 }
336 
337 #endif
338