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 | |
22 | using namespace std; |
23 | using namespace boost; |
24 | using namespace boost::iostreams::test; |
25 | using boost::unit_test::test_suite; |
26 | |
27 | // Infrastructure for checking that operations are |
28 | // executed in the correct order |
29 | |
30 | void 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 | |
263 | test_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 | |