toolkit/components/jsdownloads/test/unit/test_DownloadStore.js

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:3e8b63bdb207
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* Any copyright is dedicated to the Public Domain.
4 * http://creativecommons.org/publicdomain/zero/1.0/ */
5
6 /**
7 * Tests the DownloadStore object.
8 */
9
10 "use strict";
11
12 ////////////////////////////////////////////////////////////////////////////////
13 //// Globals
14
15 XPCOMUtils.defineLazyModuleGetter(this, "DownloadStore",
16 "resource://gre/modules/DownloadStore.jsm");
17 XPCOMUtils.defineLazyModuleGetter(this, "OS",
18 "resource://gre/modules/osfile.jsm")
19
20 /**
21 * Returns a new DownloadList object with an associated DownloadStore.
22 *
23 * @param aStorePath
24 * String pointing to the file to be associated with the DownloadStore,
25 * or undefined to use a non-existing temporary file. In this case, the
26 * temporary file is deleted when the test file execution finishes.
27 *
28 * @return {Promise}
29 * @resolves Array [ Newly created DownloadList , associated DownloadStore ].
30 * @rejects JavaScript exception.
31 */
32 function promiseNewListAndStore(aStorePath)
33 {
34 return promiseNewList().then(function (aList) {
35 let path = aStorePath || getTempFile(TEST_STORE_FILE_NAME).path;
36 let store = new DownloadStore(aList, path);
37 return [aList, store];
38 });
39 }
40
41 ////////////////////////////////////////////////////////////////////////////////
42 //// Tests
43
44 /**
45 * Saves downloads to a file, then reloads them.
46 */
47 add_task(function test_save_reload()
48 {
49 let [listForSave, storeForSave] = yield promiseNewListAndStore();
50 let [listForLoad, storeForLoad] = yield promiseNewListAndStore(
51 storeForSave.path);
52
53 listForSave.add(yield promiseNewDownload(httpUrl("source.txt")));
54 listForSave.add(yield Downloads.createDownload({
55 source: { url: httpUrl("empty.txt"),
56 referrer: TEST_REFERRER_URL },
57 target: getTempFile(TEST_TARGET_FILE_NAME),
58 }));
59
60 let legacyDownload = yield promiseStartLegacyDownload();
61 yield legacyDownload.cancel();
62 listForSave.add(legacyDownload);
63
64 yield storeForSave.save();
65 yield storeForLoad.load();
66
67 let itemsForSave = yield listForSave.getAll();
68 let itemsForLoad = yield listForLoad.getAll();
69
70 do_check_eq(itemsForSave.length, itemsForLoad.length);
71
72 // Downloads should be reloaded in the same order.
73 for (let i = 0; i < itemsForSave.length; i++) {
74 // The reloaded downloads are different objects.
75 do_check_neq(itemsForSave[i], itemsForLoad[i]);
76
77 // The reloaded downloads have the same properties.
78 do_check_eq(itemsForSave[i].source.url,
79 itemsForLoad[i].source.url);
80 do_check_eq(itemsForSave[i].source.referrer,
81 itemsForLoad[i].source.referrer);
82 do_check_eq(itemsForSave[i].target.path,
83 itemsForLoad[i].target.path);
84 do_check_eq(itemsForSave[i].saver.toSerializable(),
85 itemsForLoad[i].saver.toSerializable());
86 }
87 });
88
89 /**
90 * Checks that saving an empty list deletes any existing file.
91 */
92 add_task(function test_save_empty()
93 {
94 let [list, store] = yield promiseNewListAndStore();
95
96 let createdFile = yield OS.File.open(store.path, { create: true });
97 yield createdFile.close();
98
99 yield store.save();
100
101 do_check_false(yield OS.File.exists(store.path));
102
103 // If the file does not exist, saving should not generate exceptions.
104 yield store.save();
105 });
106
107 /**
108 * Checks that loading from a missing file results in an empty list.
109 */
110 add_task(function test_load_empty()
111 {
112 let [list, store] = yield promiseNewListAndStore();
113
114 do_check_false(yield OS.File.exists(store.path));
115
116 yield store.load();
117
118 let items = yield list.getAll();
119 do_check_eq(items.length, 0);
120 });
121
122 /**
123 * Loads downloads from a string in a predefined format. The purpose of this
124 * test is to verify that the JSON format used in previous versions can be
125 * loaded, assuming the file is reloaded on the same platform.
126 */
127 add_task(function test_load_string_predefined()
128 {
129 let [list, store] = yield promiseNewListAndStore();
130
131 // The platform-dependent file name should be generated dynamically.
132 let targetPath = getTempFile(TEST_TARGET_FILE_NAME).path;
133 let filePathLiteral = JSON.stringify(targetPath);
134 let sourceUriLiteral = JSON.stringify(httpUrl("source.txt"));
135 let emptyUriLiteral = JSON.stringify(httpUrl("empty.txt"));
136 let referrerUriLiteral = JSON.stringify(TEST_REFERRER_URL);
137
138 let string = "{\"list\":[{\"source\":" + sourceUriLiteral + "," +
139 "\"target\":" + filePathLiteral + "}," +
140 "{\"source\":{\"url\":" + emptyUriLiteral + "," +
141 "\"referrer\":" + referrerUriLiteral + "}," +
142 "\"target\":" + filePathLiteral + "}]}";
143
144 yield OS.File.writeAtomic(store.path,
145 new TextEncoder().encode(string),
146 { tmpPath: store.path + ".tmp" });
147
148 yield store.load();
149
150 let items = yield list.getAll();
151
152 do_check_eq(items.length, 2);
153
154 do_check_eq(items[0].source.url, httpUrl("source.txt"));
155 do_check_eq(items[0].target.path, targetPath);
156
157 do_check_eq(items[1].source.url, httpUrl("empty.txt"));
158 do_check_eq(items[1].source.referrer, TEST_REFERRER_URL);
159 do_check_eq(items[1].target.path, targetPath);
160 });
161
162 /**
163 * Loads downloads from a well-formed JSON string containing unrecognized data.
164 */
165 add_task(function test_load_string_unrecognized()
166 {
167 let [list, store] = yield promiseNewListAndStore();
168
169 // The platform-dependent file name should be generated dynamically.
170 let targetPath = getTempFile(TEST_TARGET_FILE_NAME).path;
171 let filePathLiteral = JSON.stringify(targetPath);
172 let sourceUriLiteral = JSON.stringify(httpUrl("source.txt"));
173
174 let string = "{\"list\":[{\"source\":null," +
175 "\"target\":null}," +
176 "{\"source\":{\"url\":" + sourceUriLiteral + "}," +
177 "\"target\":{\"path\":" + filePathLiteral + "}," +
178 "\"saver\":{\"type\":\"copy\"}}]}";
179
180 yield OS.File.writeAtomic(store.path,
181 new TextEncoder().encode(string),
182 { tmpPath: store.path + ".tmp" });
183
184 yield store.load();
185
186 let items = yield list.getAll();
187
188 do_check_eq(items.length, 1);
189
190 do_check_eq(items[0].source.url, httpUrl("source.txt"));
191 do_check_eq(items[0].target.path, targetPath);
192 });
193
194 /**
195 * Loads downloads from a malformed JSON string.
196 */
197 add_task(function test_load_string_malformed()
198 {
199 let [list, store] = yield promiseNewListAndStore();
200
201 let string = "{\"list\":[{\"source\":null,\"target\":null}," +
202 "{\"source\":{\"url\":\"about:blank\"}}}";
203
204 yield OS.File.writeAtomic(store.path, new TextEncoder().encode(string),
205 { tmpPath: store.path + ".tmp" });
206
207 try {
208 yield store.load();
209 do_throw("Exception expected when JSON data is malformed.");
210 } catch (ex if ex.name == "SyntaxError") {
211 do_print("The expected SyntaxError exception was thrown.");
212 }
213
214 let items = yield list.getAll();
215
216 do_check_eq(items.length, 0);
217 });
218
219 /**
220 * Saves downloads with unknown properties to a file and then reloads
221 * them to ensure that these properties are preserved.
222 */
223 add_task(function test_save_reload_unknownProperties()
224 {
225 let [listForSave, storeForSave] = yield promiseNewListAndStore();
226 let [listForLoad, storeForLoad] = yield promiseNewListAndStore(
227 storeForSave.path);
228
229 let download1 = yield promiseNewDownload(httpUrl("source.txt"));
230 // startTime should be ignored as it is a known property, and error
231 // is ignored by serialization
232 download1._unknownProperties = { peanut: "butter",
233 orange: "marmalade",
234 startTime: 77,
235 error: { message: "Passed" } };
236 listForSave.add(download1);
237
238 let download2 = yield promiseStartLegacyDownload();
239 yield download2.cancel();
240 download2._unknownProperties = { number: 5, object: { test: "string" } };
241 listForSave.add(download2);
242
243 let download3 = yield Downloads.createDownload({
244 source: { url: httpUrl("empty.txt"),
245 referrer: TEST_REFERRER_URL,
246 source1: "download3source1",
247 source2: "download3source2" },
248 target: { path: getTempFile(TEST_TARGET_FILE_NAME).path,
249 target1: "download3target1",
250 target2: "download3target2" },
251 saver : { type: "copy",
252 saver1: "download3saver1",
253 saver2: "download3saver2" },
254 });
255 listForSave.add(download3);
256
257 yield storeForSave.save();
258 yield storeForLoad.load();
259
260 let itemsForSave = yield listForSave.getAll();
261 let itemsForLoad = yield listForLoad.getAll();
262
263 do_check_eq(itemsForSave.length, itemsForLoad.length);
264
265 do_check_eq(Object.keys(itemsForLoad[0]._unknownProperties).length, 2);
266 do_check_eq(itemsForLoad[0]._unknownProperties.peanut, "butter");
267 do_check_eq(itemsForLoad[0]._unknownProperties.orange, "marmalade");
268 do_check_false("startTime" in itemsForLoad[0]._unknownProperties);
269 do_check_false("error" in itemsForLoad[0]._unknownProperties);
270
271 do_check_eq(Object.keys(itemsForLoad[1]._unknownProperties).length, 2);
272 do_check_eq(itemsForLoad[1]._unknownProperties.number, 5);
273 do_check_eq(itemsForLoad[1]._unknownProperties.object.test, "string");
274
275 do_check_eq(Object.keys(itemsForLoad[2].source._unknownProperties).length, 2);
276 do_check_eq(itemsForLoad[2].source._unknownProperties.source1,
277 "download3source1");
278 do_check_eq(itemsForLoad[2].source._unknownProperties.source2,
279 "download3source2");
280
281 do_check_eq(Object.keys(itemsForLoad[2].target._unknownProperties).length, 2);
282 do_check_eq(itemsForLoad[2].target._unknownProperties.target1,
283 "download3target1");
284 do_check_eq(itemsForLoad[2].target._unknownProperties.target2,
285 "download3target2");
286
287 do_check_eq(Object.keys(itemsForLoad[2].saver._unknownProperties).length, 2);
288 do_check_eq(itemsForLoad[2].saver._unknownProperties.saver1,
289 "download3saver1");
290 do_check_eq(itemsForLoad[2].saver._unknownProperties.saver2,
291 "download3saver2");
292 });
293
294 ////////////////////////////////////////////////////////////////////////////////
295 //// Termination
296
297 let tailFile = do_get_file("tail.js");
298 Services.scriptloader.loadSubScript(NetUtil.newURI(tailFile).spec);

mercurial