269 lines
9.5 KiB
C++
269 lines
9.5 KiB
C++
/*
|
|
* 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;
|
|
}
|