From 9f0efb9c00f440abfa32888a0f16b83b6386a5a8 Mon Sep 17 00:00:00 2001 From: Kia Rahimian Date: Sat, 9 Feb 2019 15:48:01 -0500 Subject: [PATCH] wip --- .../runner/benchmarks/utils/start-ipfs.js | 42 ++-- package-lock.json | 212 ++++++++---------- package.json | 1 + src/entry-index.js | 21 +- src/log-io.js | 4 +- src/log.js | 181 ++++++++------- test/entry-io.spec.js | 33 ++- test/log-append.spec.js | 21 +- test/log-crdt.spec.js | 32 +-- test/log-heads-tails.spec.js | 71 +++--- test/log-iterator.spec.js | 77 ++++--- test/log-join-concurrent.spec.js | 15 +- test/log-join.spec.js | 52 +++-- test/log-load.spec.js | 172 ++++++++------ test/log-references.spec.js | 40 ++-- test/log.spec.js | 105 +++++---- test/replicate.spec.js | 18 +- test/signed-log.spec.js | 29 ++- 18 files changed, 638 insertions(+), 488 deletions(-) diff --git a/benchmarks/runner/benchmarks/utils/start-ipfs.js b/benchmarks/runner/benchmarks/utils/start-ipfs.js index 4d859497..457bbee3 100644 --- a/benchmarks/runner/benchmarks/utils/start-ipfs.js +++ b/benchmarks/runner/benchmarks/utils/start-ipfs.js @@ -2,34 +2,28 @@ const IPFS = require('ipfs') const IPFSRepo = require('ipfs-repo') const DatastoreLevel = require('datastore-level') -const startIpfs = (repoPath) => { - return new Promise((resolve, reject) => { - const repoConf = { - storageBackends: { - blocks: DatastoreLevel - } +const startIpfs = async (repoPath) => { + const repoConf = { + storageBackends: { + blocks: DatastoreLevel } + } - const repo = new IPFSRepo(repoPath, repoConf) + const repo = new IPFSRepo(repoPath, repoConf) - const ipfs = new IPFS({ - repo: repo, - start: false, - EXPERIMENTAL: { - pubsub: true, - sharding: false, - dht: false - } - }) - - ipfs.on('error', (err) => { - reject(err) - }) - - ipfs.on('ready', () => { - resolve({ ipfs, repo }) - }) + const ipfs = await IPFS.create({ + repo: repo, + start: false, + init: { + emptyRepo: true + }, + EXPERIMENTAL: { + sharding: false, + dht: false + } }) + + return { ipfs, repo } } module.exports = startIpfs diff --git a/package-lock.json b/package-lock.json index e4592bb2..b8dd41c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1421,7 +1421,8 @@ "acorn": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", - "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==" + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", + "dev": true }, "acorn-dynamic-import": { "version": "3.0.0", @@ -4701,8 +4702,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -4723,14 +4723,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4745,20 +4743,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -4875,8 +4870,7 @@ "inherits": { "version": "2.0.4", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -4888,7 +4882,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4903,7 +4896,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4911,14 +4903,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.9.0", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -4937,7 +4927,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -5027,8 +5016,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -5040,7 +5028,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -5126,8 +5113,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -5163,7 +5149,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -5183,7 +5168,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -5227,14 +5211,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -8292,6 +8274,11 @@ "negotiator": "0.6.2" } }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==" + }, "acorn-jsx": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", @@ -8302,6 +8289,7 @@ "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", "requires": { + "acorn": "^7.0.0", "acorn-walk": "^7.0.0", "xtend": "^4.0.2" } @@ -13550,6 +13538,7 @@ "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", "requires": { + "acorn": "^7.1.0", "acorn-jsx": "^5.1.0", "eslint-visitor-keys": "^1.1.0" } @@ -14834,8 +14823,7 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true, - "optional": true + "bundled": true }, "aproba": { "version": "1.2.0", @@ -14853,13 +14841,11 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true, - "optional": true + "bundled": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -14872,18 +14858,15 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "concat-map": { "version": "0.0.1", - "bundled": true, - "optional": true + "bundled": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "core-util-is": { "version": "1.0.2", @@ -14986,8 +14969,7 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, - "optional": true + "bundled": true }, "ini": { "version": "1.3.5", @@ -14997,7 +14979,6 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -15010,20 +14991,17 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true, - "optional": true + "bundled": true }, "minipass": { "version": "2.3.5", "bundled": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -15040,7 +15018,6 @@ "mkdirp": { "version": "0.5.1", "bundled": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -15113,8 +15090,7 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, - "optional": true + "bundled": true }, "object-assign": { "version": "4.1.1", @@ -15124,7 +15100,6 @@ "once": { "version": "1.4.0", "bundled": true, - "optional": true, "requires": { "wrappy": "1" } @@ -15200,8 +15175,7 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true, - "optional": true + "bundled": true }, "safer-buffer": { "version": "2.1.2", @@ -15231,7 +15205,6 @@ "string-width": { "version": "1.0.2", "bundled": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -15249,7 +15222,6 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -15288,13 +15260,11 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, - "optional": true + "bundled": true }, "yallist": { "version": "3.0.3", - "bundled": true, - "optional": true + "bundled": true } } }, @@ -15381,8 +15351,7 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true, - "optional": true + "bundled": true }, "aproba": { "version": "1.2.0", @@ -15400,13 +15369,11 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true, - "optional": true + "bundled": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -15419,18 +15386,15 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "concat-map": { "version": "0.0.1", - "bundled": true, - "optional": true + "bundled": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "core-util-is": { "version": "1.0.2", @@ -15533,8 +15497,7 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, - "optional": true + "bundled": true }, "ini": { "version": "1.3.5", @@ -15544,7 +15507,6 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -15557,20 +15519,17 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true, - "optional": true + "bundled": true }, "minipass": { "version": "2.3.5", "bundled": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -15587,7 +15546,6 @@ "mkdirp": { "version": "0.5.1", "bundled": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -15660,8 +15618,7 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, - "optional": true + "bundled": true }, "object-assign": { "version": "4.1.1", @@ -15671,7 +15628,6 @@ "once": { "version": "1.4.0", "bundled": true, - "optional": true, "requires": { "wrappy": "1" } @@ -15747,8 +15703,7 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true, - "optional": true + "bundled": true }, "safer-buffer": { "version": "2.1.2", @@ -15778,7 +15733,6 @@ "string-width": { "version": "1.0.2", "bundled": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -15796,7 +15750,6 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -15835,13 +15788,11 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, - "optional": true + "bundled": true }, "yallist": { "version": "3.0.3", - "bundled": true, - "optional": true + "bundled": true } } }, @@ -17719,7 +17670,7 @@ "datastore-core": "~0.6.0", "encoding-down": "^6.0.2", "interface-datastore": "~0.6.0", - "level-js": "github:timkuijsten/level.js#idbunwrapper", + "level-js": "github:timkuijsten/level.js#18e03adab34c49523be7d3d58fafb0c632f61303", "leveldown": "^5.0.0", "levelup": "^4.0.1", "pull-stream": "^3.6.9" @@ -17836,7 +17787,7 @@ "bs58": "^4.0.1", "buffer": "^5.4.2", "cids": "~0.7.1", - "concat-stream": "github:hugomrdias/concat-stream#feat/smaller", + "concat-stream": "github:hugomrdias/concat-stream#057bc7b5d6d8df26c8cf00a3f151b6721a0a8034", "debug": "^4.1.0", "delay": "^4.3.0", "detect-node": "^2.0.4", @@ -17871,7 +17822,7 @@ "multibase": "~0.6.0", "multicodec": "~0.5.1", "multihashes": "~0.4.14", - "ndjson": "github:hugomrdias/ndjson#feat/readable-stream3", + "ndjson": "github:hugomrdias/ndjson#4db16da6b42e5b39bf300c3a7cde62abb3fa3a11", "once": "^1.4.0", "peer-id": "~0.12.3", "peer-info": "~0.15.1", @@ -18217,7 +18168,7 @@ "bs58": "^4.0.1", "buffer": "^5.2.1", "cids": "~0.7.1", - "concat-stream": "github:hugomrdias/concat-stream#feat/smaller", + "concat-stream": "github:hugomrdias/concat-stream#057bc7b5d6d8df26c8cf00a3f151b6721a0a8034", "debug": "^4.1.0", "detect-node": "^2.0.4", "end-of-stream": "^1.4.1", @@ -18242,7 +18193,7 @@ "multibase": "~0.6.0", "multicodec": "~0.5.1", "multihashes": "~0.4.14", - "ndjson": "github:hugomrdias/ndjson#feat/readable-stream3", + "ndjson": "github:hugomrdias/ndjson#4db16da6b42e5b39bf300c3a7cde62abb3fa3a11", "once": "^1.4.0", "peer-id": "~0.12.2", "peer-info": "~0.15.1", @@ -18301,7 +18252,7 @@ "bs58": "^4.0.1", "buffer": "^5.2.1", "cids": "~0.7.1", - "concat-stream": "github:hugomrdias/concat-stream#feat/smaller", + "concat-stream": "github:hugomrdias/concat-stream#057bc7b5d6d8df26c8cf00a3f151b6721a0a8034", "debug": "^4.1.0", "detect-node": "^2.0.4", "end-of-stream": "^1.4.1", @@ -18326,7 +18277,7 @@ "multibase": "~0.6.0", "multicodec": "~0.5.1", "multihashes": "~0.4.14", - "ndjson": "github:hugomrdias/ndjson#feat/readable-stream3", + "ndjson": "github:hugomrdias/ndjson#4db16da6b42e5b39bf300c3a7cde62abb3fa3a11", "once": "^1.4.0", "peer-id": "~0.12.2", "peer-info": "~0.15.1", @@ -18597,7 +18548,7 @@ "buffer": "^5.4.2", "callbackify": "^1.1.0", "cids": "~0.7.1", - "concat-stream": "github:hugomrdias/concat-stream#feat/smaller", + "concat-stream": "github:hugomrdias/concat-stream#057bc7b5d6d8df26c8cf00a3f151b6721a0a8034", "debug": "^4.1.0", "delay": "^4.3.0", "detect-node": "^2.0.4", @@ -18633,7 +18584,7 @@ "multibase": "~0.6.0", "multicodec": "~0.5.1", "multihashes": "~0.4.14", - "ndjson": "github:hugomrdias/ndjson#feat/readable-stream3", + "ndjson": "github:hugomrdias/ndjson#4db16da6b42e5b39bf300c3a7cde62abb3fa3a11", "once": "^1.4.0", "peer-id": "~0.12.3", "peer-info": "~0.15.1", @@ -18845,7 +18796,7 @@ "datastore-core": "~0.6.0", "encoding-down": "^6.0.2", "interface-datastore": "~0.6.0", - "level-js": "github:timkuijsten/level.js#idbunwrapper", + "level-js": "github:timkuijsten/level.js#18e03adab34c49523be7d3d58fafb0c632f61303", "leveldown": "^5.0.0", "levelup": "^4.0.1", "pull-stream": "^3.6.9" @@ -18924,7 +18875,7 @@ "bs58": "^4.0.1", "buffer": "^5.2.1", "cids": "~0.7.1", - "concat-stream": "github:hugomrdias/concat-stream#feat/smaller", + "concat-stream": "github:hugomrdias/concat-stream#057bc7b5d6d8df26c8cf00a3f151b6721a0a8034", "debug": "^4.1.0", "detect-node": "^2.0.4", "end-of-stream": "^1.4.1", @@ -18949,7 +18900,7 @@ "multibase": "~0.6.0", "multicodec": "~0.5.1", "multihashes": "~0.4.14", - "ndjson": "github:hugomrdias/ndjson#feat/readable-stream3", + "ndjson": "github:hugomrdias/ndjson#4db16da6b42e5b39bf300c3a7cde62abb3fa3a11", "once": "^1.4.0", "peer-id": "~0.12.2", "peer-info": "~0.15.1", @@ -19055,7 +19006,7 @@ "bs58": "^4.0.1", "buffer": "^5.2.1", "cids": "~0.7.1", - "concat-stream": "github:hugomrdias/concat-stream#feat/smaller", + "concat-stream": "github:hugomrdias/concat-stream#057bc7b5d6d8df26c8cf00a3f151b6721a0a8034", "debug": "^4.1.0", "detect-node": "^2.0.4", "end-of-stream": "^1.4.1", @@ -19079,7 +19030,7 @@ "multibase": "~0.6.0", "multicodec": "~0.5.1", "multihashes": "~0.4.14", - "ndjson": "github:hugomrdias/ndjson#feat/readable-stream3", + "ndjson": "github:hugomrdias/ndjson#4db16da6b42e5b39bf300c3a7cde62abb3fa3a11", "once": "^1.4.0", "peer-id": "~0.12.2", "peer-info": "~0.15.1", @@ -19614,7 +19565,7 @@ "buffer": "^5.4.2", "callbackify": "^1.1.0", "cids": "~0.7.1", - "concat-stream": "github:hugomrdias/concat-stream#feat/smaller", + "concat-stream": "github:hugomrdias/concat-stream#057bc7b5d6d8df26c8cf00a3f151b6721a0a8034", "debug": "^4.1.0", "delay": "^4.3.0", "detect-node": "^2.0.4", @@ -19649,7 +19600,7 @@ "multibase": "~0.6.0", "multicodec": "~0.5.1", "multihashes": "~0.4.14", - "ndjson": "github:hugomrdias/ndjson#feat/readable-stream3", + "ndjson": "github:hugomrdias/ndjson#4db16da6b42e5b39bf300c3a7cde62abb3fa3a11", "once": "^1.4.0", "peer-id": "~0.12.3", "peer-info": "~0.15.1", @@ -21791,7 +21742,7 @@ "bs58": "^4.0.1", "buffer": "^5.2.1", "cids": "~0.7.1", - "concat-stream": "github:hugomrdias/concat-stream#feat/smaller", + "concat-stream": "github:hugomrdias/concat-stream#057bc7b5d6d8df26c8cf00a3f151b6721a0a8034", "debug": "^4.1.0", "detect-node": "^2.0.4", "end-of-stream": "^1.4.1", @@ -21816,7 +21767,7 @@ "multibase": "~0.6.0", "multicodec": "~0.5.1", "multihashes": "~0.4.14", - "ndjson": "github:hugomrdias/ndjson#feat/readable-stream3", + "ndjson": "github:hugomrdias/ndjson#4db16da6b42e5b39bf300c3a7cde62abb3fa3a11", "once": "^1.4.0", "peer-id": "~0.12.2", "peer-info": "~0.15.1", @@ -21954,7 +21905,7 @@ "bs58": "^4.0.1", "buffer": "^5.2.1", "cids": "~0.7.1", - "concat-stream": "github:hugomrdias/concat-stream#feat/smaller", + "concat-stream": "github:hugomrdias/concat-stream#057bc7b5d6d8df26c8cf00a3f151b6721a0a8034", "debug": "^4.1.0", "detect-node": "^2.0.4", "end-of-stream": "^1.4.1", @@ -21979,7 +21930,7 @@ "multibase": "~0.6.0", "multicodec": "~0.5.1", "multihashes": "~0.4.14", - "ndjson": "github:hugomrdias/ndjson#feat/readable-stream3", + "ndjson": "github:hugomrdias/ndjson#4db16da6b42e5b39bf300c3a7cde62abb3fa3a11", "once": "^1.4.0", "peer-id": "~0.12.2", "peer-info": "~0.15.1", @@ -22437,7 +22388,7 @@ "socket.io": "^2.1.1", "socket.io-client": "^2.1.1", "stream-to-pull-stream": "^1.7.3", - "webrtcsupport": "github:ipfs/webrtcsupport" + "webrtcsupport": "github:ipfs/webrtcsupport#0669f576582c53a3a42aa5ac014fcc5966809615" }, "dependencies": { "webrtcsupport": { @@ -22524,7 +22475,7 @@ "rsa-pem-to-jwk": "^1.1.3", "tweetnacl": "^1.0.0", "ursa-optional": "~0.9.9", - "webcrypto-shim": "github:dignifiedquire/webcrypto-shim#master" + "webcrypto-shim": "github:dignifiedquire/webcrypto-shim#190bc9ec341375df6025b17ae12ddb2428ea49c8" } }, "multiaddr": { @@ -22587,7 +22538,7 @@ "protons": "^1.0.1", "rsa-pem-to-jwk": "^1.1.3", "tweetnacl": "^1.0.0", - "webcrypto-shim": "github:dignifiedquire/webcrypto-shim#master" + "webcrypto-shim": "github:dignifiedquire/webcrypto-shim#190bc9ec341375df6025b17ae12ddb2428ea49c8" } }, "multiaddr": { @@ -22656,7 +22607,7 @@ "interface-connection": "~0.3.3", "mafmt": "^6.0.7", "multiaddr-to-uri": "^5.0.0", - "pull-ws": "github:hugomrdias/pull-ws#fix/bundle-size" + "pull-ws": "github:hugomrdias/pull-ws#8e2ce0bb3b1cd6804828316e937fff8e0bef6225" }, "dependencies": { "pull-ws": { @@ -23947,6 +23898,11 @@ "xtend": "^4.0.0" }, "dependencies": { + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" + }, "concat-stream": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", @@ -23977,6 +23933,7 @@ "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", "requires": { + "acorn": "^5.2.1", "defined": "^1.0.0" } }, @@ -26507,7 +26464,7 @@ "resolved": "https://registry.npmjs.org/rabin-wasm/-/rabin-wasm-0.0.8.tgz", "integrity": "sha512-TpIki3NG/X7nPnYHtYdF4Vp5NLrHvztiM5oL8+9NoeX/ClUfUyy7Y7DMrESZl1ropCpZJAjFMv/ZHYrkLu3bCQ==", "requires": { - "assemblyscript": "github:assemblyscript/assemblyscript#v0.6", + "assemblyscript": "github:assemblyscript/assemblyscript#3ed76a97f05335504166fce1653da75f4face28f", "bl": "^1.0.0", "debug": "^4.1.1", "minimist": "^1.2.0", @@ -30378,6 +30335,11 @@ "webpack-sources": "^1.4.1" }, "dependencies": { + "acorn": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", + "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==" + }, "cacache": { "version": "12.0.3", "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", @@ -30473,6 +30435,11 @@ "ws": "^6.0.0" }, "dependencies": { + "acorn": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", + "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==" + }, "acorn-walk": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", @@ -31100,7 +31067,7 @@ "buffer": "^5.4.2", "callbackify": "^1.1.0", "cids": "~0.7.1", - "concat-stream": "github:hugomrdias/concat-stream#feat/smaller", + "concat-stream": "github:hugomrdias/concat-stream#057bc7b5d6d8df26c8cf00a3f151b6721a0a8034", "debug": "^4.1.0", "delay": "^4.3.0", "detect-node": "^2.0.4", @@ -31135,7 +31102,7 @@ "multibase": "~0.6.0", "multicodec": "~0.5.1", "multihashes": "~0.4.14", - "ndjson": "github:hugomrdias/ndjson#feat/readable-stream3", + "ndjson": "github:hugomrdias/ndjson#4db16da6b42e5b39bf300c3a7cde62abb3fa3a11", "once": "^1.4.0", "peer-id": "~0.12.3", "peer-info": "~0.15.1", @@ -32807,7 +32774,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, "requires": { "yallist": "^3.0.2" } @@ -34323,9 +34289,8 @@ } }, "orbit-db-io": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/orbit-db-io/-/orbit-db-io-0.2.0.tgz", - "integrity": "sha512-wOunD4ZRgtTsAXJEu9NNEeJ8s98tZTtFlrLiI/ThuDKBy4AwpIvr+vMkzMD0DMSUTurRtK+xz7AfkP0nd9bcxQ==", + "version": "github:mistakia/orbit-db-io#d8adf71ca06d8ffce48ad1caff10751285f5e030", + "from": "github:mistakia/orbit-db-io#proto/record", "requires": { "cids": "^0.7.1", "ipld-dag-pb": "^0.18.1" @@ -37954,8 +37919,7 @@ "yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "yargs": { "version": "13.3.0", diff --git a/package.json b/package.json index 92b1a94d..bb0fdce5 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ ], "dependencies": { "json-stringify-deterministic": "^1.0.1", + "lru-cache": "^5.1.1", "multihashing-async": "^0.7.0", "orbit-db-identity-provider": "~0.3.0", "orbit-db-io": "~0.2.0", diff --git a/src/entry-index.js b/src/entry-index.js index 1568729e..066da7a9 100644 --- a/src/entry-index.js +++ b/src/entry-index.js @@ -1,28 +1,33 @@ 'use strict' +const LRU = require('lru-cache') + class EntryIndex { - constructor (entries = {}) { - this._cache = entries + constructor (entries = {}, cacheSize = Infinity) { + this._cache = new LRU({ max: cacheSize }) + this.add(entries) } set (k, v) { - this._cache[k] = v + this._cache.set(k, v) } get (k) { - return this._cache[k] + return this._cache.get(k) } delete (k) { - return delete this._cache[k] + this._cache.del(k) } - add (newItems) { - this._cache = Object.assign(this._cache, newItems) + add (items) { + for (const k in items) { + this._cache.set(k, items[k]) + } } get length () { - return Object.values(this._cache).length + return this._cache.length } } diff --git a/src/log-io.js b/src/log-io.js index 225ec90f..47b7225a 100644 --- a/src/log-io.js +++ b/src/log-io.js @@ -23,7 +23,9 @@ class LogIO { if (!isDefined(ipfs)) throw LogError.IPFSNotDefinedError() if (!isDefined(log)) throw LogError.LogNotDefinedError() if (!isDefined(format)) format = 'dag-cbor' - if (log.values.length < 1) throw new Error(`Can't serialize an empty log`) + + const values = await log.values() + if (values.length < 1) throw new Error(`Can't serialize an empty log`) return io.write(ipfs, format, log.toJSON(), { links: IPLD_LINKS }) } diff --git a/src/log.js b/src/log.js index ea05c085..00f4e22c 100644 --- a/src/log.js +++ b/src/log.js @@ -45,7 +45,7 @@ class Log extends GSet { * @param {Function} options.sortFn The sort function - by default LastWriteWins * @return {Log} The log instance */ - constructor (ipfs, identity, { logId, access, entries, heads, clock, sortFn, concurrency } = {}) { + constructor (ipfs, identity, { logId, access, entries, heads, clock, sortFn, concurrency, hashIndex = new Map() } = {}) { if (!isDefined(ipfs)) { throw LogError.IPFSNotDefinedError() } @@ -91,13 +91,15 @@ class Log extends GSet { heads = heads || Log.findHeads(entries) this._headsIndex = heads.reduce(uniqueEntriesReducer, {}) + // Index of log hashes + this._hashIndex = hashIndex + entries.forEach(e => this._hashIndex.set(e.hash, e.next)) + // Index of all next pointers in this log this._nextsIndex = {} const addToNextsIndex = e => e.next.forEach(a => (this._nextsIndex[a] = e.hash)) entries.forEach(addToNextsIndex) - - // Set the length, we calculate the length manually internally - this._length = entries.length + hashIndex.forEach((nexts, hash) => nexts.forEach(a => (this._nextsIndex[a] = hash))) // Set the clock const maxTime = Math.max(clock ? clock.time : 0, this.heads.reduce(maxClockTimeReducer, 0)) @@ -130,15 +132,15 @@ class Log extends GSet { * @return {number} Length */ get length () { - return this._length + return this._hashIndex.size } /** * Returns the values in the log. * @returns {Array} */ - get values () { - return Object.values(this.traverse(this.heads)).reverse() + async values () { + return Object.values(await this.traverse(this.heads)).reverse() } /** @@ -154,8 +156,9 @@ class Log extends GSet { * are not in the log currently. * @returns {Array} */ - get tails () { - return Log.findTails(this.values) + async tails () { + const values = await this.values() + return Log.findTails(values) } /** @@ -163,8 +166,9 @@ class Log extends GSet { * are not in the log currently. * @returns {Array} Array of hashes */ - get tailHashes () { - return Log.findTailHashes(this.values) + async tailHashes () { + const values = await this.values() + return Log.findTailHashes(values) } /** @@ -183,8 +187,25 @@ class Log extends GSet { * @param {string} [hash] The hashes of the entry * @returns {Entry|undefined} */ - get (hash) { - return this._entryIndex.get(hash) + async get (hash) { + if (!this.has(hash)) { + return undefined + } + + const haveCache = this._entryIndex.get(hash) + if (haveCache) { + return haveCache + } + + let entry + try { + entry = await Entry.fromMultihash(this._storage, hash) + this._entryIndex.set(entry.hash, entry) + } catch (error) { + // TODO + } + + return entry } /** @@ -193,10 +214,10 @@ class Log extends GSet { * @returns {boolean} */ has (entry) { - return this._entryIndex.get(entry.hash || entry) !== undefined + return this._hashIndex.has(entry.hash || entry) } - traverse (rootEntries, amount = -1, endHash) { + async traverse (rootEntries, amount = -1, endHash) { // Sort the given given root entries and use as the starting stack let stack = rootEntries.sort(this._sortFn).reverse() @@ -206,7 +227,7 @@ class Log extends GSet { let result = {} let count = 0 // Named function for getting an entry from the log - const getEntry = e => this.get(e) + const getEntry = async e => this.get(e) // Add an entry to the stack and traversed nodes index const addToStack = entry => { @@ -242,7 +263,7 @@ class Log extends GSet { if (endHash && endHash === entry.hash) break // Add entry's next references to the stack - const entries = entry.next.map(getEntry) + const entries = await pMap(entry.next, getEntry) const defined = entries.filter(isDefined) defined.forEach(addToStack) } @@ -263,7 +284,7 @@ class Log extends GSet { const newTime = Math.max(this.clock.time, this.heads.reduce(maxClockTimeReducer, 0)) + 1 this._clock = new Clock(this.clock.id, newTime) - const all = Object.values(this.traverse(this.heads, Math.max(pointerCount, this.heads.length))) + const all = Object.values(await this.traverse(this.heads, Math.max(pointerCount, this.heads.length))) // If pointer count is 4, returns 2 // If pointer count is 8, returns 3 references @@ -312,8 +333,7 @@ class Log extends GSet { nexts.forEach(e => (this._nextsIndex[e] = entry.hash)) this._headsIndex = {} this._headsIndex[entry.hash] = entry - // Update the length - this._length++ + this._hashIndex.set(entry.hash, nexts) return entry } @@ -326,7 +346,7 @@ class Log extends GSet { * @param {string|Array} options.lt Ending hash of the iterator, non-inclusive * @param {string|Array} options.lte Ending hash of the iterator, inclusive * @param {amount} options.amount Number of entried to return to / from the gte / lte hash - * @returns {Symbol.Iterator} Iterator object containing log entries + * @returns {Symbol.asyncIterator} asyncIterator object containing log entries * * @examples * @@ -349,31 +369,51 @@ class Log extends GSet { */ iterator ({ gt = undefined, gte = undefined, lt = undefined, lte = undefined, amount = -1 } = {}) { - if (amount === 0) return (function * () {})() - if (typeof lte === 'string') lte = [this.get(lte)] - if (typeof lt === 'string') lt = [this.get(this.get(lt).next)] + if (amount === 0) return (async function * () {})() + if (lte && (typeof lte !== 'string' || !Array.isArray(lte))) { + throw LogError.LtOrLteMustBeStringOrArray() + } + if (lt && (typeof lt !== 'string' || !Array.isArray(lt))) { + throw LogError.LtOrLteMustBeStringOrArray() + } - if (lte && !Array.isArray(lte)) throw LogError.LtOrLteMustBeStringOrArray() - if (lt && !Array.isArray(lt)) throw LogError.LtOrLteMustBeStringOrArray() + const self = this + return (async function * () { + if (typeof lte === 'string') { + const value = await self.get(lte) + lte = [value] + } + if (typeof lt === 'string') { + const value = await self.get(lt) + const next = await self.get(value.next[0]) + lt = [next] + } - let start = (lte || (lt || this.heads)).filter(isDefined) - let endHash = gte ? this.get(gte).hash : gt ? this.get(gt).hash : null - let count = endHash ? -1 : amount || -1 + let start = (lte || (lt || self.heads)).filter(isDefined) + let endHash = null + if (gte) { + const value = await self.get(gte) + endHash = value.hash + } else if (gt) { + const value = await self.get(gt) + endHash = value.hash + } + let count = endHash ? -1 : amount || -1 - let entries = this.traverse(start, count, endHash) - let entryValues = Object.values(entries) + let entries = await self.traverse(start, count, endHash) + let entryValues = Object.values(entries) - // Strip off last entry if gt is non-inclusive - if (gt) entryValues.pop() + // Strip off last entry if gt is non-inclusive + if (gt) entryValues.pop() - // Deal with the amount argument working backwards from gt/gte - if ((gt || gte) && amount > -1) { - entryValues = entryValues.slice(entryValues.length - amount, entryValues.length) - } + // Deal with the amount argument working backwards from gt/gte + if ((gt || gte) && amount > -1) { + entryValues = entryValues.slice(entryValues.length - amount, entryValues.length) + } - return (function * () { - for (let i in entryValues) { - yield entryValues[i] + // TODO convert traverse into async iterator + for await (const value of entryValues) { + yield value } })() } @@ -395,7 +435,7 @@ class Log extends GSet { if (this.id !== log.id) return // Get the difference of the logs - const newItems = Log.difference(log, this) + const newItems = await Log.difference(log, this) const identityProvider = this._identity.provider // Verify if entries are allowed to be added to the log and throws if @@ -420,13 +460,12 @@ class Log extends GSet { await verify(e) }, { concurrency: this.joinConcurrency }) - // Update the internal next pointers index - const addToNextsIndex = e => { - const entry = this.get(e.hash) - if (!entry) this._length++ /* istanbul ignore else */ + // Update internal indexes + const addToIndexes = e => { e.next.forEach(a => (this._nextsIndex[a] = e.hash)) + this._hashIndex.set(e.hash, e.next) } - Object.values(newItems).forEach(addToNextsIndex) + entriesToJoin.forEach(addToIndexes) // Update the internal entry index this._entryIndex.add(newItems) @@ -444,12 +483,16 @@ class Log extends GSet { // Slice to the requested size if (size > -1) { - let tmp = this.values + let tmp = await this.values() tmp = tmp.slice(-size) this._entryIndex = null this._entryIndex = new EntryIndex(tmp.reduce(uniqueEntriesReducer, {})) + this._hashIndex = new Map() + tmp.forEach(e => this._hashIndex.set(e.hash, e.next)) + this._nextsIndex = {} + const addToNextsIndex = e => e.next.forEach(a => (this._nextsIndex[a] = e.hash)) + tmp.forEach(addToNextsIndex) this._headsIndex = Log.findHeads(tmp).reduce(uniqueEntriesReducer, {}) - this._length = this._entryIndex.length } // Find the latest clock from the heads @@ -476,11 +519,12 @@ class Log extends GSet { * Get the log in JSON format as a snapshot. * @returns {Object} An object with the id, heads and value properties */ - toSnapshot () { + async toSnapshot () { + const values = await this.values() return { id: this.id, heads: this.heads, - values: this.values + values: values } } @@ -500,12 +544,13 @@ class Log extends GSet { * └─one * └─three */ - toString (payloadMapper) { - return this.values + async toString (payloadMapper) { + const values = await this.values() + return values .slice() .reverse() .map((e, idx) => { - const parents = Entry.findChildren(e, this.values) + const parents = Entry.findChildren(e, values) const len = parents.length let padding = new Array(Math.max(len - 1, 0)) padding = len > 1 ? padding.fill(' ') : padding @@ -523,8 +568,7 @@ class Log extends GSet { */ static isLog (log) { return log.id !== undefined && - log.heads !== undefined && - log._entryIndex !== undefined + log.heads !== undefined } /** @@ -710,31 +754,18 @@ class Log extends GSet { return entries.reduce(reduceTailHashes, []) } - static difference (a, b) { - let stack = Object.keys(a._headsIndex) - let traversed = {} + static async difference (a, b) { let res = {} - - const pushToStack = hash => { - if (!traversed[hash] && !b.get(hash)) { - stack.push(hash) - traversed[hash] = true - } - } - - while (stack.length > 0) { - const hash = stack.shift() - const entry = a.get(hash) - if (entry && !b.get(hash) && entry.id === b.id) { - res[entry.hash] = entry - traversed[entry.hash] = true - entry.next.forEach(pushToStack) - } - } + const hashesFromA = Array.from(a._hashIndex.keys()) + const diff = hashesFromA.filter(hash => !b.has(hash)) + const entries = await pMap(diff, hash => a.get(hash)) + entries.forEach(e => { res[e.hash] = e }) return res } } +Log.Entry = Entry + module.exports = Log module.exports.Sorting = Sorting module.exports.Entry = Entry diff --git a/test/entry-io.spec.js b/test/entry-io.spec.js index d863435b..7a00994e 100644 --- a/test/entry-io.spec.js +++ b/test/entry-io.spec.js @@ -68,7 +68,8 @@ Object.keys(testAPIs).forEach((IPFS) => { it('log with one entry', async () => { let log = new Log(ipfs, testIdentity, { logId: 'X' }) await log.append('one') - const hash = log.values[0].hash + const values = await log.values() + const hash = values[0].hash const res = await EntryIO.fetchAll(ipfs, hash, { length: 1 }) assert.strictEqual(res.length, 1) }) @@ -77,7 +78,8 @@ Object.keys(testAPIs).forEach((IPFS) => { let log = new Log(ipfs, testIdentity, { logId: 'X' }) await log.append('one') await log.append('two') - const hash = last(log.values).hash + const values = await log.values() + const hash = last(values).hash const res = await EntryIO.fetchAll(ipfs, hash, { length: 2 }) assert.strictEqual(res.length, 2) }) @@ -86,7 +88,8 @@ Object.keys(testAPIs).forEach((IPFS) => { let log = new Log(ipfs, testIdentity, { logId: 'X' }) await log.append('one') await log.append('two') - const hash = last(log.values).hash + const values = await log.values() + const hash = last(values).hash const res = await EntryIO.fetchAll(ipfs, hash, { length: 1 }) assert.strictEqual(res.length, 1) }) @@ -108,9 +111,10 @@ Object.keys(testAPIs).forEach((IPFS) => { let log2 = new Log(ipfs, testIdentity, { logId: 'X' }) for (let i = 1; i <= count; i++) { await log.append('hello' + i) + const values2 = await log2.values() if (i % 10 === 0) { log2 = new Log(ipfs, testIdentity, - { logId: log2.id, entries: log2.values, heads: log2.heads.concat(log.heads) }) + { logId: log2.id, entries: values2, heads: log2.heads.concat(log.heads) }) await log2.append('hi' + i) } } @@ -127,7 +131,8 @@ Object.keys(testAPIs).forEach((IPFS) => { for (let i = 1; i <= count; i++) { await log.append('hello' + i) if (i % 10 === 0) { - log2 = new Log(ipfs, testIdentity, { logId: log2.id, entries: log2.values }) + const values2 = await log2.values() + log2 = new Log(ipfs, testIdentity, { logId: log2.id, entries: values2 }) await log2.append('hi' + i) await log2.join(log) } @@ -146,14 +151,16 @@ Object.keys(testAPIs).forEach((IPFS) => { for (let i = 1; i <= count; i++) { await log.append('hello' + i) if (i % 10 === 0) { + const values2 = await log2.values() log2 = new Log(ipfs, testIdentity, - { logId: log2.id, entries: log2.values, heads: log2.heads }) + { logId: log2.id, entries: values2, heads: log2.heads }) await log2.append('hi' + i) await log2.join(log) } if (i % 25 === 0) { + const values3 = await log3.values() log3 = new Log(ipfs, testIdentity, - { logId: log3.id, entries: log3.values, heads: log3.heads.concat(log2.heads) }) + { logId: log3.id, entries: values3, heads: log3.heads.concat(log2.heads) }) await log3.append('--' + i) } } @@ -177,8 +184,9 @@ Object.keys(testAPIs).forEach((IPFS) => { await log2.join(log) } if (i % 25 === 0) { + const values3 = await log3.values() log3 = new Log(ipfs, testIdentity3, - { logId: log3.id, entries: log3.values, heads: log3.heads.concat(log2.heads) }) + { logId: log3.id, entries: values3, heads: log3.heads.concat(log2.heads) }) await log3.append('--' + i) } } @@ -189,10 +197,13 @@ Object.keys(testAPIs).forEach((IPFS) => { await log4.join(log2) await log4.join(log3) - const values3 = log3.values.map((e) => e.payload) - const values4 = log4.values.map((e) => e.payload) + const values3 = await log3.values() + const values4 = await log4.values() - assert.deepStrictEqual(values3, values4) + const entryPayloads3 = values3.map((e) => e.payload) + const entryPayloads4 = values4.map((e) => e.payload) + + assert.deepStrictEqual(entryPayloads3, entryPayloads4) }) }) }) diff --git a/test/log-append.spec.js b/test/log-append.spec.js index 426f79dd..c16f1255 100644 --- a/test/log-append.spec.js +++ b/test/log-append.spec.js @@ -55,11 +55,12 @@ Object.keys(testAPIs).forEach((IPFS) => { describe('append', () => { describe('append one', async () => { - let log + let log, values before(async () => { log = new Log(ipfs, testIdentity, 'A') await log.append('hello1') + values = await log.values() }) it('added the correct amount of items', () => { @@ -67,25 +68,25 @@ Object.keys(testAPIs).forEach((IPFS) => { }) it('added the correct values', async () => { - log.values.forEach((entry) => { + values.forEach((entry) => { assert.strictEqual(entry.payload, 'hello1') }) }) it('added the correct amount of next pointers', async () => { - log.values.forEach((entry) => { + values.forEach((entry) => { assert.strictEqual(entry.next.length, 0) }) }) it('has the correct heads', async () => { log.heads.forEach((head) => { - assert.strictEqual(head.hash, log.values[0].hash) + assert.strictEqual(head.hash, values[0].hash) }) }) it('updated the clocks correctly', async () => { - log.values.forEach((entry) => { + values.forEach((entry) => { assert.strictEqual(entry.clock.id, testIdentity.publicKey) assert.strictEqual(entry.clock.time, 1) }) @@ -96,14 +97,14 @@ Object.keys(testAPIs).forEach((IPFS) => { const amount = 100 const nextPointerAmount = 64 - let log + let log, values before(async () => { log = new Log(ipfs, testIdentity, 'A') for (let i = 0; i < amount; i++) { await log.append('hello' + i, nextPointerAmount) // Make sure the log has the right heads after each append - const values = log.values + values = await log.values() assert.strictEqual(log.heads.length, 1) assert.strictEqual(log.heads[0].hash, values[values.length - 1].hash) } @@ -114,20 +115,20 @@ Object.keys(testAPIs).forEach((IPFS) => { }) it('added the correct values', async () => { - log.values.forEach((entry, index) => { + values.forEach((entry, index) => { assert.strictEqual(entry.payload, 'hello' + index) }) }) it('updated the clocks correctly', async () => { - log.values.forEach((entry, index) => { + values.forEach((entry, index) => { assert.strictEqual(entry.clock.time, index + 1) assert.strictEqual(entry.clock.id, testIdentity.publicKey) }) }) it('added the correct amount of refs pointers', async () => { - log.values.forEach((entry, index) => { + values.forEach((entry, index) => { assert.strictEqual(entry.refs.length, index > 0 ? Math.ceil(Math.log2(Math.min(nextPointerAmount, index))) : 0) }) }) diff --git a/test/log-crdt.spec.js b/test/log-crdt.spec.js index 7cfd50ff..d3134825 100644 --- a/test/log-crdt.spec.js +++ b/test/log-crdt.spec.js @@ -78,7 +78,8 @@ Object.keys(testAPIs).forEach((IPFS) => { await log2.join(log3) await log1.join(log2) - const res1 = log1.values.slice() + const values1 = await log1.values() + const res1 = values1.slice() log1 = new Log(ipfs, testIdentity, { logId: 'X' }) log2 = new Log(ipfs, testIdentity2, { logId: 'X' }) @@ -94,7 +95,8 @@ Object.keys(testAPIs).forEach((IPFS) => { await log1.join(log2) await log3.join(log1) - const res2 = log3.values.slice() + const values3 = await log3.values() + const res2 = values3.slice() // associativity: a + (b + c) == (a + b) + c assert.strictEqual(res1.length, expectedElementsCount) @@ -112,7 +114,8 @@ Object.keys(testAPIs).forEach((IPFS) => { // b + a await log2.join(log1) - const res1 = log2.values.slice() + const values2 = await log2.values() + const res1 = values2.slice() log1 = new Log(ipfs, testIdentity, { logId: 'X' }) log2 = new Log(ipfs, testIdentity2, { logId: 'X' }) @@ -123,7 +126,8 @@ Object.keys(testAPIs).forEach((IPFS) => { // a + b await log1.join(log2) - const res2 = log1.values.slice() + const values1 = await log1.values() + const res2 = values1.slice() // commutativity: a + b == b + a assert.strictEqual(res1.length, expectedElementsCount) @@ -140,7 +144,7 @@ Object.keys(testAPIs).forEach((IPFS) => { await log2.append('helloB1') await log2.append('helloB2') await log2.join(log1) - const resA1 = log2.toString() + const resA1 = await log2.toString() log1 = new Log(ipfs, testIdentity, { logId: 'X' }) log2 = new Log(ipfs, testIdentity2, { logId: 'X' }) @@ -149,7 +153,7 @@ Object.keys(testAPIs).forEach((IPFS) => { await log2.append('helloB1') await log2.append('helloB2') await log1.join(log2) - const resA2 = log1.toString() + const resA2 = await log1.toString() assert.strictEqual(resA1, resA2) @@ -161,7 +165,7 @@ Object.keys(testAPIs).forEach((IPFS) => { await log2.append('helloB1') await log2.append('helloB2') await log1.join(log2) - const resB1 = log1.toString() + const resB1 = await log1.toString() log1 = new Log(ipfs, testIdentity, { logId: 'X' }) log2 = new Log(ipfs, testIdentity2, { logId: 'X' }) @@ -170,7 +174,7 @@ Object.keys(testAPIs).forEach((IPFS) => { await log2.append('helloB1') await log2.append('helloB2') await log2.join(log1) - const resB2 = log2.toString() + const resB2 = await log2.toString() assert.strictEqual(resB1, resB2) @@ -182,7 +186,7 @@ Object.keys(testAPIs).forEach((IPFS) => { await log3.append('helloC1') await log3.append('helloC2') await log3.join(log1) - const resC1 = log3.toString() + const resC1 = await log3.toString() log1 = new Log(ipfs, testIdentity, { logId: 'X' }) log3 = new Log(ipfs, testIdentity3, { logId: 'X' }) @@ -191,7 +195,7 @@ Object.keys(testAPIs).forEach((IPFS) => { await log3.append('helloC1') await log3.append('helloC2') await log1.join(log3) - const resC2 = log1.toString() + const resC2 = await log1.toString() assert.strictEqual(resC1, resC2) @@ -204,7 +208,7 @@ Object.keys(testAPIs).forEach((IPFS) => { await log3.append('helloC1') await log3.append('helloC2') await log3.join(log2) - const resD1 = log3.toString() + const resD1 = await log3.toString() log2 = new Log(ipfs, testIdentity2, { logId: 'X' }) log3 = new Log(ipfs, testIdentity3, { logId: 'X' }) @@ -213,7 +217,7 @@ Object.keys(testAPIs).forEach((IPFS) => { await log3.append('helloC1') await log3.append('helloC2') await log2.join(log3) - const resD2 = log2.toString() + const resD2 = await log2.toString() assert.strictEqual(resD1, resD2) @@ -229,7 +233,7 @@ Object.keys(testAPIs).forEach((IPFS) => { await log3.append('helloC2') await log1.join(log2) await log1.join(log3) - const logLeft = log1.toString() + const logLeft = await log1.toString() log1 = new Log(ipfs, testIdentity, { logId: 'X' }) log2 = new Log(ipfs, testIdentity2, { logId: 'X' }) @@ -242,7 +246,7 @@ Object.keys(testAPIs).forEach((IPFS) => { await log3.append('helloC2') await log3.join(log2) await log3.join(log1) - const logRight = log3.toString() + const logRight = await log3.toString() assert.strictEqual(logLeft, logRight) }) diff --git a/test/log-heads-tails.spec.js b/test/log-heads-tails.spec.js index 2456e881..a4565d95 100644 --- a/test/log-heads-tails.spec.js +++ b/test/log-heads-tails.spec.js @@ -79,7 +79,8 @@ Object.keys(testAPIs).forEach((IPFS) => { let log1 = new Log(ipfs, testIdentity, { logId: 'A' }) await log1.append('helloA1') await log1.append('helloA2') - assert.deepStrictEqual(log1.get(log1.heads[0].hash), log1.heads[0]) + const entry = await log1.get(log1.heads[0].hash) + assert.deepStrictEqual(entry, log1.heads[0]) }) it('finds head after a join and append', async () => { @@ -92,7 +93,8 @@ Object.keys(testAPIs).forEach((IPFS) => { await log2.join(log1) await log2.append('helloB2') - const expectedHead = last(log2.values) + const values2 = await log2.values() + const expectedHead = last(values2) assert.strictEqual(log2.heads.length, 1) assert.deepStrictEqual(log2.heads[0].hash, expectedHead.hash) @@ -104,11 +106,13 @@ Object.keys(testAPIs).forEach((IPFS) => { await log1.append('helloA1') await log1.append('helloA2') - const expectedHead1 = last(log1.values) + const values1 = await log1.values() + const expectedHead1 = last(values1) await log2.append('helloB1') await log2.append('helloB2') - const expectedHead2 = last(log2.values) + const values2 = await log2.values() + const expectedHead2 = last(values2) await log1.join(log2) @@ -134,8 +138,10 @@ Object.keys(testAPIs).forEach((IPFS) => { await log1.append('helloA3') await log1.append('helloA4') - const expectedHead2 = last(log2.values) - const expectedHead1 = last(log1.values) + const values1 = await log1.values() + const values2 = await log2.values() + const expectedHead2 = last(values2) + const expectedHead1 = last(values1) await log1.join(log2) @@ -157,12 +163,14 @@ Object.keys(testAPIs).forEach((IPFS) => { await log1.join(log2) await log1.append('helloA3') await log1.append('helloA4') - const expectedHead1 = last(log1.values) + const values1 = await log1.values() + const expectedHead1 = last(values1) await log3.append('helloC1') await log3.append('helloC2') await log2.join(log3) await log2.append('helloB3') - const expectedHead2 = last(log2.values) + const values2 = await log2.values() + const expectedHead2 = last(values2) await log1.join(log2) const heads = log1.heads @@ -183,12 +191,15 @@ Object.keys(testAPIs).forEach((IPFS) => { await log1.join(log2) await log1.append('helloA3') await log1.append('helloA4') - const expectedHead1 = last(log1.values) + const values1 = await log1.values() + const expectedHead1 = last(values1) await log3.append('helloC1') await log2.append('helloB3') await log3.append('helloC2') - const expectedHead2 = last(log2.values) - const expectedHead3 = last(log3.values) + const values2 = await log2.values() + const values3 = await log3.values() + const expectedHead2 = last(values2) + const expectedHead3 = last(values3) await log1.join(log2) await log1.join(log3) @@ -204,13 +215,15 @@ Object.keys(testAPIs).forEach((IPFS) => { it('returns a tail', async () => { let log1 = new Log(ipfs, testIdentity, { logId: 'A' }) await log1.append('helloA1') - assert.strictEqual(log1.tails.length, 1) + const tails1 = await log1.tails() + assert.strictEqual(tails1.length, 1) }) it('tail is a Entry', async () => { let log1 = new Log(ipfs, testIdentity, { logId: 'A' }) await log1.append('helloA1') - assert.strictEqual(Entry.isEntry(log1.tails[0]), true) + const tails1 = await log1.tails() + assert.strictEqual(Entry.isEntry(tails1[0]), true) }) it('returns tail entries', async () => { @@ -219,9 +232,10 @@ Object.keys(testAPIs).forEach((IPFS) => { await log1.append('helloA1') await log2.append('helloB1') await log1.join(log2) - assert.strictEqual(log1.tails.length, 2) - assert.strictEqual(Entry.isEntry(log1.tails[0]), true) - assert.strictEqual(Entry.isEntry(log1.tails[1]), true) + const tails1 = await log1.tails() + assert.strictEqual(tails1.length, 2) + assert.strictEqual(Entry.isEntry(tails1[0]), true) + assert.strictEqual(Entry.isEntry(tails1[1]), true) }) it('returns tail hashes', async () => { @@ -232,7 +246,8 @@ Object.keys(testAPIs).forEach((IPFS) => { await log2.append('helloB1') await log2.append('helloB2') await log1.join(log2, 2) - assert.strictEqual(log1.tailHashes.length, 2) + const tailHashes = await log1.tailHashes() + assert.strictEqual(tailHashes.length, 2) }) it('returns no tail hashes if all entries point to empty nexts', async () => { @@ -241,7 +256,8 @@ Object.keys(testAPIs).forEach((IPFS) => { await log1.append('helloA1') await log2.append('helloB1') await log1.join(log2) - assert.strictEqual(log1.tailHashes.length, 0) + const tailHashes = await log1.tailHashes() + assert.strictEqual(tailHashes.length, 0) }) it('returns tails after loading a partial log', async () => { @@ -254,9 +270,11 @@ Object.keys(testAPIs).forEach((IPFS) => { await log1.join(log2) const log4 = await Log.fromEntry(ipfs, testIdentity, log1.heads, { length: 2 }) assert.strictEqual(log4.length, 2) - assert.strictEqual(log4.tails.length, 2) - assert.strictEqual(log4.tails[0].hash, log4.values[0].hash) - assert.strictEqual(log4.tails[1].hash, log4.values[1].hash) + const tails4 = await log4.tails() + assert.strictEqual(tails4.length, 2) + const values4 = await log4.values() + assert.strictEqual(tails4[0].hash, values4[0].hash) + assert.strictEqual(tails4[1].hash, values4[1].hash) }) it('returns tails sorted by public key', async () => { @@ -270,11 +288,12 @@ Object.keys(testAPIs).forEach((IPFS) => { await log3.join(log1) await log3.join(log2) await log4.join(log3) - assert.strictEqual(log4.tails.length, 3) - assert.strictEqual(log4.tails[0].id, 'XX') - assert.strictEqual(log4.tails[0].clock.id, testIdentity3.publicKey) - assert.strictEqual(log4.tails[1].clock.id, testIdentity2.publicKey) - assert.strictEqual(log4.tails[2].clock.id, testIdentity.publicKey) + const tails4 = await log4.tails() + assert.strictEqual(tails4.length, 3) + assert.strictEqual(tails4[0].id, 'XX') + assert.strictEqual(tails4[0].clock.id, testIdentity3.publicKey) + assert.strictEqual(tails4[1].clock.id, testIdentity2.publicKey) + assert.strictEqual(tails4[2].clock.id, testIdentity.publicKey) assert.strictEqual(log4.clock.id, testIdentity4.publicKey) }) }) diff --git a/test/log-iterator.spec.js b/test/log-iterator.spec.js index 458ae6f2..83e0c820 100644 --- a/test/log-iterator.spec.js +++ b/test/log-iterator.spec.js @@ -16,6 +16,16 @@ const { stopIpfs } = require('orbit-db-test-utils') +const toArray = async (iterator) => { + const arr = [] + + for await (const entry of iterator) { + arr.push(entry) + } + + return arr +} + let ipfsd, ipfs, testIdentity, testIdentity2, testIdentity3 Object.keys(testAPIs).forEach((IPFS) => { @@ -67,14 +77,14 @@ Object.keys(testAPIs).forEach((IPFS) => { } }) - it('returns a Symbol.iterator object', async () => { + it('returns a Symbol.asyncIterator object', async () => { let it = log1.iterator({ lte: 'zdpuAuNuQ4YBeXY5YStfrsJx6ykz4yBV2XnNcBR4uGmiojQde', amount: 0 }) - assert.strictEqual(typeof it[Symbol.iterator], 'function') - assert.deepStrictEqual(it.next(), { value: undefined, done: true }) + assert.strictEqual(typeof it[Symbol.asyncIterator], 'function') + assert.deepStrictEqual(await it.next(), { value: undefined, done: true }) }) it('returns length with lte and amount', async () => { @@ -84,7 +94,8 @@ Object.keys(testAPIs).forEach((IPFS) => { amount: amount }) - assert.strictEqual([...it].length, 10) + const values = await toArray(it) + assert.strictEqual(values.length, 10) }) it('returns entries with lte and amount', async () => { @@ -96,7 +107,7 @@ Object.keys(testAPIs).forEach((IPFS) => { }) let i = 0 - for (let entry of it) { + for await (let entry of it) { assert.strictEqual(entry.payload, 'entry' + (67 - i++)) } }) @@ -109,7 +120,8 @@ Object.keys(testAPIs).forEach((IPFS) => { amount: amount }) - assert.strictEqual([...it].length, amount) + const values = await toArray(it) + assert.strictEqual(values.length, amount) }) it('returns entries with lt and amount', async () => { @@ -121,7 +133,7 @@ Object.keys(testAPIs).forEach((IPFS) => { }) let i = 1 - for (let entry of it) { + for await (let entry of it) { assert.strictEqual(entry.payload, 'entry' + (67 - i++)) } }) @@ -135,7 +147,7 @@ Object.keys(testAPIs).forEach((IPFS) => { let i = 0 let count = 0 - for (let entry of it) { + for await (let entry of it) { assert.strictEqual(entry.payload, 'entry' + (72 - i++)) count++ } @@ -150,7 +162,8 @@ Object.keys(testAPIs).forEach((IPFS) => { amount: amount }) - assert.strictEqual([...it].length, amount) + const values = await toArray(it) + assert.strictEqual(values.length, amount) }) it('returns entries with gte and amount', async () => { @@ -162,7 +175,7 @@ Object.keys(testAPIs).forEach((IPFS) => { }) let i = 0 - for (let entry of it) { + for await (let entry of it) { assert.strictEqual(entry.payload, 'entry' + (79 - i++)) } }) @@ -173,7 +186,8 @@ Object.keys(testAPIs).forEach((IPFS) => { gt: 'zdpuAymZUrYbHgwfYK76xXYhzxNqwaXRWWrn5kmRsZJFdqBEz', lt: 'zdpuAoDcWRiChLXnGskymcGrM1VdAjsaFrsXvNZmcDattA7AF' }) - let hashes = [...it].map(e => e.hash) + const values = await toArray(it) + let hashes = values.map(e => e.hash) // neither hash should appear in the array assert.strictEqual(hashes.indexOf('zdpuAymZUrYbHgwfYK76xXYhzxNqwaXRWWrn5kmRsZJFdqBEz'), -1) @@ -186,7 +200,8 @@ Object.keys(testAPIs).forEach((IPFS) => { gte: 'zdpuAt7YtNE1i9APJitGyKomcmxjc2BDHa57wkrjq4onqBNaR', lt: 'zdpuAr8N4vzqcB5sh5JLcr6Eszo4HnYefBWDbBBwwrTPo6kU6' }) - let hashes = [...it].map(e => e.hash) + const values = await toArray(it) + let hashes = values.map(e => e.hash) // only the gte hash should appear in the array assert.strictEqual(hashes.indexOf('zdpuAt7YtNE1i9APJitGyKomcmxjc2BDHa57wkrjq4onqBNaR'), 24) @@ -199,7 +214,8 @@ Object.keys(testAPIs).forEach((IPFS) => { gt: 'zdpuAqUrGrPa4AaZAQbCH4yxQfEjB32rdFY743XCgyGW8iAuU', lte: 'zdpuAwkagwE9D2jUtLnDiCPqBGh9xhpnaX8iEDQ3K7HRmjggi' }) - let hashes = [...it].map(e => e.hash) + const values = await toArray(it) + let hashes = values.map(e => e.hash) // only the lte hash should appear in the array assert.strictEqual(hashes.indexOf('zdpuAqUrGrPa4AaZAQbCH4yxQfEjB32rdFY743XCgyGW8iAuU'), -1) @@ -212,7 +228,8 @@ Object.keys(testAPIs).forEach((IPFS) => { gte: 'zdpuAzG5AD1GdeNffSskTErjjPbAb95QiNyoaQSrbB62eqYSD', lte: 'zdpuAuujURnUUxVw338Xwh47zGEFjjbaZXXARHPik6KYUcUVk' }) - let hashes = [...it].map(e => e.hash) + const values = await toArray(it) + let hashes = values.map(e => e.hash) // neither hash should appear in the array assert.strictEqual(hashes.indexOf('zdpuAzG5AD1GdeNffSskTErjjPbAb95QiNyoaQSrbB62eqYSD'), 9) @@ -225,7 +242,8 @@ Object.keys(testAPIs).forEach((IPFS) => { gt: 'zdpuAuNuQ4YBeXY5YStfrsJx6ykz4yBV2XnNcBR4uGmiojQde' }) - assert.strictEqual([...it].length, 33) + const values = await toArray(it) + assert.strictEqual(values.length, 33) }) it('returns entries with gt and default amount', async () => { @@ -234,7 +252,7 @@ Object.keys(testAPIs).forEach((IPFS) => { }) let i = 0 - for (let entry of it) { + for await (let entry of it) { assert.strictEqual(entry.payload, 'entry' + (100 - i++)) } }) @@ -244,7 +262,8 @@ Object.keys(testAPIs).forEach((IPFS) => { gte: 'zdpuAuNuQ4YBeXY5YStfrsJx6ykz4yBV2XnNcBR4uGmiojQde' }) - assert.strictEqual([...it].length, 34) + const values = await toArray(it) + assert.strictEqual(values.length, 34) }) it('returns entries with gte and default amount', async () => { @@ -253,7 +272,7 @@ Object.keys(testAPIs).forEach((IPFS) => { }) let i = 0 - for (let entry of it) { + for await (let entry of it) { assert.strictEqual(entry.payload, 'entry' + (100 - i++)) } }) @@ -263,7 +282,8 @@ Object.keys(testAPIs).forEach((IPFS) => { lt: 'zdpuAuNuQ4YBeXY5YStfrsJx6ykz4yBV2XnNcBR4uGmiojQde' }) - assert.strictEqual([...it].length, 67) + const values = await toArray(it) + assert.strictEqual(values.length, 67) }) it('returns entries with lt and default amount value', async () => { @@ -272,7 +292,7 @@ Object.keys(testAPIs).forEach((IPFS) => { }) let i = 0 - for (let entry of it) { + for await (let entry of it) { assert.strictEqual(entry.payload, 'entry' + (66 - i++)) } }) @@ -282,7 +302,8 @@ Object.keys(testAPIs).forEach((IPFS) => { lte: 'zdpuAuNuQ4YBeXY5YStfrsJx6ykz4yBV2XnNcBR4uGmiojQde' }) - assert.strictEqual([...it].length, 68) + const values = await toArray(it) + assert.strictEqual(values.length, 68) }) it('returns entries with lte and default amount value', async () => { @@ -291,7 +312,7 @@ Object.keys(testAPIs).forEach((IPFS) => { }) let i = 0 - for (let entry of it) { + for await (let entry of it) { assert.strictEqual(entry.payload, 'entry' + (67 - i++)) } }) @@ -310,7 +331,8 @@ Object.keys(testAPIs).forEach((IPFS) => { lte: fixture.log.heads }) - assert.strictEqual([...it].length, 16) + const values = await toArray(it) + assert.strictEqual(values.length, 16) }) it('returns partial entries from all heads', async () => { @@ -319,7 +341,8 @@ Object.keys(testAPIs).forEach((IPFS) => { amount: 6 }) - assert.deepStrictEqual([...it].map(e => e.payload), + const values = await toArray(it) + assert.deepStrictEqual(values.map(e => e.payload), ['entryA10', 'entryA9', 'entryA8', 'entryA7', 'entryC0', 'entryA6']) }) @@ -328,7 +351,8 @@ Object.keys(testAPIs).forEach((IPFS) => { lte: [fixture.log.heads[0]] }) - assert.strictEqual([...it].length, 10) + const values = await toArray(it) + assert.strictEqual(values.length, 10) }) it('returns partial logs from single heads #2', async () => { @@ -336,7 +360,8 @@ Object.keys(testAPIs).forEach((IPFS) => { lte: [fixture.log.heads[1]] }) - assert.strictEqual([...it].length, 11) + const values = await toArray(it) + assert.strictEqual(values.length, 11) }) it('throws error if lt/lte not a string or array of entries', async () => { diff --git a/test/log-join-concurrent.spec.js b/test/log-join-concurrent.spec.js index 3a5ea4f1..3526ed2d 100644 --- a/test/log-join-concurrent.spec.js +++ b/test/log-join-concurrent.spec.js @@ -65,9 +65,12 @@ Object.keys(testAPIs).forEach(IPFS => { let hash1 = await log1.toMultihash() let hash2 = await log2.toMultihash() + const values1 = await log1.values() + const values2 = await log2.values() + assert.strictEqual(hash1, hash2) assert.strictEqual(log1.length, 20) - assert.deepStrictEqual(log1.values.map(e => e.payload), log2.values.map(e => e.payload)) + assert.deepStrictEqual(values1.map(e => e.payload), values2.map(e => e.payload)) }) it('Concurrently appending same payload after join results in same state', async () => { @@ -85,19 +88,25 @@ Object.keys(testAPIs).forEach(IPFS => { let hash1 = await log1.toMultihash() let hash2 = await log2.toMultihash() + const values1 = await log1.values() + const values2 = await log2.values() + assert.strictEqual(hash1, hash2) assert.strictEqual(log1.length, 41) assert.strictEqual(log2.length, 41) - assert.deepStrictEqual(log1.values.map(e => e.payload), log2.values.map(e => e.payload)) + assert.deepStrictEqual(values1.map(e => e.payload), values2.map(e => e.payload)) }) it('Joining after concurrently appending same payload joins entry once', async () => { await log1.join(log2) await log2.join(log1) + const values1 = await log1.values() + const values2 = await log2.values() + assert.strictEqual(log1.length, log2.length) assert.strictEqual(log1.length, 41) - assert.deepStrictEqual(log1.values.map(e => e.payload), log2.values.map(e => e.payload)) + assert.deepStrictEqual(values1.map(e => e.payload), values2.map(e => e.payload)) }) }) }) diff --git a/test/log-join.spec.js b/test/log-join.spec.js index e45f2b8a..358e1ff6 100644 --- a/test/log-join.spec.js +++ b/test/log-join.spec.js @@ -141,10 +141,11 @@ Object.keys(testAPIs).forEach((IPFS) => { 'helloA1', 'helloB1', 'helloA2', 'helloB2' ] + const values1 = await log1.values() assert.strictEqual(log1.length, 4) - assert.deepStrictEqual(log1.values.map((e) => e.payload), expectedData) + assert.deepStrictEqual(values1.map((e) => e.payload), expectedData) - const item = last(log1.values) + const item = last(values1) assert.strictEqual(item.next.length, 1) }) @@ -160,9 +161,11 @@ Object.keys(testAPIs).forEach((IPFS) => { 'helloA1', 'helloB1', 'helloA2', 'helloB2' ] - assert.deepStrictEqual(log1.values.map((e) => e.hash), log2.values.map((e) => e.hash)) - assert.deepStrictEqual(log1.values.map((e) => e.payload), expectedData) - assert.deepStrictEqual(log2.values.map((e) => e.payload), expectedData) + const values1 = await log1.values() + const values2 = await log2.values() + assert.deepStrictEqual(values1.map((e) => e.hash), values2.map((e) => e.hash)) + assert.deepStrictEqual(values1.map((e) => e.payload), expectedData) + assert.deepStrictEqual(values2.map((e) => e.payload), expectedData) }) it('joins logs twice', async () => { @@ -179,7 +182,8 @@ Object.keys(testAPIs).forEach((IPFS) => { ] assert.strictEqual(log2.length, 4) - assert.deepStrictEqual(log2.values.map((e) => e.payload), expectedData) + const values2 = await log2.values() + assert.deepStrictEqual(values2.map((e) => e.payload), expectedData) }) it('joins 2 logs two ways', async () => { @@ -196,7 +200,8 @@ Object.keys(testAPIs).forEach((IPFS) => { ] assert.strictEqual(log2.length, 4) - assert.deepStrictEqual(log2.values.map((e) => e.payload), expectedData) + const values2 = await log2.values() + assert.deepStrictEqual(values2.map((e) => e.payload), expectedData) }) it('joins 2 logs two ways and has the right heads at every step', async () => { @@ -261,7 +266,8 @@ Object.keys(testAPIs).forEach((IPFS) => { ] assert.strictEqual(log1.length, 8) - assert.deepStrictEqual(log1.values.map(e => e.payload), expectedData) + const values1 = await log1.values() + assert.deepStrictEqual(values1.map(e => e.payload), expectedData) }) it('joins 4 logs to one is commutative', async () => { @@ -281,7 +287,9 @@ Object.keys(testAPIs).forEach((IPFS) => { await log2.join(log4) assert.strictEqual(log1.length, 8) - assert.deepStrictEqual(log1.values.map(e => e.payload), log2.values.map(e => e.payload)) + const values1 = await log1.values() + const values2 = await log2.values() + assert.deepStrictEqual(values1.map(e => e.payload), values2.map(e => e.payload)) }) it('joins logs and updates clocks', async () => { @@ -340,7 +348,8 @@ Object.keys(testAPIs).forEach((IPFS) => { { payload: 'helloD6', id: 'X', clock: new Clock(testIdentity4.publicKey, 8) } ] - const transformed = log4.values.map((e) => { + const values4 = await log4.values() + const transformed = values4.map((e) => { return { payload: e.payload, id: e.id, clock: e.clock } }) @@ -395,7 +404,8 @@ Object.keys(testAPIs).forEach((IPFS) => { ] assert.strictEqual(log4.length, 10) - assert.deepStrictEqual(log4.values.map((e) => e.payload), expectedData) + const values4 = await log4.values() + assert.deepStrictEqual(values4.map((e) => e.payload), expectedData) }) describe('takes length as an argument', async () => { @@ -412,10 +422,11 @@ Object.keys(testAPIs).forEach((IPFS) => { const expectedData = [ 'helloB2' ] - const lastEntry = last(log1.values) + const values1 = await log1.values() + const lastEntry = last(values1) assert.strictEqual(log1.length, 1) - assert.deepStrictEqual(log1.values.map((e) => e.payload), expectedData) + assert.deepStrictEqual(values1.map((e) => e.payload), expectedData) assert.strictEqual(lastEntry.next.length, 1) }) @@ -425,10 +436,11 @@ Object.keys(testAPIs).forEach((IPFS) => { const expectedData = [ 'helloA2', 'helloB2' ] - const lastEntry = last(log1.values) + const values1 = await log1.values() + const lastEntry = last(values1) assert.strictEqual(log1.length, 2) - assert.deepStrictEqual(log1.values.map((e) => e.payload), expectedData) + assert.deepStrictEqual(values1.map((e) => e.payload), expectedData) assert.strictEqual(lastEntry.next.length, 1) }) @@ -438,10 +450,11 @@ Object.keys(testAPIs).forEach((IPFS) => { const expectedData = [ 'helloB1', 'helloA2', 'helloB2' ] - const lastEntry = last(log1.values) + const values1 = await log1.values() + const lastEntry = last(values1) assert.strictEqual(log1.length, 3) - assert.deepStrictEqual(log1.values.map((e) => e.payload), expectedData) + assert.deepStrictEqual(values1.map((e) => e.payload), expectedData) assert.strictEqual(lastEntry.next.length, 1) }) @@ -451,10 +464,11 @@ Object.keys(testAPIs).forEach((IPFS) => { const expectedData = [ 'helloA1', 'helloB1', 'helloA2', 'helloB2' ] - const lastEntry = last(log1.values) + const values1 = await log1.values() + const lastEntry = last(values1) assert.strictEqual(log1.length, 4) - assert.deepStrictEqual(log1.values.map((e) => e.payload), expectedData) + assert.deepStrictEqual(values1.map((e) => e.payload), expectedData) assert.strictEqual(lastEntry.next.length, 1) }) }) diff --git a/test/log-load.spec.js b/test/log-load.spec.js index b9922029..f11a8b80 100644 --- a/test/log-load.spec.js +++ b/test/log-load.spec.js @@ -98,10 +98,10 @@ Object.keys(testAPIs).forEach((IPFS) => { json.heads = await Promise.all(json.heads.map(headHash => Entry.fromMultihash(ipfs, headHash))) let log = await Log.fromJSON(ipfs, testIdentity, json, { logId: 'X' }) - + const values = await log.values() assert.strictEqual(log.id, data.heads[0].id) assert.strictEqual(log.length, 16) - assert.deepStrictEqual(log.values.map(e => e.payload), fixture.expectedData) + assert.deepStrictEqual(values.map(e => e.payload), fixture.expectedData) }) it('creates a log from an entry with custom tiebreaker', async () => { @@ -114,9 +114,10 @@ Object.keys(testAPIs).forEach((IPFS) => { let log = await Log.fromJSON(ipfs, testIdentity, json, { length: -1, logId: 'X', sortFn: FirstWriteWins }) + const values = await log.values() assert.strictEqual(log.id, data.heads[0].id) assert.strictEqual(log.length, 16) - assert.deepStrictEqual(log.values.map(e => e.payload), firstWriteExpectedData) + assert.deepStrictEqual(values.map(e => e.payload), firstWriteExpectedData) }) it('respects timeout parameter', async () => { @@ -128,9 +129,10 @@ Object.keys(testAPIs).forEach((IPFS) => { const st = new Date().getTime() let log = await Log.fromJSON(ipfs, testIdentity, json, { logId: 'X', timeout }) const et = new Date().getTime() + const values = await log.values() assert.strictEqual((et - st) >= timeout, true, '' + (et - st) + ' should be greater than timeout ' + timeout) assert.strictEqual(log.length, 0) - assert.deepStrictEqual(log.values.map(e => e.payload), []) + assert.deepStrictEqual(values.map(e => e.payload), []) }) }) @@ -152,10 +154,10 @@ Object.keys(testAPIs).forEach((IPFS) => { { logId: 'X' }) await log1.join(log2) - + const values1 = await log1.values() assert.strictEqual(log1.id, data.heads[0].id) assert.strictEqual(log1.length, 16) - assert.deepStrictEqual(log1.values.map(e => e.payload), fixture.expectedData) + assert.deepStrictEqual(values1.map(e => e.payload), fixture.expectedData) }) it('creates a log from an entry hash with custom tiebreaker', async () => { @@ -168,20 +170,21 @@ Object.keys(testAPIs).forEach((IPFS) => { { logId: 'X', sortFn: FirstWriteWins }) await log1.join(log2) - + const values1 = await log1.values() assert.strictEqual(log1.id, data.heads[0].id) assert.strictEqual(log1.length, 16) - assert.deepStrictEqual(log1.values.map(e => e.payload), firstWriteExpectedData) + assert.deepStrictEqual(values1.map(e => e.payload), firstWriteExpectedData) }) it('respects timeout parameter', async () => { const timeout = 500 const st = new Date().getTime() - let log = await Log.fromEntryHash(ipfs, testIdentity, 'zdpuAwNuRc2Kc1aNDdcdSWuxfNpHRJQw8L8APBNHCEFXbogus', { logId: 'X', timeout }) + let log1 = await Log.fromEntryHash(ipfs, testIdentity, 'zdpuAwNuRc2Kc1aNDdcdSWuxfNpHRJQw8L8APBNHCEFXbogus', { logId: 'X', timeout }) const et = new Date().getTime() + const values1 = await log1.values() assert.strictEqual((et - st) >= timeout, true, '' + (et - st) + ' should be greater than timeout ' + timeout) - assert.strictEqual(log.length, 0) - assert.deepStrictEqual(log.values.map(e => e.payload), []) + assert.strictEqual(log1.length, 0) + assert.deepStrictEqual(values1.map(e => e.payload), []) }) }) @@ -196,21 +199,24 @@ Object.keys(testAPIs).forEach((IPFS) => { let fixture = await LogCreator.createLogWithSixteenEntries(Log, ipfs, identities) let data = fixture.log - let log = await Log.fromEntry(ipfs, testIdentity, data.heads, { length: -1 }) - assert.strictEqual(log.id, data.heads[0].id) - assert.strictEqual(log.length, 16) - assert.deepStrictEqual(log.values.map(e => e.payload), fixture.expectedData) + let log1 = await Log.fromEntry(ipfs, testIdentity, data.heads, { length: -1 }) + const values1 = await log1.values() + assert.strictEqual(log1.id, data.heads[0].id) + assert.strictEqual(log1.length, 16) + assert.deepStrictEqual(values1.map(e => e.payload), fixture.expectedData) }) it('creates a log from an entry with custom tiebreaker', async () => { let fixture = await LogCreator.createLogWithSixteenEntries(Log, ipfs, identities) let data = fixture.log - let log = await Log.fromEntry(ipfs, testIdentity, data.heads, + let log1 = await Log.fromEntry(ipfs, testIdentity, data.heads, { length: -1, sortFn: FirstWriteWins }) - assert.strictEqual(log.id, data.heads[0].id) - assert.strictEqual(log.length, 16) - assert.deepStrictEqual(log.values.map(e => e.payload), firstWriteExpectedData) + + const values1 = await log1.values() + assert.strictEqual(log1.id, data.heads[0].id) + assert.strictEqual(log1.length, 16) + assert.deepStrictEqual(values1.map(e => e.payload), firstWriteExpectedData) }) it('keeps the original heads', async () => { @@ -219,29 +225,33 @@ Object.keys(testAPIs).forEach((IPFS) => { let log1 = await Log.fromEntry(ipfs, testIdentity, data.heads, { length: data.heads.length }) + + const values1 = await log1.values() assert.strictEqual(log1.id, data.heads[0].id) assert.strictEqual(log1.length, data.heads.length) - assert.strictEqual(log1.values[0].payload, 'entryC0') - assert.strictEqual(log1.values[1].payload, 'entryA10') + assert.strictEqual(values1[0].payload, 'entryC0') + assert.strictEqual(values1[1].payload, 'entryA10') let log2 = await Log.fromEntry(ipfs, testIdentity, data.heads, { length: 4 }) + const values2 = await log2.values() assert.strictEqual(log2.id, data.heads[0].id) assert.strictEqual(log2.length, 4) - assert.strictEqual(log2.values[0].payload, 'entryC0') - assert.strictEqual(log2.values[1].payload, 'entryA8') - assert.strictEqual(log2.values[2].payload, 'entryA9') - assert.strictEqual(log2.values[3].payload, 'entryA10') + assert.strictEqual(values2[0].payload, 'entryC0') + assert.strictEqual(values2[1].payload, 'entryA8') + assert.strictEqual(values2[2].payload, 'entryA9') + assert.strictEqual(values2[3].payload, 'entryA10') let log3 = await Log.fromEntry(ipfs, testIdentity, data.heads, { length: 7 }) + const values3 = await log3.values() assert.strictEqual(log3.id, data.heads[0].id) assert.strictEqual(log3.length, 7) - assert.strictEqual(log3.values[0].payload, 'entryB5') - assert.strictEqual(log3.values[1].payload, 'entryA6') - assert.strictEqual(log3.values[2].payload, 'entryC0') - assert.strictEqual(log3.values[3].payload, 'entryA7') - assert.strictEqual(log3.values[4].payload, 'entryA8') - assert.strictEqual(log3.values[5].payload, 'entryA9') - assert.strictEqual(log3.values[6].payload, 'entryA10') + assert.strictEqual(values3[0].payload, 'entryB5') + assert.strictEqual(values3[1].payload, 'entryA6') + assert.strictEqual(values3[2].payload, 'entryC0') + assert.strictEqual(values3[3].payload, 'entryA7') + assert.strictEqual(values3[4].payload, 'entryA8') + assert.strictEqual(values3[5].payload, 'entryA9') + assert.strictEqual(values3[6].payload, 'entryA10') }) it('onProgress callback is fired for each entry', async () => { @@ -439,8 +449,9 @@ Object.keys(testAPIs).forEach((IPFS) => { const b = await Log.fromEntry(ipfs, testIdentity2, last(items2), { length: amount * 2 }) + const bValues = await b.values() assert.strictEqual(b.length, amount * 2) - assert.deepStrictEqual(b.values.map((e) => e.payload), itemsInB) + assert.deepStrictEqual(bValues.map((e) => e.payload), itemsInB) let c = await Log.fromEntry(ipfs, testIdentity4, last(items3), { length: amount * 3 }) @@ -480,14 +491,16 @@ Object.keys(testAPIs).forEach((IPFS) => { 'entryC10', 'EOF' ] - assert.deepStrictEqual(c.values.map(e => e.payload), tmp) + let cValues = await c.values() + assert.deepStrictEqual(cValues.map(e => e.payload), tmp) // make sure logX comes after A, B and C let logX = new Log(ipfs, testIdentity4, { logId: 'X' }) await logX.append('1') await logX.append('2') await logX.append('3') - const d = await Log.fromEntry(ipfs, testIdentity3, last(logX.values), + const xValues = await logX.values() + const d = await Log.fromEntry(ipfs, testIdentity3, last(xValues), { length: -1 }) await c.join(d) @@ -495,13 +508,17 @@ Object.keys(testAPIs).forEach((IPFS) => { await c.append('DONE') await d.append('DONE') - const f = await Log.fromEntry(ipfs, testIdentity3, last(c.values), + cValues = await c.values() + const f = await Log.fromEntry(ipfs, testIdentity3, last(cValues), { amount: -1, exclude: [] }) - const g = await Log.fromEntry(ipfs, testIdentity3, last(d.values), + const dValues = await d.values() + const g = await Log.fromEntry(ipfs, testIdentity3, last(dValues), { length: -1, exclude: [] }) - assert.strictEqual(f.toString(), bigLogString) - assert.strictEqual(g.toString(), bigLogString) + const fString = await f.toString() + const gString = await g.toString() + assert.strictEqual(fString, bigLogString) + assert.strictEqual(gString, bigLogString) }) it('retrieves full log of randomly joined log', async () => { @@ -538,7 +555,8 @@ Object.keys(testAPIs).forEach((IPFS) => { 'entryA11', 'entryA12', 'entryA13', 'entryA14', 'entryA15' ] - assert.deepStrictEqual(log1.values.map(e => e.payload), expectedData) + const values1 = await log1.values() + assert.deepStrictEqual(values1.map(e => e.payload), expectedData) }) it('retrieves randomly joined log deterministically', async () => { @@ -574,7 +592,8 @@ Object.keys(testAPIs).forEach((IPFS) => { 'entryC0', 'entryA7', 'entryA8', 'entryA9', 'entryA10' ] - assert.deepStrictEqual(log.values.map(e => e.payload), expectedData) + const values = await log.values() + assert.deepStrictEqual(values.map(e => e.payload), expectedData) }) it('sorts', async () => { @@ -603,26 +622,27 @@ Object.keys(testAPIs).forEach((IPFS) => { 'entryA8', 'entryA9', 'entryA10' ] - let fetchOrder = log.values.slice().sort(Entry.compare) + const values = await log.values() + let fetchOrder = values.slice().sort(Entry.compare) assert.deepStrictEqual(fetchOrder.map(e => e.payload), expectedData) - let reverseOrder = log.values.slice().reverse().sort(Entry.compare) + let reverseOrder = values.slice().reverse().sort(Entry.compare) assert.deepStrictEqual(fetchOrder, reverseOrder) - let hashOrder = log.values.slice().sort((a, b) => a.hash > b.hash).sort(Entry.compare) + let hashOrder = values.slice().sort((a, b) => a.hash > b.hash).sort(Entry.compare) assert.deepStrictEqual(fetchOrder, hashOrder) - let randomOrder2 = log.values.slice().sort((a, b) => 0.5 - Math.random()).sort(Entry.compare) + let randomOrder2 = values.slice().sort((a, b) => 0.5 - Math.random()).sort(Entry.compare) assert.deepStrictEqual(fetchOrder, randomOrder2) // partial data - let partialLog = log.values.filter(e => e.payload !== 'entryC0').sort(Entry.compare) + let partialLog = values.filter(e => e.payload !== 'entryC0').sort(Entry.compare) assert.deepStrictEqual(partialLog.map(e => e.payload), expectedData2) - let partialLog2 = log.values.filter(e => e.payload !== 'entryA10').sort(Entry.compare) + let partialLog2 = values.filter(e => e.payload !== 'entryA10').sort(Entry.compare) assert.deepStrictEqual(partialLog2.map(e => e.payload), expectedData3) - let partialLog3 = log.values.filter(e => e.payload !== 'entryB5').sort(Entry.compare) + let partialLog3 = values.filter(e => e.payload !== 'entryB5').sort(Entry.compare) assert.deepStrictEqual(partialLog3.map(e => e.payload), expectedData4) }) @@ -631,12 +651,14 @@ Object.keys(testAPIs).forEach((IPFS) => { let log = testLog.log const expectedData = testLog.expectedData - let fetchOrder = log.values.slice().sort(Entry.compare) + const values = await log.values() + let fetchOrder = values.slice().sort(Entry.compare) assert.deepStrictEqual(fetchOrder.map(e => e.payload), expectedData) let sorted for (let i = 0; i < 1000; i++) { - const randomOrder = log.values.slice().sort((a, b) => 0.5 - Math.random()) + const values = await log.values() + const randomOrder = values.slice().sort((a, b) => 0.5 - Math.random()) sorted = randomOrder.sort(Entry.compare) assert.deepStrictEqual(sorted.map(e => e.payload), expectedData) } @@ -646,7 +668,8 @@ Object.keys(testAPIs).forEach((IPFS) => { let testLog = await LogCreator.createLogWithTwoHundredEntries(Log, ipfs, identities) let log = testLog.log const expectedData = testLog.expectedData - assert.deepStrictEqual(log.values.map(e => e.payload), expectedData) + const values = await log.values() + assert.deepStrictEqual(values.map(e => e.payload), expectedData) }) it('sorts entries according to custom tiebreaker function', async () => { @@ -655,7 +678,8 @@ Object.keys(testAPIs).forEach((IPFS) => { let firstWriteWinsLog = new Log(ipfs, identities[0], { logId: 'X', sortFn: FirstWriteWins }) await firstWriteWinsLog.join(testLog.log) - assert.deepStrictEqual(firstWriteWinsLog.values.map(e => e.payload), + const firstWriteWinsLogValues = await firstWriteWinsLog.values() + assert.deepStrictEqual(firstWriteWinsLogValues.map(e => e.payload), firstWriteExpectedData) }) @@ -664,7 +688,7 @@ Object.keys(testAPIs).forEach((IPFS) => { let firstWriteWinsLog = new Log(ipfs, identities[0], { logId: 'X', sortFn: BadComparatorReturnsZero }) await firstWriteWinsLog.join(testLog.log) - assert.throws(() => firstWriteWinsLog.values, Error, 'Error Thrown') + assert.rejects(async () => firstWriteWinsLog.values(), Error, 'Error Thrown') }) it('retrieves partially joined log deterministically - single next pointer', async () => { @@ -704,7 +728,8 @@ Object.keys(testAPIs).forEach((IPFS) => { 'entryC0', 'entryA7', 'entryA8', 'entryA9', 'entryA10' ] - assert.deepStrictEqual(res.values.map(e => e.payload), first5) + const values = await res.values() + assert.deepStrictEqual(values.map(e => e.payload), first5) // First 11 res = await Log.fromMultihash(ipfs, testIdentity2, hash, { length: 11 }) @@ -716,7 +741,8 @@ Object.keys(testAPIs).forEach((IPFS) => { 'entryC0', 'entryA7', 'entryA8', 'entryA9', 'entryA10' ] - assert.deepStrictEqual(res.values.map(e => e.payload), first11) + const values2 = await res.values() + assert.deepStrictEqual(values2.map(e => e.payload), first11) // All but one res = await Log.fromMultihash(ipfs, testIdentity2, hash, { length: 16 - 1 }) @@ -728,7 +754,8 @@ Object.keys(testAPIs).forEach((IPFS) => { 'entryC0', 'entryA7', 'entryA8', 'entryA9', 'entryA10' ] - assert.deepStrictEqual(res.values.map(e => e.payload), all) + const values3 = await res.values() + assert.deepStrictEqual(values3.map(e => e.payload), all) }) it('retrieves partially joined log deterministically - multiple next pointers', async () => { @@ -768,7 +795,8 @@ Object.keys(testAPIs).forEach((IPFS) => { 'entryC0', 'entryA7', 'entryA8', 'entryA9', 'entryA10' ] - assert.deepStrictEqual(res.values.map(e => e.payload), first5) + const values = await res.values() + assert.deepStrictEqual(values.map(e => e.payload), first5) // First 11 res = await Log.fromMultihash(ipfs, testIdentity2, hash, { length: 11 }) @@ -780,7 +808,8 @@ Object.keys(testAPIs).forEach((IPFS) => { 'entryA7', 'entryA8', 'entryA9', 'entryA10' ] - assert.deepStrictEqual(res.values.map(e => e.payload), first11) + const values1 = await res.values() + assert.deepStrictEqual(values1.map(e => e.payload), first11) // All but one res = await Log.fromMultihash(ipfs, testIdentity2, hash, { length: 16 - 1 }) @@ -792,7 +821,8 @@ Object.keys(testAPIs).forEach((IPFS) => { 'entryC0', 'entryA7', 'entryA8', 'entryA9', 'entryA10' ] - assert.deepStrictEqual(res.values.map(e => e.payload), all) + const values2 = await res.values() + assert.deepStrictEqual(values2.map(e => e.payload), all) }) it('throws an error if ipfs is not defined', async () => { @@ -847,21 +877,24 @@ Object.keys(testAPIs).forEach((IPFS) => { const a = await Log.fromEntry(ipfs, testIdentity, last(items1), { length: -1 }) assert.strictEqual(a.length, amount) - assert.strictEqual(a.values[0].hash, items1[0].hash) + const values = await a.values() + assert.strictEqual(values[0].hash, items1[0].hash) }) it('returns all entries - including excluded entries', async () => { // One entry const a = await Log.fromEntry(ipfs, testIdentity, last(items1), { length: -1, exclude: [items1[0]] }) + const aValues = await a.values() assert.strictEqual(a.length, amount) - assert.strictEqual(a.values[0].hash, items1[0].hash) + assert.strictEqual(aValues[0].hash, items1[0].hash) // All entries const b = await Log.fromEntry(ipfs, testIdentity, last(items1), { length: -1, exclude: items1 }) + const bValues = await b.values() assert.strictEqual(b.length, amount) - assert.strictEqual(b.values[0].hash, items1[0].hash) + assert.strictEqual(bValues[0].hash, items1[0].hash) }) it('respects timeout parameter', async () => { @@ -873,7 +906,8 @@ Object.keys(testAPIs).forEach((IPFS) => { const et = new Date().getTime() assert.strictEqual((et - st) >= timeout, true, '' + (et - st) + ' should be greater than timeout ' + timeout) assert.strictEqual(log.length, 1) - assert.deepStrictEqual(log.values.map(e => e.payload), [e.payload]) + const values = await log.values() + assert.deepStrictEqual(values.map(e => e.payload), [e.payload]) }) }) }) @@ -922,19 +956,22 @@ Object.keys(testAPIs).forEach((IPFS) => { json.heads = await Promise.all(json.heads.map(headHash => Entry.fromMultihash(ipfs, headHash))) const log = await Log.fromJSON(ipfs, testIdentity, json, { logId: 'A' }) assert.strictEqual(log.length, 5) - assert.deepStrictEqual(log.values, v1Entries.map(e => Entry.toEntry(e, { includeHash: true }))) + const values = await log.values() + assert.deepStrictEqual(values, v1Entries.map(e => Entry.toEntry(e, { includeHash: true }))) }) it('creates a log from v1 entry', async () => { const log = await Log.fromEntry(ipfs, testIdentity, v1Entries[v1Entries.length - 1], { logId: 'A' }) assert.strictEqual(log.length, 5) - assert.deepStrictEqual(log.values, v1Entries.map(e => Entry.toEntry(e, { includeHash: true }))) + const values = await log.values() + assert.deepStrictEqual(values, v1Entries.map(e => Entry.toEntry(e, { includeHash: true }))) }) it('creates a log from v1 entry hash', async () => { const log = await Log.fromEntryHash(ipfs, testIdentity, v1Entries[v1Entries.length - 1].hash, { logId: 'A' }) assert.strictEqual(log.length, 5) - assert.deepStrictEqual(log.values, v1Entries.map(e => Entry.toEntry(e, { includeHash: true }))) + const values = await log.values() + assert.deepStrictEqual(values, v1Entries.map(e => Entry.toEntry(e, { includeHash: true }))) }) it('creates a log from log hash of v1 entries', async () => { @@ -942,7 +979,8 @@ Object.keys(testAPIs).forEach((IPFS) => { const hash = await log1.toMultihash() const log = await Log.fromMultihash(ipfs, testIdentity, hash, { logId: 'A' }) assert.strictEqual(log.length, 5) - assert.deepStrictEqual(log.values, v1Entries.map(e => Entry.toEntry(e, { includeHash: true }))) + const values = await log.values() + assert.deepStrictEqual(values, v1Entries.map(e => Entry.toEntry(e, { includeHash: true }))) }) }) }) diff --git a/test/log-references.spec.js b/test/log-references.spec.js index 057eb6b2..19d7ca8d 100644 --- a/test/log-references.spec.js +++ b/test/log-references.spec.js @@ -77,14 +77,19 @@ Object.keys(testAPIs).forEach((IPFS) => { await log4.append(i.toString(), Math.pow(maxReferenceDistance, 4)) } - assert.strict.equal(log1.values[log1.length - 1].next.length, 1) - assert.strict.equal(log2.values[log2.length - 1].next.length, 1) - assert.strict.equal(log3.values[log3.length - 1].next.length, 1) - assert.strict.equal(log4.values[log4.length - 1].next.length, 1) - assert.strict.equal(log1.values[log1.length - 1].refs.length, 1) - assert.strict.equal(log2.values[log2.length - 1].refs.length, 2) - assert.strict.equal(log3.values[log3.length - 1].refs.length, 3) - assert.strict.equal(log4.values[log4.length - 1].refs.length, 4) + const values1 = await log1.values() + const values2 = await log2.values() + const values3 = await log3.values() + const values4 = await log4.values() + + assert.strict.equal(values1[log1.length - 1].next.length, 1) + assert.strict.equal(values2[log2.length - 1].next.length, 1) + assert.strict.equal(values3[log3.length - 1].next.length, 1) + assert.strict.equal(values4[log4.length - 1].next.length, 1) + assert.strict.equal(values1[log1.length - 1].refs.length, 1) + assert.strict.equal(values2[log2.length - 1].refs.length, 2) + assert.strict.equal(values3[log3.length - 1].refs.length, 3) + assert.strict.equal(values4[log4.length - 1].refs.length, 4) }) const inputs = [ @@ -119,31 +124,32 @@ Object.keys(testAPIs).forEach((IPFS) => { await log1.append((i + 1).toString(), referenceCount) } - assert.strict.equal(log1.values.length, input.amount) - assert.strict.equal(log1.values[log1.length - 1].clock.time, input.amount) + const values1 = await log1.values() + assert.strict.equal(values1.length, input.amount) + assert.strict.equal(values1[log1.length - 1].clock.time, input.amount) for (let k = 0; k < input.amount; k++) { const idx = log1.length - k - 1 - assert.strict.equal(log1.values[idx].clock.time, idx + 1) + assert.strict.equal(values1[idx].clock.time, idx + 1) // Check the first ref (distance 2) - if (log1.values[idx].refs.length > 0) { assert.strict.equal(log1.values[idx].refs[0], log1.values[idx - 2].hash) } + if (values1[idx].refs.length > 0) { assert.strict.equal(values1[idx].refs[0], values1[idx - 2].hash) } // Check the second ref (distance 2) - if (log1.values[idx].refs.length > 1 && idx > referenceCount) { assert.strict.equal(log1.values[idx].refs[1], log1.values[idx - 4].hash) } + if (values1[idx].refs.length > 1 && idx > referenceCount) { assert.strict.equal(values1[idx].refs[1], values1[idx - 4].hash) } // Check the third ref (distance 4) - if (log1.values[idx].refs.length > 2 && idx > referenceCount) { assert.strict.equal(log1.values[idx].refs[2], log1.values[idx - 8].hash) } + if (values1[idx].refs.length > 2 && idx > referenceCount) { assert.strict.equal(values1[idx].refs[2], values1[idx - 8].hash) } // Check the fourth ref (distance 8) - if (log1.values[idx].refs.length > 3 && idx > referenceCount) { assert.strict.equal(log1.values[idx].refs[3], log1.values[idx - 16].hash) } + if (values1[idx].refs.length > 3 && idx > referenceCount) { assert.strict.equal(values1[idx].refs[3], values1[idx - 16].hash) } // Check the fifth ref (distance 16) - if (log1.values[idx].refs.length > 4 && idx > referenceCount) { assert.strict.equal(log1.values[idx].refs[4], log1.values[idx - 32].hash) } + if (values1[idx].refs.length > 4 && idx > referenceCount) { assert.strict.equal(values1[idx].refs[4], values1[idx - 32].hash) } // Check the reference of each entry - if (idx > referenceCount) { assert.strict.equal(log1.values[idx].refs.length, refLength) } + if (idx > referenceCount) { assert.strict.equal(values1[idx].refs.length, refLength) } } } diff --git a/test/log.spec.js b/test/log.spec.js index 57ce47a1..2b6bf1f0 100644 --- a/test/log.spec.js +++ b/test/log.spec.js @@ -65,16 +65,17 @@ Object.keys(testAPIs).forEach((IPFS) => { const log = new Log(ipfs, testIdentity) assert.notStrictEqual(log._entryIndex, null) assert.notStrictEqual(log._headsIndex, null) + assert.notStrictEqual(log._hashIndex, new Map()) assert.notStrictEqual(log._id, null) assert.notStrictEqual(log.id, null) assert.notStrictEqual(log.clock, null) - assert.notStrictEqual(log.values, null) + // assert.notStrictEqual(log.values, new Promise(() => {})) //TODO assert.notStrictEqual(log.heads, null) - assert.notStrictEqual(log.tails, null) + // assert.notStrictEqual(log.tails, null) // TODO assert.notStrictEqual(log.tailCids, null) - assert.deepStrictEqual(log.values, []) + // assert.deepStrictEqual(log.values, []) // TODO assert.deepStrictEqual(log.heads, []) - assert.deepStrictEqual(log.tails, []) + // assert.deepStrictEqual(log.tails, []) // TODO }) it('throws an error if IPFS instance is not passed as an argument', () => { @@ -109,10 +110,11 @@ Object.keys(testAPIs).forEach((IPFS) => { const three = await Entry.create(ipfs, testIdentity, 'A', 'entryC', [], new Clock('C', 0)) const log = new Log(ipfs, testIdentity, { logId: 'A', entries: [one, two, three] }) + const values = await log.values() assert.strictEqual(log.length, 3) - assert.strictEqual(log.values[0].payload, 'entryA') - assert.strictEqual(log.values[1].payload, 'entryB') - assert.strictEqual(log.values[2].payload, 'entryC') + assert.strictEqual(values[0].payload, 'entryA') + assert.strictEqual(values[1].payload, 'entryB') + assert.strictEqual(values[2].payload, 'entryC') }) it('sets heads if given as params', async () => { @@ -191,8 +193,9 @@ Object.keys(testAPIs).forEach((IPFS) => { await log.append('five') }) - it('returns a nicely formatted string', () => { - assert.strictEqual(log.toString(), expectedData) + it('returns a nicely formatted string', async () => { + const logString = await log.toString() + assert.strictEqual(logString, expectedData) }) }) @@ -204,13 +207,14 @@ Object.keys(testAPIs).forEach((IPFS) => { await log.append('one') }) - it('returns an Entry', () => { - const entry = log.get(log.values[0].hash) + it('returns an Entry', async () => { + const values = await log.values() + const entry = await log.get(values[0].hash) assert.deepStrictEqual(entry.hash, 'zdpuAoFzNYcuuQHk1gLcB8fomHGrqT9k1uQeAvewZJ1cSYrms') }) - it('returns undefined when Entry is not in the log', () => { - const entry = log.get('QmFoo') + it('returns undefined when Entry is not in the log', async () => { + const entry = await log.get('QmFoo') assert.deepStrictEqual(entry, undefined) }) }) @@ -224,16 +228,19 @@ Object.keys(testAPIs).forEach((IPFS) => { }) it('changes identity', async () => { - assert.strictEqual(log.values[0].clock.id, testIdentity.publicKey) - assert.strictEqual(log.values[0].clock.time, 1) + let values = await log.values() + assert.strictEqual(values[0].clock.id, testIdentity.publicKey) + assert.strictEqual(values[0].clock.time, 1) log.setIdentity(testIdentity2) await log.append('two') - assert.strictEqual(log.values[1].clock.id, testIdentity2.publicKey) - assert.strictEqual(log.values[1].clock.time, 2) + values = await log.values() + assert.strictEqual(values[1].clock.id, testIdentity2.publicKey) + assert.strictEqual(values[1].clock.time, 2) log.setIdentity(testIdentity3) await log.append('three') - assert.strictEqual(log.values[2].clock.id, testIdentity3.publicKey) - assert.strictEqual(log.values[2].clock.time, 3) + values = await log.values() + assert.strictEqual(values[2].clock.id, testIdentity3.publicKey) + assert.strictEqual(values[2].clock.time, 3) }) }) @@ -304,8 +311,8 @@ Object.keys(testAPIs).forEach((IPFS) => { ] } - it('returns the log snapshot', () => { - const snapshot = log.toSnapshot() + it('returns the log snapshot', async () => { + const snapshot = await log.toSnapshot() assert.strictEqual(snapshot.id, expectedData.id) assert.strictEqual(snapshot.heads.length, expectedData.heads.length) assert.strictEqual(snapshot.heads[0].hash, expectedData.heads[0]) @@ -406,23 +413,25 @@ Object.keys(testAPIs).forEach((IPFS) => { await log.append('one') const hash = await log.toMultihash() const res = await Log.fromMultihash(ipfs, testIdentity, hash, -1) + const values = await res.values() assert.strictEqual(JSON.stringify(res.toJSON()), JSON.stringify(expectedData)) assert.strictEqual(res.length, 1) - assert.strictEqual(res.values[0].payload, 'one') - assert.strictEqual(res.values[0].clock.id, testIdentity.publicKey) - assert.strictEqual(res.values[0].clock.time, 1) + assert.strictEqual(values[0].payload, 'one') + assert.strictEqual(values[0].clock.id, testIdentity.publicKey) + assert.strictEqual(values[0].clock.time, 1) }) it('creates a log from ipfs CID - three entries', async () => { const hash = await log.toMultihash() const res = await Log.fromMultihash(ipfs, testIdentity, hash, -1) + const values = await res.values() assert.strictEqual(res.length, 3) - assert.strictEqual(res.values[0].payload, 'one') - assert.strictEqual(res.values[0].clock.time, 1) - assert.strictEqual(res.values[1].payload, 'two') - assert.strictEqual(res.values[1].clock.time, 2) - assert.strictEqual(res.values[2].payload, 'three') - assert.strictEqual(res.values[2].clock.time, 3) + assert.strictEqual(values[0].payload, 'one') + assert.strictEqual(values[0].clock.time, 1) + assert.strictEqual(values[1].payload, 'two') + assert.strictEqual(values[1].clock.time, 2) + assert.strictEqual(values[2].payload, 'three') + assert.strictEqual(values[2].clock.time, 3) }) it('creates a log from ipfs multihash (backwards compat)', async () => { @@ -434,21 +443,24 @@ Object.keys(testAPIs).forEach((IPFS) => { await log.append('one') const multihash = await log.toMultihash() const res = await Log.fromMultihash(ipfs, testIdentity, multihash, { length: -1 }) + const values = await res.values() assert.strictEqual(JSON.stringify(res.toJSON()), JSON.stringify(expectedData)) assert.strictEqual(res.length, 1) - assert.strictEqual(res.values[0].payload, 'one') - assert.strictEqual(res.values[0].clock.id, testIdentity.publicKey) - assert.strictEqual(res.values[0].clock.time, 1) + assert.strictEqual(values[0].payload, 'one') + assert.strictEqual(values[0].clock.id, testIdentity.publicKey) + assert.strictEqual(values[0].clock.time, 1) }) it('has the right sequence number after creation and appending', async () => { const hash = await log.toMultihash() let res = await Log.fromMultihash(ipfs, testIdentity, hash, { length: -1 }) + let values = await res.values() assert.strictEqual(res.length, 3) await res.append('four') + values = await res.values() assert.strictEqual(res.length, 4) - assert.strictEqual(res.values[3].payload, 'four') - assert.strictEqual(res.values[3].clock.time, 4) + assert.strictEqual(values[3].payload, 'four') + assert.strictEqual(values[3].clock.time, 4) }) it('creates a log from ipfs CID that has three heads', async () => { @@ -567,7 +579,7 @@ Object.keys(testAPIs).forEach((IPFS) => { await log.append(i.toString()) } - const items = log.values + const items = await log.values() let i = 0 const loadProgressCallback = (hash, entry, depth) => { assert.notStrictEqual(entry, null) @@ -582,13 +594,14 @@ Object.keys(testAPIs).forEach((IPFS) => { const result = await Log.fromMultihash(ipfs, testIdentity, hash, { length: -1, exclude: [], onProgressCallback: loadProgressCallback }) + const values = await result.values() // Make sure the onProgress callback was called for each entry assert.strictEqual(i, amount) // Make sure the log entries are correct ones - assert.strictEqual(result.values[0].clock.time, 1) - assert.strictEqual(result.values[0].payload, '0') - assert.strictEqual(result.values[result.length - 1].clock.time, 100) - assert.strictEqual(result.values[result.length - 1].payload, '99') + assert.strictEqual(values[0].clock.time, 1) + assert.strictEqual(values[0].payload, '0') + assert.strictEqual(values[result.length - 1].clock.time, 100) + assert.strictEqual(values[result.length - 1].payload, '99') }) }) @@ -649,16 +662,18 @@ Object.keys(testAPIs).forEach((IPFS) => { describe('values', () => { it('returns all entries in the log', async () => { let log = new Log(ipfs, testIdentity) - assert.strictEqual(log.values instanceof Array, true) + let values = await log.values() + assert.strictEqual(values instanceof Array, true) assert.strictEqual(log.length, 0) await log.append('hello1') await log.append('hello2') await log.append('hello3') - assert.strictEqual(log.values instanceof Array, true) + values = await log.values() + assert.strictEqual(values instanceof Array, true) assert.strictEqual(log.length, 3) - assert.strictEqual(log.values[0].payload, 'hello1') - assert.strictEqual(log.values[1].payload, 'hello2') - assert.strictEqual(log.values[2].payload, 'hello3') + assert.strictEqual(values[0].payload, 'hello1') + assert.strictEqual(values[1].payload, 'hello2') + assert.strictEqual(values[2].payload, 'hello3') }) }) }) diff --git a/test/replicate.spec.js b/test/replicate.spec.js index 06cf06d8..97dc81d8 100644 --- a/test/replicate.spec.js +++ b/test/replicate.spec.js @@ -163,19 +163,21 @@ Object.keys(testAPIs).forEach((IPFS) => { await result.join(log1) await result.join(log2) + const values = await result.values() + assert.strictEqual(buffer1.length, amount) assert.strictEqual(buffer2.length, amount) assert.strictEqual(result.length, amount * 2) assert.strictEqual(log1.length, amount) assert.strictEqual(log2.length, amount) - assert.strictEqual(result.values[0].payload, 'A1') - assert.strictEqual(result.values[1].payload, 'B1') - assert.strictEqual(result.values[2].payload, 'A2') - assert.strictEqual(result.values[3].payload, 'B2') - assert.strictEqual(result.values[99].payload, 'B50') - assert.strictEqual(result.values[100].payload, 'A51') - assert.strictEqual(result.values[198].payload, 'A100') - assert.strictEqual(result.values[199].payload, 'B100') + assert.strictEqual(values[0].payload, 'A1') + assert.strictEqual(values[1].payload, 'B1') + assert.strictEqual(values[2].payload, 'A2') + assert.strictEqual(values[3].payload, 'B2') + assert.strictEqual(values[99].payload, 'B50') + assert.strictEqual(values[100].payload, 'A51') + assert.strictEqual(values[198].payload, 'A100') + assert.strictEqual(values[199].payload, 'B100') }) }) }) diff --git a/test/signed-log.spec.js b/test/signed-log.spec.js index 856776a0..66af7588 100644 --- a/test/signed-log.spec.js +++ b/test/signed-log.spec.js @@ -87,8 +87,9 @@ Object.keys(testAPIs).forEach((IPFS) => { it('entries contain an identity', async () => { const log = new Log(ipfs, testIdentity, { logId: 'A' }) await log.append('one') - assert.notStrictEqual(log.values[0].sig, null) - assert.deepStrictEqual(log.values[0].identity, testIdentity.toJSON()) + const values = await log.values() + assert.notStrictEqual(values[0].sig, null) + assert.deepStrictEqual(values[0].identity, testIdentity.toJSON()) }) it('doesn\'t sign entries when identity is not defined', async () => { @@ -116,10 +117,11 @@ Object.keys(testAPIs).forEach((IPFS) => { throw e } + const values1 = await log1.values() assert.strictEqual(err, undefined) assert.strictEqual(log1.id, 'A') - assert.strictEqual(log1.values.length, 1) - assert.strictEqual(log1.values[0].payload, 'one') + assert.strictEqual(values1.length, 1) + assert.strictEqual(values1[0].payload, 'one') }) it('throws an error if log is signed but trying to merge with an entry that doesn\'t have public signing key', async () => { @@ -130,7 +132,8 @@ Object.keys(testAPIs).forEach((IPFS) => { try { await log1.append('one') await log2.append('two') - delete log2.values[0].key + const values2 = await log2.values() + delete values2[0].key await log1.join(log2) } catch (e) { err = e.toString() @@ -146,7 +149,8 @@ Object.keys(testAPIs).forEach((IPFS) => { try { await log1.append('one') await log2.append('two') - delete log2.values[0].sig + const values2 = await log2.values() + delete values2[0].sig await log1.join(log2) } catch (e) { err = e.toString() @@ -162,16 +166,21 @@ Object.keys(testAPIs).forEach((IPFS) => { try { await log1.append('one') await log2.append('two') - log2.values[0].sig = log1.values[0].sig + const values1 = await log1.values() + const values2 = await log2.values() + values2[0].sig = values1[0].sig await log1.join(log2) } catch (e) { err = e.toString() } - const entry = log2.values[0] + const values1 = await log1.values() + const values2 = await log2.values() + + const entry = values2[0] assert.strictEqual(err, `Error: Could not validate signature "${entry.sig}" for entry "${entry.hash}" and key "${entry.key}"`) - assert.strictEqual(log1.values.length, 1) - assert.strictEqual(log1.values[0].payload, 'one') + assert.strictEqual(values1.length, 1) + assert.strictEqual(values1[0].payload, 'one') }) it('throws an error if entry doesn\'t have append access', async () => {