1 /*
2 * ====================================================================
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 * ====================================================================
20 */
21 #include <boost/test/unit_test.hpp>
22
23 #include <algorithm>
24 #include <cstdio>
25 #include <iomanip>
26 #include <ios>
27 #include <iostream>
28
29 #include "../src/private/exception_private.hpp"
30
31 namespace svn = ::apache::subversion::svnxx;
32 namespace impl = ::apache::subversion::svnxx::impl;
33
34 #include "fixture_init.hpp"
35
36 BOOST_AUTO_TEST_SUITE(exceptions,
37 * boost::unit_test::fixture<init>());
38
39 namespace {
make_error_test_error()40 svn_error_t* make_error_test_error()
41 {
42 svn_error_t* err;
43 err = svn_error_create(SVN_ERR_TEST_FAILED, NULL, "original message");
44 err = svn_error_create(SVN_ERR_BASE, err, "wrapper message");
45 err = svn_error_trace(err);
46 err = svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, err, NULL);
47 err = svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, err, NULL);
48 err = svn_error_trace(err);
49 return err;
50 }
51 } // anonymous namespace
52
BOOST_AUTO_TEST_CASE(thrown_error)53 BOOST_AUTO_TEST_CASE(thrown_error)
54 {
55 BOOST_CHECK_THROW(
56 impl::checked_call(make_error_test_error()),
57 svn::error);
58 }
59
BOOST_AUTO_TEST_CASE(catch_error)60 BOOST_AUTO_TEST_CASE(catch_error)
61 {
62 BOOST_CHECK_THROW(
63 impl::checked_call(make_error_test_error()),
64 svn::error);
65
66 try
67 {
68 impl::checked_call(make_error_test_error());
69 }
70 catch (const svn::error& err)
71 {
72 BOOST_TEST(err.code() == SVN_ERR_UNSUPPORTED_FEATURE);
73 BOOST_TEST(err.name() == "SVN_ERR_UNSUPPORTED_FEATURE");
74 BOOST_TEST(err.what() == "Trying to use an unsupported feature");
75
76 auto ml = err.messages();
77 BOOST_TEST(ml.size() == 3);
78 BOOST_TEST(ml[0].code() == SVN_ERR_UNSUPPORTED_FEATURE);
79 BOOST_TEST(ml[0].name() == "SVN_ERR_UNSUPPORTED_FEATURE");
80 BOOST_TEST(ml[1].code() == SVN_ERR_BASE);
81 BOOST_TEST(ml[1].name() == "SVN_ERR_BASE");
82 BOOST_TEST(ml[1].text() == "wrapper message");
83 BOOST_TEST(ml[2].code() == SVN_ERR_TEST_FAILED);
84 BOOST_TEST(ml[2].name() == "SVN_ERR_TEST_FAILED");
85 BOOST_TEST(ml[2].text() == "original message");
86
87 auto tml = err.traced_messages();
88 #ifdef SVN_DEBUG
89 BOOST_TEST(tml.size() == 8);
90 BOOST_TEST(tml[0].code() == SVN_ERR_UNSUPPORTED_FEATURE);
91 BOOST_TEST(tml[1].code() == SVN_ERR_UNSUPPORTED_FEATURE);
92 BOOST_TEST(tml[2].code() == SVN_ERR_UNSUPPORTED_FEATURE);
93 BOOST_TEST(tml[3].code() == SVN_ERR_BASE);
94 BOOST_TEST(tml[4].code() == SVN_ERR_BASE);
95 BOOST_TEST(tml[5].code() == SVN_ERR_BASE);
96 BOOST_TEST(tml[6].code() == SVN_ERR_TEST_FAILED);
97 BOOST_TEST(tml[7].code() == SVN_ERR_TEST_FAILED);
98 #else // !SVN_DEBUG
99 BOOST_TEST(tml.size() == 3);
100 BOOST_TEST(tml[0].code() == SVN_ERR_UNSUPPORTED_FEATURE);
101 BOOST_TEST(tml[1].code() == SVN_ERR_BASE);
102 BOOST_TEST(tml[2].code() == SVN_ERR_TEST_FAILED);
103 #endif // SVN_DEBUG
104 }
105 }
106
BOOST_AUTO_TEST_CASE(propagate_error)107 BOOST_AUTO_TEST_CASE(propagate_error)
108 {
109 std::exception_ptr xptr;
110 try
111 {
112 impl::checked_call(make_error_test_error());
113 }
114 catch (...)
115 {
116 xptr = std::current_exception();
117 }
118 BOOST_REQUIRE(xptr);
119 BOOST_CHECK_THROW(std::rethrow_exception(xptr), svn::error);
120 }
121
122
123 namespace {
make_cancel_test_error()124 svn_error_t* make_cancel_test_error()
125 {
126 svn_error_t* err;
127 err = svn_error_create(SVN_ERR_CANCELLED, NULL, NULL);
128 err = svn_error_create(SVN_ERR_CANCELLED, err, NULL);
129 err = svn_error_trace(err);
130 err = svn_error_create(SVN_ERR_TEST_FAILED, err, "original message");
131 err = svn_error_create(SVN_ERR_BASE, err, "wrapper message");
132 err = svn_error_trace(err);
133 return err;
134 }
135 } // anonymous namespace
136
BOOST_AUTO_TEST_CASE(thtrown_cancelled)137 BOOST_AUTO_TEST_CASE(thtrown_cancelled)
138 {
139 BOOST_CHECK_THROW(
140 impl::checked_call(make_cancel_test_error()),
141 svn::cancelled);
142 }
143
BOOST_AUTO_TEST_CASE(catch_cancelled)144 BOOST_AUTO_TEST_CASE(catch_cancelled)
145 {
146 try
147 {
148 impl::checked_call(make_cancel_test_error());
149 }
150 catch (const svn::cancelled& err)
151 {
152 BOOST_TEST(err.code() == SVN_ERR_BASE);
153 BOOST_TEST(err.name() == "SVN_ERR_BASE");
154 BOOST_TEST(err.what() == "wrapper message");
155
156 auto ml = err.messages();
157 BOOST_TEST(ml.size() == 3);
158 BOOST_TEST(ml[0].code() == SVN_ERR_BASE);
159 BOOST_TEST(ml[0].name() == "SVN_ERR_BASE");
160 BOOST_TEST(ml[0].text() == "wrapper message");
161 BOOST_TEST(ml[1].code() == SVN_ERR_TEST_FAILED);
162 BOOST_TEST(ml[1].name() == "SVN_ERR_TEST_FAILED");
163 BOOST_TEST(ml[1].text() == "original message");
164 BOOST_TEST(ml[2].code() == SVN_ERR_CANCELLED);
165 BOOST_TEST(ml[2].name() == "SVN_ERR_CANCELLED");
166
167 auto tml = err.traced_messages();
168 #ifdef SVN_DEBUG
169 BOOST_TEST(tml.size() == 8);
170 BOOST_TEST(tml[0].code() == SVN_ERR_BASE);
171 BOOST_TEST(tml[1].code() == SVN_ERR_BASE);
172 BOOST_TEST(tml[2].code() == SVN_ERR_BASE);
173 BOOST_TEST(tml[3].code() == SVN_ERR_TEST_FAILED);
174 BOOST_TEST(tml[4].code() == SVN_ERR_TEST_FAILED);
175 BOOST_TEST(tml[5].code() == SVN_ERR_CANCELLED);
176 BOOST_TEST(tml[6].code() == SVN_ERR_CANCELLED);
177 BOOST_TEST(tml[7].code() == SVN_ERR_CANCELLED);
178 #else // !SVN_DEBUG
179 BOOST_TEST(tml.size() == 3);
180 BOOST_TEST(tml[0].code() == SVN_ERR_BASE);
181 BOOST_TEST(tml[1].code() == SVN_ERR_TEST_FAILED);
182 BOOST_TEST(tml[2].code() == SVN_ERR_CANCELLED);
183 #endif // SVN_DEBUG
184 }
185 }
186
BOOST_AUTO_TEST_CASE(propagate_cancelled)187 BOOST_AUTO_TEST_CASE(propagate_cancelled)
188 {
189 std::exception_ptr xptr;
190 try
191 {
192 impl::checked_call(make_cancel_test_error());
193 }
194 catch (...)
195 {
196 xptr = std::current_exception();
197 }
198 BOOST_REQUIRE(xptr);
199 BOOST_CHECK_THROW(std::rethrow_exception(xptr), svn::cancelled);
200 }
201
BOOST_AUTO_TEST_CASE(iteration_stopped_cancels)202 BOOST_AUTO_TEST_CASE(iteration_stopped_cancels)
203 {
204 BOOST_CHECK_THROW(
205 impl::checked_call(impl::iteration_stopped()),
206 svn::cancelled);
207 }
208
BOOST_AUTO_TEST_CASE(iteration_stopped)209 BOOST_AUTO_TEST_CASE(iteration_stopped)
210 {
211 try
212 {
213 impl::checked_call(impl::iteration_stopped());
214 }
215 catch (const svn::cancelled& err)
216 {
217 BOOST_TEST(err.code() == SVN_ERR_ITER_BREAK);
218 BOOST_TEST(err.name() == "SVN_ERR_ITER_BREAK");
219 BOOST_TEST(err.what() == "Iteration terminated before completion");
220
221 auto ml = err.messages();
222 BOOST_TEST(ml.size() == 1);
223 BOOST_TEST(ml[0].code() == SVN_ERR_ITER_BREAK);
224 BOOST_TEST(ml[0].name() == "SVN_ERR_ITER_BREAK");
225 BOOST_TEST(ml[0].text() == "Iteration terminated before completion");
226 }
227 }
228
229 BOOST_AUTO_TEST_SUITE_END();
230