version.test.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. const _ = require("lodash");
  4. const version_1 = require("./version");
  5. const delta_registry_1 = require("./delta_registry");
  6. const test_helpers_1 = require("./util/test_helpers");
  7. const assert_1 = require("./util/assert");
  8. describe("Version", () => {
  9. it("Get deltas", () => {
  10. const deltaRegistry = new delta_registry_1.DeltaRegistry();
  11. const getId = (0, test_helpers_1.mockUuid)();
  12. const registry = new version_1.VersionRegistry();
  13. const nodeCreation = deltaRegistry.newNodeCreation(getId());
  14. const nodeDeletion = deltaRegistry.newNodeDeletion(nodeCreation, [], []);
  15. const version1 = registry.createVersion(registry.initialVersion, nodeCreation);
  16. const version2 = registry.createVersion(version1, nodeDeletion);
  17. (0, assert_1.assert)(_.isEqual([...registry.initialVersion], []), "expected initialVersion to be empty");
  18. (0, assert_1.assert)(_.isEqual([...version1], [nodeCreation]), "expected version1 to contain creation");
  19. (0, assert_1.assert)(_.isEqual([...version2], [nodeDeletion, nodeCreation]), "expected version2 to contain creation and deletion");
  20. });
  21. it("Commutating operations yield equal versions", () => {
  22. const deltaRegistry = new delta_registry_1.DeltaRegistry();
  23. const getId = (0, test_helpers_1.mockUuid)();
  24. const registry = new version_1.VersionRegistry();
  25. const nodeCreationA = deltaRegistry.newNodeCreation(getId());
  26. const nodeCreationB = deltaRegistry.newNodeCreation(getId());
  27. const versionA = registry.createVersion(registry.initialVersion, nodeCreationA);
  28. const versionAB = registry.createVersion(versionA, nodeCreationB);
  29. const versionB = registry.createVersion(registry.initialVersion, nodeCreationB);
  30. const versionBA = registry.createVersion(versionB, nodeCreationA);
  31. (0, assert_1.assert)(versionAB === versionBA, "expected versions to be equal");
  32. });
  33. it("Intersection", () => {
  34. const deltaRegistry = new delta_registry_1.DeltaRegistry();
  35. const getId = (0, test_helpers_1.mockUuid)();
  36. const registry = new version_1.VersionRegistry();
  37. const A = deltaRegistry.newNodeCreation(getId());
  38. const B = deltaRegistry.newNodeCreation(getId());
  39. const C = deltaRegistry.newNodeCreation(getId());
  40. const D = deltaRegistry.newNodeDeletion(A, [], []);
  41. const v1 = registry.quickVersion([D, B, A]);
  42. const v2 = registry.quickVersion([C, B]);
  43. const intersection0 = registry.getIntersection([v1, v2]);
  44. (0, assert_1.assert)(intersection0 === registry.quickVersion([B]), "expected intersection of v1 and v2 to be B.");
  45. const intersection1 = registry.getIntersection([v1, v1]);
  46. (0, assert_1.assert)(intersection1 === v1, "expected intersection of v1 with itself to be v1");
  47. const intersection2 = registry.getIntersection([v1]);
  48. (0, assert_1.assert)(intersection2 === v1, "expected intersection of v1 with itself to be v1");
  49. const intersection3 = registry.getIntersection([]);
  50. (0, assert_1.assert)(intersection3 === registry.initialVersion, "expected intersection of empty set to be initial (empty) version");
  51. });
  52. describe("Merging", () => {
  53. // Helper
  54. function mergeAgain(registry, merged, nameMap) {
  55. const mergedAgain = registry.merge(merged, nameMap);
  56. (0, assert_1.assert)(mergedAgain.length === merged.length
  57. && mergedAgain.every(version => merged.includes(version)), "merging a merge result should just give the same result again.");
  58. }
  59. it("Merge empty set", () => {
  60. const registry = new version_1.VersionRegistry();
  61. const merged = registry.merge([]);
  62. (0, assert_1.assert)(merged.length === 1 && merged[0] === registry.initialVersion, "expected intial version");
  63. mergeAgain(registry, merged);
  64. });
  65. it("Merge non-conflicting versions", () => {
  66. const deltaRegistry = new delta_registry_1.DeltaRegistry();
  67. const getId = (0, test_helpers_1.mockUuid)();
  68. const registry = new version_1.VersionRegistry();
  69. const nodeCreationA = deltaRegistry.newNodeCreation(getId());
  70. const nodeCreationB = deltaRegistry.newNodeCreation(getId());
  71. const versionA = registry.createVersion(registry.initialVersion, nodeCreationA);
  72. const versionB = registry.createVersion(registry.initialVersion, nodeCreationB);
  73. const nameMap = new Map([[nodeCreationA, "A"], [nodeCreationB, "B"]]);
  74. const merged = registry.merge([versionA, versionB], delta => nameMap.get(delta));
  75. (0, assert_1.assert)(merged.length === 1, "expected 1 merged version");
  76. const deltas = [...merged[0]];
  77. (0, assert_1.assert)(deltas.length === 2
  78. && deltas.includes(nodeCreationA)
  79. && deltas.includes(nodeCreationB), "expected merged version to contain nodes A and B");
  80. mergeAgain(registry, merged, delta => nameMap.get(delta));
  81. });
  82. it("Merge complex conflicting versions", () => {
  83. const deltaRegistry = new delta_registry_1.DeltaRegistry();
  84. const getId = (0, test_helpers_1.mockUuid)();
  85. const registry = new version_1.VersionRegistry();
  86. // the names of the deltas and the versions in this test trace back to an illustration in a Xournal++ file.
  87. const X = deltaRegistry.newNodeCreation(getId());
  88. const Y = deltaRegistry.newNodeCreation(getId());
  89. const Z = deltaRegistry.newNodeCreation(getId());
  90. const A = deltaRegistry.newNodeDeletion(X, [], []);
  91. const B = deltaRegistry.newEdgeUpdate(X.createOutgoingEdge("label"), Y); // conflicts with A
  92. (0, assert_1.assert)(_.isEqual(B.conflictsWith, [[A, 'U/D']]), "Expected B to conflict with A");
  93. const C = deltaRegistry.newEdgeUpdate(Y.createOutgoingEdge("label"), Z);
  94. const BB = deltaRegistry.newEdgeUpdate(B.overwrite(), null); // unset edge B.
  95. const D = deltaRegistry.newNodeDeletion(Y, [], [BB]); // conflicts with C
  96. (0, assert_1.assert)(_.isEqual(D.conflictsWith, [[C, 'U/D']]), "Expected D to conflict with C");
  97. const nameMap = new Map([
  98. [X, "X"],
  99. [Y, "Y"],
  100. [Z, "Z"],
  101. [A, "A"],
  102. [B, "B"],
  103. [BB, "BB"],
  104. [C, "C"],
  105. [D, "D"],
  106. ]);
  107. const three = registry.quickVersion([A, X, Y, Z]);
  108. const seven = registry.quickVersion([C, X, Y, Z]);
  109. const five = registry.quickVersion([D, BB, B, X, Y, Z]);
  110. const merged = registry.merge([three, seven, five], d => nameMap.get(d));
  111. (0, assert_1.assert)(merged.length === 3, "expected three maximal versions");
  112. (0, assert_1.assert)(merged.includes(registry.quickVersion([A, C, X, Y, Z])), "expected [X,Y,Z,A,C] to be a maximal version");
  113. (0, assert_1.assert)(merged.includes(registry.quickVersion([BB, B, C, X, Y, Z])), "expected [X,Y,Z,B,C] to be a maximal version");
  114. (0, assert_1.assert)(merged.includes(registry.quickVersion([D, BB, B, X, Y, Z])), "expected [X,Y,Z,B,D] to be a maximal version");
  115. mergeAgain(registry, merged, d => nameMap.get(d));
  116. });
  117. it("Merge many non-conflicting versions (scalability test)", () => {
  118. const deltaRegistry = new delta_registry_1.DeltaRegistry();
  119. const getId = (0, test_helpers_1.mockUuid)();
  120. const registry = new version_1.VersionRegistry();
  121. // Bunch of non-conflicting deltas:
  122. const deltas = [];
  123. const nameMap = new Map();
  124. for (let i = 0; i < 10; i++) {
  125. const delta = deltaRegistry.newNodeCreation(getId());
  126. deltas.push(delta);
  127. nameMap.set(delta, i.toString());
  128. }
  129. // Create a version for each delta, containing only that delta:
  130. const versions = deltas.map(d => registry.createVersion(registry.initialVersion, d));
  131. const merged = registry.merge(versions, d => nameMap.get(d));
  132. (0, assert_1.assert)(merged.length === 1, "only one merged version should result");
  133. const mergedAgain = registry.merge(merged, d => nameMap.get(d));
  134. (0, assert_1.assert)(mergedAgain.length === merged.length
  135. && mergedAgain.every(version => merged.includes(version)), "merging a merge result should just give the same result again.");
  136. });
  137. it("Merge many conflicting versions (scalability test 2)", () => {
  138. const deltaRegistry = new delta_registry_1.DeltaRegistry();
  139. const getId = (0, test_helpers_1.mockUuid)();
  140. const registry = new version_1.VersionRegistry();
  141. const HOW_MANY = 3;
  142. const creations = [];
  143. const deletions = [];
  144. const edges = [];
  145. const versions = [];
  146. const nameMap = new Map();
  147. for (let i = 0; i < HOW_MANY; i++) {
  148. const creation = deltaRegistry.newNodeCreation(getId());
  149. const deletion = deltaRegistry.newNodeDeletion(creation, [], []);
  150. const edge = deltaRegistry.newEdgeUpdate(creation.createOutgoingEdge("l"), creation); // conflicts with deletion0
  151. creations.push(creation);
  152. deletions.push(deletion);
  153. edges.push(edge);
  154. nameMap.set(creation, "C" + i.toString());
  155. nameMap.set(deletion, "D" + i.toString());
  156. nameMap.set(edge, "E" + i.toString());
  157. versions.push(registry.quickVersion([deletion, creation]));
  158. versions.push(registry.quickVersion([edge, creation]));
  159. }
  160. const merged = registry.merge(versions, d => nameMap.get(d));
  161. (0, assert_1.assert)(merged.length === Math.pow(2, HOW_MANY), HOW_MANY.toString() + " binary choices should result in " + Math.pow(2, HOW_MANY).toString() + " possible conflict resolutions and therefore merge results.");
  162. console.log("merging again...");
  163. mergeAgain(registry, merged, d => nameMap.get(d));
  164. });
  165. });
  166. describe("Embedding of versions", () => {
  167. it("Creating embedded versions", () => {
  168. const deltaRegistry = new delta_registry_1.DeltaRegistry();
  169. const getId = (0, test_helpers_1.mockUuid)();
  170. const registry = new version_1.VersionRegistry();
  171. const guestCreate = deltaRegistry.newNodeCreation(getId());
  172. const guestV1 = registry.createVersion(registry.initialVersion, guestCreate);
  173. const guestDel = deltaRegistry.newNodeDeletion(guestCreate, [], []);
  174. const guestV2 = registry.createVersion(guestV1, guestDel);
  175. const hostCreate = deltaRegistry.newNodeCreation(getId());
  176. const hostLink = deltaRegistry.newEdgeUpdate(hostCreate.createOutgoingEdge("guest"), guestCreate);
  177. const allCreate = deltaRegistry.newTransaction([guestCreate, hostCreate, hostLink], "");
  178. const hostV1 = registry.createVersion(registry.initialVersion, allCreate, () => new Map([
  179. ["guest", { version: guestV1, overridings: new Map() }], // no overridings
  180. ]));
  181. const hostUnlink = deltaRegistry.newEdgeUpdate(hostLink.overwrite(), null);
  182. const hostDel = deltaRegistry.newNodeDeletion(hostCreate, [hostUnlink], []);
  183. const guestDelOverride = deltaRegistry.newNodeDeletion(guestCreate, [], [hostUnlink]);
  184. const allDel = deltaRegistry.newTransaction([hostUnlink, hostDel, guestDelOverride], "");
  185. (0, assert_1.assertThrows)(() => {
  186. registry.createVersion(hostV1, allDel, () => new Map([
  187. ["guest", { version: guestV2, overridings: new Map() }]
  188. ]));
  189. }, "should not be able to create host version without explicitly stating that guestDel was overridden by guestDelOver");
  190. const hostV2 = registry.createVersion(hostV1, allDel, () => new Map([
  191. ["guest", { version: guestV2, overridings: new Map([[guestDel, guestDelOverride]]) }],
  192. ]));
  193. });
  194. it("Merging host versions", () => {
  195. const deltaRegistry = new delta_registry_1.DeltaRegistry();
  196. const getId = (0, test_helpers_1.mockUuid)();
  197. const registry = new version_1.VersionRegistry();
  198. const createA = deltaRegistry.newNodeCreation(getId());
  199. const createB = deltaRegistry.newNodeCreation(getId());
  200. const guestA = registry.createVersion(registry.initialVersion, createA);
  201. const guestB = registry.createVersion(registry.initialVersion, createB);
  202. const createC = deltaRegistry.newNodeCreation(getId());
  203. const createD = deltaRegistry.newNodeCreation(getId());
  204. const createAC = deltaRegistry.newTransaction([createA, createC], "");
  205. const createBD = deltaRegistry.newTransaction([createB, createD], "");
  206. const debugNames = new Map([
  207. [createA, "createA"],
  208. [createB, "createB"],
  209. [createC, "createC"],
  210. [createD, "createD"],
  211. [createAC, "createAC"],
  212. [createBD, "createBD"],
  213. ]);
  214. const hostAC = registry.createVersion(registry.initialVersion, createAC, () => new Map([
  215. ["guest", { version: guestA, overridings: new Map() }],
  216. ]));
  217. const hostBD = registry.createVersion(registry.initialVersion, createBD, () => new Map([
  218. ["guest", { version: guestB, overridings: new Map() }],
  219. ]));
  220. console.log("Merging hosts...");
  221. const mergedHosts = registry.merge([hostAC, hostBD], d => debugNames.get(d));
  222. (0, assert_1.assert)(mergedHosts.length === 1, "expected no host merge conflict");
  223. console.log("Merging guests...");
  224. const mergedGuests = registry.merge([guestA, guestB], d => debugNames.get(d));
  225. (0, assert_1.assert)(mergedGuests.length === 1, "expected no guest merge conflict");
  226. const [guestAB] = mergedGuests;
  227. const [hostABCD] = mergedHosts;
  228. const { version: mergedGuest, overridings: mergedOverridings } = hostABCD.getEmbedding("guest");
  229. (0, assert_1.assert)(mergedGuest === guestAB, "merged host should embed merged guest");
  230. (0, assert_1.assert)(mergedOverridings.size === 0, "expected no overridings in merged embedding");
  231. });
  232. it("Multi-level embedding", () => {
  233. var _a, _b;
  234. const deltaRegistry = new delta_registry_1.DeltaRegistry();
  235. const getId = (0, test_helpers_1.mockUuid)();
  236. const registry = new version_1.VersionRegistry();
  237. const createA = deltaRegistry.newNodeCreation(getId());
  238. const createB = deltaRegistry.newNodeCreation(getId());
  239. const createC = deltaRegistry.newNodeCreation(getId());
  240. const createAB = deltaRegistry.newTransaction([createA, createB], "");
  241. const createABC = deltaRegistry.newTransaction([createAB, createC], "");
  242. const vA = registry.createVersion(registry.initialVersion, createA);
  243. const vAB = registry.createVersion(registry.initialVersion, createAB, () => new Map([
  244. ["L0", { version: vA, overridings: new Map() }],
  245. ]));
  246. const vABC = registry.createVersion(registry.initialVersion, createABC, () => new Map([
  247. ["L1", { version: vAB, overridings: new Map() }],
  248. ]));
  249. const createD = deltaRegistry.newNodeCreation(getId());
  250. const createE = deltaRegistry.newNodeCreation(getId());
  251. const createF = deltaRegistry.newNodeCreation(getId());
  252. const createDE = deltaRegistry.newTransaction([createD, createE], "");
  253. const createDEF = deltaRegistry.newTransaction([createDE, createF], "");
  254. const vD = registry.createVersion(registry.initialVersion, createD);
  255. const vDE = registry.createVersion(registry.initialVersion, createDE, () => new Map([
  256. ["L0", { version: vD, overridings: new Map() }],
  257. ]));
  258. const vDEF = registry.createVersion(registry.initialVersion, createDEF, () => new Map([
  259. ["L1", { version: vDE, overridings: new Map() }],
  260. ]));
  261. const [vABCDEF] = registry.merge([vABC, vDEF]);
  262. const vABDE = (_a = vABCDEF.embeddings.get("L1")) === null || _a === void 0 ? void 0 : _a.version;
  263. (0, assert_1.assert)(vABDE !== undefined, "No L1 merged version");
  264. (0, assert_1.assert)([...vABDE].length === 2, "L1 merge result unexpected number of deltas: " + [...vABDE].length);
  265. const vAD = (_b = vABDE.embeddings.get("L0")) === null || _b === void 0 ? void 0 : _b.version;
  266. (0, assert_1.assert)(vAD !== undefined, "No L0 merged version");
  267. (0, assert_1.assert)([...vAD].length === 2, "L1 merge result unexpected number of deltas: " + [...vAD].length);
  268. });
  269. it("Self-embedding", () => {
  270. const deltaRegistry = new delta_registry_1.DeltaRegistry();
  271. const getId = (0, test_helpers_1.mockUuid)();
  272. const registry = new version_1.VersionRegistry();
  273. const createA = deltaRegistry.newNodeCreation(getId());
  274. const createB = deltaRegistry.newNodeCreation(getId());
  275. const vA = registry.createVersion(registry.initialVersion, createA, version => new Map([
  276. ["self", { version, overridings: new Map() }]
  277. ]));
  278. const vB = registry.createVersion(registry.initialVersion, createB, version => new Map([
  279. ["self", { version, overridings: new Map() }]
  280. ]));
  281. const [vAB] = registry.merge([vA, vB]);
  282. (0, assert_1.assert)(vAB.embeddings.get("self") !== undefined, "Expected merge result to embed itself");
  283. });
  284. });
  285. });
  286. //# sourceMappingURL=version.test.js.map