| /************************************************************************ |
| * |
| * 0.char.cpp - test exercising the UserTraits helper class template |
| * and the rw_widen() set of overloaded functions |
| * |
| * $Id$ |
| * |
| ************************************************************************ |
| * |
| * Copyright 2006 The Apache Software Foundation or its licensors, |
| * as applicable. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| **************************************************************************/ |
| |
| #include <rw_char.h> |
| #include <rw_printf.h> |
| #include <driver.h> |
| |
| #include <stdlib.h> // for free() |
| #include <string.h> // for memset(), size_t, strlen() |
| |
| /***********************************************************************/ |
| |
| static void |
| test_user_traits_char () |
| { |
| ////////////////////////////////////////////////////////////////// |
| rw_info (0, 0, 0, "template class UserTraits<char>"); |
| |
| rw_warn (0, 0, 0, "UserTraits<char> not exercised"); |
| } |
| |
| /***********************************************************************/ |
| |
| static void |
| test_user_traits_wchar () |
| { |
| ////////////////////////////////////////////////////////////////// |
| rw_info (0, 0, 0, "template class UserTraits<wchar_t>"); |
| |
| rw_warn (0, 0, 0, "UserTraits<wchar_t> not exercised"); |
| } |
| |
| /***********************************************************************/ |
| |
| static void |
| test_user_traits_user_char () |
| { |
| ////////////////////////////////////////////////////////////////// |
| rw_info (0, 0, 0, "template class UserTraits<UserChar>"); |
| |
| const UserChar src [] = { |
| { 1, 2 }, { 0, 0 }, { 3, 4 }, { 5, 6 }, { 7, 8 }, { 0, 0 } |
| }; |
| |
| const size_t nsrc = sizeof src / sizeof *src; |
| |
| UserChar dst [nsrc]; |
| |
| typedef UserTraits<UserChar> Traits; |
| typedef UserTraits<UserChar>::MemFun MemFun; |
| |
| ////////////////////////////////////////////////////////////////// |
| Traits::n_calls_ [MemFun::assign] = 0; |
| |
| Traits::assign (dst [0], src [0]); |
| rw_assert (dst [0].f == src [0].f && dst [0].c == src [0].c, 0, __LINE__, |
| "UserTraits::assign(char_type&, const char_type&)"); |
| |
| rw_assert (1 == Traits::n_calls_ [MemFun::assign], 0, __LINE__, |
| "UserTraits::assign(char_type&, const char_type&)"); |
| |
| ////////////////////////////////////////////////////////////////// |
| Traits::n_calls_ [MemFun::eq] = 0; |
| |
| bool eq = Traits::eq (dst [0], src [0]); |
| rw_assert (eq, 0, __LINE__, |
| "UserTraits::eq(const char_type&, const char_type&)"); |
| |
| rw_assert (1 == Traits::n_calls_ [MemFun::eq], 0, __LINE__, |
| "UserTraits::eq(const char_type&, const char_type&)"); |
| |
| ////////////////////////////////////////////////////////////////// |
| Traits::n_calls_ [MemFun::lt] = 0; |
| |
| bool lt = Traits::lt (dst [0], src [0]); |
| rw_assert (!lt, 0, __LINE__, |
| "UserTraits::lt(const char_type&, const char_type&)"); |
| |
| rw_assert (1 == Traits::n_calls_ [MemFun::lt], 0, __LINE__, |
| "UserTraits::lt(const char_type&, const char_type&)"); |
| |
| lt = Traits::lt (src [0], src [1]); |
| rw_assert (eq, 0, __LINE__, |
| "UserTraits::lt(const char_type&, const char_type&)"); |
| |
| rw_assert (2 == Traits::n_calls_ [MemFun::lt], 0, __LINE__, |
| "UserTraits::lt(const char_type&, const char_type&)"); |
| |
| ////////////////////////////////////////////////////////////////// |
| Traits::n_calls_ [MemFun::compare] = 0; |
| |
| int compare = Traits::compare (src, src, nsrc); |
| rw_assert (0 == compare, 0, __LINE__, |
| "UserTraits::compare(const char_type*, const char_type*) " |
| "== 0, got %d", compare); |
| |
| rw_assert (1 == Traits::n_calls_ [MemFun::compare], 0, __LINE__, |
| "UserTraits::compare(const char_type*, const char_type*)"); |
| |
| compare = Traits::compare (src, src + 1, nsrc - 1); |
| rw_assert (+1 == compare, 0, __LINE__, |
| "UserTraits::compare(const char_type*, const char_type*) " |
| "== +1, got %d", compare); |
| |
| rw_assert (2 == Traits::n_calls_ [MemFun::compare], 0, __LINE__, |
| "UserTraits::compare(const char_type*, const char_type*)"); |
| |
| compare = Traits::compare (src + 1, src, nsrc - 1); |
| rw_assert (-1 == compare, 0, __LINE__, |
| "UserTraits::compare(const char_type*, const char_type*) " |
| "== -1, got %d", compare); |
| |
| rw_assert (3 == Traits::n_calls_ [MemFun::compare], 0, __LINE__, |
| "UserTraits::compare(const char_type*, const char_type*)"); |
| |
| ////////////////////////////////////////////////////////////////// |
| Traits::n_calls_ [MemFun::length] = 0; |
| |
| size_t length = Traits::length (src); |
| rw_assert (1 == length, 0, __LINE__, |
| "UserTraits::length(const char_type*)"); |
| |
| rw_assert (1 == Traits::n_calls_ [MemFun::length], 0, __LINE__, |
| "UserTraits::length(const char_type*)"); |
| |
| length = Traits::length (src + 1); |
| rw_assert (0 == length, 0, __LINE__, |
| "UserTraits::length(const char_type*)"); |
| |
| rw_assert (2 == Traits::n_calls_ [MemFun::length], 0, __LINE__, |
| "UserTraits::length(const char_type*)"); |
| |
| length = Traits::length (src + 2); |
| rw_assert (nsrc - 3 == length, 0, __LINE__, |
| "UserTraits::length(const char_type*) == %zu, got %zu", |
| nsrc - 3, length); |
| |
| rw_assert (3 == Traits::n_calls_ [MemFun::length], 0, __LINE__, |
| "UserTraits::length(const char_type*)"); |
| |
| ////////////////////////////////////////////////////////////////// |
| Traits::n_calls_ [MemFun::find] = 0; |
| |
| const UserChar *find = Traits::find (src, nsrc, src [0]); |
| rw_assert (src == find, 0, __LINE__, |
| "UserTraits::find(const char_type*, size_t, const char_type&)"); |
| |
| rw_assert (1 == Traits::n_calls_ [MemFun::find], 0, __LINE__, |
| "UserTraits::find(const char_type*, size_t, const char_type&)"); |
| |
| find = Traits::find (src, nsrc, src [1]); |
| rw_assert (src + 1 == find, 0, __LINE__, |
| "UserTraits::find(const char_type*, size_t, const char_type&)"); |
| |
| rw_assert (2 == Traits::n_calls_ [MemFun::find], 0, __LINE__, |
| "UserTraits::find(const char_type*, size_t, const char_type&)"); |
| |
| find = Traits::find (src, nsrc, src [2]); |
| rw_assert (src + 2 == find, 0, __LINE__, |
| "UserTraits::find(const char_type*, size_t, const char_type&)"); |
| |
| rw_assert (3 == Traits::n_calls_ [MemFun::find], 0, __LINE__, |
| "UserTraits::find(const char_type*, size_t, const char_type&)"); |
| |
| find = Traits::find (src + 1, nsrc - 1, src [0]); |
| rw_assert (0 == find, 0, __LINE__, |
| "UserTraits::find(const char_type*, size_t, const char_type&)"); |
| |
| rw_assert (4 == Traits::n_calls_ [MemFun::find], 0, __LINE__, |
| "UserTraits::find(const char_type*, size_t, const char_type&)"); |
| |
| ////////////////////////////////////////////////////////////////// |
| Traits::n_calls_ [MemFun::copy] = 0; |
| |
| const UserChar uc = { -1, 1 }; |
| |
| memset (dst, 0, sizeof dst); |
| dst [0] = uc; |
| |
| const UserChar *copy = Traits::copy (dst, src, 0); |
| rw_assert (dst == copy, 0, __LINE__, |
| "UserTraits::copy(char_type*, const char_type*, size_t)"); |
| |
| rw_assert (Traits::eq (dst [0], uc), 0, __LINE__, |
| "UserTraits::copy(char_type*, const char_type*, size_t)"); |
| |
| rw_assert (1 == Traits::n_calls_ [MemFun::copy], 0, __LINE__, |
| "UserTraits::copy(char_type*, const char_type*, size_t)"); |
| |
| memset (dst, 0, sizeof dst); |
| dst [1] = uc; |
| |
| copy = Traits::copy (dst, src, 1); |
| |
| rw_assert (dst == copy, 0, __LINE__, |
| "UserTraits::copy(char_type*, const char_type*, size_t)"); |
| |
| rw_assert (Traits::eq (dst [0], src [0]) && Traits::eq (dst [1], uc), |
| 0, __LINE__, |
| "UserTraits::copy(char_type*, const char_type*, size_t)"); |
| |
| rw_assert (2 == Traits::n_calls_ [MemFun::copy], 0, __LINE__, |
| "UserTraits::copy(char_type*, const char_type*, size_t)"); |
| |
| ////////////////////////////////////////////////////////////////// |
| Traits::n_calls_ [MemFun::move] = 0; |
| |
| memset (dst, 0, sizeof dst); |
| dst [0] = uc; |
| |
| const UserChar *move = Traits::move (dst, src, 0); |
| rw_assert (dst == move, 0, __LINE__, |
| "UserTraits::move(char_type*, const char_type*, size_t)"); |
| |
| rw_assert (Traits::eq (dst [0], uc), 0, __LINE__, |
| "UserTraits::move(char_type*, const char_type*, size_t)"); |
| |
| rw_assert (1 == Traits::n_calls_ [MemFun::move], 0, __LINE__, |
| "UserTraits::move(char_type*, const char_type*, size_t)"); |
| |
| memset (dst, 0, sizeof dst); |
| dst [1] = uc; |
| |
| move = Traits::move (dst, src, 1); |
| |
| rw_assert (dst == move, 0, __LINE__, |
| "UserTraits::move(char_type*, const char_type*, size_t)"); |
| |
| rw_assert (Traits::eq (dst [0], src [0]) && Traits::eq (dst [1], uc), |
| 0, __LINE__, |
| "UserTraits::move(char_type*, const char_type*, size_t)"); |
| |
| rw_assert (2 == Traits::n_calls_ [MemFun::move], 0, __LINE__, |
| "UserTraits::move(char_type*, const char_type*, size_t)"); |
| |
| |
| memcpy (dst, src, sizeof dst); |
| move = Traits::move (dst, dst + 1, 1); |
| |
| rw_assert (dst == move, 0, __LINE__, |
| "UserTraits::move(char_type*, const char_type*, size_t)"); |
| |
| rw_assert ( Traits::eq (dst [0], src [1]) |
| && Traits::eq (dst [1], src [1]), |
| 0, __LINE__, |
| "UserTraits::move(char_type*, const char_type*, size_t)"); |
| |
| rw_assert (3 == Traits::n_calls_ [MemFun::move], 0, __LINE__, |
| "UserTraits::move(char_type*, const char_type*, size_t)"); |
| |
| memcpy (dst, src, sizeof dst); |
| move = Traits::move (dst, dst + 1, 2); |
| |
| rw_assert (dst == move, 0, __LINE__, |
| "UserTraits::move(char_type*, const char_type*, size_t)"); |
| |
| rw_assert ( Traits::eq (dst [0], src [1]) |
| && Traits::eq (dst [1], src [2]) |
| && Traits::eq (dst [2], src [2]), |
| 0, __LINE__, |
| "UserTraits::move(char_type*, const char_type*, size_t)"); |
| |
| rw_assert (4 == Traits::n_calls_ [MemFun::move], 0, __LINE__, |
| "UserTraits::move(char_type*, const char_type*, size_t)"); |
| |
| memcpy (dst, src, sizeof dst); |
| move = Traits::move (dst + 1, dst, 1); |
| |
| rw_assert (dst + 1 == move, 0, __LINE__, |
| "UserTraits::move(char_type*, const char_type*, size_t)"); |
| |
| rw_assert ( Traits::eq (dst [0], src [0]) |
| && Traits::eq (dst [1], src [0]) |
| && Traits::eq (dst [2], src [2]), |
| 0, __LINE__, |
| "UserTraits::move(char_type*, const char_type*, size_t)"); |
| |
| rw_assert (5 == Traits::n_calls_ [MemFun::move], 0, __LINE__, |
| "UserTraits::move(char_type*, const char_type*, size_t)"); |
| |
| memcpy (dst, src, sizeof dst); |
| move = Traits::move (dst + 1, dst, 2); |
| |
| rw_assert (dst + 1 == move, 0, __LINE__, |
| "UserTraits::move(char_type*, const char_type*, size_t)"); |
| |
| rw_assert ( Traits::eq (dst [0], src [0]) |
| && Traits::eq (dst [1], src [0]) |
| && Traits::eq (dst [2], src [1]) |
| && Traits::eq (dst [3], src [3]), |
| 0, __LINE__, |
| "UserTraits::move(char_type*, const char_type*, size_t)"); |
| |
| rw_assert (6 == Traits::n_calls_ [MemFun::move], 0, __LINE__, |
| "UserTraits::move(char_type*, const char_type*, size_t)"); |
| |
| ////////////////////////////////////////////////////////////////// |
| Traits::n_calls_ [MemFun::assign] = 0; |
| |
| memset (dst, 0, sizeof dst); |
| dst [0] = uc; |
| |
| const UserChar *assign = Traits::assign (dst, 0, src [0]); |
| |
| rw_assert (dst == assign, 0, __LINE__, |
| "UserTraits::assign(char_type*, size_t, const char_type&)"); |
| |
| rw_assert (Traits::eq (dst [0], uc), 0, __LINE__, |
| "UserTraits::assign(char_type*, size_t, const char_type&)"); |
| |
| rw_assert (1 == Traits::n_calls_ [MemFun::assign2], 0, __LINE__, |
| "UserTraits::assign(char_type*, size_t, const char_type&)"); |
| |
| memset (dst, 0, sizeof dst); |
| dst [1] = uc; |
| |
| assign = Traits::assign (dst, 1, src [0]); |
| rw_assert (dst == assign, 0, __LINE__, |
| "UserTraits::assign(char_type*, size_t, const char_type&)"); |
| |
| rw_assert (Traits::eq (dst [0], src [0]) && Traits::eq (dst [1], uc), |
| 0, __LINE__, |
| "UserTraits::assign(char_type*, size_t, const char_type&)"); |
| |
| rw_assert (2 == Traits::n_calls_ [MemFun::assign2], 0, __LINE__, |
| "UserTraits::assign(char_type*, size_t, const char_type&)"); |
| |
| memset (dst, 0, sizeof dst); |
| dst [2] = uc; |
| |
| assign = Traits::assign (dst, 2, src [0]); |
| rw_assert (dst == assign, 0, __LINE__, |
| "UserTraits::assign(char_type*, size_t, const char_type&)"); |
| |
| rw_assert ( Traits::eq (dst [0], src [0]) |
| && Traits::eq (dst [1], src [0]) |
| && Traits::eq (dst [2], uc), |
| 0, __LINE__, |
| "UserTraits::assign(char_type*, size_t, const char_type&)"); |
| |
| rw_assert (3 == Traits::n_calls_ [MemFun::assign2], 0, __LINE__, |
| "UserTraits::assign(char_type*, size_t, const char_type&)"); |
| |
| ////////////////////////////////////////////////////////////////// |
| rw_warn (0, 0, 0, "UserTraits<UserChar>::not_eof() not exercised"); |
| rw_warn (0, 0, 0, "UserTraits<UserChar>::eof() not exercised"); |
| rw_warn (0, 0, 0, "UserTraits<UserChar>::to_char_type() not exercised"); |
| rw_warn (0, 0, 0, "UserTraits<UserChar>::to_int_type() not exercised"); |
| rw_warn (0, 0, 0, "UserTraits<UserChar>::eq_int_type() not exercised"); |
| } |
| |
| /***********************************************************************/ |
| |
| static void |
| test_rw_widen () |
| { |
| ////////////////////////////////////////////////////////////////// |
| rw_info (0, 0, 0, "rw_widen(char*, const char*, size_t)"); |
| |
| static const char src [] = "abcdefgh"; |
| const size_t nsrc = sizeof src - 1; |
| static const char null [nsrc + 1] = ""; |
| char cdst [nsrc + 1]; |
| |
| for (size_t i = 0; i != nsrc + 1; ++i) { |
| |
| memset (cdst, 0, sizeof cdst); |
| |
| const char* const ret = i < nsrc ? |
| rw_widen (cdst, src, i) : rw_widen (cdst, src); |
| |
| rw_assert (cdst == ret, 0, __LINE__, |
| "rw_widen(char*, %{#s}%{?}, %zu%{;})", |
| src, i < nsrc); |
| |
| rw_assert (0 == memcmp (cdst, src, i) && '\0' == cdst [i], |
| 0, __LINE__, |
| "rw_widen(char*, %{#s}%{?}, %zu%{;}) == %{#*s}, got %{#*s}", |
| src, i < nsrc, i, int (i), src, int (i + 1), cdst); |
| } |
| |
| memset (cdst, '@', sizeof cdst); |
| rw_widen (cdst, 0, sizeof cdst); |
| |
| rw_assert (0 == memcmp (cdst, null, sizeof cdst), 0, __LINE__, |
| "rw_widen(char*, %{#s}, %zu) == %{#*s}, got %{#*s}", |
| 0, sizeof cdst, int (sizeof cdst), null, |
| int (sizeof cdst), cdst); |
| |
| ////////////////////////////////////////////////////////////////// |
| rw_info (0, 0, 0, "rw_widen(wchar_t*, const char*, size_t)"); |
| |
| #ifndef _RWSTD_NO_WCHAR_T |
| |
| static const wchar_t wsrc [] = L"abcdefgh"; |
| static const wchar_t wnull [nsrc + 1] = L""; |
| wchar_t wdst [nsrc + 1]; |
| |
| for (size_t i = 0; i != nsrc + 1; ++i) { |
| |
| memset (wdst, 0, sizeof wdst); |
| |
| const wchar_t* const ret = i < nsrc ? |
| rw_widen (wdst, src, i) : rw_widen (wdst, src); |
| |
| rw_assert (wdst == ret, 0, __LINE__, |
| "rw_widen(wchar_t*, %{#s}%{?}, %zu%{;})", |
| src, i < nsrc, i); |
| |
| rw_assert ( 0 == memcmp (wdst, wsrc, i * sizeof *wdst) |
| && '\0' == wdst [i], |
| 0, __LINE__, |
| "rw_widen(wchar_t*, %{#s}%{?}, %zu%{;}) == L%{#*ls}, " |
| "got L%{#*ls}", |
| src, i < nsrc, i, int (i), wsrc, int (i + 1), wdst); |
| } |
| |
| memset (wdst, '@', sizeof wdst); |
| rw_widen (wdst, 0, sizeof wdst / sizeof *wdst); |
| |
| rw_assert (0 == memcmp (wdst, wnull, sizeof wdst), 0, __LINE__, |
| "rw_widen(wchar_t*, %{#s}, %zu) == %{#*s}, got L%{#*ls}", |
| 0, sizeof wdst, int (sizeof wdst / sizeof *wdst), wnull, |
| int (sizeof wdst / sizeof *wdst), wdst); |
| |
| #else // if defined (_RWSTD_NO_WCHAR_T) |
| |
| rw_note (0, 0, 0, "_RWSTD_NO_WCHAR_T #defined, wchar_t test disabled"); |
| |
| #endif // _RWSTD_NO_WCHAR_T |
| |
| ////////////////////////////////////////////////////////////////// |
| rw_info (0, 0, 0, "rw_widen(UserChar*, const char*, size_t)"); |
| |
| static const UserChar usrc [] = { |
| { 0, 'a' }, { 0, 'b' }, { 0, 'c' }, { 0, 'd' }, |
| { 0, 'e' }, { 0, 'f' }, { 0, 'g' }, { 0, 'h' }, |
| { 0, '\0' } |
| }; |
| static const UserChar unull [] = { |
| { 0, '\0' }, { 0, '\0' }, { 0, '\0' }, { 0, '\0' }, |
| { 0, '\0' }, { 0, '\0' }, { 0, '\0' }, { 0, '\0' }, |
| { 0, '\0' } |
| }; |
| |
| UserChar udst [nsrc + 1]; |
| |
| for (size_t i = 0; i != nsrc + 1; ++i) { |
| |
| memset (udst, 0, sizeof udst); |
| |
| const UserChar* const ret = i < nsrc ? |
| rw_widen (udst, src, i) : rw_widen (udst, src); |
| |
| rw_assert (udst == ret, 0, __LINE__, |
| "rw_widen(UserChar*, %{#s}%{?}, %zu%{;})", |
| src, i < nsrc, i); |
| |
| rw_assert ( 0 == memcmp (udst, usrc, i * sizeof *udst) |
| && 0 == udst [i].f && 0 == udst [i].c, |
| 0, __LINE__, |
| "rw_widen(UserChar*, %{#s}%{?}, %zu%{;})", |
| src, i < nsrc, i); |
| } |
| |
| memset (udst, 1, sizeof udst); |
| rw_widen (udst, 0, sizeof udst / sizeof *udst); |
| |
| rw_assert (0 == memcmp (udst, unull, sizeof udst), 0, __LINE__, |
| "rw_widen(UserChar*, %{#s}, %zu)", |
| 0, sizeof udst, int (sizeof udst), wnull); |
| } |
| |
| /***********************************************************************/ |
| |
| static void |
| test_rw_expand () |
| { |
| ////////////////////////////////////////////////////////////////// |
| rw_info (0, 0, 0, "rw_expand(char*, const char*, size_t, size_t*)"); |
| |
| #undef TEST |
| #define TEST(str, expstr) \ |
| do { \ |
| const size_t str_size = sizeof str - 1; \ |
| const size_t exp_size = sizeof expstr - 1; \ |
| size_t len; \ |
| char* const res = rw_expand ((char*)0, str, str_size, &len); \ |
| rw_assert ( 0 == memcmp (res, expstr, exp_size) \ |
| && exp_size == len, \ |
| 0, __LINE__, \ |
| "rw_expand((char*)0, %{#*s}, %zu, ...) == " \ |
| "%{#*s} (length %zu), got %{#*s} (length %zu)", \ |
| int (str_size), str, str_size, \ |
| int (exp_size), expstr, exp_size, \ |
| int (len), res, len); \ |
| delete[] res; \ |
| } while (0) |
| |
| TEST ("", ""); |
| TEST ("\0", "\0"); |
| TEST ("a", "a"); |
| TEST ("a\0", "a\0"); |
| TEST ("ab", "ab"); |
| TEST ("abc", "abc"); |
| TEST ("a\0b", "a\0b"); |
| TEST ("a\0b\0c\0", "a\0b\0c\0"); |
| TEST ("\0\0\0", "\0\0\0"); |
| |
| TEST ("\0@0", ""); |
| TEST ("a@0", ""); |
| TEST ("\0@1", "\0"); |
| TEST ("a@1", "a"); |
| TEST ("\0@2", "\0\0"); |
| TEST ("a@2", "aa"); |
| TEST ("a@2\0", "aa\0"); |
| TEST ("a@3", "aaa"); |
| TEST ("a@1b", "ab"); |
| TEST ("a@2b", "aab"); |
| TEST ("a@3b", "aaab"); |
| TEST ("a@2\0\0", "aa\0\0"); |
| TEST ("\0@2b", "\0\0b"); |
| TEST ("a@3bc", "aaabc"); |
| TEST ("a@3b@1c", "aaabc"); |
| TEST ("a@3b@2c", "aaabbc"); |
| TEST ("a@3b@2c@1", "aaabbc"); |
| TEST ("a@3b@3c@2", "aaabbbcc"); |
| |
| ////////////////////////////////////////////////////////////////// |
| rw_info (0, 0, 0, "rw_expand(wchar_t*, const char*, size_t, size_t*)"); |
| |
| #ifndef _RWSTD_NO_WCHAR_T |
| |
| # undef TEST |
| #define TEST(str, expstr) \ |
| do { \ |
| const size_t str_size = sizeof str - 1; \ |
| const size_t exp_size = sizeof expstr / sizeof *expstr - 1; \ |
| size_t len; \ |
| wchar_t* const res = rw_expand ((wchar_t*)0, str, str_size, &len); \ |
| rw_assert ( 0 == memcmp (res, expstr, exp_size * sizeof *res) \ |
| && exp_size == len, \ |
| 0, __LINE__, \ |
| "rw_expand((wchar_t*)0, %{#*s}, %zu, ...) == " \ |
| "%{#*ls} (length %zu), got %{#*ls} (length %zu)", \ |
| int (str_size), str, str_size, \ |
| int (exp_size), expstr, exp_size, \ |
| int (len), res, len); \ |
| delete[] res; \ |
| } while (0) |
| |
| TEST ("", L""); |
| TEST ("\0", L"\0"); |
| TEST ("a", L"a"); |
| TEST ("a\0", L"a\0"); |
| TEST ("ab", L"ab"); |
| TEST ("abc", L"abc"); |
| TEST ("a\0b", L"a\0b"); |
| TEST ("a\0b\0c\0", L"a\0b\0c\0"); |
| TEST ("\0\0\0", L"\0\0\0"); |
| |
| TEST ("\0@0", L""); |
| TEST ("a@0", L""); |
| TEST ("\0@1", L"\0"); |
| TEST ("a@1", L"a"); |
| TEST ("\0@2", L"\0\0"); |
| TEST ("a@2", L"aa"); |
| TEST ("a@2\0", L"aa\0"); |
| TEST ("\0@2a", L"\0\0a"); |
| TEST ("a@3", L"aaa"); |
| TEST ("a@1b", L"ab"); |
| TEST ("a@2b", L"aab"); |
| TEST ("a@3b", L"aaab"); |
| TEST ("a@2\0\0", L"aa\0\0"); |
| TEST ("\0@2b", L"\0\0b"); |
| TEST ("a@3bc", L"aaabc"); |
| TEST ("a@3b@1c", L"aaabc"); |
| TEST ("a@3b@2c", L"aaabbc"); |
| TEST ("a@3b@2c@1", L"aaabbc"); |
| TEST ("a@3b@3c@2", L"aaabbbcc"); |
| |
| #else // if defined (_RWSTD_NO_WCHAR_T) |
| |
| rw_note (0, 0, 0, "_RWSTD_NO_WCHAR_T #defined, wchar_t test disabled"); |
| |
| #endif // _RWSTD_NO_WCHAR_T |
| |
| ////////////////////////////////////////////////////////////////// |
| rw_info (0, 0, 0, "rw_expand(UserChar*, const char*, size_t, size_t*)"); |
| |
| rw_warn (0, 0, 0, "rw_expand(UserChar*, const char*, size_t, size_t*) " |
| "not exercised"); |
| } |
| |
| |
| /***********************************************************************/ |
| |
| static void |
| test_rw_narrow () |
| { |
| ////////////////////////////////////////////////////////////////// |
| rw_info (0, 0, 0, "rw_narrow(char*, const char*, size_t)"); |
| |
| static const char src [] = "abcdefgh"; |
| const size_t nsrc = sizeof src - 1; |
| static const char null [nsrc + 1] = ""; |
| char cdst [nsrc + 1]; |
| |
| for (size_t i = 0; i != nsrc + 1; ++i) { |
| |
| memset (cdst, 0, sizeof cdst); |
| |
| const char* const ret = i < nsrc ? |
| rw_narrow (cdst, src, i) : rw_narrow (cdst, src); |
| |
| rw_assert (cdst == ret, 0, __LINE__, |
| "rw_narrow(char*, %{#s}%{?}, %zu%{;})", |
| src, i < nsrc); |
| |
| rw_assert (0 == memcmp (cdst, src, i) && '\0' == cdst [i], |
| 0, __LINE__, |
| "rw_narrow(char*, %{#s}%{?}, %zu%{;}) == %{#*s}, got %{#*s}", |
| src, i < nsrc, i, int (i), src, int (i + 1), cdst); |
| } |
| |
| memset (cdst, '@', sizeof cdst); |
| rw_narrow (cdst, (const char*)0, sizeof cdst); |
| |
| rw_assert (0 == memcmp (cdst, null, sizeof cdst), 0, __LINE__, |
| "rw_narrow(char*, %{#s}, %zu) == %{#*s}, got %{#*s}", |
| 0, sizeof cdst, int (sizeof cdst), null, |
| int (sizeof cdst), cdst); |
| |
| ////////////////////////////////////////////////////////////////// |
| rw_info (0, 0, 0, "rw_narrow(wchar_t*, const wchar_t*, size_t)"); |
| |
| #ifndef _RWSTD_NO_WCHAR_T |
| |
| static const wchar_t wsrc [] = L"abcdefgh"; |
| |
| for (size_t i = 0; i != nsrc + 1; ++i) { |
| |
| memset (cdst, 0, sizeof cdst); |
| |
| const char* const ret = i < nsrc ? |
| rw_narrow (cdst, wsrc, i) : rw_narrow (cdst, wsrc); |
| |
| rw_assert (cdst == ret, 0, __LINE__, |
| "rw_narrow(char*, %{#s}%{?}, %zu%{;})", |
| src, i < nsrc, i); |
| |
| rw_assert (0 == memcmp (cdst, src, i) && '\0' == cdst [i], |
| 0, __LINE__, |
| "rw_narrow(char*, L%{#*ls}%{?}, %zu%{;}) == %{#*s}, " |
| "got %{#*s}", |
| int (i), src, i < nsrc, i, int (i), wsrc, |
| int (i + 1), cdst); |
| } |
| |
| memset (cdst, '@', sizeof cdst); |
| rw_narrow (cdst, (const wchar_t*)0, sizeof cdst); |
| |
| rw_assert (0 == memcmp (cdst, null, nsrc + 1), 0, __LINE__, |
| "rw_narrow(char*, %{#s}, %zu) == %{#*s}, got %{#*s}", |
| 0, sizeof cdst, int (sizeof null), null, |
| int (sizeof cdst), cdst); |
| |
| #else // if defined (_RWSTD_NO_WCHAR_T) |
| |
| rw_note (0, 0, 0, "_RWSTD_NO_WCHAR_T #defined, wchar_t test disabled"); |
| |
| #endif // _RWSTD_NO_WCHAR_T |
| |
| ////////////////////////////////////////////////////////////////// |
| rw_info (0, 0, 0, "rw_narrow(char*, const UserChar*, size_t)"); |
| |
| static const UserChar usrc [] = { |
| { 0, 'a' }, { 0, 'b' }, { 0, 'c' }, { 0, 'd' }, |
| { 0, 'e' }, { 0, 'f' }, { 0, 'g' }, { 0, 'h' }, |
| { 0, '\0' } |
| }; |
| |
| for (size_t i = 0; i != nsrc + 1; ++i) { |
| |
| memset (cdst, 0, sizeof cdst); |
| |
| const char* const ret = i < nsrc ? |
| rw_narrow (cdst, usrc, i) : rw_narrow (cdst, usrc); |
| |
| rw_assert (cdst == ret, 0, __LINE__, |
| "rw_narrow(char*, %{#s}%{?}, %zu%{;})", |
| src, i < nsrc, i); |
| |
| rw_assert (0 == memcmp (cdst, src, i) && 0 == cdst [i], |
| 0, __LINE__, |
| "rw_narrow(char*, %{#s}%{?}, %zu%{;})", |
| src, i < nsrc, i); |
| } |
| |
| memset (cdst, '@', sizeof cdst); |
| rw_narrow (cdst, (const UserChar*)0, sizeof cdst); |
| |
| rw_assert (0 == memcmp (cdst, null, nsrc + 1), 0, __LINE__, |
| "rw_narrow(char*, %{#s}, %zu)", |
| 0, sizeof cdst); |
| } |
| |
| /***********************************************************************/ |
| |
| static const UserChar* |
| make_user_string (const char *s, size_t len) |
| { |
| static UserChar usrbuf [32]; |
| memset (usrbuf, 0, sizeof usrbuf); |
| |
| if (s) { |
| for (size_t i = 0; i != len; ++i) { |
| |
| typedef unsigned char UChar; |
| |
| usrbuf [i].f = 0; |
| usrbuf [i].c = UChar (s [i]); |
| } |
| return usrbuf; |
| } |
| |
| return 0; |
| } |
| |
| |
| static void |
| test_rw_match () |
| { |
| ////////////////////////////////////////////////////////////////// |
| rw_info (0, 0, 0, "rw_match(char*, const char*, size_t)"); |
| |
| size_t result; |
| |
| #undef TEST |
| #define TEST(s1, s2, len, expect) \ |
| result = rw_match ((const char*)s1, (const char*)s2, size_t (len)); \ |
| rw_assert (expect == result, \ |
| 0, __LINE__, \ |
| "rw_match(%{#*s}, %{#*s}, %zu) == %zu, got %zu", \ |
| int (sizeof s1 - 1), s1, int (sizeof s2 - 1), s2, len, \ |
| expect, result) |
| |
| TEST (0, 0, -1, 0); |
| TEST ("", 0, -1, 0); |
| TEST (0, "", -1, 0); |
| TEST ("", "", -1, 1); |
| |
| // same as above but using the <char>@<count> directive |
| TEST ("a@0", "", -1, 1); |
| TEST ("", "b@0", -1, 1); |
| TEST ("a@0", "b@0", -1, 1); |
| |
| // when invoked with NULL as the first argument returns |
| // the length of the second string with all directives |
| // expanded |
| TEST (0, "a", -1, 1); |
| TEST (0, "ab", -1, 2); |
| TEST (0, "abc", -1, 3); |
| TEST (0, "a@0", -1, 0); |
| TEST (0, "a@1", -1, 1); |
| TEST (0, "a@2", -1, 2); |
| TEST (0, "a@2b@0", -1, 2); |
| TEST (0, "a@2b@1", -1, 3); |
| TEST (0, "a@2b@2", -1, 4); |
| |
| // same as above but with the arguments reversed |
| TEST ("a", 0, -1, 1); |
| TEST ("ab", 0, -1, 2); |
| TEST ("abc", 0, -1, 3); |
| TEST ("a@0", 0, -1, 0); |
| TEST ("a@1", 0, -1, 1); |
| TEST ("a@2", 0, -1, 2); |
| TEST ("a@2b@0", 0, -1, 2); |
| TEST ("a@2b@1", 0, -1, 3); |
| TEST ("a@2b@2", 0, -1, 4); |
| |
| TEST ("", "a", -1, 0); |
| TEST ("a", "", -1, 0); |
| TEST ("a", "a", -1, 2); |
| |
| // same as above but using the <char>@<count> directive |
| TEST ("", "a@1", -1, 0); |
| TEST ("a@1", "", -1, 0); |
| TEST ("a", "a@1", -1, 2); |
| TEST ("a@1", "a", -1, 2); |
| TEST ("a@1", "a@1", -1, 2); |
| |
| TEST ("\0ab", "\0ac", 2, 2); |
| TEST ("\0@0ab", "ab", 2, 2); |
| TEST ("\0@0a\0@0b", "ab", 2, 2); |
| TEST ("\0@1ab", "\0@1ac", 2, 2); |
| TEST ("\0@1ab", "\0@1ac", 2, 2); |
| TEST ("a\0@0b", "a\0@0c", -1, 2); |
| TEST ("a\0@0b", "a\0@1c", -1, 2); |
| TEST ("a\0@1b", "a\0@0c", -1, 2); |
| TEST ("a\0@1b", "a\0@1c", -1, 2); |
| |
| TEST ("a\0bc", "a\0bd", -1, 2); |
| TEST ("a\0bc", "a\0bd", 0, 0); |
| TEST ("a\0bc", "a\0bd", 1, 1); |
| TEST ("a\0bc", "a\0bd", 2, 2); |
| TEST ("a\0bc", "a\0bd", 3, 3); |
| TEST ("a\0bc", "a\0bd", 4, 3); |
| |
| TEST ("aaaaa", "a@5", -1, 6); |
| TEST ("aaaaaa@0", "a@5", -1, 6); |
| TEST ("aaaaa@1", "a@5", -1, 6); |
| TEST ("aaaa@2", "a@5", -1, 6); |
| TEST ("aaa@3", "a@5", -1, 6); |
| TEST ("aa@4", "a@5", -1, 6); |
| TEST ("a@5", "a@5", -1, 6); |
| TEST ("a@4a", "a@5", -1, 6); |
| TEST ("a@3aa", "a@5", -1, 6); |
| TEST ("a@2aaa", "a@5", -1, 6); |
| TEST ("a@1aaaa", "a@5", -1, 6); |
| TEST ("a@0aaaaa", "a@5", -1, 6); |
| |
| TEST ("a@0a@1a@2a@3", "a@3a@2a@1a@0", -1, 7); |
| TEST ("a@0a@1a@2a@3", "a@3a@2a@1a@0", 0, 0); |
| TEST ("a@0a@1a@2a@3", "a@3a@2a@1a@0", 1, 1); |
| TEST ("a@0a@1a@2a@3", "a@3a@2a@1a@0", 2, 2); |
| TEST ("a@0a@1a@2a@3", "a@3a@2a@1a@0", 3, 3); |
| TEST ("a@0a@1a@2a@3", "a@3a@2a@1a@0", 4, 4); |
| TEST ("a@0a@1a@2a@3", "a@3a@2a@1a@0", 5, 5); |
| TEST ("a@0a@1a@2a@3", "a@3a@2a@1a@0", 6, 6); |
| TEST ("a@0a@1a@2a@3", "a@3a@2a@1a@0", 7, 7); |
| |
| TEST ("a@0\0a@1a@2\0a@3\0", "\0a@3\0a@2a@1a@0\0", 10, 10); |
| TEST ("a@0*a@1a@2\0a@3\0", "\0a@3\0a@2a@1a@0\0", 10, 0); |
| TEST ("a@0\0a@1a@2*a@3\0", "\0a@3\0a@2a@1a@0\0", 10, 4); |
| TEST ("a@0\0a@1a@2\0a@3*", "\0a@3\0a@2a@1a@0\0", 10, 8); |
| TEST ("a@11aa@12aaa@13b", "a@13aa@12aaa@11c", -1, 39); |
| |
| // invalid directives |
| TEST ("a@b", "a@0a@b", -1, 4); |
| TEST ("a@b@c", "a@0a@b@c", -1, 6); |
| |
| ////////////////////////////////////////////////////////////////// |
| // exercise Unicode escape sequences |
| TEST ("<U0>", "", -1, 1); |
| TEST ("<U00>", "", -1, 1); |
| TEST ("<U000>", "", -1, 1); |
| TEST ("<U0000>", "", -1, 1); |
| TEST ("", "<U0>", -1, 1); |
| TEST ("", "<U00>", -1, 1); |
| TEST ("", "<U000>", -1, 1); |
| TEST ("", "<U0000>", -1, 1); |
| TEST ("<U0>", "<U0000>", -1, 1); |
| TEST ("<U00>", "<U000>", -1, 1); |
| TEST ("<U000>", "<U00>", -1, 1); |
| TEST ("<U0000>", "<U0>", -1, 1); |
| |
| TEST ("<U1>", 0, -1, 1); |
| TEST ("<U1><U02>", 0, -1, 2); |
| TEST ("<U1><U02><U003>", 0, -1, 3); |
| TEST ("<U1><U02><U003><U0004>", 0, -1, 4); |
| |
| #if 'A' == 0x41 // ASCII |
| TEST ("<UA>", "\n", -1, 2); |
| TEST ("<U0A>", "\n", -1, 2); |
| TEST ("<U00A>", "\n", -1, 2); |
| TEST ("<U000A>", "\n", -1, 2); |
| TEST ("<U0000A>", "\n", -1, 2); |
| TEST ("<U41>", "A", -1, 2); |
| TEST ("<U41>A", "AA", -1, 3); |
| TEST ("A<U41>A", "AAA", -1, 4); |
| TEST ("A<U41>@3A", "AAAAA", -1, 6); |
| |
| TEST ("<U41>@0<U42>@1<U43>@2<U44>@3", "BCCDDD", -1, 7); |
| #elif 'A' == 0xC1 // EBCDIC |
| TEST ("<U25>", "\n", -1, 2); |
| TEST ("<U025>", "\n", -1, 2); |
| TEST ("<U025>", "\n", -1, 2); |
| TEST ("<U0025>", "\n", -1, 2); |
| TEST ("<UC1>", "A", -1, 2); |
| TEST ("<UC1>A", "AA", -1, 3); |
| TEST ("A<UC1>A", "AAA", -1, 4); |
| TEST ("A<UC1>@3A", "AAAAA", -1, 6); |
| |
| TEST ("<UC1>@0<UC2>@1<UC3>@2<UC4>@3", "BCCDDD", -1, 7); |
| #else // unknown |
| rw_warn (0, 0, "unknown character set (neither ASCII nor EBCDIC)"); |
| #endif |
| |
| ////////////////////////////////////////////////////////////////// |
| rw_info (0, 0, 0, "rw_match(char*, const wchar_t*, size_t)"); |
| |
| #ifndef _RWSTD_NO_WCHAR_T |
| |
| #undef TEST |
| #define TEST(s1, s2, len, expect) \ |
| result = rw_match ((const char*)s1, (const wchar_t*)s2, size_t (len)); \ |
| rw_assert (expect == result, \ |
| 0, __LINE__, \ |
| "rw_match(%{#*s}, L%{#*ls}, %zu) == %zu, got %zu", \ |
| int (sizeof s1 - 1), s1, \ |
| int (sizeof (s2) / sizeof *(s2) - 1), s2, len, \ |
| expect, result) |
| |
| TEST (0, (wchar_t*)0, -1, 0); |
| TEST ("", (wchar_t*)0, -1, 0); |
| TEST (0, L"", -1, 0); |
| TEST ("", L"", -1, 1); |
| |
| // same as above but using the <char>@<count> directive |
| TEST ("a@0", L"", -1, 1); |
| TEST ("", L"", -1, 1); |
| TEST ("a@0", L"", -1, 1); |
| |
| // when invoked with NULL as the first argument returns |
| // the length of the second string with all directives |
| // expanded |
| TEST (0, L"a", -1, 1); |
| TEST (0, L"ab", -1, 2); |
| TEST (0, L"abc", -1, 3); |
| TEST (0, L"abcd", -1, 4); |
| TEST (0, L"abcde", -1, 5); |
| TEST (0, L"abcdef", -1, 6); |
| |
| // same as above but with the arguments reversed |
| TEST ("a", (wchar_t*)0, -1, 1); |
| TEST ("ab", (wchar_t*)0, -1, 2); |
| TEST ("abc", (wchar_t*)0, -1, 3); |
| TEST ("a@0", (wchar_t*)0, -1, 0); |
| TEST ("a@1", (wchar_t*)0, -1, 1); |
| TEST ("a@2", (wchar_t*)0, -1, 2); |
| TEST ("a@2b@0", (wchar_t*)0, -1, 2); |
| TEST ("a@2b@1", (wchar_t*)0, -1, 3); |
| TEST ("a@2b@2", (wchar_t*)0, -1, 4); |
| |
| TEST ("", L"a", -1, 0); |
| TEST ("a", L"", -1, 0); |
| TEST ("a", L"a", -1, 2); |
| |
| // same as above but using the <char>@<count> directive |
| TEST ("a@1", L"", -1, 0); |
| TEST ("a@1", L"a", -1, 2); |
| |
| TEST ("\0ab", L"\0ac", 2, 2); |
| TEST ("\0@0ab", L"ab", 2, 2); |
| TEST ("\0@0a\0@0b", L"ab", 2, 2); |
| TEST ("a\0@0b", L"a\0\0", -1, 2); |
| TEST ("a\0@1b", L"a\0\0", -1, 2); |
| |
| TEST ("a\0bc", L"a\0bd", -1, 2); |
| TEST ("a\0bc", L"a\0bd", 0, 0); |
| TEST ("a\0bc", L"a\0bd", 1, 1); |
| TEST ("a\0bc", L"a\0bd", 2, 2); |
| TEST ("a\0bc", L"a\0bd", 3, 3); |
| TEST ("a\0bc", L"a\0bd", 4, 3); |
| |
| TEST ("aaaaa", L"aaaaa", -1, 6); |
| TEST ("aaaaaa@0", L"aaaaa", -1, 6); |
| TEST ("aaaaa@1", L"aaaaa", -1, 6); |
| TEST ("aaaa@2", L"aaaaa", -1, 6); |
| TEST ("aaa@3", L"aaaaa", -1, 6); |
| TEST ("aa@4", L"aaaaa", -1, 6); |
| TEST ("a@5", L"aaaaa", -1, 6); |
| TEST ("a@4a", L"aaaaa", -1, 6); |
| TEST ("a@3aa", L"aaaaa", -1, 6); |
| TEST ("a@2aaa", L"aaaaa", -1, 6); |
| TEST ("a@1aaaa", L"aaaaa", -1, 6); |
| TEST ("a@0aaaaa", L"aaaaa", -1, 6); |
| |
| TEST ("a@0a@1a@2a@3", L"aaaaaa", -1, 7); |
| TEST ("a@0a@1a@2a@3", L"aaaaaa", 0, 0); |
| TEST ("a@0a@1a@2a@3", L"aaaaaa", 1, 1); |
| TEST ("a@0a@1a@2a@3", L"aaaaaa", 2, 2); |
| TEST ("a@0a@1a@2a@3", L"aaaaaa", 3, 3); |
| TEST ("a@0a@1a@2a@3", L"aaaaaa", 4, 4); |
| TEST ("a@0a@1a@2a@3", L"aaaaaa", 5, 5); |
| TEST ("a@0a@1a@2a@3", L"aaaaaa", 6, 6); |
| TEST ("a@0a@1a@2a@3", L"aaaaaa", 7, 7); |
| |
| TEST ("a@0\0a@1a@2\0a@3\0", L"\0aaa\0aaa\0", 10, 10); |
| TEST ("a@0*a@1a@2\0a@3\0", L"\0aaa\0aaa\0", 10, 0); |
| TEST ("a@0\0a@1a@2*a@3\0", L"\0aaa\0aaa\0", 10, 4); |
| TEST ("a@0\0a@1a@2\0a@3*", L"\0aaa\0aaa\0", 10, 8); |
| |
| // invalid directives |
| TEST ("a@b", L"a@b", -1, 4); |
| TEST ("a@b@c", L"a@b@c", -1, 6); |
| |
| #else // if defined (_RWSTD_NO_WCHAR_T) |
| |
| rw_note (0, 0, 0, "_RWSTD_NO_WCHAR_T #defined, wchar_t test disabled"); |
| |
| #endif // _RWSTD_NO_WCHAR_T |
| |
| ////////////////////////////////////////////////////////////////// |
| rw_info (0, 0, 0, "rw_match(char*, const UserChar*, size_t)"); |
| |
| #undef TEST |
| #define TEST(s1, s2, len, expect) \ |
| result = rw_match ((const char*)s1, \ |
| make_user_string (s2, sizeof (s2)), size_t (len)); \ |
| rw_assert (expect == result, \ |
| 0, __LINE__, \ |
| "rw_match(%{#*s}, %{#*s}, %zu) == %zu, got %zu", \ |
| int (sizeof s1 - 1), s1, int (sizeof s2 - 1), s2, len, \ |
| expect, result) |
| |
| TEST (0, 0, -1, 0); |
| TEST ("", 0, -1, 0); |
| TEST (0, "", -1, 0); |
| TEST ("", "", -1, 1); |
| |
| // same as above but using the <char>@<count> directive |
| TEST ("a@0", "", -1, 1); |
| TEST ("", "", -1, 1); |
| TEST ("a@0", "", -1, 1); |
| |
| // when invoked with NULL as the first string returns |
| // the length of the second string (if non-NULL) |
| TEST (0, "a", -1, 1); |
| TEST (0, "ab", -1, 2); |
| TEST (0, "abc", -1, 3); |
| |
| // same as above but with the arguments reversed |
| TEST ("a", 0, -1, 1); |
| TEST ("ab", 0, -1, 2); |
| TEST ("abc", 0, -1, 3); |
| |
| TEST ("", "a", -1, 0); |
| TEST ("a", "", -1, 0); |
| TEST ("a", "a", -1, 2); |
| |
| // same as above but using the <char>@<count> directive |
| TEST ("a@1", "", -1, 0); |
| TEST ("a@1", "a", -1, 2); |
| |
| TEST ("\0ab", "\0ac", 2, 2); |
| TEST ("\0@0ab", "ab", 2, 2); |
| TEST ("\0@0a\0@0b", "ab", 2, 2); |
| TEST ("a\0@0b", "a\0\0", -1, 2); |
| TEST ("a\0@1b", "a\0\0", -1, 2); |
| |
| TEST ("a\0bc", "a\0bd", -1, 2); |
| TEST ("a\0bc", "a\0bd", 0, 0); |
| TEST ("a\0bc", "a\0bd", 1, 1); |
| TEST ("a\0bc", "a\0bd", 2, 2); |
| TEST ("a\0bc", "a\0bd", 3, 3); |
| TEST ("a\0bc", "a\0bd", 4, 3); |
| |
| TEST ("aaaaa", "aaaaa", -1, 6); |
| TEST ("aaaaaa@0", "aaaaa", -1, 6); |
| TEST ("aaaaa@1", "aaaaa", -1, 6); |
| TEST ("aaaa@2", "aaaaa", -1, 6); |
| TEST ("aaa@3", "aaaaa", -1, 6); |
| TEST ("aa@4", "aaaaa", -1, 6); |
| TEST ("a@5", "aaaaa", -1, 6); |
| TEST ("a@4a", "aaaaa", -1, 6); |
| TEST ("a@3aa", "aaaaa", -1, 6); |
| TEST ("a@2aaa", "aaaaa", -1, 6); |
| TEST ("a@1aaaa", "aaaaa", -1, 6); |
| TEST ("a@0aaaaa", "aaaaa", -1, 6); |
| |
| TEST ("a@0a@1a@2a@3", "aaaaaa", -1, 7); |
| TEST ("a@0a@1a@2a@3", "aaaaaa", 0, 0); |
| TEST ("a@0a@1a@2a@3", "aaaaaa", 1, 1); |
| TEST ("a@0a@1a@2a@3", "aaaaaa", 2, 2); |
| TEST ("a@0a@1a@2a@3", "aaaaaa", 3, 3); |
| TEST ("a@0a@1a@2a@3", "aaaaaa", 4, 4); |
| TEST ("a@0a@1a@2a@3", "aaaaaa", 5, 5); |
| TEST ("a@0a@1a@2a@3", "aaaaaa", 6, 6); |
| TEST ("a@0a@1a@2a@3", "aaaaaa", 7, 7); |
| |
| TEST ("a@0\0a@1a@2\0a@3\0", "\0aaa\0aaa\0", 10, 10); |
| TEST ("a@0*a@1a@2\0a@3\0", "\0aaa\0aaa\0", 10, 0); |
| TEST ("a@0\0a@1a@2*a@3\0", "\0aaa\0aaa\0", 10, 4); |
| TEST ("a@0\0a@1a@2\0a@3*", "\0aaa\0aaa\0", 10, 8); |
| |
| // invalid directives |
| TEST ("a@b", "a@b", -1, 4); |
| TEST ("a@b@c", "a@b@c", -1, 6); |
| } |
| |
| /***********************************************************************/ |
| |
| static void |
| test_formatting () |
| { |
| ////////////////////////////////////////////////////////////////// |
| rw_info (0, 0, 0, "\"%s\": formatting directive", "%{/Gs}"); |
| |
| const int wchsize = int (sizeof (wchar_t)); |
| const int usrsize = int (sizeof (UserChar)); |
| |
| char *str; |
| |
| #undef TEST |
| #define TEST(fmt, arg0, arg1, arg2, expect_str) \ |
| str = rw_sprintfa (fmt, arg0, arg1, arg2); \ |
| rw_assert (str && 0 == strcmp (str, expect_str), \ |
| 0, __LINE__, \ |
| "rw_printf(%#s, ...) == %#s; got %#s", \ |
| fmt, expect_str, str); \ |
| free (str) |
| |
| TEST (">%{/Gs}<", (char*)0, 0, 0, ">(null)<"); |
| TEST (">%{/Gs}<", "", 0, 0, ">\"\"<"); |
| TEST (">%{/Gs}<", "a", 0, 0, ">\"a\"<"); |
| TEST (">%{/Gs}<", "ab", 0, 0, ">\"ab\"<"); |
| TEST (">%{/Gs}<", "abc", 0, 0, ">\"abc\"<"); |
| TEST (">%{/Gs}<", "x\0z", 0, 0, ">\"x\"<"); |
| |
| TEST (">%{/*Gs}<", 1, "abc", 0, ">\"abc\"<"); |
| TEST (">%{/*.*Gs}<", 1, 2, "abc", ">\"ab\"<"); |
| TEST (">%{/.*Gs}<", 2, "abc", 0, ">\"ab\"<"); |
| TEST (">%{/.*Gs}<", 3, "x\0z", 0, ">\"x\\0z\"<"); |
| |
| TEST (">%{/*Gs}<", wchsize, (wchar_t*)0, 0, ">(null)<"); |
| TEST (">%{/*Gs}<", wchsize, L"", 0, ">\"\"<"); |
| TEST (">%{/*Gs}<", wchsize, L"a", 0, ">\"a\"<"); |
| TEST (">%{/*Gs}<", wchsize, L"ab", 0, ">\"ab\"<"); |
| TEST (">%{/*Gs}<", wchsize, L"abc", 0, ">\"abc\"<"); |
| TEST (">%{/*Gs}<", wchsize, L"x\0z", 0, ">\"x\"<"); |
| TEST (">%{/*.*Gs}<", wchsize, 2, L"abc", ">\"ab\"<"); |
| TEST (">%{/*.*Gs}<", wchsize, 3, L"x\0z",">\"x\\0z\"<"); |
| |
| #define US(s) make_user_string (s, sizeof (s)) |
| |
| TEST (">%{/*Gs}<", usrsize, (UserChar*)0, 0, ">(null)<"); |
| TEST (">%{/*Gs}<", usrsize, US (""), 0, ">\"\"<"); |
| TEST (">%{/*Gs}<", usrsize, US ("a"), 0, ">\"a\"<"); |
| TEST (">%{/*Gs}<", usrsize, US ("ab"), 0, ">\"ab\"<"); |
| TEST (">%{/*Gs}<", usrsize, US ("abc"), 0, ">\"abc\"<"); |
| TEST (">%{/*Gs}<", usrsize, US ("x\0z"), 0, ">\"x\"<"); |
| TEST (">%{/*.*Gs}<", usrsize, 2, US ("abc"), ">\"ab\"<"); |
| TEST (">%{/*.*Gs}<", usrsize, 3, US ("x\0z"), ">\"x\\0z\"<"); |
| } |
| |
| /***********************************************************************/ |
| |
| static int opt_user_traits; |
| static int opt_user_traits_char; |
| static int opt_user_traits_wchar; |
| static int opt_user_traits_user_char; |
| static int opt_rw_widen; |
| static int opt_rw_expand; |
| static int opt_rw_narrow; |
| static int opt_rw_match; |
| static int opt_formatting; |
| |
| |
| static int |
| run_test (int, char*[]) |
| { |
| if (opt_user_traits < 0) { |
| rw_note (0, 0, 0, "UserTraits tests disabled"); |
| } |
| else { |
| if (opt_user_traits_char < 0) { |
| rw_note (0, 0, 0, "UserTraits<char> tests disabled"); |
| } |
| else { |
| test_user_traits_char (); |
| } |
| |
| if (opt_user_traits_wchar < 0) { |
| rw_note (0, 0, 0, "UserTraits<wchar_t> tests disabled"); |
| } |
| else { |
| test_user_traits_wchar (); |
| } |
| |
| if (opt_user_traits_user_char < 0) { |
| rw_note (0, 0, 0, "UserTraits<UserChar> tests disabled"); |
| } |
| else { |
| test_user_traits_user_char (); |
| } |
| } |
| |
| #undef TEST |
| #define TEST(fun) \ |
| if (opt_ ## fun < 0) \ |
| rw_note (0, 0, 0, "%s() tests disabled", #fun); \ |
| else \ |
| test_ ## fun () |
| |
| TEST (rw_widen); |
| TEST (rw_expand); |
| TEST (rw_narrow); |
| TEST (rw_match); |
| TEST (formatting); |
| |
| return 0; |
| } |
| |
| /***********************************************************************/ |
| |
| int main (int argc, char *argv[]) |
| { |
| return rw_test (argc, argv, __FILE__, |
| "", |
| 0, |
| run_test, |
| "|-UserTraits~ " |
| "|-UserTraits<char>~ " |
| "|-UserTraits<wchar_t>~ " |
| "|-UserTraits<UserChar>~ " |
| "|-rw_widen~ " |
| "|-rw_expand~ " |
| "|-rw_narrow~ " |
| "|-rw_macth~ " |
| "|-formatting~", |
| &opt_user_traits, |
| &opt_user_traits_char, |
| &opt_user_traits_wchar, |
| &opt_user_traits_user_char, |
| &opt_rw_widen, |
| &opt_rw_expand, |
| &opt_rw_narrow, |
| &opt_rw_match, |
| &opt_formatting, |
| 0); |
| } |