delta.test.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. const delta_registry_1 = require("./delta_registry");
  4. const test_helpers_1 = require("./util/test_helpers");
  5. const assert_1 = require("./util/assert");
  6. describe("Primitive Delta", () => {
  7. it("Delete/delete node conflict", () => {
  8. const registry = new delta_registry_1.DeltaRegistry();
  9. const getId = (0, test_helpers_1.mockUuid)();
  10. const creation = registry.newNodeCreation(getId());
  11. (0, assert_1.assert)(creation.conflictsWith.length === 0, "did not expect node creation to be conflicting with any other operation");
  12. const deletion1 = registry.newNodeDeletion(creation, [], []);
  13. (0, assert_1.assert)(deletion1.conflictsWith.length === 0, "did not expect first deletion alone to be conflicting with anything");
  14. const deletion2 = registry.newNodeDeletion(creation, [], []);
  15. (0, assert_1.assert)(deletion1 === deletion2, "expected deltas to be identical");
  16. (0, assert_1.assert)(deletion1.conflictsWith.length === 0, "expected no conflicts");
  17. (0, assert_1.assert)(deletion1.hash.equals(deletion2.hash), "deletions should have equal hash");
  18. });
  19. it("Create/create edge conflict", () => {
  20. const registry = new delta_registry_1.DeltaRegistry();
  21. const getId = (0, test_helpers_1.mockUuid)();
  22. const sourceCreation = registry.newNodeCreation(getId());
  23. const target1Creation = registry.newNodeCreation(getId());
  24. const target2Creation = registry.newNodeCreation(getId());
  25. const edge1Creation = registry.newEdgeUpdate(sourceCreation.createOutgoingEdge("label"), target1Creation);
  26. (0, assert_1.assert)(edge1Creation.conflictsWith.length === 0, "expected a single edge alone to not be involved in conflicts");
  27. const edge2Creation = registry.newEdgeUpdate(sourceCreation.createOutgoingEdge("label"), target2Creation);
  28. (0, assert_1.assert)(edge1Creation.conflictsWith.length === 1, "expected conflict: same edge created twice, concurrently");
  29. (0, assert_1.assert)(edge2Creation.conflictsWith.length === 1, "expected conflict: same edge created twice, concurrently");
  30. });
  31. it("Update/update edge conflict", () => {
  32. const registry = new delta_registry_1.DeltaRegistry();
  33. const getId = (0, test_helpers_1.mockUuid)();
  34. const sourceCreation = registry.newNodeCreation(getId());
  35. const targetCreation = registry.newNodeCreation(getId());
  36. const newTarget1Creation = registry.newNodeCreation(getId());
  37. const newTarget2Creation = registry.newNodeCreation(getId());
  38. const edgeCreation = registry.newEdgeUpdate(sourceCreation.createOutgoingEdge("label"), targetCreation);
  39. const update1 = registry.newEdgeUpdate(edgeCreation.overwrite(), newTarget1Creation);
  40. (0, assert_1.assert)(update1.conflictsWith.length === 0, "expected no conflict with a single edge update.");
  41. const update2 = registry.newEdgeUpdate(edgeCreation.overwrite(), newTarget2Creation);
  42. (0, assert_1.assert)(update1.conflictsWith.length === 1, "expected conflict between concurrent edge updates.");
  43. (0, assert_1.assert)(update2.conflictsWith.length === 1, "expected conflict between concurrent edge updates.");
  44. });
  45. it("Delete/require (edge source) conflict", () => {
  46. const registry = new delta_registry_1.DeltaRegistry();
  47. const getId = (0, test_helpers_1.mockUuid)();
  48. const sourceCreation = registry.newNodeCreation(getId());
  49. const targetCreation = registry.newNodeCreation(getId());
  50. const sourceDeletion = registry.newNodeDeletion(sourceCreation, [], []);
  51. (0, assert_1.assert)(sourceDeletion.conflictsWith.length === 0, "expected no conflicts so far");
  52. const edgeCreation = registry.newEdgeUpdate(sourceCreation.createOutgoingEdge("label"), targetCreation);
  53. (0, assert_1.assert)(edgeCreation.conflictsWith.length === 1, "expected require/delete conflict, because edge source is concurrently deleted");
  54. (0, assert_1.assert)(sourceDeletion.conflictsWith.length === 1, "expected require/delete conflict, because edge source is concurrently deleted");
  55. });
  56. it("Delete/require (edge source) conflict (reverse order)", () => {
  57. const registry = new delta_registry_1.DeltaRegistry();
  58. const getId = (0, test_helpers_1.mockUuid)();
  59. // same as before, but now the 'order' of edgeCreation and sourceDeletion is reversed.
  60. const sourceCreation = registry.newNodeCreation(getId());
  61. const targetCreation = registry.newNodeCreation(getId());
  62. const edgeCreation = registry.newEdgeUpdate(sourceCreation.createOutgoingEdge("label"), targetCreation);
  63. (0, assert_1.assert)(edgeCreation.conflictsWith.length === 0, "expected no conflicts so far");
  64. const sourceDeletion = registry.newNodeDeletion(sourceCreation, [], []);
  65. (0, assert_1.assert)(edgeCreation.conflictsWith.length === 1, "expected require/delete conflict, because edge source is concurrently deleted");
  66. (0, assert_1.assert)(sourceDeletion.conflictsWith.length === 1, "expected require/delete conflict, because edge source is concurrently deleted");
  67. });
  68. it("Require (edge source), then delete (no conflict)", () => {
  69. const registry = new delta_registry_1.DeltaRegistry();
  70. const getId = (0, test_helpers_1.mockUuid)();
  71. // proper way of deleting the source of an edge: the deletion must depend on the edgeCreation
  72. const sourceCreation = registry.newNodeCreation(getId());
  73. const targetCreation = registry.newNodeCreation(getId());
  74. const edgeCreation = registry.newEdgeUpdate(sourceCreation.createOutgoingEdge("label"), targetCreation);
  75. const edgeDeletion = registry.newEdgeUpdate(edgeCreation.overwrite(), null);
  76. const sourceDeletion = registry.newNodeDeletion(sourceCreation, [edgeDeletion], []);
  77. (0, assert_1.assert)(sourceDeletion.conflictsWith.length === 0, "Since node deletion was aware of outgoing edge deletion, there should be no conflict");
  78. });
  79. it("Delete/require (edge source) conflict (3)", () => {
  80. const registry = new delta_registry_1.DeltaRegistry();
  81. const getId = (0, test_helpers_1.mockUuid)();
  82. // Same as (2), really, because the additional EdgeUpdate doesn't change anything.
  83. // Only the earliest conflict, between EdgeCreation and source NodeDeletion, matters.
  84. const sourceCreation = registry.newNodeCreation(getId());
  85. const targetCreation = registry.newNodeCreation(getId());
  86. const edgeCreation = registry.newEdgeUpdate(sourceCreation.createOutgoingEdge("label"), targetCreation);
  87. const newTargetCreation = registry.newNodeCreation(getId());
  88. const edgeUpdate = registry.newEdgeUpdate(edgeCreation.overwrite(), newTargetCreation);
  89. // no conflicts so far
  90. const sourceDeletion = registry.newNodeDeletion(sourceCreation, [], []);
  91. (0, assert_1.assert)(edgeCreation.conflictsWith.length === 1, "expected require/delete conflict, because edge source is concurrently deleted");
  92. (0, assert_1.assert)(sourceDeletion.conflictsWith.length === 1, "expected require/delete conflict, because edge source is concurrently deleted");
  93. (0, assert_1.assert)(edgeUpdate.conflictsWith.length === 0, "edge update should not be involved in any conflict");
  94. });
  95. it("Update edge after deletion of source node conflict", () => {
  96. const registry = new delta_registry_1.DeltaRegistry();
  97. const getId = (0, test_helpers_1.mockUuid)();
  98. // create edge between 2 nodes, and then properly delete the source node
  99. const sourceCreation = registry.newNodeCreation(getId());
  100. const targetCreation = registry.newNodeCreation(getId());
  101. const edgeCreation = registry.newEdgeUpdate(sourceCreation.createOutgoingEdge("label"), targetCreation);
  102. const edgeDeletion = registry.newEdgeUpdate(edgeCreation.overwrite(), null);
  103. const sourceDeletion = registry.newNodeDeletion(sourceCreation, [edgeDeletion], []);
  104. // no conflicts so far
  105. const newTargetCreation = registry.newNodeCreation(getId()); // no conflict
  106. const edgeUpdate = registry.newEdgeUpdate(edgeCreation.overwrite(), newTargetCreation);
  107. // console.log("edgeUpdate.conflictsWith", edgeUpdate.conflictsWith, "edgeDeletion.conflictsWith", edgeDeletion.conflictsWith);
  108. (0, assert_1.assert)(edgeUpdate.conflictsWith.length === 2, "expected U/U conflict");
  109. (0, assert_1.assert)(edgeUpdate.conflictsWith.some(([d]) => d === edgeDeletion), "expected U/U conflict");
  110. (0, assert_1.assert)(edgeUpdate.conflictsWith.some(([d]) => d === sourceDeletion), "expected U/U conflict");
  111. (0, assert_1.assert)(edgeDeletion.conflictsWith.length === 1, "expected U/U conflict");
  112. (0, assert_1.assert)(edgeDeletion.conflictsWith.some(([d]) => d === edgeUpdate), "expected U/U conflict");
  113. });
  114. it("Delete/require (edge target) conflict", () => {
  115. const registry = new delta_registry_1.DeltaRegistry();
  116. const getId = (0, test_helpers_1.mockUuid)();
  117. const sourceCreation = registry.newNodeCreation(getId());
  118. const targetCreation = registry.newNodeCreation(getId());
  119. const targetDeletion = registry.newNodeDeletion(targetCreation, [], []);
  120. const edgeCreation = registry.newEdgeUpdate(sourceCreation.createOutgoingEdge("label"), targetCreation);
  121. (0, assert_1.assert)(edgeCreation.conflictsWith.length === 1, "expected require/delete conflict");
  122. (0, assert_1.assert)(targetDeletion.conflictsWith.length === 1, "expected require/delete conflict");
  123. });
  124. it("Delete/require (edge target) conflict (reverse order)", () => {
  125. const registry = new delta_registry_1.DeltaRegistry();
  126. const getId = (0, test_helpers_1.mockUuid)();
  127. const sourceCreation = registry.newNodeCreation(getId());
  128. const targetCreation = registry.newNodeCreation(getId());
  129. const edgeCreation = registry.newEdgeUpdate(sourceCreation.createOutgoingEdge("label"), targetCreation);
  130. // delete target of edge, unaware that edge exists:
  131. const targetDeletion = registry.newNodeDeletion(targetCreation, [], []);
  132. (0, assert_1.assert)(edgeCreation.conflictsWith.length === 1, "expected require/delete conflict");
  133. (0, assert_1.assert)(targetDeletion.conflictsWith.length === 1, "expected require/delete conflict");
  134. });
  135. it("Require (edge target), then delete (no conflict)", () => {
  136. const registry = new delta_registry_1.DeltaRegistry();
  137. const getId = (0, test_helpers_1.mockUuid)();
  138. const sourceCreation = registry.newNodeCreation(getId());
  139. const targetCreation = registry.newNodeCreation(getId());
  140. const edgeCreation = registry.newEdgeUpdate(sourceCreation.createOutgoingEdge("label"), targetCreation);
  141. const edgeUpdate = registry.newEdgeUpdate(edgeCreation.overwrite(), sourceCreation); // turn edge into self-edge
  142. // because of the edgeUpdate, 'target' is no longer the target of the edge, and can be deleted:
  143. const targetDeletion = registry.newNodeDeletion(targetCreation, [], [edgeUpdate]);
  144. // console.log(edgeCreation.conflictsWith)
  145. (0, assert_1.assert)(edgeCreation.conflictsWith.length === 0, "expected no require/delete conflict");
  146. (0, assert_1.assert)(targetDeletion.conflictsWith.length === 0, "expected no require/delete conflict");
  147. });
  148. it("Delete source and target of edge (no conflict)", () => {
  149. const registry = new delta_registry_1.DeltaRegistry();
  150. const getId = (0, test_helpers_1.mockUuid)();
  151. const sourceCreation = registry.newNodeCreation(getId());
  152. const targetCreation = registry.newNodeCreation(getId());
  153. const edgeCreation = registry.newEdgeUpdate(sourceCreation.createOutgoingEdge("label"), targetCreation);
  154. const edgeDeletion = registry.newEdgeUpdate(edgeCreation.overwrite(), null);
  155. const sourceDeletion = registry.newNodeDeletion(sourceCreation, [edgeDeletion], []);
  156. (0, assert_1.assert)(sourceDeletion.conflictsWith.length === 0, "expected no conflicts");
  157. const targetDeletion = registry.newNodeDeletion(targetCreation, [], [edgeDeletion]);
  158. (0, assert_1.assert)(targetDeletion.conflictsWith.length === 0, "expected no conflicts");
  159. });
  160. it("Delete node with self-edge", () => {
  161. const registry = new delta_registry_1.DeltaRegistry();
  162. const getId = (0, test_helpers_1.mockUuid)();
  163. const nodeCreation = registry.newNodeCreation(getId());
  164. const edgeCreation = registry.newEdgeUpdate(nodeCreation.createOutgoingEdge("label"), nodeCreation);
  165. const edgeDeletion = registry.newEdgeUpdate(edgeCreation.overwrite(), null);
  166. const nodeDeletion = registry.newNodeDeletion(nodeCreation, [edgeDeletion], [edgeDeletion]);
  167. // console.log(nodeDeletion.conflictsWith);
  168. (0, assert_1.assert)(nodeDeletion.conflictsWith.length === 0, "expected no conflicts");
  169. });
  170. it("Read/write conflict", () => {
  171. const registry = new delta_registry_1.DeltaRegistry();
  172. const getId = (0, test_helpers_1.mockUuid)();
  173. const envCreation = registry.newNodeCreation(getId());
  174. const xInitial = registry.newEdgeUpdate(envCreation.createOutgoingEdge("x"), 1);
  175. const yInitial = registry.newEdgeUpdate(envCreation.createOutgoingEdge("y"), 2);
  176. // so now, x == 1, y == 2
  177. // then, x := x + 1
  178. const xUpdate = registry.newEdgeUpdate(xInitial.overwrite(), 2, [xInitial.overwrite()]);
  179. // and concurrently, y := x + y
  180. const yUpdate = registry.newEdgeUpdate(yInitial.overwrite(), 3, [xInitial.overwrite(), yInitial.overwrite()]);
  181. (0, assert_1.assert)(xUpdate.conflictsWith.length === 1 && yUpdate.conflictsWith.length === 1, "expected one conflict");
  182. (0, assert_1.assert)(xUpdate.conflictsWith.some(([d]) => d === yUpdate), "expected one conflict");
  183. });
  184. it("No Read/Read conflict", () => {
  185. const registry = new delta_registry_1.DeltaRegistry();
  186. const getId = (0, test_helpers_1.mockUuid)();
  187. const envCreation = registry.newNodeCreation(getId());
  188. const xInitial = registry.newEdgeUpdate(envCreation.createOutgoingEdge("x"), 1);
  189. // so now, x == 1
  190. // then, y := x + 1
  191. const yInitial = registry.newEdgeUpdate(envCreation.createOutgoingEdge("y"), 2, [xInitial.overwrite()]);
  192. // and concurrently, z := x + 2
  193. const zInitial = registry.newEdgeUpdate(envCreation.createOutgoingEdge("z"), 3, [xInitial.overwrite()]);
  194. (0, assert_1.assert)(yInitial.conflictsWith.length === 0 && zInitial.conflictsWith.length === 0, "expected no conflicts");
  195. });
  196. it("R*/U conflict", () => {
  197. const registry = new delta_registry_1.DeltaRegistry();
  198. const getId = (0, test_helpers_1.mockUuid)();
  199. const collection = registry.newNodeCreation(getId());
  200. const newEdge = collection.createOutgoingEdge("x");
  201. (0, assert_1.assert)(newEdge === collection.createOutgoingEdge("x"), "Should return same object");
  202. const addItemX = registry.newEdgeUpdate(newEdge, "x");
  203. (0, assert_1.assert)(newEdge === collection.createOutgoingEdge("x"), "Should return same object");
  204. (0, assert_1.assert)(addItemX.conflictsWith.length === 0, "No conflicts so far");
  205. // Now we'll create our conflict:
  206. const readAll = registry.newReadAllOutgoing(collection, [collection.createOutgoingEdge("x")]);
  207. const addItemY = registry.newEdgeUpdate(collection.createOutgoingEdge("y"), "y");
  208. console.log(collection);
  209. console.log(readAll.conflictsWith);
  210. console.log(addItemY.conflictsWith);
  211. (0, assert_1.assert)(readAll.conflictsWith.length === 1
  212. && addItemY.conflictsWith.length === 1, "Expected one conflict here");
  213. (0, assert_1.assert)(readAll.conflictsWith.some(([d]) => d === addItemY)
  214. && addItemY.conflictsWith.some(([d]) => d === readAll), "Expected 'addItemY' and 'readAll' to be conflicting");
  215. (0, assert_1.assert)(addItemX.conflictsWith.length === 0, "Still no conflicts here");
  216. });
  217. });
  218. //# sourceMappingURL=delta.test.js.map