Merge lp:~jamesh/storage-framework/convert-exception-ptr into lp:storage-framework/devel

Proposed by James Henstridge
Status: Merged
Approved by: Michi Henning
Approved revision: 125
Merged at revision: 123
Proposed branch: lp:~jamesh/storage-framework/convert-exception-ptr
Merge into: lp:storage-framework/devel
Diff against target: 433 lines (+307/-28)
9 files modified
include/unity/storage/provider/Exceptions.h (+9/-2)
include/unity/storage/provider/internal/utils.h (+38/-0)
src/provider/CMakeLists.txt (+1/-0)
src/provider/internal/DownloadJobImpl.cpp (+2/-13)
src/provider/internal/UploadJobImpl.cpp (+2/-13)
src/provider/internal/utils.cpp (+95/-0)
tests/CMakeLists.txt (+1/-0)
tests/provider-utils/CMakeLists.txt (+8/-0)
tests/provider-utils/utils_test.cpp (+151/-0)
To merge this branch: bzr merge lp:~jamesh/storage-framework/convert-exception-ptr
Reviewer Review Type Date Requested Status
Michi Henning (community) Approve
unity-api-1-bot continuous-integration Approve
Review via email: mp+321251@code.launchpad.net

Commit message

Fix the report_error() methods of DownloadJob and UploadJob to correctly preserve the type of StorageException subclasses.

Description of the change

Make the report_error() methods on DownloadJob and UploadJob correctly preserve the exception type for StorageExceptions.

Previously subclasses of StorageException were being squashed down to the base type, losing additional data members on e.g. ResourceException.

I've also made StorageException's destructor protected, as discussed on IRC.

To post a comment you must log in.
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

PASSED: Continuous integration, rev:124
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/271/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/1880
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1887
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1669
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1669/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/1669
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/1669/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1669
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1669/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/1669
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/1669/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/1669
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/1669/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/1669
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/1669/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/271/rebuild

review: Approve (continuous-integration)
Revision history for this message
Michi Henning (michihenning) wrote :

This looks good!

One request: can you please also replace the existing comment in provider/Exceptions.h with the following:

// Note: Adding new exception types also requires updating the marshaling and
// unmarshaling code for exceptions in provider/internal/Handler.cpp and
// qt/internal/unmarshal_error.cpp, as well as the exception re-throwing
// code in provider/internal/utils.cpp.

It's nice to have my memory jogged when there are internal dependencies such as these :-)

review: Needs Fixing
125. By James Henstridge

Add a note about source files that need to know about all provider
exceptions.

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

PASSED: Continuous integration, rev:125
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/274/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/1885
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1892
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1674
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1674/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/1674
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/1674/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1674
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1674/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/1674
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/1674/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/1674
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/1674/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/1674
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/1674/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/274/rebuild

review: Approve (continuous-integration)
Revision history for this message
Michi Henning (michihenning) wrote :

Sweet!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/unity/storage/provider/Exceptions.h'
2--- include/unity/storage/provider/Exceptions.h 2017-03-09 07:02:46 +0000
3+++ include/unity/storage/provider/Exceptions.h 2017-03-30 02:53:50 +0000
4@@ -29,8 +29,12 @@
5 namespace provider
6 {
7
8-// Note: Adding new exception types also requires updating the marshaling and
9-// unmarshaling code for exceptions in the client and server APIs.
10+// Note: Adding new exception types also requires updating the
11+// marshaling and unmarshaling code for exceptions in the client
12+// and server APIs. In particular:
13+// - src/provider/internal/Handler.cpp
14+// - src/provider/internal/utils.cpp
15+// - src/qt/internal/unmarshal_error.cpp
16
17 /**
18 \brief Base exception class for all server-side exceptions.
19@@ -39,8 +43,11 @@
20 {
21 public:
22 StorageException(std::string const& exception_type, std::string const& error_message);
23+
24+protected:
25 ~StorageException();
26
27+public:
28 virtual char const* what() const noexcept override;
29
30 std::string type() const;
31
32=== added file 'include/unity/storage/provider/internal/utils.h'
33--- include/unity/storage/provider/internal/utils.h 1970-01-01 00:00:00 +0000
34+++ include/unity/storage/provider/internal/utils.h 2017-03-30 02:53:50 +0000
35@@ -0,0 +1,38 @@
36+/*
37+ * Copyright (C) 2017 Canonical Ltd
38+ *
39+ * This program is free software: you can redistribute it and/or modify
40+ * it under the terms of the GNU Lesser General Public License version 3 as
41+ * published by the Free Software Foundation.
42+ *
43+ * This program is distributed in the hope that it will be useful,
44+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
45+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46+ * GNU Lesser General Public License for more details.
47+ *
48+ * You should have received a copy of the GNU Lesser General Public License
49+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
50+ *
51+ * Authors: James Henstridge <james.henstridge@canonical.com>
52+ */
53+
54+#pragma once
55+
56+#include <boost/exception_ptr.hpp>
57+#include <exception>
58+
59+namespace unity
60+{
61+namespace storage
62+{
63+namespace provider
64+{
65+namespace internal
66+{
67+
68+boost::exception_ptr convert_exception_ptr(std::exception_ptr ep);
69+
70+}
71+}
72+}
73+}
74
75=== modified file 'src/provider/CMakeLists.txt'
76--- src/provider/CMakeLists.txt 2017-03-09 08:13:34 +0000
77+++ src/provider/CMakeLists.txt 2017-03-30 02:53:50 +0000
78@@ -34,6 +34,7 @@
79 internal/TestServerImpl.cpp
80 internal/UploadJobImpl.cpp
81 internal/dbusmarshal.cpp
82+ internal/utils.cpp
83 ${CMAKE_SOURCE_DIR}/include/unity/storage/provider/internal/AccountData.h
84 ${CMAKE_SOURCE_DIR}/include/unity/storage/provider/internal/DownloadJobImpl.h
85 ${CMAKE_SOURCE_DIR}/include/unity/storage/provider/internal/FixedAccountData.h
86
87=== modified file 'src/provider/internal/DownloadJobImpl.cpp'
88--- src/provider/internal/DownloadJobImpl.cpp 2016-12-20 03:00:07 +0000
89+++ src/provider/internal/DownloadJobImpl.cpp 2017-03-30 02:53:50 +0000
90@@ -20,6 +20,7 @@
91 #include <unity/storage/internal/safe_strerror.h>
92 #include <unity/storage/provider/DownloadJob.h>
93 #include <unity/storage/provider/Exceptions.h>
94+#include <unity/storage/provider/internal/utils.h>
95
96 #include <sys/socket.h>
97 #include <sys/types.h>
98@@ -133,19 +134,7 @@
99
100 lock_guard<mutex> guard(completion_lock_);
101 completed_ = true;
102- // Convert std::exception_ptr to boost::exception_ptr
103- try
104- {
105- std::rethrow_exception(p);
106- }
107- catch (StorageException const& e)
108- {
109- completion_promise_.set_exception(e);
110- }
111- catch (...)
112- {
113- completion_promise_.set_exception(boost::current_exception());
114- }
115+ completion_promise_.set_exception(convert_exception_ptr(p));
116 }
117
118 boost::future<void> DownloadJobImpl::finish(DownloadJob& job)
119
120=== modified file 'src/provider/internal/UploadJobImpl.cpp'
121--- src/provider/internal/UploadJobImpl.cpp 2016-12-20 03:00:07 +0000
122+++ src/provider/internal/UploadJobImpl.cpp 2017-03-30 02:53:50 +0000
123@@ -21,6 +21,7 @@
124 #include <unity/storage/provider/Exceptions.h>
125 #include <unity/storage/provider/UploadJob.h>
126 #include <unity/storage/provider/internal/MainLoopExecutor.h>
127+#include <unity/storage/provider/internal/utils.h>
128
129 #include <sys/socket.h>
130 #include <sys/types.h>
131@@ -123,19 +124,7 @@
132
133 lock_guard<mutex> guard(completion_lock_);
134 completed_ = true;
135- // Convert std::exception_ptr to boost::exception_ptr
136- try
137- {
138- rethrow_exception(p);
139- }
140- catch (StorageException const& e)
141- {
142- completion_promise_.set_exception(e);
143- }
144- catch (...)
145- {
146- completion_promise_.set_exception(boost::current_exception());
147- }
148+ completion_promise_.set_exception(convert_exception_ptr(p));
149 }
150
151 boost::future<Item> UploadJobImpl::finish(UploadJob& job)
152
153=== added file 'src/provider/internal/utils.cpp'
154--- src/provider/internal/utils.cpp 1970-01-01 00:00:00 +0000
155+++ src/provider/internal/utils.cpp 2017-03-30 02:53:50 +0000
156@@ -0,0 +1,95 @@
157+/*
158+ * Copyright (C) 2017 Canonical Ltd
159+ *
160+ * This program is free software: you can redistribute it and/or modify
161+ * it under the terms of the GNU Lesser General Public License version 3 as
162+ * published by the Free Software Foundation.
163+ *
164+ * This program is distributed in the hope that it will be useful,
165+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
166+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
167+ * GNU Lesser General Public License for more details.
168+ *
169+ * You should have received a copy of the GNU Lesser General Public License
170+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
171+ *
172+ * Authors: James Henstridge <james.henstridge@canonical.com>
173+ */
174+
175+#include <unity/storage/provider/internal/utils.h>
176+#include <unity/storage/provider/Exceptions.h>
177+
178+namespace unity
179+{
180+namespace storage
181+{
182+namespace provider
183+{
184+namespace internal
185+{
186+
187+boost::exception_ptr convert_exception_ptr(std::exception_ptr ep)
188+{
189+ // Convert std::exception_ptr to boost::exception_ptr
190+ try
191+ {
192+ std::rethrow_exception(ep);
193+ }
194+ catch (RemoteCommsException const& e)
195+ {
196+ return boost::copy_exception(e);
197+ }
198+ catch (NotExistsException const& e)
199+ {
200+ return boost::copy_exception(e);
201+ }
202+ catch (ExistsException const& e)
203+ {
204+ return boost::copy_exception(e);
205+ }
206+ catch (ConflictException const& e)
207+ {
208+ return boost::copy_exception(e);
209+ }
210+ catch (UnauthorizedException const& e)
211+ {
212+ return boost::copy_exception(e);
213+ }
214+ catch (PermissionException const& e)
215+ {
216+ return boost::copy_exception(e);
217+ }
218+ catch (QuotaException const& e)
219+ {
220+ return boost::copy_exception(e);
221+ }
222+ catch (CancelledException const& e)
223+ {
224+ return boost::copy_exception(e);
225+ }
226+ catch (LogicException const& e)
227+ {
228+ return boost::copy_exception(e);
229+ }
230+ catch (InvalidArgumentException const& e)
231+ {
232+ return boost::copy_exception(e);
233+ }
234+ catch (ResourceException const& e)
235+ {
236+ return boost::copy_exception(e);
237+ }
238+ catch (UnknownException const& e)
239+ {
240+ return boost::copy_exception(e);
241+ }
242+ catch (...)
243+ {
244+ return boost::current_exception();
245+ }
246+}
247+
248+}
249+}
250+}
251+}
252
253=== modified file 'tests/CMakeLists.txt'
254--- tests/CMakeLists.txt 2017-03-14 07:15:06 +0000
255+++ tests/CMakeLists.txt 2017-03-30 02:53:50 +0000
256@@ -15,6 +15,7 @@
257 provider-DBusPeerCache
258 provider-ProviderInterface
259 provider-Server
260+ provider-utils
261 )
262
263 set(slow_test_dirs
264
265=== added directory 'tests/provider-utils'
266=== added file 'tests/provider-utils/CMakeLists.txt'
267--- tests/provider-utils/CMakeLists.txt 1970-01-01 00:00:00 +0000
268+++ tests/provider-utils/CMakeLists.txt 2017-03-30 02:53:50 +0000
269@@ -0,0 +1,8 @@
270+add_executable(provider-utils_test
271+ utils_test.cpp
272+)
273+target_link_libraries(provider-utils_test
274+ storage-framework-provider-static
275+ gtest
276+)
277+add_test(provider-utils provider-utils_test)
278
279=== added file 'tests/provider-utils/utils_test.cpp'
280--- tests/provider-utils/utils_test.cpp 1970-01-01 00:00:00 +0000
281+++ tests/provider-utils/utils_test.cpp 2017-03-30 02:53:50 +0000
282@@ -0,0 +1,151 @@
283+/*
284+ * Copyright (C) 2017 Canonical Ltd
285+ *
286+ * This program is free software: you can redistribute it and/or modify
287+ * it under the terms of the GNU Lesser General Public License version 3 as
288+ * published by the Free Software Foundation.
289+ *
290+ * This program is distributed in the hope that it will be useful,
291+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
292+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
293+ * GNU Lesser General Public License for more details.
294+ *
295+ * You should have received a copy of the GNU Lesser General Public License
296+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
297+ *
298+ * Authors: James Henstridge <james.henstridge@canonical.com>
299+ */
300+
301+#include <unity/storage/provider/Exceptions.h>
302+#include <unity/storage/provider/internal/utils.h>
303+
304+#pragma GCC diagnostic push
305+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
306+#include <gtest/gtest.h>
307+#pragma GCC diagnostic pop
308+
309+#include <stdexcept>
310+#include <string>
311+
312+using namespace unity::storage::provider;
313+
314+// Helper function to create exceptions, with specialisations for
315+// types with irregular constructors.
316+template <typename Exception>
317+Exception make_exception(std::string const& message)
318+{
319+ return Exception(message);
320+}
321+
322+template<>
323+NotExistsException make_exception<NotExistsException>(std::string const& message)
324+{
325+ return NotExistsException(message, "key");
326+}
327+
328+template<>
329+ExistsException make_exception<ExistsException>(std::string const& message)
330+{
331+ return ExistsException(message, "item_id", "name");
332+}
333+
334+template<>
335+ResourceException make_exception<ResourceException>(std::string const& message)
336+{
337+ return ResourceException(message, 0);
338+}
339+
340+template <typename Ex>
341+class ConvertExceptionTest : public ::testing::Test {
342+};
343+
344+using ExceptionTypes = ::testing::Types<
345+ RemoteCommsException,
346+ NotExistsException,
347+ ExistsException,
348+ ConflictException,
349+ UnauthorizedException,
350+ PermissionException,
351+ QuotaException,
352+ CancelledException,
353+ LogicException,
354+ InvalidArgumentException,
355+ ResourceException,
356+ UnknownException>;
357+
358+TYPED_TEST_CASE(ConvertExceptionTest, ExceptionTypes);
359+
360+TYPED_TEST(ConvertExceptionTest, storage_exception)
361+{
362+ using Exception = TypeParam;
363+ std::string const message = "exception message";
364+
365+ std::exception_ptr sep = std::make_exception_ptr(
366+ make_exception<Exception>(message));
367+
368+ boost::exception_ptr bep = internal::convert_exception_ptr(sep);
369+ try
370+ {
371+ boost::rethrow_exception(bep);
372+ FAIL();
373+ }
374+ catch (Exception const& e)
375+ {
376+ EXPECT_EQ(message, e.error_message());
377+ }
378+}
379+
380+class CustomException : public std::exception
381+{
382+public:
383+ virtual char const* what() const noexcept override
384+ {
385+ return "custom message";
386+ }
387+};
388+
389+// Exceptions raised with boost::enable_current_exception() are preserved
390+TEST(ConvertExceptionTest, enable_current_exception)
391+{
392+ std::exception_ptr sep = std::make_exception_ptr(
393+ boost::enable_current_exception(CustomException()));
394+
395+ boost::exception_ptr bep = internal::convert_exception_ptr(sep);
396+ try
397+ {
398+ boost::rethrow_exception(bep);
399+ FAIL();
400+ }
401+ catch (CustomException const& e)
402+ {
403+ EXPECT_EQ("custom message", e.what());
404+ }
405+}
406+
407+TEST(ConvertExceptionTest, unknown_exception)
408+{
409+ std::exception_ptr sep = std::make_exception_ptr(CustomException());
410+
411+ boost::exception_ptr bep = internal::convert_exception_ptr(sep);
412+ try
413+ {
414+ boost::rethrow_exception(bep);
415+ FAIL();
416+ }
417+ catch (CustomException const& e)
418+ {
419+ // Boost can't convert exceptions that haven't been annotated
420+ // with enable_current_exception().
421+ FAIL();
422+ }
423+ catch (boost::unknown_exception const& e)
424+ {
425+ EXPECT_EQ("std::exception", std::string(e.what()));
426+ }
427+}
428+
429+int main(int argc, char **argv)
430+{
431+ ::testing::InitGoogleTest(&argc, argv);
432+ return RUN_ALL_TESTS();
433+}

Subscribers

People subscribed via source and target branches