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