Merge lp:~michihenning/storage-framework/remote-client-coverage into lp:storage-framework/devel
- remote-client-coverage
- Merge into devel
Status: | Merged |
---|---|
Approved by: | James Henstridge |
Approved revision: | 60 |
Merged at revision: | 57 |
Proposed branch: | lp:~michihenning/storage-framework/remote-client-coverage |
Merge into: | lp:storage-framework/devel |
Diff against target: |
1244 lines (+766/-105) 14 files modified
demo/provider_test/provider-test.cpp (+1/-1) src/provider/internal/TestServerImpl.cpp (+1/-1) src/provider/testing/TestServer.cpp (+0/-1) src/qt/client/internal/remote_client/AccountImpl.cpp (+2/-6) src/qt/client/internal/remote_client/RuntimeImpl.cpp (+8/-2) tests/provider-ProviderInterface/CMakeLists.txt (+0/-14) tests/provider-ProviderInterface/ProviderInterface_test.cpp (+21/-66) tests/remote-client/CMakeLists.txt (+3/-2) tests/remote-client/MockProvider.cpp (+236/-0) tests/remote-client/MockProvider.h (+96/-0) tests/remote-client/remote-client_test.cpp (+254/-10) tests/utils/CMakeLists.txt (+16/-2) tests/utils/ProviderFixture.cpp (+79/-0) tests/utils/ProviderFixture.h (+49/-0) |
To merge this branch: | bzr merge lp:~michihenning/storage-framework/remote-client-coverage |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Henstridge | Approve | ||
unity-api-1-bot | continuous-integration | Approve | |
Review via email: mp+303368@code.launchpad.net |
Commit message
Increased remote client coverage.
Description of the change
Refactored the fake provider from the provider test into test/utils.
Added mock provider for remote client test. (This is currently mostly
a copy of the original; I'll pare that down to something simpler as I flesh out coverage some more.)
This is incomplete, but I don't want the MR to get any larger, so I'll push this in stages.
Added coverage tests to make sure that we are handling a destroyed runtime correctly if the runtime is destroyed while the reply to a dbus request is outstanding.
unity-api-1-bot (unity-api-1-bot) wrote : | # |
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:57
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
James Henstridge (jamesh) wrote : | # |
I've noted a few things that need attention as inline comments
- 58. By Michi Henning
-
Review comments from James.
Michi Henning (michihenning) wrote : | # |
Thanks for that!
I've renamed the test class to ProviderFixture and addressed the other issues.
- 59. By Michi Henning
-
Oops, missed change in MockProvider.cpp.
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:58
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:59
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
James Henstridge (jamesh) wrote : | # |
The class still seems to be called FakeProvider?
- 60. By Michi Henning
-
Renamed FakeProvider -> ProviderFixture.
Michi Henning (michihenning) wrote : | # |
Oh boy, I shouldn't be writing code when I'm sick :-(
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:60
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:60
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | === modified file 'demo/provider_test/provider-test.cpp' |
2 | --- demo/provider_test/provider-test.cpp 2016-08-18 09:25:51 +0000 |
3 | +++ demo/provider_test/provider-test.cpp 2016-08-23 01:48:44 +0000 |
4 | @@ -161,7 +161,7 @@ |
5 | if (page_token != "") |
6 | { |
7 | string msg = string("Item::list(): invalid page token: \"") + page_token + "\""; |
8 | - return make_exceptional_future<tuple<ItemList,string>>(msg); |
9 | + return make_exceptional_future<tuple<ItemList,string>>(LogicException(msg)); |
10 | } |
11 | ItemList children = |
12 | { |
13 | |
14 | === modified file 'src/provider/internal/TestServerImpl.cpp' |
15 | --- src/provider/internal/TestServerImpl.cpp 2016-08-12 01:34:34 +0000 |
16 | +++ src/provider/internal/TestServerImpl.cpp 2016-08-23 01:48:44 +0000 |
17 | @@ -56,7 +56,7 @@ |
18 | new ProviderAdaptor(interface_.get()); |
19 | |
20 | if (!connection_.registerObject(QString::fromStdString(object_path_), |
21 | - interface_.get())) |
22 | + interface_.get())) |
23 | { |
24 | string msg = "Could not register provider on connection: " + connection_.lastError().message().toStdString(); |
25 | throw ResourceException(msg, int(connection_.lastError().type())); |
26 | |
27 | === modified file 'src/provider/testing/TestServer.cpp' |
28 | --- src/provider/testing/TestServer.cpp 2016-08-11 04:29:36 +0000 |
29 | +++ src/provider/testing/TestServer.cpp 2016-08-23 01:48:44 +0000 |
30 | @@ -22,7 +22,6 @@ |
31 | |
32 | #include <OnlineAccounts/Account> |
33 | |
34 | - |
35 | using namespace std; |
36 | |
37 | namespace unity |
38 | |
39 | === modified file 'src/qt/client/internal/remote_client/AccountImpl.cpp' |
40 | --- src/qt/client/internal/remote_client/AccountImpl.cpp 2016-08-11 07:34:49 +0000 |
41 | +++ src/qt/client/internal/remote_client/AccountImpl.cpp 2016-08-23 01:48:44 +0000 |
42 | @@ -55,10 +55,6 @@ |
43 | auto rt_impl = dynamic_pointer_cast<RuntimeImpl>(runtime.lock()->p_); |
44 | assert(rt_impl); |
45 | provider_.reset(new ProviderInterface(bus_name, object_path, rt_impl->connection())); |
46 | - if (!provider_->isValid()) |
47 | - { |
48 | - throw LocalCommsException("AccountImpl(): " + provider_->lastError().message()); |
49 | - } |
50 | } |
51 | |
52 | QString AccountImpl::owner() const |
53 | @@ -85,9 +81,9 @@ |
54 | { |
55 | runtime(); // Throws if runtime was destroyed. |
56 | } |
57 | - catch (RuntimeDestroyedException const& e) |
58 | + catch (RuntimeDestroyedException const&) |
59 | { |
60 | - return make_exceptional_future<QVector<Root::SPtr>>(e); |
61 | + return make_exceptional_future<QVector<Root::SPtr>>(RuntimeDestroyedException("Account::roots()")); |
62 | } |
63 | |
64 | auto reply = provider_->Roots(); |
65 | |
66 | === modified file 'src/qt/client/internal/remote_client/RuntimeImpl.cpp' |
67 | --- src/qt/client/internal/remote_client/RuntimeImpl.cpp 2016-08-19 03:16:52 +0000 |
68 | +++ src/qt/client/internal/remote_client/RuntimeImpl.cpp 2016-08-23 01:48:44 +0000 |
69 | @@ -84,9 +84,9 @@ |
70 | shutdown(); |
71 | } |
72 | // LCOV_EXCL_START |
73 | - catch (std::exception const&) |
74 | + catch (std::exception const& e) |
75 | { |
76 | - qCritical() << "shutdown error"; // TODO, log the error properly |
77 | + qCritical() << "shutdown error" << e.what(); |
78 | } |
79 | // LCOV_EXCL_STOP |
80 | } |
81 | @@ -130,8 +130,10 @@ |
82 | { |
83 | if (destroyed_) |
84 | { |
85 | + // LCOV_EXCL_START |
86 | make_exceptional_future(qf_, RuntimeDestroyedException("Runtime::accounts()")); |
87 | return; |
88 | + // LCOV_EXCL_STOP |
89 | } |
90 | |
91 | timer_.stop(); |
92 | @@ -161,16 +163,20 @@ |
93 | accounts_ = accounts; |
94 | make_ready_future(qf_, accounts); |
95 | } |
96 | + // LCOV_EXCL_START |
97 | catch (StorageException const& e) |
98 | { |
99 | make_exceptional_future(qf_, e); |
100 | } |
101 | + // LCOV_EXCL_STOP |
102 | } |
103 | |
104 | +// LCOV_EXCL_START |
105 | void RuntimeImpl::timeout() |
106 | { |
107 | make_exceptional_future(qf_, ResourceException("Runtime::accounts(): timeout retrieving Online accounts", 0)); |
108 | } |
109 | +// LCOV_EXCL_STOP |
110 | |
111 | shared_ptr<Account> RuntimeImpl::make_test_account(QString const& bus_name, |
112 | QString const& object_path) |
113 | |
114 | === modified file 'tests/provider-ProviderInterface/CMakeLists.txt' |
115 | --- tests/provider-ProviderInterface/CMakeLists.txt 2016-08-11 08:21:23 +0000 |
116 | +++ tests/provider-ProviderInterface/CMakeLists.txt 2016-08-23 01:48:44 +0000 |
117 | @@ -1,17 +1,3 @@ |
118 | - |
119 | - |
120 | -set_source_files_properties(${CMAKE_SOURCE_DIR}/data/provider.xml PROPERTIES |
121 | - CLASSNAME ProviderClient |
122 | - INCLUDE unity/storage/internal/dbusmarshal.h |
123 | -) |
124 | -qt5_add_dbus_interface(generated_files |
125 | - ${CMAKE_SOURCE_DIR}/data/provider.xml |
126 | - ProviderClient |
127 | -) |
128 | -set_source_files_properties(${generated_files} PROPERTIES |
129 | - GENERATED TRUE |
130 | -) |
131 | - |
132 | add_executable(provider-ProviderInterface_test |
133 | ProviderInterface_test.cpp |
134 | TestProvider.cpp |
135 | |
136 | === modified file 'tests/provider-ProviderInterface/ProviderInterface_test.cpp' |
137 | --- tests/provider-ProviderInterface/ProviderInterface_test.cpp 2016-08-12 06:29:15 +0000 |
138 | +++ tests/provider-ProviderInterface/ProviderInterface_test.cpp 2016-08-23 01:48:44 +0000 |
139 | @@ -21,9 +21,8 @@ |
140 | #include <unity/storage/provider/testing/TestServer.h> |
141 | |
142 | #include "TestProvider.h" |
143 | -#include "ProviderClient.h" |
144 | |
145 | -#include <utils/DBusEnvironment.h> |
146 | +#include <utils/ProviderFixture.h> |
147 | |
148 | #include <gtest/gtest.h> |
149 | #include <OnlineAccounts/Account> |
150 | @@ -55,69 +54,25 @@ |
151 | |
152 | } |
153 | |
154 | - |
155 | -class ProviderInterfaceTest : public ::testing::Test |
156 | +class ProviderInterfaceTest : public ProviderFixture |
157 | { |
158 | -public: |
159 | - QDBusConnection const& connection() |
160 | - { |
161 | - return dbus_->connection(); |
162 | - } |
163 | - |
164 | - void make_provider(unique_ptr<ProviderBase>&& provider) |
165 | - { |
166 | - account_manager_->waitForReady(); |
167 | - OnlineAccounts::Account* account = account_manager_->account( |
168 | - 2, "oauth2-service"); |
169 | - ASSERT_NE(nullptr, account); |
170 | - |
171 | - test_server_.reset( |
172 | - new TestServer(move(provider), account, |
173 | - *service_connection_, BUS_PATH.toStdString())); |
174 | - |
175 | - client_.reset(new ProviderClient(service_connection_->baseService(), |
176 | - BUS_PATH, |
177 | - connection())); |
178 | - } |
179 | - |
180 | - void wait_for(QDBusPendingCall const& call) { |
181 | - QDBusPendingCallWatcher watcher(call); |
182 | - QSignalSpy spy(&watcher, &QDBusPendingCallWatcher::finished); |
183 | - ASSERT_TRUE(spy.wait()); |
184 | - } |
185 | - |
186 | protected: |
187 | void SetUp() override |
188 | { |
189 | - dbus_.reset(new DBusEnvironment); |
190 | - dbus_->start_services(); |
191 | - service_connection_.reset( |
192 | - new QDBusConnection(QDBusConnection::connectToBus( |
193 | - dbus_->busAddress(), SERVICE_CONNECTION_NAME))); |
194 | - account_manager_.reset(new OnlineAccounts::Manager( |
195 | - "", *service_connection_)); |
196 | + client_.reset(new ProviderClient(service_connection_->baseService(), BUS_PATH, connection())); |
197 | } |
198 | |
199 | void TearDown() override |
200 | { |
201 | client_.reset(); |
202 | - test_server_.reset(); |
203 | - service_connection_.reset(); |
204 | - QDBusConnection::disconnectFromBus(SERVICE_CONNECTION_NAME); |
205 | - dbus_.reset(); |
206 | } |
207 | |
208 | - unique_ptr<DBusEnvironment> dbus_; |
209 | - unique_ptr<QDBusConnection> service_connection_; |
210 | - unique_ptr<OnlineAccounts::Manager> account_manager_; |
211 | - unique_ptr<TestServer> test_server_; |
212 | - unique_ptr<ProviderClient> client_; |
213 | + std::unique_ptr<ProviderClient> client_; |
214 | }; |
215 | |
216 | - |
217 | TEST_F(ProviderInterfaceTest, roots) |
218 | { |
219 | - make_provider(unique_ptr<ProviderBase>(new TestProvider)); |
220 | + set_provider(unique_ptr<ProviderBase>(new TestProvider)); |
221 | |
222 | auto reply = client_->Roots(); |
223 | wait_for(reply); |
224 | @@ -133,7 +88,7 @@ |
225 | |
226 | TEST_F(ProviderInterfaceTest, list) |
227 | { |
228 | - make_provider(unique_ptr<ProviderBase>(new TestProvider)); |
229 | + set_provider(unique_ptr<ProviderBase>(new TestProvider)); |
230 | |
231 | auto reply = client_->List("root_id", ""); |
232 | wait_for(reply); |
233 | @@ -171,7 +126,7 @@ |
234 | |
235 | TEST_F(ProviderInterfaceTest, lookup) |
236 | { |
237 | - make_provider(unique_ptr<ProviderBase>(new TestProvider)); |
238 | + set_provider(unique_ptr<ProviderBase>(new TestProvider)); |
239 | |
240 | auto reply = client_->Lookup("root_id", "Filename"); |
241 | wait_for(reply); |
242 | @@ -187,7 +142,7 @@ |
243 | |
244 | TEST_F(ProviderInterfaceTest, metadata) |
245 | { |
246 | - make_provider(unique_ptr<ProviderBase>(new TestProvider)); |
247 | + set_provider(unique_ptr<ProviderBase>(new TestProvider)); |
248 | |
249 | auto reply = client_->Metadata("root_id"); |
250 | wait_for(reply); |
251 | @@ -201,7 +156,7 @@ |
252 | |
253 | TEST_F(ProviderInterfaceTest, create_folder) |
254 | { |
255 | - make_provider(unique_ptr<ProviderBase>(new TestProvider)); |
256 | + set_provider(unique_ptr<ProviderBase>(new TestProvider)); |
257 | |
258 | auto reply = client_->CreateFolder("root_id", "New Folder"); |
259 | wait_for(reply); |
260 | @@ -215,7 +170,7 @@ |
261 | |
262 | TEST_F(ProviderInterfaceTest, create_file) |
263 | { |
264 | - make_provider(unique_ptr<ProviderBase>(new TestProvider)); |
265 | + set_provider(unique_ptr<ProviderBase>(new TestProvider)); |
266 | |
267 | const std::string file_contents = "Hello world!"; |
268 | QString upload_id; |
269 | @@ -263,7 +218,7 @@ |
270 | |
271 | TEST_F(ProviderInterfaceTest, update) |
272 | { |
273 | - make_provider(unique_ptr<ProviderBase>(new TestProvider)); |
274 | + set_provider(unique_ptr<ProviderBase>(new TestProvider)); |
275 | |
276 | const std::string file_contents = "Hello world!"; |
277 | QString upload_id; |
278 | @@ -309,7 +264,7 @@ |
279 | |
280 | TEST_F(ProviderInterfaceTest, upload_short_write) |
281 | { |
282 | - make_provider(unique_ptr<ProviderBase>(new TestProvider)); |
283 | + set_provider(unique_ptr<ProviderBase>(new TestProvider)); |
284 | |
285 | QString upload_id; |
286 | QDBusUnixFileDescriptor socket; |
287 | @@ -329,7 +284,7 @@ |
288 | |
289 | TEST_F(ProviderInterfaceTest, upload_long_write) |
290 | { |
291 | - make_provider(unique_ptr<ProviderBase>(new TestProvider)); |
292 | + set_provider(unique_ptr<ProviderBase>(new TestProvider)); |
293 | |
294 | const std::string file_contents = "Hello world!"; |
295 | QString upload_id; |
296 | @@ -374,7 +329,7 @@ |
297 | |
298 | TEST_F(ProviderInterfaceTest, cancel_upload) |
299 | { |
300 | - make_provider(unique_ptr<ProviderBase>(new TestProvider)); |
301 | + set_provider(unique_ptr<ProviderBase>(new TestProvider)); |
302 | |
303 | QString upload_id; |
304 | QDBusUnixFileDescriptor socket; |
305 | @@ -392,7 +347,7 @@ |
306 | |
307 | TEST_F(ProviderInterfaceTest, finish_upload_unknown) |
308 | { |
309 | - make_provider(unique_ptr<ProviderBase>(new TestProvider)); |
310 | + set_provider(unique_ptr<ProviderBase>(new TestProvider)); |
311 | |
312 | auto reply = client_->FinishUpload("no-such-upload"); |
313 | wait_for(reply); |
314 | @@ -403,7 +358,7 @@ |
315 | |
316 | TEST_F(ProviderInterfaceTest, download) |
317 | { |
318 | - make_provider(unique_ptr<ProviderBase>(new TestProvider)); |
319 | + set_provider(unique_ptr<ProviderBase>(new TestProvider)); |
320 | |
321 | QString download_id; |
322 | QDBusUnixFileDescriptor socket; |
323 | @@ -446,7 +401,7 @@ |
324 | |
325 | TEST_F(ProviderInterfaceTest, download_short_read) |
326 | { |
327 | - make_provider(unique_ptr<ProviderBase>(new TestProvider)); |
328 | + set_provider(unique_ptr<ProviderBase>(new TestProvider)); |
329 | |
330 | QString download_id; |
331 | QDBusUnixFileDescriptor socket; |
332 | @@ -466,7 +421,7 @@ |
333 | |
334 | TEST_F(ProviderInterfaceTest, finish_download_unknown) |
335 | { |
336 | - make_provider(unique_ptr<ProviderBase>(new TestProvider)); |
337 | + set_provider(unique_ptr<ProviderBase>(new TestProvider)); |
338 | |
339 | auto reply = client_->FinishDownload("no-such-download"); |
340 | wait_for(reply); |
341 | @@ -477,7 +432,7 @@ |
342 | |
343 | TEST_F(ProviderInterfaceTest, delete_) |
344 | { |
345 | - make_provider(unique_ptr<ProviderBase>(new TestProvider)); |
346 | + set_provider(unique_ptr<ProviderBase>(new TestProvider)); |
347 | |
348 | auto reply = client_->Delete("item_id"); |
349 | wait_for(reply); |
350 | @@ -486,7 +441,7 @@ |
351 | |
352 | TEST_F(ProviderInterfaceTest, move) |
353 | { |
354 | - make_provider(unique_ptr<ProviderBase>(new TestProvider)); |
355 | + set_provider(unique_ptr<ProviderBase>(new TestProvider)); |
356 | |
357 | auto reply = client_->Move("child_id", "new_parent_id", "New name"); |
358 | wait_for(reply); |
359 | @@ -500,7 +455,7 @@ |
360 | |
361 | TEST_F(ProviderInterfaceTest, copy) |
362 | { |
363 | - make_provider(unique_ptr<ProviderBase>(new TestProvider)); |
364 | + set_provider(unique_ptr<ProviderBase>(new TestProvider)); |
365 | |
366 | auto reply = client_->Copy("child_id", "new_parent_id", "New name"); |
367 | wait_for(reply); |
368 | |
369 | === modified file 'tests/remote-client/CMakeLists.txt' |
370 | --- tests/remote-client/CMakeLists.txt 2016-08-11 04:07:55 +0000 |
371 | +++ tests/remote-client/CMakeLists.txt 2016-08-23 01:48:44 +0000 |
372 | @@ -1,10 +1,11 @@ |
373 | -add_executable(remote-client_test remote-client_test.cpp) |
374 | +add_executable(remote-client_test remote-client_test.cpp MockProvider.cpp) |
375 | set_target_properties(remote-client_test PROPERTIES AUTOMOC TRUE) |
376 | |
377 | -add_definitions(-DTEST_DIR="${CMAKE_CURRENT_BINARY_DIR}") |
378 | +add_definitions(-DTEST_DIR="${CMAKE_CURRENT_BINARY_DIR}" -DBOOST_THREAD_VERSION=4) |
379 | include_directories(${GLIB_DEPS_INCLUDE_DIRS}) |
380 | |
381 | target_link_libraries(remote-client_test |
382 | + storage-framework-provider |
383 | storage-framework-qt-client |
384 | Qt5::Network |
385 | Qt5::Test |
386 | |
387 | === added file 'tests/remote-client/MockProvider.cpp' |
388 | --- tests/remote-client/MockProvider.cpp 1970-01-01 00:00:00 +0000 |
389 | +++ tests/remote-client/MockProvider.cpp 2016-08-23 01:48:44 +0000 |
390 | @@ -0,0 +1,236 @@ |
391 | +/* |
392 | + * Copyright (C) 2016 Canonical Ltd |
393 | + * |
394 | + * This program is free software: you can redistribute it and/or modify |
395 | + * it under the terms of the GNU Lesser General Public License version 3 as |
396 | + * published by the Free Software Foundation. |
397 | + * |
398 | + * This program is distributed in the hope that it will be useful, |
399 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
400 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
401 | + * GNU Lesser General Public License for more details. |
402 | + * |
403 | + * You should have received a copy of the GNU Lesser General Public License |
404 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
405 | + * |
406 | + * Authors: Michi Henning <michi.henning@canonical.com> |
407 | + */ |
408 | + |
409 | +#include "MockProvider.h" |
410 | + |
411 | +#include <unity/storage/provider/Exceptions.h> |
412 | +#include <unity/storage/provider/metadata_keys.h> |
413 | + |
414 | +#include <boost/thread.hpp> |
415 | +#include <boost/thread/future.hpp> |
416 | + |
417 | +#include <chrono> |
418 | +#include <thread> |
419 | +#include <inttypes.h> |
420 | + |
421 | +using namespace unity::storage; |
422 | +using namespace unity::storage::provider; |
423 | +using namespace std; |
424 | + |
425 | +using boost::make_exceptional_future; |
426 | +using boost::make_ready_future; |
427 | + |
428 | +MockProvider::MockProvider() |
429 | +{ |
430 | +} |
431 | + |
432 | +MockProvider::MockProvider(string const& cmd) |
433 | + : cmd_(cmd) |
434 | +{ |
435 | +} |
436 | + |
437 | +boost::future<ItemList> MockProvider::roots(Context const&) |
438 | +{ |
439 | + ItemList roots = |
440 | + { |
441 | + {"root_id", {}, "Root", "etag", ItemType::root, {}} |
442 | + }; |
443 | + return make_ready_future<ItemList>(roots); |
444 | +} |
445 | + |
446 | +boost::future<tuple<ItemList,string>> MockProvider::list( |
447 | + string const& item_id, string const& page_token, |
448 | + Context const&) |
449 | +{ |
450 | + if (item_id != "root_id") |
451 | + { |
452 | + string msg = string("Item::list(): no such item: \"") + item_id + "\""; |
453 | + return make_exceptional_future<tuple<ItemList,string>>(NotExistsException(msg, item_id)); |
454 | + } |
455 | + if (page_token != "") |
456 | + { |
457 | + string msg = string("Item::list(): invalid page token: \"") + page_token + "\""; |
458 | + return make_exceptional_future<tuple<ItemList,string>>(LogicException("invalid page token")); |
459 | + } |
460 | + ItemList children = |
461 | + { |
462 | + { |
463 | + "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
464 | + { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
465 | + } |
466 | + }; |
467 | + boost::promise<tuple<ItemList,string>> p; |
468 | + p.set_value(make_tuple(children, string())); |
469 | + return p.get_future(); |
470 | +} |
471 | + |
472 | +boost::future<ItemList> MockProvider::lookup( |
473 | + string const& parent_id, string const& name, Context const&) |
474 | +{ |
475 | + if (parent_id != "root_id") |
476 | + { |
477 | + string msg = string("Folder::lookup(): no such item: \"") + parent_id + "\""; |
478 | + return make_exceptional_future<ItemList>(NotExistsException(msg, parent_id)); |
479 | + } |
480 | + if (name != "Child") |
481 | + { |
482 | + string msg = string("Folder::lookup(): no such item: \"") + name + "\""; |
483 | + return make_exceptional_future<ItemList>(NotExistsException(msg, name)); |
484 | + } |
485 | + ItemList children = |
486 | + { |
487 | + { "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
488 | + { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } } |
489 | + }; |
490 | + return make_ready_future<ItemList>(children); |
491 | +} |
492 | + |
493 | +boost::future<Item> MockProvider::metadata(string const& item_id, Context const&) |
494 | +{ |
495 | + if (item_id == "root_id") |
496 | + { |
497 | + Item metadata{"root_id", {}, "Root", "etag", ItemType::root, {}}; |
498 | + return make_ready_future<Item>(metadata); |
499 | + } |
500 | + else if (item_id == "child_id") |
501 | + { |
502 | + Item metadata |
503 | + { |
504 | + "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
505 | + { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
506 | + }; |
507 | + return make_ready_future<Item>(metadata); |
508 | + } |
509 | + else if (item_id == "child_folder_id") |
510 | + { |
511 | + Item metadata{"child_folder_id", { "root_id" }, "Child_Folder", "etag", ItemType::folder, {}}; |
512 | + return make_ready_future<Item>(metadata); |
513 | + } |
514 | + return make_exceptional_future<Item>(NotExistsException("metadata(): no such item: " + item_id, item_id)); |
515 | +} |
516 | + |
517 | +boost::future<Item> MockProvider::create_folder( |
518 | + string const& parent_id, string const& name, |
519 | + Context const&) |
520 | +{ |
521 | + Item metadata{"new_folder_id", { parent_id }, name, "etag", ItemType::folder, {}}; |
522 | + return make_ready_future<Item>(metadata); |
523 | +} |
524 | + |
525 | +string make_job_id() |
526 | +{ |
527 | + static int last_job_id = 0; |
528 | + return to_string(++last_job_id); |
529 | +} |
530 | + |
531 | +boost::future<unique_ptr<UploadJob>> MockProvider::create_file( |
532 | + string const&, string const&, |
533 | + int64_t, string const&, bool, Context const&) |
534 | +{ |
535 | + return make_ready_future<unique_ptr<UploadJob>>(new MockUploadJob(make_job_id())); |
536 | +} |
537 | + |
538 | +boost::future<unique_ptr<UploadJob>> MockProvider::update( |
539 | + string const&, int64_t, string const&, Context const&) |
540 | +{ |
541 | + return make_ready_future<unique_ptr<UploadJob>>(new MockUploadJob(make_job_id())); |
542 | +} |
543 | + |
544 | +boost::future<unique_ptr<DownloadJob>> MockProvider::download( |
545 | + string const&, Context const&) |
546 | +{ |
547 | + unique_ptr<DownloadJob> job(new MockDownloadJob(make_job_id())); |
548 | + const char contents[] = "Hello world"; |
549 | + if (write(job->write_socket(), contents, sizeof(contents)) != sizeof(contents)) |
550 | + { |
551 | + ResourceException e("download(): write failed", errno); |
552 | + job->report_error(make_exception_ptr(e)); |
553 | + return make_exceptional_future<unique_ptr<DownloadJob>>(e); |
554 | + } |
555 | + job->report_complete(); |
556 | + return make_ready_future(std::move(job)); |
557 | +} |
558 | + |
559 | +boost::future<void> MockProvider::delete_item( |
560 | + string const&, Context const&) |
561 | +{ |
562 | + return make_ready_future(); |
563 | +} |
564 | + |
565 | +boost::future<Item> MockProvider::move( |
566 | + string const& item_id, string const& new_parent_id, |
567 | + string const& new_name, Context const&) |
568 | +{ |
569 | + Item metadata{item_id, { new_parent_id }, new_name, "etag", ItemType::file, {}}; |
570 | + return make_ready_future(metadata); |
571 | +} |
572 | + |
573 | +boost::future<Item> MockProvider::copy( |
574 | + string const&, string const& new_parent_id, |
575 | + string const& new_name, Context const&) |
576 | +{ |
577 | + Item metadata{"new_item_id", { new_parent_id }, new_name, "etag", ItemType::file, {}}; |
578 | + return make_ready_future(metadata); |
579 | +} |
580 | + |
581 | +MockUploadJob::MockUploadJob() |
582 | + : UploadJob("some_id") |
583 | +{ |
584 | +} |
585 | + |
586 | +MockUploadJob::MockUploadJob(string const& cmd) |
587 | + : UploadJob("some_id") |
588 | + , cmd_(cmd) |
589 | +{ |
590 | +} |
591 | + |
592 | +boost::future<void> MockUploadJob::cancel() |
593 | +{ |
594 | + return make_ready_future(); |
595 | +} |
596 | + |
597 | +boost::future<Item> MockUploadJob::finish() |
598 | +{ |
599 | + Item metadata |
600 | + { |
601 | + "some_id", { "root_id" }, "some_upload", "etag", ItemType::file, |
602 | + { { SIZE_IN_BYTES, 10 }, { LAST_MODIFIED_TIME, "2011-04-05T14:30:10.005Z" } } |
603 | + }; |
604 | + return make_ready_future(metadata); |
605 | +} |
606 | + |
607 | +MockDownloadJob::MockDownloadJob() |
608 | + : DownloadJob("some_id") |
609 | +{ |
610 | +} |
611 | + |
612 | +MockDownloadJob::MockDownloadJob(string const& cmd) |
613 | + : DownloadJob("some_id") |
614 | + , cmd_(cmd) |
615 | +{ |
616 | +} |
617 | + |
618 | +boost::future<void> MockDownloadJob::cancel() |
619 | +{ |
620 | + return make_ready_future(); |
621 | +} |
622 | + |
623 | +boost::future<void> MockDownloadJob::finish() |
624 | +{ |
625 | + return make_ready_future(); |
626 | +} |
627 | |
628 | === added file 'tests/remote-client/MockProvider.h' |
629 | --- tests/remote-client/MockProvider.h 1970-01-01 00:00:00 +0000 |
630 | +++ tests/remote-client/MockProvider.h 2016-08-23 01:48:44 +0000 |
631 | @@ -0,0 +1,96 @@ |
632 | +/* |
633 | + * Copyright (C) 2016 Canonical Ltd |
634 | + * |
635 | + * This program is free software: you can redistribute it and/or modify |
636 | + * it under the terms of the GNU Lesser General Public License version 3 as |
637 | + * published by the Free Software Foundation. |
638 | + * |
639 | + * This program is distributed in the hope that it will be useful, |
640 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
641 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
642 | + * GNU Lesser General Public License for more details. |
643 | + * |
644 | + * You should have received a copy of the GNU Lesser General Public License |
645 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
646 | + * |
647 | + * Authors: Michi Henning <michi.henning@canonical.com> |
648 | + */ |
649 | + |
650 | +#pragma once |
651 | + |
652 | +#include <unity/storage/provider/DownloadJob.h> |
653 | +#include <unity/storage/provider/ProviderBase.h> |
654 | +#include <unity/storage/provider/UploadJob.h> |
655 | + |
656 | +class MockProvider : public unity::storage::provider::ProviderBase |
657 | +{ |
658 | +public: |
659 | + MockProvider(); |
660 | + MockProvider(std::string const& cmd); |
661 | + |
662 | + boost::future<unity::storage::provider::ItemList> roots(unity::storage::provider::Context const& ctx) override; |
663 | + boost::future<std::tuple<unity::storage::provider::ItemList, std::string>> list( |
664 | + std::string const& item_id, std::string const& page_token, |
665 | + unity::storage::provider::Context const& ctx) override; |
666 | + boost::future<unity::storage::provider::ItemList> lookup( |
667 | + std::string const& parent_id, std::string const& name, |
668 | + unity::storage::provider::Context const& ctx) override; |
669 | + boost::future<unity::storage::provider::Item> metadata( |
670 | + std::string const& item_id, unity::storage::provider::Context const& ctx) override; |
671 | + boost::future<unity::storage::provider::Item> create_folder( |
672 | + std::string const& parent_id, std::string const& name, |
673 | + unity::storage::provider::Context const& ctx) override; |
674 | + |
675 | + boost::future<std::unique_ptr<unity::storage::provider::UploadJob>> create_file( |
676 | + std::string const& parent_id, std::string const& name, |
677 | + int64_t size, std::string const& content_type, bool allow_overwrite, |
678 | + unity::storage::provider::Context const& ctx) override; |
679 | + boost::future<std::unique_ptr<unity::storage::provider::UploadJob>> update( |
680 | + std::string const& item_id, int64_t size, std::string const& old_etag, |
681 | + unity::storage::provider::Context const& ctx) override; |
682 | + |
683 | + boost::future<std::unique_ptr<unity::storage::provider::DownloadJob>> download( |
684 | + std::string const& item_id, unity::storage::provider::Context const& ctx) override; |
685 | + |
686 | + boost::future<void> delete_item( |
687 | + std::string const& item_id, unity::storage::provider::Context const& ctx) override; |
688 | + boost::future<unity::storage::provider::Item> move( |
689 | + std::string const& item_id, std::string const& new_parent_id, |
690 | + std::string const& new_name, unity::storage::provider::Context const& ctx) override; |
691 | + boost::future<unity::storage::provider::Item> copy( |
692 | + std::string const& item_id, std::string const& new_parent_id, |
693 | + std::string const& new_name, unity::storage::provider::Context const& ctx) override; |
694 | + |
695 | +private: |
696 | + std::string cmd_; |
697 | +}; |
698 | + |
699 | +class MockUploadJob : public unity::storage::provider::UploadJob |
700 | +{ |
701 | +public: |
702 | + using UploadJob::UploadJob; |
703 | + |
704 | + MockUploadJob(); |
705 | + MockUploadJob(std::string const& cmd); |
706 | + |
707 | + boost::future<void> cancel() override; |
708 | + boost::future<unity::storage::provider::Item> finish() override; |
709 | + |
710 | +private: |
711 | + std::string cmd_; |
712 | +}; |
713 | + |
714 | +class MockDownloadJob : public unity::storage::provider::DownloadJob |
715 | +{ |
716 | +public: |
717 | + using DownloadJob::DownloadJob; |
718 | + |
719 | + MockDownloadJob(); |
720 | + MockDownloadJob(const std::string& cmd); |
721 | + |
722 | + boost::future<void> cancel() override; |
723 | + boost::future<void> finish() override; |
724 | + |
725 | +private: |
726 | + std::string cmd_; |
727 | +}; |
728 | |
729 | === modified file 'tests/remote-client/remote-client_test.cpp' |
730 | --- tests/remote-client/remote-client_test.cpp 2016-08-19 03:16:52 +0000 |
731 | +++ tests/remote-client/remote-client_test.cpp 2016-08-23 01:48:44 +0000 |
732 | @@ -19,6 +19,8 @@ |
733 | #include <unity/storage/qt/client/client-api.h> |
734 | |
735 | #include <utils/DBusEnvironment.h> |
736 | +#include <utils/ProviderFixture.h> |
737 | +#include <MockProvider.h> |
738 | |
739 | #include <gtest/gtest.h> |
740 | #include <QCoreApplication> |
741 | @@ -71,37 +73,64 @@ |
742 | class FileTest : public RemoteClientTest {}; |
743 | class ItemTest : public RemoteClientTest {}; |
744 | |
745 | +class DestroyedTest : public ProviderFixture |
746 | +{ |
747 | +protected: |
748 | + void SetUp() override |
749 | + { |
750 | + runtime_ = Runtime::create(connection()); |
751 | + acc_ = runtime_->make_test_account(service_connection_->baseService(), bus_path()); |
752 | + } |
753 | + |
754 | + void TearDown() override |
755 | + { |
756 | + } |
757 | + |
758 | + Runtime::SPtr runtime_; |
759 | + Account::SPtr acc_; |
760 | +}; |
761 | + |
762 | // Bunch of helper functions to reduce the amount of noise in the tests. |
763 | |
764 | template<typename T> |
765 | -void wait(T fut) |
766 | +bool wait(T fut) |
767 | { |
768 | QFutureWatcher<decltype(fut.result())> w; |
769 | QSignalSpy spy(&w, &decltype(w)::finished); |
770 | w.setFuture(fut); |
771 | - ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
772 | + bool rc = spy.wait(SIGNAL_WAIT_TIME); |
773 | + EXPECT_TRUE(rc); |
774 | + return rc; |
775 | } |
776 | |
777 | template<> |
778 | -void wait(QFuture<void> fut) |
779 | +bool wait(QFuture<void> fut) |
780 | { |
781 | QFutureWatcher<void> w; |
782 | QSignalSpy spy(&w, &decltype(w)::finished); |
783 | w.setFuture(fut); |
784 | - ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
785 | + bool rc = spy.wait(SIGNAL_WAIT_TIME); |
786 | + EXPECT_TRUE(rc); |
787 | + return rc; |
788 | } |
789 | |
790 | template <typename T> |
791 | T call(QFuture<T> fut) |
792 | { |
793 | - wait(fut); |
794 | + if (!wait(fut)) |
795 | + { |
796 | + throw runtime_error("call timed out"); |
797 | + } |
798 | return fut.result(); |
799 | } |
800 | |
801 | template <> |
802 | void call(QFuture<void> fut) |
803 | { |
804 | - wait(fut); |
805 | + if (!wait(fut)) |
806 | + { |
807 | + throw runtime_error("call timed out"); |
808 | + } |
809 | fut.waitForFinished(); |
810 | } |
811 | |
812 | @@ -114,7 +143,14 @@ |
813 | qCritical() << "Configure at least one online account for a provider in System Settings -> Online Accounts"; |
814 | return nullptr; |
815 | } |
816 | - return accounts[0]; |
817 | + for (auto acc : accounts) |
818 | + { |
819 | + if (acc->owner_id() == "google-drive-scope") |
820 | + { |
821 | + return acc; |
822 | + } |
823 | + } |
824 | + abort(); // Impossible |
825 | } |
826 | |
827 | Root::SPtr get_root(Runtime::SPtr const& runtime) |
828 | @@ -139,7 +175,7 @@ |
829 | assert(items.size() != 0); // TODO: temporary hack for use with demo provider |
830 | for (auto i : items) |
831 | { |
832 | - wait(i->delete_item()); |
833 | + call(i->delete_item()); |
834 | } |
835 | } |
836 | |
837 | @@ -282,7 +318,7 @@ |
838 | |
839 | TEST_F(RuntimeTest, runtime_destroyed_exceptions) |
840 | { |
841 | - // Gettting an account after shutting down the runtime must fail. |
842 | + // Getting the runtime from an account after shutting down the runtime must fail. |
843 | { |
844 | auto runtime = Runtime::create(connection()); |
845 | auto acc = get_account(runtime); |
846 | @@ -298,7 +334,7 @@ |
847 | } |
848 | } |
849 | |
850 | - // Getting an account after destroying the runtime must fail. |
851 | + // Getting the runtime from an account after destroying the runtime must fail. |
852 | { |
853 | auto runtime = Runtime::create(connection()); |
854 | auto acc = get_account(runtime); |
855 | @@ -329,6 +365,22 @@ |
856 | } |
857 | } |
858 | |
859 | + // Getting roots from an account after shutting down the runtime must fail. |
860 | + { |
861 | + auto runtime = Runtime::create(connection()); |
862 | + auto acc = get_account(runtime); |
863 | + runtime->shutdown(); |
864 | + try |
865 | + { |
866 | + call(acc->roots()); |
867 | + FAIL(); |
868 | + } |
869 | + catch (RuntimeDestroyedException const& e) |
870 | + { |
871 | + EXPECT_EQ("Account::roots(): runtime was destroyed previously", e.error_message()); |
872 | + } |
873 | + } |
874 | + |
875 | // Getting the account from a root with a destroyed runtime must fail. |
876 | { |
877 | auto runtime = Runtime::create(connection()); |
878 | @@ -888,6 +940,198 @@ |
879 | } |
880 | } |
881 | |
882 | +TEST_F(DestroyedTest, roots_destroyed_while_reply_outstanding) |
883 | +{ |
884 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider)); |
885 | + |
886 | + auto fut = acc_->roots(); |
887 | + runtime_->shutdown(); |
888 | + try |
889 | + { |
890 | + ASSERT_TRUE(wait(fut)); |
891 | + fut.result(); |
892 | + FAIL(); |
893 | + } |
894 | + catch (RuntimeDestroyedException const& e) |
895 | + { |
896 | + EXPECT_EQ("Account::roots(): runtime was destroyed previously", e.error_message()); |
897 | + } |
898 | +} |
899 | + |
900 | +TEST_F(DestroyedTest, get_destroyed_while_reply_outstanding) |
901 | +{ |
902 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("metadata slow"))); |
903 | + |
904 | + auto root = call(acc_->roots())[0]; |
905 | + auto fut = root->get("root_id"); |
906 | + runtime_->shutdown(); |
907 | + try |
908 | + { |
909 | + ASSERT_TRUE(wait(fut)); |
910 | + fut.result(); |
911 | + FAIL(); |
912 | + } |
913 | + catch (RuntimeDestroyedException const& e) |
914 | + { |
915 | + EXPECT_EQ("Root::get(): runtime was destroyed previously", e.error_message()); |
916 | + } |
917 | +} |
918 | + |
919 | +TEST_F(DestroyedTest, copy_destroyed_while_reply_outstanding) |
920 | +{ |
921 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider())); |
922 | + |
923 | + auto root = call(acc_->roots())[0]; |
924 | + auto fut = root->copy(root, "new name"); |
925 | + runtime_->shutdown(); |
926 | + try |
927 | + { |
928 | + ASSERT_TRUE(wait(fut)); |
929 | + fut.result(); |
930 | + FAIL(); |
931 | + } |
932 | + catch (RuntimeDestroyedException const& e) |
933 | + { |
934 | + EXPECT_EQ("Item::copy(): runtime was destroyed previously", e.error_message()); |
935 | + } |
936 | +} |
937 | + |
938 | +TEST_F(DestroyedTest, move_destroyed_while_reply_outstanding) |
939 | +{ |
940 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("move slow"))); |
941 | + |
942 | + auto root = call(acc_->roots())[0]; |
943 | + auto file = dynamic_pointer_cast<File>(call(root->get("child_id"))); |
944 | + auto fut = file->move(root, "new name"); |
945 | + runtime_->shutdown(); |
946 | + try |
947 | + { |
948 | + ASSERT_TRUE(wait(fut)); |
949 | + fut.result(); |
950 | + FAIL(); |
951 | + } |
952 | + catch (RuntimeDestroyedException const& e) |
953 | + { |
954 | + EXPECT_EQ("Item::move(): runtime was destroyed previously", e.error_message()); |
955 | + } |
956 | +} |
957 | + |
958 | +TEST_F(DestroyedTest, list_destroyed_while_reply_outstanding) |
959 | +{ |
960 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("list slow"))); |
961 | + |
962 | + auto root = call(acc_->roots())[0]; |
963 | + auto fut = root->list(); |
964 | + runtime_->shutdown(); |
965 | + try |
966 | + { |
967 | + ASSERT_TRUE(wait(fut)); |
968 | + fut.result(); |
969 | + FAIL(); |
970 | + } |
971 | + catch (RuntimeDestroyedException const& e) |
972 | + { |
973 | + EXPECT_EQ("Folder::list(): runtime was destroyed previously", e.error_message()); |
974 | + } |
975 | +} |
976 | + |
977 | +TEST_F(DestroyedTest, lookup_destroyed_while_reply_outstanding) |
978 | +{ |
979 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("lookup slow"))); |
980 | + |
981 | + auto root = call(acc_->roots())[0]; |
982 | + auto fut = root->lookup("Child"); |
983 | + runtime_->shutdown(); |
984 | + try |
985 | + { |
986 | + ASSERT_TRUE(wait(fut)); |
987 | + fut.result(); |
988 | + FAIL(); |
989 | + } |
990 | + catch (RuntimeDestroyedException const& e) |
991 | + { |
992 | + EXPECT_EQ("Folder::lookup(): runtime was destroyed previously", e.error_message()); |
993 | + } |
994 | +} |
995 | + |
996 | +TEST_F(DestroyedTest, create_folder_destroyed_while_reply_outstanding) |
997 | +{ |
998 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("create_folder slow"))); |
999 | + |
1000 | + auto root = call(acc_->roots())[0]; |
1001 | + auto fut = root->create_folder("Child"); |
1002 | + runtime_->shutdown(); |
1003 | + try |
1004 | + { |
1005 | + ASSERT_TRUE(wait(fut)); |
1006 | + fut.result(); |
1007 | + FAIL(); |
1008 | + } |
1009 | + catch (RuntimeDestroyedException const& e) |
1010 | + { |
1011 | + EXPECT_EQ("Folder::create_folder(): runtime was destroyed previously", e.error_message()); |
1012 | + } |
1013 | +} |
1014 | + |
1015 | +TEST_F(DestroyedTest, create_file_destroyed_while_reply_outstanding) |
1016 | +{ |
1017 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("create_file slow"))); |
1018 | + |
1019 | + auto root = call(acc_->roots())[0]; |
1020 | + auto fut = root->create_file("Child", 0); |
1021 | + runtime_->shutdown(); |
1022 | + try |
1023 | + { |
1024 | + ASSERT_TRUE(wait(fut)); |
1025 | + fut.result(); |
1026 | + FAIL(); |
1027 | + } |
1028 | + catch (RuntimeDestroyedException const& e) |
1029 | + { |
1030 | + EXPECT_EQ("Folder::create_file(): runtime was destroyed previously", e.error_message()); |
1031 | + } |
1032 | +} |
1033 | + |
1034 | +TEST_F(DestroyedTest, create_uploader_destroyed_while_reply_outstanding) |
1035 | +{ |
1036 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("create_file slow"))); |
1037 | + |
1038 | + auto root = call(acc_->roots())[0]; |
1039 | + auto file = dynamic_pointer_cast<File>(call(root->get("child_id"))); |
1040 | + auto fut = file->create_uploader(ConflictPolicy::overwrite, 0); |
1041 | + runtime_->shutdown(); |
1042 | + try |
1043 | + { |
1044 | + ASSERT_TRUE(wait(fut)); |
1045 | + fut.result(); |
1046 | + FAIL(); |
1047 | + } |
1048 | + catch (RuntimeDestroyedException const& e) |
1049 | + { |
1050 | + EXPECT_EQ("File::create_uploader(): runtime was destroyed previously", e.error_message()); |
1051 | + } |
1052 | +} |
1053 | + |
1054 | +TEST_F(DestroyedTest, create_downloader_destroyed_while_reply_outstanding) |
1055 | +{ |
1056 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("create_file slow"))); |
1057 | + |
1058 | + auto root = call(acc_->roots())[0]; |
1059 | + auto file = dynamic_pointer_cast<File>(call(root->get("child_id"))); |
1060 | + auto fut = file->create_downloader(); |
1061 | + runtime_->shutdown(); |
1062 | + try |
1063 | + { |
1064 | + ASSERT_TRUE(wait(fut)); |
1065 | + fut.result(); |
1066 | + FAIL(); |
1067 | + } |
1068 | + catch (RuntimeDestroyedException const& e) |
1069 | + { |
1070 | + EXPECT_EQ("File::create_downloader(): runtime was destroyed previously", e.error_message()); |
1071 | + } |
1072 | +} |
1073 | + |
1074 | int main(int argc, char** argv) |
1075 | { |
1076 | QCoreApplication app(argc, argv); |
1077 | |
1078 | === modified file 'tests/utils/CMakeLists.txt' |
1079 | --- tests/utils/CMakeLists.txt 2016-07-12 06:42:53 +0000 |
1080 | +++ tests/utils/CMakeLists.txt 2016-08-23 01:48:44 +0000 |
1081 | @@ -1,9 +1,23 @@ |
1082 | pkg_check_modules(QTDBUSTEST_DEPS libqtdbustest-1 REQUIRED) |
1083 | |
1084 | +set_source_files_properties(${CMAKE_SOURCE_DIR}/data/provider.xml PROPERTIES |
1085 | + CLASSNAME ProviderClient |
1086 | + INCLUDE unity/storage/internal/dbusmarshal.h |
1087 | +) |
1088 | +qt5_add_dbus_interface(generated_files |
1089 | + ${CMAKE_SOURCE_DIR}/data/provider.xml |
1090 | + ProviderClient |
1091 | +) |
1092 | +set_source_files_properties(${generated_files} PROPERTIES GENERATED TRUE) |
1093 | + |
1094 | add_library(testutils STATIC |
1095 | DBusEnvironment.cpp |
1096 | + ProviderFixture.cpp |
1097 | + ${generated_files} |
1098 | ) |
1099 | -target_compile_options(testutils PRIVATE ${QTDBUSTEST_DEPS_CFLAGS}) |
1100 | +target_compile_options(testutils PRIVATE ${QTDBUSTEST_DEPS_CFLAGS} ${ONLINEACCOUNTS_DEPS_CFLAGS}) |
1101 | target_link_libraries(testutils |
1102 | PUBLIC Qt5::DBus Qt5::Core |
1103 | - PRIVATE ${QTDBUSTEST_DEPS_LIBRARIES}) |
1104 | + PRIVATE Qt5::Test ${QTDBUSTEST_DEPS_LIBRARIES} ${ONLINEAACOUNTS_DEPS_LIBRARIES}) |
1105 | + |
1106 | +add_definitions(-DBOOST_THREAD_VERSION=4) |
1107 | |
1108 | === added file 'tests/utils/ProviderFixture.cpp' |
1109 | --- tests/utils/ProviderFixture.cpp 1970-01-01 00:00:00 +0000 |
1110 | +++ tests/utils/ProviderFixture.cpp 2016-08-23 01:48:44 +0000 |
1111 | @@ -0,0 +1,79 @@ |
1112 | +/* |
1113 | + * Copyright (C) 2016 Canonical Ltd |
1114 | + * |
1115 | + * This program is free software: you can redistribute it and/or modify |
1116 | + * it under the terms of the GNU Lesser General Public License version 3 as |
1117 | + * published by the Free Software Foundation. |
1118 | + * |
1119 | + * This program is distributed in the hope that it will be useful, |
1120 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1121 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1122 | + * GNU Lesser General Public License for more details. |
1123 | + * |
1124 | + * You should have received a copy of the GNU Lesser General Public License |
1125 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1126 | + * |
1127 | + * Authors: James Henstridge <james.henstridge@canonical.com> |
1128 | + */ |
1129 | + |
1130 | +#include "ProviderFixture.h" |
1131 | + |
1132 | +#include <unity/storage/internal/dbus_error.h> |
1133 | + |
1134 | +#include <QSignalSpy> |
1135 | + |
1136 | +using namespace unity::storage::provider; |
1137 | +using namespace std; |
1138 | + |
1139 | +namespace |
1140 | +{ |
1141 | + |
1142 | +const auto SERVICE_CONNECTION_NAME = QStringLiteral("service-session-bus"); |
1143 | +const auto BUS_PATH = QStringLiteral("/provider"); |
1144 | + |
1145 | +} // namespace |
1146 | + |
1147 | +ProviderFixture::ProviderFixture() |
1148 | +{ |
1149 | + dbus_.reset(new DBusEnvironment); |
1150 | + dbus_->start_services(); |
1151 | + service_connection_.reset(new QDBusConnection(QDBusConnection::connectToBus(dbus_->busAddress(), |
1152 | + SERVICE_CONNECTION_NAME))); |
1153 | + account_manager_.reset(new OnlineAccounts::Manager("", *service_connection_)); |
1154 | +} |
1155 | + |
1156 | +ProviderFixture::~ProviderFixture() |
1157 | +{ |
1158 | + test_server_.reset(); |
1159 | + service_connection_.reset(); |
1160 | + QDBusConnection::disconnectFromBus(SERVICE_CONNECTION_NAME); |
1161 | + dbus_.reset(); |
1162 | +} |
1163 | + |
1164 | +QDBusConnection const& ProviderFixture::connection() const |
1165 | +{ |
1166 | + return dbus_->connection(); |
1167 | +} |
1168 | + |
1169 | +void ProviderFixture::set_provider(unique_ptr<ProviderBase>&& provider) |
1170 | +{ |
1171 | + account_manager_->waitForReady(); |
1172 | + OnlineAccounts::Account* account = account_manager_->account(2, "oauth2-service"); |
1173 | + ASSERT_NE(nullptr, account); |
1174 | + |
1175 | + test_server_.reset( |
1176 | + new unity::storage::provider::testing::TestServer(move(provider), account, |
1177 | + *service_connection_, BUS_PATH.toStdString())); |
1178 | +} |
1179 | + |
1180 | +void ProviderFixture::wait_for(QDBusPendingCall const& call) |
1181 | +{ |
1182 | + QDBusPendingCallWatcher watcher(call); |
1183 | + QSignalSpy spy(&watcher, &QDBusPendingCallWatcher::finished); |
1184 | + ASSERT_TRUE(spy.wait()); |
1185 | +} |
1186 | + |
1187 | +QString ProviderFixture::bus_path() const |
1188 | +{ |
1189 | + return BUS_PATH; |
1190 | +} |
1191 | |
1192 | === added file 'tests/utils/ProviderFixture.h' |
1193 | --- tests/utils/ProviderFixture.h 1970-01-01 00:00:00 +0000 |
1194 | +++ tests/utils/ProviderFixture.h 2016-08-23 01:48:44 +0000 |
1195 | @@ -0,0 +1,49 @@ |
1196 | +/* |
1197 | + * Copyright (C) 2016 Canonical Ltd |
1198 | + * |
1199 | + * This program is free software: you can redistribute it and/or modify |
1200 | + * it under the terms of the GNU Lesser General Public License version 3 as |
1201 | + * published by the Free Software Foundation. |
1202 | + * |
1203 | + * This program is distributed in the hope that it will be useful, |
1204 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1205 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1206 | + * GNU Lesser General Public License for more details. |
1207 | + * |
1208 | + * You should have received a copy of the GNU Lesser General Public License |
1209 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1210 | + * |
1211 | + * Authors: James Henstridge <james.henstridge@canonical.com> |
1212 | + */ |
1213 | + |
1214 | +#pragma once |
1215 | + |
1216 | +#include <unity/storage/provider/ProviderBase.h> |
1217 | +#include <unity/storage/provider/testing/TestServer.h> |
1218 | +#include <utils/DBusEnvironment.h> |
1219 | +#include <utils/ProviderClient.h> |
1220 | + |
1221 | +#include <gtest/gtest.h> |
1222 | +#include <OnlineAccounts/Account> |
1223 | +#include <OnlineAccounts/Manager> |
1224 | +#include <QDBusConnection> |
1225 | + |
1226 | +#include <memory> |
1227 | + |
1228 | +class ProviderFixture : public ::testing::Test |
1229 | +{ |
1230 | +public: |
1231 | + ProviderFixture(); |
1232 | + virtual ~ProviderFixture(); |
1233 | + |
1234 | + QDBusConnection const& connection() const; |
1235 | + void set_provider(std::unique_ptr<unity::storage::provider::ProviderBase>&& provider); |
1236 | + void wait_for(QDBusPendingCall const& call); |
1237 | + QString bus_path() const; |
1238 | + |
1239 | +protected: |
1240 | + std::unique_ptr<DBusEnvironment> dbus_; |
1241 | + std::unique_ptr<QDBusConnection> service_connection_; |
1242 | + std::unique_ptr<OnlineAccounts::Manager> account_manager_; |
1243 | + std::unique_ptr<unity::storage::provider::testing::TestServer> test_server_; |
1244 | +}; |
FAILED: Continuous integration, rev:57 /jenkins. canonical. com/unity- api-1/job/ lp-storage- framework- ci/81/ /jenkins. canonical. com/unity- api-1/job/ build/425/ console /jenkins. canonical. com/unity- api-1/job/ build-0- fetch/431 /jenkins. canonical. com/unity- api-1/job/ build-1- sourcepkg/ release= vivid+overlay/ 338 /jenkins. canonical. com/unity- api-1/job/ build-1- sourcepkg/ release= xenial+ overlay/ 338 /jenkins. canonical. com/unity- api-1/job/ build-1- sourcepkg/ release= yakkety/ 338 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 268 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 268/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 268 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 268/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 268/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 268 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 268/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 268 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 268/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 268 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 268/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 268 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 268/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 268 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 268/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= yakkety/ 268 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= yakkety/ 268/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/unity- api-1/job/ lp-storage- framework- ci/81/rebuild
https:/