Merge lp:~mandel/ubuntu-download-manager/atomic-steps into lp:ubuntu-download-manager
- atomic-steps
- Merge into trunk
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Approved by: | Manuel de la Peña | ||||||||
Approved revision: | 246 | ||||||||
Merged at revision: | 247 | ||||||||
Proposed branch: | lp:~mandel/ubuntu-download-manager/atomic-steps | ||||||||
Merge into: | lp:ubuntu-download-manager | ||||||||
Diff against target: |
1895 lines (+1198/-98) 32 files modified
debian/libubuntu-download-manager-common-dev.install (+1/-0) download-manager.pro (+7/-1) ubuntu-download-manager-common-tests/main.cpp (+25/-0) ubuntu-download-manager-common-tests/test_metadata.cpp (+169/-0) ubuntu-download-manager-common-tests/test_metadata.h (+55/-0) ubuntu-download-manager-common-tests/ubuntu-download-manager-common-tests.pro (+36/-0) ubuntu-download-manager-common/ubuntu-download-manager-common.pro (+2/-0) ubuntu-download-manager-common/ubuntu/download_manager/metadata.cpp (+80/-0) ubuntu-download-manager-common/ubuntu/download_manager/metadata.h (+56/-0) ubuntu-download-manager-priv/downloads/daemon.cpp (+5/-2) ubuntu-download-manager-priv/downloads/factory.cpp (+3/-8) ubuntu-download-manager-priv/downloads/file_download.cpp (+61/-59) ubuntu-download-manager-priv/downloads/file_download.h (+5/-4) ubuntu-download-manager-priv/downloads/group_download.cpp (+2/-1) ubuntu-download-manager-priv/system/file_manager.cpp (+5/-0) ubuntu-download-manager-priv/system/file_manager.h (+1/-0) ubuntu-download-manager-priv/system/filename_mutex.cpp (+133/-0) ubuntu-download-manager-priv/system/filename_mutex.h (+64/-0) ubuntu-download-manager-priv/ubuntu-download-manager-priv.pro (+4/-2) ubuntu-download-manager-test-lib/ubuntu-download-manager-test-lib.pro (+4/-2) ubuntu-download-manager-test-lib/ubuntu/download_manager/tests/base_testcase.cpp (+1/-1) ubuntu-download-manager-test-lib/ubuntu/download_manager/tests/server/file_manager.cpp (+1/-1) ubuntu-download-manager-test-lib/ubuntu/download_manager/tests/server/filename_mutex.cpp (+58/-0) ubuntu-download-manager-test-lib/ubuntu/download_manager/tests/server/filename_mutex.h (+43/-0) ubuntu-download-manager-tests/downloads/test_download.cpp (+197/-4) ubuntu-download-manager-tests/downloads/test_download.h (+9/-0) ubuntu-download-manager-tests/downloads/test_downloads_db.cpp (+5/-5) ubuntu-download-manager-tests/downloads/test_downloads_db.h (+2/-0) ubuntu-download-manager-tests/downloads/test_group_download.cpp (+7/-6) ubuntu-download-manager-tests/system/test_filename_mutex.cpp (+108/-0) ubuntu-download-manager-tests/system/test_filename_mutex.h (+45/-0) ubuntu-download-manager-tests/ubuntu-download-manager-tests.pro (+4/-2) |
||||||||
To merge this branch: | bzr merge lp:~mandel/ubuntu-download-manager/atomic-steps | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Approve | |
Diego Sarmentero (community) | Approve | ||
Review via email: mp+207012@code.launchpad.net |
Commit message
Ensure that we do no have race issues between the diff downloads. This is fixed in two ways:
1. Use a temp file.
2. USe a mutex to decide the final path of the download.
Description of the change
Ensure that we do no have race issues between the diff downloads. This is fixed in two ways:
1. Use a temp file.
2. USe a mutex to decide the final path of the download.
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:241
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:246
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 240. By Manuel de la Peña
-
Auth errs.
- 241. By Manuel de la Peña
-
Client auth errors.
- 242. By Manuel de la Peña
-
Group downloads.
- 243. By Manuel de la Peña
-
Use log
- 244. By Manuel de la Peña
-
better logging.
- 245. By Manuel de la Peña
-
Abstract classes.
- 246. By Manuel de la Peña
-
Fix merge issues.
- 247. By Manuel de la Peña
-
Small logging fix lost in the merge.
- 248. By Manuel de la Peña
-
Fixed merge issues.
- 249. By Manuel de la Peña
-
Merge fix logs.
- 250. By Manuel de la Peña
-
Better implementation for the unconfined apps.
Preview Diff
1 | === modified file 'debian/libubuntu-download-manager-common-dev.install' |
2 | --- debian/libubuntu-download-manager-common-dev.install 2014-02-11 15:35:52 +0000 |
3 | +++ debian/libubuntu-download-manager-common-dev.install 2014-02-22 10:42:10 +0000 |
4 | @@ -6,5 +6,6 @@ |
5 | usr/include/ubuntu/download_manager/http_error_struct.h |
6 | usr/include/ubuntu/download_manager/network_error_struct.h |
7 | usr/include/ubuntu/download_manager/process_error_struct.h |
8 | +usr/include/ubuntu/download_manager/metadata.h |
9 | usr/lib/*/pkgconfig/ubuntu-download-manager-common.pc |
10 | usr/lib/*/libubuntu-download-manager-common.so |
11 | |
12 | === modified file 'download-manager.pro' |
13 | --- download-manager.pro 2014-01-09 15:21:14 +0000 |
14 | +++ download-manager.pro 2014-02-22 10:42:10 +0000 |
15 | @@ -10,8 +10,10 @@ |
16 | ubuntu-download-manager-client \ |
17 | ubuntu-download-manager-test-lib \ |
18 | ubuntu-download-manager-tests \ |
19 | + ubuntu-download-manager-common-tests \ |
20 | ubuntu-download-manager-test-daemon \ |
21 | - ubuntu-download-manager-client-tests \ |
22 | + ubuntu-download-manager-client-tests |
23 | + |
24 | |
25 | ubuntu-download-manager-priv.depends = ubuntu-download-manager-common |
26 | |
27 | @@ -19,6 +21,10 @@ |
28 | |
29 | ubuntu-download-manager-client.depends = ubuntu-download-manager-common |
30 | |
31 | +ubuntu-download-manager-common-tests.depends += ubuntu-download-manager-test-daemon |
32 | +ubuntu-download-manager-common-tests.depends += ubuntu-download-manager-common |
33 | +ubuntu-download-manager-common-tests.depends += ubuntu-download-manager-test-lib |
34 | + |
35 | ubuntu-download-manager-tests.depends += ubuntu-download-manager-test-lib |
36 | ubuntu-download-manager-tests.depends += ubuntu-download-manager-priv |
37 | |
38 | |
39 | === added directory 'ubuntu-download-manager-common-tests' |
40 | === added file 'ubuntu-download-manager-common-tests/main.cpp' |
41 | --- ubuntu-download-manager-common-tests/main.cpp 1970-01-01 00:00:00 +0000 |
42 | +++ ubuntu-download-manager-common-tests/main.cpp 2014-02-22 10:42:10 +0000 |
43 | @@ -0,0 +1,25 @@ |
44 | +/* |
45 | + * Copyright 2014 Canonical Ltd. |
46 | + * |
47 | + * This library is free software; you can redistribute it and/or |
48 | + * modify it under the terms of version 3 of the GNU Lesser General Public |
49 | + * License as published by the Free Software Foundation. |
50 | + * |
51 | + * This program is distributed in the hope that it will be useful, |
52 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
53 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
54 | + * General Public License for more details. |
55 | + * |
56 | + * You should have received a copy of the GNU Lesser General Public |
57 | + * License along with this library; if not, write to the |
58 | + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
59 | + * Boston, MA 02110-1301, USA. |
60 | + */ |
61 | + |
62 | +#include <QCoreApplication> |
63 | +#include <ubuntu/download_manager/tests/test_runner.h> |
64 | + |
65 | +int main(int argc, char *argv[]) { |
66 | + QCoreApplication a(argc, argv); |
67 | + return RUN_ALL_QTESTS(argc, argv); |
68 | +} |
69 | |
70 | === added file 'ubuntu-download-manager-common-tests/test_metadata.cpp' |
71 | --- ubuntu-download-manager-common-tests/test_metadata.cpp 1970-01-01 00:00:00 +0000 |
72 | +++ ubuntu-download-manager-common-tests/test_metadata.cpp 2014-02-22 10:42:10 +0000 |
73 | @@ -0,0 +1,169 @@ |
74 | +/* |
75 | + * Copyright 2014 Canonical Ltd. |
76 | + * |
77 | + * This library is free software; you can redistribute it and/or |
78 | + * modify it under the terms of version 3 of the GNU Lesser General Public |
79 | + * License as published by the Free Software Foundation. |
80 | + * |
81 | + * This program is distributed in the hope that it will be useful, |
82 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
83 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
84 | + * General Public License for more details. |
85 | + * |
86 | + * You should have received a copy of the GNU Lesser General Public |
87 | + * License along with this library; if not, write to the |
88 | + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
89 | + * Boston, MA 02110-1301, USA. |
90 | + */ |
91 | + |
92 | +#include "test_metadata.h" |
93 | + |
94 | +using namespace Ubuntu::DownloadManager; |
95 | + |
96 | +TestMetadata::TestMetadata(QObject *parent) |
97 | + : BaseTestCase("TestMetadata", parent) { |
98 | +} |
99 | + |
100 | +void |
101 | +TestMetadata::testCommnad_data() { |
102 | + QTest::addColumn<QString>("command"); |
103 | + |
104 | + QTest::newRow("mkdir") << "mkdir test"; |
105 | + QTest::newRow("cd") << "cd test"; |
106 | + QTest::newRow("ls") << "ls -la"; |
107 | +} |
108 | + |
109 | +void |
110 | +TestMetadata::testCommnad() { |
111 | + QFETCH(QString, command); |
112 | + |
113 | + Metadata metadata; |
114 | + metadata[Metadata::COMMAND_KEY] = command; |
115 | + QCOMPARE(command, metadata.command()); |
116 | +} |
117 | + |
118 | +void |
119 | +TestMetadata::testSetCommnad_data() { |
120 | + QTest::addColumn<QString>("command"); |
121 | + |
122 | + QTest::newRow("mkdir") << "mkdir test"; |
123 | + QTest::newRow("cd") << "cd test"; |
124 | + QTest::newRow("ls") << "ls -la"; |
125 | +} |
126 | + |
127 | +void |
128 | +TestMetadata::testSetCommnad() { |
129 | + QFETCH(QString, command); |
130 | + |
131 | + Metadata metadata; |
132 | + metadata.setCommand(command); |
133 | + QCOMPARE(metadata[Metadata::COMMAND_KEY].toString(), command); |
134 | +} |
135 | + |
136 | +void |
137 | +TestMetadata::testHasCommnadTrue() { |
138 | + Metadata metadata; |
139 | + metadata.setCommand("command"); |
140 | + |
141 | + QVERIFY(metadata.hasCommand()); |
142 | +} |
143 | + |
144 | +void |
145 | +TestMetadata::testHasCommnadFalse() { |
146 | + Metadata metadata; |
147 | + QVERIFY(!metadata.hasCommand()); |
148 | +} |
149 | + |
150 | +void |
151 | +TestMetadata::testLocalPath_data() { |
152 | + QTest::addColumn<QString>("path"); |
153 | + |
154 | + QTest::newRow("/home/test") << "/home/test"; |
155 | + QTest::newRow("second_file") << "second_file"; |
156 | + QTest::newRow("/tmp/data") << "/tmp/data"; |
157 | +} |
158 | + |
159 | +void |
160 | +TestMetadata::testLocalPath() { |
161 | + QFETCH(QString, path); |
162 | + |
163 | + Metadata metadata; |
164 | + metadata[Metadata::LOCAL_PATH_KEY] = path; |
165 | + QCOMPARE(path, metadata.localPath()); |
166 | +} |
167 | + |
168 | +void |
169 | +TestMetadata::testSetLocalPath_data() { |
170 | + QTest::addColumn<QString>("path"); |
171 | + |
172 | + QTest::newRow("/home/test") << "/home/test"; |
173 | + QTest::newRow("second_file") << "second_file"; |
174 | + QTest::newRow("/tmp/data") << "/tmp/data"; |
175 | +} |
176 | + |
177 | +void |
178 | +TestMetadata::testSetLocalPath() { |
179 | + QFETCH(QString, path); |
180 | + |
181 | + Metadata metadata; |
182 | + metadata.setLocalPath(path); |
183 | + QCOMPARE(metadata[Metadata::LOCAL_PATH_KEY].toString(), path); |
184 | +} |
185 | + |
186 | +void |
187 | +TestMetadata::testHasLocalPathTrue() { |
188 | + Metadata metadata; |
189 | + metadata.setLocalPath("command"); |
190 | + |
191 | + QVERIFY(metadata.hasLocalPath()); |
192 | +} |
193 | + |
194 | +void |
195 | +TestMetadata::testHashLocalPathFalse() { |
196 | + Metadata metadata; |
197 | + QVERIFY(!metadata.hasLocalPath()); |
198 | +} |
199 | + |
200 | +void TestMetadata::testObjectPath_data() { |
201 | + QTest::addColumn<QString>("objectPath"); |
202 | + |
203 | + QTest::newRow("/com/canonica/si") << "/com/canonical/si"; |
204 | + QTest::newRow("/com/testing") << "/com/testing"; |
205 | + QTest::newRow("/com/data/download") << "/com/data/download"; |
206 | +} |
207 | + |
208 | +void TestMetadata::testObjectPath() { |
209 | + QFETCH(QString, objectPath); |
210 | + |
211 | + Metadata metadata; |
212 | + metadata[Metadata::OBJECT_PATH_KEY] = objectPath; |
213 | + QCOMPARE(objectPath, metadata.objectPath()); |
214 | +} |
215 | + |
216 | +void TestMetadata::testSetObjectPath_data() { |
217 | + QTest::addColumn<QString>("objectPath"); |
218 | + |
219 | + QTest::newRow("/com/canonica/si") << "/com/canonical/si"; |
220 | + QTest::newRow("/com/testing") << "/com/testing"; |
221 | + QTest::newRow("/com/data/download") << "/com/data/download"; |
222 | +} |
223 | + |
224 | +void TestMetadata::testSetObjectPath() { |
225 | + QFETCH(QString, objectPath); |
226 | + |
227 | + Metadata metadata; |
228 | + metadata.setObjectPath(objectPath); |
229 | + QCOMPARE(metadata[Metadata::OBJECT_PATH_KEY].toString(), objectPath); |
230 | +} |
231 | + |
232 | +void TestMetadata::testHasObjectPathTrue() { |
233 | + Metadata metadata; |
234 | + metadata.setObjectPath("command"); |
235 | + |
236 | + QVERIFY(metadata.hasObjectPath()); |
237 | +} |
238 | + |
239 | +void TestMetadata::testHasObjectPathFalse() { |
240 | + Metadata metadata; |
241 | + QVERIFY(!metadata.hasObjectPath()); |
242 | +} |
243 | |
244 | === added file 'ubuntu-download-manager-common-tests/test_metadata.h' |
245 | --- ubuntu-download-manager-common-tests/test_metadata.h 1970-01-01 00:00:00 +0000 |
246 | +++ ubuntu-download-manager-common-tests/test_metadata.h 2014-02-22 10:42:10 +0000 |
247 | @@ -0,0 +1,55 @@ |
248 | +/* |
249 | + * Copyright 2014 Canonical Ltd. |
250 | + * |
251 | + * This library is free software; you can redistribute it and/or |
252 | + * modify it under the terms of version 3 of the GNU Lesser General Public |
253 | + * License as published by the Free Software Foundation. |
254 | + * |
255 | + * This program is distributed in the hope that it will be useful, |
256 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
257 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
258 | + * General Public License for more details. |
259 | + * |
260 | + * You should have received a copy of the GNU Lesser General Public |
261 | + * License along with this library; if not, write to the |
262 | + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
263 | + * Boston, MA 02110-1301, USA. |
264 | + */ |
265 | + |
266 | +#ifndef TEST_METADATA_H |
267 | +#define TEST_METADATA_H |
268 | + |
269 | +#include <QObject> |
270 | +#include <ubuntu/download_manager/tests/base_testcase.h> |
271 | +#include <ubuntu/download_manager/tests/test_runner.h> |
272 | +#include <ubuntu/download_manager/metadata.h> |
273 | + |
274 | +class TestMetadata : public BaseTestCase { |
275 | + Q_OBJECT |
276 | + |
277 | + public: |
278 | + explicit TestMetadata(QObject* parent = 0); |
279 | + |
280 | + private slots: // NOLINT(whitespace/indent) |
281 | + void testCommnad_data(); |
282 | + void testCommnad(); |
283 | + void testSetCommnad_data(); |
284 | + void testSetCommnad(); |
285 | + void testHasCommnadTrue(); |
286 | + void testHasCommnadFalse(); |
287 | + void testLocalPath_data(); |
288 | + void testLocalPath(); |
289 | + void testSetLocalPath_data(); |
290 | + void testSetLocalPath(); |
291 | + void testHasLocalPathTrue(); |
292 | + void testHashLocalPathFalse(); |
293 | + void testObjectPath_data(); |
294 | + void testObjectPath(); |
295 | + void testSetObjectPath_data(); |
296 | + void testSetObjectPath(); |
297 | + void testHasObjectPathTrue(); |
298 | + void testHasObjectPathFalse(); |
299 | +}; |
300 | + |
301 | +DECLARE_TEST(TestMetadata) |
302 | +#endif // TEST_METADATA_H |
303 | |
304 | === added file 'ubuntu-download-manager-common-tests/ubuntu-download-manager-common-tests.pro' |
305 | --- ubuntu-download-manager-common-tests/ubuntu-download-manager-common-tests.pro 1970-01-01 00:00:00 +0000 |
306 | +++ ubuntu-download-manager-common-tests/ubuntu-download-manager-common-tests.pro 2014-02-22 10:42:10 +0000 |
307 | @@ -0,0 +1,36 @@ |
308 | +include( ../common-project-config.pri ) |
309 | +include( ../common-vars.pri ) |
310 | + |
311 | +QT += core testlib network |
312 | +QT -= gui |
313 | + |
314 | +TARGET = ubuntu-download-manager-common-tests |
315 | +CONFIG += console |
316 | +CONFIG -= app_bundle |
317 | + |
318 | +TEMPLATE = app |
319 | + |
320 | +HEADERS += \ |
321 | + test_metadata.h |
322 | + |
323 | +SOURCES += main.cpp \ |
324 | + test_metadata.cpp |
325 | + |
326 | +LIBS += -L$$OUT_PWD/../ubuntu-download-manager-common/ -lubuntu-download-manager-common |
327 | + |
328 | +INCLUDEPATH += $$PWD/../ubuntu-download-manager-common |
329 | +DEPENDPATH += $$PWD/../ubuntu-download-manager-common |
330 | + |
331 | +LIBS += -L$$OUT_PWD/../ubuntu-download-manager-test-lib/ -lubuntu-download-manager-test-lib |
332 | + |
333 | +INCLUDEPATH += $$PWD/../ubuntu-download-manager-test-lib |
334 | +DEPENDPATH += $$PWD/../ubuntu-download-manager-test-lib |
335 | + |
336 | +LIBS += -L$$OUT_PWD/../ubuntu-download-manager-priv/ -lubuntu-download-manager-priv |
337 | + |
338 | +INCLUDEPATH += $$PWD/../ubuntu-download-manager-priv |
339 | +DEPENDPATH += $$PWD/../ubuntu-download-manager-priv |
340 | + |
341 | +check.depends = $${TARGET} |
342 | +check.commands = LD_LIBRARY_PATH=$$OUT_PWD/../ubuntu-download-manager-common:$$OUT_PWD/../ubuntu-download-manager-test-lib:$$OUT_PWD/../ubuntu-download-manager-priv ./$${TARGET} |
343 | +QMAKE_EXTRA_TARGETS += check |
344 | |
345 | === modified file 'ubuntu-download-manager-common/ubuntu-download-manager-common.pro' |
346 | --- ubuntu-download-manager-common/ubuntu-download-manager-common.pro 2014-02-11 15:35:52 +0000 |
347 | +++ ubuntu-download-manager-common/ubuntu-download-manager-common.pro 2014-02-22 10:42:10 +0000 |
348 | @@ -17,6 +17,7 @@ |
349 | ubuntu/download_manager/http_error_struct.cpp \ |
350 | ubuntu/download_manager/network_error_struct.cpp \ |
351 | ubuntu/download_manager/process_error_struct.cpp \ |
352 | + ubuntu/download_manager/metadata.cpp \ |
353 | ubuntu/download_manager/auth_error_struct.cpp |
354 | |
355 | public_headers = \ |
356 | @@ -27,6 +28,7 @@ |
357 | ubuntu/download_manager/http_error_struct.h \ |
358 | ubuntu/download_manager/network_error_struct.h \ |
359 | ubuntu/download_manager/process_error_struct.h \ |
360 | + ubuntu/download_manager/metadata.h \ |
361 | ubuntu/download_manager/auth_error_struct.h |
362 | |
363 | private_headers = \ |
364 | |
365 | === added file 'ubuntu-download-manager-common/ubuntu/download_manager/metadata.cpp' |
366 | --- ubuntu-download-manager-common/ubuntu/download_manager/metadata.cpp 1970-01-01 00:00:00 +0000 |
367 | +++ ubuntu-download-manager-common/ubuntu/download_manager/metadata.cpp 2014-02-22 10:42:10 +0000 |
368 | @@ -0,0 +1,80 @@ |
369 | +/* |
370 | + * Copyright 2014 Canonical Ltd. |
371 | + * |
372 | + * This library is free software; you can redistribute it and/or |
373 | + * modify it under the terms of version 3 of the GNU Lesser General Public |
374 | + * License as published by the Free Software Foundation. |
375 | + * |
376 | + * This program is distributed in the hope that it will be useful, |
377 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
378 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
379 | + * General Public License for more details. |
380 | + * |
381 | + * You should have received a copy of the GNU Lesser General Public |
382 | + * License along with this library; if not, write to the |
383 | + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
384 | + * Boston, MA 02110-1301, USA. |
385 | + */ |
386 | + |
387 | +#include "metadata.h" |
388 | + |
389 | +namespace Ubuntu { |
390 | + |
391 | +namespace DownloadManager { |
392 | + |
393 | +const QString Metadata::COMMAND_KEY = "post-download-command"; |
394 | +const QString Metadata::COMMAND_FILE_KEY = "$file"; |
395 | +const QString Metadata::LOCAL_PATH_KEY = "local-path"; |
396 | +const QString Metadata::OBJECT_PATH_KEY = "objectpath"; |
397 | + |
398 | +QString |
399 | +Metadata::command() const { |
400 | + return (contains(Metadata::COMMAND_KEY))? |
401 | + value(COMMAND_KEY).toString():""; |
402 | +} |
403 | + |
404 | +void |
405 | +Metadata::setCommand(const QString& command) { |
406 | + insert(Metadata::COMMAND_KEY, command); |
407 | +} |
408 | + |
409 | +bool |
410 | +Metadata::hasCommand() const { |
411 | + return contains(Metadata::COMMAND_KEY); |
412 | +} |
413 | + |
414 | +QString |
415 | +Metadata::localPath() const { |
416 | + return (contains(Metadata::LOCAL_PATH_KEY))? |
417 | + value(LOCAL_PATH_KEY).toString():""; |
418 | +} |
419 | + |
420 | +void |
421 | +Metadata::setLocalPath(const QString& localPath) { |
422 | + insert(Metadata::LOCAL_PATH_KEY, localPath); |
423 | +} |
424 | + |
425 | +bool |
426 | +Metadata::hasLocalPath() const { |
427 | + return contains(Metadata::LOCAL_PATH_KEY); |
428 | +} |
429 | + |
430 | +QString |
431 | +Metadata::objectPath() const { |
432 | + return (contains(Metadata::OBJECT_PATH_KEY))? |
433 | + value(OBJECT_PATH_KEY).toString():""; |
434 | +} |
435 | + |
436 | +void |
437 | +Metadata::setObjectPath(const QString& path) { |
438 | + insert(Metadata::OBJECT_PATH_KEY, path); |
439 | +} |
440 | + |
441 | +bool |
442 | +Metadata::hasObjectPath() const { |
443 | + return contains(Metadata::OBJECT_PATH_KEY); |
444 | +} |
445 | + |
446 | +} // DownloadManager |
447 | + |
448 | +} // Ubuntu |
449 | |
450 | === added file 'ubuntu-download-manager-common/ubuntu/download_manager/metadata.h' |
451 | --- ubuntu-download-manager-common/ubuntu/download_manager/metadata.h 1970-01-01 00:00:00 +0000 |
452 | +++ ubuntu-download-manager-common/ubuntu/download_manager/metadata.h 2014-02-22 10:42:10 +0000 |
453 | @@ -0,0 +1,56 @@ |
454 | +/* |
455 | + * Copyright 2014 Canonical Ltd. |
456 | + * |
457 | + * This library is free software; you can redistribute it and/or |
458 | + * modify it under the terms of version 3 of the GNU Lesser General Public |
459 | + * License as published by the Free Software Foundation. |
460 | + * |
461 | + * This program is distributed in the hope that it will be useful, |
462 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
463 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
464 | + * General Public License for more details. |
465 | + * |
466 | + * You should have received a copy of the GNU Lesser General Public |
467 | + * License along with this library; if not, write to the |
468 | + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
469 | + * Boston, MA 02110-1301, USA. |
470 | + */ |
471 | + |
472 | +#ifndef DOWNLOADER_LIB_METADATA_H |
473 | +#define DOWNLOADER_LIB_METADATA_H |
474 | + |
475 | +#include <QMap> |
476 | +#include <QVariant> |
477 | + |
478 | +namespace Ubuntu { |
479 | + |
480 | +namespace DownloadManager { |
481 | + |
482 | +class Metadata : public QVariantMap { |
483 | + |
484 | + public: |
485 | + |
486 | + static const QString COMMAND_KEY; |
487 | + static const QString COMMAND_FILE_KEY; |
488 | + static const QString LOCAL_PATH_KEY; |
489 | + static const QString OBJECT_PATH_KEY; |
490 | + |
491 | + // accessors to simplify the use of the metadata |
492 | + QString command() const; |
493 | + void setCommand(const QString& command); |
494 | + bool hasCommand() const; |
495 | + |
496 | + QString localPath() const; |
497 | + void setLocalPath(const QString& localPath); |
498 | + bool hasLocalPath() const; |
499 | + |
500 | + QString objectPath() const; |
501 | + void setObjectPath(const QString& path); |
502 | + bool hasObjectPath() const; |
503 | +}; |
504 | + |
505 | +} // DownloadManager |
506 | + |
507 | +} // Ubuntu |
508 | + |
509 | +#endif // METADATA_H |
510 | |
511 | === modified file 'ubuntu-download-manager-priv/downloads/daemon.cpp' |
512 | --- ubuntu-download-manager-priv/downloads/daemon.cpp 2014-02-13 11:01:48 +0000 |
513 | +++ ubuntu-download-manager-priv/downloads/daemon.cpp 2014-02-22 10:42:10 +0000 |
514 | @@ -170,11 +170,14 @@ |
515 | if (args.count() > index + 1) { |
516 | auto logPath = args[index + 1]; |
517 | Logger::setupLogging(logPath); |
518 | - LOG(INFO) << "Log path is" << logPath; |
519 | + LOG(INFO) << "Log path is" << logPath; |
520 | } else { |
521 | + Logger::setupLogging(); |
522 | LOG(ERROR) << "Missing log dir path."; |
523 | - Logger::setupLogging(); |
524 | } |
525 | + } else { |
526 | + Logger::setupLogging(); |
527 | + LOG(INFO) << "Using default log path."; |
528 | } |
529 | |
530 | if (args.contains(SELFSIGNED_CERT)) { |
531 | |
532 | === modified file 'ubuntu-download-manager-priv/downloads/factory.cpp' |
533 | --- ubuntu-download-manager-priv/downloads/factory.cpp 2014-02-01 08:46:28 +0000 |
534 | +++ ubuntu-download-manager-priv/downloads/factory.cpp 2014-02-22 10:42:10 +0000 |
535 | @@ -18,6 +18,7 @@ |
536 | |
537 | #include <QNetworkProxy> |
538 | #include <QPair> |
539 | +#include <ubuntu/download_manager/metadata.h> |
540 | #include "downloads/download_adaptor.h" |
541 | #include "downloads/group_download.h" |
542 | #include "downloads/group_download_adaptor.h" |
543 | @@ -26,12 +27,6 @@ |
544 | #include "downloads/factory.h" |
545 | #include "system/logger.h" |
546 | |
547 | -namespace { |
548 | - |
549 | - const QString OBJECT_PATH_KEY = "objectpath"; |
550 | - |
551 | -} |
552 | - |
553 | namespace Ubuntu { |
554 | |
555 | namespace DownloadManager { |
556 | @@ -61,9 +56,9 @@ |
557 | QString& rootPath, |
558 | bool& isConfined) { |
559 | TRACE << dbusOwner; |
560 | - if (metadata.contains(OBJECT_PATH_KEY)) { |
561 | + if (metadata.contains(Metadata::OBJECT_PATH_KEY)) { |
562 | // create a uuid using the string value form the metadata |
563 | - id = metadata[OBJECT_PATH_KEY].toString(); |
564 | + id = metadata[Metadata::OBJECT_PATH_KEY].toString(); |
565 | if (id.isEmpty()) { |
566 | LOG(ERROR) << "Id sent by client is ''"; |
567 | id = _apparmor->getSecurePath(dbusOwner, dbusPath, rootPath, |
568 | |
569 | === modified file 'ubuntu-download-manager-priv/downloads/file_download.cpp' |
570 | --- ubuntu-download-manager-priv/downloads/file_download.cpp 2014-02-20 13:12:04 +0000 |
571 | +++ ubuntu-download-manager-priv/downloads/file_download.cpp 2014-02-22 10:42:10 +0000 |
572 | @@ -23,8 +23,10 @@ |
573 | #include <QFile> |
574 | #include <QFileInfo> |
575 | #include <QSslError> |
576 | +#include <ubuntu/download_manager/metadata.h> |
577 | #include <ubuntu/download_manager/system/hash_algorithm.h> |
578 | #include "downloads/file_download.h" |
579 | +#include "system/filename_mutex.h" |
580 | #include "system/logger.h" |
581 | #include "system/network_reply.h" |
582 | |
583 | @@ -34,18 +36,15 @@ |
584 | namespace { |
585 | |
586 | const QString DATA_FILE_NAME = "data.download"; |
587 | - const QString METADATA_FILE_NAME = "metadata"; |
588 | - const QString METADATA_COMMAND_KEY = "post-download-command"; |
589 | - const QString METADATA_COMMAND_FILE_KEY = "$file"; |
590 | const QString NETWORK_ERROR = "NETWORK ERROR"; |
591 | const QString HASH_ERROR = "HASH ERROR"; |
592 | const QString COMMAND_ERROR = "COMMAND ERROR"; |
593 | const QString SSL_ERROR = "SSL ERROR"; |
594 | const QString FILE_SYSTEM_ERROR = "FILE SYSTEM ERROR: %1"; |
595 | + const QString TEMP_EXTENSION = ".tmp"; |
596 | const QString AUTH_ERROR = "AUTHENTICATION ERROR"; |
597 | const QString PROXY_AUTH_ERROR = "PROXY_AUTHENTICATION ERROR"; |
598 | const QString UNEXPECTED_ERROR = "UNEXPECTED_ERROR"; |
599 | - |
600 | } |
601 | |
602 | namespace Ubuntu { |
603 | @@ -116,6 +115,9 @@ |
604 | |
605 | // remove current data and metadata |
606 | cleanUpCurrentData(); |
607 | + // unlock the file name so that other downloads can use it it if is |
608 | + // no used in the file system |
609 | + _fileNameMutex->unlockFileName(_filePath); |
610 | _downloading = false; |
611 | emit canceled(true); |
612 | } |
613 | @@ -197,7 +199,7 @@ |
614 | |
615 | // create file that will be used to maintain the state of the |
616 | // download when resumed. |
617 | - _currentData = FileManager::instance()->createFile(_filePath); |
618 | + _currentData = FileManager::instance()->createFile(_tempFilePath); |
619 | bool canWrite = _currentData->open(QIODevice::ReadWrite | QFile::Append); |
620 | |
621 | if (!canWrite) { |
622 | @@ -326,11 +328,13 @@ |
623 | _reply->deleteLater(); |
624 | _reply = nullptr; |
625 | |
626 | - // clean the local file |
627 | + // clean the local file without unlocking the file the reason for |
628 | + // this is that the file pat is going to be reused to store the |
629 | + // data from the redirect |
630 | cleanUpCurrentData(); |
631 | |
632 | // perform again the request but do not emit started signal |
633 | - _currentData = FileManager::instance()->createFile(_filePath); |
634 | + _currentData = FileManager::instance()->createFile(_tempFilePath); |
635 | bool canWrite = _currentData->open(QIODevice::ReadWrite | QFile::Append); |
636 | |
637 | if (!canWrite) { |
638 | @@ -369,7 +373,7 @@ |
639 | // means we are done here else we execute the command AND raise the |
640 | // finish signals once the command was done (or an error occurred in |
641 | // the command execution. |
642 | - if (metadata().contains(METADATA_COMMAND_KEY)) { |
643 | + if (metadata().contains(Metadata::COMMAND_KEY)) { |
644 | // just emit processing if we DO NOT have a hash because else we |
645 | // already emitted it. |
646 | if (_hash.isEmpty()) { |
647 | @@ -377,7 +381,7 @@ |
648 | } |
649 | // toStringList will return an empty list if it cannot be converted |
650 | QStringList commandData = |
651 | - metadata()[METADATA_COMMAND_KEY].toStringList(); |
652 | + metadata()[Metadata::COMMAND_KEY].toStringList(); |
653 | if (commandData.count() == 0) { |
654 | DOWN_LOG(ERROR) << "COMMAND DATA MISSING"; |
655 | emitError(COMMAND_ERROR); |
656 | @@ -390,7 +394,7 @@ |
657 | QStringList args; |
658 | |
659 | foreach(const QString& arg, commandData) { |
660 | - if (arg == METADATA_COMMAND_FILE_KEY) |
661 | + if (arg == Metadata::COMMAND_FILE_KEY) |
662 | args << filePath(); |
663 | else |
664 | args << arg; |
665 | @@ -412,9 +416,7 @@ |
666 | return; |
667 | } |
668 | } else { |
669 | - setState(Download::FINISH); |
670 | - DOWN_LOG(INFO) << "EMIT finished" << filePath(); |
671 | - emit finished(filePath()); |
672 | + emitFinished(); |
673 | } |
674 | |
675 | // clean the reply |
676 | @@ -467,9 +469,20 @@ |
677 | if (exitCode == 0 && exitStatus == QProcess::NormalExit) { |
678 | // remove the file since we are done with it |
679 | cleanUpCurrentData(); |
680 | - setState(Download::FINISH); |
681 | - DOWN_LOG(INFO) << "EMIT finished" << filePath(); |
682 | - emit finished(filePath()); |
683 | + emitFinished(); |
684 | + // remove the file because that is the contract that we have with |
685 | + // the clients |
686 | + auto fileMan = FileManager::instance(); |
687 | + |
688 | + if (fileMan->exists(_tempFilePath)) { |
689 | + LOG(INFO) << "Removing '" << _tempFilePath << "'"; |
690 | + fileMan->remove(_tempFilePath); |
691 | + } |
692 | + |
693 | + if (fileMan->exists(_filePath)) { |
694 | + LOG(INFO) << "Removing '" << _filePath << "'"; |
695 | + fileMan->remove(_filePath); |
696 | + } |
697 | } else { |
698 | auto standardOut = p->readAllStandardOutput(); |
699 | auto standardErr = p->readAllStandardError(); |
700 | @@ -507,6 +520,7 @@ |
701 | void |
702 | FileDownload::init() { |
703 | _requestFactory = RequestFactory::instance(); |
704 | + _fileNameMutex = System::FileNameMutex::instance(); |
705 | SystemNetworkInfo* networkInfo = SystemNetworkInfo::instance(); |
706 | _connected = networkInfo->isOnline(); |
707 | _downloading = false; |
708 | @@ -515,7 +529,7 @@ |
709 | connect(networkInfo, &SystemNetworkInfo::onlineStateChanged, |
710 | this, &FileDownload::onOnlineStateChanged); |
711 | |
712 | - _filePath = getSaveFileName(); |
713 | + initFileNames(); |
714 | |
715 | // ensure that the download is valid |
716 | if (!_url.isValid()) { |
717 | @@ -563,66 +577,52 @@ |
718 | return flushed; |
719 | } |
720 | |
721 | -QString |
722 | -FileDownload::getSaveFileName() { |
723 | +void |
724 | +FileDownload::initFileNames() { |
725 | + // the mutex will ensure that we do not have race conditions about |
726 | + // the file names in the download manager |
727 | QString path = _url.path(); |
728 | QString basename = QFileInfo(path).fileName(); |
729 | |
730 | if (basename.isEmpty()) |
731 | basename = DATA_FILE_NAME; |
732 | |
733 | - QVariantMap metadataMap = metadata(); |
734 | - QString finalPath; |
735 | + auto metadataMap = metadata(); |
736 | |
737 | - if (!isConfined() && metadataMap.contains(LOCAL_PATH_KEY)) { |
738 | - finalPath = metadataMap[LOCAL_PATH_KEY].toString(); |
739 | + if (!isConfined() && metadataMap.contains(Metadata::LOCAL_PATH_KEY)) { |
740 | + _filePath = metadataMap[Metadata::LOCAL_PATH_KEY].toString(); |
741 | + _tempFilePath = _fileNameMutex->lockFileName( |
742 | + _filePath + TEMP_EXTENSION); |
743 | |
744 | // in this case and because the app is not confined we are |
745 | // going to check if the file exists, if it does we will |
746 | // raise an error |
747 | - if (QFile::exists(finalPath)) { |
748 | + if (QFile::exists(_filePath)) { |
749 | setIsValid(false); |
750 | setLastError(QString("File already exists at: '%1'").arg( |
751 | - finalPath)); |
752 | + _filePath)); |
753 | } |
754 | } else { |
755 | - finalPath = rootPath() + QDir::separator() + basename; |
756 | - if (QFile::exists(finalPath)) { |
757 | - finalPath = uniqueFilePath(finalPath); |
758 | - } |
759 | - |
760 | + auto desiredPath = rootPath() + QDir::separator() + basename; |
761 | + _filePath = _fileNameMutex->lockFileName(desiredPath); |
762 | + _tempFilePath = _filePath + TEMP_EXTENSION; |
763 | } |
764 | - |
765 | - return finalPath; |
766 | } |
767 | |
768 | -QString |
769 | -FileDownload::uniqueFilePath(QString path) { |
770 | - QFileInfo fileInfo(path); |
771 | - |
772 | - // Split the file into 2 parts - dot+extension, and everything else. For |
773 | - // example, "path/file.tar.gz" becomes "path/file"+".tar.gz", while |
774 | - // "path/file" (note lack of extension) becomes "path/file"+"". |
775 | - auto secondPart = fileInfo.completeSuffix(); |
776 | - auto firstPart = path; |
777 | - |
778 | - if (!secondPart.isEmpty()) { |
779 | - secondPart = "." + secondPart; |
780 | - firstPart = path.left(path.size() - secondPart.size()); |
781 | +void |
782 | +FileDownload::emitFinished() { |
783 | + auto fileMan = FileManager::instance(); |
784 | + |
785 | + LOG(INFO) << "EMIT finished" << filePath(); |
786 | + setState(Download::FINISH); |
787 | + |
788 | + if (fileMan->exists(_tempFilePath)) { |
789 | + LOG(INFO) << "Rename '" << _tempFilePath << "' to '" |
790 | + << _filePath << "'"; |
791 | + fileMan->rename(_tempFilePath, _filePath); |
792 | } |
793 | - |
794 | - // Try with an ever-increasing number suffix, until we've reached a file |
795 | - // that does not yet exist. |
796 | - for (int ii = 1; ; ii++) { |
797 | - // Construct the new file name by adding the unique number between the |
798 | - // first and second part. |
799 | - auto finalPath = QString("%1 (%2)%3").arg(firstPart).arg(ii).arg(secondPart); |
800 | - // If no file exists with the new name, return it. |
801 | - if (!QFile::exists(finalPath)) { |
802 | - return finalPath; |
803 | - } |
804 | - } // for |
805 | - return path; |
806 | + _fileNameMutex->unlockFileName(_filePath); |
807 | + emit finished(_filePath); |
808 | } |
809 | |
810 | void |
811 | @@ -638,7 +638,7 @@ |
812 | _currentData->deleteLater(); |
813 | _currentData = nullptr; |
814 | } else { |
815 | - QScopedPointer<QFile> tempFile(new QFile(_filePath)); |
816 | + QScopedPointer<QFile> tempFile(new QFile(_tempFilePath)); |
817 | success = tempFile->remove(); |
818 | if (!success) |
819 | error = tempFile->error(); |
820 | @@ -674,6 +674,8 @@ |
821 | _reply->deleteLater(); |
822 | _reply = nullptr; |
823 | cleanUpCurrentData(); |
824 | + // let other downloads use the same file name |
825 | + _fileNameMutex->unlockFileName(_filePath); |
826 | Download::emitError(error); |
827 | } |
828 | |
829 | |
830 | === modified file 'ubuntu-download-manager-priv/downloads/file_download.h' |
831 | --- ubuntu-download-manager-priv/downloads/file_download.h 2014-02-11 15:35:52 +0000 |
832 | +++ ubuntu-download-manager-priv/downloads/file_download.h 2014-02-22 10:42:10 +0000 |
833 | @@ -30,8 +30,7 @@ |
834 | #include <ubuntu/download_manager/process_error_struct.h> |
835 | #include "downloads/download.h" |
836 | #include "system/file_manager.h" |
837 | - |
838 | -#define LOCAL_PATH_KEY "local-path" |
839 | +#include "system/filename_mutex.h" |
840 | |
841 | namespace Ubuntu { |
842 | |
843 | @@ -121,8 +120,8 @@ |
844 | void onProcessFinished(int exitCode, |
845 | QProcess::ExitStatus exitStatus); |
846 | void onOnlineStateChanged(bool); |
847 | - QString getSaveFileName(); |
848 | - QString uniqueFilePath(QString path); |
849 | + void initFileNames(); |
850 | + void emitFinished(); |
851 | |
852 | private: |
853 | bool _downloading = false; |
854 | @@ -130,10 +129,12 @@ |
855 | qulonglong _totalSize = 0; |
856 | QUrl _url; |
857 | QString _filePath; |
858 | + QString _tempFilePath; |
859 | QString _hash; |
860 | QCryptographicHash::Algorithm _algo; |
861 | NetworkReply* _reply = nullptr; |
862 | File* _currentData = nullptr; |
863 | + FileNameMutex* _fileNameMutex = nullptr; |
864 | QList<QUrl> _visitedUrls; |
865 | }; |
866 | |
867 | |
868 | === modified file 'ubuntu-download-manager-priv/downloads/group_download.cpp' |
869 | --- ubuntu-download-manager-priv/downloads/group_download.cpp 2014-02-20 13:12:04 +0000 |
870 | +++ ubuntu-download-manager-priv/downloads/group_download.cpp 2014-02-22 10:42:10 +0000 |
871 | @@ -16,6 +16,7 @@ |
872 | * boston, ma 02110-1301, usa. |
873 | */ |
874 | |
875 | +#include <ubuntu/download_manager/metadata.h> |
876 | #include <ubuntu/download_manager/system/hash_algorithm.h> |
877 | #include "downloads/download_adaptor.h" |
878 | #include "downloads/file_download.h" |
879 | @@ -95,7 +96,7 @@ |
880 | |
881 | FileDownload* singleDownload; |
882 | QVariantMap downloadMetadata = QVariantMap(metadataMap); |
883 | - downloadMetadata[LOCAL_PATH_KEY] = download.getLocalFile(); |
884 | + downloadMetadata[Metadata::LOCAL_PATH_KEY] = download.getLocalFile(); |
885 | |
886 | if (hash.isEmpty()) { |
887 | singleDownload = qobject_cast<FileDownload*>( |
888 | |
889 | === modified file 'ubuntu-download-manager-priv/system/file_manager.cpp' |
890 | --- ubuntu-download-manager-priv/system/file_manager.cpp 2014-02-01 09:01:47 +0000 |
891 | +++ ubuntu-download-manager-priv/system/file_manager.cpp 2014-02-22 10:42:10 +0000 |
892 | @@ -107,6 +107,11 @@ |
893 | return QFile::exists(path); |
894 | } |
895 | |
896 | +bool |
897 | +FileManager::rename(const QString& oldName, const QString& newName) { |
898 | + return QFile::rename(oldName, newName); |
899 | +} |
900 | + |
901 | FileManager* FileManager::instance() { |
902 | if(_instance == nullptr) { |
903 | _mutex.lock(); |
904 | |
905 | === modified file 'ubuntu-download-manager-priv/system/file_manager.h' |
906 | --- ubuntu-download-manager-priv/system/file_manager.h 2014-02-01 09:01:47 +0000 |
907 | +++ ubuntu-download-manager-priv/system/file_manager.h 2014-02-22 10:42:10 +0000 |
908 | @@ -66,6 +66,7 @@ |
909 | virtual File* createFile(const QString& name); |
910 | virtual bool remove(const QString& path); |
911 | virtual bool exists(const QString& path); |
912 | + virtual bool rename(const QString& oldName, const QString& newName); |
913 | |
914 | static FileManager* instance(); |
915 | |
916 | |
917 | === added file 'ubuntu-download-manager-priv/system/filename_mutex.cpp' |
918 | --- ubuntu-download-manager-priv/system/filename_mutex.cpp 1970-01-01 00:00:00 +0000 |
919 | +++ ubuntu-download-manager-priv/system/filename_mutex.cpp 2014-02-22 10:42:10 +0000 |
920 | @@ -0,0 +1,133 @@ |
921 | +/* |
922 | + * Copyright 2014 Canonical Ltd. |
923 | + * |
924 | + * This library is free software; you can redistribute it and/or |
925 | + * modify it under the terms of version 3 of the GNU Lesser General Public |
926 | + * License as published by the Free Software Foundation. |
927 | + * |
928 | + * This program is distributed in the hope that it will be useful, |
929 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
930 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
931 | + * General Public License for more details. |
932 | + * |
933 | + * You should have received a copy of the GNU Lesser General Public |
934 | + * License along with this library; if not, write to the |
935 | + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
936 | + * Boston, MA 02110-1301, USA. |
937 | + */ |
938 | + |
939 | +#include <QFile> |
940 | +#include <QFileInfo> |
941 | +#include <ubuntu/download_manager/metadata.h> |
942 | +#include "logger.h" |
943 | +#include "filename_mutex.h" |
944 | + |
945 | +namespace Ubuntu { |
946 | + |
947 | +namespace DownloadManager { |
948 | + |
949 | +namespace System { |
950 | + |
951 | +FileNameMutex* FileNameMutex::_instance = nullptr; |
952 | +QMutex FileNameMutex::_singletonMutex; |
953 | + |
954 | +FileNameMutex::FileNameMutex(QObject* parent) |
955 | + : QObject(parent) { |
956 | +} |
957 | + |
958 | +QString |
959 | +FileNameMutex::lockFileName(const QString& expectedName) { |
960 | + auto path = expectedName; |
961 | + _mutex.lock(); |
962 | + QFileInfo fileInfo(expectedName); |
963 | + if (!_paths.contains(path) && !QFile::exists(path)) { |
964 | + _paths.insert(path); |
965 | + _mutex.unlock(); |
966 | + return path; |
967 | + } |
968 | + // Split the file into 2 parts - dot+extension, and everything |
969 | + // else. For example, "path/file.tar.gz" becomes |
970 | + // "path/file"+".tar.gz", while "path/file" (note lack of |
971 | + // extension) becomes "path/file"+"". |
972 | + auto secondPart = fileInfo.completeSuffix(); |
973 | + auto firstPart = expectedName; |
974 | + |
975 | + if (!secondPart.isEmpty()) { |
976 | + secondPart = "." + secondPart; |
977 | + firstPart = expectedName.left(expectedName.size() |
978 | + - secondPart.size()); |
979 | + } |
980 | + |
981 | + // Try with an ever-increasing number suffix, until we've |
982 | + // reached a file that does not yet exist. |
983 | + for (int ii = 1; ; ii++) { |
984 | + // Construct the new file name by adding the unique |
985 | + // number between the first and second part. |
986 | + path = QString("%1 (%2)%3").arg(firstPart |
987 | + ).arg(ii).arg(secondPart); |
988 | + // If no file exists with the new name, return it. |
989 | + if (!_paths.contains(path) && !QFile::exists(path)) { |
990 | + _paths.insert(path); |
991 | + LOG(INFO) << "Locked path '" << path << "'"; |
992 | + break; |
993 | + } |
994 | + } // for |
995 | + |
996 | + _mutex.unlock(); |
997 | + return path; |
998 | +} |
999 | + |
1000 | +void |
1001 | +FileNameMutex::unlockFileName(const QString& filename) { |
1002 | + _mutex.lock(); |
1003 | + auto removed = _paths.remove(filename); |
1004 | + if (!removed) { |
1005 | + LOG(WARNING) << "Tired to remove filename '" << filename |
1006 | + << "' when it was not owned by any object."; |
1007 | + } else { |
1008 | + LOG(INFO) << "Released path '" << filename << "'"; |
1009 | + } |
1010 | + _mutex.unlock(); |
1011 | +} |
1012 | + |
1013 | +bool |
1014 | +FileNameMutex::isLocked(const QString& filename) { |
1015 | + _mutex.lock(); |
1016 | + auto present = _paths.contains(filename); |
1017 | + _mutex.unlock(); |
1018 | + return present; |
1019 | +} |
1020 | + |
1021 | +FileNameMutex* |
1022 | +FileNameMutex::instance() { |
1023 | + if(_instance == nullptr) { |
1024 | + _singletonMutex.lock(); |
1025 | + if(_instance == nullptr) |
1026 | + _instance = new FileNameMutex(); |
1027 | + _singletonMutex.unlock(); |
1028 | + } |
1029 | + return _instance; |
1030 | +} |
1031 | + |
1032 | +void |
1033 | +FileNameMutex::deleteInstance() { |
1034 | + if(_instance != nullptr) { |
1035 | + _singletonMutex.lock(); |
1036 | + if(_instance != nullptr) { |
1037 | + delete _instance; |
1038 | + _instance = nullptr; |
1039 | + } |
1040 | + _singletonMutex.unlock(); |
1041 | + } |
1042 | +} |
1043 | + |
1044 | +void |
1045 | +FileNameMutex::setInstance(FileNameMutex* instance) { |
1046 | + _instance = instance; |
1047 | +} |
1048 | + |
1049 | +} // System |
1050 | + |
1051 | +} // DownloadManager |
1052 | + |
1053 | +} // Ubuntu |
1054 | |
1055 | === added file 'ubuntu-download-manager-priv/system/filename_mutex.h' |
1056 | --- ubuntu-download-manager-priv/system/filename_mutex.h 1970-01-01 00:00:00 +0000 |
1057 | +++ ubuntu-download-manager-priv/system/filename_mutex.h 2014-02-22 10:42:10 +0000 |
1058 | @@ -0,0 +1,64 @@ |
1059 | +/* |
1060 | + * Copyright 2014 Canonical Ltd. |
1061 | + * |
1062 | + * This library is free software; you can redistribute it and/or |
1063 | + * modify it under the terms of version 3 of the GNU Lesser General Public |
1064 | + * License as published by the Free Software Foundation. |
1065 | + * |
1066 | + * This program is distributed in the hope that it will be useful, |
1067 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1068 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1069 | + * General Public License for more details. |
1070 | + * |
1071 | + * You should have received a copy of the GNU Lesser General Public |
1072 | + * License along with this library; if not, write to the |
1073 | + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
1074 | + * Boston, MA 02110-1301, USA. |
1075 | + */ |
1076 | + |
1077 | +#ifndef DOWNLOADER_LIB_FILENAME_MUTEX_H |
1078 | +#define DOWNLOADER_LIB_FILENAME_MUTEX_H |
1079 | + |
1080 | +#include <QMutex> |
1081 | +#include <QObject> |
1082 | +#include <QVariant> |
1083 | +#include <QSet> |
1084 | + |
1085 | +namespace Ubuntu { |
1086 | + |
1087 | +namespace DownloadManager { |
1088 | + |
1089 | +namespace System { |
1090 | + |
1091 | +class FileNameMutex : public QObject { |
1092 | + Q_OBJECT |
1093 | + public: |
1094 | + explicit FileNameMutex(QObject* parent = 0); |
1095 | + virtual QString lockFileName(const QString& expectedName); |
1096 | + virtual void unlockFileName(const QString& filename); |
1097 | + virtual bool isLocked(const QString& filename); |
1098 | + |
1099 | + static FileNameMutex* instance(); |
1100 | + |
1101 | + // only used for testing so that we can inject a fake |
1102 | + static void setInstance(FileNameMutex* instance); |
1103 | + static void deleteInstance(); |
1104 | + |
1105 | + protected: |
1106 | + QSet<QString> _paths; |
1107 | + |
1108 | + private: |
1109 | + // used for the singleton |
1110 | + static FileNameMutex* _instance; |
1111 | + static QMutex _singletonMutex; |
1112 | + |
1113 | + QMutex _mutex; |
1114 | +}; |
1115 | + |
1116 | +} // System |
1117 | + |
1118 | +} // DownloadManager |
1119 | + |
1120 | +} // Ubuntu |
1121 | + |
1122 | +#endif // FILENAME_MUTEX_H |
1123 | |
1124 | === modified file 'ubuntu-download-manager-priv/ubuntu-download-manager-priv.pro' |
1125 | --- ubuntu-download-manager-priv/ubuntu-download-manager-priv.pro 2014-02-13 21:30:25 +0000 |
1126 | +++ ubuntu-download-manager-priv/ubuntu-download-manager-priv.pro 2014-02-22 10:42:10 +0000 |
1127 | @@ -41,7 +41,8 @@ |
1128 | downloads/state_machines/final_state.cpp \ |
1129 | system/apn_request_factory.cpp \ |
1130 | downloads/mms_file_download.cpp \ |
1131 | - system/apn_proxy.cpp |
1132 | + system/apn_proxy.cpp \ |
1133 | + system/filename_mutex.cpp |
1134 | |
1135 | HEADERS +=\ |
1136 | downloads/daemon.h \ |
1137 | @@ -74,7 +75,8 @@ |
1138 | downloads/state_machines/final_state.h \ |
1139 | system/apn_request_factory.h \ |
1140 | downloads/mms_file_download.h \ |
1141 | - system/apn_proxy.h |
1142 | + system/apn_proxy.h \ |
1143 | + system/filename_mutex.h |
1144 | |
1145 | OTHER_FILES += \ |
1146 | generate_adaptors.sh \ |
1147 | |
1148 | === modified file 'ubuntu-download-manager-test-lib/ubuntu-download-manager-test-lib.pro' |
1149 | --- ubuntu-download-manager-test-lib/ubuntu-download-manager-test-lib.pro 2014-02-13 13:21:14 +0000 |
1150 | +++ ubuntu-download-manager-test-lib/ubuntu-download-manager-test-lib.pro 2014-02-22 10:42:10 +0000 |
1151 | @@ -35,7 +35,8 @@ |
1152 | ubuntu/download_manager/tests/client/testing_interface.cpp \ |
1153 | ubuntu/download_manager/tests/client/testing_file_download.cpp \ |
1154 | ubuntu/download_manager/tests/server/apn_request_factory.cpp \ |
1155 | - ubuntu/download_manager/tests/server/group_download.cpp |
1156 | + ubuntu/download_manager/tests/server/filename_mutex.cpp \ |
1157 | + ubuntu/download_manager/tests/server/group_download.cpp |
1158 | |
1159 | HEADERS += ubuntu/download_manager/tests/base_testcase.h \ |
1160 | ubuntu/download_manager/tests/fake.h\ |
1161 | @@ -64,7 +65,8 @@ |
1162 | ubuntu/download_manager/tests/client/testing_interface.h \ |
1163 | ubuntu/download_manager/tests/client/testing_file_download.h \ |
1164 | ubuntu/download_manager/tests/server/apn_request_factory.h \ |
1165 | - ubuntu/download_manager/tests/server/group_download.h |
1166 | + ubuntu/download_manager/tests/server/filename_mutex.h \ |
1167 | + ubuntu/download_manager/tests/server/group_download.h |
1168 | |
1169 | LIBS += -L$$OUT_PWD/../ubuntu-download-manager-common/ -lubuntu-download-manager-common |
1170 | |
1171 | |
1172 | === modified file 'ubuntu-download-manager-test-lib/ubuntu/download_manager/tests/base_testcase.cpp' |
1173 | --- ubuntu-download-manager-test-lib/ubuntu/download_manager/tests/base_testcase.cpp 2014-01-24 11:24:40 +0000 |
1174 | +++ ubuntu-download-manager-test-lib/ubuntu/download_manager/tests/base_testcase.cpp 2014-02-22 10:42:10 +0000 |
1175 | @@ -46,7 +46,7 @@ |
1176 | pathComponents << dataPath << objectName(); |
1177 | QString path = pathComponents.join(QDir::separator()); |
1178 | |
1179 | - if (!QDir().exists(path)) |
1180 | + if (!QDir().exists(path)) |
1181 | QDir().mkpath(path); |
1182 | |
1183 | return path; |
1184 | |
1185 | === modified file 'ubuntu-download-manager-test-lib/ubuntu/download_manager/tests/server/file_manager.cpp' |
1186 | --- ubuntu-download-manager-test-lib/ubuntu/download_manager/tests/server/file_manager.cpp 2014-02-01 09:01:47 +0000 |
1187 | +++ ubuntu-download-manager-test-lib/ubuntu/download_manager/tests/server/file_manager.cpp 2014-02-22 10:42:10 +0000 |
1188 | @@ -76,5 +76,5 @@ |
1189 | MethodData methodData("remove", params); |
1190 | _called.append(methodData); |
1191 | } |
1192 | - return true; |
1193 | + return QFile::remove(path); |
1194 | } |
1195 | |
1196 | === added file 'ubuntu-download-manager-test-lib/ubuntu/download_manager/tests/server/filename_mutex.cpp' |
1197 | --- ubuntu-download-manager-test-lib/ubuntu/download_manager/tests/server/filename_mutex.cpp 1970-01-01 00:00:00 +0000 |
1198 | +++ ubuntu-download-manager-test-lib/ubuntu/download_manager/tests/server/filename_mutex.cpp 2014-02-22 10:42:10 +0000 |
1199 | @@ -0,0 +1,58 @@ |
1200 | +/* |
1201 | + * Copyright 2014 Canonical Ltd. |
1202 | + * |
1203 | + * This library is free software; you can redistribute it and/or |
1204 | + * modify it under the terms of version 3 of the GNU Lesser General Public |
1205 | + * License as published by the Free Software Foundation. |
1206 | + * |
1207 | + * This program is distributed in the hope that it will be useful, |
1208 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1209 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1210 | + * General Public License for more details. |
1211 | + * |
1212 | + * You should have received a copy of the GNU Lesser General Public |
1213 | + * License along with this library; if not, write to the |
1214 | + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
1215 | + * Boston, MA 02110-1301, USA. |
1216 | + */ |
1217 | + |
1218 | +#include "filename_mutex.h" |
1219 | + |
1220 | +FakeFileNameMutex::FakeFileNameMutex(QObject* parent) |
1221 | + : FileNameMutex(parent), |
1222 | + Fake(){ |
1223 | +} |
1224 | + |
1225 | +QString |
1226 | +FakeFileNameMutex::lockFileName(const QString& expectedName) { |
1227 | + if (_recording) { |
1228 | + QList<QObject*> inParams; |
1229 | + inParams.append(new StringWrapper(expectedName, this)); |
1230 | + QList<QObject*> outParams; |
1231 | + MethodParams params(inParams, outParams); |
1232 | + |
1233 | + MethodData methodData("lockFileName", params); |
1234 | + _called.append(methodData); |
1235 | + } |
1236 | + |
1237 | + return FileNameMutex::lockFileName(expectedName); |
1238 | +} |
1239 | + |
1240 | +void |
1241 | +FakeFileNameMutex::unlockFileName(const QString& filename) { |
1242 | + if (_recording) { |
1243 | + QList<QObject*> inParams; |
1244 | + inParams.append(new StringWrapper(filename, this)); |
1245 | + QList<QObject*> outParams; |
1246 | + MethodParams params(inParams, outParams); |
1247 | + |
1248 | + MethodData methodData("unlockFileName", params); |
1249 | + _called.append(methodData); |
1250 | + } |
1251 | + FileNameMutex::unlockFileName(filename); |
1252 | +} |
1253 | + |
1254 | +void |
1255 | +FakeFileNameMutex::clearMutex() { |
1256 | + _paths.clear(); |
1257 | +} |
1258 | |
1259 | === added file 'ubuntu-download-manager-test-lib/ubuntu/download_manager/tests/server/filename_mutex.h' |
1260 | --- ubuntu-download-manager-test-lib/ubuntu/download_manager/tests/server/filename_mutex.h 1970-01-01 00:00:00 +0000 |
1261 | +++ ubuntu-download-manager-test-lib/ubuntu/download_manager/tests/server/filename_mutex.h 2014-02-22 10:42:10 +0000 |
1262 | @@ -0,0 +1,43 @@ |
1263 | +/* |
1264 | + * Copyright 2014 Canonical Ltd. |
1265 | + * |
1266 | + * This library is free software; you can redistribute it and/or |
1267 | + * modify it under the terms of version 3 of the GNU Lesser General Public |
1268 | + * License as published by the Free Software Foundation. |
1269 | + * |
1270 | + * This program is distributed in the hope that it will be useful, |
1271 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1272 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1273 | + * General Public License for more details. |
1274 | + * |
1275 | + * You should have received a copy of the GNU Lesser General Public |
1276 | + * License along with this library; if not, write to the |
1277 | + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
1278 | + * Boston, MA 02110-1301, USA. |
1279 | + */ |
1280 | + |
1281 | +#ifndef FILENAME_MUTEXT_H |
1282 | +#define FILENAME_MUTEXT_H |
1283 | + |
1284 | +#include <QObject> |
1285 | +#include <system/filename_mutex.h> |
1286 | +#include "ubuntu/download_manager/tests/fake.h" |
1287 | + |
1288 | +using namespace Ubuntu::DownloadManager::System; |
1289 | + |
1290 | +class FakeFileNameMutex : public FileNameMutex, public Fake { |
1291 | + Q_OBJECT |
1292 | + |
1293 | + public: |
1294 | + explicit FakeFileNameMutex(QObject *parent = 0); |
1295 | + |
1296 | + /// override to keep track of the calls |
1297 | + QString lockFileName(const QString& expectedName) override; |
1298 | + void unlockFileName(const QString& filename) override; |
1299 | + |
1300 | + // just for testing purposes |
1301 | + void clearMutex(); |
1302 | + |
1303 | +}; |
1304 | + |
1305 | +#endif // FILENAME_MUTEXT_H |
1306 | |
1307 | === modified file 'ubuntu-download-manager-tests/downloads/test_download.cpp' |
1308 | --- ubuntu-download-manager-tests/downloads/test_download.cpp 2014-02-11 15:35:52 +0000 |
1309 | +++ ubuntu-download-manager-tests/downloads/test_download.cpp 2014-02-22 10:42:10 +0000 |
1310 | @@ -50,6 +50,8 @@ |
1311 | ProcessFactory::setInstance(_processFactory); |
1312 | _fileManager = new FakeFileManager(); |
1313 | FileManager::setInstance(_fileManager); |
1314 | + _fileNameMutex = new FakeFileNameMutex(); |
1315 | + FileNameMutex::setInstance(_fileNameMutex); |
1316 | } |
1317 | |
1318 | void |
1319 | @@ -60,6 +62,7 @@ |
1320 | RequestFactory::deleteInstance(); |
1321 | ProcessFactory::deleteInstance(); |
1322 | FileManager::deleteInstance(); |
1323 | + FileNameMutex::deleteInstance(); |
1324 | } |
1325 | |
1326 | void |
1327 | @@ -711,7 +714,9 @@ |
1328 | QCOMPARE(spy.count(), 1); |
1329 | |
1330 | // assert that the files does exist in the system |
1331 | - QFileInfo info = QFileInfo(download->filePath()); |
1332 | + QFileInfo info(download->filePath()); |
1333 | + QVERIFY(!info.exists()); |
1334 | + info = QFileInfo(download->filePath() + ".tmp"); |
1335 | QVERIFY(info.exists()); |
1336 | } |
1337 | |
1338 | @@ -735,6 +740,8 @@ |
1339 | |
1340 | // assert that the files does exist in the system |
1341 | QFileInfo info = QFileInfo(download->filePath()); |
1342 | + QVERIFY(!info.exists()); |
1343 | + info = QFileInfo(download->filePath() + ".tmp"); |
1344 | QVERIFY(info.exists()); |
1345 | } |
1346 | |
1347 | @@ -1639,8 +1646,9 @@ |
1348 | |
1349 | _processFactory->record(); |
1350 | _reqFactory->record(); |
1351 | - QScopedPointer<FileDownload> download(new FileDownload(_id, _path, _isConfined, |
1352 | - _rootPath, _url, metadata, _headers)); |
1353 | + QScopedPointer<FileDownload> download(new FileDownload(_id, _path, |
1354 | + _isConfined, _rootPath, _url, metadata, _headers)); |
1355 | + QSignalSpy finishedSpy(download.data(), SIGNAL(finished(QString))); |
1356 | |
1357 | // write something in the expected file |
1358 | QString fileName = download->filePath(); |
1359 | @@ -1668,6 +1676,7 @@ |
1360 | |
1361 | // emit the finished signal with a result > 0 and ensure error is emitted |
1362 | process->emitFinished(0, QProcess::NormalExit); |
1363 | + QTRY_COMPARE(1, finishedSpy.count()); |
1364 | // assert that the file does not longer exist in the system |
1365 | QVERIFY(!QFile::exists(fileName)); |
1366 | } |
1367 | @@ -1901,7 +1910,7 @@ |
1368 | |
1369 | QTest::newRow("One") << 1; |
1370 | QTest::newRow("Some") << 3; |
1371 | - QTest::newRow("Several") << 10; |
1372 | + QTest::newRow("Several") << 10; |
1373 | QTest::newRow("Plenti") << 100; |
1374 | } |
1375 | |
1376 | @@ -1921,11 +1930,14 @@ |
1377 | |
1378 | QFileInfo fileInfo(filePath); |
1379 | auto suffix = "." + fileInfo.completeSuffix(); |
1380 | + qDebug() << "SUFIX" << suffix; |
1381 | auto prefix = filePath.left(filePath.size() - suffix.size()); |
1382 | + qDebug() << "PREFIX" << prefix; |
1383 | |
1384 | // write the rest of the files |
1385 | for(int index=1; index < count; index++) { |
1386 | auto otherPath = QString("%1 (%2)%3").arg(prefix).arg(index).arg(suffix); |
1387 | + qDebug() << "Writing a new file" << otherPath; |
1388 | QScopedPointer<QFile> otherFile(new QFile(otherPath)); |
1389 | otherFile->open(QIODevice::ReadWrite | QFile::Append); |
1390 | otherFile->write("data data data!"); |
1391 | @@ -2220,3 +2232,184 @@ |
1392 | QTRY_COMPARE(finishedSpy.count(), 1); |
1393 | QCOMPARE(redirectCount, urls.count()); |
1394 | } |
1395 | + |
1396 | +void |
1397 | +TestDownload::testRedirectDoesNotUnlockPath() { |
1398 | + _fileNameMutex->record(); |
1399 | + |
1400 | + QUrl redirectUrl("http://redirect.example.com"); |
1401 | + _reqFactory->record(); |
1402 | + QScopedPointer<FileDownload> download(new FileDownload(_id, _path, |
1403 | + _isConfined, _rootPath, _url, _metadata, _headers)); |
1404 | + |
1405 | + download->start(); // change state |
1406 | + download->startDownload(); |
1407 | + |
1408 | + QList<MethodData> calledMethods = _reqFactory->calledMethods(); |
1409 | + QCOMPARE(1, calledMethods.count()); |
1410 | + FakeNetworkReply* reply = qobject_cast<FakeNetworkReply*>( |
1411 | + calledMethods[0].params().outParams()[0]); |
1412 | + |
1413 | + // set the attr for a redirect to a new url |
1414 | + // makes the process to be executed |
1415 | + reply->setAttribute(QNetworkRequest::RedirectionTargetAttribute, |
1416 | + redirectUrl); |
1417 | + QSignalSpy replySpy(_reqFactory, SIGNAL(requestCreated(NetworkReply*))); |
1418 | + |
1419 | + // use a spy to wait for the second reply |
1420 | + reply->emitFinished(); |
1421 | + |
1422 | + // ensure that a second request is performed |
1423 | + QTRY_COMPARE(1, replySpy.count()); |
1424 | + |
1425 | + reply = qobject_cast<FakeNetworkReply*>( |
1426 | + replySpy.takeFirst().at(0).value<NetworkReply*>()); |
1427 | + |
1428 | + download->pause(); |
1429 | + |
1430 | + QSignalSpy errorSpy(download.data(), SIGNAL(error(QString))); |
1431 | + QSignalSpy networkErrorSpy(download.data(), |
1432 | + SIGNAL(networkError(NetworkErrorStruct))); |
1433 | + QSignalSpy finishedSpy(download.data(), SIGNAL(finished(QString))); |
1434 | + |
1435 | + reply->emitFinished(); |
1436 | + |
1437 | + QTRY_COMPARE(networkErrorSpy.count(), 0); |
1438 | + QTRY_COMPARE(errorSpy.count(), 0); |
1439 | + QTRY_COMPARE(finishedSpy.count(), 1); |
1440 | + |
1441 | + // ensure that we only called lock and unlock once and not several times |
1442 | + calledMethods = _fileNameMutex->calledMethods(); |
1443 | + QCOMPARE(2, calledMethods.count()); |
1444 | + auto methodName = calledMethods[0].methodName(); |
1445 | + QCOMPARE(QString("lockFileName"), methodName); |
1446 | + methodName = calledMethods[1].methodName(); |
1447 | + QCOMPARE(QString("unlockFileName"), methodName); |
1448 | +} |
1449 | + |
1450 | +void |
1451 | +TestDownload::testCancelUnlocksPath() { |
1452 | + _fileNameMutex->record(); |
1453 | + QScopedPointer<FileDownload> download(new FileDownload(_id, _path, |
1454 | + _isConfined, _rootPath, _url, _metadata, _headers)); |
1455 | + QSignalSpy spy(download.data(), |
1456 | + SIGNAL(canceled(bool))); // NOLINT(readability/function) |
1457 | + |
1458 | + download->start(); // change state |
1459 | + download->startDownload(); |
1460 | + download->cancel(); // change state |
1461 | + download->cancelDownload(); // method under test |
1462 | + |
1463 | + // assert that the filename was correctly managed |
1464 | + auto calledMethods = _fileNameMutex->calledMethods(); |
1465 | + QCOMPARE(2, calledMethods.count()); |
1466 | + auto methodName = calledMethods[0].methodName(); |
1467 | + QCOMPARE(QString("lockFileName"), methodName); |
1468 | + methodName = calledMethods[1].methodName(); |
1469 | + QCOMPARE(QString("unlockFileName"), methodName); |
1470 | +} |
1471 | + |
1472 | +void |
1473 | +TestDownload::testFinishUnlocksPath() { |
1474 | + _fileNameMutex->record(); |
1475 | + _reqFactory->record(); |
1476 | + QScopedPointer<FileDownload> download(new FileDownload(_id, _path, _isConfined, |
1477 | + _rootPath, _url, _metadata, _headers)); |
1478 | + QSignalSpy spy(download.data(), SIGNAL(finished(QString))); |
1479 | + |
1480 | + download->start(); // change state |
1481 | + download->startDownload(); |
1482 | + |
1483 | + QList<MethodData> calledMethods = _reqFactory->calledMethods(); |
1484 | + QCOMPARE(1, calledMethods.count()); |
1485 | + FakeNetworkReply* reply = reinterpret_cast<FakeNetworkReply*>( |
1486 | + calledMethods[0].params().outParams()[0]); |
1487 | + |
1488 | + // emit the finish signal and expect it to be raised |
1489 | + emit reply->finished(); |
1490 | + QCOMPARE(spy.count(), 1); |
1491 | + QCOMPARE(download->state(), Download::FINISH); |
1492 | + |
1493 | + calledMethods = _fileNameMutex->calledMethods(); |
1494 | + QCOMPARE(2, calledMethods.count()); |
1495 | + auto methodName = calledMethods[0].methodName(); |
1496 | + QCOMPARE(QString("lockFileName"), methodName); |
1497 | + methodName = calledMethods[1].methodName(); |
1498 | + QCOMPARE(QString("unlockFileName"), methodName); |
1499 | +} |
1500 | + |
1501 | +void |
1502 | +TestDownload::testProcessFinishUnlocksPath() { |
1503 | + _fileNameMutex->record(); |
1504 | + _processFactory->record(); |
1505 | + _reqFactory->record(); |
1506 | + |
1507 | + QString command = "cd"; |
1508 | + QVariantMap metadata; |
1509 | + metadata["post-download-command"] = command; |
1510 | + |
1511 | + QScopedPointer<FileDownload> download(new FileDownload(_id, _path, |
1512 | + _isConfined, _rootPath, _url, metadata, _headers)); |
1513 | + QSignalSpy spy(download.data(), SIGNAL(finished(QString))); |
1514 | + |
1515 | + download->start(); // change state |
1516 | + download->startDownload(); |
1517 | + |
1518 | + // we need to set the data before we pause!!! |
1519 | + QList<MethodData> calledMethods = _reqFactory->calledMethods(); |
1520 | + QCOMPARE(1, calledMethods.count()); |
1521 | + FakeNetworkReply* reply = reinterpret_cast<FakeNetworkReply*>( |
1522 | + calledMethods[0].params().outParams()[0]); |
1523 | + |
1524 | + // makes the process to be executed |
1525 | + reply->emitFinished(); |
1526 | + |
1527 | + calledMethods = _processFactory->calledMethods(); |
1528 | + QCOMPARE(1, calledMethods.count()); |
1529 | + FakeProcess* process = reinterpret_cast<FakeProcess*>( |
1530 | + calledMethods[0].params().outParams()[0]); |
1531 | + |
1532 | + process->emitFinished(0, QProcess::NormalExit); |
1533 | + QTRY_COMPARE(spy.count(), 1); |
1534 | + |
1535 | + calledMethods = _fileNameMutex->calledMethods(); |
1536 | + QCOMPARE(2, calledMethods.count()); |
1537 | + auto methodName = calledMethods[0].methodName(); |
1538 | + QCOMPARE(QString("lockFileName"), methodName); |
1539 | + methodName = calledMethods[1].methodName(); |
1540 | + QCOMPARE(QString("unlockFileName"), methodName); |
1541 | +} |
1542 | + |
1543 | +void |
1544 | +TestDownload::testErrorUnlocksPath() { |
1545 | + // fake an error and make sure that unlock is called |
1546 | + _fileNameMutex->record(); |
1547 | + _reqFactory->record(); |
1548 | + QScopedPointer<FileDownload> download(new FileDownload(_id, _path, |
1549 | + _isConfined, _rootPath, _url, _metadata, _headers)); |
1550 | + QSignalSpy errorSpy(download.data(), SIGNAL(error(QString))); |
1551 | + |
1552 | + download->start(); // change state |
1553 | + download->startDownload(); |
1554 | + |
1555 | + // we need to set the data before we pause!!! |
1556 | + QList<MethodData> calledMethods = _reqFactory->calledMethods(); |
1557 | + QCOMPARE(1, calledMethods.count()); |
1558 | + FakeNetworkReply* reply = reinterpret_cast<FakeNetworkReply*>( |
1559 | + calledMethods[0].params().outParams()[0]); |
1560 | + |
1561 | + // set the attrs in the reply so that we do raise two signals |
1562 | + reply->setAttribute(QNetworkRequest::HttpStatusCodeAttribute, 404); |
1563 | + reply->setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, ""); |
1564 | + |
1565 | + // emit the error and esure that the signals are raised |
1566 | + reply->emitHttpError(QNetworkReply::ContentAccessDenied); |
1567 | + QCOMPARE(errorSpy.count(), 1); |
1568 | + |
1569 | + calledMethods = _fileNameMutex->calledMethods(); |
1570 | + QCOMPARE(2, calledMethods.count()); |
1571 | + auto methodName = calledMethods[0].methodName(); |
1572 | + QCOMPARE(QString("lockFileName"), methodName); |
1573 | + methodName = calledMethods[1].methodName(); |
1574 | + QCOMPARE(QString("unlockFileName"), methodName); |
1575 | +} |
1576 | |
1577 | === modified file 'ubuntu-download-manager-tests/downloads/test_download.h' |
1578 | --- ubuntu-download-manager-tests/downloads/test_download.h 2014-02-11 15:35:52 +0000 |
1579 | +++ ubuntu-download-manager-tests/downloads/test_download.h 2014-02-22 10:42:10 +0000 |
1580 | @@ -24,6 +24,7 @@ |
1581 | #include <downloads/file_download.h> |
1582 | #include <ubuntu/download_manager/metatypes.h> |
1583 | #include <ubuntu/download_manager/tests/server/file_manager.h> |
1584 | +#include <ubuntu/download_manager/tests/server/filename_mutex.h> |
1585 | #include <ubuntu/download_manager/tests/server/system_network_info.h> |
1586 | #include <ubuntu/download_manager/tests/server/request_factory.h> |
1587 | #include <ubuntu/download_manager/tests/server/process_factory.h> |
1588 | @@ -162,6 +163,13 @@ |
1589 | void testSeveralRedirects_data(); |
1590 | void testSeveralRedirects(); |
1591 | |
1592 | + // test lock of files |
1593 | + void testRedirectDoesNotUnlockPath(); |
1594 | + void testCancelUnlocksPath(); |
1595 | + void testFinishUnlocksPath(); |
1596 | + void testProcessFinishUnlocksPath(); |
1597 | + void testErrorUnlocksPath(); |
1598 | + |
1599 | private: |
1600 | QString _id; |
1601 | bool _isConfined; |
1602 | @@ -175,6 +183,7 @@ |
1603 | FakeRequestFactory* _reqFactory; |
1604 | FakeProcessFactory* _processFactory; |
1605 | FakeFileManager* _fileManager; |
1606 | + FakeFileNameMutex* _fileNameMutex; |
1607 | }; |
1608 | |
1609 | Q_DECLARE_METATYPE(QNetworkInfo::NetworkMode) |
1610 | |
1611 | === modified file 'ubuntu-download-manager-tests/downloads/test_downloads_db.cpp' |
1612 | --- ubuntu-download-manager-tests/downloads/test_downloads_db.cpp 2014-02-10 09:54:01 +0000 |
1613 | +++ ubuntu-download-manager-tests/downloads/test_downloads_db.cpp 2014-02-22 10:42:10 +0000 |
1614 | @@ -47,6 +47,8 @@ |
1615 | void |
1616 | TestDownloadsDb::init() { |
1617 | BaseTestCase::init(); |
1618 | + _fileNameMutex = new FakeFileNameMutex(); |
1619 | + FileNameMutex::setInstance(_fileNameMutex); |
1620 | _db = DownloadsDb::instance(); |
1621 | } |
1622 | |
1623 | @@ -62,6 +64,7 @@ |
1624 | QFile::remove(dbFile); |
1625 | SystemNetworkInfo::deleteInstance(); |
1626 | FileManager::deleteInstance(); |
1627 | + FileNameMutex::deleteInstance(); |
1628 | } |
1629 | |
1630 | void |
1631 | @@ -244,8 +247,8 @@ |
1632 | |
1633 | // create a second download with same id but a diff path to test is update |
1634 | QString newPath = path + path; |
1635 | - QScopedPointer<FakeDownload> secondDownload(new FakeDownload(id, newPath, true, "", |
1636 | - url, hash, hashAlgoString, metadata, headers)); |
1637 | + QScopedPointer<FakeDownload> secondDownload(new FakeDownload(id, |
1638 | + newPath, true, "", url, hash, hashAlgoString, metadata, headers)); |
1639 | |
1640 | _db->storeSingleDownload(secondDownload.data()); |
1641 | |
1642 | @@ -263,9 +266,6 @@ |
1643 | QString dbDbusPath = query.value(1).toString(); |
1644 | QCOMPARE(newPath, dbDbusPath); |
1645 | |
1646 | - QString dbLocalPath = query.value(2).toString(); |
1647 | - QCOMPARE(dbLocalPath, download->filePath()); |
1648 | - |
1649 | QString dbHash = query.value(3).toString(); |
1650 | QCOMPARE(hash, dbHash); |
1651 | |
1652 | |
1653 | === modified file 'ubuntu-download-manager-tests/downloads/test_downloads_db.h' |
1654 | --- ubuntu-download-manager-tests/downloads/test_downloads_db.h 2014-02-10 09:51:58 +0000 |
1655 | +++ ubuntu-download-manager-tests/downloads/test_downloads_db.h 2014-02-22 10:42:10 +0000 |
1656 | @@ -24,6 +24,7 @@ |
1657 | #include <downloads/downloads_db.h> |
1658 | #include <ubuntu/download_manager/tests/base_testcase.h> |
1659 | #include <ubuntu/download_manager/tests/test_runner.h> |
1660 | +#include <ubuntu/download_manager/tests/server/filename_mutex.h> |
1661 | |
1662 | using namespace Ubuntu::DownloadManager::Daemon; |
1663 | |
1664 | @@ -68,6 +69,7 @@ |
1665 | |
1666 | private: |
1667 | DownloadsDb* _db; |
1668 | + FakeFileNameMutex* _fileNameMutex; |
1669 | }; |
1670 | |
1671 | DECLARE_TEST(TestDownloadsDb) |
1672 | |
1673 | === modified file 'ubuntu-download-manager-tests/downloads/test_group_download.cpp' |
1674 | --- ubuntu-download-manager-tests/downloads/test_group_download.cpp 2014-02-13 13:21:14 +0000 |
1675 | +++ ubuntu-download-manager-tests/downloads/test_group_download.cpp 2014-02-22 10:42:10 +0000 |
1676 | @@ -20,6 +20,7 @@ |
1677 | #include <QSignalSpy> |
1678 | #include <downloads/group_download.h> |
1679 | #include <system/uuid_utils.h> |
1680 | +#include <ubuntu/download_manager/metadata.h> |
1681 | #include <ubuntu/download_manager/tests/server/download.h> |
1682 | #include <ubuntu/download_manager/tests/server/group_download.h> |
1683 | #include "test_group_download.h" |
1684 | @@ -667,18 +668,18 @@ |
1685 | |
1686 | // assert that each metadata has the local file set |
1687 | QVariantMap downMeta = downloads[0]->metadata(); |
1688 | - QVERIFY(downMeta.contains(LOCAL_PATH_KEY)); |
1689 | - QCOMPARE(downMeta[LOCAL_PATH_KEY].toString(), |
1690 | + QVERIFY(downMeta.contains(Metadata::LOCAL_PATH_KEY)); |
1691 | + QCOMPARE(downMeta[Metadata::LOCAL_PATH_KEY].toString(), |
1692 | downloadsStruct[0].getLocalFile()); |
1693 | |
1694 | downMeta = downloads[1]->metadata(); |
1695 | - QVERIFY(downMeta.contains(LOCAL_PATH_KEY)); |
1696 | - QCOMPARE(downMeta[LOCAL_PATH_KEY].toString(), |
1697 | + QVERIFY(downMeta.contains(Metadata::LOCAL_PATH_KEY)); |
1698 | + QCOMPARE(downMeta[Metadata::LOCAL_PATH_KEY].toString(), |
1699 | downloadsStruct[1].getLocalFile()); |
1700 | |
1701 | downMeta = downloads[2]->metadata(); |
1702 | - QVERIFY(downMeta.contains(LOCAL_PATH_KEY)); |
1703 | - QCOMPARE(downMeta[LOCAL_PATH_KEY].toString(), |
1704 | + QVERIFY(downMeta.contains(Metadata::LOCAL_PATH_KEY)); |
1705 | + QCOMPARE(downMeta[Metadata::LOCAL_PATH_KEY].toString(), |
1706 | downloadsStruct[2].getLocalFile()); |
1707 | } |
1708 | |
1709 | |
1710 | === added file 'ubuntu-download-manager-tests/system/test_filename_mutex.cpp' |
1711 | --- ubuntu-download-manager-tests/system/test_filename_mutex.cpp 1970-01-01 00:00:00 +0000 |
1712 | +++ ubuntu-download-manager-tests/system/test_filename_mutex.cpp 2014-02-22 10:42:10 +0000 |
1713 | @@ -0,0 +1,108 @@ |
1714 | +/* |
1715 | + * Copyright 2014 Canonical Ltd. |
1716 | + * |
1717 | + * This library is free software; you can redistribute it and/or |
1718 | + * modify it under the terms of version 3 of the GNU Lesser General Public |
1719 | + * License as published by the Free Software Foundation. |
1720 | + * |
1721 | + * This program is distributed in the hope that it will be useful, |
1722 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1723 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1724 | + * General Public License for more details. |
1725 | + * |
1726 | + * You should have received a copy of the GNU Lesser General Public |
1727 | + * License along with this library; if not, write to the |
1728 | + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
1729 | + * Boston, MA 02110-1301, USA. |
1730 | + */ |
1731 | + |
1732 | +#include <QByteArray> |
1733 | +#include <QDir> |
1734 | +#include <QFile> |
1735 | +#include <QScopedPointer> |
1736 | +#include <system/filename_mutex.h> |
1737 | +#include "test_filename_mutex.h" |
1738 | + |
1739 | +using namespace Ubuntu::DownloadManager::System; |
1740 | + |
1741 | +TestFileNameMutex::TestFileNameMutex(QObject *parent) |
1742 | + : BaseTestCase("TestFileNameMutex", parent) { |
1743 | +} |
1744 | + |
1745 | +void |
1746 | +TestFileNameMutex::testExpectedNameValid_data() { |
1747 | + QTest::addColumn<QString>("path"); |
1748 | + auto dir = testDirectory(); |
1749 | + |
1750 | + QTest::newRow("First path") << dir + QDir::separator() + "first.zip"; |
1751 | + QTest::newRow("Second path") << dir + QDir::separator() + "second.zip"; |
1752 | + QTest::newRow("Last path") << dir + QDir::separator() + "last.zip"; |
1753 | +} |
1754 | + |
1755 | +void |
1756 | +TestFileNameMutex::testExpectedNameValid() { |
1757 | + QFETCH(QString, path); |
1758 | + |
1759 | + QScopedPointer<FileNameMutex> mutex(new FileNameMutex()); |
1760 | + auto locked = mutex->lockFileName(path); |
1761 | + QCOMPARE(path, locked); |
1762 | + QVERIFY(mutex->isLocked(path)); |
1763 | +} |
1764 | + |
1765 | +void |
1766 | +TestFileNameMutex::testExpectedNameLocked_data() { |
1767 | + QTest::addColumn<QString>("path"); |
1768 | + auto dir = testDirectory(); |
1769 | + |
1770 | + QTest::newRow("First path") << dir + QDir::separator() + "first.zip"; |
1771 | + QTest::newRow("Second path") << dir + QDir::separator() + "second.zip"; |
1772 | + QTest::newRow("Last path") << dir + QDir::separator() + "last.zip"; |
1773 | +} |
1774 | + |
1775 | +void |
1776 | +TestFileNameMutex::testExpectedNameLocked() { |
1777 | + QFETCH(QString, path); |
1778 | + |
1779 | + QScopedPointer<FileNameMutex> mutex(new FileNameMutex()); |
1780 | + mutex->lockFileName(path); // ensure that we already locked the path |
1781 | + auto locked = mutex->lockFileName(path); |
1782 | + QVERIFY(path != locked); |
1783 | + QVERIFY(mutex->isLocked(locked)); |
1784 | +} |
1785 | + |
1786 | +void |
1787 | +TestFileNameMutex::testExpectedNameInFileSystem_data() { |
1788 | + QTest::addColumn<QString>("path"); |
1789 | + auto dir = testDirectory(); |
1790 | + |
1791 | + QTest::newRow("First path") << dir + QDir::separator() + "first.zip"; |
1792 | + QTest::newRow("Second path") << dir + QDir::separator() + "second_zip"; |
1793 | + QTest::newRow("Last path") << dir + QDir::separator() + "last_zip"; |
1794 | +} |
1795 | + |
1796 | +void |
1797 | +TestFileNameMutex::testExpectedNameInFileSystem() { |
1798 | + QFETCH(QString, path); |
1799 | + testDirectory(); // build temp dir |
1800 | + QScopedPointer<FileNameMutex> mutex(new FileNameMutex()); |
1801 | + |
1802 | + QFile file(path); |
1803 | + file.open(QIODevice::ReadWrite | QFile::Append); |
1804 | + file.write(QByteArray(400, 'f')); |
1805 | + file.flush(); |
1806 | + file.close(); |
1807 | + |
1808 | + auto locked = mutex->lockFileName(path); |
1809 | + QVERIFY(path != locked); |
1810 | + QVERIFY(!mutex->isLocked(path)); |
1811 | +} |
1812 | + |
1813 | +void |
1814 | +TestFileNameMutex::testUnlockPresent() { |
1815 | + auto path = testDirectory() + QDir::separator() + "test.txt"; |
1816 | + QScopedPointer<FileNameMutex> mutex(new FileNameMutex()); |
1817 | + auto locked = mutex->lockFileName(path); |
1818 | + QVERIFY(mutex->isLocked(locked)); |
1819 | + mutex->unlockFileName(path); |
1820 | + QVERIFY(!mutex->isLocked(locked)); |
1821 | +} |
1822 | |
1823 | === added file 'ubuntu-download-manager-tests/system/test_filename_mutex.h' |
1824 | --- ubuntu-download-manager-tests/system/test_filename_mutex.h 1970-01-01 00:00:00 +0000 |
1825 | +++ ubuntu-download-manager-tests/system/test_filename_mutex.h 2014-02-22 10:42:10 +0000 |
1826 | @@ -0,0 +1,45 @@ |
1827 | +/* |
1828 | + * Copyright 2014 Canonical Ltd. |
1829 | + * |
1830 | + * This library is free software; you can redistribute it and/or |
1831 | + * modify it under the terms of version 3 of the GNU Lesser General Public |
1832 | + * License as published by the Free Software Foundation. |
1833 | + * |
1834 | + * This program is distributed in the hope that it will be useful, |
1835 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1836 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1837 | + * General Public License for more details. |
1838 | + * |
1839 | + * You should have received a copy of the GNU Lesser General Public |
1840 | + * License along with this library; if not, write to the |
1841 | + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
1842 | + * Boston, MA 02110-1301, USA. |
1843 | + */ |
1844 | + |
1845 | +#ifndef TEST_FILENAME_MUTEX_H |
1846 | +#define TEST_FILENAME_MUTEX_H |
1847 | + |
1848 | +#include <QObject> |
1849 | +#include <ubuntu/download_manager/tests/base_testcase.h> |
1850 | +#include <ubuntu/download_manager/tests/test_runner.h> |
1851 | + |
1852 | +class TestFileNameMutex : public BaseTestCase { |
1853 | + Q_OBJECT |
1854 | + |
1855 | + public: |
1856 | + explicit TestFileNameMutex(QObject *parent = 0); |
1857 | + |
1858 | + private slots: // NOLINT(whitespace/indent) |
1859 | + |
1860 | + void testExpectedNameValid_data(); |
1861 | + void testExpectedNameValid(); |
1862 | + void testExpectedNameLocked_data(); |
1863 | + void testExpectedNameLocked(); |
1864 | + void testExpectedNameInFileSystem_data(); |
1865 | + void testExpectedNameInFileSystem(); |
1866 | + void testUnlockPresent(); |
1867 | +}; |
1868 | + |
1869 | +DECLARE_TEST(TestFileNameMutex) |
1870 | + |
1871 | +#endif // TEST_FILENAME_MUTEX_H |
1872 | |
1873 | === modified file 'ubuntu-download-manager-tests/ubuntu-download-manager-tests.pro' |
1874 | --- ubuntu-download-manager-tests/ubuntu-download-manager-tests.pro 2014-02-03 17:50:07 +0000 |
1875 | +++ ubuntu-download-manager-tests/ubuntu-download-manager-tests.pro 2014-02-22 10:42:10 +0000 |
1876 | @@ -28,7 +28,8 @@ |
1877 | downloads/state_machines/test_file_download_sm.cpp \ |
1878 | system/test_apn_request_factory.cpp \ |
1879 | downloads/test_mms_download.cpp \ |
1880 | - downloads/test_base_download.cpp |
1881 | + downloads/test_base_download.cpp \ |
1882 | + system/test_filename_mutex.cpp |
1883 | |
1884 | HEADERS += \ |
1885 | downloads/test_download.h \ |
1886 | @@ -48,7 +49,8 @@ |
1887 | downloads/state_machines/test_file_download_sm.h \ |
1888 | system/test_apn_request_factory.h \ |
1889 | downloads/test_mms_download.h \ |
1890 | - downloads/test_base_download.h |
1891 | + downloads/test_base_download.h \ |
1892 | + system/test_filename_mutex.h |
1893 | |
1894 | |
1895 | exists ($$OUT_PWD/data){ |
PASSED: Continuous integration, rev:240 jenkins. qa.ubuntu. com/job/ ubuntu- download- manager- ci/357/ jenkins. qa.ubuntu. com/job/ ubuntu- download- manager- trusty- amd64-ci/ 246 jenkins. qa.ubuntu. com/job/ ubuntu- download- manager- trusty- armhf-ci/ 246
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/ubuntu- download- manager- ci/357/ rebuild
http://