You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by an...@apache.org on 2006/05/15 16:08:19 UTC
svn commit: r406631 -
/incubator/stdcxx/trunk/tests/strings/21.string.cons.cpp
Author: antonp
Date: Mon May 15 07:08:18 2006
New Revision: 406631
URL: http://svn.apache.org/viewcvs?rev=406631&view=rev
Log:
2006-05-15 Anton Pevtsov <an...@moscow.vdiweb.com>
STDCXX-4
* 21.string.cons.cpp: New test exercising lib.string.cons.
Modified:
incubator/stdcxx/trunk/tests/strings/21.string.cons.cpp
Modified: incubator/stdcxx/trunk/tests/strings/21.string.cons.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/strings/21.string.cons.cpp?rev=406631&r1=406630&r2=406631&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/strings/21.string.cons.cpp (original)
+++ incubator/stdcxx/trunk/tests/strings/21.string.cons.cpp Mon May 15 07:08:18 2006
@@ -19,799 +19,993 @@
*
**************************************************************************/
-#include <stdexcept> // for length_error
-#include <string>
-#include <cstring>
+#include <string> // for string
+#include <stdexcept> // for out_of_range, length_error
+#include <cstddef> // for size_t
+
+#include <21.strings.h>
+#include <alg_test.h> // for InputIter
+#include <cmdopt.h> // for rw_enabled()
+#include <driver.h> // for rw_test()
+#include <rw_char.h> // for rw_expand()
+#include <rw_new.h> // for bad_alloc, replacement operator new
+#include <rw_printf.h> // for rw_asnprintf()
-#include <cmdopt.h>
-#include <driver.h>
+/**************************************************************************/
-#include <alg_test.h> // for InputIterator
+// for convenience and brevity
+#define Ctor(which) StringMembers::ctor_ ## which
+#define OpSet(which) StringMembers::op_set_ ## which
+
+typedef StringMembers::OverloadId OverloadId;
+typedef StringMembers::TestCase TestCase;
+typedef StringMembers::Test Test;
+typedef StringMembers::Function MemFun;
+
+static const char* const exceptions[] = {
+ "unknown exception", "out_of_range", "length_error",
+ "bad_alloc", "exception"
+};
-#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
-# include <rw_new.h> // for replacing operator new/delete
-#else // if defined (_RWSTD_NO_REPLACEABLE_NEW_DELETE)
- // e.g., AIX, Win32
-# define rwt_check_leaks(pint, ignore) (pint ? *((std::size_t*)pint) = 0 : 0)
-#endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
+/**************************************************************************/
+// exercises:
+// ctor (void*)
+static const TestCase
+void_test_cases [] = {
+
+#undef TEST
+#define TEST(dummy) { \
+ __LINE__, -1, -1, -1, -1, -1, \
+ 0, 0, dummy, sizeof dummy - 1, \
+ "", 0, 0 \
+ }
+
+ // +--------------------- dummy argument
+ // |
+ // V
+ TEST ("ab"),
-template<class charT>
-class Lit { };
+ TEST ("last test")
+};
-_RWSTD_SPECIALIZED_CLASS
-class Lit<char>
-{
-public:
- static const char null[];
- static const char space[];
- static const char aString[];
- static const char abcdef[];
- static const char abcdefg[];
- static const char abcnulldefg[];
- static const char nullchar[];
- static const char a[];
- static const char b[];
- static const char c[];
- static const char d[];
- static const char ef[];
- static const char f[];
- static const char cd[];
- static const char abc[];
- static const char ddddd[];
-};
-
-const char Lit<char>::null[] = "\0";
-const char Lit<char>::space[] = " ";
-const char Lit<char>::aString[] = "A String";
-const char Lit<char>::abcdef[] = "abcdef";
-const char Lit<char>::abcdefg[] = "abcdefg";
-const char Lit<char>::abcnulldefg[] = "abc\0defg";
-const char Lit<char>::nullchar[] = " ";
-const char Lit<char>::a[] = "a";
-const char Lit<char>::b[] = "b";
-const char Lit<char>::c[] = "c";
-const char Lit<char>::d[] = "d";
-const char Lit<char>::ef[] = "ef";
-const char Lit<char>::f[] = "f";
-const char Lit<char>::cd[] = "cd";
-const char Lit<char>::abc[] = "abc";
-const char Lit<char>::ddddd[] = "ddddd";
-
-
-#ifndef _RWSTD_NO_WCHAR_T
-_RWSTD_SPECIALIZED_CLASS
-class Lit<wchar_t>
-{
-public:
- static const wchar_t null[];
- static const wchar_t space[];
- static const wchar_t aString[];
- static const wchar_t abcdef[];
- static const wchar_t abcdefg[];
- static const wchar_t abcnulldefg[];
- static const wchar_t nullchar[];
- static const wchar_t a[];
- static const wchar_t b[];
- static const wchar_t c[];
- static const wchar_t d[];
- static const wchar_t ef[];
- static const wchar_t f[];
- static const wchar_t cd[];
- static const wchar_t abc[];
- static const wchar_t ddddd[];
-};
-
-const wchar_t Lit<wchar_t>::null[] = L"\0";
-const wchar_t Lit<wchar_t>::space[] = L" ";
-const wchar_t Lit<wchar_t>::aString[] = L"A String";
-const wchar_t Lit<wchar_t>::abcdef[] = L"abcdef";
-const wchar_t Lit<wchar_t>::abcdefg[] = L"abcdefg";
-const wchar_t Lit<wchar_t>::abcnulldefg[] = L"abc\0defg";
-const wchar_t Lit<wchar_t>::nullchar[] = L" ";
-const wchar_t Lit<wchar_t>::a[] = L"a";
-const wchar_t Lit<wchar_t>::b[] = L"b";
-const wchar_t Lit<wchar_t>::c[] = L"c";
-const wchar_t Lit<wchar_t>::d[] = L"d";
-const wchar_t Lit<wchar_t>::ef[] = L"ef";
-const wchar_t Lit<wchar_t>::f[] = L"f";
-const wchar_t Lit<wchar_t>::cd[] = L"cd";
-const wchar_t Lit<wchar_t>::abc[] = L"abc";
-const wchar_t Lit<wchar_t>::ddddd[] = L"ddddd";
-
-#endif
+/**************************************************************************/
+
+// exercises:
+// ctor (const value_type*)
+static const TestCase
+ptr_test_cases [] = {
+
+#undef TEST
+#define TEST(arg, res) { \
+ __LINE__, -1, -1, -1, -1, -1, \
+ 0, 0, arg, sizeof arg - 1, \
+ res, sizeof res - 1, 0 \
+ }
+
+ // +----------------------------------------- source sequence
+ // | +--------------------------- expected result sequence
+ // | |
+ // | |
+ // V V
+ TEST ("ab", "ab"),
+
+ TEST ("", ""),
+ TEST ("\0", ""),
+
+ TEST ("a", "a"),
+ TEST ("bcd", "bcd"),
+ TEST ("cdefaihjb", "cdefaihjb"),
+
+ TEST ("\0\0ab", ""),
+ TEST ("a\0\0b", "a"),
+ TEST ("ab\0\0", "ab"),
+ TEST ("abefdcc\0a", "abefdcc"),
+
+ TEST ("x@4096", "x@4096"),
+
+ TEST ("last test", "last test")
+};
/**************************************************************************/
-/* extern */ int rw_opt_no_copy_ctor; // for --no-copy-ctor
-/* extern */ int rw_opt_no_def_ctor; // for --no-default-ctor
-/* extern */ int rw_opt_no_ptr_ctor; // for --no-pointer-ctor
-/* extern */ int rw_opt_no_fill_ctor; // for --no-fill-ctor
+// exercises:
+// ctor (const basic_string&)
+static const TestCase
+str_test_cases [] = {
+
+#undef TEST
+#define TEST(arg, res) { \
+ __LINE__, -1, -1, -1, -1, -1, \
+ 0, 0, arg, sizeof arg - 1, \
+ res, sizeof res - 1, 0 \
+ }
+
+ // +----------------------------------------- source sequence
+ // | +--------------------------- expected result sequence
+ // | |
+ // | |
+ // V V
+ TEST ("ab", "ab"),
+
+ TEST ("", ""),
+ TEST ("\0", "\0"),
+ TEST ("\0\0", "\0\0"),
+
+ TEST ("a", "a"),
+ TEST ("bcd", "bcd"),
+ TEST ("cdefaihjb", "cdefaihjb"),
+
+ TEST ("\0\0ab", "\0\0ab"),
+ TEST ("a\0\0b", "a\0\0b"),
+ TEST ("ab\0\0", "ab\0\0"),
+ TEST ("abefdcc\0a", "abefdcc\0a"),
+ TEST ("x@4096", "x@4096"),
-template <class T>
-void test_signatures (T, const char* tname)
-{
- // verify that constructs below compile ad run (no assertions)
+ TEST ("last test", "last test")
+};
- typedef std::char_traits<T> Traits;
- typedef std::allocator<T> Allocator;
- typedef std::basic_string<T, Traits, Allocator> String;
+/**************************************************************************/
- typedef typename String::size_type SizeT;
+// exercises:
+// ctor (const value_type*, size_type)
+static const TestCase
+ptr_size_test_cases [] = {
+
+#undef TEST
+#define TEST(arg, size, res) { \
+ __LINE__, -1, size, -1, -1, -1, \
+ 0, 0, arg, sizeof arg - 1, \
+ res, sizeof res - 1, 0 \
+ }
+
+ // +----------------------------------------- source sequence
+ // | +--------------------------- ctor n argument
+ // | | +------------------------ expected result sequence
+ // | | |
+ // | | |
+ // V V V
+ TEST ("ab", 2, "ab"),
+
+ TEST ("", 0, ""),
+ TEST ("\0", 1, "\0"),
+
+ TEST ("a", 1, "a"),
+ TEST ("bcd", 3, "bcd"),
+ TEST ("cdefaihjb", 9, "cdefaihjb"),
+
+ TEST ("\0\0ab", 1, "\0"),
+ TEST ("\0\0ab", 4, "\0\0ab"),
+ TEST ("a\0\0b", 4, "a\0\0b"),
+ TEST ("ab\0\0", 3, "ab\0"),
+ TEST ("abefdcc\0a", 7, "abefdcc"),
+ TEST ("abefdcc\0a", 8, "abefdcc\0"),
+ TEST ("abefdcc\0a", 9, "abefdcc\0a"),
- rw_info (0, 0, 0, "std::basic_string<%s> constructors signatures", tname);
+ TEST ("x@4096", 4096, "x@4096"),
- // 21.3.1, p2
- String s0 /* (Allocator ()) */;
- String s1 = String (Allocator ());
+ TEST ("last test", 9, "last test")
+};
- // lwg issue #42
- String s2 = String (String ());
+/**************************************************************************/
- // 21.3.1, p3
- String s3 = String (String (), SizeT (), SizeT () /* , Allocator () */);
- String s4 = String (String (), SizeT (), SizeT (), Allocator ());
+// exercises:
+// ctor (const basic_string&, size_type)
+static const TestCase
+str_size_test_cases [] = {
+
+#undef TEST
+#define TEST(arg, off, res, bthrow) { \
+ __LINE__, off, -1, -1, -1, -1, \
+ 0, 0, arg, sizeof arg - 1, \
+ res, sizeof res - 1, bthrow \
+ }
+
+ // +----------------------------------------- source sequence
+ // | +--------------------------- ctor off argument
+ // | | +------------------------ expected result sequence
+ // | | | +--------- exception info
+ // | | | | 0 - no exception
+ // | | | | 1 - out_of_range
+ // | | | |
+ // | | | |
+ // V V V V
+ TEST ("ab", 0, "ab", 0),
+
+ TEST ("", 0, "", 0),
+ TEST ("\0", 0, "\0", 0),
+ TEST ("\0\0", 0, "\0\0", 0),
+
+ TEST ("a", 0, "a", 0),
+ TEST ("bcd", 0, "bcd", 0),
+ TEST ("cdefaihjb", 0, "cdefaihjb", 0),
+
+ TEST ("\0\0ab", 0, "\0\0ab", 0),
+ TEST ("a\0\0b", 0, "a\0\0b", 0),
+ TEST ("ab\0\0", 0, "ab\0\0", 0),
+ TEST ("abefdcc\0a", 0, "abefdcc\0a", 0),
- // 21.3.1, p6
- const T c = T ();
- String s5 (&c, 1 /* , Allocator () */);
- String s6 (&c, 1, Allocator ());
+ TEST ("x@4096", 0, "x@4096", 0),
- // 21.3.1, p9
- String s7 (&c /* , Allocator () */);
- String s8 (&c, Allocator ());
+ TEST ("abc", 5, "abc", 1),
+ TEST ("x@4096", 4106, "x@4096", 1),
+
+ TEST ("last test", 0, "last test", 0)
+};
- // 21.3.1, p12
- String s9 = String (SizeT (), c /* , Allocator () */);
- String s10 = String (SizeT (), c, Allocator ());
+/**************************************************************************/
- // 21.3.1, p15 - template ctor
+// exercises:
+// ctor (const basic_string&, size_type, size_type)
+// ctor (InputIterator, InputIterator)
+static const TestCase
+str_size_size_test_cases [] = {
+
+#define range_test_cases str_size_size_test_cases
+
+#undef TEST
+#define TEST(arg, off, size, res, bthrow) { \
+ __LINE__, off, size, -1, -1, -1, \
+ 0, 0, arg, sizeof arg - 1, \
+ res, sizeof res - 1, bthrow \
+ }
+
+ // +----------------------------------------- source sequence
+ // | +--------------------------- ctor off argument
+ // | | +----------------------- ctor n argument
+ // | | | +-------------------- expected result sequence
+ // | | | | +----- exception info
+ // | | | | | 0 - no exception
+ // | | | | | 1 - out_of_range
+ // | | | | |
+ // | | | | |
+ // V V V V V
+ TEST ("ab", 0, 2, "ab", 0),
+
+ TEST ("", 0, 0, "", 0),
+ TEST ("\0", 0, 1, "\0", 0),
+ TEST ("\0\0", 0, 2, "\0\0", 0),
+
+ TEST ("a", 0, 1, "a", 0),
+ TEST ("bcd", 0, 3, "bcd", 0),
+ TEST ("cdefaihjb", 0, 9, "cdefaihjb", 0),
+
+ TEST ("\0\0ab", 0, 4, "\0\0ab", 0),
+ TEST ("a\0\0b", 0, 4, "a\0\0b", 0),
+ TEST ("ab\0\0", 0, 4, "ab\0\0", 0),
+ TEST ("abefdcc\0a", 0, 9, "abefdcc\0a", 0),
- // check basic_string::const_pointer
- String s11 = String ((const T*)0, (const T*)0 /* , Allocator () */);
- String s12 = String ((const T*)0, (const T*)0, Allocator ());
+ TEST ("x@4096", 0, 4096, "x@4096", 0),
- _RWSTD_UNUSED (s0); _RWSTD_UNUSED (s1); _RWSTD_UNUSED (s2);
- _RWSTD_UNUSED (s3); _RWSTD_UNUSED (s4); _RWSTD_UNUSED (s5);
- _RWSTD_UNUSED (s6); _RWSTD_UNUSED (s7); _RWSTD_UNUSED (s8);
- _RWSTD_UNUSED (s9); _RWSTD_UNUSED (s10); _RWSTD_UNUSED (s11);
- _RWSTD_UNUSED (s12);
+ TEST ("abc", 5, 3, "abc", 1),
+ TEST ("x@4096", 4106, 3, "xxx", 1),
-#ifndef _RWSTD_NO_INLINE_MEMBER_TEMPLATES
-# if _MSC_VER >= 1300 // MSVC 6.0 and prior are too dumb to handle this
+ TEST ("last test", 0, 9, "last test", 0)
+};
- // check a pointer other than basic_string::const_pointer
- String s13 = String ((const int*)0, (const int*)0 /* , Allocator () */);
- String s14 = String ((const int*)0, (const int*)0, Allocator ());
+/**************************************************************************/
- // check integral types
- String s15 = String (true, false /* , Allocator () */);
- String s16 = String (true, false, Allocator ());
- String s17 = String (2, 1 /* , Allocator () */);
- String s18 = String (2, 1, Allocator ());
- String s19 = String (2L, 1L /* , Allocator () */);
- String s20 = String (2L, 1L, Allocator ());
+// exercises:
+// ctor (size_type, value_type)
+static const TestCase
+size_val_test_cases [] = {
+
+#undef TEST
+#define TEST(size, val, res) { \
+ __LINE__, -1, size, -1, -1, val, \
+ 0, 0, 0, 0, \
+ res, sizeof res - 1, 0 \
+ }
+
+ // +---------------------------------------- ctor n argument
+ // | +----------------------------- source value
+ // | | +------------------------ expected result sequence
+ // | | |
+ // | | |
+ // V V V
+ TEST (1, 'a', "a"),
+ TEST (1, '\0', "\0"),
+
+ TEST (2, 'a', "aa"),
+ TEST (2, '\0', "\0\0"),
- _RWSTD_UNUSED (s13); _RWSTD_UNUSED (s14); _RWSTD_UNUSED (s15);
- _RWSTD_UNUSED (s16); _RWSTD_UNUSED (s17); _RWSTD_UNUSED (s18);
- _RWSTD_UNUSED (s19); _RWSTD_UNUSED (s20);
+ TEST (5, '\0', "\0\0\0\0\0"),
+ TEST (10, 'a', "aaaaaaaaaa"),
-# endif // MSVC > 6.0
-#endif // _RWSTD_NO_INLINE_MEMBER_TEMPLATES
+ TEST (4096, 'x', "x@4096"),
-}
+ TEST (4, 't', "tttt")
+};
/**************************************************************************/
+// exercises:
+// operator= (const value_type*)
+static const TestCase
+op_set_ptr_test_cases [] = {
+
+#undef TEST
+#define TEST(str, arg, res, bthrow) { \
+ __LINE__, -1, -1, -1, -1, -1, \
+ str, sizeof str - 1, arg, sizeof arg - 1, \
+ res, sizeof res - 1, bthrow \
+ }
+
+ // +----------------------------------------- source sequence
+ // | +------------------------------ argument sequence
+ // | | +----------------- expected result sequence
+ // | | | +-- exception info
+ // | | | | 0 - no exception
+ // | | | | -1 - excpetion safety
+ // | | | |
+ // | | | |
+ // V V V V
+ TEST ("", "ab", "ab", 0),
+
+ TEST ("", "", "", 0),
+ TEST ("abc", "", "", 0),
+ TEST ("", "\0", "", 0),
+ TEST ("abc", "\0", "", 0),
+
+ TEST ("", "a", "a", 0),
+ TEST ("\0\0", "a", "a", 0),
+ TEST ("a", "bcd", "bcd", 0),
+ TEST ("x@4096", "bcd", "bcd", 0),
+ TEST ("", "cdefaihjb", "cdefaihjb", 0),
+ TEST ("a\0b", "cdefaihjb", "cdefaihjb", 0),
+
+ TEST ("", "\0\0ab", "", 0),
+ TEST ("c\0d", "\0\0ab", "", 0),
+ TEST ("", "a\0\0b", "a", 0),
+ TEST ("bcd", "a\0\0b", "a", 0),
+ TEST ("\0", "ab\0\0", "ab", 0),
+ TEST ("x@4096", "ab\0\0", "ab", 0),
+ TEST ("\0a", "abefdcc\0a", "abefdcc", 0),
+ TEST ("x@4096", "abefdcc\0a", "abefdcc", 0),
+
+ TEST ("abc", "x@4096", "x@4096", 0),
+
+ TEST ("", 0, "", 0),
+ TEST ("a\0b\0", 0, "a", 0),
+ TEST ("x@4096", 0, "x@4096", 0),
-template <class T>
-void test_ctors (T, const char* tname)
-{
- typedef std::char_traits<T> Traits;
- typedef std::allocator<T> Allocator;
- typedef std::basic_string<T, Traits, Allocator> String;
+ TEST ("abcd", "x@4096", "x@4096", -1),
- typedef typename String::size_type SizeT;
+ TEST ("", "last test", "last test", 0)
+};
- static const char* const sname = "basic_string";
+/**************************************************************************/
+// exercises:
+// operator= (const basic_string&)
+static const TestCase
+op_set_str_test_cases [] = {
+
+#undef TEST
+#define TEST(str, arg, res, bthrow) { \
+ __LINE__, -1, -1, -1, -1, -1, \
+ str, sizeof str - 1, arg, sizeof arg - 1, \
+ res, sizeof res - 1, bthrow \
+ }
+
+ // +----------------------------------------- source sequence
+ // | +------------------------------ argument sequence
+ // | | +----------------- expected result sequence
+ // | | | +-- exception info
+ // | | | | 0 - no exception
+ // | | | | -1 - excpetion safety
+ // | | | |
+ // | | | |
+ // V V V V
+ TEST ("", "ab", "ab", 0),
+
+ TEST ("", "", "", 0),
+ TEST ("abc", "", "", 0),
+ TEST ("", "\0", "\0", 0),
+ TEST ("abc", "\0", "\0", 0),
+
+ TEST ("", "a", "a", 0),
+ TEST ("\0\0", "a", "a", 0),
+ TEST ("a", "bcd", "bcd", 0),
+ TEST ("x@4096", "bcd", "bcd", 0),
+ TEST ("", "cdefaihjb", "cdefaihjb", 0),
+ TEST ("a\0b", "cdefaihjb", "cdefaihjb", 0),
+
+ TEST ("", "\0\0ab", "\0\0ab", 0),
+ TEST ("c\0d", "\0\0ab", "\0\0ab", 0),
+ TEST ("", "a\0\0b", "a\0\0b", 0),
+ TEST ("bcd", "a\0\0b", "a\0\0b", 0),
+ TEST ("\0", "ab\0\0", "ab\0\0", 0),
+ TEST ("x@4096", "ab\0\0", "ab\0\0", 0),
+ TEST ("\0a", "abefdcc\0a", "abefdcc\0a", 0),
+ TEST ("x@4096", "abefdcc\0a", "abefdcc\0a", 0),
+
+ TEST ("abc", "x@4096", "x@4096", 0),
+
+ TEST ("", 0, "", 0),
+ TEST ("a\0b\0", 0, "a\0b\0", 0),
+ TEST ("x@4096", 0, "x@4096", 0),
- SizeT nbytes = 0;
- SizeT nblocks = 0;
+ TEST ("", "last test", "last test", 0)
+};
- // establish a checkpoint for memory leaks
- rwt_check_leaks (0, 0);
- //////////////////////////////////////////////////////////////
- if (rw_opt_no_def_ctor) {
- rw_note (0, 0, 0, "std::%s<%s>::%1$s (const %s&) test disabled",
- sname, tname, "allocator_type");
- }
- else {
- rw_info (0, 0, 0, "std::%s<%s>::%1$s (const allocator_type&)",
- sname, tname);
-
- // 21.3.1, p2 - create an empty string
- const String s0;
-
- // 21.3.1, p2 - effects table, row 1
- rw_assert (0 != s0.data (), 0, __LINE__,
- "%s<%s>::%1$s ().data () != 0", sname, tname);
-
- // 21.3.1, p2 - effects table, row 2
- rw_assert (0 == s0.size (), 0, __LINE__,
- "%s<%s>::%1$s().size () == 0", sname, tname);
-
- // 21.3.1, p2 - effects table, row 3
- rw_assert (s0.size () <= s0.capacity (), 0, __LINE__,
- "%s<%s>::%1$s(const char_type*).capacity() >= %zu, got %zu",
- sname, tname, s0.size (), s0.capacity ());
-
- rw_assert (0 != s0.c_str (), 0, __LINE__,
- "%s<%s>().c_str () != 0", sname, tname);
-
- rw_assert (Traits::eq (*s0.c_str(), T ()), 0, __LINE__,
- "%s<%s>().c_str ()[0] == '\\0'", sname, tname);
- }
-
- nblocks = rwt_check_leaks (&nbytes, 0);
-
- rw_assert (!nblocks && !nbytes, 0, __LINE__,
- "%s<%s>() leaked %zu bytes in %zu block(s)",
- sname, tname, nbytes, nblocks);
-
-
- //////////////////////////////////////////////////////////////
- if (rw_opt_no_ptr_ctor) {
- rw_note (0, 0, 0,
- "std::%s<%s>::%1$s (const_pointer %s&) test disabled",
- sname, tname);
- }
- else {
- rw_info (0, 0, 0, "std::%s<%s>::%1$s (const_pointer)", sname, tname);
-
- const T ca [] = { '\0' };
-
- // 21.3.1, p9 - create an empty string using a (non-null) pointer
- const String s0 (ca + 0);
-
- // 21.3.1, p10 - effects table, row 1
- rw_assert (0 != s0.data (), 0, __LINE__,
- "%s<%s>::%1$s(const_pointer = %{*Ac}).data() != 0",
- sname, tname, int (sizeof *ca), ca);
-
- // 21.3.1, p10 - effects table, row 2
- rw_assert (Traits::length (ca) == s0.size (), 0, __LINE__,
- "%s<%s>::%1$s(const_pointer = %{*Ac}).size() "
- "== 0, got %zu",
- sname, tname, int (sizeof *ca), ca, s0.size ());
-
- // 21.3.1, p10 - effects table, row 3
- rw_assert (s0.size () <= s0.capacity (), 0, __LINE__,
- "%s<%s>::%1$s(const_pointer= %{*Ac}).capacity() "
- ">= %zu, got %zu",
- sname, tname, int (sizeof *ca), ca,
- s0.size (), s0.capacity ());
-
- rw_assert (0 != s0.c_str (), 0, __LINE__,
- "%s<%s>::%1$s(const_pointer = %{*Ac}).c_str () != 0",
- sname, tname, int (sizeof *ca), ca);
-
- rw_assert (Traits::eq (*s0.c_str(), T ()), 0, __LINE__,
- "%s<%s>::%1$s(const_pointer = %{*Ac})"
- ".c_str()[0] == '\\0'",
- sname, tname, int (sizeof *ca), ca);
- }
-
- nblocks = rwt_check_leaks (&nbytes, 0);
-
- rw_assert (!nblocks && !nbytes, 0, __LINE__,
- "%s<%s>(\"\") leaked %d bytes in %d block(s)",
- sname, tname, nbytes, nblocks);
+/**************************************************************************/
-#ifndef _RWSTD_NO_EXCEPTIONS
+// exercises:
+// operator= (value_type)
+static const TestCase
+op_set_val_test_cases [] = {
+
+#undef TEST
+#define TEST(str, val, res) { \
+ __LINE__, -1, -1, -1, -1, val, \
+ str, sizeof str - 1, 0, 0, \
+ res, sizeof res - 1, 0 \
+ }
+
+ // +----------------------------------- initial sequence
+ // | +------------------------ source value
+ // | | +------------------- expected result sequence
+ // | | |
+ // | | |
+ // V V V
+ TEST ("", 'a', "a"),
+ TEST ("abcdef", 'a', "a"),
+ TEST ("", '\0', "\0"),
+ TEST ("a", '\0', "\0"),
+ TEST ("\0\0", 'x', "x"),
+ TEST ("x@4096", 'x', "x"),
+ TEST ("", 't', "t")
+};
- //////////////////////////////////////////////////////////////
- if (rw_opt_no_fill_ctor) {
- rw_note (0, 0, 0,
- "std::%s<%s>::%1$s (size_type, value_type) test disabled",
- sname, tname);
- }
- else {
- rw_info (0, 0, 0,
- "std::%s<%s>::%1$s (size_type, value_type)", sname, tname);
- bool thrown = false;
-
- try {
- String ts (String::npos, Lit<T>::space[0]);
- }
- catch (std::length_error) {
- thrown = true;
- }
- catch (...) {
- }
-
- rw_assert (thrown, 0, __LINE__,
- "%s<%s>::%1$s (size_type = %zu, char_type = %#lc) "
- "threw std::length_error",
- sname, tname, String::npos, Lit<T>::space[0]);
- }
+/**************************************************************************/
- nblocks = rwt_check_leaks (&nbytes, 0);
-
- rw_assert (!nblocks && !nbytes, 0, __LINE__,
- "%s<%s>(size_type, char_type) leaked %d bytes "
- "in %d block(s) after an exception",
- sname, tname, nbytes, nblocks);
+template <class charT, class Traits, class Iterator>
+void test_ctor_range (const charT* warg,
+ std::size_t warg_len,
+ std::size_t res_len,
+ Traits*,
+ const Iterator &it,
+ const TestCase &tcase)
+{
+ typedef std::allocator<charT> Allocator;
+ typedef std::basic_string <charT, Traits, Allocator> String;
+ typedef typename String::iterator StringIter;
-#endif // _RWSTD_NO_EXCEPTIONS
+ const char* const itname =
+ tcase.arg ? type_name (it, (charT*)0) : "basic_string::iterator";
- {
- const SizeT siz = 120;
-
- const String ts (siz, Lit<T>::space[0] );
+ /*const*/ String s_arg (warg, warg_len);
- // Length set to siz when reserving
- rw_assert ( (ts.length() == siz), 0, __LINE__, "C9");
-
- // Allocated size at least as large as requested
- rw_assert ( (ts.capacity() >= siz), 0, __LINE__, "C10");
- }
+ std::size_t off_last = tcase.off + tcase.size;
- nblocks = rwt_check_leaks (&nbytes, 0);
+ const StringIter it_first (std::size_t (tcase.off) >= s_arg.size () ?
+ s_arg.end () : s_arg.begin () + tcase.off);
+ const StringIter it_last (std::size_t (off_last) >= s_arg.size () ?
+ s_arg.end () : s_arg.begin () + off_last);
- rw_assert (!nblocks && !nbytes, 0, __LINE__,
- "%s<%s>(size_type, char_type) leaked %d bytes "
- "in %d block(s)", sname, tname, nbytes, nblocks);
+ const String s_str (it_first, it_last);
- //////////////////////////////////////////////////////////////
- if (rw_opt_no_copy_ctor) {
- rw_note (0, 0, 0, "%s<%s>::%1$s (const %1$&) test disabled",
- sname, tname);
- }
- else {
- rw_info (0, 0, 0, "std::%s<%s>::%1$s (const %1$s&)", sname, tname);
+ const std::size_t match =
+ rw_match (tcase.res, s_str.c_str(), tcase.nres);
+
+ rw_assert (match == res_len, 0, tcase.line,
+ "line %d. %{$FUNCALL} expected %{#*s}, got %{/*.*Gs}, "
+ "difference at offset %zu for %s",
+ __LINE__, int (tcase.nres), tcase.res,
+ int (sizeof (charT)), int (s_str.size ()), s_str.c_str (),
+ match, itname);
+}
- const String s1 (Lit<T>::aString);
- const String s2 (s1);
+/**************************************************************************/
-#ifndef _RWSTD_NO_STRING_REF_COUNT
+template <class charT, class Traits>
+void test_ctor_range (const charT* warg,
+ std::size_t warg_len,
+ std::size_t res_len,
+ Traits*,
+ const TestCase &tcase)
+{
+ if (tcase.bthrow) // this method doesn't throw
+ return;
- // verify that the two strings share the same data
- rw_assert (s1.data () == s2.data (), 0, __LINE__,
- "s1.data () == s2.data (); strings NOT reference counted");
+ test_ctor_range (warg, warg_len, res_len, (Traits*)0,
+ InputIter<charT>(0, 0, 0), tcase);
-#else // if defined (_RWSTD_NO_STRING_REF_COUNT)
+ test_ctor_range (warg, warg_len, res_len, (Traits*)0,
+ ConstFwdIter<charT>(0, 0, 0), tcase);
- // verify that the two strings share the same data
- rw_assert (s1.data () != s2.data (), 0, __LINE__,
- "s1.data () != s2.data (); strings reference counted");
+ test_ctor_range (warg, warg_len, res_len, (Traits*)0,
+ ConstBidirIter<charT>(0, 0, 0), tcase);
-#endif // _RWSTD_NO_STRING_REF_COUNT
+ test_ctor_range (warg, warg_len, res_len, (Traits*)0,
+ ConstRandomAccessIter<charT>(0, 0, 0), tcase);
+}
- // 21.3.1, p5 - effects table, row 1
- rw_assert (&s2 [0] == s2.data (), 0, __LINE__,
- "%s<%s>::%1$s(const %1$s&)", sname, tname);
+/**************************************************************************/
- // 21.3.1, p5 - effects table, row 2
- rw_assert (s1.size () == s2.size (), 0, __LINE__,
- "%s<%s>::%1$s(const %1$s&).size () == %zu, got %zu",
- sname, tname, s1.size (), s2.size ());
+template <class charT, class Traits>
+void test_ctor (charT, Traits*,
+ OverloadId which,
+ const TestCase &tcase)
+{
+ typedef std::allocator<charT> Allocator;
+ typedef std::basic_string <charT, Traits, Allocator> String;
- // 21.3.1, p5 - effects table, row 3
- rw_assert (s2.size () <= s2.capacity (), 0, __LINE__,
- "%s<%s>::%1$s(%1$s&).capacity () >= %zu, got %zu",
- sname, tname, s2.size (), s2.capacity ());
+ static const std::size_t BUFSIZE = 256;
- // verify that both strings are the same
- rw_assert (s2 == s1
- && 0 == Traits::compare (s1.data (), s2.data (), s1.size ()),
- 0, __LINE__,
- "std::operator==(const %s<%s>&, const %1$s<%2$s>&)",
- sname, tname);
- }
+ static charT warg_buf [BUFSIZE];
+ std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf;
+ charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len);
- nblocks = rwt_check_leaks (&nbytes, 0);
+ static charT wres_buf [BUFSIZE];
+ std::size_t res_len = sizeof wres_buf / sizeof *wres_buf;
+ charT* wres = rw_expand (wres_buf, tcase.res, tcase.nres, &res_len);
- rw_assert (!nblocks && !nbytes, 0, __LINE__,
- "%s<%s>(const %1$s&) leaked %d bytes in %d block(s)",
- sname, tname, nbytes, nblocks);
+ // special processing for ctor_range to exercise all iterators
+ if (Ctor (range) == which) {
+ test_ctor_range (warg, arg_len, res_len, (Traits*)0, tcase);
- if (!rw_opt_no_copy_ctor) {
- String s1;
- String s2(s1);
-
- // Empty copies have same lengths
- rw_assert((s1.length() == s2.length()), 0, __LINE__, "C19");
+ if (warg != warg_buf)
+ delete[] warg;
- // Empty copies compare equal
- rw_assert ( (s1.compare(s2) == 0), 0, __LINE__, "C16");
-
- // Empty copies return same data string.
- rw_assert (!Traits::compare (s1.data (), s2.data (), s1.size ()),
- 0, __LINE__, "C17");
+ if (wres != wres_buf)
+ delete[] wres;
- // Empty copies return same c_str string.
- rw_assert (!Traits::compare (s1.c_str (), s2.c_str (), s1.size()),
- 0, __LINE__, "C18");
+ return;
}
- nblocks = rwt_check_leaks (&nbytes, 0);
+ // construct the string object to be modified
+ // and the (possibly unused) argument string
+ const String arg (warg, arg_len);
+ if (warg != warg_buf)
+ delete[] warg;
+
+ warg = 0;
+
+ // offset and extent function arguments
+ const std::size_t arg_off = std::size_t (tcase.off);
+ const std::size_t arg_size = std::size_t (tcase.size);
- rw_assert (!nblocks && !nbytes, 0, __LINE__,
- "%s<%s>(const basic_string&) leaked %d bytes "
- "in %d block(s)", tname, nbytes, nblocks);
+ // string function argument
+ const charT* const arg_ptr = arg.c_str ();
+ const String& arg_str = arg;
+ const charT arg_val = make_char (char (tcase.val), (charT*)0);
+ // (name of) expected and caught exception
+ const char* expected = 0;
+ const char* caught = 0;
#ifndef _RWSTD_NO_EXCEPTIONS
- { //////////////////////////////////////////////////////////////
- rw_info (0, 0, 0, "std::%s<%s>::%1$s (const %1$s&, size_type)",
- sname, tname);
-
- bool thrown = false;
- String t1( Lit<T>::abcdef );
+ if (1 == tcase.bthrow)
+ expected = exceptions [1]; // out_of_range
+ else if (2 == tcase.bthrow)
+ expected = exceptions [2]; // length_error
+
+#else // if defined (_RWSTD_NO_EXCEPTIONS)
+
+ if (tcase.bthrow) {
+ if (wres != wres_buf)
+ delete[] wres;
- try {
- String t2(t1, 7);
+ return;
+ }
+
+#endif // _RWSTD_NO_EXCEPTIONS
+
+ // pointer to the returned reference
+ String* ret_ptr = 0;
+
+ // start checking for memory leaks
+ rwt_check_leaks (0, 0);
+
+ try {
+ switch (which) {
+ case Ctor (void): {
+ ret_ptr = new String ();
+ break;
}
- catch (std::out_of_range) {
- thrown = true;
+ case Ctor (ptr): {
+ ret_ptr = new String (arg_ptr);
+ break;
}
- catch (...) {
+ case Ctor (str): {
+ ret_ptr = new String (arg_str);
+ break;
+ }
+ case Ctor (ptr_size): {
+ ret_ptr = new String (arg_ptr, arg_size);
+ break;
+ }
+ case Ctor (str_size): {
+ ret_ptr = new String (arg_str, arg_off);
+ break;
+ }
+ case Ctor (str_size_size): {
+ ret_ptr = new String (arg_str, arg_off, arg_size);
+ break;
+ }
+ case Ctor (size_val): {
+ ret_ptr = new String (tcase.size, arg_val);
+ break;
}
-
- // Threw exception when pos exceeded length of str
- rw_assert ( ( thrown==true ) , 0, __LINE__, "C20");
- }
-#endif // _RWSTD_NO_EXCEPTIONS
+ default:
+ RW_ASSERT (!"logic error: unknown constructor overload");
+ }
+
+ // verify that returned pointer is valid
+ rw_assert (0 != ret_ptr, 0, tcase.line,
+ "line %d. %{$FUNCALL} expected %{#*s}, got null",
+ __LINE__, int (res_len), tcase.res);
+
+ if (0 != ret_ptr) {
+ // verify the length of the resulting string
+ rw_assert (res_len == ret_ptr->size (), 0, tcase.line,
+ "line %d. %{$FUNCALL} expected %{#*s} with length "
+ "%zu, got %{/*.*Gs} with length %zu",
+ __LINE__, int (res_len), tcase.res,
+ res_len, int (sizeof (charT)),
+ int (ret_ptr->size ()), ret_ptr->c_str (),
+ ret_ptr->size ());
+
+ if (Ctor (void) != which) {
+ // verify the capacity of the resulting string
+ rw_assert (ret_ptr->size () <= ret_ptr->capacity (), 0,
+ tcase.line, "line %d. %{$FUNCALL} expected "
+ "capacity () >= size (), got capacity () == "
+ "%zu, size () == %zu", __LINE__,
+ ret_ptr->capacity (), ret_ptr->size ());
+ }
+
+ if (res_len == ret_ptr->size ()) {
+ // if the result length matches the expected length
+ // (and only then), also verify that the modified
+ // string matches the expected result
+ const std::size_t match =
+ rw_match (tcase.res, ret_ptr->c_str (), tcase.nres);
+
+ rw_assert (match == res_len, 0, tcase.line,
+ "line %d. %{$FUNCALL} expected %{/*.*Gs}, "
+ "got %{/*.*Gs}, difference at offset %zu",
+ __LINE__, int (sizeof (charT)), int (res_len),
+ wres, int (sizeof (charT)),
+ int (ret_ptr->size ()), ret_ptr->c_str (),
+ match);
+ }
- {
- String t1( Lit<T>::abcdef );
- String t2(t1, 6);
-
- // Correct single character beyond end value
- rw_assert ( t2 == Lit<T>::null, 0, __LINE__, "C21");
-
- // Correctly references nullRef
- rw_assert ( t2.data() == String ().data(), 0, __LINE__, "C22");
-
- // Correct single character beyond end length
- rw_assert ( (t2.length() == 0), 0, __LINE__, "C23");
- }
- {
- String t1( Lit<T>::abcdef );
- String t2(t1, 5);
-
- // Correct single character at end value
- rw_assert ( (t2 == Lit<T>::f), 0, __LINE__, "C24");
-
- // Correct single character at end length
- rw_assert ( (t2.length() == 1), 0, __LINE__, "C25");
- }
- {
- String t1( Lit<T>::abcdef );
- String t2(t1, 4);
-
- // Correct last two characters value
- rw_assert ( (t2 == Lit<T>::ef), 0, __LINE__, "C26");
-
- // Correct last two characters length
- rw_assert ( (t2.length() == 2), 0, __LINE__, "C27");
- }
- {
- String t1( Lit<T>::abcdef );
- String t2(t1, 0);
-
- // Correct entire String value
- rw_assert ( (t2 == t1), 0, __LINE__, "C28");
-
- // Correct entire String length
- rw_assert ( (t2.length() == t1.length()), 0, __LINE__, "C29");
- }
- {
- String t1( Lit<T>::abcdef );
- String t2(t1, 0, 0);
-
- // Correct zero-length string off front value
- rw_assert ( t2 == Lit<T>::null, 0, __LINE__, "C30");
-
- // Correctly references nullRef
- rw_assert ( t2.data () == String ().data (), 0, __LINE__, "C31");
-
- // Correct zero-length string off front length
- rw_assert ( (t2.length() == 0), 0, __LINE__, "C32");
- }
- {
- String t1( Lit<T>::abcdef );
- String t2(t1, 0, 1);
-
- // Correct one character off front value
- rw_assert ( (t2 == Lit<T>::a), 0, __LINE__, "C33");
-
- // Correct one character off front length
- rw_assert ( (t2.length() == 1), 0, __LINE__, "C34");
- }
- {
- String t1( Lit<T>::abcdef );
- String t2(t1, 2, 2);
-
- // Correct subString from middle value
- rw_assert ( (t2 == Lit<T>::cd), 0, __LINE__, "C35");
-
- // Correct subString from middle length
- rw_assert ( (t2.length() == 2), 0, __LINE__, "C36");
- }
- {
- rw_info (0, 0, 0, "std::%s<%s>::%1$s (const_pointer, size_type)",
- sname, tname);
-
- String t1( Lit<T>::abcdefg, (SizeT)0);
- String t2( Lit<T>::abcdefg, 1 );
- String t3( Lit<T>::abcdefg, 3 );
- String t4( Lit<T>::abcnulldefg, 8 ); //Embedded null
-
- // Correct value when n is zero
- rw_assert ( t1 == Lit<T>::null, 0, __LINE__, "C37");
-
- // Correctly references nullRef when n is zero
- rw_assert ( t1.data () == String ().data (), 0, __LINE__, "C38");
-
- // Correct value when n is one
- rw_assert ( (t2 == Lit<T>::a), 0, __LINE__, "C39");
-
- // Correct value when n is three
- rw_assert ( (t3 == Lit<T>::abc), 0, __LINE__, "C40");
-
- // Correct value with embedded null
- rw_assert (!std::memcmp(t4.c_str(), Lit<T>::abcnulldefg, 8),
- 0, __LINE__, "C41");
-
- // Lengths are n that was passed in
- rw_assert (((t1.length()==0)&&(t2.length()==1) &&
- (t3.length()==3)&&(t4.length()==8)),
- 0, __LINE__, "C42");
- }
-
- if (!rw_opt_no_ptr_ctor) {
- rw_info (0, 0, 0, "std::%s<%s>::"
- "basic_string (const_pointer)", tname);
-
- String t1( Lit<T>::abcdefg );
- String t2( Lit<T>::abcnulldefg );
-
- // Correct value with normal string
- rw_assert ( (t1 == Lit<T>::abcdefg), 0, __LINE__, "C43");
-
- // Correct value with _EXPLICIT embedded null
- rw_assert ( (t2 == Lit<T>::abc), 0, __LINE__, "C44");
-
- // Lengths are n that was passed in
- rw_assert ( ((t1.length() == 7) && (t2.length() == 3)),
- 0, __LINE__, "C45");
+ delete ret_ptr;
+ }
}
#ifndef _RWSTD_NO_EXCEPTIONS
- {
- rw_info (0, 0, 0, "std::%s<%s>::%1$s (size_type, char_type)",
- sname, tname);
-
- bool thrown = false;
-
- try { String ts(String::npos, Lit<T>::a[0] ); }
- catch (std::length_error) { thrown = true; }
-
- rw_assert ( (thrown==true), 0, __LINE__, "C46");
- }
-#endif
-
- {
- String t1( (SizeT)0, Lit<T>::b[0] );
- String t2( (SizeT)1, Lit<T>::c[0] );
- String t3( (SizeT)5, Lit<T>::d[0] );
-
- // Correct value for no repetitions
- rw_assert ( (t1 == Lit<T>::null), 0, __LINE__, "C47");
-
- // Correctly references nullRef when no reps
- rw_assert ( t1.data () == String ().data (), 0, __LINE__, "C48");
-
- // Correct value for default repetitions
- rw_assert ( (t2 == Lit<T>::c ), 0, __LINE__, "C49");
-
- // Correct value for five repetitions
- rw_assert ( (t3 == Lit<T>::ddddd), 0, __LINE__, "C50");
-
- // Correct lengths for all
- rw_assert (((t1.length() == 0) && (t2.length() == 1) &&
- (t3.length() == 5) ), 0, __LINE__, "C51");
- }
-
- {
- // extension (for compilers with no member templates)
- rw_info (0, 0, 0, "std::%s<%s>::%1$s(const_pointer, const_pointer)",
- sname, tname);
-
- const T ca [] = { 'a', 'b', 'c', 'd', 'e', 'f', '\0' };
-
- SizeT size = sizeof ca / sizeof *ca;
-
- // 21.3.1, p16 - construct a string using two pointers
- const String s1 (ca, ca + 0);
-
- // verify that the constructed string is empty
- rw_assert (s1.size () == 0, 0, __LINE__,
- "%s (const_pointer, const_pointer).size ()"
- " == 0, got %zu", sname, s1.size ());
-
- rw_assert (s1.data () == String ().data (), 0, __LINE__,
- "%s (const_pointer, const_pointer).data () == "
- "%1$s().data ()", sname);
-
- const String s2 (ca, ca + size);
-
- // verify that both strings are the same
- rw_assert (s2.size () == size, 0, __LINE__,
- "%s (const_pointer, const_pointer).size ()"
- " == %zu, got %zu", sname, size, s2.size ());
- rw_assert (0 == Traits::compare (s2.data (), ca, s2.size ()),
- 0, __LINE__, "%s (const_pointer, const_pointer)", sname);
+ catch (const std::out_of_range &ex) {
+ caught = exceptions [1];
+ rw_assert (caught == expected, 0, tcase.line,
+ "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
+ "unexpectedly%{;} caught std::%s(%#s)",
+ __LINE__, 0 != expected, expected, caught, ex.what ());
+ }
+ catch (const std::length_error &ex) {
+ caught = exceptions [2];
+ rw_assert (caught == expected, 0, tcase.line,
+ "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
+ "unexpectedly%{;} caught std::%s(%#s)",
+ __LINE__, 0 != expected, expected, caught, ex.what ());
+ }
+ catch (const std::bad_alloc &ex) {
+ caught = exceptions [3];
+ rw_assert (-1 == tcase.bthrow, 0, tcase.line,
+ "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
+ "unexpectedly%{;} caught std::%s(%#s)",
+ __LINE__, 0 != expected, expected, caught, ex.what ());
+ }
+ catch (const std::exception &ex) {
+ caught = exceptions [4];
+ rw_assert (0, 0, tcase.line,
+ "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
+ "unexpectedly%{;} caught std::%s(%#s)",
+ __LINE__, 0 != expected, expected, caught, ex.what ());
+ }
+ catch (...) {
+ caught = exceptions [0];
+ rw_assert (0, 0, tcase.line,
+ "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
+ "unexpectedly%{;} caught %s",
+ __LINE__, 0 != expected, expected, caught);
}
-#ifndef _RWSTD_NO_INLINE_MEMBER_TEMPLATES
-# if !defined (_MSC_VER) || _MSC_VER >= 1300
-
- //////////////////////////////////////////////////////////////
- if (rw_opt_no_fill_ctor) {
- rw_note (0, 0, 0, "template <class %s> "
- "std::%s<%s>::%2$s (%1$s, %1$s) test disabled",
- "InputIterator", "basic_string", sname, tname);
- }
- else {
- rw_info (0, 0, 0, "template <class %s> "
- "std::%s<%s>::%2$s (%1$s, %1$s)",
- "InputIterator", "basic_string", sname, tname);
+#endif // _RWSTD_NO_EXCEPTIONS
+
+ /* const */ std::size_t nbytes;
+ const std::size_t nblocks = rwt_check_leaks (&nbytes, 0);
+
+ // FIXME: verify the number of blocks the function call
+ // is expected to allocate and detect any memory leaks
+ const std::size_t expect_blocks = nblocks;
+
+ rw_assert (nblocks == expect_blocks, 0, tcase.line,
+ "line %d. %{$FUNCALL} allocated %td bytes in %td blocks",
+ __LINE__, nbytes, expect_blocks);
- const T ca [] = { 'a', 'b', 'c', 'd', 'e', 'f', '\0' };
- const int ia [] = { 'a', 'b', 'c', 'd', 'e', 'f', '\0' };
+ if (wres != wres_buf)
+ delete[] wres;
+}
- SizeT size = sizeof ia / sizeof *ia;
+/**************************************************************************/
- // 21.3.1, p16 - construct a string using two InputIterators
- const String s1 =
- String (InputIter<int>(ia, ia, ia + size),
- InputIter<int>(ia + size, ia + size, ia + size));
+template <class charT, class Traits>
+void test_op_set (charT, Traits*,
+ OverloadId which,
+ const TestCase &tcase)
+{
+ typedef std::allocator<charT> Allocator;
+ typedef std::basic_string <charT, Traits, Allocator> String;
+ typedef typename UserTraits<charT>::MemFun UTMemFun;
- // verify that both strings are the same
- rw_assert (s1.size () == size, 0, __LINE__,
- "%s (InputIterator, InputIterator).size ()"
- " == %zu, got %zu", sname, size, s1.size ());
+ static const std::size_t BUFSIZE = 256;
- // verify that both strings are the same
- rw_assert (0 == Traits::compare (s1.data (), ca, s1.size ()),
- 0, __LINE__,
- "%s (InputIterator, InputIterator)", sname);
+ static charT wstr_buf [BUFSIZE];
+ static charT warg_buf [BUFSIZE];
- const T ca2 [] = { 'a', 'a', 'a', 'a', 'a', 'a', '\0' };
+ std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
+ std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf;
- // 21.3.1, p15 - construct a string using a template ctor
- // with InputIterator being an integral type
- const String s2 = String (6, int (ca2 [0]));
+ charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
+ charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len);
- // effects: same as basic_string (size_type (begin) size_type (end))
- rw_assert (s2.size () == 6, 0, __LINE__,
- "%s (InputIterator, InputIterator).size ()"
- " == %zu, got %zu", sname, 6, s1.size ());
+ // construct the string object to be modified
+ // and the (possibly unused) argument string
+ /* const */ String str (wstr, str_len);
+ const String arg (warg, arg_len);
- // verify that both strings are the same
- rw_assert (0 == Traits::compare (s2.data (), ca2, s2.size ()),
- 0, __LINE__,
- "%s (InputIterator, InputIterator)", sname);
- }
+ if (wstr != wstr_buf)
+ delete[] wstr;
- nblocks = rwt_check_leaks (&nbytes, 0);
+ if (warg != warg_buf)
+ delete[] warg;
- rw_assert (!nblocks && !nbytes, 0, __LINE__,
- "template <class %s> %s::%2$s"
- "(%1$s, %1$s) leaked %d bytes in %d block(s)",
- "InputIterator", tname, sname, nbytes, nblocks);
+ wstr = 0;
+ warg = 0;
-# endif // !MSVC || MSVC > 6.0
-#endif // _RWSTD_NO_INLINE_MEMBER_TEMPLATES
+ static charT wres_buf [BUFSIZE];
+ std::size_t res_len = sizeof wres_buf / sizeof *wres_buf;
+ charT* wres = rw_expand (wres_buf, tcase.res, tcase.nres, &res_len);
+ // save the state of the string object before the call
+ // to detect wxception safety violations (changes to
+ // the state of the object after an exception)
+ const StringState str_state (rw_get_string_state (str));
-#if 0
+ // string function argument
+ const charT* const arg_ptr = tcase.arg ? arg.c_str () : str.c_str ();
+ const String& arg_str = tcase.arg ? arg : str;
+ const charT arg_val = make_char (char (tcase.val), (charT*)0);
- { // FIXME: implement and enable
+ std::size_t total_length_calls = 0;
+ std::size_t n_length_calls = 0;
+ std::size_t* const rg_calls = OpSet (ptr) == which ?
+ rw_get_call_counters ((Traits*)0, (charT*)0) : 0;
- rw_info (0, 0, 0,
- "dynamic allocation, construction, destruction, "
- "and deallocation of string objects across "
- "library boundaries");
+ if (rg_calls)
+ total_length_calls = rg_calls [UTMemFun::length];
- typedef std::allocator<T> Allocator;
- typedef std::basic_string<T, Traits, Allocator> String;
+ rwt_free_store* const pst = rwt_get_free_store (0);
- const T eos = T ();
- const T* const empty = &eos;
- const T non_empty[] = { ' ', '\0' };
+ // iterate for`throw_after' starting at the next call to operator new,
+ // forcing each call to throw an exception, until the function finally
+ // succeeds (i.e, no exception is thrown)
+ std::size_t throw_after;
+ for (throw_after = 0; ; ++throw_after) {
- // exercise the ability to dynamically allocate, construct
- // destroy, and deallocate std::string and std::wstring objects
- // across library boundaries; especially important when strings
- // are reference counted and _RWSTD_NO_COLLAPSE_TEMPLATE_STATICS
- // is #defined
- String *ps = copy_string ((String*)0);
- delete ps;
+ // (name of) expected and caught exception
+ const char* expected = 0;
+ const char* caught = 0;
+
+#ifndef _RWSTD_NO_EXCEPTIONS
+
+ if (-1 == tcase.bthrow) {
+ expected = exceptions [3]; // bad_alloc
+ *pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_after + 1;
+ }
- ps = copy_string (new String ());
- delete ps;
+#else // if defined (_RWSTD_NO_EXCEPTIONS)
- ps = copy_string (new String (empty));
- delete ps;
+ if (tcase.bthrow) {
+ if (wres != wres_buf)
+ delete[] wres;
+
+ return;
+ }
+
+#endif // _RWSTD_NO_EXCEPTIONS
+
+ // start checking for memory leaks
+ rwt_check_leaks (0, 0);
+
+ try {
+ switch (which) {
+ case OpSet (ptr): {
+ str = arg_ptr;
+ break;
+ }
+ case OpSet (str): {
+ str = arg_str;
+ break;
+ }
+ case OpSet (val): {
+ str = arg_val;
+ break;
+ }
+
+ default:
+ RW_ASSERT (!"logic error: unknown operator= overload");
+ }
+
+ // verify the length of the resulting string
+ rw_assert (res_len == str.size (), 0, tcase.line,
+ "line %d. %{$FUNCALL} expected %{#*s} with length "
+ "%zu, got %{/*.*Gs} with length %zu",
+ __LINE__, int (res_len), tcase.res,
+ res_len, int (sizeof (charT)),
+ int (str.size ()), str.c_str (), str.size ());
+
+ if (res_len == str.size ()) {
+ // if the result length matches the expected length
+ // (and only then), also verify that the modified
+ // string matches the expected result
+ const std::size_t match =
+ rw_match (tcase.res, str.c_str (), tcase.nres);
+
+ rw_assert (match == res_len, 0, tcase.line,
+ "line %d. %{$FUNCALL} expected %{/*.*Gs}, "
+ "got %{/*.*Gs}, difference at offset %zu",
+ __LINE__, int (sizeof (charT)), int (res_len),
+ wres, int (sizeof (charT)),
+ int (str.size ()), str.c_str (), match);
+ }
+
+ // verify that Traits::length was used
+ if (rg_calls) {
+ rw_assert (n_length_calls - total_length_calls > 0,
+ 0, tcase.line, "line %d. %{$FUNCALL} doesn't "
+ "use traits::length()", __LINE__);
+ }
+ }
- ps = copy_string (new String (0, eos));
- delete ps;
+#ifndef _RWSTD_NO_EXCEPTIONS
- ps = copy_string (new String (non_empty));
- delete ps;
+ catch (const std::bad_alloc &ex) {
+ caught = exceptions [3];
+ rw_assert (-1 == tcase.bthrow, 0, tcase.line,
+ "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
+ "unexpectedly%{;} caught std::%s(%#s)",
+ __LINE__, 0 != expected, expected, caught, ex.what ());
+ }
+ catch (const std::exception &ex) {
+ caught = exceptions [4];
+ rw_assert (0, 0, tcase.line,
+ "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
+ "unexpectedly%{;} caught std::%s(%#s)",
+ __LINE__, 0 != expected, expected, caught, ex.what ());
+ }
+ catch (...) {
+ caught = exceptions [0];
+ rw_assert (0, 0, tcase.line,
+ "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
+ "unexpectedly%{;} caught %s",
+ __LINE__, 0 != expected, expected, caught);
+ }
- ps = copy_string (copy_string ((String*)0));
- delete ps;
+#endif // _RWSTD_NO_EXCEPTIONS
- ps = copy_string (copy_string (new String (empty)));
- delete ps;
+ /* const */ std::size_t nbytes;
+ const std::size_t nblocks = rwt_check_leaks (&nbytes, 0);
- ps = copy_string (copy_string (new String (0, eos)));
- delete ps;
+ // FIXME: verify the number of blocks the function call
+ // is expected to allocate and detect any memory leaks
+ const std::size_t expect_blocks = nblocks;
+
+ rw_assert (nblocks == expect_blocks, 0, tcase.line,
+ "line %d. %{$FUNCALL} allocated %td bytes in %td blocks",
+ __LINE__, nbytes, expect_blocks);
+
+ if (caught) {
+ // verify that an exception thrown during allocation
+ // didn't cause a change in the state of the object
+ str_state.assert_equal (rw_get_string_state (str),
+ __LINE__, tcase.line, caught);
+ if (-1 == tcase.bthrow) {
+ // allow this call to operator new to succeed and try
+ // to make the next one to fail during the next call
+ // to the same function again
+ continue;
+ }
+ }
+ else if (-1 != tcase.bthrow) {
+ rw_assert (caught == expected, 0, tcase.line,
+ "line %d. %{$FUNCALL} %{?}expected %s, caught %s"
+ "%{:}unexpectedly caught %s%{;}",
+ __LINE__, 0 != expected, expected, caught, caught);
+ }
- ps = copy_string (copy_string (new String (non_empty)));
- delete ps;
+ break;
}
-#endif // 0/1
+#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
+
+ // verify that if exceptions are enabled and when capacity changes
+ // at least one exception is thrown
+ rw_assert ( *pst->throw_at_calls_ [0] == std::size_t (-1)
+ || throw_after,
+ 0, tcase.line,
+ "line %d: %{$FUNCALL}: failed to throw an expected exception",
+ __LINE__);
+#endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
+
+ *pst->throw_at_calls_ [0] = std::size_t (-1);
+
+ if (wres != wres_buf)
+ delete[] wres;
}
/**************************************************************************/
-int run_test (int, char**)
+template <class charT, class Traits>
+void test_cons (charT, Traits*,
+ OverloadId which,
+ const TestCase &tcase)
{
- if (rw_enabled ("char")) {
- test_signatures (char (), "char");
- test_ctors (char (), "char");
- }
+ if (OpSet(ptr) <= which)
+ test_op_set (charT (), (Traits*)0, which, tcase);
else
- rw_note (0, __FILE__, __LINE__, "char test disabled");
+ test_ctor (charT (), (Traits*)0, which, tcase);
+}
+
+/**************************************************************************/
+
+DEFINE_TEST_DISPATCH (test_cons);
-#ifndef _RWSTD_NO_WCHAR_T
+int main (int argc, char** argv)
+{
+ static const StringMembers::Test
+ tests [] = {
- if (rw_enabled ("wchar_t")) {
- test_signatures (wchar_t (), "wchar_t");
- test_ctors (wchar_t (), "wchar_t");
+#undef TEST
+#define TEST(tag) { \
+ StringMembers::ctor_ ## tag, tag ## _test_cases, \
+ sizeof tag ## _test_cases / sizeof *tag ## _test_cases \
}
- else
- rw_note (0, __FILE__, __LINE__, "wchar_t test disabled");
-#endif // _RWSTD_NO_WCHAR_T
+ TEST (void),
+ TEST (ptr),
+ TEST (str),
+ TEST (ptr_size),
+ TEST (str_size),
+ TEST (str_size_size),
+ TEST (size_val),
+ TEST (range),
- return 0;
-}
+#undef TEST
+#define TEST(tag) { \
+ StringMembers::tag, tag ## _test_cases, \
+ sizeof tag ## _test_cases / sizeof *tag ## _test_cases \
+ }
-/**************************************************************************/
+ TEST (op_set_ptr),
+ TEST (op_set_str),
+ TEST (op_set_val)
-int main (int argc, char** argv)
-{
- return rw_test (argc, argv, __FILE__,
- "lib.string.cons",
- 0 /* no comment */,
- run_test,
- "|-no-copy-ctor# "
- "|-no-default-ctor# "
- "|-no-pointer-ctor# ",
- &rw_opt_no_copy_ctor,
- &rw_opt_no_def_ctor,
- &rw_opt_no_ptr_ctor);
+ };
+
+ const std::size_t test_count = sizeof tests / sizeof *tests;
+
+ return StringMembers::run_test (argc, argv, __FILE__,
+ "lib.string.cons",
+ test_cons, tests, test_count);
}
+