47#if _RWSTD_PATH_SEP == '/'
55#define RELPATH "etc" SLASH "nls"
56#define TESTS_ETC_PATH "tests" SLASH "etc"
59#define LOCALE_ROOT "RWSTD_LOCALE_ROOT"
62#define LC_COLLATE_SRC "LC_COLLATE.src"
63#define LC_COLLATE_CM "LC_COLLATE.cm"
64#define TEST_LOCALE_NAME "test.locale"
74 const int ret = std::strcoll(
s1,
s2);
75 return ret ? ret > 0 ? 1 : -1 : 0;
78std::size_t
c_xfrm (
char* to,
const char* from, std::size_t
size)
81 if (0 == to && 0 ==
size) {
89 std::size_t
n = std::strxfrm (to, from,
size);
99 return std::strlen (
s1);
102const char*
narrow (
char* dst,
const char* src)
104 if (src == dst || !src || !dst)
107 std::memcpy (dst, src, std::strlen (src) + 1);
111const char*
widen (
char* dst,
const char* src)
113 if (src == dst || !src || !dst)
116 std::memcpy (dst, src, std::strlen (src) + 1);
120#ifndef _RWSTD_NO_WCHAR_T
124 const int ret = std::wcscoll(
s1,
s2);
125 return ret ? ret > 0 ? 1 : -1 : 0;
128std::size_t
c_xfrm (
wchar_t* to,
const wchar_t* from, std::size_t
size)
130#if !defined (_MSC_VER) || _MSC_VER > 1200
132 wchar_t safety_buf [8];
133 if (0 == to && 0 ==
size) {
141 std::size_t
n = std::wcsxfrm (to, from,
size);
144 n = std::wcslen (to);
151 std::size_t
n = std::wcsxfrm (to, from,
size);
153 n = std::wcslen (to);
160 std::size_t
n = std::wcslen (from);
164 std::wcscpy (
tmp, from);
166 std::wcsxfrm (
tmp, from,
sizeof tmp /
sizeof *
tmp);
168 n = std::wcslen (
tmp);
177 return std::wcslen (
s1);
180const wchar_t*
widen (
wchar_t* dst,
const char* src)
182 static wchar_t buf [4096];
190 std::size_t
len = std::strlen (src);
194 len = std::mbstowcs (dst, src,
sizeof buf /
sizeof *
buf);
196 if (std::size_t (-1) ==
len)
202const char*
narrow (
char* dst,
const wchar_t* src)
204 static char buf [4096];
212 std::size_t
len = std::wcslen (src);
216 len = std::wcstombs (dst, src,
sizeof buf /
sizeof *
buf);
218 if (std::size_t (-1) ==
len)
228template <
class charT>
237 for (std::size_t
i = 0;
i !=
size - 1; ++
i)
238 str [
i] =
' ' + std::rand () % (
'~' -
' ');
245template <
class charT>
255 int nfail [3] = { 0 };
257 rw_info (0, __FILE__, __LINE__,
258 "libc std::collate<%s>::transform ()", charTname);
260 rw_info (0, __FILE__, __LINE__,
261 "libc std::collate<%s>::compare ()", charTname);
263 rw_info (0, __FILE__, __LINE__,
264 "std::collate<%s>::hash ()", charTname);
267 *locname; locname += std::strlen (locname) + 1) {
278 loc = std::locale (locname);
282 "std::locale(\"%s\") unexpectedly threw "
283 "an exception", locname);
287 const std::collate<charT> &co =
289 co._C_opts |= co._C_use_libc;
290 co._C_opts &= ~co._C_use_libstd;
295 for (
int loop_cntrl = 0; loop_cntrl < 10; loop_cntrl++) {
303 gen_str (str1,
sizeof str1 /
sizeof *str1);
304 gen_str (str2,
sizeof str2 /
sizeof *str2);
308 const std::basic_string <charT, std::char_traits<charT>,
309 std::allocator<charT> >
out =
310 co.transform (str1, str1 +
sizeof str1 /
sizeof *str1 - 1);
320 std::basic_string <charT, std::char_traits<charT>,
321 std::allocator<charT> > c_out;
340 "%d. collate<%s>::transform(%s, ...) "
341 "== %{S}, got %{S} in locale(\"%s\")",
342 loop_cntrl, charTname, str1,
343 &c_out, &
out, locname);
347 int ret1 = co.compare (str1, str1 +
sizeof str1 /
sizeof *str1,
348 str2, str2 +
sizeof str2 /
sizeof *str2);
357 "%d. collate<%s>::compare(%s, ..., %s, ...) "
358 "== %d, got %d in locale(\"%s\")",
359 loop_cntrl, charTname, str1,
360 str2, ret2, ret1, locname);
368 const long hashNum1 =
369 co.hash (str1, str1 +
sizeof str1 /
sizeof *str1);
371 const long hashNum2 =
372 co.hash (str1, str1 +
sizeof str1 /
sizeof *str1);
374 if (hashNum1 != hashNum2) {
377 "%d. collate<%s>::hash(%s, ...) == %d, "
378 "got %d in locale(\"%s\")",
379 loop_cntrl, charTname, str1,
380 hashNum1, hashNum2, locname);
388 "locale(\"%s\") threw an exception", locname);
392 rw_assert (0 == nfail [0], __FILE__, __LINE__,
393 "collate<%s>::transform () failed %d times",
394 charTname, nfail [0]);
396 rw_assert (0 == nfail [1], __FILE__, __LINE__,
397 "collate<%s>::compare () failed %d times",
398 charTname, nfail [1]);
400 rw_assert (0 == nfail [2], __FILE__, __LINE__,
401 "collate<%s>::hash () failed %d times",
402 charTname, nfail [2]);
415 std::strcat (lc_collate_src_path,
SLASH);
418 std::FILE *fout = std::fopen (lc_collate_src_path,
"w");
420 const char lc_collate_file[] = {
422 "script <ALL_FORWARD>\n"
423 "collating-element <er> from \"<e><r>\"\n"
424 "collating-element <ic> from \"ic\"\n"
425 "collating-symbol <LETTER>\n"
426 "collating-symbol <COLLATING_ELEMENT>\n"
427 "collating-symbol <DIGIT>\n"
429 "order_start forward;backward;forward,position\n"
431 "<COLLATING_ELEMENT>\n"
434 "<a> <a> <LETTER> IGNORE\n"
435 "<b> <b> <LETTER> IGNORE\n"
438 "<c> <c> <LETTER> <c>\n"
441 "<d> \"<d><a>\" <LETTER> IGNORE\n"
444 "<e> \\d139 <LETTER> IGNORE\n"
447 "<f> \\36 <LETTER> IGNORE\n"
450 "<g> \\x3A <LETTER> IGNORE\n"
452 "<zero> <zero> <DIGIT> IGNORE\n"
453 "<one> <one> <DIGIT> <zero>\n"
454 "<two> <two> <DIGIT> IGNORE\n"
455 "<three> <three> <DIGIT> IGNORE\n"
456 "<er> <a> <COLLATING_ELEMENT> IGNORE\n"
459 "<ic> <c> <LETTER> <c>\n"
460 "UNDEFINED IGNORE IGNORE IGNORE\n"
465 "order_start <ALL_FORWARD>;forward;forward;forward\n"
466 "<h>\n<i>\n<j>\n<k>\n"
471 "reorder-after <g>\n"
472 "<h>\n<i>\n<j>\n<k>\n"
475 "reorder-after <b>\n"
476 "<a> <a> <LETTER> IGNORE\n"
482 std::fputs (lc_collate_file, fout);
490 std::strcat (lc_collate_cm_path,
SLASH);
493 fout = std::fopen (lc_collate_cm_path,
"w");
506template <
class charT>
510 rw_info (0, __FILE__, __LINE__,
511 "libstd std::collate<%s>::transform () "
512 "collate test database", charTname);
513 rw_info (0, __FILE__, __LINE__,
514 "libstd std::collate<%s>::compare () collate test "
515 "database", charTname);
516 rw_info (0, __FILE__, __LINE__,
517 "libstd std::collate<%s>::hash () collate test "
518 "database", charTname);
520 const char*
const locname = make_test_locale ();
526 loc = std::locale (locname);
532 "std::locale(\"%s\") unexpectedly threw "
534 locname,
var ?
var :
"(null)");
538 const std::collate<charT> &co =
540 co._C_opts |= co._C_use_libstd;
541 co._C_opts &= ~co._C_use_libc;
549#define TEST(ch, w0, w1, w2, w3, w3_is_fp) \
550 test_weight_val (charTname, co, charT (ch), w0, w1, w2, w3, w3_is_fp)
592 "unable to create a locale database");
599template <
class charT>
601test_hash (
const char* charTname,
const std::collate<charT>& co,
602 const char* str1,
const char* str2)
608 const charT*
const wstr =
widen (wstrbuf, str1);
609 const charT*
const wstr2 =
widen (wstrbuf2, str2);
611 long hashNum1 = co.hash (wstr, wstr +
c_strlen (wstr));
612 long hashNum2 = co.hash (wstr2, wstr2 +
c_strlen (wstr2));
614 if (hashNum1 != hashNum2) {
616 "collate<%s>::hash(%s, ...) returned %d and\n "
617 "collate<%s>::hash(%s, ...) returned %d",
619 hashNum1, charTname, str2, hashNum2);
625template <
class charT>
628 const char* str1,
const char* str2,
635 const charT*
const wstr =
widen (wstrbuf, str1);
636 const charT*
const wstr2 =
widen (wstrbuf2, str2);
638 int ret = co.compare (wstr, wstr +
c_strlen (wstr),
640 if (ret != expected_val)
642 "libstd std::collate<%s>::compare"
643 "(%s, ..., %s, ...) == %d, got %d",
644 charTname, str1, str2, expected_val, ret);
649template <
class charT>
652 charT ch,
int w1a,
int w1b,
int w2,
int w3,
bool w3_is_fp)
656 typedef std::char_traits<charT>
Traits;
657 typedef std::allocator<charT>
Alloc;
658 typedef std::basic_string <charT, Traits, Alloc>
String;
663 if (
sizeof (
charT) ==
sizeof (
char)) {
664 for (
int i = 0;
i < 3; ++
i) {
665 for (
int k = 0;
k < 2; ++
k) {
667 while (
w [
i][
k] > _RWSTD_CHAR_MAX) {
668 expected +=
charT (_RWSTD_CHAR_MAX);
669 w [
i][
k] -= _RWSTD_CHAR_MAX;
673 else if (
i == 2 &&
k == 0 && w3_is_fp)
674 expected +=
charT (_RWSTD_CHAR_MAX);
678 expected +=
charT (1);
682 for (
int i = 0;
i < 3; ++
i) {
683 for (
int k = 0;
k < 2; ++
k) {
687 else if (
i == 2 &&
k == 0 && w3_is_fp)
688 expected +=
charT (_RWSTD_WCHAR_MAX);
691 expected +=
charT (1);
696 const String actual = co.transform (&ch, &ch + 1);
699 rw_assert (expected != actual, __FILE__, __LINE__,
700 "collate<%s>::transform (\"%c\", ...) == %{S}, "
701 "got %{S}", charTname, ch, &expected, &actual);
706template <
class charT>
710 rw_info (0, __FILE__, __LINE__,
711 "libstd std::collate<%s>::transform () sorting "
712 "file test", charTname);
714 rw_info (0, __FILE__, __LINE__,
715 "libstd std::collate<%s>::compare () sorting "
716 "file test", charTname);
724 static const char*
const locales[][3] = {
731 {
"cs_CZ",
"ISO-8859-2",
"collate.cs_CZ.in" },
732 {
"da_DK",
"ISO-8859-1",
"collate.da_DK.in" },
733 {
"en_US",
"ISO-8859-1",
"collate.en_US.in" },
734 {
"hr_HR",
"ISO-8859-2",
"collate.hr_HR.in" },
735 {
"sv_SE",
"ISO-8859-1",
"collate.sv_SE.in" },
736 {
"th_TH",
"TIS-620",
"collate.th_TH.in" }
741 typedef std::char_traits<charT>
Traits;
743 typedef std::basic_string<charT, Traits, Allocator>
String;
747 const char*
const locname =
756 loc = std::locale (locname);
762 "std::locale(\"%s\") unexpectedly threw "
764 locname,
var ?
var :
"(null)");
768 const std::collate<charT> &co =
771 co._C_opts |= co._C_use_libstd;
772 co._C_opts &= ~co._C_use_libc;
774 typedef std::codecvt<charT, char, std::mbstate_t>
CodeCvt;
778 cvt._C_opts |=
cvt._C_use_libstd;
779 cvt._C_opts &=
~cvt._C_use_libc;
788#define TOPDIR "TOPDIR"
790 const char* in_path = std::getenv (
TOPDIR);
791 if (!in_path || !*in_path) {
792 std::fprintf (
stderr,
"TOPDIR not defined or empty");
797 std::string
path (in_path);
801 std::FILE*
const f = std::fopen (
path.c_str (),
"r");
804 "file \"%s\" could not be opened",
path.c_str ());
812 if (0 != std::fgets (next_line,
bufsiz,
f)) {
814 std::size_t line_len = std::strlen (next_line);
817 next_line [--line_len] =
'\0';
822 const char* from_next;
825 static std::mbstate_t initial;
826 std::mbstate_t mbs = initial;
828 const std::codecvt_base::result
res =
830 next_line, next_line + line_len + 1,
832 to, to +
sizeof to /
sizeof *to,
839 else if (
cvt.noconv ==
res) {
864 for (idx2 =
j - 1; idx2 >= idx; --idx2) {
866 const std::size_t idx1 = idx2 - 1;
868 if (co.compare (
in [idx1].c_str (),
869 in [idx1].c_str () +
in [idx1].size (),
871 in [idx2].c_str () +
in [idx2].size ())
873 in [idx1].swap (
in [idx2]);
877 }
while (++idx <
j && flipped);
882 std::size_t nfail = 0;
884 for (std::size_t
k = 0;
k <
j; ++
k) {
891 "%{S} != %{S} at line %u of %s",
899 "collate<%s>::compare() failed %d times",
908template <
class charT>
913 rw_info (0, __FILE__, __LINE__,
914 "std::collate<%s>::hash () -- effectiveness", charTname);
918 std::locale
loc (
"C");
919 const std::collate<charT> &co =
929 static const std::size_t
N = 100;
930 long hashed [
N] = { 0 };
933 for (
k = 1;
k !=
N && next; ++
k) {
938 hashed [
k] = co.hash (
s,
s + std::char_traits<charT>::length(
s));
942 std::sort (hashed, hashed +
k);
943 k = std::unique (hashed, hashed +
k) - hashed;
948 if (
N -
k >
N /100) {
951 "collate<%s>::do_hash (const char_type*, "
952 "const char_type*); "
953 "probability of collision %f",
954 charTname,
double (
N -
k) /
N);
958 "collate<%s>::do_hash () failed %d times", charTname,
966template <
class charT>
970 rw_info (0, __FILE__, __LINE__,
971 "std::collate<%s>::compare() with embedded NULs", charTname);
984 *locname && !
fail; locname += std::strlen (locname) + 1, ++
i) {
989 loc = std::locale (locname);
995 const std::size_t buflen =
sizeof buf_1 /
sizeof *buf_1 - 1;
997 gen_str (buf_1,
sizeof buf_1 /
sizeof *buf_1);
998 std::memcpy (buf_2, buf_1,
sizeof buf_2);
1003 const std::size_t inx_2 = std::rand () % (buflen - 1);
1004 const std::size_t inx_1 =
1005 inx_2 + 1 + std::rand () % (buflen - inx_2 - 1);
1007 buf_2 [inx_2] =
charT ();
1009 typedef std::collate<charT> CollateT;
1011 const CollateT &col = std::use_facet<CollateT>(
loc);
1013 int cmp = col.compare (buf_1, buf_1 + buflen, buf_2, buf_2 + buflen);
1016 typedef typename CollateT::string_type StringT;
1018 const StringT str_1 (buf_1, buflen);
1019 const StringT str_2 (buf_2, buflen);
1024 "collate<%s>::compare(%{S}, ..., %{S}, ...) "
1025 "!= 0, got 0 in locale(\"%s\")", charTname,
1026 &str_1, &str_2, locname);
1033 buf_1 [inx_1] =
charT ();
1034 buf_1 [inx_2] =
charT ();
1036 cmp = col.compare (buf_1, buf_1 + buflen, buf_2, buf_2 + buflen);
1039 typedef typename CollateT::string_type StringT;
1041 const StringT str_1 (buf_1, buflen);
1042 const StringT str_2 (buf_2, buflen);
1047 "collate<%s>::compare(%{S}, ..., %{S}, ...) "
1048 "!= 0, got 0 in locale(\"%s\")", charTname,
1049 &str_1, &str_2, locname);
1056template <
class charT>
1060 check_libstd_test_locale<charT> (charTname);
1061 check_libstd<charT> (charTname);
1062 check_libc<charT> (charTname);
1063 check_NUL<charT> (charTname);
1064 check_hash_eff<charT> (charTname);
1068#if _RWSTD_PATH_SEP == '/'
1069# define RM_RF "rm -rf "
1071# define RM_RF "rmdir /Q /S "
1095 do_test<char> (
"char");
1097#ifndef _RWSTD_NO_WCHAR_T
1099 do_test<wchar_t> (
"wchar_t");
1113 return rw_test (argc, argv, __FILE__,
1114 "[lib.category.collate]",
1115 "22.2.4 The collate category",
void check_libstd_test_locale(const char *charTname)
void check_libc(const char *charTname)
void test_string(const char *charTname, const std::collate< charT > &co, const char *str1, const char *str2, int expected_val)
const char * widen(char *dst, const char *src)
void test_weight_val(const char *charTname, const std::collate< charT > &co, charT ch, int w1a, int w1b, int w2, int w3, bool w3_is_fp)
#define TEST(ch, w0, w1, w2, w3, w3_is_fp)
void check_NUL(const char *charTname)
const char * narrow(char *dst, const char *src)
std::size_t c_strlen(const char *s1)
int c_strcoll(const char *s1, const char *s2)
void check_hash_eff(const char *charTname)
std::size_t c_xfrm(char *to, const char *from, std::size_t size)
void gen_str(charT *str, std::size_t size)
void test_hash(const char *charTname, const std::collate< charT > &co, const char *str1, const char *str2)
void check_libstd(const char *charTname)
void do_test(int line, const char *src, std::size_t resoff, ForwardIterator dummy_iter, const T *, const char *predname)
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define _STD_USE_FACET(type, arg)
#define _RWSTD_ASSERT(ignore)
const struct @19 locales[]
_TEST_EXPORT int rw_test(int argc, char *argv[], const char *filename, const char *clause, const char *comment, int(*testfun)(int, char **), const char *optspec,...)
_TEST_EXPORT int rw_info(int, const char *, int, const char *,...)
_TEST_EXPORT int rw_assert(int, const char *, int, const char *,...)
_TEST_EXPORT int rw_putenv(const char *, int=-1)
_TEST_EXPORT void pcs_write(void *, const char *)
_TEST_EXPORT char * rw_locales(int=_UNUSED_CAT, const char *=0, bool=true)
_TEST_EXPORT const char * rw_localedef(const char *, const char *, const char *, const char *)
_TEST_EXPORT int rw_system(const char *,...)