Merge lp:~michihenning/storage-framework/upload-download-fixes into lp:storage-framework/devel

Proposed by Michi Henning
Status: Merged
Approved by: James Henstridge
Approved revision: 80
Merged at revision: 42
Proposed branch: lp:~michihenning/storage-framework/upload-download-fixes
Merge into: lp:storage-framework/devel
Prerequisite: lp:~michihenning/storage-framework/more-coverage
Diff against target: 334 lines (+115/-14)
10 files modified
include/unity/storage/qt/client/Uploader.h (+8/-0)
include/unity/storage/qt/client/internal/UploaderBase.h (+4/-1)
include/unity/storage/qt/client/internal/remote_client/UploaderImpl.h (+0/-1)
src/qt/client/Uploader.cpp (+5/-0)
src/qt/client/internal/UploaderBase.cpp (+11/-2)
src/qt/client/internal/local_client/UploaderImpl.cpp (+12/-5)
src/qt/client/internal/remote_client/DownloaderImpl.cpp (+4/-2)
src/qt/client/internal/remote_client/UploaderImpl.cpp (+4/-3)
tests/local-client/local-client_test.cpp (+65/-0)
tests/remote-client/remote-client_test.cpp (+2/-0)
To merge this branch: bzr merge lp:~michihenning/storage-framework/upload-download-fixes
Reviewer Review Type Date Requested Status
James Henstridge Approve
unity-api-1-bot continuous-integration Needs Fixing
Review via email: mp+301865@code.launchpad.net

Commit message

Added size() accessor to Uploader. Fixed upload/download finalization for remote client.

Description of the change

Added size() accessor to Uploader.
Added tests for upload size mismatch and that calling finish_upload() more than once continues to return the same error future.
Fixed upload/download finalization for remote client.

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

FAILED: Continuous integration, rev:80
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/46/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/273/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/279
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-1-sourcepkg/release=vivid+overlay/213
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-1-sourcepkg/release=xenial+overlay/213
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-1-sourcepkg/release=yakkety/213
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/142/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/142/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/142/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/142/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/142/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/142/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/142/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/142/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/142/console

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

review: Needs Fixing (continuous-integration)
Revision history for this message
James Henstridge (jamesh) wrote :

Looks great!

Revision history for this message
James Henstridge (jamesh) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/unity/storage/qt/client/Uploader.h'
--- include/unity/storage/qt/client/Uploader.h 2016-07-22 02:35:12 +0000
+++ include/unity/storage/qt/client/Uploader.h 2016-08-03 04:16:38 +0000
@@ -92,6 +92,14 @@
92 std::shared_ptr<QLocalSocket> socket() const;92 std::shared_ptr<QLocalSocket> socket() const;
9393
94 /**94 /**
95 \brief Returns the size that was passed to Folder::create_file() or File::create_uploader().
96
97 \return The number of bytes that the uploader expects to be written to the `QLocalSocket` returned
98 from socket().
99 */
100 int64_t size() const;
101
102 /**
95 \brief Finalizes the upload.103 \brief Finalizes the upload.
96104
97 Once you have written the file contents to the socket returned by socket(), you must call finish_upload(),105 Once you have written the file contents to the socket returned by socket(), you must call finish_upload(),
98106
=== modified file 'include/unity/storage/qt/client/internal/UploaderBase.h'
--- include/unity/storage/qt/client/internal/UploaderBase.h 2016-07-22 02:35:12 +0000
+++ include/unity/storage/qt/client/internal/UploaderBase.h 2016-08-03 04:16:38 +0000
@@ -47,7 +47,7 @@
47class UploaderBase : public QObject47class UploaderBase : public QObject
48{48{
49public:49public:
50 UploaderBase(ConflictPolicy policy);50 UploaderBase(ConflictPolicy policy, int64_t size);
51 UploaderBase(UploaderBase&) = delete;51 UploaderBase(UploaderBase&) = delete;
52 UploaderBase& operator=(UploaderBase const&) = delete;52 UploaderBase& operator=(UploaderBase const&) = delete;
5353
@@ -55,8 +55,11 @@
55 virtual QFuture<std::shared_ptr<File>> finish_upload() = 0;55 virtual QFuture<std::shared_ptr<File>> finish_upload() = 0;
56 virtual QFuture<void> cancel() noexcept = 0;56 virtual QFuture<void> cancel() noexcept = 0;
5757
58 int64_t size() const;
59
58protected:60protected:
59 ConflictPolicy policy_;61 ConflictPolicy policy_;
62 int64_t size_;
60};63};
6164
62} // namespace internal65} // namespace internal
6366
=== modified file 'include/unity/storage/qt/client/internal/remote_client/UploaderImpl.h'
--- include/unity/storage/qt/client/internal/remote_client/UploaderImpl.h 2016-08-03 04:16:38 +0000
+++ include/unity/storage/qt/client/internal/remote_client/UploaderImpl.h 2016-08-03 04:16:38 +0000
@@ -67,7 +67,6 @@
67private:67private:
68 QString upload_id_;68 QString upload_id_;
69 QDBusUnixFileDescriptor fd_;69 QDBusUnixFileDescriptor fd_;
70 int64_t size_;
71 QString old_etag_;70 QString old_etag_;
72 std::shared_ptr<Root> root_;71 std::shared_ptr<Root> root_;
73 std::shared_ptr<ProviderInterface> provider_;72 std::shared_ptr<ProviderInterface> provider_;
7473
=== modified file 'src/qt/client/Uploader.cpp'
--- src/qt/client/Uploader.cpp 2016-07-12 02:22:05 +0000
+++ src/qt/client/Uploader.cpp 2016-08-03 04:16:38 +0000
@@ -46,6 +46,11 @@
46 return p_->socket();46 return p_->socket();
47}47}
4848
49int64_t Uploader::size() const
50{
51 return p_->size();
52}
53
49QFuture<shared_ptr<File>> Uploader::finish_upload()54QFuture<shared_ptr<File>> Uploader::finish_upload()
50{55{
51 return p_->finish_upload();56 return p_->finish_upload();
5257
=== modified file 'src/qt/client/internal/UploaderBase.cpp'
--- src/qt/client/internal/UploaderBase.cpp 2016-07-22 01:45:39 +0000
+++ src/qt/client/internal/UploaderBase.cpp 2016-08-03 04:16:38 +0000
@@ -25,6 +25,8 @@
25#include <QFuture>25#include <QFuture>
26#pragma GCC diagnostic pop26#pragma GCC diagnostic pop
2727
28#include <cassert>
29
28using namespace std;30using namespace std;
2931
30namespace unity32namespace unity
@@ -38,9 +40,16 @@
38namespace internal40namespace internal
39{41{
4042
41UploaderBase::UploaderBase(ConflictPolicy policy)43UploaderBase::UploaderBase(ConflictPolicy policy, int64_t size)
42 : policy_(policy)44 : policy_(policy)
43{45 , size_(size)
46{
47 assert(size >= 0);
48}
49
50int64_t UploaderBase::size() const
51{
52 return size_;
44}53}
4554
46} // namespace internal55} // namespace internal
4756
=== modified file 'src/qt/client/internal/local_client/UploaderImpl.cpp'
--- src/qt/client/internal/local_client/UploaderImpl.cpp 2016-08-03 04:16:38 +0000
+++ src/qt/client/internal/local_client/UploaderImpl.cpp 2016-08-03 04:16:38 +0000
@@ -143,8 +143,17 @@
143 {143 {
144 case in_progress:144 case in_progress:
145 {145 {
146 state_ = finalized;146 if (bytes_read_ != size_)
147 finalize();147 {
148 QString msg = "Uploader::finish_upload(): " + path_ + ": upload size of " + QString::number(size_)
149 + " does not match actual number of bytes read: " + QString::number(bytes_read_);
150 make_exceptional_future(qf_, LogicException(msg));
151 }
152 else
153 {
154 state_ = finalized;
155 finalize();
156 }
148 break;157 break;
149 }158 }
150 case finalized:159 case finalized:
@@ -342,7 +351,7 @@
342 QString const& path,351 QString const& path,
343 ConflictPolicy policy,352 ConflictPolicy policy,
344 weak_ptr<Root> root)353 weak_ptr<Root> root)
345 : UploaderBase(policy)354 : UploaderBase(policy, size)
346 , write_socket_(new QLocalSocket)355 , write_socket_(new QLocalSocket)
347{356{
348 // Set up socket pair.357 // Set up socket pair.
@@ -401,7 +410,6 @@
401 if (write_socket_->state() == QLocalSocket::ConnectedState)410 if (write_socket_->state() == QLocalSocket::ConnectedState)
402 {411 {
403 write_socket_->disconnectFromServer();412 write_socket_->disconnectFromServer();
404 write_socket_->close();
405 }413 }
406 return qf_.future();414 return qf_.future();
407}415}
@@ -409,7 +417,6 @@
409QFuture<void> UploaderImpl::cancel() noexcept417QFuture<void> UploaderImpl::cancel() noexcept
410{418{
411 Q_EMIT do_cancel();419 Q_EMIT do_cancel();
412 upload_thread_->wait();
413 write_socket_->abort();420 write_socket_->abort();
414 return qf_.future();421 return qf_.future();
415}422}
416423
=== modified file 'src/qt/client/internal/remote_client/DownloaderImpl.cpp'
--- src/qt/client/internal/remote_client/DownloaderImpl.cpp 2016-07-15 03:56:14 +0000
+++ src/qt/client/internal/remote_client/DownloaderImpl.cpp 2016-08-03 04:16:38 +0000
@@ -20,6 +20,7 @@
2020
21#include "ProviderInterface.h"21#include "ProviderInterface.h"
22#include <unity/storage/qt/client/Downloader.h>22#include <unity/storage/qt/client/Downloader.h>
23#include <unity/storage/qt/client/File.h>
23#include <unity/storage/qt/client/internal/remote_client/Handler.h>24#include <unity/storage/qt/client/internal/remote_client/Handler.h>
2425
25#include <cassert>26#include <cassert>
@@ -61,7 +62,7 @@
6162
62DownloaderImpl::~DownloaderImpl()63DownloaderImpl::~DownloaderImpl()
63{64{
64 cancel();65 read_socket_->abort();
65}66}
6667
67shared_ptr<File> DownloaderImpl::file() const68shared_ptr<File> DownloaderImpl::file() const
@@ -90,7 +91,8 @@
90QFuture<void> DownloaderImpl::cancel() noexcept91QFuture<void> DownloaderImpl::cancel() noexcept
91{92{
92 read_socket_->abort();93 read_socket_->abort();
93 return make_ready_future();94 QString msg = "Downloader::finish_download(): download of " + file_->name() + " was cancelled";
95 return make_exceptional_future(CancelledException(msg));
94}96}
9597
96Downloader::SPtr DownloaderImpl::make_downloader(QString const& download_id,98Downloader::SPtr DownloaderImpl::make_downloader(QString const& download_id,
9799
=== modified file 'src/qt/client/internal/remote_client/UploaderImpl.cpp'
--- src/qt/client/internal/remote_client/UploaderImpl.cpp 2016-08-03 04:16:38 +0000
+++ src/qt/client/internal/remote_client/UploaderImpl.cpp 2016-08-03 04:16:38 +0000
@@ -46,10 +46,9 @@
46 QString const& old_etag,46 QString const& old_etag,
47 weak_ptr<Root> root,47 weak_ptr<Root> root,
48 shared_ptr<ProviderInterface> const& provider)48 shared_ptr<ProviderInterface> const& provider)
49 : UploaderBase(old_etag == "" ? ConflictPolicy::overwrite : ConflictPolicy::error_if_conflict)49 : UploaderBase(old_etag == "" ? ConflictPolicy::overwrite : ConflictPolicy::error_if_conflict, size)
50 , upload_id_(upload_id)50 , upload_id_(upload_id)
51 , fd_(fd)51 , fd_(fd)
52 , size_(size)
53 , old_etag_(old_etag)52 , old_etag_(old_etag)
54 , root_(root.lock())53 , root_(root.lock())
55 , provider_(provider)54 , provider_(provider)
@@ -66,7 +65,7 @@
6665
67UploaderImpl::~UploaderImpl()66UploaderImpl::~UploaderImpl()
68{67{
69 cancel();68 write_socket_->abort();
70}69}
7170
72shared_ptr<QLocalSocket> UploaderImpl::socket() const71shared_ptr<QLocalSocket> UploaderImpl::socket() const
@@ -91,6 +90,7 @@
91 make_ready_future(qf, FileImpl::make_file(md, root_));90 make_ready_future(qf, FileImpl::make_file(md, root_));
92 };91 };
9392
93 write_socket_->disconnectFromServer();
94 auto handler = new Handler<shared_ptr<File>>(this, reply, process_reply);94 auto handler = new Handler<shared_ptr<File>>(this, reply, process_reply);
95 return handler->future();95 return handler->future();
96}96}
@@ -103,6 +103,7 @@
103 make_ready_future();103 make_ready_future();
104 };104 };
105105
106 write_socket_->abort();
106 auto handler = new Handler<void>(this, reply, process_reply);107 auto handler = new Handler<void>(this, reply, process_reply);
107 return handler->future();108 return handler->future();
108}109}
109110
=== modified file 'tests/local-client/local-client_test.cpp'
--- tests/local-client/local-client_test.cpp 2016-08-03 04:16:38 +0000
+++ tests/local-client/local-client_test.cpp 2016-08-03 04:16:38 +0000
@@ -422,6 +422,7 @@
422422
423 // Make a new file first.423 // Make a new file first.
424 auto uploader = call(root->create_file("new_file", 0));424 auto uploader = call(root->create_file("new_file", 0));
425 EXPECT_EQ(0, uploader->size());
425 auto file = call(uploader->finish_upload());426 auto file = call(uploader->finish_upload());
426 EXPECT_EQ(0, file->size());427 EXPECT_EQ(0, file->size());
427 auto old_etag = file->etag();428 auto old_etag = file->etag();
@@ -434,6 +435,7 @@
434 // Same test again, but this time, we write a bunch of data.435 // Same test again, but this time, we write a bunch of data.
435 std::string s(1000000, 'a');436 std::string s(1000000, 'a');
436 uploader = call(file->create_uploader(ConflictPolicy::overwrite, s.size()));437 uploader = call(file->create_uploader(ConflictPolicy::overwrite, s.size()));
438 EXPECT_EQ(1000000, uploader->size());
437 uploader->socket()->write(&s[0], s.size());439 uploader->socket()->write(&s[0], s.size());
438440
439 // Need to sleep here, otherwise it is possible for the441 // Need to sleep here, otherwise it is possible for the
@@ -549,6 +551,69 @@
549 }551 }
550}552}
551553
554TEST(File, upload_bad_size)
555{
556 auto runtime = Runtime::create();
557
558 auto acc = get_account(runtime);
559 auto root = get_root(runtime);
560 clear_folder(root);
561
562 // Uploader expects 100 bytes, but we write only 50.
563 {
564 auto uploader = call(root->create_file("file50", 100));
565 auto socket = uploader->socket();
566
567 QByteArray const contents(50, 'x');
568 auto written = socket->write(contents);
569 ASSERT_EQ(50, written);
570
571 try
572 {
573 call(uploader->finish_upload());
574 FAIL();
575 }
576 catch (LogicException const& e)
577 {
578 EXPECT_TRUE(e.error_message().startsWith("Uploader::finish_upload(): "));
579 EXPECT_TRUE(e.error_message().endsWith(": upload size of 100 does not match actual number of bytes read: 50"));
580 }
581 }
582
583 // Uploader expects 100 bytes, but we write 101.
584 {
585 auto uploader = call(root->create_file("file100", 100));
586 auto socket = uploader->socket();
587
588 QByteArray const contents(101, 'x');
589 auto written = socket->write(contents);
590 ASSERT_EQ(101, written);
591
592 try
593 {
594 call(uploader->finish_upload());
595 FAIL();
596 }
597 catch (LogicException const& e)
598 {
599 EXPECT_TRUE(e.error_message().startsWith("Uploader::finish_upload(): "));
600 EXPECT_TRUE(e.error_message().endsWith(": upload size of 100 does not match actual number of bytes read: 101"));
601 }
602
603 // Calling finish_upload() again must return the same future as the first time.
604 try
605 {
606 call(uploader->finish_upload());
607 FAIL();
608 }
609 catch (LogicException const& e)
610 {
611 EXPECT_TRUE(e.error_message().startsWith("Uploader::finish_upload(): "));
612 EXPECT_TRUE(e.error_message().endsWith(": upload size of 100 does not match actual number of bytes read: 101"));
613 }
614 }
615}
616
552TEST(File, create_uploader_bad_arg)617TEST(File, create_uploader_bad_arg)
553{618{
554 auto runtime = Runtime::create();619 auto runtime = Runtime::create();
555620
=== modified file 'tests/remote-client/remote-client_test.cpp'
--- tests/remote-client/remote-client_test.cpp 2016-08-03 04:16:38 +0000
+++ tests/remote-client/remote-client_test.cpp 2016-08-03 04:16:38 +0000
@@ -276,6 +276,7 @@
276 ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME));276 ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME));
277 }277 }
278 auto uploader = create_file_fut.result();278 auto uploader = create_file_fut.result();
279 EXPECT_EQ(0, uploader->size());
279 auto finish_upload_fut = uploader->finish_upload();280 auto finish_upload_fut = uploader->finish_upload();
280 {281 {
281 QFutureWatcher<File::SPtr> w;282 QFutureWatcher<File::SPtr> w;
@@ -424,6 +425,7 @@
424 ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME));425 ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME));
425 }426 }
426 auto uploader = create_uploader_fut.result();427 auto uploader = create_uploader_fut.result();
428 EXPECT_EQ(0, uploader->size());
427429
428 auto finish_upload_fut = uploader->finish_upload();430 auto finish_upload_fut = uploader->finish_upload();
429 {431 {

Subscribers

People subscribed via source and target branches

to all changes: