blob: b03b8e07079a893885b5a8c143c55fcaeee8d3f4 [file] [log] [blame]
/*
* 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;
}