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)
9using namespace std;
10#  endif
11
12static 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
24CPPUNIT_TEST_SUITE_REGISTRATION(LocaleTest);
25
26//
27// tests implementation
28//
29typedef void (LocaleTest::*_Test) (const locale&);
30static 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
51void 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
145void 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
155void 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 */
166static locale global_loc;
167static locale other_loc("");
168
169#  if !defined (STLPORT) || !defined (_STLP_NO_MEMBER_TEMPLATES)
170void 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
224void LocaleTest::default_locale()
225{
226  locale loc( "" );
227}
228
229class dummy_facet : public locale::facet {
230public:
231  static locale::id id;
232};
233
234locale::id dummy_facet::id;
235
236void 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