| /*************************************************************************** |
| * |
| * 21.string.io.cpp - string test exercising lib.string.io |
| * |
| * $Id$ |
| * |
| *************************************************************************** |
| * |
| * Copyright 2006 The Apache Software Foundation or its licensors, |
| * as applicable. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| **************************************************************************/ |
| |
| #include <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); |
| } |