Merge lp:~michihenning/storage-framework/metadata-keys into lp:storage-framework/devel
- metadata-keys
- Merge into devel
Status: | Merged |
---|---|
Approved by: | James Henstridge |
Approved revision: | 92 |
Merged at revision: | 84 |
Proposed branch: | lp:~michihenning/storage-framework/metadata-keys |
Merge into: | lp:storage-framework/devel |
Prerequisite: | lp:~michihenning/storage-framework/specify-metadata |
Diff against target: |
1147 lines (+500/-115) 18 files modified
CMakeLists.txt (+1/-1) debian/changelog (+1/-0) demo/provider_test/provider-test.cpp (+5/-5) include/unity/storage/common.h (+19/-0) include/unity/storage/internal/metadata_keys.h (+22/-15) include/unity/storage/qt/Downloader.h (+1/-1) include/unity/storage/qt/Item.h (+1/-3) include/unity/storage/qt/MetadataKeys.h.THIS (+37/-0) include/unity/storage/qt/internal/ItemImpl.h (+1/-2) src/qt/Item.cpp (+5/-10) src/qt/client/internal/remote_client/FileImpl.cpp (+2/-2) src/qt/client/internal/remote_client/ItemImpl.cpp (+3/-3) src/qt/client/internal/remote_client/validate.cpp (+14/-9) src/qt/internal/ItemImpl.cpp (+14/-14) src/qt/internal/validate.cpp (+43/-31) tests/remote-client-v1/MockProvider.cpp (+5/-5) tests/remote-client/MockProvider.cpp (+123/-14) tests/remote-client/remote-client_test.cpp (+203/-0) |
To merge this branch: | bzr merge lp:~michihenning/storage-framework/metadata-keys |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
unity-api-1-bot | continuous-integration | Approve | |
James Henstridge | Approve | ||
Review via email: mp+309653@code.launchpad.net |
Commit message
Moved metadata key definitions into common.h and move metadata_keys.h to include/
Added commonly supported metadata keys.
Removed free and used space methods (they are metadata now).
No metadata validation for roots because Dropbox can't support that.
Description of the change
Moved metadata key definitions into common.h and move metadata_keys.h to include/
Added commonly supported metadata keys.
Removed free and used space methods (they are metadata now).
No metadata validation for roots because Dropbox can't support that.
unity-api-1-bot (unity-api-1-bot) wrote : | # |
- 88. By Michi Henning
-
Updated changelog. Bumped API version.
- 89. By Michi Henning
-
Server-side API version back to 1. Updated changelog accordingly.
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:87
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:89
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 90. By Michi Henning
-
Merged dependent branch.
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:90
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 91. By Michi Henning
-
Merged dependent branch.
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:91
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 92. By Michi Henning
-
Relaxed validation of etag so it applies only to files.
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:92
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2016-09-29 11:37:05 +0000 |
3 | +++ CMakeLists.txt 2016-11-02 06:07:10 +0000 |
4 | @@ -8,7 +8,7 @@ |
5 | project(storage-framework VERSION "0.2" LANGUAGES C CXX) |
6 | |
7 | # These variables should be incremented when we wish to create a new |
8 | -# source incompatible version of the the library where users of the |
9 | +# source incompatible version of the library where users of the |
10 | # old API will not compile against the new one. It is not |
11 | # necessary to increment this for ABI breaks that are source compatible. |
12 | set(SF_CLIENT_API_VERSION "2") |
13 | |
14 | === modified file 'debian/changelog' |
15 | --- debian/changelog 2016-09-21 04:41:06 +0000 |
16 | +++ debian/changelog 2016-11-02 06:07:10 +0000 |
17 | @@ -2,6 +2,7 @@ |
18 | |
19 | [ Michi Henning ] |
20 | * Added v2 of the client-side API. |
21 | + * Updated server-side API to tell the provider which metadata to return. |
22 | |
23 | -- Michi Henning <michi.henning@canonical.com> Wed, 21 Sep 2016 14:36:15 +1000 |
24 | |
25 | |
26 | === modified file 'demo/provider_test/provider-test.cpp' |
27 | --- demo/provider_test/provider-test.cpp 2016-11-02 06:07:10 +0000 |
28 | +++ demo/provider_test/provider-test.cpp 2016-11-02 06:07:10 +0000 |
29 | @@ -16,9 +16,9 @@ |
30 | * Authors: James Henstridge <james.henstridge@canonical.com> |
31 | */ |
32 | |
33 | +#include <unity/storage/common.h> |
34 | #include <unity/storage/provider/DownloadJob.h> |
35 | #include <unity/storage/provider/Exceptions.h> |
36 | -#include <unity/storage/provider/metadata_keys.h> |
37 | #include <unity/storage/provider/ProviderBase.h> |
38 | #include <unity/storage/provider/Server.h> |
39 | #include <unity/storage/provider/TempfileUploadJob.h> |
40 | @@ -128,7 +128,7 @@ |
41 | { |
42 | { |
43 | "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
44 | - { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
45 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
46 | } |
47 | }; |
48 | boost::promise<tuple<ItemList,string>> p; |
49 | @@ -154,7 +154,7 @@ |
50 | ItemList children = |
51 | { |
52 | { "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
53 | - { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } } |
54 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } } |
55 | }; |
56 | return make_ready_future<ItemList>(children); |
57 | } |
58 | @@ -175,7 +175,7 @@ |
59 | Item metadata |
60 | { |
61 | "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
62 | - { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
63 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
64 | }; |
65 | return make_ready_future<Item>(metadata); |
66 | } |
67 | @@ -289,7 +289,7 @@ |
68 | Item metadata |
69 | { |
70 | "some_id", { "root_id" }, "some_upload", "etag", ItemType::file, |
71 | - { { SIZE_IN_BYTES, 10 }, { LAST_MODIFIED_TIME, "2011-04-05T14:30:10.005Z" } } |
72 | + { { metadata::SIZE_IN_BYTES, 10 }, { metadata::LAST_MODIFIED_TIME, "2011-04-05T14:30:10.005Z" } } |
73 | }; |
74 | return make_ready_future(metadata); |
75 | } |
76 | |
77 | === modified file 'include/unity/storage/common.h' |
78 | --- include/unity/storage/common.h 2016-07-12 02:22:05 +0000 |
79 | +++ include/unity/storage/common.h 2016-11-02 06:07:10 +0000 |
80 | @@ -37,5 +37,24 @@ |
81 | overwrite, |
82 | }; |
83 | |
84 | +namespace metadata |
85 | +{ |
86 | + |
87 | +static char constexpr SIZE_IN_BYTES[] = "size_in_bytes"; // int64_t, >= 0 |
88 | +static char constexpr CREATION_TIME[] = "creation_time"; // String, ISO 8601 format |
89 | +static char constexpr LAST_MODIFIED_TIME[] = "last_modified_time"; // String, ISO 8601 format |
90 | +static char constexpr CHILD_COUNT[] = "child_count"; // int64_t, >= 0 |
91 | +static char constexpr DESCRIPTION[] = "description"; // String |
92 | +static char constexpr DISPLAY_NAME[] = "display_name"; // String |
93 | +static char constexpr FREE_SPACE_BYTES[] = "free_space_bytes"; // int64_t, >= 0 |
94 | +static char constexpr USED_SPACE_BYTES[] = "used_space_bytes"; // int64_t, >= 0 |
95 | +static char constexpr CONTENT_TYPE[] = "content_type"; // String |
96 | +static char constexpr WRITABLE[] = "writable"; // Bool |
97 | +static char constexpr MD5[] = "md5"; // String |
98 | +static char constexpr DOWNLOAD_URL[] = "download_url"; // String |
99 | + |
100 | +static char constexpr ALL[] = "__ALL__"; |
101 | + |
102 | +} // namespace metadata |
103 | } // namespace storage |
104 | } // namespace unity |
105 | |
106 | === renamed file 'include/unity/storage/provider/metadata_keys.h' => 'include/unity/storage/internal/metadata_keys.h' |
107 | --- include/unity/storage/provider/metadata_keys.h 2016-08-09 02:25:13 +0000 |
108 | +++ include/unity/storage/internal/metadata_keys.h 2016-11-02 06:07:10 +0000 |
109 | @@ -18,28 +18,35 @@ |
110 | |
111 | #pragma once |
112 | |
113 | +#include <unity/storage/common.h> |
114 | + |
115 | #include <unordered_map> |
116 | |
117 | namespace unity |
118 | { |
119 | namespace storage |
120 | { |
121 | -namespace provider |
122 | -{ |
123 | - |
124 | -static char constexpr SIZE_IN_BYTES[] = "size_in_bytes"; // int64_t, >= 0 |
125 | -static char constexpr CREATION_TIME[] = "creation_time"; // String, ISO 8601 format |
126 | -static char constexpr LAST_MODIFIED_TIME[] = "last_modified_time"; // String, ISO 8601 format |
127 | - |
128 | -enum class MetadataType { int64, iso_8601_date_time }; |
129 | - |
130 | -static std::unordered_map<std::string, MetadataType> known_metadata = |
131 | -{ |
132 | - { SIZE_IN_BYTES, MetadataType::int64 }, |
133 | - { CREATION_TIME, MetadataType::iso_8601_date_time }, |
134 | - { LAST_MODIFIED_TIME, MetadataType::iso_8601_date_time } |
135 | +namespace metadata |
136 | +{ |
137 | + |
138 | +enum class MetadataType { non_zero_pos_int64, iso_8601_date_time, string, boolean }; |
139 | + |
140 | +static std::unordered_map<std::string, MetadataType> const known_metadata = |
141 | +{ |
142 | + { metadata::SIZE_IN_BYTES, MetadataType::non_zero_pos_int64 }, |
143 | + { metadata::CREATION_TIME, MetadataType::iso_8601_date_time }, |
144 | + { metadata::LAST_MODIFIED_TIME, MetadataType::iso_8601_date_time }, |
145 | + { metadata::CHILD_COUNT, MetadataType::non_zero_pos_int64 }, |
146 | + { metadata::DESCRIPTION, MetadataType::string }, |
147 | + { metadata::DISPLAY_NAME, MetadataType::string }, |
148 | + { metadata::FREE_SPACE_BYTES, MetadataType::non_zero_pos_int64 }, |
149 | + { metadata::USED_SPACE_BYTES, MetadataType::non_zero_pos_int64 }, |
150 | + { metadata::CONTENT_TYPE, MetadataType::string }, |
151 | + { metadata::WRITABLE, MetadataType::boolean }, |
152 | + { metadata::MD5, MetadataType::string }, |
153 | + { metadata::DOWNLOAD_URL, MetadataType::string } |
154 | }; |
155 | |
156 | -} // namespace provider |
157 | +} // namespace metadata |
158 | } // namespace storage |
159 | } // namespace unity |
160 | |
161 | === modified file 'include/unity/storage/qt/Downloader.h' |
162 | --- include/unity/storage/qt/Downloader.h 2016-10-12 05:25:20 +0000 |
163 | +++ include/unity/storage/qt/Downloader.h 2016-11-02 06:07:10 +0000 |
164 | @@ -54,7 +54,7 @@ |
165 | bool isValid() const; // Not nice, hides QLocalSocket::isValid() |
166 | Status status() const; |
167 | StorageError error() const; // Not nice, hides QLocalSocket::error() |
168 | - Item item() const; // TODO: Should we keep this? |
169 | + Item item() const; |
170 | |
171 | Q_INVOKABLE void finishDownload(); |
172 | Q_INVOKABLE void cancel(); |
173 | |
174 | === modified file 'include/unity/storage/qt/Item.h' |
175 | --- include/unity/storage/qt/Item.h 2016-11-02 06:07:10 +0000 |
176 | +++ include/unity/storage/qt/Item.h 2016-11-02 06:07:10 +0000 |
177 | @@ -94,6 +94,7 @@ |
178 | QString etag() const; |
179 | Type type() const; |
180 | QVariantMap metadata() const; |
181 | + qint64 sizeInBytes() const; |
182 | QDateTime lastModifiedTime() const; |
183 | QStringList parentIds() const; |
184 | |
185 | @@ -120,9 +121,6 @@ |
186 | QString const& contentType, |
187 | QStringList const& keys = QStringList()) const; |
188 | |
189 | - Q_INVOKABLE IntJob* freeSpaceBytes() const; |
190 | - Q_INVOKABLE IntJob* usedSpaceBytes() const; |
191 | - |
192 | bool operator==(Item const&) const; |
193 | bool operator!=(Item const&) const; |
194 | bool operator<(Item const&) const; |
195 | |
196 | === added file 'include/unity/storage/qt/MetadataKeys.h.THIS' |
197 | --- include/unity/storage/qt/MetadataKeys.h.THIS 1970-01-01 00:00:00 +0000 |
198 | +++ include/unity/storage/qt/MetadataKeys.h.THIS 2016-11-02 06:07:10 +0000 |
199 | @@ -0,0 +1,37 @@ |
200 | +/* |
201 | + * Copyright (C) 2016 Canonical Ltd |
202 | + * |
203 | + * This program is free software: you can redistribute it and/or modify |
204 | + * it under the terms of the GNU Lesser General Public License version 3 as |
205 | + * published by the Free Software Foundation. |
206 | + * |
207 | + * This program is distributed in the hope that it will be useful, |
208 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
209 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
210 | + * GNU Lesser General Public License for more details. |
211 | + * |
212 | + * You should have received a copy of the GNU Lesser General Public License |
213 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
214 | + * |
215 | + * Authors: Michi Henning <michi.henning@canonical.com> |
216 | + */ |
217 | + |
218 | +#pragma once |
219 | + |
220 | +#include <unity/storage/common.h> |
221 | + |
222 | +#include <QList> |
223 | +#include <QString> |
224 | + |
225 | +namespace unity |
226 | +{ |
227 | +namespace storage |
228 | +{ |
229 | +namespace qt |
230 | +{ |
231 | + |
232 | +static QStringList const ALL_METADATA = { metadata::ALL }; |
233 | + |
234 | +} // namespace qt |
235 | +} // namespace storage |
236 | +} // namespace unity |
237 | |
238 | === modified file 'include/unity/storage/qt/internal/ItemImpl.h' |
239 | --- include/unity/storage/qt/internal/ItemImpl.h 2016-11-02 06:07:10 +0000 |
240 | +++ include/unity/storage/qt/internal/ItemImpl.h 2016-11-02 06:07:10 +0000 |
241 | @@ -55,6 +55,7 @@ |
242 | QString etag() const; |
243 | Item::Type type() const; |
244 | QVariantMap metadata() const; |
245 | + qint64 sizeInBytes() const; |
246 | QDateTime lastModifiedTime() const; |
247 | QList<QString> parentIds() const; |
248 | |
249 | @@ -73,8 +74,6 @@ |
250 | qint64 sizeInBytes, |
251 | QString const& contentType, |
252 | QStringList const& keys) const; |
253 | - IntJob* freeSpaceBytes() const; |
254 | - IntJob* usedSpaceBytes() const; |
255 | |
256 | bool operator==(ItemImpl const&) const; |
257 | bool operator!=(ItemImpl const&) const; |
258 | |
259 | === modified file 'src/qt/Item.cpp' |
260 | --- src/qt/Item.cpp 2016-11-02 06:07:10 +0000 |
261 | +++ src/qt/Item.cpp 2016-11-02 06:07:10 +0000 |
262 | @@ -107,6 +107,11 @@ |
263 | return p_->metadata(); |
264 | } |
265 | |
266 | +qint64 Item::sizeInBytes() const |
267 | +{ |
268 | + return p_->sizeInBytes(); |
269 | +} |
270 | + |
271 | QDateTime Item::lastModifiedTime() const |
272 | { |
273 | return p_->lastModifiedTime(); |
274 | @@ -171,16 +176,6 @@ |
275 | return p_->createFile(name, policy, sizeInBytes, contentType, keys); |
276 | } |
277 | |
278 | -IntJob* Item::freeSpaceBytes() const |
279 | -{ |
280 | - return p_->freeSpaceBytes(); |
281 | -} |
282 | - |
283 | -IntJob* Item::usedSpaceBytes() const |
284 | -{ |
285 | - return p_->usedSpaceBytes(); |
286 | -} |
287 | - |
288 | bool Item::operator==(Item const& other) const |
289 | { |
290 | return p_->operator==(*other.p_); |
291 | |
292 | === modified file 'src/qt/client/internal/remote_client/FileImpl.cpp' |
293 | --- src/qt/client/internal/remote_client/FileImpl.cpp 2016-11-02 06:07:10 +0000 |
294 | +++ src/qt/client/internal/remote_client/FileImpl.cpp 2016-11-02 06:07:10 +0000 |
295 | @@ -19,7 +19,7 @@ |
296 | #include <unity/storage/qt/client/internal/remote_client/FileImpl.h> |
297 | |
298 | #include "ProviderInterface.h" |
299 | -#include <unity/storage/provider/metadata_keys.h> |
300 | +#include <unity/storage/common.h> |
301 | #include <unity/storage/qt/client/File.h> |
302 | #include <unity/storage/qt/client/internal/remote_client/Handler.h> |
303 | #include <unity/storage/qt/client/internal/remote_client/DownloaderImpl.h> |
304 | @@ -51,7 +51,7 @@ |
305 | int64_t FileImpl::size() const |
306 | { |
307 | throw_if_destroyed("File::size()"); |
308 | - return md_.metadata.value(provider::SIZE_IN_BYTES).toLongLong(); |
309 | + return md_.metadata.value(metadata::SIZE_IN_BYTES).toLongLong(); |
310 | } |
311 | |
312 | QFuture<shared_ptr<Uploader>> FileImpl::create_uploader(ConflictPolicy policy, int64_t size) |
313 | |
314 | === modified file 'src/qt/client/internal/remote_client/ItemImpl.cpp' |
315 | --- src/qt/client/internal/remote_client/ItemImpl.cpp 2016-11-02 06:07:10 +0000 |
316 | +++ src/qt/client/internal/remote_client/ItemImpl.cpp 2016-11-02 06:07:10 +0000 |
317 | @@ -19,7 +19,7 @@ |
318 | #include <unity/storage/qt/client/internal/remote_client/ItemImpl.h> |
319 | |
320 | #include "ProviderInterface.h" |
321 | -#include <unity/storage/provider/metadata_keys.h> |
322 | +#include <unity/storage/common.h> |
323 | #include <unity/storage/qt/client/Account.h> |
324 | #include <unity/storage/qt/client/internal/remote_client/AccountImpl.h> |
325 | #include <unity/storage/qt/client/internal/remote_client/FileImpl.h> |
326 | @@ -72,7 +72,7 @@ |
327 | QDateTime ItemImpl::last_modified_time() const |
328 | { |
329 | throw_if_destroyed("Item::last_modified_time()"); |
330 | - return QDateTime::fromString(md_.metadata.value(provider::LAST_MODIFIED_TIME).toString(), Qt::ISODate); |
331 | + return QDateTime::fromString(md_.metadata.value(metadata::LAST_MODIFIED_TIME).toString(), Qt::ISODate); |
332 | } |
333 | |
334 | QFuture<shared_ptr<Item>> ItemImpl::copy(shared_ptr<Folder> const& new_parent, QString const& new_name) |
335 | @@ -254,7 +254,7 @@ |
336 | QDateTime ItemImpl::creation_time() const |
337 | { |
338 | throw_if_destroyed("Item::creation_time()"); |
339 | - return QDateTime::fromString(md_.metadata.value(provider::CREATION_TIME).toString(), Qt::ISODate); |
340 | + return QDateTime::fromString(md_.metadata.value(metadata::CREATION_TIME).toString(), Qt::ISODate); |
341 | } |
342 | |
343 | MetadataMap ItemImpl::native_metadata() const |
344 | |
345 | === modified file 'src/qt/client/internal/remote_client/validate.cpp' |
346 | --- src/qt/client/internal/remote_client/validate.cpp 2016-09-28 10:08:40 +0000 |
347 | +++ src/qt/client/internal/remote_client/validate.cpp 2016-11-02 06:07:10 +0000 |
348 | @@ -18,7 +18,7 @@ |
349 | |
350 | #include <unity/storage/internal/ItemMetadata.h> |
351 | |
352 | -#include <unity/storage/provider/metadata_keys.h> |
353 | +#include <unity/storage/internal/metadata_keys.h> |
354 | #include <unity/storage/qt/client/Exceptions.h> |
355 | |
356 | #include <QDateTime> |
357 | @@ -48,9 +48,9 @@ |
358 | |
359 | void validate_type_and_value(QString const& prefix, |
360 | QMapIterator<QString, QVariant> actual, |
361 | - unordered_map<string, provider::MetadataType>::const_iterator known) |
362 | + unordered_map<string, metadata::MetadataType>::const_iterator known) |
363 | { |
364 | - using namespace unity::storage::provider; |
365 | + using namespace unity::storage::metadata; |
366 | |
367 | switch (known->second) |
368 | { |
369 | @@ -75,7 +75,7 @@ |
370 | } |
371 | break; |
372 | } |
373 | - case MetadataType::int64: |
374 | + case MetadataType::non_zero_pos_int64: |
375 | { |
376 | if (actual.value().type() != QVariant::LongLong) |
377 | { |
378 | @@ -84,6 +84,11 @@ |
379 | } |
380 | break; |
381 | } |
382 | + case MetadataType::string: |
383 | + case MetadataType::boolean: |
384 | + { |
385 | + break; |
386 | + } |
387 | default: |
388 | { |
389 | abort(); // Impossible. // LCOV_EXCL_LINE |
390 | @@ -95,7 +100,7 @@ |
391 | |
392 | void validate(QString const& method, ItemMetadata const& md) |
393 | { |
394 | - using namespace unity::storage::provider; |
395 | + using namespace unity::storage::metadata; |
396 | |
397 | QString prefix = method + ": received invalid metadata from server: "; |
398 | |
399 | @@ -150,13 +155,13 @@ |
400 | // Sanity check metadata to make sure that mandatory fields are present. |
401 | if (md.type == ItemType::file) |
402 | { |
403 | - if (!md.metadata.contains(SIZE_IN_BYTES)) |
404 | + if (!md.metadata.contains(metadata::SIZE_IN_BYTES)) |
405 | { |
406 | - throw LocalCommsException(prefix + "missing key " + SIZE_IN_BYTES + " in metadata for " + md.item_id); |
407 | + throw LocalCommsException(prefix + "missing key " + metadata::SIZE_IN_BYTES + " in metadata for " + md.item_id); |
408 | } |
409 | - if (!md.metadata.contains(LAST_MODIFIED_TIME)) |
410 | + if (!md.metadata.contains(metadata::LAST_MODIFIED_TIME)) |
411 | { |
412 | - throw LocalCommsException(prefix + "missing key " + LAST_MODIFIED_TIME + " in metadata for " + md.item_id); |
413 | + throw LocalCommsException(prefix + "missing key " + metadata::LAST_MODIFIED_TIME + " in metadata for " + md.item_id); |
414 | } |
415 | } |
416 | } |
417 | |
418 | === modified file 'src/qt/internal/ItemImpl.cpp' |
419 | --- src/qt/internal/ItemImpl.cpp 2016-11-02 06:07:10 +0000 |
420 | +++ src/qt/internal/ItemImpl.cpp 2016-11-02 06:07:10 +0000 |
421 | @@ -19,7 +19,7 @@ |
422 | #include <unity/storage/qt/internal/ItemImpl.h> |
423 | |
424 | #include "ProviderInterface.h" |
425 | -#include <unity/storage/provider/metadata_keys.h> |
426 | +#include <unity/storage/common.h> |
427 | #include <unity/storage/qt/internal/DownloaderImpl.h> |
428 | #include <unity/storage/qt/internal/ItemJobImpl.h> |
429 | #include <unity/storage/qt/internal/ItemListJobImpl.h> |
430 | @@ -96,13 +96,23 @@ |
431 | |
432 | QVariantMap ItemImpl::metadata() const |
433 | { |
434 | - // TODO: Need to agree on metadata representation. |
435 | - return is_valid_ ? QVariantMap() : QVariantMap(); |
436 | + return is_valid_ ? md_.metadata : QVariantMap(); |
437 | +} |
438 | + |
439 | +qint64 ItemImpl::sizeInBytes() const |
440 | +{ |
441 | + if (!is_valid_ || md_.type != ItemType::file) |
442 | + { |
443 | + return 0; |
444 | + } |
445 | + auto variant = md_.metadata.value(metadata::SIZE_IN_BYTES); |
446 | + assert(variant.isValid()); |
447 | + return variant.toLongLong(); |
448 | } |
449 | |
450 | QDateTime ItemImpl::lastModifiedTime() const |
451 | { |
452 | - return is_valid_ ? QDateTime::fromString(md_.metadata.value(provider::LAST_MODIFIED_TIME).toString(), Qt::ISODate) |
453 | + return is_valid_ ? QDateTime::fromString(md_.metadata.value(metadata::LAST_MODIFIED_TIME).toString(), Qt::ISODate) |
454 | : QDateTime(); |
455 | } |
456 | |
457 | @@ -425,16 +435,6 @@ |
458 | return UploaderImpl::make_job(This, method, reply, validate, policy, sizeInBytes); |
459 | } |
460 | |
461 | -IntJob* ItemImpl::freeSpaceBytes() const |
462 | -{ |
463 | - return nullptr; // TODO |
464 | -} |
465 | - |
466 | -IntJob* ItemImpl::usedSpaceBytes() const |
467 | -{ |
468 | - return nullptr; // TODO |
469 | -} |
470 | - |
471 | bool ItemImpl::operator==(ItemImpl const& other) const |
472 | { |
473 | if (is_valid_) |
474 | |
475 | === modified file 'src/qt/internal/validate.cpp' |
476 | --- src/qt/internal/validate.cpp 2016-09-16 06:25:08 +0000 |
477 | +++ src/qt/internal/validate.cpp 2016-11-02 06:07:10 +0000 |
478 | @@ -19,7 +19,7 @@ |
479 | #include <unity/storage/qt/internal/validate.h> |
480 | |
481 | #include <unity/storage/internal/ItemMetadata.h> |
482 | -#include <unity/storage/provider/metadata_keys.h> |
483 | +#include <unity/storage/internal/metadata_keys.h> |
484 | #include <unity/storage/qt/internal/StorageErrorImpl.h> |
485 | |
486 | #include <QDateTime> |
487 | @@ -45,9 +45,9 @@ |
488 | |
489 | void validate_type_and_value(QString const& prefix, |
490 | QMapIterator<QString, QVariant> actual, |
491 | - unordered_map<string, provider::MetadataType>::const_iterator known) |
492 | + unordered_map<string, metadata::MetadataType>::const_iterator known) |
493 | { |
494 | - using namespace unity::storage::provider; |
495 | + using namespace unity::storage::metadata; |
496 | |
497 | switch (known->second) |
498 | { |
499 | @@ -55,7 +55,7 @@ |
500 | { |
501 | if (actual.value().type() != QVariant::String) |
502 | { |
503 | - QString msg = prefix + actual.key() + ": expected value of type String, but received value of type " |
504 | + QString msg = prefix + actual.key() + ": expected value of type QString, but received value of type " |
505 | + actual.value().typeName(); |
506 | throw StorageErrorImpl::local_comms_error(msg); |
507 | } |
508 | @@ -75,14 +75,26 @@ |
509 | } |
510 | break; |
511 | } |
512 | - case MetadataType::int64: |
513 | - { |
514 | - if (actual.value().type() != QVariant::LongLong) |
515 | - { |
516 | - QString msg = prefix + actual.key() + ": expected value of type LongLong, but received value of type " |
517 | - + actual.value().typeName(); |
518 | - throw StorageErrorImpl::local_comms_error(msg); |
519 | - } |
520 | + case MetadataType::non_zero_pos_int64: |
521 | + { |
522 | + auto variant = actual.value(); |
523 | + if (variant.type() != QVariant::LongLong) |
524 | + { |
525 | + QString msg = prefix + actual.key() + ": expected value of type qlonglong, but received value of type " |
526 | + + variant.typeName(); |
527 | + throw StorageErrorImpl::local_comms_error(msg); |
528 | + } |
529 | + qint64 val = variant.toLongLong(); |
530 | + if (val < 0) |
531 | + { |
532 | + QString msg = prefix + actual.key() + ": expected value >= 0, but received " + QString::number(val); |
533 | + throw StorageErrorImpl::local_comms_error(msg); |
534 | + } |
535 | + break; |
536 | + } |
537 | + case MetadataType::string: |
538 | + case MetadataType::boolean: |
539 | + { |
540 | break; |
541 | } |
542 | default: |
543 | @@ -96,7 +108,7 @@ |
544 | |
545 | void validate(QString const& method, ItemMetadata const& md) |
546 | { |
547 | - using namespace unity::storage::provider; |
548 | + using namespace unity::storage::metadata; |
549 | |
550 | QString prefix = method + ": received invalid metadata from provider: "; |
551 | |
552 | @@ -121,15 +133,18 @@ |
553 | } |
554 | if (md.type == ItemType::root && !md.parent_ids.isEmpty()) |
555 | { |
556 | - throw StorageErrorImpl::local_comms_error(prefix + "metadata: parent_ids of root must be empty"); |
557 | - } |
558 | - if (md.name.isEmpty()) |
559 | - { |
560 | - throw StorageErrorImpl::local_comms_error(prefix + "name cannot be empty"); |
561 | - } |
562 | - if (md.etag.isEmpty()) |
563 | - { |
564 | - throw StorageErrorImpl::local_comms_error(prefix + "etag cannot be empty"); |
565 | + throw StorageErrorImpl::local_comms_error(prefix + "parent_ids of root must be empty"); |
566 | + } |
567 | + if (md.type != ItemType::root) // Dropbox does not support metadata for roots. |
568 | + { |
569 | + if (md.name.isEmpty()) |
570 | + { |
571 | + throw StorageErrorImpl::local_comms_error(prefix + "name cannot be empty"); |
572 | + } |
573 | + } |
574 | + if (md.type == ItemType::file && md.etag.isEmpty()) // WebDav doesn't do etag for folders. |
575 | + { |
576 | + throw StorageErrorImpl::local_comms_error(prefix + "etag of a file cannot be empty"); |
577 | } |
578 | |
579 | // Sanity check metadata to make sure only known metadata keys appear. |
580 | @@ -140,7 +155,7 @@ |
581 | auto known = known_metadata.find(actual.key().toStdString()); |
582 | if (known == known_metadata.end()) |
583 | { |
584 | - qWarning() << prefix << "unknown metadata key:" << actual.key(); |
585 | + qWarning().noquote().nospace() << prefix << "unknown metadata key: \"" << actual.key() << "\""; |
586 | } |
587 | else |
588 | { |
589 | @@ -151,14 +166,11 @@ |
590 | // Sanity check metadata to make sure that mandatory fields are present. |
591 | if (md.type == ItemType::file) |
592 | { |
593 | - if (!md.metadata.contains(SIZE_IN_BYTES)) |
594 | - { |
595 | - QString msg = prefix + "missing key " + SIZE_IN_BYTES + " in metadata for " + md.item_id; |
596 | - throw StorageErrorImpl::local_comms_error(msg); |
597 | - } |
598 | - if (!md.metadata.contains(LAST_MODIFIED_TIME)) |
599 | - { |
600 | - QString msg = prefix + "missing key " + LAST_MODIFIED_TIME + " in metadata for " + md.item_id; |
601 | + if (!md.metadata.contains(metadata::SIZE_IN_BYTES) || |
602 | + !md.metadata.contains(metadata::LAST_MODIFIED_TIME)) |
603 | + { |
604 | + QString msg = prefix + "missing key \"" + metadata::SIZE_IN_BYTES + "\" " |
605 | + "in metadata for \"" + md.item_id + "\""; |
606 | throw StorageErrorImpl::local_comms_error(msg); |
607 | } |
608 | } |
609 | |
610 | === modified file 'tests/remote-client-v1/MockProvider.cpp' |
611 | --- tests/remote-client-v1/MockProvider.cpp 2016-11-02 06:07:10 +0000 |
612 | +++ tests/remote-client-v1/MockProvider.cpp 2016-11-02 06:07:10 +0000 |
613 | @@ -18,8 +18,8 @@ |
614 | |
615 | #include "MockProvider.h" |
616 | |
617 | +#include <unity/storage/internal/metadata_keys.h> |
618 | #include <unity/storage/provider/Exceptions.h> |
619 | -#include <unity/storage/provider/metadata_keys.h> |
620 | |
621 | #include <boost/thread.hpp> |
622 | #include <boost/thread/future.hpp> |
623 | @@ -71,7 +71,7 @@ |
624 | { |
625 | { |
626 | "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
627 | - { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
628 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
629 | } |
630 | }; |
631 | boost::promise<tuple<ItemList,string>> p; |
632 | @@ -95,7 +95,7 @@ |
633 | ItemList children = |
634 | { |
635 | { "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
636 | - { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } } |
637 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } } |
638 | }; |
639 | return make_ready_future<ItemList>(children); |
640 | } |
641 | @@ -112,7 +112,7 @@ |
642 | Item metadata |
643 | { |
644 | "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
645 | - { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
646 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
647 | }; |
648 | return make_ready_future<Item>(metadata); |
649 | } |
650 | @@ -209,7 +209,7 @@ |
651 | Item metadata |
652 | { |
653 | "some_id", { "root_id" }, "some_upload", "etag", ItemType::file, |
654 | - { { SIZE_IN_BYTES, 10 }, { LAST_MODIFIED_TIME, "2011-04-05T14:30:10.005Z" } } |
655 | + { { metadata::SIZE_IN_BYTES, 10 }, { metadata::LAST_MODIFIED_TIME, "2011-04-05T14:30:10.005Z" } } |
656 | }; |
657 | return make_ready_future(metadata); |
658 | } |
659 | |
660 | === modified file 'tests/remote-client/MockProvider.cpp' |
661 | --- tests/remote-client/MockProvider.cpp 2016-11-02 06:07:10 +0000 |
662 | +++ tests/remote-client/MockProvider.cpp 2016-11-02 06:07:10 +0000 |
663 | @@ -18,8 +18,8 @@ |
664 | |
665 | #include "MockProvider.h" |
666 | |
667 | +#include <unity/storage/internal/metadata_keys.h> |
668 | #include <unity/storage/provider/Exceptions.h> |
669 | -#include <unity/storage/provider/metadata_keys.h> |
670 | |
671 | #include <boost/thread.hpp> |
672 | #include <boost/thread/future.hpp> |
673 | @@ -96,7 +96,7 @@ |
674 | { |
675 | { |
676 | "child_id", { "root_id" }, "Child", "etag", ItemType::root, |
677 | - { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
678 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
679 | } |
680 | }; |
681 | boost::promise<tuple<ItemList,string>> p; |
682 | @@ -114,7 +114,7 @@ |
683 | { |
684 | { |
685 | "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
686 | - { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
687 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
688 | } |
689 | }; |
690 | } |
691 | @@ -125,7 +125,7 @@ |
692 | { |
693 | { |
694 | "child2_id", { "root_id" }, "Child2", "etag", ItemType::file, |
695 | - { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
696 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
697 | } |
698 | }; |
699 | } |
700 | @@ -147,7 +147,7 @@ |
701 | { |
702 | { |
703 | "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
704 | - { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
705 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
706 | } |
707 | }; |
708 | boost::promise<tuple<ItemList,string>> p; |
709 | @@ -171,7 +171,7 @@ |
710 | ItemList children = |
711 | { |
712 | { "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
713 | - { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } } |
714 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } } |
715 | }; |
716 | return make_ready_future<ItemList>(children); |
717 | } |
718 | @@ -216,24 +216,133 @@ |
719 | return make_ready_future<Item>(metadata); |
720 | } |
721 | } |
722 | + if (cmd_ == "root_with_parent") |
723 | + { |
724 | + Item metadata{"root_id", { "this shouldn't be here" }, "Root", "etag", ItemType::root, {}}; |
725 | + return make_ready_future<Item>(metadata); |
726 | + } |
727 | Item metadata{"root_id", {}, "Root", "etag", ItemType::root, {}}; |
728 | return make_ready_future<Item>(metadata); |
729 | } |
730 | if (item_id == "child_id") |
731 | { |
732 | + if (cmd_ == "no_parents") |
733 | + { |
734 | + Item metadata |
735 | + { |
736 | + "child_id", {}, "Child", "etag", ItemType::file, |
737 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
738 | + }; |
739 | + return make_ready_future<Item>(metadata); |
740 | + } |
741 | + if (cmd_ == "empty_name") |
742 | + { |
743 | + Item metadata |
744 | + { |
745 | + "child_id", { "root_id" }, "", "etag", ItemType::file, |
746 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
747 | + }; |
748 | + return make_ready_future<Item>(metadata); |
749 | + } |
750 | + if (cmd_ == "empty_etag") |
751 | + { |
752 | + Item metadata |
753 | + { |
754 | + "child_id", { "root_id" }, "Child", "", ItemType::file, |
755 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
756 | + }; |
757 | + return make_ready_future<Item>(metadata); |
758 | + } |
759 | + if (cmd_ == "unknown_key") |
760 | + { |
761 | + Item metadata |
762 | + { |
763 | + "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
764 | + { { metadata::SIZE_IN_BYTES, 0 }, |
765 | + { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" }, |
766 | + { metadata::DESCRIPTION, "child test file" }, // For coverage |
767 | + { metadata::WRITABLE, true }, // For coverage |
768 | + { "unknown_key", "" } |
769 | + } |
770 | + }; |
771 | + return make_ready_future<Item>(metadata); |
772 | + } |
773 | + if (cmd_ == "missing_key") |
774 | + { |
775 | + Item metadata |
776 | + { |
777 | + "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
778 | + { { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
779 | + }; |
780 | + return make_ready_future<Item>(metadata); |
781 | + } |
782 | + if (cmd_ == "wrong_type_for_time") |
783 | + { |
784 | + Item metadata |
785 | + { |
786 | + "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
787 | + { { metadata::SIZE_IN_BYTES, 10 }, { metadata::LAST_MODIFIED_TIME, true } } |
788 | + }; |
789 | + return make_ready_future<Item>(metadata); |
790 | + } |
791 | + if (cmd_ == "bad_parse_for_time") |
792 | + { |
793 | + Item metadata |
794 | + { |
795 | + "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
796 | + { { metadata::SIZE_IN_BYTES, 10 }, { metadata::LAST_MODIFIED_TIME, "xyz" } } |
797 | + }; |
798 | + return make_ready_future<Item>(metadata); |
799 | + } |
800 | + if (cmd_ == "missing_timezone") |
801 | + { |
802 | + Item metadata |
803 | + { |
804 | + "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
805 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30" } } |
806 | + }; |
807 | + return make_ready_future<Item>(metadata); |
808 | + } |
809 | + if (cmd_ == "wrong_type_for_size") |
810 | + { |
811 | + Item metadata |
812 | + { |
813 | + "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
814 | + { { metadata::SIZE_IN_BYTES, "10" }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
815 | + }; |
816 | + return make_ready_future<Item>(metadata); |
817 | + } |
818 | + if (cmd_ == "negative_size") |
819 | + { |
820 | + Item metadata |
821 | + { |
822 | + "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
823 | + { { metadata::SIZE_IN_BYTES, -1 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
824 | + }; |
825 | + return make_ready_future<Item>(metadata); |
826 | + } |
827 | + if (cmd_ == "empty_parent") |
828 | + { |
829 | + Item metadata |
830 | + { |
831 | + "child_id", { "" }, "Child", "etag", ItemType::file, |
832 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
833 | + }; |
834 | + return make_ready_future<Item>(metadata); |
835 | + } |
836 | if (cmd_ == "two_parents" || cmd_ == "two_parents_throw") |
837 | { |
838 | Item metadata |
839 | { |
840 | "child_id", { "root_id", "child_folder_id" }, "Child", "etag", ItemType::file, |
841 | - { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
842 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
843 | }; |
844 | return make_ready_future<Item>(metadata); |
845 | } |
846 | Item metadata |
847 | { |
848 | "child_id", { "root_id" }, "Child", "etag", ItemType::file, |
849 | - { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
850 | + { { metadata::SIZE_IN_BYTES, 10 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
851 | }; |
852 | return make_ready_future<Item>(metadata); |
853 | } |
854 | @@ -335,7 +444,7 @@ |
855 | Item metadata |
856 | { |
857 | "root_id", { new_parent_id }, new_name, "etag", ItemType::root, |
858 | - { { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
859 | + { { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
860 | }; |
861 | return make_ready_future(metadata); |
862 | } |
863 | @@ -344,14 +453,14 @@ |
864 | Item metadata |
865 | { |
866 | item_id, { new_parent_id }, new_name, "etag", ItemType::folder, |
867 | - { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
868 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
869 | }; |
870 | return make_ready_future(metadata); |
871 | } |
872 | Item metadata |
873 | { |
874 | item_id, { new_parent_id }, new_name, "etag", ItemType::file, |
875 | - { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
876 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
877 | }; |
878 | return make_ready_future(metadata); |
879 | } |
880 | @@ -365,14 +474,14 @@ |
881 | Item metadata |
882 | { |
883 | "new_item_id", { new_parent_id }, new_name, "etag", ItemType::folder, |
884 | - { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
885 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
886 | }; |
887 | return make_ready_future(metadata); |
888 | } |
889 | Item metadata |
890 | { |
891 | "new_item_id", { new_parent_id }, new_name, "etag", ItemType::file, |
892 | - { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
893 | + { { metadata::SIZE_IN_BYTES, 0 }, { metadata::LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
894 | }; |
895 | return make_ready_future(metadata); |
896 | } |
897 | @@ -416,7 +525,7 @@ |
898 | Item metadata |
899 | { |
900 | "child_id", { "root_id" }, "some_upload", "etag", ItemType::file, |
901 | - { { SIZE_IN_BYTES, 10 }, { LAST_MODIFIED_TIME, "2011-04-05T14:30:10.005Z" } } |
902 | + { { metadata::SIZE_IN_BYTES, 10 }, { metadata::LAST_MODIFIED_TIME, "2011-04-05T14:30:10.005Z" } } |
903 | }; |
904 | return make_ready_future(metadata); |
905 | } |
906 | |
907 | === modified file 'tests/remote-client/remote-client_test.cpp' |
908 | --- tests/remote-client/remote-client_test.cpp 2016-10-17 13:01:16 +0000 |
909 | +++ tests/remote-client/remote-client_test.cpp 2016-11-02 06:07:10 +0000 |
910 | @@ -66,6 +66,7 @@ |
911 | class ItemTest : public RemoteClientTest {}; |
912 | class ListTest : public RemoteClientTest {}; |
913 | class LookupTest : public RemoteClientTest {}; |
914 | +class MetadataTest : public RemoteClientTest {}; |
915 | class MoveTest : public RemoteClientTest {}; |
916 | class ParentsTest : public RemoteClientTest {}; |
917 | class RootsTest : public RemoteClientTest {}; |
918 | @@ -345,6 +346,8 @@ |
919 | EXPECT_EQ(AccountsJob::Status::Finished, j->status()); |
920 | EXPECT_EQ(StorageError::Type::NoError, j->error().type()); |
921 | |
922 | + EXPECT_TRUE(runtime_->connection().isConnected()); // Just for coverage. |
923 | + |
924 | auto accounts = j->accounts(); |
925 | |
926 | // We don't check the contents of accounts here because we are using the real online accounts manager |
927 | @@ -635,6 +638,203 @@ |
928 | EXPECT_EQ("no_such_id", j->error().itemId()); |
929 | } |
930 | |
931 | +TEST_F(MetadataTest, basic) |
932 | +{ |
933 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider())); |
934 | + |
935 | + { |
936 | + Item i; |
937 | + EXPECT_EQ(0, i.metadata().size()); |
938 | + } |
939 | + |
940 | + { |
941 | + unique_ptr<ItemJob> j(acc_.get("root_id")); |
942 | + |
943 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
944 | + spy.wait(SIGNAL_WAIT_TIME); |
945 | + |
946 | + EXPECT_EQ(0, j->item().sizeInBytes()); |
947 | + EXPECT_EQ(0, j->item().metadata().size()); |
948 | + } |
949 | + |
950 | + { |
951 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
952 | + |
953 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
954 | + spy.wait(SIGNAL_WAIT_TIME); |
955 | + |
956 | + EXPECT_EQ(10, j->item().sizeInBytes()); |
957 | + EXPECT_EQ(2, j->item().metadata().size()); |
958 | + } |
959 | +} |
960 | + |
961 | +TEST_F(MetadataTest, no_parents) |
962 | +{ |
963 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("no_parents"))); |
964 | + |
965 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
966 | + |
967 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
968 | + spy.wait(SIGNAL_WAIT_TIME); |
969 | + |
970 | + EXPECT_EQ(ItemJob::Status::Error, j->status()); |
971 | + EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: " |
972 | + "file or folder must have at least one parent ID", j->error().errorString()); |
973 | +} |
974 | + |
975 | +TEST_F(MetadataTest, empty_parent) |
976 | +{ |
977 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("empty_parent"))); |
978 | + |
979 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
980 | + |
981 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
982 | + spy.wait(SIGNAL_WAIT_TIME); |
983 | + |
984 | + EXPECT_EQ(ItemJob::Status::Error, j->status()); |
985 | + EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: " |
986 | + "parent_id of file or folder cannot be empty", j->error().errorString()); |
987 | +} |
988 | + |
989 | +TEST_F(MetadataTest, root_with_parent) |
990 | +{ |
991 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("root_with_parent"))); |
992 | + |
993 | + unique_ptr<ItemJob> j(acc_.get("root_id")); |
994 | + |
995 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
996 | + spy.wait(SIGNAL_WAIT_TIME); |
997 | + |
998 | + EXPECT_EQ(ItemJob::Status::Error, j->status()); |
999 | + EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: " |
1000 | + "parent_ids of root must be empty", j->error().errorString()); |
1001 | +} |
1002 | + |
1003 | +TEST_F(MetadataTest, empty_name) |
1004 | +{ |
1005 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("empty_name"))); |
1006 | + |
1007 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
1008 | + |
1009 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
1010 | + spy.wait(SIGNAL_WAIT_TIME); |
1011 | + |
1012 | + EXPECT_EQ(ItemJob::Status::Error, j->status()); |
1013 | + EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: " |
1014 | + "name cannot be empty", j->error().errorString()); |
1015 | +} |
1016 | + |
1017 | +TEST_F(MetadataTest, empty_etag) |
1018 | +{ |
1019 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("empty_etag"))); |
1020 | + |
1021 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
1022 | + |
1023 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
1024 | + spy.wait(SIGNAL_WAIT_TIME); |
1025 | + |
1026 | + EXPECT_EQ(ItemJob::Status::Error, j->status()); |
1027 | + EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: " |
1028 | + "etag of a file cannot be empty", j->error().errorString()); |
1029 | +} |
1030 | + |
1031 | +TEST_F(MetadataTest, unknown_key) |
1032 | +{ |
1033 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("unknown_key"))); |
1034 | + |
1035 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
1036 | + |
1037 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
1038 | + spy.wait(SIGNAL_WAIT_TIME); |
1039 | + |
1040 | + // We only emit a warning for unknown keys. |
1041 | + EXPECT_EQ(ItemJob::Status::Finished, j->status()); |
1042 | +} |
1043 | + |
1044 | +TEST_F(MetadataTest, missing_size) |
1045 | +{ |
1046 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("missing_key"))); |
1047 | + |
1048 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
1049 | + |
1050 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
1051 | + spy.wait(SIGNAL_WAIT_TIME); |
1052 | + |
1053 | + EXPECT_EQ(ItemJob::Status::Error, j->status()); |
1054 | + EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: " |
1055 | + "missing key \"size_in_bytes\" in metadata for \"child_id\"", j->error().errorString()); |
1056 | +} |
1057 | + |
1058 | +TEST_F(MetadataTest, wrong_type_for_time) |
1059 | +{ |
1060 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("wrong_type_for_time"))); |
1061 | + |
1062 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
1063 | + |
1064 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
1065 | + spy.wait(SIGNAL_WAIT_TIME); |
1066 | + |
1067 | + EXPECT_EQ(ItemJob::Status::Error, j->status()); |
1068 | + EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: last_modified_time: " |
1069 | + "expected value of type QString, but received value of type qlonglong", j->error().errorString()); |
1070 | +} |
1071 | + |
1072 | +TEST_F(MetadataTest, bad_parse_for_time) |
1073 | +{ |
1074 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("bad_parse_for_time"))); |
1075 | + |
1076 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
1077 | + |
1078 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
1079 | + spy.wait(SIGNAL_WAIT_TIME); |
1080 | + |
1081 | + EXPECT_EQ(ItemJob::Status::Error, j->status()); |
1082 | + EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: last_modified_time: " |
1083 | + "value \"xyz\" does not parse as ISO-8601 date", j->error().errorString()); |
1084 | +} |
1085 | + |
1086 | +TEST_F(MetadataTest, missing_timezone) |
1087 | +{ |
1088 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("missing_timezone"))); |
1089 | + |
1090 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
1091 | + |
1092 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
1093 | + spy.wait(SIGNAL_WAIT_TIME); |
1094 | + |
1095 | + EXPECT_EQ(ItemJob::Status::Error, j->status()); |
1096 | + EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: last_modified_time: " |
1097 | + "value \"2007-04-05T14:30\" lacks a time zone specification", j->error().errorString()); |
1098 | +} |
1099 | + |
1100 | +TEST_F(MetadataTest, wrong_type_for_size) |
1101 | +{ |
1102 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("wrong_type_for_size"))); |
1103 | + |
1104 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
1105 | + |
1106 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
1107 | + spy.wait(SIGNAL_WAIT_TIME); |
1108 | + |
1109 | + EXPECT_EQ(ItemJob::Status::Error, j->status()); |
1110 | + EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: size_in_bytes: " |
1111 | + "expected value of type qlonglong, but received value of type QString", j->error().errorString()); |
1112 | +} |
1113 | + |
1114 | +TEST_F(MetadataTest, negative_size) |
1115 | +{ |
1116 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("negative_size"))); |
1117 | + |
1118 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
1119 | + |
1120 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
1121 | + spy.wait(SIGNAL_WAIT_TIME); |
1122 | + |
1123 | + EXPECT_EQ(ItemJob::Status::Error, j->status()); |
1124 | + EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: size_in_bytes: " |
1125 | + "expected value >= 0, but received -1", j->error().errorString()); |
1126 | +} |
1127 | + |
1128 | TEST_F(DeleteTest, basic) |
1129 | { |
1130 | set_provider(unique_ptr<provider::ProviderBase>(new MockProvider)); |
1131 | @@ -817,6 +1017,8 @@ |
1132 | EXPECT_EQ("", i.name()); |
1133 | EXPECT_EQ("", i.etag()); |
1134 | EXPECT_EQ(Item::Type::File, i.type()); |
1135 | + EXPECT_EQ(0, i.metadata().size()); |
1136 | + EXPECT_EQ(0, i.sizeInBytes()); |
1137 | auto mtime = i.lastModifiedTime(); |
1138 | EXPECT_FALSE(mtime.isValid()); |
1139 | auto pids = i.parentIds(); |
1140 | @@ -834,6 +1036,7 @@ |
1141 | EXPECT_TRUE(i.isValid()); |
1142 | EXPECT_EQ("child_id", i.itemId()); |
1143 | EXPECT_EQ("Child", i.name()); |
1144 | + EXPECT_EQ(10, i.sizeInBytes()); |
1145 | EXPECT_TRUE(i.account().isValid()); |
1146 | EXPECT_EQ("etag", i.etag()); |
1147 | EXPECT_EQ(Item::Type::File, i.type()); |
PASSED: Continuous integration, rev:85 /jenkins. canonical. com/unity- api-1/job/ lp-storage- framework- ci/159/ /jenkins. canonical. com/unity- api-1/job/ build/919 /jenkins. canonical. com/unity- api-1/job/ build-0- fetch/926 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 729 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 729/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 729 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 729/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 729 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 729/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 729 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 729/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 729 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 729/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 729 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 729/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 729 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 729/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 729 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 729/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= yakkety/ 729 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= yakkety/ 729/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/unity- api-1/job/ lp-storage- framework- ci/159/ rebuild
https:/