1/*
2 * Distributed under the Boost Software License, Version 1.0.(See accompanying
3 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
4 *
5 * See http://www.boost.org/libs/iostreams for documentation.
6 *
7 * Tests the facilities defined in the header
8 * libs/iostreams/test/detail/operation_sequence.hpp
9 *
10 * File: libs/iostreams/test/operation_sequence_test.cpp
11 * Date: Mon Dec 10 18:58:19 MST 2007
12 * Copyright: 2007-2008 CodeRage, LLC
13 * Author: Jonathan Turkanis
14 * Contact: turkanis at coderage dot com
15 */
16
17#include <stdexcept>
18#include <boost/test/test_tools.hpp>
19#include <boost/test/unit_test.hpp>
20#include "detail/operation_sequence.hpp"
21
22using namespace std;
23using namespace boost;
24using namespace boost::iostreams::test;
25using boost::unit_test::test_suite;
26
27 // Infrastructure for checking that operations are
28 // executed in the correct order
29
30void operation_sequence_test()
31{
32 // Test creating a duplicate operation
33 {
34 operation_sequence seq;
35 operation op = seq.new_operation(id: 1);
36 BOOST_CHECK_THROW(seq.new_operation(1), runtime_error);
37 }
38
39 // Test reusing an operation id after first operation is destroyed
40 {
41 operation_sequence seq;
42 seq.new_operation(id: 1);
43 BOOST_CHECK_NO_THROW(seq.new_operation(1));
44 }
45
46 // Test creating operations with illegal error codes
47 {
48 operation_sequence seq;
49 BOOST_CHECK_THROW(seq.new_operation(1, -100), runtime_error);
50 BOOST_CHECK_THROW(
51 seq.new_operation(1, BOOST_IOSTREAMS_TEST_MAX_OPERATION_ERROR + 1),
52 runtime_error
53 );
54 }
55
56 // Test two successful operations executed out of order
57 {
58 operation_sequence seq;
59 operation op1 = seq.new_operation(id: 1);
60 operation op2 = seq.new_operation(id: 2);
61 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
62 BOOST_CHECK_NO_THROW(op2.execute());
63 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
64 BOOST_CHECK_NO_THROW(op1.execute());
65 BOOST_CHECK(seq.is_failure());
66 }
67
68 // Test executing an operation twice without resetting the sequence
69 {
70 operation_sequence seq;
71 operation op = seq.new_operation(id: 1);
72 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
73 BOOST_CHECK_NO_THROW(op.execute());
74 BOOST_CHECK(seq.is_success());
75 BOOST_CHECK_NO_THROW(op.execute());
76 BOOST_CHECK(seq.is_failure());
77 }
78
79 // Test creating an operation after operation execution has commenced
80 {
81 operation_sequence seq;
82 operation op1 = seq.new_operation(id: 1);
83 operation op2 = seq.new_operation(id: 2);
84 operation op3;
85 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
86 BOOST_CHECK_NO_THROW(op1.execute());
87 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
88 BOOST_CHECK_THROW(op3 = seq.new_operation(3), runtime_error);
89 BOOST_CHECK_NO_THROW(op2.execute());
90 BOOST_CHECK(seq.is_success());
91 }
92
93 // Test three successful operations with consecutive ids, executed in order
94 {
95 operation_sequence seq;
96 operation op1 = seq.new_operation(id: 1);
97 operation op2 = seq.new_operation(id: 2);
98 operation op3 = seq.new_operation(id: 3);
99
100 // First pass
101 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
102 op1.execute();
103 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
104 op2.execute();
105 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
106 op3.execute();
107 BOOST_CHECK(seq.is_success());
108
109 // Second pass
110 seq.reset();
111 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
112 op1.execute();
113 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
114 op2.execute();
115 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
116 op3.execute();
117 BOOST_CHECK(seq.is_success());
118 }
119
120 // Test three successful operations with non-consecutive ids,
121 // executed in order
122 {
123 operation_sequence seq;
124 operation op2 = seq.new_operation(id: 2);
125 operation op3 = seq.new_operation(id: 101);
126 operation op1 = seq.new_operation(id: -43);
127
128 // First pass
129 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
130 op1.execute();
131 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
132 op2.execute();
133 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
134 op3.execute();
135 BOOST_CHECK(seq.is_success());
136
137 // Second pass
138 seq.reset();
139 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
140 op1.execute();
141 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
142 op2.execute();
143 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
144 op3.execute();
145 BOOST_CHECK(seq.is_success());
146 }
147
148 // Test checking for success after one of three operations
149 // has been destroyed
150 {
151 operation_sequence seq;
152 operation op1 = seq.new_operation(id: 1);
153 operation op3 = seq.new_operation(id: 3);
154
155 {
156 operation op2 = seq.new_operation(id: 2);
157 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
158 op1.execute();
159 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
160 op2.execute();
161 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
162 op3.execute();
163 }
164 BOOST_CHECK(seq.is_success());
165 }
166
167 // Test executing an operation sequence twice, with one of the
168 // operations replaced with a new operation with the same id
169 // in the second pass
170 {
171 operation_sequence seq;
172 operation op1 = seq.new_operation(id: 1);
173 operation op3 = seq.new_operation(id: 3);
174
175 // First pass
176 {
177 operation op2 = seq.new_operation(id: 2);
178 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
179 op1.execute();
180 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
181 op2.execute();
182 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
183 op3.execute();
184 BOOST_CHECK(seq.is_success());
185 }
186
187 // Second pass
188 seq.reset();
189 {
190 operation op2 = seq.new_operation(id: 2);
191 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
192 op1.execute();
193 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
194 op2.execute();
195 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
196 op3.execute();
197 BOOST_CHECK(seq.is_success());
198 }
199 }
200
201 // Test three operations executed in order, the first of which throws
202 {
203 operation_sequence seq;
204 operation op1 = seq.new_operation(id: 1, error_code: 1);
205 operation op2 = seq.new_operation(id: 2);
206 operation op3 = seq.new_operation(id: 3);
207 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
208 BOOST_CHECK_THROW(op1.execute(), operation_error<1>);
209 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
210 BOOST_CHECK_NO_THROW(op2.execute());
211 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
212 BOOST_CHECK_NO_THROW(op3.execute());
213 BOOST_CHECK(seq.is_success());
214 }
215
216 // Test three operations executed in order, the second of which throws
217 {
218 operation_sequence seq;
219 operation op1 = seq.new_operation(id: 1);
220 operation op2 = seq.new_operation(id: 2, error_code: 2);
221 operation op3 = seq.new_operation(id: 3);
222 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
223 BOOST_CHECK_NO_THROW(op1.execute());
224 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
225 BOOST_CHECK_THROW(op2.execute(), operation_error<2>);
226 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
227 BOOST_CHECK_NO_THROW(op3.execute());
228 BOOST_CHECK(seq.is_success());
229 }
230
231 // Test three operations executed in order, the third of which throws
232 {
233 operation_sequence seq;
234 operation op1 = seq.new_operation(id: 1);
235 operation op2 = seq.new_operation(id: 2);
236 operation op3 = seq.new_operation(id: 3, error_code: 3);
237 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
238 BOOST_CHECK_NO_THROW(op1.execute());
239 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
240 BOOST_CHECK_NO_THROW(op2.execute());
241 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
242 BOOST_CHECK_THROW(op3.execute(), operation_error<3>);
243 BOOST_CHECK(seq.is_success());
244 }
245
246 // Test three operations executed in order, the first and
247 // third of which throw
248 {
249 operation_sequence seq;
250 operation op1 = seq.new_operation(id: 1, error_code: 1);
251 operation op2 = seq.new_operation(id: 2);
252 operation op3 = seq.new_operation(id: 3, error_code: 3);
253 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
254 BOOST_CHECK_THROW(op1.execute(), operation_error<1>);
255 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
256 BOOST_CHECK_NO_THROW(op2.execute());
257 BOOST_CHECK(!seq.is_failure() && !seq.is_success());
258 BOOST_CHECK_THROW(op3.execute(), operation_error<3>);
259 BOOST_CHECK(seq.is_success());
260 }
261}
262
263test_suite* init_unit_test_suite(int, char* [])
264{
265 test_suite* test = BOOST_TEST_SUITE("execute test");
266 test->add(BOOST_TEST_CASE(&operation_sequence_test));
267 return test;
268}
269

source code of boost/libs/iostreams/test/operation_sequence_test.cpp