test_storage_adapter.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /* Any copyright is dedicated to the Public Domain.
  2. http://creativecommons.org/publicdomain/zero/1.0/ */
  3. Cu.import("resource://services-common/kinto-offline-client.js");
  4. // set up what we need to make storage adapters
  5. const Kinto = loadKinto();
  6. const FirefoxAdapter = Kinto.adapters.FirefoxAdapter;
  7. const kintoFilename = "kinto.sqlite";
  8. let gFirefoxAdapter = null;
  9. function do_get_kinto_adapter() {
  10. if (gFirefoxAdapter == null) {
  11. gFirefoxAdapter = new FirefoxAdapter("test");
  12. }
  13. return gFirefoxAdapter;
  14. }
  15. function do_get_kinto_db() {
  16. let profile = do_get_profile();
  17. let kintoDB = profile.clone();
  18. kintoDB.append(kintoFilename);
  19. return kintoDB;
  20. }
  21. function cleanup_kinto() {
  22. add_test(function cleanup_kinto_files(){
  23. let kintoDB = do_get_kinto_db();
  24. // clean up the db
  25. kintoDB.remove(false);
  26. // force re-creation of the adapter
  27. gFirefoxAdapter = null;
  28. run_next_test();
  29. });
  30. }
  31. function test_collection_operations() {
  32. add_task(function* test_kinto_clear() {
  33. let adapter = do_get_kinto_adapter();
  34. yield adapter.open();
  35. yield adapter.clear();
  36. yield adapter.close();
  37. });
  38. // test creating new records... and getting them again
  39. add_task(function* test_kinto_create_new_get_existing() {
  40. let adapter = do_get_kinto_adapter();
  41. yield adapter.open();
  42. let record = {id:"test-id", foo:"bar"};
  43. yield adapter.execute((transaction) => transaction.create(record));
  44. let newRecord = yield adapter.get("test-id");
  45. // ensure the record is the same as when it was added
  46. deepEqual(record, newRecord);
  47. yield adapter.close();
  48. });
  49. // test removing records
  50. add_task(function* test_kinto_can_remove_some_records() {
  51. let adapter = do_get_kinto_adapter();
  52. yield adapter.open();
  53. // create a second record
  54. let record = {id:"test-id-2", foo:"baz"};
  55. yield adapter.execute((transaction) => transaction.create(record));
  56. let newRecord = yield adapter.get("test-id-2");
  57. deepEqual(record, newRecord);
  58. // delete the record
  59. yield adapter.execute((transaction) => transaction.delete(record.id));
  60. newRecord = yield adapter.get(record.id);
  61. // ... and ensure it's no longer there
  62. do_check_eq(newRecord, undefined);
  63. // ensure the other record still exists
  64. newRecord = yield adapter.get("test-id");
  65. do_check_neq(newRecord, undefined);
  66. yield adapter.close();
  67. });
  68. // test getting records that don't exist
  69. add_task(function* test_kinto_get_non_existant() {
  70. let adapter = do_get_kinto_adapter();
  71. yield adapter.open();
  72. // Kinto expects adapters to either:
  73. let newRecord = yield adapter.get("missing-test-id");
  74. // resolve with an undefined record
  75. do_check_eq(newRecord, undefined);
  76. yield adapter.close();
  77. });
  78. // test updating records... and getting them again
  79. add_task(function* test_kinto_update_get_existing() {
  80. let adapter = do_get_kinto_adapter();
  81. yield adapter.open();
  82. let originalRecord = {id:"test-id", foo:"bar"};
  83. let updatedRecord = {id:"test-id", foo:"baz"};
  84. yield adapter.clear();
  85. yield adapter.execute((transaction) => transaction.create(originalRecord));
  86. yield adapter.execute((transaction) => transaction.update(updatedRecord));
  87. // ensure the record exists
  88. let newRecord = yield adapter.get("test-id");
  89. // ensure the record is the same as when it was added
  90. deepEqual(updatedRecord, newRecord);
  91. yield adapter.close();
  92. });
  93. // test listing records
  94. add_task(function* test_kinto_list() {
  95. let adapter = do_get_kinto_adapter();
  96. yield adapter.open();
  97. let originalRecord = {id:"test-id-1", foo:"bar"};
  98. let records = yield adapter.list();
  99. do_check_eq(records.length, 1);
  100. yield adapter.execute((transaction) => transaction.create(originalRecord));
  101. records = yield adapter.list();
  102. do_check_eq(records.length, 2);
  103. yield adapter.close();
  104. });
  105. // test aborting transaction
  106. add_task(function* test_kinto_aborting_transaction() {
  107. let adapter = do_get_kinto_adapter();
  108. yield adapter.open();
  109. yield adapter.clear();
  110. let record = {id: 1, foo: "bar"};
  111. let error = null;
  112. try {
  113. yield adapter.execute((transaction) => {
  114. transaction.create(record);
  115. throw new Error("unexpected");
  116. });
  117. } catch (e) {
  118. error = e;
  119. }
  120. do_check_neq(error, null);
  121. records = yield adapter.list();
  122. do_check_eq(records.length, 0);
  123. yield adapter.close();
  124. });
  125. // test save and get last modified
  126. add_task(function* test_kinto_last_modified() {
  127. const initialValue = 0;
  128. const intendedValue = 12345678;
  129. let adapter = do_get_kinto_adapter();
  130. yield adapter.open();
  131. let lastModified = yield adapter.getLastModified();
  132. do_check_eq(lastModified, initialValue);
  133. let result = yield adapter.saveLastModified(intendedValue);
  134. do_check_eq(result, intendedValue);
  135. lastModified = yield adapter.getLastModified();
  136. do_check_eq(lastModified, intendedValue);
  137. // test saveLastModified parses values correctly
  138. result = yield adapter.saveLastModified(" " + intendedValue + " blah");
  139. // should resolve with the parsed int
  140. do_check_eq(result, intendedValue);
  141. // and should have saved correctly
  142. lastModified = yield adapter.getLastModified();
  143. do_check_eq(lastModified, intendedValue);
  144. yield adapter.close();
  145. });
  146. // test loadDump(records)
  147. add_task(function* test_kinto_import_records() {
  148. let adapter = do_get_kinto_adapter();
  149. yield adapter.open();
  150. let record1 = {id: 1, foo: "bar"};
  151. let record2 = {id: 2, foo: "baz"};
  152. let impactedRecords = yield adapter.loadDump([
  153. record1, record2
  154. ]);
  155. do_check_eq(impactedRecords.length, 2);
  156. let newRecord1 = yield adapter.get("1");
  157. // ensure the record is the same as when it was added
  158. deepEqual(record1, newRecord1);
  159. let newRecord2 = yield adapter.get("2");
  160. // ensure the record is the same as when it was added
  161. deepEqual(record2, newRecord2);
  162. yield adapter.close();
  163. });
  164. add_task(function* test_kinto_import_records_should_override_existing() {
  165. let adapter = do_get_kinto_adapter();
  166. yield adapter.open();
  167. yield adapter.clear();
  168. records = yield adapter.list();
  169. do_check_eq(records.length, 0);
  170. let impactedRecords = yield adapter.loadDump([
  171. {id: 1, foo: "bar"},
  172. {id: 2, foo: "baz"},
  173. ]);
  174. do_check_eq(impactedRecords.length, 2);
  175. yield adapter.loadDump([
  176. {id: 1, foo: "baz"},
  177. {id: 3, foo: "bab"},
  178. ]);
  179. records = yield adapter.list();
  180. do_check_eq(records.length, 3);
  181. let newRecord1 = yield adapter.get("1");
  182. deepEqual(newRecord1.foo, "baz");
  183. yield adapter.close();
  184. });
  185. add_task(function* test_import_updates_lastModified() {
  186. let adapter = do_get_kinto_adapter();
  187. yield adapter.open();
  188. yield adapter.loadDump([
  189. {id: 1, foo: "bar", last_modified: 1457896541},
  190. {id: 2, foo: "baz", last_modified: 1458796542},
  191. ]);
  192. let lastModified = yield adapter.getLastModified();
  193. do_check_eq(lastModified, 1458796542);
  194. yield adapter.close();
  195. });
  196. add_task(function* test_import_preserves_older_lastModified() {
  197. let adapter = do_get_kinto_adapter();
  198. yield adapter.open();
  199. yield adapter.saveLastModified(1458796543);
  200. yield adapter.loadDump([
  201. {id: 1, foo: "bar", last_modified: 1457896541},
  202. {id: 2, foo: "baz", last_modified: 1458796542},
  203. ]);
  204. let lastModified = yield adapter.getLastModified();
  205. do_check_eq(lastModified, 1458796543);
  206. yield adapter.close();
  207. });
  208. }
  209. // test kinto db setup and operations in various scenarios
  210. // test from scratch - no current existing database
  211. add_test(function test_db_creation() {
  212. add_test(function test_create_from_scratch() {
  213. // ensure the file does not exist in the profile
  214. let kintoDB = do_get_kinto_db();
  215. do_check_false(kintoDB.exists());
  216. run_next_test();
  217. });
  218. test_collection_operations();
  219. cleanup_kinto();
  220. run_next_test();
  221. });
  222. // this is the closest we can get to a schema version upgrade at v1 - test an
  223. // existing database
  224. add_test(function test_creation_from_empty_db() {
  225. add_test(function test_create_from_empty_db() {
  226. // place an empty kinto db file in the profile
  227. let profile = do_get_profile();
  228. let kintoDB = do_get_kinto_db();
  229. let emptyDB = do_get_file("test_storage_adapter/empty.sqlite");
  230. emptyDB.copyTo(profile,kintoFilename);
  231. run_next_test();
  232. });
  233. test_collection_operations();
  234. cleanup_kinto();
  235. run_next_test();
  236. });
  237. function run_test() {
  238. run_next_test();
  239. }