| /* |
| * Distributed under the Boost Software License, Version 1.0.(See accompanying |
| * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) |
| * |
| * See http://www.boost.org/libs/iostreams for documentation. |
| * |
| * Tests the facilities defined in the header |
| * libs/iostreams/test/detail/operation_sequence.hpp |
| * |
| * File: libs/iostreams/test/operation_sequence_test.cpp |
| * Date: Mon Dec 10 18:58:19 MST 2007 |
| * Copyright: 2007-2008 CodeRage, LLC |
| * Author: Jonathan Turkanis |
| * Contact: turkanis at coderage dot com |
| */ |
| |
| #include <stdexcept> |
| #include <boost/test/test_tools.hpp> |
| #include <boost/test/unit_test.hpp> |
| #include "detail/operation_sequence.hpp" |
| |
| using namespace std; |
| using namespace boost; |
| using namespace boost::iostreams::test; |
| using boost::unit_test::test_suite; |
| |
| // Infrastructure for checking that operations are |
| // executed in the correct order |
| |
| void operation_sequence_test() |
| { |
| // Test creating a duplicate operation |
| { |
| operation_sequence seq; |
| operation op = seq.new_operation(1); |
| BOOST_CHECK_THROW(seq.new_operation(1), runtime_error); |
| } |
| |
| // Test reusing an operation id after first operation is destroyed |
| { |
| operation_sequence seq; |
| seq.new_operation(1); |
| BOOST_CHECK_NO_THROW(seq.new_operation(1)); |
| } |
| |
| // Test creating operations with illegal error codes |
| { |
| operation_sequence seq; |
| BOOST_CHECK_THROW(seq.new_operation(1, -100), runtime_error); |
| BOOST_CHECK_THROW( |
| seq.new_operation(1, BOOST_IOSTREAMS_TEST_MAX_OPERATION_ERROR + 1), |
| runtime_error |
| ); |
| } |
| |
| // Test two successful operations executed out of order |
| { |
| operation_sequence seq; |
| operation op1 = seq.new_operation(1); |
| operation op2 = seq.new_operation(2); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| BOOST_CHECK_NO_THROW(op2.execute()); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| BOOST_CHECK_NO_THROW(op1.execute()); |
| BOOST_CHECK(seq.is_failure()); |
| } |
| |
| // Test executing an operation twice without resetting the sequence |
| { |
| operation_sequence seq; |
| operation op = seq.new_operation(1); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| BOOST_CHECK_NO_THROW(op.execute()); |
| BOOST_CHECK(seq.is_success()); |
| BOOST_CHECK_NO_THROW(op.execute()); |
| BOOST_CHECK(seq.is_failure()); |
| } |
| |
| // Test creating an operation after operation execution has commenced |
| { |
| operation_sequence seq; |
| operation op1 = seq.new_operation(1); |
| operation op2 = seq.new_operation(2); |
| operation op3; |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| BOOST_CHECK_NO_THROW(op1.execute()); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| BOOST_CHECK_THROW(op3 = seq.new_operation(3), runtime_error); |
| BOOST_CHECK_NO_THROW(op2.execute()); |
| BOOST_CHECK(seq.is_success()); |
| } |
| |
| // Test three successful operations with consecutive ids, executed in order |
| { |
| operation_sequence seq; |
| operation op1 = seq.new_operation(1); |
| operation op2 = seq.new_operation(2); |
| operation op3 = seq.new_operation(3); |
| |
| // First pass |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op1.execute(); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op2.execute(); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op3.execute(); |
| BOOST_CHECK(seq.is_success()); |
| |
| // Second pass |
| seq.reset(); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op1.execute(); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op2.execute(); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op3.execute(); |
| BOOST_CHECK(seq.is_success()); |
| } |
| |
| // Test three successful operations with non-consecutive ids, |
| // executed in order |
| { |
| operation_sequence seq; |
| operation op2 = seq.new_operation(2); |
| operation op3 = seq.new_operation(101); |
| operation op1 = seq.new_operation(-43); |
| |
| // First pass |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op1.execute(); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op2.execute(); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op3.execute(); |
| BOOST_CHECK(seq.is_success()); |
| |
| // Second pass |
| seq.reset(); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op1.execute(); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op2.execute(); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op3.execute(); |
| BOOST_CHECK(seq.is_success()); |
| } |
| |
| // Test checking for success after one of three operations |
| // has been destroyed |
| { |
| operation_sequence seq; |
| operation op1 = seq.new_operation(1); |
| operation op3 = seq.new_operation(3); |
| |
| { |
| operation op2 = seq.new_operation(2); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op1.execute(); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op2.execute(); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op3.execute(); |
| } |
| BOOST_CHECK(seq.is_success()); |
| } |
| |
| // Test executing an operation sequence twice, with one of the |
| // operations replaced with a new operation with the same id |
| // in the second pass |
| { |
| operation_sequence seq; |
| operation op1 = seq.new_operation(1); |
| operation op3 = seq.new_operation(3); |
| |
| // First pass |
| { |
| operation op2 = seq.new_operation(2); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op1.execute(); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op2.execute(); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op3.execute(); |
| BOOST_CHECK(seq.is_success()); |
| } |
| |
| // Second pass |
| seq.reset(); |
| { |
| operation op2 = seq.new_operation(2); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op1.execute(); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op2.execute(); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| op3.execute(); |
| BOOST_CHECK(seq.is_success()); |
| } |
| } |
| |
| // Test three operations executed in order, the first of which throws |
| { |
| operation_sequence seq; |
| operation op1 = seq.new_operation(1, 1); |
| operation op2 = seq.new_operation(2); |
| operation op3 = seq.new_operation(3); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| BOOST_CHECK_THROW(op1.execute(), operation_error<1>); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| BOOST_CHECK_NO_THROW(op2.execute()); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| BOOST_CHECK_NO_THROW(op3.execute()); |
| BOOST_CHECK(seq.is_success()); |
| } |
| |
| // Test three operations executed in order, the second of which throws |
| { |
| operation_sequence seq; |
| operation op1 = seq.new_operation(1); |
| operation op2 = seq.new_operation(2, 2); |
| operation op3 = seq.new_operation(3); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| BOOST_CHECK_NO_THROW(op1.execute()); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| BOOST_CHECK_THROW(op2.execute(), operation_error<2>); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| BOOST_CHECK_NO_THROW(op3.execute()); |
| BOOST_CHECK(seq.is_success()); |
| } |
| |
| // Test three operations executed in order, the third of which throws |
| { |
| operation_sequence seq; |
| operation op1 = seq.new_operation(1); |
| operation op2 = seq.new_operation(2); |
| operation op3 = seq.new_operation(3, 3); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| BOOST_CHECK_NO_THROW(op1.execute()); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| BOOST_CHECK_NO_THROW(op2.execute()); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| BOOST_CHECK_THROW(op3.execute(), operation_error<3>); |
| BOOST_CHECK(seq.is_success()); |
| } |
| |
| // Test three operations executed in order, the first and |
| // third of which throw |
| { |
| operation_sequence seq; |
| operation op1 = seq.new_operation(1, 1); |
| operation op2 = seq.new_operation(2); |
| operation op3 = seq.new_operation(3, 3); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| BOOST_CHECK_THROW(op1.execute(), operation_error<1>); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| BOOST_CHECK_NO_THROW(op2.execute()); |
| BOOST_CHECK(!seq.is_failure() && !seq.is_success()); |
| BOOST_CHECK_THROW(op3.execute(), operation_error<3>); |
| BOOST_CHECK(seq.is_success()); |
| } |
| } |
| |
| test_suite* init_unit_test_suite(int, char* []) |
| { |
| test_suite* test = BOOST_TEST_SUITE("execute test"); |
| test->add(BOOST_TEST_CASE(&operation_sequence_test)); |
| return test; |
| } |