1292 lines
62 KiB
C++
1292 lines
62 KiB
C++
/***************************************************************************
|
|
*
|
|
* 21.string.io.cpp - string test exercising lib.string.io
|
|
*
|
|
* $Id: 21.string.io.cpp 590052 2007-10-30 12:44:14Z faridz $
|
|
*
|
|
***************************************************************************
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you 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 <string> // for string
|
|
#include <cstddef> // for size_t
|
|
#include <istream> // for istream
|
|
#include <ostream> // for ostream
|
|
#include <locale> // for locale
|
|
|
|
#include <21.strings.h> // for StringMembers
|
|
#include <driver.h> // for rw_test()
|
|
#include <rw_allocator.h> // for UserAlloc
|
|
#include <rw_char.h> // for rw_expand()
|
|
#include <rw_ctype.h> // for UserCtype
|
|
#include <rw_new.h> // for bad_alloc, replacement operator new
|
|
#include <rw_streambuf.h> // for MyStreambuf
|
|
|
|
/**************************************************************************/
|
|
|
|
static const char* const exceptions[] = {
|
|
"unknown exception", "ios_base::failure", "bad_alloc", "exception"
|
|
};
|
|
|
|
/**************************************************************************/
|
|
|
|
// for convenience
|
|
#define Good std::ios_base::goodbit
|
|
#define Eof std::ios_base::eofbit
|
|
#define Fail std::ios_base::failbit
|
|
#define Bad std::ios_base::badbit
|
|
#define NotGood (Eof | Fail | Bad)
|
|
|
|
#define Skipws std::ios_base::skipws
|
|
#define Left std::ios_base::left
|
|
#define Right std::ios_base::right
|
|
|
|
#define WHITESPACE " \f\n\r\t\v"
|
|
|
|
const char SYMB_THROW = '!';
|
|
|
|
// off - width
|
|
// size - fmtflags
|
|
// off2 - iostate or exceptions mask
|
|
// size2 - expected iostate or -1 if not verifyed
|
|
// val - expected width
|
|
// str - controlled sequence
|
|
// arg - sequence in stream
|
|
// res - expected result
|
|
|
|
// bthrow == 0 - off2 is initial stream state
|
|
// == 1 - off2 is exceptions mask
|
|
|
|
// used to exercise
|
|
// operator>> (istream&, string&)
|
|
static const StringTestCase
|
|
extractor_test_cases [] = {
|
|
|
|
#undef TEST
|
|
#define TEST(str, arg, width, flags, state, res, res_width, res_st, bthrow) { \
|
|
__LINE__, width, flags, state, res_st, res_width, \
|
|
str, sizeof (str) - 1, arg, sizeof (arg) - 1, \
|
|
res, sizeof (res) - 1, bthrow \
|
|
}
|
|
|
|
// 1.
|
|
// the string argument and stream width should be unchanged when
|
|
// the stream's initial state is not good, or the initial state
|
|
// is good and skipws is set and the stream's buffer contains only
|
|
// whitespace characters or is empty
|
|
|
|
// +----------------------------------------------- initial string
|
|
// | +------------------------------------------ sequence in stream
|
|
// | | +------------------------------ stream width
|
|
// | | | +-------------------------- stream flags
|
|
// | | | | +------------------ stream state
|
|
// | | | | | or exceptions
|
|
// | | | | | +--------- expected result
|
|
// | | | | | | +------- expected width
|
|
// | | | | | | | +--- expected state
|
|
// | | | | | | | | +- exception info:
|
|
// | | | | | | | | | 0 - no exception
|
|
// | | | | | | | | | 1 - ios_base::failure
|
|
// | | | | | | | | | -1 - exc. safety
|
|
// | | | | | | | | |
|
|
// | | | | | | | | +------------+
|
|
// | | | | | | | +--+ |
|
|
// | | | | | | +--+ | |
|
|
// | | | | | | | | |
|
|
// V V V V V V V V V
|
|
|
|
#undef TEST1
|
|
#define TEST1(str) \
|
|
TEST (str, "", 0, 0, Eof, str, 0, Eof, 0), \
|
|
TEST (str, "", 1, 0, Fail, str, 1, Fail, 0), \
|
|
TEST (str, "", 2, 0, Bad, str, 2, Bad, 0), \
|
|
TEST (str, "", 3, Skipws, Eof, str, 3, Eof, 0), \
|
|
TEST (str, "", 4, Skipws, Fail, str, 4, Fail, 0), \
|
|
TEST (str, "", 5, Skipws, Bad, str, 5, Bad, 0), \
|
|
TEST (str, "", 6, Skipws, Good, str, 6, Eof | Fail, 0), \
|
|
TEST (str, WHITESPACE, 7, 0, Eof, str, 7, Eof, 0), \
|
|
TEST (str, WHITESPACE, 8, 0, Fail, str, 8, Fail, 0), \
|
|
TEST (str, WHITESPACE, 9, 0, Bad, str, 9, Bad, 0), \
|
|
TEST (str, WHITESPACE, 10, Skipws, Eof, str, 10, Eof, 0), \
|
|
TEST (str, WHITESPACE, 11, Skipws, Fail, str, 11, Fail, 0), \
|
|
TEST (str, WHITESPACE, 12, Skipws, Bad, str, 12, Bad, 0), \
|
|
TEST (str, WHITESPACE, 13, Skipws, Good, str, 13, Eof | Fail, 0), \
|
|
TEST (str, "", 14, Skipws, NotGood, str, 14, Eof | Fail, 1), \
|
|
TEST (str, WHITESPACE, 15, Skipws, NotGood, str, 15, Eof | Fail, 1)
|
|
|
|
// +----------------------------------------- controlled sequence
|
|
// |
|
|
// |
|
|
// V
|
|
TEST1 ("" ),
|
|
TEST1 ("ab" ),
|
|
TEST1 ("abc" ),
|
|
TEST1 ("<U0>" ),
|
|
TEST1 ("<U0>@2ab" ),
|
|
TEST1 ("a<U0>@2b" ),
|
|
TEST1 ("ab<U0>@2" ),
|
|
TEST1 ("a<U0>b<U0>@2c"),
|
|
TEST1 ("<U0>ab<U0>@2c"),
|
|
TEST1 ("x@4096" ),
|
|
|
|
// 2.
|
|
// the string argument should be cleared when the stream's initial
|
|
// state is good and skipws is not set and the stream's buffer is
|
|
// empty or contains a string which begins with whitespace
|
|
// width should be reset to 0, and the stream's state should have
|
|
// failbit set
|
|
|
|
// +----------------------------------------------- initial string
|
|
// | +------------------------------------------ sequence in stream
|
|
// | | +------------------- stream width
|
|
// | | | +--------------- stream flags
|
|
// | | | | +------------ stream state
|
|
// | | | | | or exceptions
|
|
// | | | | | +-------- expected result
|
|
// | | | | | | +----- expected width
|
|
// | | | | | | | +--- expected state
|
|
// | | | | | | | | +- exception info:
|
|
// | | | | | | | | | 0 - no exception
|
|
// | | | | | | | | | 1 - ios_base::failure
|
|
// | | | | | | | | | -1 - exc. safety
|
|
// | | | | | | | | |
|
|
// | | | | | | | | +-----------------+
|
|
// | | | | | | | +-------+ |
|
|
// | | | | | | +-----+ | |
|
|
// | | | | | +----+ | | |
|
|
// | | | | | | | | |
|
|
// V V V V V V V V V
|
|
|
|
#undef TEST2
|
|
#define TEST2(str) \
|
|
TEST (str, "", 0, 0, Good, "", 0 , Eof | Fail, 0), \
|
|
TEST (str, "", 10, 0, Good, "", 0 , Eof | Fail, 0), \
|
|
TEST (str, WHITESPACE, 0, 0, Good, "", 0 , Fail, 0), \
|
|
TEST (str, WHITESPACE, 2, 0, Good, "", 0 , Fail, 0), \
|
|
TEST (str, WHITESPACE, 20, 0, Good, "", 0 , Fail, 0), \
|
|
TEST (str, WHITESPACE "abc", 0, 0, Good, "", 0 , Fail, 0), \
|
|
TEST (str, WHITESPACE "abc", 2, 0, Good, "", 0 , Fail, 0), \
|
|
TEST (str, WHITESPACE "abc", 10, 0, Good, "", 0 , Fail, 0), \
|
|
TEST (str, WHITESPACE "abc\ndef", 0, 0, Good, "", 0 , Fail, 0), \
|
|
TEST (str, WHITESPACE "abc\ndef", 3, 0, Good, "", 0 , Fail, 0), \
|
|
TEST (str, WHITESPACE "abc\ndef", 30, 0, Good, "", 0 , Fail, 0), \
|
|
TEST (str, WHITESPACE "<U0>@3", 0, 0, Good, "", 0 , Fail, 0), \
|
|
TEST (str, WHITESPACE "<U0>@3", 2, 0, Good, "", 0 , Fail, 0), \
|
|
TEST (str, WHITESPACE "<U0>@3", 10, 0, Good, "", 0 , Fail, 0), \
|
|
TEST (str, "", 0, 0, NotGood, "", 0 , Eof | Fail, 1), \
|
|
TEST (str, "", 10, 0, NotGood, "", 0 , Eof | Fail, 1), \
|
|
TEST (str, WHITESPACE, 0, 0, NotGood, "", 0 , Fail, 1), \
|
|
TEST (str, WHITESPACE, 2, 0, NotGood, "", 0 , Fail, 1), \
|
|
TEST (str, WHITESPACE, 20, 0, NotGood, "", 0 , Fail, 1), \
|
|
TEST (str, WHITESPACE "abc", 0, 0, NotGood, "", 0 , Fail, 1), \
|
|
TEST (str, WHITESPACE "abc", 2, 0, NotGood, "", 0 , Fail, 1), \
|
|
TEST (str, WHITESPACE "abc", 10, 0, NotGood, "", 0 , Fail, 1), \
|
|
TEST (str, WHITESPACE "abc\ndef", 0, 0, NotGood, "", 0 , Fail, 1), \
|
|
TEST (str, WHITESPACE "abc\ndef", 3, 0, NotGood, "", 0 , Fail, 1), \
|
|
TEST (str, WHITESPACE "abc\ndef", 30, 0, NotGood, "", 0 , Fail, 1), \
|
|
TEST (str, WHITESPACE "<U0>@3", 0, 0, NotGood, "", 0 , Fail, 1), \
|
|
TEST (str, WHITESPACE "<U0>@3", 2, 0, NotGood, "", 0 , Fail, 1), \
|
|
TEST (str, WHITESPACE "<U0>@3", 10, 0, NotGood, "", 0 , Fail, 1)
|
|
|
|
// +----------------------------------------- controlled sequence
|
|
// |
|
|
// |
|
|
// V
|
|
TEST2 ("" ),
|
|
TEST2 ("ab" ),
|
|
TEST2 ("abc" ),
|
|
TEST2 ("<U0>" ),
|
|
TEST2 ("<U0>@2ab" ),
|
|
TEST2 ("a<U0>@2b" ),
|
|
TEST2 ("ab<U0>@2" ),
|
|
TEST2 ("a<U0>b<U0>@2c"),
|
|
TEST2 ("<U0>ab<U0>@2c"),
|
|
TEST2 ("x@4096" ),
|
|
|
|
|
|
// 3.
|
|
// the string argument should contain the extracted characters when
|
|
// the stream's initial state is good and either
|
|
// skipws is clear and the stream's buffer doesn't contain whitespace
|
|
// or
|
|
// skipws is set
|
|
// width should be reset to 0
|
|
|
|
// +----------------------------------------------- initial string
|
|
// | +------------------------------ sequence in stream
|
|
// | | +------------------------- stream width
|
|
// | | | +------------------ stream flags
|
|
// | | | | +----------- stream state
|
|
// | | | | | or exceptions
|
|
// | | | | | +-------- expected result
|
|
// | | | | | | +----- expected width
|
|
// | | | | | | | +--- expected state
|
|
// | | | | | | | | +- exception info:
|
|
// | | | | | | | | | 0 - no exception
|
|
// | | | | | | | | | 1 - ios_base::failure
|
|
// | | | | | | | | | -1 - exc. safety
|
|
// | | | | | | | | |
|
|
// | | | | | | | | +----------+
|
|
// | | | | | | | +--------+ |
|
|
// | | | | | | +------+ | |
|
|
// | | | | | +-----+ | | |
|
|
// | | | | | | | | |
|
|
// V V V V V V V V V
|
|
|
|
#undef TEST3
|
|
#define TEST3(arg, width, flags, res) \
|
|
TEST ("", arg, width, flags, Good, res, 0, -1, 0), \
|
|
TEST ("ab", arg, width, flags, Good, res, 0, -1, 0), \
|
|
TEST ("abc", arg, width, flags, Good, res, 0, -1, 0), \
|
|
TEST ("<U0>", arg, width, flags, Good, res, 0, -1, 0), \
|
|
TEST ("<U0>@2ab", arg, width, flags, Good, res, 0, -1, 0), \
|
|
TEST ("a<U0>@2b", arg, width, flags, Good, res, 0, -1, 0), \
|
|
TEST ("ab<U0>@2", arg, width, flags, Good, res, 0, -1, 0), \
|
|
TEST ("a<U0>b<U0>@2c", arg, width, flags, Good, res, 0, -1, 0), \
|
|
TEST ("<U0>ab<U0>@2c", arg, width, flags, Good, res, 0, -1, 0), \
|
|
TEST ("x@4096", arg, width, flags, Good, res, 0, -1, 0), \
|
|
TEST ("", arg, width, flags, NotGood, res, 0, -1, 1), \
|
|
TEST ("ab", arg, width, flags, NotGood, res, 0, -1, 1), \
|
|
TEST ("abc", arg, width, flags, NotGood, res, 0, -1, 1), \
|
|
TEST ("<U0>", arg, width, flags, NotGood, res, 0, -1, 1), \
|
|
TEST ("<U0>@2ab", arg, width, flags, NotGood, res, 0, -1, 1), \
|
|
TEST ("a<U0>@2b", arg, width, flags, NotGood, res, 0, -1, 1), \
|
|
TEST ("ab<U0>@2", arg, width, flags, NotGood, res, 0, -1, 1), \
|
|
TEST ("a<U0>b<U0>@2c", arg, width, flags, NotGood, res, 0, -1, 1), \
|
|
TEST ("<U0>ab<U0>@2c", arg, width, flags, NotGood, res, 0, -1, 1), \
|
|
TEST ("x@4096", arg, width, flags, NotGood, res, 0, -1, 1)
|
|
|
|
// +------------------------------------------------- sequence in stream
|
|
// | +-------------------- stream width
|
|
// | | +---------------- stream flags
|
|
// | | | +-------- expected result
|
|
// | | | |
|
|
// | | | |
|
|
// V V V V
|
|
TEST3 ("a!bc", 1, 0, "a" ),
|
|
TEST3 ("a!bc", 2, 0, "a!" ),
|
|
TEST3 ("a!bc", 10, 0, "a!bc"),
|
|
TEST3 ("ab!c ", 10, 0, "ab!c"),
|
|
TEST3 ("ab!c\f", 10, 0, "ab!c"),
|
|
TEST3 ("ab!c\n", 10, 0, "ab!c"),
|
|
TEST3 ("ab!c\r", 10, 0, "ab!c"),
|
|
TEST3 ("ab!c\t", 10, 0, "ab!c"),
|
|
TEST3 ("ab!c\v", 10, 0, "ab!c"),
|
|
|
|
TEST3 ("a!bc" WHITESPACE, 0, 0, "a!bc"),
|
|
TEST3 ("ab!c" WHITESPACE, 2, 0, "ab" ),
|
|
TEST3 ("abc!" WHITESPACE, 10, 0, "abc!"),
|
|
|
|
TEST3 ("abc!", 0, Skipws, "abc!"),
|
|
TEST3 ("ab!c", 2, Skipws, "ab" ),
|
|
TEST3 ("a!bc", 10, Skipws, "a!bc"),
|
|
|
|
TEST3 ("abc" WHITESPACE, 0, Skipws, "abc" ),
|
|
TEST3 ("abc" WHITESPACE, 2, Skipws, "ab" ),
|
|
TEST3 ("abc" WHITESPACE, 10, Skipws, "abc" ),
|
|
|
|
TEST3 (WHITESPACE "abc", 0, Skipws, "abc" ),
|
|
TEST3 (WHITESPACE "abc", 2, Skipws, "ab" ),
|
|
TEST3 (WHITESPACE "abc", 30, Skipws, "abc" ),
|
|
|
|
TEST3 (WHITESPACE "abc" WHITESPACE, 0, Skipws, "abc" ),
|
|
TEST3 (WHITESPACE "abc" WHITESPACE, 2, Skipws, "ab" ),
|
|
TEST3 (WHITESPACE "abc" WHITESPACE, 30, Skipws, "abc" )
|
|
};
|
|
|
|
/**************************************************************************/
|
|
|
|
// off - width
|
|
// size - fmtflags
|
|
// off2 - iostate or exceptions mask
|
|
// size2 - expected iostate or -1 if not verifyed
|
|
// val - unused
|
|
// str - controlled sequence
|
|
// arg - sequence in stream
|
|
// res - expected result
|
|
|
|
// bthrow == 0 - off2 is initial stream state
|
|
// == 1 - off2 is exceptions mask
|
|
|
|
// used to exercise
|
|
// getline (istream&, string&)
|
|
static const StringTestCase
|
|
getline_test_cases [] = {
|
|
|
|
#undef TEST
|
|
#define TEST(str, arg, width, flags, state, res, res_width, res_st, bthrow) { \
|
|
__LINE__, width, flags, state, res_st, res_width, \
|
|
str, sizeof (str) - 1, arg, sizeof (arg) - 1, \
|
|
res, sizeof (res) - 1, bthrow \
|
|
}
|
|
|
|
// 1.
|
|
// string and width should be unchanged when initial iostate is not good
|
|
|
|
// +---------------------------------------------- controlled sequence
|
|
// | +----------------------------------------- sequence in stream
|
|
// | | +-------------------------- stream width
|
|
// | | | +---------------------- stream flags
|
|
// | | | | +-------------- stream state
|
|
// | | | | | or exceptions
|
|
// | | | | | +-------- expected result
|
|
// | | | | | | +----- unused
|
|
// | | | | | | | +--- expected state
|
|
// | | | | | | | | +- exception info:
|
|
// | | | | | | | | | 0 - no exception
|
|
// | | | | | | | | | 1 - ios_base::failure
|
|
// | | | | | | | | | -1 - exc. safety
|
|
// | | | | | | | | |
|
|
// | | | | | | | | +---------+
|
|
// | | | | | | | +-----+ |
|
|
// | | | | | | +---+ | |
|
|
// | | | | | +--+ | | |
|
|
// | | | | | | | | |
|
|
// V V V V V V V V V
|
|
|
|
#undef TEST1
|
|
#define TEST1(str) \
|
|
TEST (str, "", 0, 0, Eof, str, 0, Eof, 0), \
|
|
TEST (str, "", 1, 0, Fail, str, 0, Fail, 0), \
|
|
TEST (str, "", 2, 0, Bad, str, 0, Bad, 0), \
|
|
TEST (str, "", 3, Skipws, Eof, str, 0, Eof, 0), \
|
|
TEST (str, "", 4, Skipws, Fail, str, 0, Fail, 0), \
|
|
TEST (str, "", 5, Skipws, Bad, str, 0, Bad, 0), \
|
|
TEST (str, WHITESPACE, 7, 0, Eof, str, 0, Eof, 0), \
|
|
TEST (str, WHITESPACE, 8, 0, Fail, str, 0, Fail, 0), \
|
|
TEST (str, WHITESPACE, 9, 0, Bad, str, 0, Bad, 0), \
|
|
TEST (str, WHITESPACE, 10, Skipws, Eof, str, 0, Eof, 0), \
|
|
TEST (str, WHITESPACE, 11, Skipws, Fail, str, 0, Fail, 0), \
|
|
TEST (str, WHITESPACE, 12, Skipws, Bad, str, 0, Bad, 0), \
|
|
TEST (str, "abc", 13, 0, Eof, str, 0, Eof, 0), \
|
|
TEST (str, "x@4096", 14, 0, Fail, str, 0, Fail, 0), \
|
|
TEST (str, "<U0>abc<U0>", 15, 0, Bad, str, 0, Bad, 0), \
|
|
TEST (str, "abc\ndef", 16, Skipws, Eof, str, 0, Eof, 0), \
|
|
TEST (str, " \tabc", 17, Skipws, Fail, str, 0, Fail, 0), \
|
|
TEST (str, "\n\n<U0>\n", 18, Skipws, Bad, str, 0, Bad, 0)
|
|
|
|
// +----------------------------------------- controlled sequence
|
|
// |
|
|
// |
|
|
// V
|
|
TEST1 ("" ),
|
|
TEST1 ("ab" ),
|
|
TEST1 ("abc" ),
|
|
TEST1 ("<U0>" ),
|
|
TEST1 ("<U0>@2ab" ),
|
|
TEST1 ("a<U0>@2b" ),
|
|
TEST1 ("ab<U0>@2" ),
|
|
TEST1 ("a<U0>b<U0>@2c"),
|
|
TEST1 ("<U0>ab<U0>@2c"),
|
|
TEST1 ("x@4096" ),
|
|
|
|
|
|
// 2.
|
|
// string should be erased when initial iostate is good and
|
|
// stream empty or contains string which begins from '\n'
|
|
// width should be unchanged, iostate should have failbit setted
|
|
|
|
// +--------------------------------------------- controlled sequence
|
|
// | +---------------------------------------- sequence in stream
|
|
// | | +-------------------------- stream width
|
|
// | | | +---------------------- stream flags
|
|
// | | | | +-------------- stream state
|
|
// | | | | | or exceptions
|
|
// | | | | | +-------- expected result
|
|
// | | | | | | +----- unused
|
|
// | | | | | | | +--- expected state
|
|
// | | | | | | | | +- exception info:
|
|
// | | | | | | | | | 0 - no exception
|
|
// | | | | | | | | | 1 - ios_base::failure
|
|
// | | | | | | | | | -1 - exc. safety
|
|
// | | | | | | | | |
|
|
// | | | | | | | | +--------------+
|
|
// | | | | | | | +----+ |
|
|
// | | | | | | +---+ | |
|
|
// | | | | | +--+ | | |
|
|
// | | | | | | | | |
|
|
// V V V V V V V V V
|
|
|
|
#undef TEST2
|
|
#define TEST2(str) \
|
|
TEST (str, "", 0, Skipws, Good, "", 0, Eof | Fail, 0), \
|
|
TEST (str, "", 10, 0, Good, "", 0, Eof | Fail, 0), \
|
|
TEST (str, "\n", 0, Skipws, Good, "", 0, Good, 0), \
|
|
TEST (str, "\n", 2, 0, Good, "", 0, Good, 0), \
|
|
TEST (str, "\nabc", 0, Skipws, Good, "", 0, Good, 0), \
|
|
TEST (str, "\nabc", 2, 0, Good, "", 0, Good, 0), \
|
|
TEST (str, "\nabc\ndef", 0, Skipws, Good, "", 0, Good, 0), \
|
|
TEST (str, "\nabc\ndef", 3, 0, Good, "", 0, Good, 0), \
|
|
TEST (str, "\n<U0>@3", 0, Skipws, Good, "", 0, Good, 0), \
|
|
TEST (str, "\n<U0>@3", 2, 0, Good, "", 0, Good, 0), \
|
|
TEST (str, "", 0, Skipws, NotGood, "", 0, Eof | Fail, 1), \
|
|
TEST (str, "", 10, 0, NotGood, "", 0, Eof | Fail, 1), \
|
|
TEST (str, "\n", 0, Skipws, NotGood, "", 0, Good, 1), \
|
|
TEST (str, "\n", 2, 0, NotGood, "", 0, Good, 1), \
|
|
TEST (str, "\nabc", 0, Skipws, NotGood, "", 0, Good, 1), \
|
|
TEST (str, "\nabc", 2, 0, NotGood, "", 0, Good, 1), \
|
|
TEST (str, "\nabc\ndef", 0, Skipws, NotGood, "", 0, Good, 1), \
|
|
TEST (str, "\nabc\ndef", 3, 0, NotGood, "", 0, Good, 1), \
|
|
TEST (str, "\n<U0>@3", 0, Skipws, NotGood, "", 0, Good, 1), \
|
|
TEST (str, "\n<U0>@3", 2, 0, NotGood, "", 0, Good, 1)
|
|
|
|
// +----------------------------------------- controlled sequence
|
|
// |
|
|
// |
|
|
// V
|
|
TEST2 ("" ),
|
|
TEST2 ("ab" ),
|
|
TEST2 ("abc" ),
|
|
TEST2 ("<U0>" ),
|
|
TEST2 ("<U0>@2ab" ),
|
|
TEST2 ("a<U0>@2b" ),
|
|
TEST2 ("ab<U0>@2" ),
|
|
TEST2 ("a<U0>b<U0>@2c"),
|
|
TEST2 ("<U0>ab<U0>@2c"),
|
|
TEST2 ("x@4096" ),
|
|
|
|
|
|
// 3.
|
|
// string should be compared with result when initial iostate is good
|
|
// and stream string begins from not '\n'
|
|
// width should be unchanged
|
|
|
|
// +----------------------------------------------- controlled sequence
|
|
// | +------------------------------ sequence in stream
|
|
// | | +------------------------- stream width
|
|
// | | | +--------------------- stream flags
|
|
// | | | | +------------- stream state
|
|
// | | | | | or exceptions
|
|
// | | | | | +-------- expected result
|
|
// | | | | | | +----- unused
|
|
// | | | | | | | +--- expected state
|
|
// | | | | | | | | +- exception info:
|
|
// | | | | | | | | | 0 - no exception
|
|
// | | | | | | | | | 1 - ios_base::failure
|
|
// | | | | | | | | | -1 - exc. safety
|
|
// | | | | | | | | |
|
|
// | | | | | | | | +--------+
|
|
// | | | | | | | +------+ |
|
|
// | | | | | | +-----+ | |
|
|
// | | | | | +---+ | | |
|
|
// | | | | | | | | |
|
|
// V V V V V V V V V
|
|
|
|
#undef TEST3
|
|
#define TEST3(arg, res) \
|
|
TEST ("", arg, 0, Skipws, Good, res, 0, -1, 0), \
|
|
TEST ("ab", arg, 1, 0, Good, res, 0, -1, 0), \
|
|
TEST ("abc", arg, 2, Skipws, Good, res, 0, -1, 0), \
|
|
TEST ("<U0>", arg, 3, 0, Good, res, 0, -1, 0), \
|
|
TEST ("<U0>@2ab", arg, 4, Skipws, Good, res, 0, -1, 0), \
|
|
TEST ("a<U0>@2b", arg, 5, 0, Good, res, 0, -1, 0), \
|
|
TEST ("ab<U0>@2", arg, 6, Skipws, Good, res, 0, -1, 0), \
|
|
TEST ("a<U0>b<U0>@2c", arg, 7, 0, Good, res, 0, -1, 0), \
|
|
TEST ("<U0>ab<U0>@2c", arg, 8, Skipws, Good, res, 0, -1, 0), \
|
|
TEST ("x@4096", arg, 9, 0, Good, res, 0, -1, 0), \
|
|
TEST ("", arg, 10, Skipws, NotGood, res, 0, -1, 1), \
|
|
TEST ("ab", arg, 11, 0, NotGood, res, 0, -1, 1), \
|
|
TEST ("abc", arg, 12, Skipws, NotGood, res, 0, -1, 1), \
|
|
TEST ("<U0>", arg, 13, 0, NotGood, res, 0, -1, 1), \
|
|
TEST ("<U0>@2ab", arg, 14, Skipws, NotGood, res, 0, -1, 1), \
|
|
TEST ("a<U0>@2b", arg, 15, 0, NotGood, res, 0, -1, 1), \
|
|
TEST ("ab<U0>@2", arg, 16, Skipws, NotGood, res, 0, -1, 1), \
|
|
TEST ("a<U0>b<U0>@2c", arg, 17, 0, NotGood, res, 0, -1, 1), \
|
|
TEST ("<U0>ab<U0>@2c", arg, 18, Skipws, NotGood, res, 0, -1, 1), \
|
|
TEST ("x@4096", arg, 19, 0, NotGood, res, 0, -1, 1)
|
|
|
|
// +------------------------------------------------- sequence in stream
|
|
// | +----------------------- expected result
|
|
// | |
|
|
// | |
|
|
// V V
|
|
TEST3 ("ab!c", "ab!c" ),
|
|
TEST3 ("a!b\nc", "a!b" ),
|
|
TEST3 ("a\n!bc", "a" ),
|
|
TEST3 (" !\t\n", " !\t" ),
|
|
TEST3 (" \f\r\t\v\n", " \f\r\t\v" ),
|
|
TEST3 (" \f\r\n\t\v\n", " \f\r" ),
|
|
TEST3 ("<U0>a<U0>b<U0>\n<U0>@2", "<U0>a<U0>b<U0>"),
|
|
TEST3 ("<U0>@7", "<U0>@7" ),
|
|
TEST3 ("x@4096", "x@4096" ),
|
|
TEST3 ("x@4096\nx@4096", "x@4096" )
|
|
};
|
|
|
|
/**************************************************************************/
|
|
|
|
// off - width
|
|
// size - fmtflags
|
|
// off2 - iostate or exceptions mask
|
|
// size2 - expected iostate or -1 if not verifyed
|
|
// val - char delim
|
|
// str - controlled sequence
|
|
// arg - sequence in stream
|
|
// res - expected result
|
|
|
|
// bthrow == 0 - off2 is initial stream state
|
|
// == 1 - off2 is exceptions mask
|
|
|
|
// used to exercise
|
|
// getline (istream&, string&, char)
|
|
static const StringTestCase
|
|
getline_val_test_cases [] = {
|
|
|
|
#undef TEST
|
|
#define TEST(str, arg, width, flags, state, res, res_width, res_st, bthrow) { \
|
|
__LINE__, width, flags, state, res_st, res_width, \
|
|
str, sizeof (str) - 1, arg, sizeof (arg) - 1, \
|
|
res, sizeof (res) - 1, bthrow \
|
|
}
|
|
|
|
// 1.
|
|
// string and width should be unchanged when initial iostate is not good
|
|
|
|
// +---------------------------------------------- controlled sequence
|
|
// | +----------------------------------------- sequence in stream
|
|
// | | +-------------------------- stream width
|
|
// | | | +---------------------- stream flags
|
|
// | | | | +-------------- stream state
|
|
// | | | | | or exceptions
|
|
// | | | | | +-------- expected result
|
|
// | | | | | | +----- delim
|
|
// | | | | | | | +--- expected state
|
|
// | | | | | | | | +- exception info:
|
|
// | | | | | | | | | 0 - no exception
|
|
// | | | | | | | | | 1 - ios_base::failure
|
|
// | | | | | | | | | -1 - exc. safety
|
|
// | | | | | | | | |
|
|
// | | | | | | | | +------------+
|
|
// | | | | | | | +--------+ |
|
|
// | | | | | | +----+ | |
|
|
// | | | | | +--+ | | |
|
|
// | | | | | | | | |
|
|
// V V V V V V V V V
|
|
|
|
#undef TEST1
|
|
#define TEST1(str) \
|
|
TEST (str, "", 0, 0, Eof, str, '\n', Eof, 0), \
|
|
TEST (str, "", 1, 0, Fail, str, '\0', Fail, 0), \
|
|
TEST (str, "", 2, 0, Bad, str, '\r', Bad, 0), \
|
|
TEST (str, "", 3, Skipws, Eof, str, '\a', Eof, 0), \
|
|
TEST (str, "", 4, Skipws, Fail, str, '\b', Fail, 0), \
|
|
TEST (str, "", 5, Skipws, Bad, str, '\t', Bad, 0), \
|
|
TEST (str, WHITESPACE, 7, 0, Eof, str, '\v', Eof, 0), \
|
|
TEST (str, WHITESPACE, 8, 0, Fail, str, 'a', Fail, 0), \
|
|
TEST (str, WHITESPACE, 9, 0, Bad, str, ' ', Bad, 0), \
|
|
TEST (str, WHITESPACE, 10, Skipws, Eof, str, '1', Eof, 0), \
|
|
TEST (str, WHITESPACE, 11, Skipws, Fail, str, '5', Fail, 0), \
|
|
TEST (str, WHITESPACE, 12, Skipws, Bad, str, 'w', Bad, 0), \
|
|
TEST (str, "abc", 13, 0, Eof, str, 'b', Eof, 0), \
|
|
TEST (str, "x@4096", 14, 0, Fail, str, 'x', Fail, 0), \
|
|
TEST (str, "<U0>abc<U0>", 15, 0, Bad, str, 'c', Bad, 0), \
|
|
TEST (str, "abc\ndef", 16, Skipws, Eof, str, 'e', Eof, 0), \
|
|
TEST (str, " \tabc", 17, Skipws, Fail, str, '\t', Fail, 0), \
|
|
TEST (str, "\n\n<U0>\n", 18, Skipws, Bad, str, '\0', Bad, 0)
|
|
|
|
// +----------------------------------------- controlled sequence
|
|
// |
|
|
// |
|
|
// V
|
|
TEST1 ("" ),
|
|
TEST1 ("ab" ),
|
|
TEST1 ("abc" ),
|
|
TEST1 ("<U0>" ),
|
|
TEST1 ("<U0>@2ab" ),
|
|
TEST1 ("a<U0>@2b" ),
|
|
TEST1 ("ab<U0>@2" ),
|
|
TEST1 ("a<U0>b<U0>@2c"),
|
|
TEST1 ("<U0>ab<U0>@2c"),
|
|
TEST1 ("x@4096" ),
|
|
|
|
|
|
// 2.
|
|
// string should be erased when initial iostate is good and
|
|
// stream empty or contains string which begins from delim
|
|
// width should be unchanged, iostate should have failbit setted
|
|
|
|
// +--------------------------------------------- controlled sequence
|
|
// | +---------------------------------------- sequence in stream
|
|
// | | +-------------------------- stream width
|
|
// | | | +---------------------- stream flags
|
|
// | | | | +-------------- stream state
|
|
// | | | | | or exceptions
|
|
// | | | | | +-------- expected result
|
|
// | | | | | | +----- delim
|
|
// | | | | | | | +--- expected state
|
|
// | | | | | | | | +- exception info:
|
|
// | | | | | | | | | 0 - no exception
|
|
// | | | | | | | | | 1 - ios_base::failure
|
|
// | | | | | | | | | -1 - exc. safety
|
|
// | | | | | | | | |
|
|
// | | | | | | | | +-----------------+
|
|
// | | | | | | | +-------+ |
|
|
// | | | | | | +---+ | |
|
|
// | | | | | +--+ | | |
|
|
// | | | | | | | | |
|
|
// V V V V V V V V V
|
|
|
|
#undef TEST2
|
|
#define TEST2(str) \
|
|
TEST (str, "", 0, Skipws, Good, "", '\a', Eof | Fail, 0), \
|
|
TEST (str, "", 10, 0, Good, "", '\0', Eof | Fail, 0), \
|
|
TEST (str, "<U0>", 0, Skipws, Good, "", '\0', Good, 0), \
|
|
TEST (str, "\n", 2, 0, Good, "", '\n', Good, 0), \
|
|
TEST (str, "\rabc", 0, Skipws, Good, "", '\r', Good, 0), \
|
|
TEST (str, "abc", 2, 0, Good, "", 'a', Good, 0), \
|
|
TEST (str, "\babc\ndef", 0, Skipws, Good, "", '\b', Good, 0), \
|
|
TEST (str, "\tabc\ndef", 3, 0, Good, "", '\t', Good, 0), \
|
|
TEST (str, "\v<U0>@3", 0, Skipws, Good, "", '\v', Good, 0), \
|
|
TEST (str, " <U0>@3", 2, 0, Good, "", ' ', Good, 0), \
|
|
TEST (str, "", 0, Skipws, NotGood, "", '\a', Eof | Fail, 1), \
|
|
TEST (str, "", 10, 0, NotGood, "", '\0', Eof | Fail, 1), \
|
|
TEST (str, "<U0>", 0, Skipws, NotGood, "", '\0', Good, 1), \
|
|
TEST (str, "\n", 2, 0, NotGood, "", '\n', Good, 1), \
|
|
TEST (str, "\rabc", 0, Skipws, NotGood, "", '\r', Good, 1), \
|
|
TEST (str, "abc", 2, 0, NotGood, "", 'a', Good, 1), \
|
|
TEST (str, "\babc\ndef", 0, Skipws, NotGood, "", '\b', Good, 1), \
|
|
TEST (str, "\tabc\ndef", 3, 0, NotGood, "", '\t', Good, 1), \
|
|
TEST (str, "\v<U0>@3", 0, Skipws, NotGood, "", '\v', Good, 1), \
|
|
TEST (str, " <U0>@3", 2, 0, NotGood, "", ' ', Good, 1)
|
|
|
|
// +----------------------------------------- controlled sequence
|
|
// |
|
|
// |
|
|
// V
|
|
TEST2 ("" ),
|
|
TEST2 ("ab" ),
|
|
TEST2 ("abc" ),
|
|
TEST2 ("<U0>" ),
|
|
TEST2 ("<U0>@2ab" ),
|
|
TEST2 ("a<U0>@2b" ),
|
|
TEST2 ("ab<U0>@2" ),
|
|
TEST2 ("a<U0>b<U0>@2c"),
|
|
TEST2 ("<U0>ab<U0>@2c"),
|
|
TEST2 ("x@4096" ),
|
|
|
|
|
|
// 3.
|
|
// string should be compared with result when initial iostate is good
|
|
// and stream string begins from not delim
|
|
// width should be unchanged
|
|
|
|
// +----------------------------------------------- controlled sequence
|
|
// | +------------------------------ sequence in stream
|
|
// | | +------------------------- stream width
|
|
// | | | +--------------------- stream flags
|
|
// | | | | +------------- stream state
|
|
// | | | | | or exceptions
|
|
// | | | | | +-------- expected result
|
|
// | | | | | | +----- delim
|
|
// | | | | | | | +--- expected state
|
|
// | | | | | | | | +- exception info:
|
|
// | | | | | | | | | 0 - no exception
|
|
// | | | | | | | | | 1 - ios_base::failure
|
|
// | | | | | | | | | -1 - exc. safety
|
|
// | | | | | | | | |
|
|
// | | | | | | | | +------------+
|
|
// | | | | | | | +----------+ |
|
|
// | | | | | | +-----+ | |
|
|
// | | | | | +---+ | | |
|
|
// | | | | | | | | |
|
|
// V V V V V V V V V
|
|
|
|
#undef TEST3
|
|
#define TEST3(arg, delim, res) \
|
|
TEST ("", arg, 0, Skipws, Good, res, delim, -1, 0), \
|
|
TEST ("ab", arg, 1, 0, Good, res, delim, -1, 0), \
|
|
TEST ("abc", arg, 2, Skipws, Good, res, delim, -1, 0), \
|
|
TEST ("<U0>", arg, 3, 0, Good, res, delim, -1, 0), \
|
|
TEST ("<U0>@2ab", arg, 4, Skipws, Good, res, delim, -1, 0), \
|
|
TEST ("a<U0>@2b", arg, 5, 0, Good, res, delim, -1, 0), \
|
|
TEST ("ab<U0>@2", arg, 6, Skipws, Good, res, delim, -1, 0), \
|
|
TEST ("a<U0>b<U0>@2c", arg, 7, 0, Good, res, delim, -1, 0), \
|
|
TEST ("<U0>ab<U0>@2c", arg, 8, Skipws, Good, res, delim, -1, 0), \
|
|
TEST ("x@4096", arg, 9, 0, Good, res, delim, -1, 0), \
|
|
TEST ("", arg, 10, Skipws, NotGood, res, delim, -1, 1), \
|
|
TEST ("ab", arg, 11, 0, NotGood, res, delim, -1, 1), \
|
|
TEST ("abc", arg, 12, Skipws, NotGood, res, delim, -1, 1), \
|
|
TEST ("<U0>", arg, 13, 0, NotGood, res, delim, -1, 1), \
|
|
TEST ("<U0>@2ab", arg, 14, Skipws, NotGood, res, delim, -1, 1), \
|
|
TEST ("a<U0>@2b", arg, 15, 0, NotGood, res, delim, -1, 1), \
|
|
TEST ("ab<U0>@2", arg, 16, Skipws, NotGood, res, delim, -1, 1), \
|
|
TEST ("a<U0>b<U0>@2c", arg, 17, 0, NotGood, res, delim, -1, 1), \
|
|
TEST ("<U0>ab<U0>@2c", arg, 18, Skipws, NotGood, res, delim, -1, 1), \
|
|
TEST ("x@4096", arg, 19, 0, NotGood, res, delim, -1, 1)
|
|
|
|
// +------------------------------------------------- sequence in stream
|
|
// | +----------------------- delim
|
|
// | | +----------------- expected result
|
|
// | | |
|
|
// | | |
|
|
// V V V
|
|
TEST3 ("ab!c", '\t', "ab!c" ),
|
|
TEST3 ("a!b<U0>c", '\0', "a!b" ),
|
|
TEST3 ("a\n!bc", 'b', "a\n!" ),
|
|
TEST3 (" \t\n", '\n', " \t" ),
|
|
TEST3 (" \f\r\t\v\n", '\v', " \f\r\t" ),
|
|
TEST3 (" \f\r\n\t\v\n", '\r', " \f" ),
|
|
TEST3 ("<U0>a<U0>b<U0>\n<U0>@2", 'b', "<U0>a<U0>"),
|
|
TEST3 ("<U0>@7", '1', "<U0>@7" ),
|
|
TEST3 ("x@4096", ' ', "x@4096" ),
|
|
TEST3 ("x@4096yx@4096", 'y', "x@4096" )
|
|
};
|
|
|
|
/**************************************************************************/
|
|
|
|
// off - width
|
|
// size - fmtflags
|
|
// off2 - iostate or exceptions mask
|
|
// size2 - expected iostate or -1 if not verifyed
|
|
// val - expected width
|
|
// str - controlled sequence
|
|
// arg_len - size of streambuf
|
|
// res - expected result
|
|
|
|
// bthrow == 0 - off2 is initial stream state
|
|
// == 1 - off2 is exceptions mask
|
|
|
|
// used to exercise
|
|
// operator<< (ostream&, const string&)
|
|
static const StringTestCase
|
|
inserter_test_cases [] = {
|
|
|
|
#undef TEST
|
|
#define TEST(str, arg, width, flags, state, res, res_width, res_st, bthrow) { \
|
|
__LINE__, width, flags, state, res_st, res_width, \
|
|
str, sizeof (str) - 1, 0, arg, res, sizeof (res) - 1, bthrow \
|
|
}
|
|
|
|
// 1. if initial state is not good then width should be
|
|
// unchanged and no data in output stream
|
|
|
|
// +----------------------------------------- controlled sequence
|
|
// | +------------------------------------ size of streambuf
|
|
// | | +------------------------- stream width
|
|
// | | | +--------------------- stream flags
|
|
// | | | | +------------- stream state
|
|
// | | | | | or exceptions
|
|
// | | | | | +------- expected result
|
|
// | | | | | | +----- expected width
|
|
// | | | | | | | +--- expected state
|
|
// | | | | | | | | +- exception info:
|
|
// | | | | | | | | | 0 - no exception
|
|
// | | | | | | | | | 1 - ios_base::failure
|
|
// | | | | | | | | | -1 - exc. safety
|
|
// | | | | | | | | |
|
|
// | | | | | | | | +-------+
|
|
// | | | | | | | +---+ |
|
|
// | | | | | | +-+ | |
|
|
// | | | | | | | | |
|
|
// | | | | | | | | |
|
|
// V V V V V V V V V
|
|
|
|
#undef TEST1
|
|
#define TEST1(str) \
|
|
TEST (str, 0, 0, 0, Eof, "", 0, Eof, 0), \
|
|
TEST (str, 0, 1, 0, Fail, "", 1, Fail, 0), \
|
|
TEST (str, 0, 2, 0, Bad, "", 2, Bad, 0)
|
|
|
|
// +----------------------------------------- controlled sequence
|
|
// |
|
|
// |
|
|
// V
|
|
TEST1 ("" ),
|
|
TEST1 ("ab" ),
|
|
TEST1 ("abc" ),
|
|
TEST1 ("<U0>" ),
|
|
TEST1 ("<U0>@2ab" ),
|
|
TEST1 ("a<U0>@2b" ),
|
|
TEST1 ("ab<U0>@2" ),
|
|
TEST1 ("a<U0>b<U0>@2c"),
|
|
TEST1 ("<U0>ab<U0>@2c"),
|
|
TEST1 ("x@4096" ),
|
|
|
|
|
|
// 2. if initial state is good then:
|
|
// if stream has not enough size to get string then badbit should be set
|
|
// width should be 0
|
|
|
|
// +---------------------------------------- controlled sequence
|
|
// | +----------------------------------- size of streambuf
|
|
// | | +------------------------------ stream width
|
|
// | | | +----------------------- stream flags
|
|
// | | | | +---------------- stream state
|
|
// | | | | | or exceptions
|
|
// | | | | | +------- expected result
|
|
// | | | | | | +----- expected width
|
|
// | | | | | | | +--- expected state
|
|
// | | | | | | | | +- exception info:
|
|
// | | | | | | | | | 0 - no exception
|
|
// | | | | | | | | | 1 - ios_base::failure
|
|
// | | | | | | | | | -1 - exc. safety
|
|
// | | | | | | | | |
|
|
// | | | | | | | | +-----------------+
|
|
// | | | | | | | +-----------+ |
|
|
// | | | | | | +--+ | |
|
|
// | | | | | | | | |
|
|
// | | | | | | | | |
|
|
// V V V V V V V V V
|
|
|
|
#undef TEST2
|
|
#define TEST2(str, arg, width, flags, res, res_width, res_st) \
|
|
TEST (str, arg, width, flags, Good, res, res_width, res_st, 0), \
|
|
TEST (str, arg, width, flags, NotGood, res, res_width, res_st, 1)
|
|
|
|
// +------------------------------------------------ controlled sequence
|
|
// | +------------------------------- size of streambuf
|
|
// | | +------------------------- stream width
|
|
// | | | +------------------- stream flags
|
|
// | | | | +------------ expected result
|
|
// | | | | | +----- expected width
|
|
// | | | | | | +-- expected state
|
|
// | | | | | | |
|
|
// | | | | | | +---------------+
|
|
// | | | | | +------------+ |
|
|
// | | | | | | |
|
|
// V V V V V V V
|
|
TEST2 ("", 0, 0, 0, "", 0, Good),
|
|
TEST2 ("", 0, 0, Right, "", 0, Good),
|
|
TEST2 ("", 0, 0, Left, "", 0, Good),
|
|
|
|
TEST2 ("", 20, 10, 0, " @10", 0, Good),
|
|
TEST2 ("", 20, 10, Right, " @10", 0, Good),
|
|
TEST2 ("", 20, 10, Left, " @10", 0, Good),
|
|
|
|
TEST2 ("", 5, 10, 0, " @5", 0, Bad ),
|
|
TEST2 ("", 5, 10, Right, " @5", 0, Bad ),
|
|
TEST2 ("", 5, 10, Left, " @5", 0, Bad ),
|
|
|
|
TEST2 (" @10", 20, 10, 0, " @10", 0, Good),
|
|
TEST2 (" @10", 20, 10, Right, " @10", 0, Good),
|
|
TEST2 (" @10", 20, 10, Left, " @10", 0, Good),
|
|
|
|
TEST2 ("abc def", 20, 0, 0, "abc def", 0, Good),
|
|
TEST2 ("abc def", 20, 0, Right, "abc def", 0, Good),
|
|
TEST2 ("abc def", 20, 0, Left, "abc def", 0, Good),
|
|
|
|
TEST2 ("abc def", 5, 0, 0, "abc d", 0, Bad ),
|
|
TEST2 ("abc def", 5, 0, Right, "abc d", 0, Bad ),
|
|
TEST2 ("abc def", 5, 0, Left, "abc d", 0, Bad ),
|
|
|
|
TEST2 ("abc def", 20, 5, 0, "abc def", 0, Good),
|
|
TEST2 ("abc def", 20, 5, Right, "abc def", 0, Good),
|
|
TEST2 ("abc def", 20, 5, Left, "abc def", 0, Good),
|
|
|
|
TEST2 ("abc def", 20, 10, 0, " abc def", 0, Good),
|
|
TEST2 ("abc def", 20, 10, Right, " abc def", 0, Good),
|
|
TEST2 ("abc def", 20, 10, Left, "abc def ", 0, Good),
|
|
|
|
TEST2 ("<U0>", 20, 10, 0, " @9<U0>", 0, Good),
|
|
TEST2 ("<U0>", 20, 10, Right, " @9<U0>", 0, Good),
|
|
TEST2 ("<U0>", 20, 10, Left, "<U0> @9", 0, Good),
|
|
|
|
TEST2 ("<U0>ab<U0>@2c", 20, 10, 0, " @4<U0>ab<U0>@2c", 0, Good),
|
|
TEST2 ("<U0>ab<U0>@2c", 20, 10, Right, " @4<U0>ab<U0>@2c", 0, Good),
|
|
TEST2 ("<U0>ab<U0>@2c", 20, 10, Left, "<U0>ab<U0>@2c @4", 0, Good),
|
|
|
|
TEST2 ("x@4096", 4096, 10, 0, "x@4096", 0, Good),
|
|
TEST2 ("x@4096", 4096, 10, Right, "x@4096", 0, Good),
|
|
TEST2 ("x@4096", 4096, 10, Left, "x@4096", 0, Good),
|
|
|
|
TEST2 ("x@4096", 4097, 4097, 0, " x@4096", 0, Good),
|
|
TEST2 ("x@4096", 4097, 4097, Right, " x@4096", 0, Good),
|
|
TEST2 ("x@4096", 4097, 4097, Left, "x@4096 ", 0, Good)
|
|
};
|
|
|
|
/**************************************************************************/
|
|
|
|
template <class charT, class Traits, class Allocator>
|
|
void test_io (charT*, Traits*, Allocator*,
|
|
const StringTestCaseData<charT> &tdata)
|
|
{
|
|
typedef std::basic_string <charT, Traits, Allocator> String;
|
|
typedef MyStreambuf<charT, Traits> Streambuf;
|
|
typedef std::basic_ios<charT, Traits> BasicIos;
|
|
typedef std::basic_istream<charT, Traits> Istream;
|
|
typedef std::basic_ostream<charT, Traits> Ostream;
|
|
|
|
typedef std::ios_base::fmtflags Fmtflags;
|
|
typedef std::ios_base::iostate Iostate;
|
|
|
|
const StringFunc &func = tdata.func_;
|
|
const StringTestCase &tcase = tdata.tcase_;
|
|
|
|
bool test_inserter = func.which_ == StringIds::inserter_ostream_cstr;
|
|
|
|
// construct the string object
|
|
String str (tdata.str_, tdata.strlen_);
|
|
// construct a const reference to the string object
|
|
// for tests exercising output
|
|
const String& cstr (str);
|
|
|
|
static const std::size_t BUFSIZE = 256;
|
|
|
|
static char arg_buf [BUFSIZE];
|
|
|
|
std::size_t arg_len = 0;
|
|
const char* arg = rw_expand (arg_buf, tcase.arg, tcase.arg_len, &arg_len);
|
|
|
|
// prepare arrays of indexes on which force the exception throwing
|
|
const charT* arg_throw = test_inserter ? tdata.str_ : tdata.arg_;
|
|
const std::size_t arg_throw_len =
|
|
test_inserter ? tdata.strlen_ : tdata.arglen_;
|
|
|
|
std::size_t* throw_on = new std::size_t [arg_throw_len + 1];
|
|
std::size_t pthrow = 0;
|
|
for (std::size_t k = 0; k < arg_throw_len; ++k) {
|
|
if (1 == rw_match (&SYMB_THROW, arg_throw + k, 1))
|
|
throw_on [pthrow++] = k + 1;
|
|
}
|
|
throw_on [pthrow] = NPOS;
|
|
|
|
// construct ctype facet to install in each stream's locale
|
|
// (the facet's lifetime must exceed that of the locale in
|
|
// which it is installed, which might include both the stream
|
|
// and the stream's streambuf)
|
|
const UserCtype<charT> ctyp (1);
|
|
|
|
// set the initial formatting flags in both streams
|
|
const Fmtflags flags = Fmtflags (tcase.size);
|
|
|
|
// save the state of the const string object before the call
|
|
// to any (changes to the state of the object after a call)
|
|
const StringState cstr_state (rw_get_string_state (cstr));
|
|
|
|
// Xsgetn, Sync, Xsputn
|
|
std::size_t throw_count [] = { 1, 1, 1 };
|
|
std::size_t throw_inx = 0;
|
|
|
|
while (1) {
|
|
|
|
Streambuf inbuf (arg, arg_len, Throw | Underflow | Sync | Xsgetn, -1);
|
|
|
|
Streambuf outbuf (std::streamsize (tcase.arg_len),
|
|
Throw | Overflow | Sync | Xsputn, -1);
|
|
|
|
Streambuf& sbuf = test_inserter ? outbuf : inbuf;
|
|
|
|
#ifndef _RWSTD_NO_EXCEPTIONS
|
|
|
|
// (name of) expected and caught exception
|
|
const char* expected = 0;
|
|
const char* caught = 0;
|
|
|
|
if (1 == tcase.bthrow) {
|
|
expected = exceptions [1]; // ios_base::failure
|
|
}
|
|
else if (0 == tcase.bthrow) {
|
|
// set on which call of which method to throw
|
|
sbuf.throw_when_ [sbuf.memfun_inx (
|
|
test_inserter ? Overflow : Underflow) ] = throw_on [throw_inx];
|
|
|
|
sbuf.throw_when_ [sbuf.memfun_inx (Xsgetn)] =
|
|
throw_count [0];
|
|
sbuf.throw_when_ [sbuf.memfun_inx (Sync)] =
|
|
throw_count [1];
|
|
sbuf.throw_when_ [sbuf.memfun_inx (Xsputn)] =
|
|
throw_count [2];
|
|
}
|
|
else {
|
|
// exceptions disabled for this test case
|
|
}
|
|
|
|
#else // if defined (_RWSTD_NO_EXCEPTIONS)
|
|
|
|
if (tcase.bthrow)
|
|
return;
|
|
|
|
#endif // _RWSTD_NO_EXCEPTIONS
|
|
|
|
// construct both stream objects even though only one will be used
|
|
Istream is (&inbuf);
|
|
Ostream os (&outbuf);
|
|
|
|
// base referes to the basic_ios subobject of the stream used in
|
|
// each test case (to avoid unnecessarily manipulating both streams)
|
|
BasicIos &strm = test_inserter ? (BasicIos&)os : (BasicIos&)is;
|
|
|
|
// install std::ctype<UserChar> facet
|
|
strm.imbue (std::locale (strm.getloc (), &ctyp));
|
|
|
|
// set the initial width of both streams
|
|
strm.width (tcase.off);
|
|
|
|
strm.flags (flags);
|
|
|
|
const Iostate state = Iostate (tcase.off2);
|
|
|
|
if (tcase.bthrow) {
|
|
// set exception bits leaving the initial stream state good
|
|
strm.exceptions (state);
|
|
}
|
|
else {
|
|
// set the initial stream state leaving exceptions clear
|
|
strm.clear (state);
|
|
}
|
|
|
|
// start checking for memory leaks
|
|
rw_check_leaks (str.get_allocator ());
|
|
|
|
bool streambuf_threw = false;
|
|
|
|
try {
|
|
|
|
// the offset of the address of the returned reference
|
|
// from the address of the stream object argument (the
|
|
// two must be the same)
|
|
std::ptrdiff_t ret_off = 0;
|
|
|
|
try {
|
|
switch (func.which_) {
|
|
|
|
case StringIds::extractor_istream_str:
|
|
ret_off = &is - &(is >> str);
|
|
break;
|
|
|
|
case StringIds::getline_istream_str:
|
|
ret_off = &is - &std::getline (is, str);
|
|
break;
|
|
|
|
case StringIds::getline_istream_str_val: {
|
|
const charT delim = make_char (tcase.val, (charT*)0);
|
|
ret_off = &is - &std::getline (is, str, delim);
|
|
break;
|
|
}
|
|
|
|
case StringIds::inserter_ostream_cstr:
|
|
ret_off = &os - &(os << cstr);
|
|
break;
|
|
|
|
default:
|
|
RW_ASSERT (!"test logic error: unknown io overload");
|
|
return;
|
|
}
|
|
}
|
|
#ifndef _RWSTD_NO_EXCEPTIONS
|
|
|
|
catch (std::ios_base::failure& 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 (...) {
|
|
caught = exceptions [0];
|
|
rw_assert (0, 0, tcase.line,
|
|
"line %d. %{$FUNCALL} %{?}expected %s,%{:}"
|
|
"unexpectedly%{;} caught %s",
|
|
__LINE__, 0 != expected, expected, caught);
|
|
}
|
|
|
|
#endif // _RWSTD_NO_EXCEPTIONS
|
|
|
|
const std::streamsize ret_width = strm.width ();
|
|
const Iostate ret_state = strm.rdstate ();
|
|
const charT* ret_str = str.data ();
|
|
std::size_t ret_sz = str.size ();
|
|
|
|
if (test_inserter) {
|
|
ret_str = outbuf.pubpbase ();
|
|
ret_sz = outbuf.pubepptr () - ret_str;
|
|
}
|
|
|
|
streambuf_threw = None != sbuf.threw_;
|
|
|
|
if (streambuf_threw) {
|
|
if (Overflow == sbuf.threw_ || Underflow == sbuf.threw_)
|
|
throw_inx++;
|
|
if (Xsgetn == sbuf.threw_)
|
|
throw_count [0] ++;
|
|
if (Sync == sbuf.threw_)
|
|
throw_count [1] ++;
|
|
if (Xsputn == sbuf.threw_)
|
|
throw_count [2] ++;
|
|
}
|
|
|
|
// character width (for convenience)
|
|
static const int cwidth = sizeof (charT);
|
|
|
|
// verify that the reference returned from the function
|
|
// refers to the passed stream object
|
|
bool success = 0 == ret_off;
|
|
rw_assert (success, 0, tcase.line,
|
|
"line %d. %{$FUNCALL} returned invalid reference, "
|
|
"offset is %td", __LINE__, ret_off);
|
|
|
|
if (!streambuf_threw) {
|
|
// verify the width
|
|
|
|
const std::streamsize width =
|
|
func.which_ == StringIds::getline_istream_str
|
|
|| func.which_ == StringIds::getline_istream_str_val
|
|
#ifndef _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE
|
|
|| func.which_ == StringIds::inserter_ostream_cstr
|
|
&& ret_state != Good
|
|
#endif // _RWSTD_NO_EXT_KEEP_WIDTH_ON_FAILURE
|
|
? tcase.off : tcase.val;
|
|
|
|
success = width == ret_width;
|
|
rw_assert (success, 0, tcase.line,
|
|
"line %d. %{$FUNCALL}: expected width() == %td, "
|
|
"got %td", __LINE__, width, ret_width);
|
|
}
|
|
|
|
// tcase.size2 is the expected iostate
|
|
if (0 <= tcase.size2) {
|
|
|
|
// verify the iostate
|
|
const Iostate res_state =
|
|
streambuf_threw ? Bad : Iostate (tcase.size2);
|
|
|
|
success = res_state ?
|
|
(res_state == (ret_state & res_state)) : (0 == ret_state);
|
|
rw_assert (success, 0, tcase.line,
|
|
"line %d. %{$FUNCALL}: expected rdstate() "
|
|
"== %{Is}, got %{Is}",
|
|
__LINE__, res_state, ret_state);
|
|
}
|
|
|
|
if ( !streambuf_threw
|
|
|| Overflow == sbuf.threw_ || Underflow == sbuf.threw_) {
|
|
|
|
std::size_t res_sz = streambuf_threw ?
|
|
sbuf.throw_when_ [sbuf.memfun_inx (sbuf.threw_)] - 1 :
|
|
tdata.reslen_;
|
|
|
|
// verify that strings length are equal
|
|
success = res_sz == ret_sz;
|
|
rw_assert (success, 0, tcase.line,
|
|
"line %d. %{$FUNCALL}: expected %{/*.*Gs} with "
|
|
"length %zu, got %{/*.*Gs} with length %zu",
|
|
__LINE__,
|
|
cwidth, int (res_sz), tdata.res_, res_sz,
|
|
cwidth, int (ret_sz), ret_str, ret_sz);
|
|
|
|
if (res_sz == ret_sz) {
|
|
// 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_str, ret_sz);
|
|
|
|
success = match == res_sz;
|
|
rw_assert (success, 0, tcase.line,
|
|
"line %d. %{$FUNCALL}: expected %{/*.*Gs}, "
|
|
"got %{/*.*Gs}, difference at off %zu",
|
|
__LINE__, cwidth, int (res_sz), tdata.res_,
|
|
cwidth, int (ret_sz), ret_str, match);
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifndef _RWSTD_NO_EXCEPTIONS
|
|
|
|
catch (const std::bad_alloc &ex) {
|
|
caught = exceptions [2];
|
|
rw_assert (0, 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 [3];
|
|
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);
|
|
}
|
|
|
|
#endif // _RWSTD_NO_EXCEPTIONS
|
|
|
|
// FIXME: verify the number of blocks the function call
|
|
// is expected to allocate and detect any memory leaks
|
|
rw_check_leaks (str.get_allocator (), tcase.line,
|
|
std::size_t (-1), std::size_t (-1));
|
|
|
|
if (streambuf_threw && 0 == tcase.bthrow) {
|
|
// call the function again until streambuf methods
|
|
// not throws the exception
|
|
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);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (StringIds::fid_inserter == (StringIds::fid_mask & int (func.which_))) {
|
|
// verify that const string object was not modified during
|
|
// the call to the inserter (input functions may, obviously,
|
|
// modify it)
|
|
cstr_state.assert_equal (rw_get_string_state (cstr),
|
|
__LINE__, tcase.line, "call");
|
|
}
|
|
|
|
if (arg != arg_buf)
|
|
delete[] arg;
|
|
|
|
arg = 0;
|
|
|
|
if (throw_on)
|
|
delete[] throw_on;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
|
|
DEFINE_STRING_TEST_FUNCTIONS (test_io);
|
|
|
|
int main (int argc, char** argv)
|
|
{
|
|
static const StringTest
|
|
tests [] = {
|
|
|
|
#undef TEST
|
|
#define TEST(gsig, sig) { \
|
|
gsig, sig ## _test_cases, \
|
|
sizeof sig ## _test_cases / sizeof *sig ## _test_cases \
|
|
}
|
|
|
|
TEST (StringIds::extractor_istream_str, extractor),
|
|
TEST (StringIds::inserter_ostream_cstr, inserter),
|
|
TEST (StringIds::getline_istream_str, getline),
|
|
TEST (StringIds::getline_istream_str_val, getline_val)
|
|
};
|
|
|
|
const std::size_t test_count = sizeof tests / sizeof *tests;
|
|
|
|
return rw_run_string_test (argc, argv, __FILE__,
|
|
"lib.string.io",
|
|
test_io_func_array, tests, test_count);
|
|
}
|