PageRenderTime 57ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/services/common/tests/unit/test_storageservice_client.js

https://github.com/edwindotcom/gecko-dev
JavaScript | 1381 lines | 1004 code | 363 blank | 14 comment | 20 complexity | 32a050b95618afb0c6f6a9bd681229e8 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, LGPL-3.0, MIT, AGPL-1.0, MPL-2.0-no-copyleft-exception, MPL-2.0, GPL-2.0, JSON, 0BSD, LGPL-2.1, BSD-2-Clause
  1. /* Any copyright is dedicated to the Public Domain.
  2. * http://creativecommons.org/publicdomain/zero/1.0/ */
  3. Cu.import("resource://services-common/storageservice.js");
  4. Cu.import("resource://testing-common/services-common/storageserver.js");
  5. function run_test() {
  6. initTestLogging("Trace");
  7. run_next_test();
  8. }
  9. function getRandomUser() {
  10. return "" + (Math.floor(Math.random() * 100000) + 1);
  11. }
  12. function getEmptyServer(user=getRandomUser(), password="password") {
  13. let users = {};
  14. users[user] = password;
  15. return storageServerForUsers(users, {
  16. meta: {},
  17. clients: {},
  18. crypto: {},
  19. });
  20. }
  21. function getClient(server, user=getRandomUser(), password="password") {
  22. let identity = server.server.identity;
  23. let url = identity.primaryScheme + "://" + identity.primaryHost + ":" +
  24. identity.primaryPort + "/2.0/" + user;
  25. let client = new StorageServiceClient(url);
  26. client.addListener({
  27. onDispatch: function onDispatch(request) {
  28. let up = user + ":" + password;
  29. request.request.setHeader("authorization", "Basic " + btoa(up));
  30. }
  31. });
  32. return client;
  33. }
  34. function getServerAndClient(user=getRandomUser(), password="password") {
  35. let server = getEmptyServer(user, password);
  36. let client = getClient(server, user, password);
  37. return [server, client, user, password];
  38. }
  39. add_test(function test_auth_failure_listener() {
  40. _("Ensure the onAuthFailure listener is invoked.");
  41. let server = getEmptyServer();
  42. let client = getClient(server, "324", "INVALID");
  43. client.addListener({
  44. onAuthFailure: function onAuthFailure(client, request) {
  45. _("onAuthFailure");
  46. server.stop(run_next_test);
  47. }
  48. });
  49. let request = client.getCollectionInfo();
  50. request.dispatch();
  51. });
  52. add_test(function test_duplicate_listeners() {
  53. _("Ensure that duplicate listeners aren't installed multiple times.");
  54. let server = getEmptyServer();
  55. let client = getClient(server, "1234567", "BAD_PASSWORD");
  56. let invokeCount = 0;
  57. let listener = {
  58. onAuthFailure: function onAuthFailure() {
  59. invokeCount++;
  60. }
  61. };
  62. client.addListener(listener);
  63. // No error expected.
  64. client.addListener(listener);
  65. let request = client.getCollectionInfo();
  66. request.dispatch(function onComplete() {
  67. do_check_eq(invokeCount, 1);
  68. server.stop(run_next_test);
  69. });
  70. });
  71. add_test(function test_handler_object() {
  72. _("Ensure that installed handlers get their callbacks invoked.");
  73. let [server, client] = getServerAndClient();
  74. let onCompleteCount = 0;
  75. let onDispatchCount = 0;
  76. let handler = {
  77. onComplete: function onComplete() {
  78. onCompleteCount++;
  79. do_check_eq(onDispatchCount, 1);
  80. do_check_eq(onCompleteCount, 1);
  81. server.stop(run_next_test);
  82. },
  83. onDispatch: function onDispatch() {
  84. onDispatchCount++;
  85. },
  86. };
  87. let request = client.getCollectionInfo();
  88. request.handler = handler;
  89. request.dispatch();
  90. });
  91. add_test(function test_info_collections() {
  92. _("Ensure requests to /info/collections work as expected.");
  93. let [server, client] = getServerAndClient();
  94. let request = client.getCollectionInfo();
  95. request.dispatch(function onComplete(error, req) {
  96. do_check_null(error);
  97. do_check_eq("object", typeof req.resultObj);
  98. do_check_attribute_count(req.resultObj, 3);
  99. do_check_true("meta" in req.resultObj);
  100. server.stop(run_next_test);
  101. });
  102. });
  103. add_test(function test_info_collections_conditional_not_modified() {
  104. _("Ensure conditional getCollectionInfo requests work.");
  105. let [server, client, username] = getServerAndClient();
  106. let user = server.user(username);
  107. let now = Date.now();
  108. user.createCollection("testcoll", {
  109. foo: new ServerBSO("foo", "payload", now)
  110. });
  111. let request = client.getCollectionInfo();
  112. request.locallyModifiedVersion = now + 10;
  113. request.dispatch(function onComplete(error, req) {
  114. do_check_null(error);
  115. do_check_true(req.notModified);
  116. server.stop(run_next_test);
  117. });
  118. });
  119. add_test(function test_info_collections_conditional_modified() {
  120. _("Ensure conditional getCollectionInfo requests work.");
  121. let [server, client, username] = getServerAndClient();
  122. let user = server.user(username);
  123. let now = Date.now();
  124. user.createCollection("testcoll", {
  125. foo: new ServerBSO("foo", "payload", now)
  126. });
  127. let request = client.getCollectionInfo();
  128. request.locallyModifiedVersion = now - 10;
  129. request.dispatch(function onComplete(error, req) {
  130. do_check_null(error);
  131. do_check_false(req.notModified);
  132. server.stop(run_next_test);
  133. });
  134. });
  135. add_test(function test_get_quota() {
  136. _("Ensure quota requests work.");
  137. let [server, client] = getServerAndClient();
  138. let request = client.getQuota();
  139. request.dispatch(function onComplete(error, req) {
  140. do_check_null(error);
  141. do_check_eq(req.resultObj.quota, 1048576);
  142. server.stop(run_next_test);
  143. });
  144. });
  145. add_test(function test_get_quota_conditional_not_modified() {
  146. _("Ensure conditional getQuota requests work.");
  147. let [server, client, username] = getServerAndClient();
  148. let user = server.user(username);
  149. let now = Date.now();
  150. user.createCollection("testcoll", {
  151. foo: new ServerBSO("foo", "payload", now)
  152. });
  153. let request = client.getQuota();
  154. request.locallyModifiedVersion = now + 10;
  155. request.dispatch(function onComplete(error, req) {
  156. do_check_null(error);
  157. do_check_true(req.notModified);
  158. server.stop(run_next_test);
  159. });
  160. });
  161. add_test(function test_get_quota_conditional_modified() {
  162. _("Ensure conditional getQuota requests work.");
  163. let [server, client, username] = getServerAndClient();
  164. let user = server.user(username);
  165. let now = Date.now();
  166. user.createCollection("testcoll", {
  167. foo: new ServerBSO("foo", "payload", now)
  168. });
  169. let request = client.getQuota();
  170. request.locallyModifiedVersion = now - 10;
  171. request.dispatch(function onComplete(error, req) {
  172. do_check_null(error);
  173. do_check_false(req.notModified);
  174. server.stop(run_next_test);
  175. });
  176. });
  177. add_test(function test_get_collection_usage() {
  178. _("Ensure info/collection_usage requests work.");
  179. let [server, client, username] = getServerAndClient();
  180. let user = server.user(username);
  181. user.createCollection("testcoll", {
  182. abc123: new ServerBSO("abc123", "payload", Date.now())
  183. });
  184. let request = client.getCollectionUsage();
  185. request.dispatch(function onComplete(error, req) {
  186. do_check_null(error);
  187. let usage = req.resultObj;
  188. do_check_true("testcoll" in usage);
  189. do_check_eq(usage.testcoll, "payload".length);
  190. server.stop(run_next_test);
  191. });
  192. });
  193. add_test(function test_get_usage_conditional_not_modified() {
  194. _("Ensure conditional getCollectionUsage requests work.");
  195. let [server, client, username] = getServerAndClient();
  196. let user = server.user(username);
  197. let now = Date.now();
  198. user.createCollection("testcoll", {
  199. foo: new ServerBSO("foo", "payload", now)
  200. });
  201. let request = client.getCollectionUsage();
  202. request.locallyModifiedVersion = now + 10;
  203. request.dispatch(function onComplete(error, req) {
  204. do_check_null(error);
  205. do_check_true(req.notModified);
  206. server.stop(run_next_test);
  207. });
  208. });
  209. add_test(function test_get_usage_conditional_modified() {
  210. _("Ensure conditional getCollectionUsage requests work.");
  211. let [server, client, username] = getServerAndClient();
  212. let user = server.user(username);
  213. let now = Date.now();
  214. user.createCollection("testcoll", {
  215. foo: new ServerBSO("foo", "payload", now)
  216. });
  217. let request = client.getCollectionUsage();
  218. request.locallyModifiedVersion = now - 10;
  219. request.dispatch(function onComplete(error, req) {
  220. do_check_null(error);
  221. do_check_false(req.notModified);
  222. server.stop(run_next_test);
  223. });
  224. });
  225. add_test(function test_get_collection_counts() {
  226. _("Ensure info/collection_counts requests work.");
  227. let [server, client, username] = getServerAndClient();
  228. let user = server.user(username);
  229. user.createCollection("testcoll", {
  230. foo: new ServerBSO("foo", "payload0", Date.now()),
  231. bar: new ServerBSO("bar", "payload1", Date.now())
  232. });
  233. let request = client.getCollectionCounts();
  234. request.dispatch(function onComplete(error, req) {
  235. do_check_null(error);
  236. let counts = req.resultObj;
  237. do_check_true("testcoll" in counts);
  238. do_check_eq(counts.testcoll, 2);
  239. server.stop(run_next_test);
  240. });
  241. });
  242. add_test(function test_get_counts_conditional_not_modified() {
  243. _("Ensure conditional getCollectionCounts requests work.");
  244. let [server, client, username] = getServerAndClient();
  245. let user = server.user(username);
  246. let now = Date.now();
  247. user.createCollection("testcoll", {
  248. foo: new ServerBSO("foo", "payload", now)
  249. });
  250. let request = client.getCollectionCounts();
  251. request.locallyModifiedVersion = now + 10;
  252. request.dispatch(function onComplete(error, req) {
  253. do_check_null(error);
  254. do_check_true(req.notModified);
  255. server.stop(run_next_test);
  256. });
  257. });
  258. add_test(function test_get_counts_conditional_modified() {
  259. _("Ensure conditional getCollectionCounts requests work.");
  260. let [server, client, username] = getServerAndClient();
  261. let user = server.user(username);
  262. let now = Date.now();
  263. user.createCollection("testcoll", {
  264. foo: new ServerBSO("foo", "payload", now)
  265. });
  266. let request = client.getCollectionCounts();
  267. request.locallyModifiedVersion = now - 10;
  268. request.dispatch(function onComplete(error, req) {
  269. do_check_null(error);
  270. do_check_false(req.notModified);
  271. server.stop(run_next_test);
  272. });
  273. });
  274. add_test(function test_get_collection_simple() {
  275. _("Ensure basic collection retrieval works.");
  276. let [server, client, username] = getServerAndClient();
  277. let user = server.user(username);
  278. user.createCollection("testcoll", {
  279. foo: new ServerBSO("foo", "payload0", Date.now()),
  280. bar: new ServerBSO("bar", "payload1", Date.now())
  281. });
  282. let request = client.getCollection("testcoll");
  283. let bsos = [];
  284. request.handler = {
  285. onBSORecord: function onBSORecord(request, bso) {
  286. bsos.push(bso);
  287. },
  288. onComplete: function onComplete(error, request) {
  289. do_check_null(error);
  290. do_check_eq(bsos.length, 2);
  291. do_check_eq(bsos[0], "foo");
  292. do_check_eq(bsos[1], "bar");
  293. server.stop(run_next_test);
  294. }
  295. };
  296. request.dispatch();
  297. });
  298. add_test(function test_get_collection_conditional_not_modified() {
  299. _("Ensure conditional requests with no new data to getCollection work.");
  300. let [server, client, username] = getServerAndClient();
  301. let user = server.user(username);
  302. let now = Date.now();
  303. user.createCollection("testcoll", {
  304. foo: new ServerBSO("foo", "payload0", now)
  305. });
  306. let request = client.getCollection("testcoll");
  307. request.locallyModifiedVersion = now + 1;
  308. request.dispatch(function onComplete(error, req) {
  309. do_check_null(error);
  310. do_check_true(req.notModified);
  311. server.stop(run_next_test);
  312. });
  313. });
  314. add_test(function test_get_collection_conditional_modified() {
  315. _("Ensure conditional requests with new data to getCollection work.");
  316. let [server, client, username] = getServerAndClient();
  317. let user = server.user(username);
  318. let now = Date.now();
  319. user.createCollection("testcoll", {
  320. foo: new ServerBSO("foo", "payload0", now)
  321. });
  322. let request = client.getCollection("testcoll");
  323. request.locallyModifiedVersion = now - 1;
  324. let bsoCount = 0;
  325. request.handler = {
  326. onBSORecord: function onBSORecord() {
  327. bsoCount++;
  328. },
  329. onComplete: function onComplete(error, req) {
  330. do_check_null(error);
  331. do_check_false(req.notModified);
  332. do_check_eq(bsoCount, 1);
  333. server.stop(run_next_test);
  334. }
  335. };
  336. request.dispatch();
  337. });
  338. // This is effectively a sanity test for query string generation.
  339. add_test(function test_get_collection_newer() {
  340. _("Ensure query string for newer and full work together.");
  341. let [server, client, username] = getServerAndClient();
  342. let date0 = Date.now();
  343. let date1 = date0 + 500;
  344. let user = server.user(username);
  345. user.createCollection("testcoll", {
  346. foo: new ServerBSO("foo", "payload0", date0),
  347. bar: new ServerBSO("bar", "payload1", date1)
  348. });
  349. let request = client.getCollection("testcoll");
  350. request.full = true;
  351. request.newer = date0;
  352. let bsos = [];
  353. request.handler = {
  354. onBSORecord: function onBSORecord(request, bso) {
  355. bsos.push(bso);
  356. },
  357. onComplete: function onComplete(error, req) {
  358. do_check_null(error);
  359. do_check_eq(bsos.length, 1);
  360. let bso = bsos[0];
  361. do_check_eq(bso.id, "bar");
  362. do_check_eq(bso.payload, "payload1");
  363. server.stop(run_next_test);
  364. }
  365. };
  366. request.dispatch();
  367. });
  368. add_test(function test_get_bso() {
  369. _("Ensure that simple BSO fetches work.");
  370. let [server, client, username] = getServerAndClient();
  371. server.createCollection(username, "testcoll", {
  372. abc123: new ServerBSO("abc123", "payload", Date.now())
  373. });
  374. let request = client.getBSO("testcoll", "abc123");
  375. request.dispatch(function(error, req) {
  376. do_check_null(error);
  377. do_check_true(req.resultObj instanceof BasicStorageObject);
  378. let bso = req.resultObj;
  379. do_check_eq(bso.id, "abc123");
  380. do_check_eq(bso.payload, "payload");
  381. server.stop(run_next_test);
  382. });
  383. });
  384. add_test(function test_bso_conditional() {
  385. _("Ensure conditional requests for an individual BSO work.");
  386. let [server, client, username] = getServerAndClient();
  387. let user = server.user(username);
  388. let now = Date.now();
  389. user.createCollection("testcoll", {
  390. foo: new ServerBSO("foo", "payload", now)
  391. });
  392. let request = client.getBSO("testcoll", "foo");
  393. request.locallyModifiedVersion = now;
  394. request.dispatch(function onComplete(error, req) {
  395. do_check_null(error);
  396. do_check_true(req.notModified);
  397. server.stop(run_next_test);
  398. });
  399. });
  400. add_test(function test_set_bso() {
  401. _("Ensure simple BSO PUT works.");
  402. let [server, client] = getServerAndClient();
  403. let id = "mnas08h3f3r2351";
  404. let bso = new BasicStorageObject(id, "testcoll");
  405. bso.payload = "my test payload";
  406. let request = client.setBSO(bso);
  407. request.dispatch(function(error, req) {
  408. do_check_eq(error, null);
  409. do_check_eq(req.resultObj, null);
  410. server.stop(run_next_test);
  411. });
  412. });
  413. add_test(function test_set_bso_conditional() {
  414. _("Ensure conditional setting a BSO is properly rejected.");
  415. let [server, client, username] = getServerAndClient();
  416. let user = server.user(username);
  417. let now = Date.now();
  418. user.createCollection("testcoll", {
  419. foo: new ServerBSO("foo", "payload0", now + 1000)
  420. });
  421. // Should get an mtime newer than server's.
  422. let bso = new BasicStorageObject("foo", "testcoll");
  423. bso.payload = "payload1";
  424. let request = client.setBSO(bso);
  425. request.locallyModifiedVersion = now;
  426. request.dispatch(function onComplete(error, req) {
  427. do_check_true(error instanceof StorageServiceRequestError);
  428. do_check_true(error.serverModified);
  429. server.stop(run_next_test);
  430. });
  431. });
  432. add_test(function test_set_bso_argument_errors() {
  433. _("Ensure BSO set detects invalid arguments.");
  434. let server = getEmptyServer();
  435. let bso = new BasicStorageObject();
  436. let client = getClient(server);
  437. let threw = false;
  438. try {
  439. client.setBSO(bso);
  440. } catch (ex) {
  441. threw = true;
  442. do_check_eq(ex.name, "Error");
  443. do_check_neq(ex.message.indexOf("does not have collection defined"), -1);
  444. } finally {
  445. do_check_true(threw);
  446. threw = false;
  447. }
  448. bso = new BasicStorageObject("id");
  449. try {
  450. client.setBSO(bso);
  451. } catch (ex) {
  452. threw = true;
  453. do_check_eq(ex.name, "Error");
  454. do_check_neq(ex.message.indexOf("does not have collection defined"), -1);
  455. } finally {
  456. do_check_true(threw);
  457. threw = false;
  458. }
  459. bso = new BasicStorageObject(null, "coll");
  460. try {
  461. client.setBSO(bso);
  462. } catch (ex) {
  463. threw = true;
  464. do_check_eq(ex.name, "Error");
  465. do_check_neq(ex.message.indexOf("does not have ID defined"), -1);
  466. } finally {
  467. do_check_true(threw);
  468. threw = false;
  469. }
  470. server.stop(run_next_test);
  471. });
  472. add_test(function test_set_bsos_simple() {
  473. _("Ensure setBSOs with basic options works.");
  474. let [server, client, username] = getServerAndClient();
  475. let user = server.user(username);
  476. let bso0 = new BasicStorageObject("foo");
  477. bso0.payload = "payload0";
  478. let bso1 = new BasicStorageObject("bar");
  479. bso1.payload = "payload1";
  480. let request = client.setBSOs("testcollection");
  481. request.addBSO(bso0);
  482. request.addBSO(bso1);
  483. request.dispatch(function onComplete(error, req) {
  484. do_check_null(error);
  485. let successful = req.successfulIDs;
  486. do_check_eq(successful.length, 2);
  487. do_check_eq(successful.indexOf(bso0.id), 0);
  488. do_check_true(successful.indexOf(bso1.id), 1);
  489. server.stop(run_next_test);
  490. });
  491. });
  492. add_test(function test_set_bsos_invalid_bso() {
  493. _("Ensure that adding an invalid BSO throws.");
  494. let server = getEmptyServer();
  495. let client = getClient(server);
  496. let request = client.setBSOs("testcoll");
  497. let threw = false;
  498. // Empty argument is invalid.
  499. try {
  500. request.addBSO(null);
  501. } catch (ex) {
  502. threw = true;
  503. } finally {
  504. do_check_true(threw);
  505. threw = false;
  506. }
  507. try {
  508. let bso = new BasicStorageObject();
  509. request.addBSO(bso);
  510. } catch (ex) {
  511. threw = true;
  512. } finally {
  513. do_check_true(threw);
  514. threw = false;
  515. }
  516. server.stop(run_next_test);
  517. });
  518. add_test(function test_set_bsos_newline() {
  519. _("Ensure that newlines in BSO payloads are formatted properly.");
  520. let [server, client, username] = getServerAndClient();
  521. let user = server.user(username);
  522. let request = client.setBSOs("testcoll");
  523. let bso0 = new BasicStorageObject("bso0");
  524. bso0.payload = "hello\nworld";
  525. request.addBSO(bso0);
  526. let bso1 = new BasicStorageObject("bso1");
  527. bso1.payload = "foobar";
  528. request.addBSO(bso1);
  529. request.dispatch(function onComplete(error, request) {
  530. do_check_null(error);
  531. do_check_eq(request.successfulIDs.length, 2);
  532. let coll = user.collection("testcoll");
  533. do_check_eq(coll.bso("bso0").payload, bso0.payload);
  534. do_check_eq(coll.bso("bso1").payload, bso1.payload);
  535. server.stop(run_next_test);
  536. });
  537. });
  538. add_test(function test_delete_bso_simple() {
  539. _("Ensure deletion of individual BSOs works.");
  540. let [server, client, username] = getServerAndClient();
  541. let user = server.user(username);
  542. let coll = user.createCollection("testcoll", {
  543. foo: new ServerBSO("foo", "payload0", Date.now()),
  544. bar: new ServerBSO("bar", "payload1", Date.now())
  545. });
  546. let request = client.deleteBSO("testcoll", "foo");
  547. request.dispatch(function onComplete(error, req) {
  548. do_check_null(error);
  549. do_check_eq(req.statusCode, 204);
  550. do_check_eq(coll.count(), 1);
  551. server.stop(run_next_test);
  552. });
  553. });
  554. add_test(function test_delete_bso_conditional_failed() {
  555. _("Ensure deletion of an individual BSO with older modification fails.");
  556. let [server, client, username] = getServerAndClient();
  557. let user = server.user(username);
  558. let now = Date.now();
  559. user.createCollection("testcoll", {
  560. foo: new ServerBSO("foo", "payload0", now)
  561. });
  562. let request = client.deleteBSO("testcoll", "foo");
  563. request.locallyModifiedVersion = now - 10;
  564. request.dispatch(function onComplete(error, req) {
  565. do_check_true(error instanceof StorageServiceRequestError);
  566. do_check_true(error.serverModified);
  567. server.stop(run_next_test);
  568. });
  569. });
  570. add_test(function test_delete_bso_conditional_success() {
  571. _("Ensure deletion of an individual BSO with newer modification works.");
  572. let [server, client, username] = getServerAndClient();
  573. let user = server.user(username);
  574. let now = Date.now();
  575. user.createCollection("testcoll", {
  576. foo: new ServerBSO("foo", "payload0", now)
  577. });
  578. let request = client.deleteBSO("testcoll", "foo");
  579. request.locallyModifiedVersion = now;
  580. request.dispatch(function onComplete(error, req) {
  581. do_check_null(error);
  582. do_check_eq(req.statusCode, 204);
  583. server.stop(run_next_test);
  584. });
  585. });
  586. add_test(function test_delete_bsos_simple() {
  587. _("Ensure deletion of multiple BSOs works.");
  588. let [server, client, username] = getServerAndClient();
  589. let user = server.user(username);
  590. let coll = user.createCollection("testcoll", {
  591. foo: new ServerBSO("foo", "payload0", Date.now()),
  592. bar: new ServerBSO("bar", "payload1", Date.now()),
  593. baz: new ServerBSO("baz", "payload2", Date.now())
  594. });
  595. let request = client.deleteBSOs("testcoll", ["foo", "baz"]);
  596. request.dispatch(function onComplete(error, req) {
  597. do_check_null(error);
  598. do_check_eq(req.statusCode, 204);
  599. do_check_eq(coll.count(), 1);
  600. server.stop(run_next_test);
  601. });
  602. });
  603. add_test(function test_delete_bsos_conditional_failed() {
  604. _("Ensure deletion of BSOs with server modifications fails.");
  605. let [server, client, username] = getServerAndClient();
  606. let user = server.user(username);
  607. let now = Date.now();
  608. let coll = user.createCollection("testcoll", {
  609. foo: new ServerBSO("foo", "payload0", now)
  610. });
  611. let request = client.deleteBSOs("testcoll", ["foo"]);
  612. request.locallyModifiedVersion = coll.timestamp - 1;
  613. request.dispatch(function onComplete(error, req) {
  614. do_check_true(error instanceof StorageServiceRequestError);
  615. do_check_true(error.serverModified);
  616. server.stop(run_next_test);
  617. });
  618. });
  619. add_test(function test_delete_bsos_conditional_success() {
  620. _("Ensure conditional deletion of BSOs without server modifications works.");
  621. let [server, client, username] = getServerAndClient();
  622. let user = server.user(username);
  623. let now = Date.now();
  624. let coll = user.createCollection("testcoll", {
  625. foo: new ServerBSO("foo", "payload0", now),
  626. bar: new ServerBSO("bar", "payload1", now - 10)
  627. });
  628. let request = client.deleteBSOs("testcoll", ["bar"]);
  629. request.locallyModifiedVersion = coll.timestamp;
  630. request.dispatch(function onComplete(error, req) {
  631. do_check_null(error);
  632. do_check_eq(req.statusCode, 204);
  633. server.stop(run_next_test);
  634. });
  635. });
  636. add_test(function test_delete_collection() {
  637. _("Ensure deleteCollection() works.");
  638. let [server, client, username] = getServerAndClient();
  639. let user = server.user(username);
  640. user.createCollection("testcoll", {
  641. foo: new ServerBSO("foo", "payload0", Date.now())
  642. });
  643. let request = client.deleteCollection("testcoll");
  644. request.dispatch(function onComplete(error, req) {
  645. do_check_null(error);
  646. do_check_eq(user.collection("testcoll", undefined));
  647. server.stop(run_next_test);
  648. });
  649. });
  650. add_test(function test_delete_collection_conditional_failed() {
  651. _("Ensure conditional deletes with server modifications fail.");
  652. let [server, client, username] = getServerAndClient();
  653. let user = server.user(username);
  654. let now = Date.now();
  655. let coll = user.createCollection("testcoll", {
  656. foo: new ServerBSO("foo", "payload0", now)
  657. });
  658. let request = client.deleteCollection("testcoll");
  659. request.locallyModifiedVersion = coll.timestamp - 1;
  660. request.dispatch(function onComplete(error, req) {
  661. do_check_true(error instanceof StorageServiceRequestError);
  662. do_check_true(error.serverModified);
  663. server.stop(run_next_test);
  664. });
  665. });
  666. add_test(function test_delete_collection_conditional_success() {
  667. _("Ensure conditional delete of collection works when it's supposed to.");
  668. let [server, client, username] = getServerAndClient();
  669. let user = server.user(username);
  670. let now = Date.now();
  671. let coll = user.createCollection("testcoll", {
  672. foo: new ServerBSO("foo", "payload0", now)
  673. });
  674. let request = client.deleteCollection("testcoll");
  675. request.locallyModifiedVersion = coll.timestamp;
  676. request.dispatch(function onComplete(error, req) {
  677. do_check_null(error);
  678. do_check_eq(user.collection("testcoll"), undefined);
  679. server.stop(run_next_test);
  680. });
  681. });
  682. add_test(function test_delete_collections() {
  683. _("Ensure deleteCollections() works.");
  684. let [server, client, username] = getServerAndClient();
  685. let user = server.user(username);
  686. user.createCollection("testColl", {
  687. foo: new ServerBSO("foo", "payload0", Date.now())
  688. });
  689. let request = client.deleteCollections();
  690. request.dispatch(function onComplete(error, req) {
  691. do_check_null(error);
  692. do_check_eq(user.collection("testcoll"), undefined);
  693. server.stop(run_next_test);
  694. });
  695. });
  696. add_test(function test_network_error_captured() {
  697. _("Ensure network errors are captured.");
  698. // Network errors should result in .networkError being set on request.
  699. let client = new StorageServiceClient("http://rnewman-is-splendid.badtld/");
  700. let request = client.getCollectionInfo();
  701. request.dispatch(function(error, req) {
  702. do_check_neq(error, null);
  703. do_check_neq(error.network, null);
  704. run_next_test();
  705. });
  706. });
  707. add_test(function test_network_error_listener() {
  708. _("Ensure the onNetworkError listener is invoked on network errors.");
  709. let listenerCalled = false;
  710. let client = new StorageServiceClient("http://philikon-is-too.badtld/");
  711. client.addListener({
  712. onNetworkError: function(client, request) {
  713. listenerCalled = true;
  714. }
  715. });
  716. let request = client.getCollectionInfo();
  717. request.dispatch(function() {
  718. do_check_true(listenerCalled);
  719. run_next_test();
  720. });
  721. });
  722. add_test(function test_batching_set_too_large() {
  723. _("Ensure we throw when attempting to add a BSO that is too large to fit.");
  724. let [server, client, username] = getServerAndClient();
  725. let request = client.setBSOsBatching("testcoll");
  726. let payload = "";
  727. // The actual length of the payload is a little less. But, this ensures we
  728. // exceed it.
  729. for (let i = 0; i < client.REQUEST_SIZE_LIMIT; i++) {
  730. payload += i;
  731. }
  732. let bso = new BasicStorageObject("bso");
  733. bso.payload = payload;
  734. do_check_throws(function add() { request.addBSO(bso); });
  735. server.stop(run_next_test);
  736. });
  737. add_test(function test_batching_set_basic() {
  738. _("Ensure batching set works with single requests.");
  739. let [server, client, username] = getServerAndClient();
  740. let request = client.setBSOsBatching("testcoll");
  741. for (let i = 0; i < 10; i++) {
  742. let bso = new BasicStorageObject("bso" + i);
  743. bso.payload = "payload" + i;
  744. request.addBSO(bso);
  745. }
  746. request.finish(function onFinish(request) {
  747. do_check_eq(request.successfulIDs.length, 10);
  748. let collection = server.user(username).collection("testcoll");
  749. do_check_eq(collection.timestamp, request.serverModifiedVersion);
  750. server.stop(run_next_test);
  751. });
  752. });
  753. add_test(function test_batching_set_batch_count() {
  754. _("Ensure multiple outgoing request batching works when count is exceeded.");
  755. let [server, client, username] = getServerAndClient();
  756. let requestCount = 0;
  757. server.callback.onRequest = function onRequest() {
  758. requestCount++;
  759. }
  760. let request = client.setBSOsBatching("testcoll");
  761. for (let i = 1; i <= 300; i++) {
  762. let bso = new BasicStorageObject("bso" + i);
  763. bso.payload = "XXXXXXX";
  764. request.addBSO(bso);
  765. }
  766. request.finish(function onFinish(request) {
  767. do_check_eq(request.successfulIDs.length, 300);
  768. do_check_eq(requestCount, 3);
  769. let collection = server.user(username).collection("testcoll");
  770. do_check_eq(collection.timestamp, request.serverModifiedVersion);
  771. server.stop(run_next_test);
  772. });
  773. });
  774. add_test(function test_batching_set_batch_size() {
  775. _("Ensure outgoing requests batch when size is exceeded.");
  776. let [server, client, username] = getServerAndClient();
  777. let requestCount = 0;
  778. server.callback.onRequest = function onRequest() {
  779. requestCount++;
  780. };
  781. let limit = client.REQUEST_SIZE_LIMIT;
  782. let request = client.setBSOsBatching("testcoll");
  783. // JavaScript: Y U NO EASY REPETITION FUNCTIONALITY?
  784. let data = [];
  785. for (let i = (limit / 2) - 100; i; i -= 1) {
  786. data.push("X");
  787. }
  788. let payload = data.join("");
  789. for (let i = 0; i < 4; i++) {
  790. let bso = new BasicStorageObject("bso" + i);
  791. bso.payload = payload;
  792. request.addBSO(bso);
  793. }
  794. request.finish(function onFinish(request) {
  795. do_check_eq(request.successfulIDs.length, 4);
  796. do_check_eq(requestCount, 2);
  797. let collection = server.user(username).collection("testcoll");
  798. do_check_eq(collection.timestamp, request.serverModifiedVersion);
  799. server.stop(run_next_test);
  800. });
  801. });
  802. add_test(function test_batching_set_flush() {
  803. _("Ensure flushing batch sets works.");
  804. let [server, client, username] = getServerAndClient();
  805. let requestCount = 0;
  806. server.callback.onRequest = function onRequest() {
  807. requestCount++;
  808. }
  809. let request = client.setBSOsBatching("testcoll");
  810. for (let i = 1; i < 101; i++) {
  811. let bso = new BasicStorageObject("bso" + i);
  812. bso.payload = "foo";
  813. request.addBSO(bso);
  814. if (i % 10 == 0) {
  815. request.flush();
  816. }
  817. }
  818. request.finish(function onFinish(request) {
  819. do_check_eq(request.successfulIDs.length, 100);
  820. do_check_eq(requestCount, 10);
  821. let collection = server.user(username).collection("testcoll");
  822. do_check_eq(collection.timestamp, request.serverModifiedVersion);
  823. server.stop(run_next_test);
  824. });
  825. });
  826. add_test(function test_batching_set_conditional_success() {
  827. _("Ensure conditional requests for batched sets work properly.");
  828. let [server, client, username] = getServerAndClient();
  829. let collection = server.user(username).createCollection("testcoll");
  830. let lastServerVersion = Date.now();
  831. collection.insertBSO(new ServerBSO("foo", "bar", lastServerVersion));
  832. collection.timestamp = lastServerVersion;
  833. do_check_eq(collection.timestamp, lastServerVersion);
  834. let requestCount = 0;
  835. server.callback.onRequest = function onRequest() {
  836. requestCount++;
  837. }
  838. let request = client.setBSOsBatching("testcoll");
  839. request.locallyModifiedVersion = collection.timestamp;
  840. for (let i = 1; i < 251; i++) {
  841. let bso = new BasicStorageObject("bso" + i);
  842. bso.payload = "foo" + i;
  843. request.addBSO(bso);
  844. }
  845. request.finish(function onFinish(request) {
  846. do_check_eq(requestCount, 3);
  847. do_check_eq(collection.timestamp, request.serverModifiedVersion);
  848. do_check_eq(collection.timestamp, request.locallyModifiedVersion);
  849. server.stop(run_next_test);
  850. });
  851. });
  852. add_test(function test_batching_set_initial_failure() {
  853. _("Ensure that an initial request failure setting BSOs is handled properly.");
  854. let [server, client, username] = getServerAndClient();
  855. let collection = server.user(username).createCollection("testcoll");
  856. collection.timestamp = Date.now();
  857. let requestCount = 0;
  858. server.callback.onRequest = function onRequest() {
  859. requestCount++;
  860. }
  861. let request = client.setBSOsBatching("testcoll");
  862. request.locallyModifiedVersion = collection.timestamp - 1;
  863. for (let i = 1; i < 250; i++) {
  864. let bso = new BasicStorageObject("bso" + i);
  865. bso.payload = "foo" + i;
  866. request.addBSO(bso);
  867. }
  868. request.finish(function onFinish(request) {
  869. do_check_eq(requestCount, 1);
  870. do_check_eq(request.successfulIDs.length, 0);
  871. do_check_eq(Object.keys(request.failures).length, 0);
  872. server.stop(run_next_test);
  873. });
  874. });
  875. add_test(function test_batching_set_subsequent_failure() {
  876. _("Ensure a non-initial failure during batching set is handled properly.");
  877. let [server, client, username] = getServerAndClient();
  878. let collection = server.user(username).createCollection("testcoll");
  879. collection.timestamp = Date.now();
  880. let requestCount = 0;
  881. server.callback.onRequest = function onRequest() {
  882. requestCount++;
  883. if (requestCount == 1) {
  884. return;
  885. }
  886. collection.timestamp++;
  887. }
  888. let request = client.setBSOsBatching("testcoll");
  889. request.locallyModifiedVersion = collection.timestamp;
  890. for (let i = 0; i < 250; i++) {
  891. let bso = new BasicStorageObject("bso" + i);
  892. bso.payload = "foo" + i;
  893. request.addBSO(bso);
  894. }
  895. request.finish(function onFinish(request) {
  896. do_check_eq(requestCount, 2);
  897. do_check_eq(request.successfulIDs.length, 100);
  898. do_check_eq(Object.keys(request.failures).length, 0);
  899. server.stop(run_next_test);
  900. });
  901. });
  902. function getBatchedDeleteData(collection="testcoll") {
  903. let [server, client, username] = getServerAndClient();
  904. let serverBSOs = {};
  905. for (let i = 1000; i; i -= 1) {
  906. serverBSOs["bso" + i] = new ServerBSO("bso" + i, "payload" + i);
  907. }
  908. let user = server.user(username);
  909. user.createCollection(collection, serverBSOs);
  910. return [server, client, username, collection];
  911. }
  912. add_test(function test_batched_delete_single() {
  913. _("Ensure batched delete with single request works.");
  914. let [server, client, username, collection] = getBatchedDeleteData();
  915. let requestCount = 0;
  916. server.callback.onRequest = function onRequest() {
  917. requestCount += 1;
  918. }
  919. let request = client.deleteBSOsBatching(collection);
  920. for (let i = 1; i < 51; i += 1) {
  921. request.addID("bso" + i);
  922. }
  923. request.finish(function onFinish(request) {
  924. do_check_eq(requestCount, 1);
  925. do_check_eq(request.errors.length, 0);
  926. let coll = server.user(username).collection(collection);
  927. do_check_eq(coll.count(), 950);
  928. do_check_eq(request.serverModifiedVersion, coll.timestamp);
  929. server.stop(run_next_test);
  930. });
  931. });
  932. add_test(function test_batched_delete_multiple() {
  933. _("Ensure batched delete splits requests properly.");
  934. let [server, client, username, collection] = getBatchedDeleteData();
  935. let requestCount = 0;
  936. server.callback.onRequest = function onRequest() {
  937. requestCount += 1;
  938. }
  939. let request = client.deleteBSOsBatching(collection);
  940. for (let i = 1; i < 251; i += 1) {
  941. request.addID("bso" + i);
  942. }
  943. request.finish(function onFinish(request) {
  944. do_check_eq(requestCount, 3);
  945. do_check_eq(request.errors.length, 0);
  946. let coll = server.user(username).collection(collection);
  947. do_check_eq(coll.count(), 750);
  948. do_check_eq(request.serverModifiedVersion, coll.timestamp);
  949. server.stop(run_next_test);
  950. });
  951. });
  952. add_test(function test_batched_delete_conditional_success() {
  953. _("Ensure conditional batched delete all work.");
  954. let [server, client, username, collection] = getBatchedDeleteData();
  955. let requestCount = 0;
  956. server.callback.onRequest = function onRequest() {
  957. requestCount++;
  958. }
  959. let serverCollection = server.user(username).collection(collection);
  960. let initialTimestamp = serverCollection.timestamp;
  961. let request = client.deleteBSOsBatching(collection);
  962. request.locallyModifiedVersion = initialTimestamp;
  963. for (let i = 1; i < 251; i += 1) {
  964. request.addID("bso" + 1);
  965. }
  966. request.finish(function onFinish(request) {
  967. do_check_eq(requestCount, 3);
  968. do_check_eq(request.errors.length, 0);
  969. do_check_true(request.locallyModifiedVersion > initialTimestamp);
  970. server.stop(run_next_test);
  971. });
  972. });
  973. add_test(function test_batched_delete_conditional_initial_failure() {
  974. _("Ensure conditional batched delete failure on initial request works.");
  975. // The client needs to issue multiple requests but the first one was
  976. // rejected. The client should only issue that initial request.
  977. let [server, client, username, collection] = getBatchedDeleteData();
  978. let requestCount = 0;
  979. server.callback.onRequest = function onRequest() {
  980. requestCount++;
  981. }
  982. let serverCollection = server.user(username).collection(collection);
  983. let request = client.deleteBSOsBatching(collection);
  984. request.locallyModifiedVersion = serverCollection.timestamp - 1;
  985. for (let i = 1; i < 251; i += 1) {
  986. request.addID("bso" + i);
  987. }
  988. request.finish(function onFinish(request) {
  989. do_check_eq(requestCount, 1);
  990. do_check_eq(request.errors.length, 1);
  991. server.stop(run_next_test);
  992. });
  993. });
  994. add_test(function test_batched_delete_conditional_subsequent_failure() {
  995. _("Ensure conditional batched delete failure on non-initial request.");
  996. let [server, client, username, collection] = getBatchedDeleteData();
  997. let serverCollection = server.user(username).collection(collection);
  998. let requestCount = 0;
  999. server.callback.onRequest = function onRequest() {
  1000. requestCount++;
  1001. if (requestCount <= 1) {
  1002. return;
  1003. }
  1004. // Advance collection's timestamp on subsequent requests so request is
  1005. // rejected.
  1006. serverCollection.timestamp++;
  1007. }
  1008. let request = client.deleteBSOsBatching(collection);
  1009. request.locallyModifiedVersion = serverCollection.timestamp;
  1010. for (let i = 1; i < 251; i += 1) {
  1011. request.addID("bso" + i);
  1012. }
  1013. request.finish(function onFinish(request) {
  1014. do_check_eq(requestCount, 2);
  1015. do_check_eq(request.errors.length, 1);
  1016. server.stop(run_next_test);
  1017. });
  1018. });