Merge lp:~michihenning/storage-framework/use-qiodevice into lp:storage-framework/devel

Proposed by Michi Henning
Status: Merged
Approved by: James Henstridge
Approved revision: 96
Merged at revision: 90
Proposed branch: lp:~michihenning/storage-framework/use-qiodevice
Merge into: lp:storage-framework/devel
Prerequisite: lp:~michihenning/storage-framework/metadata-keys
Diff against target: 2011 lines (+568/-498)
16 files modified
include/unity/storage/qt/Downloader.h (+14/-5)
include/unity/storage/qt/Uploader.h (+15/-4)
include/unity/storage/qt/client/internal/remote_client/HandlerBase.h (+1/-0)
include/unity/storage/qt/internal/DownloaderImpl.h (+12/-1)
include/unity/storage/qt/internal/Handler.h (+6/-0)
include/unity/storage/qt/internal/HandlerBase.h (+0/-2)
include/unity/storage/qt/internal/ListJobImplBase.h (+1/-0)
include/unity/storage/qt/internal/UploaderImpl.h (+18/-1)
include/unity/storage/qt/internal/VoidJobImpl.h (+1/-0)
src/qt/Downloader.cpp (+48/-5)
src/qt/Uploader.cpp (+48/-5)
src/qt/internal/DownloaderImpl.cpp (+97/-41)
src/qt/internal/HandlerBase.cpp (+1/-0)
src/qt/internal/UploaderImpl.cpp (+171/-59)
tests/remote-client/MockProvider.cpp (+4/-10)
tests/remote-client/remote-client_test.cpp (+131/-365)
To merge this branch: bzr merge lp:~michihenning/storage-framework/use-qiodevice
Reviewer Review Type Date Requested Status
James Henstridge Approve
unity-api-1-bot continuous-integration Approve
Review via email: mp+309713@code.launchpad.net

Commit message

Changed Uploader and Downloader to derive from QIODevice.

Description of the change

Changed Uploader and Downloader to derive from QIODevice.

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:88
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/162/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/928
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/935
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/738
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/738/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/738
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/738/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/738
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/738/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/738
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/738/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/738
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/738/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/738
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/738/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/738
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/738/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/738
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/738/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/738
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/738/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

PASSED: Continuous integration, rev:89
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/164/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/930
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/937
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/740
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/740/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/740
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/740/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/740
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/740/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/740
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/740/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/740
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/740/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/740
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/740/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/740
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/740/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/740
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/740/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/740
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/740/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
90. By Michi Henning

Merged dependent branch.

91. By Michi Henning

Merged dependent branch.

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

FAILED: Continuous integration, rev:90
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/169/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/947/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/954
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/757/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/757
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/757/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/757
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/757/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/757/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/757
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/757/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/757
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/757/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/757/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/757
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/757/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/757
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/757/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

PASSED: Continuous integration, rev:91
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/172/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/950
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/957
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/760
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/760/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/760
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/760/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/760
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/760/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/760
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/760/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/760
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/760/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/760
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/760/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/760
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/760/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/760
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/760/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/760
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/760/artifact/output/*zip*/output.zip

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

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

I've noted a few small issues via inline comments

review: Needs Fixing
Revision history for this message
Michi Henning (michihenning) wrote :

I removed the stale file from the merge conflict and got rid of the redundant Q_INVOKABLE, thanks!

For the uploader, my thinking was that the caller should not write to the uploader until it enters the Ready state.

I need to check what happens if a write is done before then. I would expect the write to return an error seeing that underlying socket isn't connected at that point. (If that isn't the case, we can easily arrange for the write to return -1.)

I think forcing the caller to wait until the socket is ready is better than buffering the data. After all, the socket may not ever become ready due to an error (such as the server side going belly-up for some reason) and, if the client is allowed to write regardless, all the data just ends up piling up in memory.

92. By Michi Henning

Got rid of merge conflict file and redundant Q_INVOKABLEs.

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

PASSED: Continuous integration, rev:92
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/176/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/965
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/972
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/773
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/773/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/773
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/773/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/773
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/773/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/773
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/773/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/773
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/773/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/773
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/773/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/773
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/773/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/773
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/773/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/773
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/773/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
93. By Michi Henning

Merged devel.

Revision history for this message
James Henstridge (jamesh) wrote :

The Uploader QIODevice is in its open state.

The expected semantics are that you can write to the device and those writes will be buffered, with the bytesWritten signal being used to notify when the write has completed.

While it is possible to signal an error, it seems that this is generally used for hard errors rather than simple "can't complete the write right now" errors. So if we throw away the early writes, we're effectively breaking the contract.

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

PASSED: Continuous integration, rev:93
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/180/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/972
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/979
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/779
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/779/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/779
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/779/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/779
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/779/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/779
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/779/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/779
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/779/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/779
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/779/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/779
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/779/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/779
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/779/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/779
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/779/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
94. By Michi Henning

Added code to deal with synchronous wait on uploader.
Not tested yet, because we need to make changes to the mock provider harness for this.

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

PASSED: Continuous integration, rev:94
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/186/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/998
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1005
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/802
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/802/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/802
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/802/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/802
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/802/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/802
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/802/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/802
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/802/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/802
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/802/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/802
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/802/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/802
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/802/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/802
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/802/artifact/output/*zip*/output.zip

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

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

This looks very close to ready. I've left a few inline comments. Some are just stylistic so could be ignored, so some could be left as is.

95. By Michi Henning

Review comments from James.

96. By Michi Henning

Renamed finishUpload() and finishDownload() to close().

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

PASSED: Continuous integration, rev:96
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/187/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/1000
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1007
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/804
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/804/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/804
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/804/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/804
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/804/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/804
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/804/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/804
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/804/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/804
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/804/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/804
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/804/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/804
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/804/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/804
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/804/artifact/output/*zip*/output.zip

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

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

Looks good!

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/qt/Downloader.h'
2--- include/unity/storage/qt/Downloader.h 2016-10-31 02:01:05 +0000
3+++ include/unity/storage/qt/Downloader.h 2016-11-04 07:34:14 +0000
4@@ -36,7 +36,7 @@
5
6 } // namespace internal
7
8-class Q_DECL_EXPORT Downloader final : public QLocalSocket
9+class Q_DECL_EXPORT Downloader final : public QIODevice
10 {
11 Q_OBJECT
12 Q_PROPERTY(bool isValid READ isValid NOTIFY statusChanged FINAL)
13@@ -51,15 +51,21 @@
14 Downloader();
15 virtual ~Downloader();
16
17- bool isValid() const; // Not nice, hides QLocalSocket::isValid()
18+ bool isValid() const;
19 Status status() const;
20- StorageError error() const; // Not nice, hides QLocalSocket::error()
21+ StorageError error() const;
22 Item item() const;
23
24- Q_INVOKABLE void finishDownload();
25 Q_INVOKABLE void cancel();
26
27- // TODO: will probably need QML invokable methods for reading and writing to/from QIODevice
28+ // From QLocalSocket interface.
29+ Q_INVOKABLE void close();
30+ Q_INVOKABLE qint64 bytesAvailable() const override;
31+ Q_INVOKABLE qint64 bytesToWrite() const override;
32+ Q_INVOKABLE bool canReadLine() const override;
33+ Q_INVOKABLE bool isSequential() const override;
34+ Q_INVOKABLE bool waitForBytesWritten(int msecs = 30000) override;
35+ Q_INVOKABLE bool waitForReadyRead(int msecs = 30000) override;
36
37 Q_SIGNALS:
38 void statusChanged(unity::storage::qt::Downloader::Status status) const;
39@@ -67,6 +73,9 @@
40 private:
41 Downloader(std::unique_ptr<internal::DownloaderImpl> p);
42
43+ qint64 readData(char* data, qint64 c);
44+ qint64 writeData(char const* data, qint64 c);
45+
46 std::unique_ptr<internal::DownloaderImpl> p_;
47
48 friend class internal::DownloaderImpl;
49
50=== modified file 'include/unity/storage/qt/Uploader.h'
51--- include/unity/storage/qt/Uploader.h 2016-10-12 05:25:20 +0000
52+++ include/unity/storage/qt/Uploader.h 2016-11-04 07:34:14 +0000
53@@ -39,7 +39,7 @@
54 class Item;
55 class StorageError;
56
57-class Q_DECL_EXPORT Uploader final : public QLocalSocket
58+class Q_DECL_EXPORT Uploader final : public QIODevice
59 {
60 Q_OBJECT
61 Q_PROPERTY(bool isValid READ isValid NOTIFY statusChanged FINAL)
62@@ -56,22 +56,33 @@
63 Uploader();
64 virtual ~Uploader();
65
66- bool isValid() const; // Not nice, hides QLocalSocket::isValid()
67+ bool isValid() const;
68 Status status() const;
69- StorageError error() const; // Not nice, hides QLocalSocket::error()
70+ StorageError error() const;
71 Item::ConflictPolicy policy() const;
72 qint64 sizeInBytes() const;
73 Item item() const;
74
75- Q_INVOKABLE void finishUpload();
76 Q_INVOKABLE void cancel();
77
78+ // From QLocalSocket interface.
79+ Q_INVOKABLE void close() override;
80+ Q_INVOKABLE qint64 bytesAvailable() const override;
81+ Q_INVOKABLE qint64 bytesToWrite() const override;
82+ Q_INVOKABLE bool canReadLine() const override;
83+ Q_INVOKABLE bool isSequential() const override;
84+ Q_INVOKABLE bool waitForBytesWritten(int msecs = 30000) override;
85+ Q_INVOKABLE bool waitForReadyRead(int msecs = 30000) override;
86+
87 Q_SIGNALS:
88 void statusChanged(unity::storage::qt::Uploader::Status status) const;
89
90 private:
91 Uploader(std::unique_ptr<internal::UploaderImpl> p);
92
93+ qint64 readData(char* data, qint64 c);
94+ qint64 writeData(char const* data, qint64 c);
95+
96 std::unique_ptr<internal::UploaderImpl> p_;
97
98 friend class internal::UploaderImpl;
99
100=== modified file 'include/unity/storage/qt/client/internal/remote_client/HandlerBase.h'
101--- include/unity/storage/qt/client/internal/remote_client/HandlerBase.h 2016-07-13 05:12:47 +0000
102+++ include/unity/storage/qt/client/internal/remote_client/HandlerBase.h 2016-11-04 07:34:14 +0000
103@@ -19,6 +19,7 @@
104 #pragma once
105
106 #pragma GCC diagnostic push
107+#pragma GCC diagnostic ignored "-Wcast-align"
108 #pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
109 #pragma GCC diagnostic ignored "-Wswitch-default"
110 #include <QDBusPendingCallWatcher>
111
112=== modified file 'include/unity/storage/qt/internal/DownloaderImpl.h'
113--- include/unity/storage/qt/internal/DownloaderImpl.h 2016-10-12 07:23:15 +0000
114+++ include/unity/storage/qt/internal/DownloaderImpl.h 2016-11-04 07:34:14 +0000
115@@ -47,9 +47,19 @@
116 StorageError error() const;
117 Item item() const;
118
119- void finishDownload();
120 void cancel();
121
122+ // From QLocalSocket interface.
123+ void close();
124+ qint64 bytesAvailable() const;
125+ qint64 bytesToWrite() const;
126+ bool canReadLine() const;
127+ bool isSequential() const;
128+ bool waitForBytesWritten(int msecs);
129+ bool waitForReadyRead(int msecs);
130+ qint64 readData(char* data, qint64 c);
131+ qint64 writeData(char const* data, qint64 c);
132+
133 static Downloader* make_job(std::shared_ptr<ItemImpl> const& item_impl,
134 QString const& method,
135 QDBusPendingReply<QString, QDBusUnixFileDescriptor>& reply);
136@@ -62,6 +72,7 @@
137 std::shared_ptr<ItemImpl> item_impl_;
138 QString download_id_;
139 QDBusUnixFileDescriptor fd_;
140+ QLocalSocket socket_;
141 bool finalizing_ = false;
142 };
143
144
145=== modified file 'include/unity/storage/qt/internal/Handler.h'
146--- include/unity/storage/qt/internal/Handler.h 2016-10-12 07:23:15 +0000
147+++ include/unity/storage/qt/internal/Handler.h 2016-11-04 07:34:14 +0000
148@@ -102,6 +102,12 @@
149 })
150 {
151 }
152+
153+ void wait_and_process_now()
154+ {
155+ watcher_.waitForFinished();
156+ finished(&watcher_);
157+ }
158 };
159
160 } // namespace internal
161
162=== modified file 'include/unity/storage/qt/internal/HandlerBase.h'
163--- include/unity/storage/qt/internal/HandlerBase.h 2016-09-21 00:29:49 +0000
164+++ include/unity/storage/qt/internal/HandlerBase.h 2016-11-04 07:34:14 +0000
165@@ -53,8 +53,6 @@
166
167 protected:
168 QDBusPendingCallWatcher watcher_;
169-
170-private:
171 std::function<void(QDBusPendingCallWatcher&)> closure_;
172 };
173
174
175=== modified file 'include/unity/storage/qt/internal/ListJobImplBase.h'
176--- include/unity/storage/qt/internal/ListJobImplBase.h 2016-10-12 05:25:20 +0000
177+++ include/unity/storage/qt/internal/ListJobImplBase.h 2016-11-04 07:34:14 +0000
178@@ -22,6 +22,7 @@
179 #include <unity/storage/qt/StorageError.h>
180
181 #pragma GCC diagnostic push
182+#pragma GCC diagnostic ignored "-Wcast-align"
183 #pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
184 #include <QDBusPendingReply>
185 #pragma GCC diagnostic pop
186
187=== modified file 'include/unity/storage/qt/internal/UploaderImpl.h'
188--- include/unity/storage/qt/internal/UploaderImpl.h 2016-11-03 03:41:24 +0000
189+++ include/unity/storage/qt/internal/UploaderImpl.h 2016-11-04 07:34:14 +0000
190@@ -18,10 +18,12 @@
191
192 #pragma once
193
194+#include <unity/storage/qt/internal/Handler.h>
195 #include <unity/storage/qt/Uploader.h>
196
197 #include <QDBusPendingReply>
198 #include <QDBusUnixFileDescriptor>
199+#include <QPointer>
200
201 namespace unity
202 {
203@@ -59,9 +61,19 @@
204 qint64 sizeInBytes() const;
205 Item item() const;
206
207- void finishUpload();
208 void cancel();
209
210+ // From QLocalSocket interface.
211+ void close();
212+ qint64 bytesAvailable() const;
213+ qint64 bytesToWrite() const;
214+ bool canReadLine() const;
215+ bool isSequential() const;
216+ bool waitForBytesWritten(int msecs);
217+ bool waitForReadyRead(int msecs);
218+ qint64 readData(char* data, qint64 c);
219+ qint64 writeData(char const* data, qint64 c);
220+
221 static Uploader* make_job(std::shared_ptr<ItemImpl> const& item_impl,
222 QString const& method,
223 QDBusPendingReply<QString, QDBusUnixFileDescriptor>& reply,
224@@ -70,6 +82,8 @@
225 qint64 size_in_bytes);
226 static Uploader* make_job(StorageError const& e);
227
228+ qint64 flush_buffer();
229+
230 private:
231 Uploader* public_instance_;
232 Uploader::Status status_;
233@@ -79,8 +93,11 @@
234 std::function<void(storage::internal::ItemMetadata const&)> validate_;
235 Item::ConflictPolicy policy_ = Item::ConflictPolicy::IgnoreConflict;
236 qint64 size_in_bytes_ = 0;
237+ QPointer<Handler<QDBusPendingReply<QString, QDBusUnixFileDescriptor>>> handler_;
238 QString upload_id_;
239 QDBusUnixFileDescriptor fd_;
240+ QLocalSocket socket_;
241+ QByteArray buffer_;
242 bool finalizing_ = false;
243 };
244
245
246=== modified file 'include/unity/storage/qt/internal/VoidJobImpl.h'
247--- include/unity/storage/qt/internal/VoidJobImpl.h 2016-10-12 08:08:48 +0000
248+++ include/unity/storage/qt/internal/VoidJobImpl.h 2016-11-04 07:34:14 +0000
249@@ -23,6 +23,7 @@
250 #include <unity/storage/qt/StorageError.h>
251
252 #pragma GCC diagnostic push
253+#pragma GCC diagnostic ignored "-Wcast-align"
254 #pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
255 #include <QDBusPendingReply>
256 #pragma GCC diagnostic pop
257
258=== modified file 'src/qt/Downloader.cpp'
259--- src/qt/Downloader.cpp 2016-10-11 08:12:32 +0000
260+++ src/qt/Downloader.cpp 2016-11-04 07:34:14 +0000
261@@ -61,16 +61,59 @@
262 return p_->item();
263 }
264
265-void Downloader::finishDownload()
266-{
267- p_->finishDownload();
268-}
269-
270 void Downloader::cancel()
271 {
272 p_->cancel();
273 }
274
275+void Downloader::close()
276+{
277+ p_->close();
278+}
279+
280+qint64 Downloader::bytesAvailable() const
281+{
282+ return p_->bytesAvailable();
283+}
284+
285+qint64 Downloader::bytesToWrite() const
286+{
287+ return p_->bytesToWrite();
288+}
289+
290+bool Downloader::canReadLine() const
291+{
292+ return p_->canReadLine();
293+}
294+
295+bool Downloader::isSequential() const
296+{
297+ return p_->isSequential();
298+}
299+
300+bool Downloader::waitForBytesWritten(int msecs)
301+{
302+ return p_->waitForBytesWritten(msecs);
303+}
304+
305+bool Downloader::waitForReadyRead(int msecs)
306+{
307+ return p_->waitForReadyRead(msecs);
308+}
309+
310+qint64 Downloader::readData(char* data, qint64 c)
311+{
312+ return p_->readData(data, c);
313+}
314+
315+// LCOV_EXCL_START
316+// Never called by QIODevice because device is opened read-only.
317+qint64 Downloader::writeData(char const* data, qint64 c)
318+{
319+ return p_->writeData(data, c);
320+}
321+// LCOV_EXCL_STOP
322+
323 } // namespace qt
324 } // namespace storage
325 } // namespace unity
326
327=== modified file 'src/qt/Uploader.cpp'
328--- src/qt/Uploader.cpp 2016-10-12 05:25:20 +0000
329+++ src/qt/Uploader.cpp 2016-11-04 07:34:14 +0000
330@@ -71,16 +71,59 @@
331 return p_->item();
332 }
333
334-void Uploader::finishUpload()
335-{
336- p_->finishUpload();
337-}
338-
339 void Uploader::cancel()
340 {
341 p_->cancel();
342 }
343
344+void Uploader::close()
345+{
346+ p_->close();
347+}
348+
349+qint64 Uploader::bytesAvailable() const
350+{
351+ return p_->bytesAvailable();
352+}
353+
354+qint64 Uploader::bytesToWrite() const
355+{
356+ return p_->bytesToWrite();
357+}
358+
359+bool Uploader::canReadLine() const
360+{
361+ return p_->canReadLine();
362+}
363+
364+bool Uploader::isSequential() const
365+{
366+ return p_->isSequential();
367+}
368+
369+bool Uploader::waitForBytesWritten(int msecs)
370+{
371+ return p_->waitForBytesWritten(msecs);
372+}
373+
374+bool Uploader::waitForReadyRead(int msecs)
375+{
376+ return p_->waitForReadyRead(msecs);
377+}
378+
379+// LCOV_EXCL_START
380+// Never called by QIODevice because device is opened write-only.
381+qint64 Uploader::readData(char* data, qint64 c)
382+{
383+ return p_->readData(data, c);
384+}
385+// LCOV_EXCL_STOP
386+
387+qint64 Uploader::writeData(char const* data, qint64 c)
388+{
389+ return p_->writeData(data, c);
390+}
391+
392 } // namespace qt
393 } // namespace storage
394 } // namespace unity
395
396=== modified file 'src/qt/internal/DownloaderImpl.cpp'
397--- src/qt/internal/DownloaderImpl.cpp 2016-10-13 06:48:11 +0000
398+++ src/qt/internal/DownloaderImpl.cpp 2016-11-04 07:34:14 +0000
399@@ -58,7 +58,7 @@
400 {
401 QString msg = method + ": Runtime was destroyed previously";
402 error_ = StorageErrorImpl::runtime_destroyed_error(msg);
403- public_instance_->abort();
404+ socket_.abort();
405 public_instance_->setErrorString(msg);
406 status_ = Downloader::Status::Error;
407 Q_EMIT public_instance_->statusChanged(status_);
408@@ -73,7 +73,7 @@
409 QString msg = method + ": invalid file descriptor returned by provider";
410 qCritical().noquote() << msg;
411 error_ = StorageErrorImpl::local_comms_error(msg);
412- public_instance_->abort();
413+ socket_.abort();
414 public_instance_->setErrorString(msg);
415 status_ = Downloader::Status::Error;
416 Q_EMIT public_instance_->statusChanged(status_);
417@@ -81,7 +81,18 @@
418 // LCOV_EXCL_STOP
419 }
420
421- public_instance_->setSocketDescriptor(fd_.fileDescriptor(), QLocalSocket::ConnectedState, QIODevice::ReadOnly);
422+ // We forward any QIODevice signals emitted by the socket to the public instance.
423+ connect(&socket_, &QIODevice::aboutToClose, public_instance_, &QIODevice::aboutToClose);
424+ connect(&socket_, &QIODevice::bytesWritten, public_instance_, &QIODevice::bytesWritten);
425+ connect(&socket_, &QIODevice::readChannelFinished, public_instance_, &QIODevice::readChannelFinished);
426+ connect(&socket_, &QIODevice::readyRead, public_instance_, &QIODevice::readyRead);
427+
428+#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
429+ connect(&socket_, &QIODevice::channelBytesWritten, public_instance_, &QIODevice::channelBytesWritten);
430+ connect(&socket_, &QIODevice::channelReadyRead, public_instance_, &QIODevice::channelReadyRead);
431+#endif
432+
433+ socket_.setSocketDescriptor(fd_.fileDescriptor(), QLocalSocket::ConnectedState, QIODevice::ReadOnly);
434 status_ = Downloader::Status::Ready;
435 Q_EMIT public_instance_->statusChanged(status_);
436 };
437@@ -91,12 +102,12 @@
438 // TODO: This does not set the method
439 error_ = error;
440 status_ = Downloader::Status::Error;
441- public_instance_->abort();
442+ socket_.abort();
443 public_instance_->setErrorString(error.errorString());
444 Q_EMIT public_instance_->statusChanged(status_);
445 };
446
447- new Handler<storage::internal::ItemMetadata>(this, reply, process_reply, process_error);
448+ new Handler<QDBusPendingReply<QString, QDBusUnixFileDescriptor>>(this, reply, process_reply, process_error);
449 }
450
451 DownloaderImpl::DownloaderImpl(StorageError const& e)
452@@ -146,11 +157,40 @@
453 return Item(item_impl_);
454 }
455
456-void DownloaderImpl::finishDownload()
457-{
458- static QString const method = "Downloader::finishDownload()";
459-
460- // If we encountered an error earlier or were cancelled, or if finishDownload() was
461+void DownloaderImpl::cancel()
462+{
463+ static QString const method = "Downloader::cancel()";
464+
465+ // If we are in a final state already, ignore the call.
466+ if ( status_ == Downloader::Status::Error
467+ || status_ == Downloader::Status::Finished
468+ || status_ == Downloader::Status::Cancelled)
469+ {
470+ return;
471+ }
472+ auto runtime = item_impl_->runtime_impl();
473+ if (!runtime || !runtime->isValid())
474+ {
475+ QString msg = method + ": Runtime was destroyed previously";
476+ error_ = StorageErrorImpl::runtime_destroyed_error(msg);
477+ status_ = Downloader::Status::Error;
478+ Q_EMIT public_instance_->statusChanged(status_);
479+ return;
480+ }
481+
482+ QString msg = method + ": download was cancelled";
483+ error_ = StorageErrorImpl::cancelled_error(msg);
484+ socket_.abort();
485+ public_instance_->setErrorString(msg);
486+ status_ = Downloader::Status::Cancelled;
487+ Q_EMIT public_instance_->statusChanged(status_);
488+}
489+
490+void DownloaderImpl::close()
491+{
492+ static QString const method = "Downloader::close()";
493+
494+ // If we encountered an error earlier or were cancelled, or if close() was
495 // called already, we ignore the call.
496 if (status_ == Downloader::Status::Error || status_ == Downloader::Status::Cancelled || finalizing_)
497 {
498@@ -162,7 +202,7 @@
499 {
500 QString msg = method + ": cannot finalize while Downloader is not in the Ready state";
501 error_ = StorageErrorImpl::logic_error(msg);
502- public_instance_->abort();
503+ socket_.abort();
504 public_instance_->setErrorString(msg);
505 status_ = Downloader::Status::Error;
506 Q_EMIT public_instance_->statusChanged(status_);
507@@ -194,7 +234,7 @@
508 {
509 QString msg = method + ": Runtime was destroyed previously";
510 error_ = StorageErrorImpl::runtime_destroyed_error(msg);
511- public_instance_->abort();
512+ socket_.abort();
513 public_instance_->setErrorString(msg);
514 status_ = Downloader::Status::Error;
515 Q_EMIT public_instance_->statusChanged(status_);
516@@ -214,7 +254,7 @@
517
518 // TODO: this doesn't set the method
519 error_ = error;
520- public_instance_->abort();
521+ socket_.abort();
522 public_instance_->setErrorString(error.errorString());
523 status_ = Downloader::Status::Error;
524 Q_EMIT public_instance_->statusChanged(status_);
525@@ -223,34 +263,48 @@
526 new Handler<void>(this, reply, process_reply, process_error);
527 }
528
529-void DownloaderImpl::cancel()
530-{
531- static QString const method = "Downloader::cancel()";
532-
533- // If we are in a final state already, ignore the call.
534- if ( status_ == Downloader::Status::Error
535- || status_ == Downloader::Status::Finished
536- || status_ == Downloader::Status::Cancelled)
537- {
538- return;
539- }
540- auto runtime = item_impl_->runtime_impl();
541- if (!runtime || !runtime->isValid())
542- {
543- QString msg = method + ": Runtime was destroyed previously";
544- error_ = StorageErrorImpl::runtime_destroyed_error(msg);
545- status_ = Downloader::Status::Error;
546- Q_EMIT public_instance_->statusChanged(status_);
547- return;
548- }
549-
550- QString msg = method + ": download was cancelled";
551- error_ = StorageErrorImpl::cancelled_error(msg);
552- public_instance_->abort();
553- public_instance_->setErrorString(msg);
554- status_ = Downloader::Status::Cancelled;
555- Q_EMIT public_instance_->statusChanged(status_);
556-}
557+qint64 DownloaderImpl::bytesAvailable() const
558+{
559+ return socket_.bytesAvailable();
560+}
561+
562+qint64 DownloaderImpl::bytesToWrite() const
563+{
564+ return socket_.bytesToWrite();
565+}
566+
567+bool DownloaderImpl::canReadLine() const
568+{
569+ return socket_.canReadLine();
570+}
571+
572+bool DownloaderImpl::isSequential() const
573+{
574+ return socket_.isSequential();
575+}
576+
577+bool DownloaderImpl::waitForBytesWritten(int msecs)
578+{
579+ return socket_.waitForBytesWritten(msecs);
580+}
581+
582+bool DownloaderImpl::waitForReadyRead(int msecs)
583+{
584+ return socket_.waitForReadyRead(msecs);
585+}
586+
587+qint64 DownloaderImpl::readData(char* data, qint64 c)
588+{
589+ return socket_.read(data, c);
590+}
591+
592+// LCOV_EXCL_START
593+// Never called by QIODevice because device is opened read-only.
594+qint64 DownloaderImpl::writeData(char const* data, qint64 c)
595+{
596+ return socket_.write(data, c);
597+}
598+// LCOV_EXCL_STOP
599
600 Downloader* DownloaderImpl::make_job(shared_ptr<ItemImpl> const& item_impl,
601 QString const& method,
602@@ -258,6 +312,7 @@
603 {
604 unique_ptr<DownloaderImpl> impl(new DownloaderImpl(item_impl, method, reply));
605 auto downloader = new Downloader(move(impl));
606+ downloader->open(QIODevice::ReadOnly);
607 downloader->p_->public_instance_ = downloader;
608 return downloader;
609 }
610@@ -266,6 +321,7 @@
611 {
612 unique_ptr<DownloaderImpl> impl(new DownloaderImpl(e));
613 auto downloader = new Downloader(move(impl));
614+ downloader->open(QIODevice::ReadOnly);
615 downloader->p_->public_instance_ = downloader;
616 QMetaObject::invokeMethod(downloader,
617 "statusChanged",
618
619=== modified file 'src/qt/internal/HandlerBase.cpp'
620--- src/qt/internal/HandlerBase.cpp 2016-09-20 04:53:49 +0000
621+++ src/qt/internal/HandlerBase.cpp 2016-11-04 07:34:14 +0000
622@@ -50,6 +50,7 @@
623 void HandlerBase::finished(QDBusPendingCallWatcher* call)
624 {
625 deleteLater();
626+ disconnect(&watcher_, &QDBusPendingCallWatcher::finished, this, &HandlerBase::finished);
627 closure_(*call);
628 }
629
630
631=== modified file 'src/qt/internal/UploaderImpl.cpp'
632--- src/qt/internal/UploaderImpl.cpp 2016-10-13 07:59:12 +0000
633+++ src/qt/internal/UploaderImpl.cpp 2016-11-04 07:34:14 +0000
634@@ -19,7 +19,7 @@
635 #include <unity/storage/qt/internal/UploaderImpl.h>
636
637 #include "ProviderInterface.h"
638-#include <unity/storage/qt/internal/Handler.h>
639+//#include <unity/storage/qt/internal/Handler.h>
640 #include <unity/storage/qt/internal/ItemImpl.h>
641 #include <unity/storage/qt/internal/VoidJobImpl.h>
642 #include <unity/storage/qt/ItemJob.h>
643@@ -55,7 +55,7 @@
644 assert(!method.isEmpty());
645 assert(size_in_bytes >= 0);
646
647- auto process_reply = [this, method](decltype(reply)& r)
648+ auto process_reply = [this, method](QDBusPendingReply<QString, QDBusUnixFileDescriptor>& r)
649 {
650 if (status_ != Uploader::Status::Loading)
651 {
652@@ -67,7 +67,7 @@
653 {
654 QString msg = method + ": Runtime was destroyed previously";
655 error_ = StorageErrorImpl::runtime_destroyed_error(msg);
656- public_instance_->abort();
657+ socket_.abort();
658 public_instance_->setErrorString(msg);
659 status_ = Uploader::Status::Error;
660 Q_EMIT public_instance_->statusChanged(status_);
661@@ -82,7 +82,7 @@
662 QString msg = method + ": invalid file descriptor returned by provider";
663 qCritical().noquote() << msg;
664 error_ = StorageErrorImpl::local_comms_error(msg);
665- public_instance_->abort();
666+ socket_.abort();
667 public_instance_->setErrorString(msg);
668 status_ = Uploader::Status::Error;
669 Q_EMIT public_instance_->statusChanged(status_);
670@@ -90,7 +90,19 @@
671 // LCOV_EXCL_STOP
672 }
673
674- public_instance_->setSocketDescriptor(fd_.fileDescriptor(), QLocalSocket::ConnectedState, QIODevice::WriteOnly);
675+ // We forward any QIODevice signals emitted by the socket to the public instance.
676+ connect(&socket_, &QIODevice::aboutToClose, public_instance_, &QIODevice::aboutToClose);
677+ connect(&socket_, &QIODevice::bytesWritten, public_instance_, &QIODevice::bytesWritten);
678+ connect(&socket_, &QIODevice::readChannelFinished, public_instance_, &QIODevice::readChannelFinished);
679+ connect(&socket_, &QIODevice::readyRead, public_instance_, &QIODevice::readyRead);
680+
681+#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
682+ connect(&socket_, &QIODevice::channelBytesWritten, public_instance_, &QIODevice::channelBytesWritten);
683+ connect(&socket_, &QIODevice::channelReadyRead, public_instance_, &QIODevice::channelReadyRead);
684+#endif
685+
686+ socket_.setSocketDescriptor(fd_.fileDescriptor(), QLocalSocket::ConnectedState, QIODevice::WriteOnly);
687+ flush_buffer();
688 status_ = Uploader::Status::Ready;
689 Q_EMIT public_instance_->statusChanged(status_);
690 };
691@@ -100,12 +112,12 @@
692 // TODO: This does not set the method
693 error_ = error;
694 status_ = Uploader::Status::Error;
695- public_instance_->abort();
696+ socket_.abort();
697 public_instance_->setErrorString(error.errorString());
698 Q_EMIT public_instance_->statusChanged(status_);
699 };
700
701- new Handler<storage::internal::ItemMetadata>(this, reply, process_reply, process_error);
702+ handler_ = new Handler<QDBusPendingReply<QString, QDBusUnixFileDescriptor>>(this, reply, process_reply, process_error);
703 }
704
705 UploaderImpl::UploaderImpl(StorageError const& e)
706@@ -165,11 +177,56 @@
707 return Item(item_impl_);
708 }
709
710-void UploaderImpl::finishUpload()
711-{
712- static QString const method = "Uploader::finishUpload()";
713-
714- // If we encountered an error earlier or were cancelled, or if finishUpload() was
715+void UploaderImpl::cancel()
716+{
717+ static QString const method = "Uploader::cancel()";
718+
719+ // If we are in a final state already, ignore the call.
720+ if ( status_ == Uploader::Status::Error
721+ || status_ == Uploader::Status::Finished
722+ || status_ == Uploader::Status::Cancelled)
723+ {
724+ return;
725+ }
726+ auto runtime = item_impl_->runtime_impl();
727+ if (!runtime || !runtime->isValid())
728+ {
729+ QString msg = method + ": Runtime was destroyed previously";
730+ error_ = StorageErrorImpl::runtime_destroyed_error(msg);
731+ status_ = Uploader::Status::Error;
732+ Q_EMIT public_instance_->statusChanged(status_);
733+ return;
734+ }
735+
736+ if (!upload_id_.isEmpty())
737+ {
738+ // We just send the cancel and ignore any reply because it is best-effort only.
739+ auto reply = item_impl_->account_impl()->provider()->CancelUpload(upload_id_);
740+
741+ auto process_reply = [](decltype(reply)&)
742+ {
743+ };
744+
745+ auto process_error = [](StorageError const&)
746+ {
747+ };
748+
749+ new Handler<void>(this, reply, process_reply, process_error);
750+ }
751+
752+ QString msg = method + ": upload was cancelled";
753+ error_ = StorageErrorImpl::cancelled_error(msg);
754+ socket_.abort();
755+ public_instance_->setErrorString(msg);
756+ status_ = Uploader::Status::Cancelled;
757+ Q_EMIT public_instance_->statusChanged(status_);
758+}
759+
760+void UploaderImpl::close()
761+{
762+ static QString const method = "Uploader::close()";
763+
764+ // If we encountered an error earlier or were cancelled, or if close() was
765 // called already, we ignore the call.
766 if (status_ == Uploader::Status::Error || status_ == Uploader::Status::Cancelled || finalizing_)
767 {
768@@ -181,7 +238,7 @@
769 {
770 QString msg = method + ": cannot finalize while Uploader is not in the Ready state";
771 error_ = StorageErrorImpl::logic_error(msg);
772- public_instance_->abort();
773+ socket_.abort();
774 public_instance_->setErrorString(msg);
775 status_ = Uploader::Status::Error;
776 Q_EMIT public_instance_->statusChanged(status_);
777@@ -199,7 +256,8 @@
778 }
779
780 finalizing_ = true;
781- public_instance_->disconnectFromServer();
782+ flush_buffer();
783+ socket_.disconnectFromServer();
784 auto reply = item_impl_->account_impl()->provider()->FinishUpload(upload_id_);
785
786 auto process_reply = [this](decltype(reply)& r)
787@@ -214,7 +272,7 @@
788 {
789 QString msg = method + ": Runtime was destroyed previously";
790 error_ = StorageErrorImpl::runtime_destroyed_error(msg);
791- public_instance_->abort();
792+ socket_.abort();
793 public_instance_->setErrorString(msg);
794 status_ = Uploader::Status::Error;
795 Q_EMIT public_instance_->statusChanged(status_);
796@@ -247,7 +305,7 @@
797
798 // TODO: this doesn't set the method
799 error_ = error;
800- public_instance_->abort();
801+ socket_.abort();
802 public_instance_->setErrorString(error.errorString());
803 status_ = Uploader::Status::Error;
804 Q_EMIT public_instance_->statusChanged(status_);
805@@ -256,49 +314,85 @@
806 new Handler<void>(this, reply, process_reply, process_error);
807 }
808
809-void UploaderImpl::cancel()
810-{
811- static QString const method = "Uploader::cancel()";
812-
813- // If we are in a final state already, ignore the call.
814- if ( status_ == Uploader::Status::Error
815- || status_ == Uploader::Status::Finished
816- || status_ == Uploader::Status::Cancelled)
817- {
818- return;
819- }
820- auto runtime = item_impl_->runtime_impl();
821- if (!runtime || !runtime->isValid())
822- {
823- QString msg = method + ": Runtime was destroyed previously";
824- error_ = StorageErrorImpl::runtime_destroyed_error(msg);
825- status_ = Uploader::Status::Error;
826- Q_EMIT public_instance_->statusChanged(status_);
827- return;
828- }
829-
830- if (!upload_id_.isEmpty())
831- {
832- // We just send the cancel and ignore any reply because it is best-effort only.
833- auto reply = item_impl_->account_impl()->provider()->CancelUpload(upload_id_);
834-
835- auto process_reply = [](decltype(reply)&)
836- {
837- };
838-
839- auto process_error = [](StorageError const&)
840- {
841- };
842-
843- new Handler<void>(this, reply, process_reply, process_error);
844- }
845-
846- QString msg = method + ": upload was cancelled";
847- error_ = StorageErrorImpl::cancelled_error(msg);
848- public_instance_->abort();
849- public_instance_->setErrorString(msg);
850- status_ = Uploader::Status::Cancelled;
851- Q_EMIT public_instance_->statusChanged(status_);
852+qint64 UploaderImpl::bytesAvailable() const
853+{
854+ return socket_.bytesAvailable();
855+}
856+
857+qint64 UploaderImpl::bytesToWrite() const
858+{
859+ return socket_.bytesToWrite();
860+}
861+
862+bool UploaderImpl::canReadLine() const
863+{
864+ return socket_.canReadLine();
865+}
866+
867+bool UploaderImpl::isSequential() const
868+{
869+ return socket_.isSequential();
870+}
871+
872+bool UploaderImpl::waitForBytesWritten(int msecs)
873+{
874+ if (status_ == Uploader::Status::Loading)
875+ {
876+ // Unfortunately, QDBusPendingReply::waitForFinished() does not accept a timeout.
877+ // The next-best thing we can do is to simply wait without a timeout. The DBus
878+ // method will finish eventually, even though it might take a lot longer than msecs.
879+ handler_->wait_and_process_now();
880+ }
881+ if (flush_buffer() == -1)
882+ {
883+ return false;
884+ }
885+ return socket_.waitForBytesWritten(msecs);
886+}
887+
888+bool UploaderImpl::waitForReadyRead(int msecs)
889+{
890+ return socket_.waitForReadyRead(msecs);
891+}
892+
893+// LCOV_EXCL_START
894+// Never called by QIODevice because device is opened write-only.
895+qint64 UploaderImpl::readData(char* data, qint64 c)
896+{
897+ return socket_.read(data, c);
898+}
899+// LCOV_EXCL_STOP
900+
901+qint64 UploaderImpl::writeData(char const* data, qint64 c)
902+{
903+ switch (status_)
904+ {
905+ case Uploader::Status::Loading:
906+ {
907+ // Client is writing before we have received the file descriptor from the provider.
908+ buffer_.append(data, c);
909+ return c;
910+ }
911+ case Uploader::Status::Ready:
912+ {
913+ if (flush_buffer() == -1)
914+ {
915+ return -1;
916+ }
917+ return socket_.write(data, c);
918+ }
919+ case Uploader::Status::Cancelled:
920+ case Uploader::Status::Finished:
921+ case Uploader::Status::Error:
922+ {
923+ return -1; // Can't write to an already-finalized uploader.
924+ }
925+ default:
926+ {
927+ abort(); // Impossible // LCOV_EXCL_LINE
928+ }
929+ }
930+ // NOTREACHED
931 }
932
933 Uploader* UploaderImpl::make_job(shared_ptr<ItemImpl> const& item_impl,
934@@ -310,6 +404,7 @@
935 {
936 unique_ptr<UploaderImpl> impl(new UploaderImpl(item_impl, method, reply, validate, policy, size_in_bytes));
937 auto uploader = new Uploader(move(impl));
938+ uploader->open(QIODevice::WriteOnly);
939 uploader->p_->public_instance_ = uploader;
940 return uploader;
941 }
942@@ -318,6 +413,7 @@
943 {
944 unique_ptr<UploaderImpl> impl(new UploaderImpl(e));
945 auto uploader = new Uploader(move(impl));
946+ uploader->open(QIODevice::WriteOnly);
947 uploader->p_->public_instance_ = uploader;
948 QMetaObject::invokeMethod(uploader,
949 "statusChanged",
950@@ -326,6 +422,22 @@
951 return uploader;
952 }
953
954+qint64 UploaderImpl::flush_buffer()
955+{
956+ qint64 bytes_written = 0;
957+ auto bytes_to_write = buffer_.size();
958+ if (bytes_to_write > 0)
959+ {
960+ auto bytes_written = socket_.write(buffer_.data(), bytes_to_write);
961+ if (bytes_written != bytes_to_write)
962+ {
963+ return -1; // Not exactly detailed, but that's the best we can do. // LCOV_EXCL_LINE
964+ }
965+ buffer_.resize(0);
966+ }
967+ return bytes_written;
968+}
969+
970 } // namespace internal
971 } // namespace qt
972 } // namespace storage
973
974=== modified file 'tests/remote-client/MockProvider.cpp'
975--- tests/remote-client/MockProvider.cpp 2016-11-03 03:41:24 +0000
976+++ tests/remote-client/MockProvider.cpp 2016-11-04 07:34:14 +0000
977@@ -194,9 +194,9 @@
978 ++num_calls;
979 switch (num_calls)
980 {
981+ case 2:
982+ return make_exceptional_future<Item>(ResourceException("metadata(): weird error", 42));
983 case 3:
984- return make_exceptional_future<Item>(ResourceException("metadata(): weird error", 42));
985- case 4:
986 num_calls = 0;
987 return make_exceptional_future<Item>(RemoteCommsException("metadata(): HTTP broken"));
988 default:
989@@ -207,14 +207,8 @@
990 {
991 if (cmd_ == "bad_parent_metadata_from_child")
992 {
993- ++num_calls;
994- if (num_calls == 2)
995- {
996- num_calls = 0;
997- // On second call, we return type file for the root.
998- Item metadata{"root_id", {}, "Root", "etag", ItemType::file, {}};
999- return make_ready_future<Item>(metadata);
1000- }
1001+ Item metadata{"root_id", {}, "Root", "etag", ItemType::file, {}};
1002+ return make_ready_future<Item>(metadata);
1003 }
1004 if (cmd_ == "root_with_parent")
1005 {
1006
1007=== modified file 'tests/remote-client/remote-client_test.cpp'
1008--- tests/remote-client/remote-client_test.cpp 2016-11-03 07:33:40 +0000
1009+++ tests/remote-client/remote-client_test.cpp 2016-11-04 07:34:14 +0000
1010@@ -1310,14 +1310,6 @@
1011 {
1012 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("two_parents")));
1013
1014- Item root;
1015- {
1016- unique_ptr<ItemJob> j(acc_.get("root_id"));
1017- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1018- spy.wait(SIGNAL_WAIT_TIME);
1019- root = j->item();
1020- }
1021-
1022 Item child;
1023 {
1024 unique_ptr<ItemJob> j(acc_.get("child_id"));
1025@@ -1364,14 +1356,6 @@
1026 {
1027 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("two_parents_throw")));
1028
1029- Item root;
1030- {
1031- unique_ptr<ItemJob> j(acc_.get("root_id"));
1032- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1033- spy.wait(SIGNAL_WAIT_TIME);
1034- root = j->item();
1035- }
1036-
1037 Item child;
1038 {
1039 unique_ptr<ItemJob> j(acc_.get("child_id"));
1040@@ -1455,14 +1439,6 @@
1041 {
1042 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("slow_metadata")));
1043
1044- Item root;
1045- {
1046- unique_ptr<ItemJob> j(acc_.get("root_id"));
1047- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1048- spy.wait(SIGNAL_WAIT_TIME);
1049- root = j->item();
1050- }
1051-
1052 Item child;
1053 {
1054 unique_ptr<ItemJob> j(acc_.get("child_id"));
1055@@ -1489,14 +1465,6 @@
1056 {
1057 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("bad_parent_metadata_from_child")));
1058
1059- Item root;
1060- {
1061- unique_ptr<ItemJob> j(acc_.get("root_id"));
1062- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1063- spy.wait(SIGNAL_WAIT_TIME);
1064- root = j->item();
1065- }
1066-
1067 Item child;
1068 {
1069 unique_ptr<ItemJob> j(acc_.get("child_id"));
1070@@ -1600,14 +1568,6 @@
1071 {
1072 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1073
1074- Item root;
1075- {
1076- unique_ptr<ItemJob> j(acc_.get("root_id"));
1077- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1078- spy.wait(SIGNAL_WAIT_TIME);
1079- root = j->item();
1080- }
1081-
1082 Item child;
1083 {
1084 unique_ptr<ItemJob> j(acc_.get("child_id"));
1085@@ -1731,14 +1691,6 @@
1086 {
1087 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1088
1089- Item root;
1090- {
1091- unique_ptr<ItemJob> j(acc_.get("root_id"));
1092- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1093- spy.wait(SIGNAL_WAIT_TIME);
1094- root = j->item();
1095- }
1096-
1097 Item child;
1098 {
1099 unique_ptr<ItemJob> j(acc_.get("child_id"));
1100@@ -2014,14 +1966,6 @@
1101 {
1102 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1103
1104- Item root;
1105- {
1106- unique_ptr<ItemJob> j(acc_.get("root_id"));
1107- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1108- spy.wait(SIGNAL_WAIT_TIME);
1109- root = j->item();
1110- }
1111-
1112 Item child;
1113 {
1114 unique_ptr<ItemJob> j(acc_.get("child_id"));
1115@@ -2102,14 +2046,6 @@
1116 {
1117 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1118
1119- Item root;
1120- {
1121- unique_ptr<ItemJob> j(acc_.get("root_id"));
1122- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1123- spy.wait(SIGNAL_WAIT_TIME);
1124- root = j->item();
1125- }
1126-
1127 Item child;
1128 {
1129 unique_ptr<ItemJob> j(acc_.get("child_id"));
1130@@ -2320,14 +2256,6 @@
1131 {
1132 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1133
1134- Item root;
1135- {
1136- unique_ptr<ItemJob> j(acc_.get("root_id"));
1137- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1138- spy.wait(SIGNAL_WAIT_TIME);
1139- root = j->item();
1140- }
1141-
1142 Item child;
1143 {
1144 unique_ptr<ItemJob> j(acc_.get("child_id"));
1145@@ -2434,14 +2362,6 @@
1146 {
1147 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1148
1149- Item root;
1150- {
1151- unique_ptr<ItemJob> j(acc_.get("root_id"));
1152- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1153- spy.wait(SIGNAL_WAIT_TIME);
1154- root = j->item();
1155- }
1156-
1157 Item child;
1158 {
1159 unique_ptr<ItemJob> j(acc_.get("child_id"));
1160@@ -2468,10 +2388,17 @@
1161 read_spy.wait(SIGNAL_WAIT_TIME);
1162 }
1163 }
1164+
1165+ EXPECT_EQ(11, downloader->bytesAvailable());
1166+ EXPECT_EQ(0, downloader->bytesToWrite());
1167+ EXPECT_EQ(-1, downloader->write("a", 1));
1168+ EXPECT_FALSE(downloader->waitForBytesWritten(1));
1169+ EXPECT_FALSE(downloader->waitForReadyRead(1));
1170+
1171 auto data = downloader->readAll();
1172 EXPECT_EQ(QByteArray("Hello world", -1), data);
1173
1174- downloader->finishDownload();
1175+ downloader->close();
1176 ASSERT_TRUE(status_spy.wait(SIGNAL_WAIT_TIME));
1177 auto arg = status_spy.takeFirst();
1178 EXPECT_EQ(Downloader::Status::Finished, qvariant_cast<Downloader::Status>(arg.at(0)));
1179@@ -2496,14 +2423,6 @@
1180 {
1181 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1182
1183- Item root;
1184- {
1185- unique_ptr<ItemJob> j(acc_.get("root_id"));
1186- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1187- spy.wait(SIGNAL_WAIT_TIME);
1188- root = j->item();
1189- }
1190-
1191 Item child;
1192 {
1193 unique_ptr<ItemJob> j(acc_.get("child_id"));
1194@@ -2521,20 +2440,14 @@
1195 auto arg = spy.takeFirst();
1196 EXPECT_EQ(Downloader::Status::Ready, qvariant_cast<Downloader::Status>(arg.at(0)));
1197 }
1198+
1199+ EXPECT_TRUE(downloader->waitForReadyRead(SIGNAL_WAIT_TIME));
1200 }
1201
1202 TEST_F(DownloadTest, runtime_destroyed)
1203 {
1204 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1205
1206- Item root;
1207- {
1208- unique_ptr<ItemJob> j(acc_.get("root_id"));
1209- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1210- spy.wait(SIGNAL_WAIT_TIME);
1211- root = j->item();
1212- }
1213-
1214 Item child;
1215 {
1216 unique_ptr<ItemJob> j(acc_.get("child_id"));
1217@@ -2566,14 +2479,6 @@
1218 {
1219 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("download_slow")));
1220
1221- Item root;
1222- {
1223- unique_ptr<ItemJob> j(acc_.get("root_id"));
1224- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1225- spy.wait(SIGNAL_WAIT_TIME);
1226- root = j->item();
1227- }
1228-
1229 Item child;
1230 {
1231 unique_ptr<ItemJob> j(acc_.get("child_id"));
1232@@ -2607,14 +2512,6 @@
1233 {
1234 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("download_error")));
1235
1236- Item root;
1237- {
1238- unique_ptr<ItemJob> j(acc_.get("root_id"));
1239- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1240- spy.wait(SIGNAL_WAIT_TIME);
1241- root = j->item();
1242- }
1243-
1244 Item child;
1245 {
1246 unique_ptr<ItemJob> j(acc_.get("child_id"));
1247@@ -2641,10 +2538,10 @@
1248 EXPECT_EQ(42, downloader->error().errorCode());
1249 EXPECT_EQ(Item(), downloader->item());
1250
1251- // For coverage: call finishDownload() while in the Error state.
1252+ // For coverage: call close() while in the Error state.
1253 {
1254 QSignalSpy spy(downloader.get(), &Downloader::statusChanged);
1255- downloader->finishDownload();
1256+ downloader->close();
1257 EXPECT_FALSE(spy.wait(1000));
1258 }
1259 }
1260@@ -2653,14 +2550,6 @@
1261 {
1262 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1263
1264- Item root;
1265- {
1266- unique_ptr<ItemJob> j(acc_.get("root_id"));
1267- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1268- spy.wait(SIGNAL_WAIT_TIME);
1269- root = j->item();
1270- }
1271-
1272 Item child;
1273 {
1274 unique_ptr<ItemJob> j(acc_.get("child_id"));
1275@@ -2674,7 +2563,7 @@
1276
1277 QSignalSpy spy(downloader.get(), &Downloader::statusChanged);
1278
1279- downloader->finishDownload();
1280+ downloader->close();
1281
1282 ASSERT_EQ(1, spy.count());
1283 auto arg = spy.takeFirst();
1284@@ -2683,7 +2572,7 @@
1285 EXPECT_FALSE(downloader->isValid());
1286 EXPECT_EQ(Downloader::Status::Error, downloader->status());
1287 EXPECT_EQ(StorageError::LogicError, downloader->error().type());
1288- EXPECT_EQ("LogicError: Downloader::finishDownload(): cannot finalize while Downloader is not in the Ready state",
1289+ EXPECT_EQ("LogicError: Downloader::close(): cannot finalize while Downloader is not in the Ready state",
1290 downloader->error().errorString());
1291 }
1292
1293@@ -2691,14 +2580,6 @@
1294 {
1295 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1296
1297- Item root;
1298- {
1299- unique_ptr<ItemJob> j(acc_.get("root_id"));
1300- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1301- spy.wait(SIGNAL_WAIT_TIME);
1302- root = j->item();
1303- }
1304-
1305 Item child;
1306 {
1307 unique_ptr<ItemJob> j(acc_.get("child_id"));
1308@@ -2721,7 +2602,7 @@
1309
1310 EXPECT_EQ(StorageError::Type::NoError, runtime_->shutdown().type()); // Destroy runtime
1311
1312- downloader->finishDownload();
1313+ downloader->close();
1314
1315 ASSERT_EQ(1, spy.count());
1316 auto arg = spy.takeFirst();
1317@@ -2730,21 +2611,13 @@
1318 EXPECT_FALSE(downloader->isValid());
1319 EXPECT_EQ(Downloader::Status::Error, downloader->status());
1320 EXPECT_EQ(StorageError::RuntimeDestroyed, downloader->error().type());
1321- EXPECT_EQ("Downloader::finishDownload(): Runtime was destroyed previously", downloader->error().message());
1322+ EXPECT_EQ("Downloader::close(): Runtime was destroyed previously", downloader->error().message());
1323 }
1324
1325 TEST_F(DownloadTest, finish_runtime_destroyed_while_reply_outstanding)
1326 {
1327 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("finish_download_slow")));
1328
1329- Item root;
1330- {
1331- unique_ptr<ItemJob> j(acc_.get("root_id"));
1332- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1333- spy.wait(SIGNAL_WAIT_TIME);
1334- root = j->item();
1335- }
1336-
1337 Item child;
1338 {
1339 unique_ptr<ItemJob> j(acc_.get("child_id"));
1340@@ -2765,7 +2638,7 @@
1341
1342 QSignalSpy spy(downloader.get(), &Downloader::statusChanged);
1343
1344- downloader->finishDownload();
1345+ downloader->close();
1346
1347 EXPECT_EQ(StorageError::Type::NoError, runtime_->shutdown().type()); // Destroy runtime, provider still sleeping
1348
1349@@ -2776,21 +2649,13 @@
1350 EXPECT_FALSE(downloader->isValid());
1351 EXPECT_EQ(Downloader::Status::Error, downloader->status());
1352 EXPECT_EQ(StorageError::RuntimeDestroyed, downloader->error().type());
1353- EXPECT_EQ("Downloader::finishDownload(): Runtime was destroyed previously", downloader->error().message());
1354+ EXPECT_EQ("Downloader::close(): Runtime was destroyed previously", downloader->error().message());
1355 }
1356
1357 TEST_F(DownloadTest, finish_twice)
1358 {
1359 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1360
1361- Item root;
1362- {
1363- unique_ptr<ItemJob> j(acc_.get("root_id"));
1364- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1365- spy.wait(SIGNAL_WAIT_TIME);
1366- root = j->item();
1367- }
1368-
1369 Item child;
1370 {
1371 unique_ptr<ItemJob> j(acc_.get("child_id"));
1372@@ -2811,8 +2676,8 @@
1373
1374 QSignalSpy spy(downloader.get(), &Downloader::statusChanged);
1375
1376- downloader->finishDownload();
1377- downloader->finishDownload();
1378+ downloader->close();
1379+ downloader->close();
1380
1381 ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME));
1382 auto arg = spy.takeFirst();
1383@@ -2825,14 +2690,6 @@
1384 {
1385 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("finish_download_error")));
1386
1387- Item root;
1388- {
1389- unique_ptr<ItemJob> j(acc_.get("root_id"));
1390- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1391- spy.wait(SIGNAL_WAIT_TIME);
1392- root = j->item();
1393- }
1394-
1395 Item child;
1396 {
1397 unique_ptr<ItemJob> j(acc_.get("child_id"));
1398@@ -2853,7 +2710,7 @@
1399
1400 QSignalSpy spy(downloader.get(), &Downloader::statusChanged);
1401
1402- downloader->finishDownload();
1403+ downloader->close();
1404
1405 ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME));
1406 auto arg = spy.takeFirst();
1407@@ -2925,14 +2782,6 @@
1408 {
1409 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("finish_download_slow_error")));
1410
1411- Item root;
1412- {
1413- unique_ptr<ItemJob> j(acc_.get("root_id"));
1414- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1415- spy.wait(SIGNAL_WAIT_TIME);
1416- root = j->item();
1417- }
1418-
1419 Item child;
1420 {
1421 unique_ptr<ItemJob> j(acc_.get("child_id"));
1422@@ -2953,12 +2802,12 @@
1423
1424 QSignalSpy spy(downloader.get(), &Downloader::statusChanged);
1425
1426- downloader->finishDownload();
1427+ downloader->close();
1428
1429 downloader->cancel();
1430 downloader->cancel(); // Second time for coverage
1431
1432- downloader->finishDownload(); // Second time for coverage
1433+ downloader->close(); // Second time for coverage
1434
1435 EXPECT_EQ(1, spy.count());
1436 auto arg = spy.takeFirst();
1437@@ -2968,7 +2817,7 @@
1438 EXPECT_EQ(StorageError::Type::Cancelled, downloader->error().type());
1439 EXPECT_EQ("Downloader::cancel(): download was cancelled", downloader->error().message());
1440
1441- // We wait here to get coverage for when the reply to a finishDownload() call
1442+ // We wait here to get coverage for when the reply to a FinishDownload() call
1443 // finds the downloader in a final state.
1444 EXPECT_FALSE(spy.wait(2000));
1445 }
1446@@ -2977,14 +2826,6 @@
1447 {
1448 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("finish_download_slow_error")));
1449
1450- Item root;
1451- {
1452- unique_ptr<ItemJob> j(acc_.get("root_id"));
1453- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1454- spy.wait(SIGNAL_WAIT_TIME);
1455- root = j->item();
1456- }
1457-
1458 Item child;
1459 {
1460 unique_ptr<ItemJob> j(acc_.get("child_id"));
1461@@ -3025,14 +2866,6 @@
1462 {
1463 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1464
1465- Item root;
1466- {
1467- unique_ptr<ItemJob> j(acc_.get("root_id"));
1468- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1469- spy.wait(SIGNAL_WAIT_TIME);
1470- root = j->item();
1471- }
1472-
1473 Item child;
1474 {
1475 unique_ptr<ItemJob> j(acc_.get("child_id"));
1476@@ -3057,10 +2890,92 @@
1477 EXPECT_EQ(Uploader::Status::Ready, qvariant_cast<Uploader::Status>(arg.at(0)));
1478 }
1479
1480- EXPECT_EQ(contents.size(), uploader->write(contents));
1481-
1482- QSignalSpy spy(uploader.get(), &Uploader::statusChanged);
1483- uploader->finishUpload();
1484+ EXPECT_EQ(0, uploader->bytesAvailable());
1485+ EXPECT_EQ(0, uploader->bytesToWrite());
1486+ char buf;
1487+ EXPECT_EQ(-1, uploader->read(&buf, 1));
1488+ EXPECT_FALSE(uploader->waitForReadyRead(1));
1489+
1490+ EXPECT_EQ(contents.size(), uploader->write(contents));
1491+ EXPECT_TRUE(uploader->waitForBytesWritten(contents.size()));
1492+
1493+ QSignalSpy spy(uploader.get(), &Uploader::statusChanged);
1494+ uploader->close();
1495+ ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME));
1496+ auto arg = spy.takeFirst();
1497+ EXPECT_EQ(Uploader::Status::Finished, qvariant_cast<Uploader::Status>(arg.at(0)));
1498+
1499+ EXPECT_EQ(Uploader::Status::Finished, uploader->status());
1500+ EXPECT_EQ(child, uploader->item());
1501+}
1502+
1503+#if 0
1504+// TODO: This test is currently disabled because a synchronous wait in the client
1505+// blocks the single event loop that is shared by the client and the mock provider.
1506+// We need to change the test harness to run a separate event loop for the provider.
1507+//
1508+TEST_F(UploadTest, write_before_ready_and_wait)
1509+{
1510+ set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("upload_slow")));
1511+
1512+ Item child;
1513+ {
1514+ unique_ptr<ItemJob> j(acc_.get("child_id"));
1515+ QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1516+ spy.wait(SIGNAL_WAIT_TIME);
1517+ child = j->item();
1518+ }
1519+
1520+ QByteArray contents("Hello world", -1);
1521+ unique_ptr<Uploader> uploader(child.createUploader(Item::ConflictPolicy::IgnoreConflict, contents.size()));
1522+ EXPECT_TRUE(uploader->isValid());
1523+
1524+ // Don't wait for ready state.
1525+
1526+ EXPECT_EQ(contents.size(), uploader->write(contents));
1527+ EXPECT_TRUE(uploader->waitForBytesWritten(1000));
1528+
1529+ QSignalSpy spy(uploader.get(), &Uploader::statusChanged);
1530+ uploader->close();
1531+ ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME));
1532+ auto arg = spy.takeFirst();
1533+ EXPECT_EQ(Uploader::Status::Finished, qvariant_cast<Uploader::Status>(arg.at(0)));
1534+
1535+ EXPECT_EQ(Uploader::Status::Finished, uploader->status());
1536+ EXPECT_EQ(child, uploader->item());
1537+}
1538+#endif
1539+
1540+TEST_F(UploadTest, write_before_ready)
1541+{
1542+ set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("upload_slow")));
1543+
1544+ Item child;
1545+ {
1546+ unique_ptr<ItemJob> j(acc_.get("child_id"));
1547+ QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1548+ spy.wait(SIGNAL_WAIT_TIME);
1549+ child = j->item();
1550+ }
1551+
1552+ QByteArray contents("Hello world", -1);
1553+ unique_ptr<Uploader> uploader(child.createUploader(Item::ConflictPolicy::IgnoreConflict, contents.size()));
1554+ EXPECT_TRUE(uploader->isValid());
1555+
1556+ // Don't wait for ready state.
1557+
1558+ EXPECT_EQ(contents.size(), uploader->write(contents));
1559+
1560+ // Wait until we get confirmation that the contents were written.
1561+ {
1562+ QSignalSpy spy(uploader.get(), &Uploader::bytesWritten);
1563+ ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME));
1564+ auto arg = spy.takeFirst();
1565+ EXPECT_TRUE(qvariant_cast<bool>(arg.at(0)));
1566+ }
1567+
1568+ QSignalSpy spy(uploader.get(), &Uploader::statusChanged);
1569+ uploader->close();
1570 ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME));
1571 auto arg = spy.takeFirst();
1572 EXPECT_EQ(Uploader::Status::Finished, qvariant_cast<Uploader::Status>(arg.at(0)));
1573@@ -3073,14 +2988,6 @@
1574 {
1575 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1576
1577- Item root;
1578- {
1579- unique_ptr<ItemJob> j(acc_.get("root_id"));
1580- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1581- spy.wait(SIGNAL_WAIT_TIME);
1582- root = j->item();
1583- }
1584-
1585 Item child;
1586 {
1587 unique_ptr<ItemJob> j(acc_.get("child_id"));
1588@@ -3098,20 +3005,15 @@
1589 auto arg = spy.takeFirst();
1590 EXPECT_EQ(Uploader::Status::Ready, qvariant_cast<Uploader::Status>(arg.at(0)));
1591 }
1592+
1593+ EXPECT_EQ(1, uploader->write("a", 1));
1594+ EXPECT_TRUE(uploader->waitForBytesWritten(SIGNAL_WAIT_TIME));
1595 }
1596
1597 TEST_F(UploadTest, runtime_destroyed)
1598 {
1599 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1600
1601- Item root;
1602- {
1603- unique_ptr<ItemJob> j(acc_.get("root_id"));
1604- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1605- spy.wait(SIGNAL_WAIT_TIME);
1606- root = j->item();
1607- }
1608-
1609 Item child;
1610 {
1611 unique_ptr<ItemJob> j(acc_.get("child_id"));
1612@@ -3143,14 +3045,6 @@
1613 {
1614 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("upload_slow")));
1615
1616- Item root;
1617- {
1618- unique_ptr<ItemJob> j(acc_.get("root_id"));
1619- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1620- spy.wait(SIGNAL_WAIT_TIME);
1621- root = j->item();
1622- }
1623-
1624 Item child;
1625 {
1626 unique_ptr<ItemJob> j(acc_.get("child_id"));
1627@@ -3184,14 +3078,6 @@
1628 {
1629 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("upload_error")));
1630
1631- Item root;
1632- {
1633- unique_ptr<ItemJob> j(acc_.get("root_id"));
1634- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1635- spy.wait(SIGNAL_WAIT_TIME);
1636- root = j->item();
1637- }
1638-
1639 Item child;
1640 {
1641 unique_ptr<ItemJob> j(acc_.get("child_id"));
1642@@ -3217,10 +3103,10 @@
1643 EXPECT_EQ("Conflict: version mismatch", uploader->error().errorString());
1644 EXPECT_EQ(Item(), uploader->item());
1645
1646- // For coverage: call finishUpload() while in the Error state.
1647+ // For coverage: call close() while in the Error state.
1648 {
1649 QSignalSpy spy(uploader.get(), &Uploader::statusChanged);
1650- uploader->finishUpload();
1651+ uploader->close();
1652 EXPECT_FALSE(spy.wait(1000));
1653 }
1654 }
1655@@ -3229,14 +3115,6 @@
1656 {
1657 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1658
1659- Item root;
1660- {
1661- unique_ptr<ItemJob> j(acc_.get("root_id"));
1662- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1663- spy.wait(SIGNAL_WAIT_TIME);
1664- root = j->item();
1665- }
1666-
1667 Item child;
1668 {
1669 unique_ptr<ItemJob> j(acc_.get("child_id"));
1670@@ -3250,7 +3128,7 @@
1671
1672 QSignalSpy spy(uploader.get(), &Uploader::statusChanged);
1673
1674- uploader->finishUpload();
1675+ uploader->close();
1676
1677 ASSERT_EQ(1, spy.count());
1678 auto arg = spy.takeFirst();
1679@@ -3259,7 +3137,7 @@
1680 EXPECT_FALSE(uploader->isValid());
1681 EXPECT_EQ(Uploader::Status::Error, uploader->status());
1682 EXPECT_EQ(StorageError::LogicError, uploader->error().type());
1683- EXPECT_EQ("LogicError: Uploader::finishUpload(): cannot finalize while Uploader is not in the Ready state",
1684+ EXPECT_EQ("LogicError: Uploader::close(): cannot finalize while Uploader is not in the Ready state",
1685 uploader->error().errorString());
1686 }
1687
1688@@ -3267,14 +3145,6 @@
1689 {
1690 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1691
1692- Item root;
1693- {
1694- unique_ptr<ItemJob> j(acc_.get("root_id"));
1695- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1696- spy.wait(SIGNAL_WAIT_TIME);
1697- root = j->item();
1698- }
1699-
1700 Item child;
1701 {
1702 unique_ptr<ItemJob> j(acc_.get("child_id"));
1703@@ -3297,7 +3167,7 @@
1704
1705 EXPECT_EQ(StorageError::Type::NoError, runtime_->shutdown().type()); // Destroy runtime
1706
1707- uploader->finishUpload();
1708+ uploader->close();
1709
1710 ASSERT_EQ(1, spy.count());
1711 auto arg = spy.takeFirst();
1712@@ -3306,21 +3176,13 @@
1713 EXPECT_FALSE(uploader->isValid());
1714 EXPECT_EQ(Uploader::Status::Error, uploader->status());
1715 EXPECT_EQ(StorageError::RuntimeDestroyed, uploader->error().type());
1716- EXPECT_EQ("Uploader::finishUpload(): Runtime was destroyed previously", uploader->error().message());
1717+ EXPECT_EQ("Uploader::close(): Runtime was destroyed previously", uploader->error().message());
1718 }
1719
1720 TEST_F(UploadTest, finish_runtime_destroyed_while_reply_outstanding)
1721 {
1722 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("finish_upload_slow")));
1723
1724- Item root;
1725- {
1726- unique_ptr<ItemJob> j(acc_.get("root_id"));
1727- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1728- spy.wait(SIGNAL_WAIT_TIME);
1729- root = j->item();
1730- }
1731-
1732 Item child;
1733 {
1734 unique_ptr<ItemJob> j(acc_.get("child_id"));
1735@@ -3341,7 +3203,7 @@
1736
1737 QSignalSpy spy(uploader.get(), &Uploader::statusChanged);
1738
1739- uploader->finishUpload();
1740+ uploader->close();
1741
1742 EXPECT_EQ(StorageError::Type::NoError, runtime_->shutdown().type()); // Destroy runtime, provider still sleeping
1743
1744@@ -3352,21 +3214,13 @@
1745 EXPECT_FALSE(uploader->isValid());
1746 EXPECT_EQ(Uploader::Status::Error, uploader->status());
1747 EXPECT_EQ(StorageError::RuntimeDestroyed, uploader->error().type());
1748- EXPECT_EQ("Uploader::finishUpload(): Runtime was destroyed previously", uploader->error().message());
1749+ EXPECT_EQ("Uploader::close(): Runtime was destroyed previously", uploader->error().message());
1750 }
1751
1752 TEST_F(UploadTest, finish_twice)
1753 {
1754 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1755
1756- Item root;
1757- {
1758- unique_ptr<ItemJob> j(acc_.get("root_id"));
1759- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1760- spy.wait(SIGNAL_WAIT_TIME);
1761- root = j->item();
1762- }
1763-
1764 Item child;
1765 {
1766 unique_ptr<ItemJob> j(acc_.get("child_id"));
1767@@ -3387,8 +3241,8 @@
1768
1769 QSignalSpy spy(uploader.get(), &Uploader::statusChanged);
1770
1771- uploader->finishUpload();
1772- uploader->finishUpload();
1773+ uploader->close();
1774+ uploader->close();
1775
1776 ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME));
1777 auto arg = spy.takeFirst();
1778@@ -3401,14 +3255,6 @@
1779 {
1780 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("finish_upload_error")));
1781
1782- Item root;
1783- {
1784- unique_ptr<ItemJob> j(acc_.get("root_id"));
1785- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1786- spy.wait(SIGNAL_WAIT_TIME);
1787- root = j->item();
1788- }
1789-
1790 Item child;
1791 {
1792 unique_ptr<ItemJob> j(acc_.get("child_id"));
1793@@ -3429,7 +3275,7 @@
1794
1795 QSignalSpy spy(uploader.get(), &Uploader::statusChanged);
1796
1797- uploader->finishUpload();
1798+ uploader->close();
1799
1800 ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME));
1801 auto arg = spy.takeFirst();
1802@@ -3472,14 +3318,6 @@
1803 {
1804 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1805
1806- Item root;
1807- {
1808- unique_ptr<ItemJob> j(acc_.get("root_id"));
1809- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1810- spy.wait(SIGNAL_WAIT_TIME);
1811- root = j->item();
1812- }
1813-
1814 Item child;
1815 {
1816 unique_ptr<ItemJob> j(acc_.get("child_id"));
1817@@ -3506,14 +3344,6 @@
1818 {
1819 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("upload_returns_dir")));
1820
1821- Item root;
1822- {
1823- unique_ptr<ItemJob> j(acc_.get("root_id"));
1824- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1825- spy.wait(SIGNAL_WAIT_TIME);
1826- root = j->item();
1827- }
1828-
1829 Item child;
1830 {
1831 unique_ptr<ItemJob> j(acc_.get("child_id"));
1832@@ -3533,7 +3363,7 @@
1833 }
1834
1835 QSignalSpy spy(uploader.get(), &Uploader::statusChanged);
1836- uploader->finishUpload();
1837+ uploader->close();
1838 ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME));
1839 auto arg = spy.takeFirst();
1840 EXPECT_EQ(Uploader::Status::Error, qvariant_cast<Uploader::Status>(arg.at(0)));
1841@@ -3547,14 +3377,6 @@
1842 {
1843 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1844
1845- Item root;
1846- {
1847- unique_ptr<ItemJob> j(acc_.get("root_id"));
1848- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1849- spy.wait(SIGNAL_WAIT_TIME);
1850- root = j->item();
1851- }
1852-
1853 Item child;
1854 {
1855 unique_ptr<ItemJob> j(acc_.get("child_id"));
1856@@ -3592,14 +3414,6 @@
1857 {
1858 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("finish_upload_slow_error")));
1859
1860- Item root;
1861- {
1862- unique_ptr<ItemJob> j(acc_.get("root_id"));
1863- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1864- spy.wait(SIGNAL_WAIT_TIME);
1865- root = j->item();
1866- }
1867-
1868 Item child;
1869 {
1870 unique_ptr<ItemJob> j(acc_.get("child_id"));
1871@@ -3620,12 +3434,12 @@
1872
1873 QSignalSpy spy(uploader.get(), &Uploader::statusChanged);
1874
1875- uploader->finishUpload();
1876+ uploader->close();
1877
1878 uploader->cancel();
1879 uploader->cancel(); // Second time for coverage
1880
1881- uploader->finishUpload(); // Second time for coverage
1882+ uploader->close(); // Second time for coverage
1883
1884 EXPECT_EQ(1, spy.count());
1885 auto arg = spy.takeFirst();
1886@@ -3635,7 +3449,7 @@
1887 EXPECT_EQ(StorageError::Type::Cancelled, uploader->error().type());
1888 EXPECT_EQ("Uploader::cancel(): upload was cancelled", uploader->error().message());
1889
1890- // We wait here to get coverage for when the reply to a finishUpload() call
1891+ // We wait here to get coverage for when the reply to a FinishUpload() call
1892 // finds the uploader in a final state.
1893 EXPECT_FALSE(spy.wait(2000));
1894 }
1895@@ -3644,14 +3458,6 @@
1896 {
1897 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("finish_upload_slow_error")));
1898
1899- Item root;
1900- {
1901- unique_ptr<ItemJob> j(acc_.get("root_id"));
1902- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1903- spy.wait(SIGNAL_WAIT_TIME);
1904- root = j->item();
1905- }
1906-
1907 Item child;
1908 {
1909 unique_ptr<ItemJob> j(acc_.get("child_id"));
1910@@ -3730,7 +3536,7 @@
1911 EXPECT_EQ(contents.size(), uploader->write(contents));
1912
1913 QSignalSpy spy(uploader.get(), &Uploader::statusChanged);
1914- uploader->finishUpload();
1915+ uploader->close();
1916 ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME));
1917 auto arg = spy.takeFirst();
1918 EXPECT_EQ(Uploader::Status::Finished, qvariant_cast<Uploader::Status>(arg.at(0)));
1919@@ -3751,14 +3557,6 @@
1920 root = j->item();
1921 }
1922
1923- Item child;
1924- {
1925- unique_ptr<ItemJob> j(acc_.get("child_id"));
1926- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1927- spy.wait(SIGNAL_WAIT_TIME);
1928- child = j->item();
1929- }
1930-
1931 EXPECT_EQ(StorageError::Type::NoError, runtime_->shutdown().type()); // Destroy runtime
1932
1933 QByteArray contents("Hello world", -1);
1934@@ -3783,14 +3581,6 @@
1935 {
1936 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1937
1938- Item root;
1939- {
1940- unique_ptr<ItemJob> j(acc_.get("root_id"));
1941- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1942- spy.wait(SIGNAL_WAIT_TIME);
1943- root = j->item();
1944- }
1945-
1946 Item child;
1947 {
1948 unique_ptr<ItemJob> j(acc_.get("child_id"));
1949@@ -3829,14 +3619,6 @@
1950 root = j->item();
1951 }
1952
1953- Item child;
1954- {
1955- unique_ptr<ItemJob> j(acc_.get("child_id"));
1956- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1957- spy.wait(SIGNAL_WAIT_TIME);
1958- child = j->item();
1959- }
1960-
1961 QByteArray contents("Hello world", -1);
1962 unique_ptr<Uploader> uploader(root.createFile("",
1963 Item::ConflictPolicy::IgnoreConflict,
1964@@ -3867,14 +3649,6 @@
1965 root = j->item();
1966 }
1967
1968- Item child;
1969- {
1970- unique_ptr<ItemJob> j(acc_.get("child_id"));
1971- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1972- spy.wait(SIGNAL_WAIT_TIME);
1973- child = j->item();
1974- }
1975-
1976 QByteArray contents("Hello world", -1);
1977 unique_ptr<Uploader> uploader(root.createFile("some_file",
1978 Item::ConflictPolicy::IgnoreConflict,
1979@@ -3905,14 +3679,6 @@
1980 root = j->item();
1981 }
1982
1983- Item child;
1984- {
1985- unique_ptr<ItemJob> j(acc_.get("child_id"));
1986- QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1987- spy.wait(SIGNAL_WAIT_TIME);
1988- child = j->item();
1989- }
1990-
1991 QByteArray contents("Hello world", -1);
1992 unique_ptr<Uploader> uploader(root.createFile("some_file",
1993 Item::ConflictPolicy::IgnoreConflict,
1994@@ -3930,7 +3696,7 @@
1995 EXPECT_EQ(contents.size(), uploader->write(contents));
1996
1997 QSignalSpy spy(uploader.get(), &Uploader::statusChanged);
1998- uploader->finishUpload();
1999+ uploader->close();
2000 ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME));
2001 auto arg = spy.takeFirst();
2002 EXPECT_EQ(Uploader::Status::Error, qvariant_cast<Uploader::Status>(arg.at(0)));
2003@@ -3968,7 +3734,7 @@
2004 EXPECT_EQ(contents.size(), uploader->write(contents));
2005
2006 QSignalSpy spy(uploader.get(), &Uploader::statusChanged);
2007- uploader->finishUpload();
2008+ uploader->close();
2009 ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME));
2010 auto arg = spy.takeFirst();
2011 EXPECT_EQ(Uploader::Status::Error, qvariant_cast<Uploader::Status>(arg.at(0)));

Subscribers

People subscribed via source and target branches

to all changes: