From 47ec987221b9b6303aa2f9894f42dc91cff9483a Mon Sep 17 00:00:00 2001 From: Christian Bundy Date: Thu, 18 Jun 2020 15:26:18 -0700 Subject: [PATCH 1/4] Add boxer init method Problem: Boxer init and unboxer init happen at different times, and the constraint that they happen at the same time can lead to a circular dependency where indexing becomes locked. Solution: Add boxer init method. --- README.md | 8 +- minimal.js | 30 +++++- package-lock.json | 202 ++++++++++++++++++++++++++++++++++++---- package.json | 5 +- test/box-unbox.js | 29 ++++-- test/private2.js | 30 ++++++ test/rebuild.js | 3 + test/util/create-ssb.js | 6 +- 8 files changed, 279 insertions(+), 34 deletions(-) create mode 100644 test/private2.js diff --git a/README.md b/README.md index aa8605fa..4e1de22d 100644 --- a/README.md +++ b/README.md @@ -593,7 +593,11 @@ db.since(fn(seq)) => Obv An [observable](https://github.com/dominictarr/obv) of the current log sequence. This is always a positive integer that usually increases, except in the exceptional circumstance that the log is deleted or corrupted. -### db.addBoxer(boxer) +### db.addBoxer: sync + +```js +db.addUnboxer({ value: boxer, init: initBoxer }) +``` Add a `boxer`, which will be added to the list of boxers which will try to automatically box (encrypt) the message `content` if the appropriate @@ -605,9 +609,11 @@ automatically box (encrypt) the message `content` if the appropriate - break (because it should know how to handle `recps`, but can't), and so throw an `Error` ## db.addUnboxer: sync + ```js db.addUnboxer({ key: unboxKey, value: unboxValue, init: initBoxer }) ``` + Add an unboxer object, any encrypted message is passed to the unboxer object to test if it can be unboxed (decrypted) diff --git a/minimal.js b/minimal.js index 159d86bf..aad1c16a 100644 --- a/minimal.js +++ b/minimal.js @@ -29,7 +29,8 @@ module.exports = function (dirname, keys, opts) { var setup = { validators: new u.AsyncJobQueue(), - unboxers: new u.AsyncJobQueue() + unboxers: new u.AsyncJobQueue(), + boxers: new u.AsyncJobQueue() } function waitForValidators (fn) { return function (...args) { @@ -41,6 +42,11 @@ module.exports = function (dirname, keys, opts) { setup.unboxers.runAll(() => fn(...args)) } } + function waitForBoxers (fn) { + return function (...args) { + setup.boxers.runAll(() => fn(...args)) + } + } const unboxerMap = waitForUnboxers((msg, cb) => { try { @@ -108,7 +114,7 @@ module.exports = function (dirname, keys, opts) { }) }) - db.append = waitForUnboxers(waitForValidators(function dbAppend (opts, cb) { + db.append = waitForBoxers(waitForValidators(function dbAppend (opts, cb) { try { const content = box(opts.content, boxers) var msg = V.create( @@ -144,7 +150,25 @@ module.exports = function (dirname, keys, opts) { } db.addBoxer = function addBoxer (boxer) { - boxers.push(boxer) + switch (typeof boxer) { + case 'function': + boxers.push(boxer) + break + + case 'object': + if (typeof boxer.value !== 'function') throw new Error('invalid boxer') + + if (boxer.init) { + setup.boxers.add(boxer.init) + setup.boxers.runAll() + } + + boxers.push(boxer.value) + + break + + default: throw new Error('invalid boxer') + } } db.addUnboxer = function addUnboxer (unboxer) { diff --git a/package-lock.json b/package-lock.json index 22481fe0..76b93c4a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -139,6 +139,15 @@ "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", "dev": true }, + "buffer-xor": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-2.0.2.tgz", + "integrity": "sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.1" + } + }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -336,6 +345,24 @@ "level-errors": "^2.0.0" } }, + "envelope-js": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/envelope-js/-/envelope-js-0.1.1.tgz", + "integrity": "sha512-VHVBUtcni6VfMMXGiI1ydSILGVI7QxyZJJWUEob9taiYDxLfLgL/PQt0syq/vH1Ao6FXh7odP7Mps+RnIDEaiQ==", + "dev": true, + "requires": { + "buffer-xor": "^2.0.2", + "envelope-spec": "0.0.1", + "futoin-hkdf": "^1.3.0", + "sodium-native": "^2.4.6" + } + }, + "envelope-spec": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/envelope-spec/-/envelope-spec-0.0.1.tgz", + "integrity": "sha512-ATCTKN7bnysBeRm+yNFoJwSarm5+z5R0ly+/xgR05Dc8AjNI5T4U3ubc3HYCVGTIrP7TDF9BDRLhHQVata6qQQ==", + "dev": true + }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", @@ -432,13 +459,13 @@ } }, "flumedb": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/flumedb/-/flumedb-2.1.5.tgz", - "integrity": "sha512-SD2VL5RZf5EtD/PIeXcvICQmr+E1w0KDAjWaocQN5/ztzwPw42eaDkAVQcQr0xaWOD88HXWqqPdQitjsnSC04w==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/flumedb/-/flumedb-2.1.8.tgz", + "integrity": "sha512-MtBCZFjj9GuqOQP8Ld87FbXm8ztQyLkLeuiHuB5+aACFuVn1kunnCis75R03ujFZTqCFmkBwFz7E016b3DB0zA==", "requires": { "cont": "^1.0.3", "explain-error": "^1.0.3", - "obv": "0.0.1", + "obz": "1.0.2", "pull-abortable": "^4.1.1", "pull-cont": "^0.1.1", "pull-looper": "^1.0.0", @@ -463,27 +490,20 @@ } }, "flumeview-level": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/flumeview-level/-/flumeview-level-4.0.3.tgz", - "integrity": "sha512-lmSiImD7vNJ9pC9hB2j9hgx5WhleUZM5n69e2qUTGU4LCyvCbVuzn85pKfqdrKEAMuVjbb+jEPEErPJFNRj0SQ==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/flumeview-level/-/flumeview-level-4.0.4.tgz", + "integrity": "sha512-8C/o/oZU73ot1LMbxCyKeZJ0D3L5AGdxzIF5H2QtmznMSoZHVG1gT2IDjkOtesenVPlLQKnL95ewMKbE7cXWEw==", "requires": { "charwise": "^3.0.1", "explain-error": "^1.0.4", "level": "^6.0.1", "ltgt": "^2.1.3", "mkdirp": "^1.0.4", - "obv": "0.0.1", + "obz": "^1.0.2", "pull-level": "^2.0.3", "pull-paramap": "^1.2.1", "pull-stream": "^3.6.14", "pull-write": "^1.1.1" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - } } }, "flumeview-reduce": { @@ -525,6 +545,30 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "futoin-hkdf": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/futoin-hkdf/-/futoin-hkdf-1.3.2.tgz", + "integrity": "sha512-3EVi3ETTyJg5PSXlxLCaUVVn0pSbDf62L3Gwxne7Uq+d8adOSNWQAad4gg7WToHkcgnCJb3Wlb1P8r4Evj4GPw==", + "dev": true + }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dev": true, + "requires": { + "is-property": "^1.0.2" + } + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "^1.0.0" + } + }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -619,8 +663,7 @@ "ini": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "optional": true + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, "int53": { "version": "1.0.0", @@ -681,12 +724,47 @@ "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==", "dev": true }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", + "dev": true + }, + "is-my-json-valid": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz", + "integrity": "sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA==", + "dev": true, + "requires": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^4.0.0", + "xtend": "^4.0.0" + } + }, + "is-my-ssb-valid": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-my-ssb-valid/-/is-my-ssb-valid-1.1.0.tgz", + "integrity": "sha512-HAcl2v9tIkpjfVqaNgaqYWk2MW3WPZtj+XVpKUMgQRWEbLJdZ4orE5l9SJ5t+bQO1LB5rKeYGTlMfxSXEG1NTw==", + "dev": true, + "requires": { + "is-my-json-valid": "^2.20.0", + "ssb-msg-content": "^1.0.1" + } + }, "is-number-object": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", "dev": true }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, "is-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", @@ -755,6 +833,12 @@ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-2.0.11.tgz", "integrity": "sha1-PkQf2jCYvo0eMXGtWRvGKjPi1V8=" }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, "level": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/level/-/level-6.0.1.tgz", @@ -870,6 +954,36 @@ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", + "dev": true + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.set": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", + "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=", + "dev": true + }, "looper": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/looper/-/looper-4.0.0.tgz", @@ -986,8 +1100,7 @@ "nan": { "version": "2.14.1", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", - "optional": true + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==" }, "napi-macros": { "version": "2.0.0", @@ -1061,6 +1174,11 @@ "resolved": "https://registry.npmjs.org/obv/-/obv-0.0.1.tgz", "integrity": "sha1-yyNhBjQVNvDaxIFeBnCCIcrX+14=" }, + "obz": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/obz/-/obz-1.0.2.tgz", + "integrity": "sha512-c+EtVwT2IpXz5we2mR40aPLJ1s0eNOsxYeaYbaHhmsY6kWKo3IRkpwpBU5ck0aHfqfKUUEiKabC6rzsrG/hSHw==" + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1133,6 +1251,11 @@ "chloride": "^2.2.9" } }, + "private-group-spec": { + "version": "github:ssbc/private-group-spec#03a383b5ecc7f5ad17e36f49760e5d39e95b4239", + "from": "github:ssbc/private-group-spec", + "dev": true + }, "process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", @@ -1584,7 +1707,6 @@ "version": "2.4.9", "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-2.4.9.tgz", "integrity": "sha512-mbkiyA2clyfwAyOFIzMvsV6ny2KrKEIhFVASJxWfsmgfUEymgLIS2MLHHcGIQMkrcKhPErRaMR5Dzv0EEn+BWg==", - "optional": true, "requires": { "ini": "^1.3.5", "nan": "^2.14.0", @@ -1639,6 +1761,12 @@ } } }, + "ssb-msg-content": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ssb-msg-content/-/ssb-msg-content-1.0.1.tgz", + "integrity": "sha512-M6W0Ef+jif829USmGvh6XeS4lYb/F2lgFhfEoCE/md7ESILNOGidp8frJE2uVOzSr2wVRA265tPrnVb7rYHkug==", + "dev": true + }, "ssb-msgs": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ssb-msgs/-/ssb-msgs-5.2.0.tgz", @@ -1657,6 +1785,27 @@ "ssb-ref": "^2.13.9" } }, + "ssb-private2": { + "version": "github:ssbc/ssb-private2#ae4c5c5191942c582d967e97c0f129658ae8d57d", + "from": "github:ssbc/ssb-private2#boxer-init", + "dev": true, + "requires": { + "charwise": "^3.0.1", + "envelope-js": "^0.1.1", + "envelope-spec": "0.0.1", + "futoin-hkdf": "^1.3.2", + "is-canonical-base64": "^1.1.1", + "is-my-ssb-valid": "^1.1.0", + "level": "^6.0.1", + "lodash.set": "^4.3.2", + "private-group-spec": "github:ssbc/private-group-spec", + "pull-level": "^2.0.4", + "pull-stream": "^3.6.14", + "sodium-native": "^2.4.9", + "ssb-ref": "^2.14.0", + "ssb-tangle": "^2.1.0" + } + }, "ssb-ref": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/ssb-ref/-/ssb-ref-2.14.0.tgz", @@ -1668,6 +1817,19 @@ "multiserver-address": "^1.0.1" } }, + "ssb-tangle": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ssb-tangle/-/ssb-tangle-2.1.0.tgz", + "integrity": "sha512-VPuMzK8DhnoU6za1Qa4RDfA/qQwOvMSa1e7s2UMbSxBk+0aa3Kw/LiZ0r6THPEIxWnYgMvc5KYMndSDRaqKT1Q==", + "dev": true, + "requires": { + "lodash.clone": "^4.5.0", + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "lodash.merge": "^4.6.2", + "lodash.set": "^4.3.2" + } + }, "ssb-validate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ssb-validate/-/ssb-validate-4.1.0.tgz", diff --git a/package.json b/package.json index 82b94ca9..f088537a 100644 --- a/package.json +++ b/package.json @@ -15,9 +15,9 @@ }, "dependencies": { "async-write": "^2.1.0", - "flumedb": "^2.1.5", + "flumedb": "^2.1.8", "flumelog-offset": "^3.4.2", - "flumeview-level": "^4.0.3", + "flumeview-level": "^4.0.4", "flumeview-reduce": "^1.3.17", "hashlru": "^2.3.0", "ltgt": "^2.2.0", @@ -44,6 +44,7 @@ "secret-stack": "^6.3.1", "ssb-feed": "^2.2.1", "ssb-private1": "^1.0.1", + "ssb-private2": "github:ssbc/ssb-private2#boxer-init", "tap-spec": "^5.0.0", "tape": "^5.0.0", "typewiselite": "^1.0.0" diff --git a/test/box-unbox.js b/test/box-unbox.js index 71e9e2f8..58fe4642 100644 --- a/test/box-unbox.js +++ b/test/box-unbox.js @@ -290,16 +290,28 @@ function run () { }) tape('addUnboxer (with init)', function (t) { - var initDone = false + let unboxerInitDone = false + let boxerInitDone = false - const unboxer = { + const boxer = { init: function (done) { setTimeout(() => { - t.ok(true, 'calls init') - initDone = true + t.ok(true, 'calls boxer init') + boxerInitDone = true done() }, 500) }, + value: (x) => x + } + + const unboxer = { + init: function (done) { + setTimeout(() => { + t.ok(true, 'calls unboxer init') + unboxerInitDone = true + done() + }, 1000) + }, key: function (ciphertext) { if (!ciphertext.endsWith('.box.hah')) return @@ -312,8 +324,10 @@ function run () { ) } } + ssb.addBoxer(boxer) ssb.addUnboxer(unboxer) - t.false(initDone) + t.false(boxerInitDone) + t.false(unboxerInitDone) const content = { type: 'poke', @@ -324,12 +338,13 @@ function run () { const ciphertext = Buffer.from(JSON.stringify(content)).toString('base64') + '.box.hah' feed.publish(ciphertext, (_, msg) => { - t.true(initDone, 'unboxer completed initialisation before publish') + t.true(boxerInitDone, 'boxer completed initialisation before publish') + t.false(unboxerInitDone, 'unboxer did not completed initialisation before publish') ssb.get({ id: msg.key, private: true, meta: true }, async (err, msg) => { t.error(err) - t.true(initDone, 'unboxer completed initialisation before get') + t.true(unboxerInitDone, 'unboxer completed initialisation before get') t.deepEqual(msg.value.content, content, 'auto unboxing works') const assertBoxed = (methodName, message) => { diff --git a/test/private2.js b/test/private2.js new file mode 100644 index 00000000..986be51a --- /dev/null +++ b/test/private2.js @@ -0,0 +1,30 @@ +const createSSB = require('./util/create-ssb') +const tape = require('tape') +const { promisify } = require('util') + +tape('partial index', async (t) => { + const name = `test-ssb-partial-index-${Date.now()}` + + t.plan(6) + + const ssb = createSSB(name, { temp: false }) + const { key } = await promisify(ssb.publish)({ type: 'test' }) + t.pass('published') + + await promisify(ssb.rebuild)() + t.pass('rebuilt') + + await promisify(ssb.close)() + t.pass('closed') + + const ssb2 = createSSB(name, { temp: false }, [require('ssb-private2')]) + + const result = await promisify(ssb2.get)(key) + t.ok(result) + + await promisify(ssb2.publish)({ type: 'test' }) + t.pass('published again') + + await promisify(ssb2.close)() + t.pass('closed again') +}) diff --git a/test/rebuild.js b/test/rebuild.js index ef752584..ca729d73 100644 --- a/test/rebuild.js +++ b/test/rebuild.js @@ -53,6 +53,9 @@ tape('basic rebuild (with an unboxer that requires init)', async (t) => { text: 'hello' } + + // BUG: weird obv bug + console.log('about to publish') await promisify(db.publish)(content) await promisify(db.rebuild)() diff --git a/test/util/create-ssb.js b/test/util/create-ssb.js index f51b24be..edab1208 100644 --- a/test/util/create-ssb.js +++ b/test/util/create-ssb.js @@ -11,10 +11,14 @@ const caps = { shs: crypto.randomBytes(32).toString('base64') } const randomName = () => crypto.randomBytes(16).toString("hex"); -module.exports = function createSSB (name = randomName(), opts = {}) { +module.exports = function createSSB (name = randomName(), opts = {}, plugins) { const ssbDb = require('../../'); const stack = secretStack({ caps }).use(ssbDb) const dir = path.join(os.tmpdir(), name); + + if (plugins) { + plugins.forEach((plugin) => stack.use(plugin)) + } if (opts.temp !== false) { rimraf.sync(dir); From 404c5af7e4f2bfdf9d4e29f075ca9ab2ea884aa9 Mon Sep 17 00:00:00 2001 From: Christian Bundy Date: Thu, 18 Jun 2020 15:33:26 -0700 Subject: [PATCH 2/4] Remove outdated obv bug note --- test/rebuild.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/rebuild.js b/test/rebuild.js index ca729d73..ef752584 100644 --- a/test/rebuild.js +++ b/test/rebuild.js @@ -53,9 +53,6 @@ tape('basic rebuild (with an unboxer that requires init)', async (t) => { text: 'hello' } - - // BUG: weird obv bug - console.log('about to publish') await promisify(db.publish)(content) await promisify(db.rebuild)() From 063d28fcea51167e3c73dda393c1c1efb98807fc Mon Sep 17 00:00:00 2001 From: mixmix Date: Fri, 19 Jun 2020 16:47:40 +1200 Subject: [PATCH 3/4] addBoxer refactor, change test to use boxer --- minimal.js | 24 +++++++----------------- test/box-unbox.js | 6 ++---- test/private2.js | 5 +++++ 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/minimal.js b/minimal.js index aad1c16a..04910719 100644 --- a/minimal.js +++ b/minimal.js @@ -150,25 +150,15 @@ module.exports = function (dirname, keys, opts) { } db.addBoxer = function addBoxer (boxer) { - switch (typeof boxer) { - case 'function': - boxers.push(boxer) - break - - case 'object': - if (typeof boxer.value !== 'function') throw new Error('invalid boxer') - - if (boxer.init) { - setup.boxers.add(boxer.init) - setup.boxers.runAll() - } - - boxers.push(boxer.value) + if (typeof boxer === 'function') return db.addBoxer({ value: boxer }) + if (typeof boxer.value !== 'function') throw new Error('invalid boxer') - break - - default: throw new Error('invalid boxer') + if (boxer.init) { + setup.boxers.add(boxer.init) + setup.boxers.runAll() } + + boxers.push(boxer.value) } db.addUnboxer = function addUnboxer (unboxer) { diff --git a/test/box-unbox.js b/test/box-unbox.js index 58fe4642..118c3acb 100644 --- a/test/box-unbox.js +++ b/test/box-unbox.js @@ -301,7 +301,7 @@ function run () { done() }, 500) }, - value: (x) => x + value: (x) => Buffer.from(JSON.stringify(x)).toString('base64') + '.box.hah' } const unboxer = { @@ -335,9 +335,7 @@ function run () { recps: [ '!test' ], myFriend: alice.id// Necessary to test links() } - const ciphertext = Buffer.from(JSON.stringify(content)).toString('base64') + '.box.hah' - - feed.publish(ciphertext, (_, msg) => { + feed.publish(content, (_, msg) => { t.true(boxerInitDone, 'boxer completed initialisation before publish') t.false(unboxerInitDone, 'unboxer did not completed initialisation before publish') diff --git a/test/private2.js b/test/private2.js index 986be51a..46084eb8 100644 --- a/test/private2.js +++ b/test/private2.js @@ -28,3 +28,8 @@ tape('partial index', async (t) => { await promisify(ssb2.close)() t.pass('closed again') }) + +/* Note - this sequence of actions sets the database in a state which could get it in a locked state + * In particular ssb-private2 requires boxer and unboxer initialistion, and they can depened on one + * another, so if you're not careful. + */ From eafa5e763c7ca25acc6a154a61dd749763c6e401 Mon Sep 17 00:00:00 2001 From: mixmix Date: Mon, 22 Jun 2020 11:07:37 +1200 Subject: [PATCH 4/4] clearly label all tests, clearly name more test files --- .travis.yml | 4 +- README.md | 25 +++-- package-lock.json | 6 +- package.json | 2 +- test/add.js | 30 +++-- test/append.js | 8 +- test/box-unbox.js | 36 +++--- test/close.js | 7 +- test/{feed.js => create-feed-stream.js} | 41 ++++--- test/{log.js => create-log-stream.js} | 105 ++++++------------ ...ce-stream.js => create-sequence-stream.js} | 8 +- ...write-stream.js => create-write-stream.js} | 14 ++- test/del.js | 77 +++++++++++++ test/history.js | 36 ++++-- test/latest.js | 7 +- test/{linktypes.js => links-types.js} | 14 ++- test/links.js | 16 ++- test/mesages-by-type.js | 7 +- test/msg-encoding.js | 11 +- test/private2.js | 35 ------ test/rebuild.js | 44 +++++++- test/validation.js | 16 +-- 22 files changed, 319 insertions(+), 230 deletions(-) rename test/{feed.js => create-feed-stream.js} (75%) rename test/{log.js => create-log-stream.js} (61%) rename test/{sequence-stream.js => create-sequence-stream.js} (77%) rename test/{write-stream.js => create-write-stream.js} (85%) create mode 100644 test/del.js rename test/{linktypes.js => links-types.js} (94%) delete mode 100644 test/private2.js diff --git a/.travis.yml b/.travis.yml index c2baa4ed..45266829 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ node_js: - node # latest os: - - linux - - osx - windows + - osx + - linux diff --git a/README.md b/README.md index 4e1de22d..704f475b 100644 --- a/README.md +++ b/README.md @@ -596,17 +596,21 @@ integer that usually increases, except in the exceptional circumstance that the ### db.addBoxer: sync ```js -db.addUnboxer({ value: boxer, init: initBoxer }) +db.addUnboxer({ value: boxer, init: initUnboxer }) ``` Add a `boxer`, which will be added to the list of boxers which will try to automatically box (encrypt) the message `content` if the appropriate `content.recps` is provided. -`boxer` is a function of signature `boxer(msg.value.content) => ciphertext` which is expected to: -- successfully box the content (based on `content.recps`), returning a `ciphertext` String -- not know how to box this content (because recps are outside it's understanding), and `undefined` (or `null`) -- break (because it should know how to handle `recps`, but can't), and so throw an `Error` +Where: +- `boxer (msg.value.content) => ciphertext` which is expected to either: + - successfully box the content (based on `content.recps`), returning a `ciphertext` String + - not know how to box this content (because recps are outside it's understanding), and `undefined` (or `null`) + - break (because it should know how to handle `recps`, but can't), and so throw an `Error` +- `initUnboxer (done) => null` (optional) + - is a functional which allows you set up your unboxer + - you're expected to call `done()` once all your initialisation is complete ## db.addUnboxer: sync @@ -621,12 +625,11 @@ Where: - `unboxKey(msg.value.content, msg.value) => readKey` - Is a function which tries to extract the message key from the encrypted content (`ciphertext`). - Is expected to return `readKey` which is the read capability for the message - - `unboxValue(msg.value.content, msg.value, readKey) => plainContent` - - Is a function which takes a `readKey` and uses it to try to extract the `plainContent` from the `ciphertext- `initBoxer(done)` - - Is an optional initialisation function (useful for asynchronously setting up state for unboxer) - - It's pased a `done` callback which you need to call once everything is ready to go - -NOTE: There's an alternative way to use `addUnboxer` but read the source to understand that. +- `unboxValue(msg.value.content, msg.value, readKey) => plainContent` + - Is a function which takes a `readKey` and uses it to try to extract the `plainContent` from the `ciphertext +- `initBoxer (done) => null` (optional) + - is a functional which allows you set up your boxer + - you're expected to call `done()` once all your initialisation is complete ## db.box(content, recps, cb) diff --git a/package-lock.json b/package-lock.json index 76b93c4a..ad02992d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1252,7 +1252,7 @@ } }, "private-group-spec": { - "version": "github:ssbc/private-group-spec#03a383b5ecc7f5ad17e36f49760e5d39e95b4239", + "version": "github:ssbc/private-group-spec#a18aa4529c2ad58b22e4160d6661f59ce29d0ba7", "from": "github:ssbc/private-group-spec", "dev": true }, @@ -1786,8 +1786,8 @@ } }, "ssb-private2": { - "version": "github:ssbc/ssb-private2#ae4c5c5191942c582d967e97c0f129658ae8d57d", - "from": "github:ssbc/ssb-private2#boxer-init", + "version": "github:ssbc/ssb-private2#94786a90f2086e22708801431461b65dbfa929d3", + "from": "github:ssbc/ssb-private2#master", "dev": true, "requires": { "charwise": "^3.0.1", diff --git a/package.json b/package.json index f088537a..5e990fb7 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "secret-stack": "^6.3.1", "ssb-feed": "^2.2.1", "ssb-private1": "^1.0.1", - "ssb-private2": "github:ssbc/ssb-private2#boxer-init", + "ssb-private2": "github:ssbc/ssb-private2#master", "tap-spec": "^5.0.0", "tape": "^5.0.0", "typewiselite": "^1.0.0" diff --git a/test/add.js b/test/add.js index 9d7c821a..8c47c9fb 100644 --- a/test/add.js +++ b/test/add.js @@ -9,14 +9,14 @@ function run (opts) { var ssb = createSSB('test-ssb-add', {}) var ssb2 = createSSB('test-ssb-add2', {}) - tape('add invalid message', function (t) { + tape('add (invalid message)', function (t) { ssb.add({}, function (err) { t.ok(err) t.end() }) }) - tape('add null message', function (t) { + tape('add (null message)', function (t) { ssb.add(null, function (err) { t.ok(err) t.end() @@ -29,7 +29,7 @@ function run (opts) { if (err) throw err t.deepEqual(_msg, msg.value) - ssb.get({id:msg.key, meta: true}, function (err, _msg2) { + ssb.get({ id: msg.key, meta: true }, function (_, _msg2) { t.deepEqual(_msg2, msg) ssb.publish({ type: 'wtf' }, function (err, msg) { @@ -45,7 +45,7 @@ function run (opts) { }) }) - tape('log', function (t) { + tape('add (createLogStream)', function (t) { pull(ssb.createLogStream({ keys: true, values: true }), pull.collect(function (err, ary) { if (err) throw err t.equal(ary.length, 2) @@ -53,7 +53,7 @@ function run (opts) { })) }) - tape('log', function (t) { + tape('add (createLogStream)', function (t) { pull( ssb.createLogStream({ keys: false, values: true }), ssb2.createWriteStream(function (err, ary) { @@ -62,20 +62,26 @@ function run (opts) { }) ) }) - tape('close', function (t) { + tape('add (close)', function (t) { ssb.close((err) => { - t.error(err) - ssb2.close(t.end) + t.error(err, 'ssb.close - add (close)') + ssb2.close(err => { + t.error(err, 'ssb2.close - add (close)') + t.end() + }) }) }) - tape('sign-cap', function (t) { + tape('add/ publish (sign-cap)', function (t) { var opts = { caps: { sign: crypto.randomBytes(32).toString('base64') } } - var ssb = createSSB('test-ssb-sign-cap', opts) - ssb.publish({ type: 'test', options: opts }, function (err, msg) { + var ssb3 = createSSB('test-ssb-sign-cap', opts) + ssb3.publish({ type: 'test', options: opts }, function (err, msg) { if (err) throw err t.deepEqual(msg.value.content.options, opts) - ssb.close(t.end) + ssb3.close(err => { + t.error(err, 'ssb3.close - add/ publish (sign-cap)') + t.end() + }) }) }) } diff --git a/test/append.js b/test/append.js index 33711d5f..a5f61261 100644 --- a/test/append.js +++ b/test/append.js @@ -17,7 +17,7 @@ var a var db = a = minimal(dirname) db.ready.set(true) var MSG -tape('setup', function (t) { +tape('append (setup)', function (t) { a.append({ keys: keys, content: { type: 'empty' } }, function (err, msg) { if (err) throw err MSG = msg @@ -37,7 +37,7 @@ tape('setup', function (t) { var state = V.initial() var N = 10000 -tape('generate', function (t) { +tape('append (generate)', function (t) { var start = Date.now() var l = N state = V.append(state, null, MSG.value) @@ -60,7 +60,7 @@ tape('generate', function (t) { t.end() }) -tape('loads', function (t) { +tape('append (loads)', function (t) { var start = Date.now() db.since(function (s) { k++ @@ -90,7 +90,7 @@ tape('loads', function (t) { })() }) -tape('read back', function (t) { +tape('append (read back)', function (t) { var msgs = state.queue // [MSG.value].concat(state.queue) var _state = V.initial() var ts = 0 diff --git a/test/box-unbox.js b/test/box-unbox.js index 118c3acb..45f2b7cc 100644 --- a/test/box-unbox.js +++ b/test/box-unbox.js @@ -33,14 +33,14 @@ function run () { var feed = ssb.createFeed(alice) tape('error when trying to encrypt without boxer', (t) => { - t.plan(2); + t.plan(2) const darlene = ssbKeys.generate() const darleneFeed = ssb.createFeed(darlene) darleneFeed.add( - { type: "error", recps: [alice, darlene] }, + { type: 'error', recps: [alice, darlene] }, (err, msg) => { - t.ok(err); - t.notOk(msg); + t.ok(err) + t.notOk(msg) t.end() }) }) @@ -357,7 +357,7 @@ function run () { const assertBoxedAsync = async (methodName, options) => { assertBoxed(methodName, await promisify(ssb[methodName])(options)) if (typeof options === 'object' && Array.isArray(options) === false) { - assertBoxed(methodName, await promisify(ssb[methodName])({ ...options, private: false } )) + assertBoxed(methodName, await promisify(ssb[methodName])({ ...options, private: false })) } } @@ -377,7 +377,7 @@ function run () { switch (methodName) { case 'createRawLogStream': assertBoxed(methodName, val[0].value) - break; + break case 'createFeedStream': case 'createUserStream': case 'messagesByType': @@ -402,20 +402,24 @@ function run () { } await assertBoxedSource('createLogStream', { limit: 1, reverse: true }) - await assertBoxedSource('createHistoryStream', { id: msg.value.author, seq: msg.value.sequence, reverse: true}) + await assertBoxedSource('createHistoryStream', { id: msg.value.author, seq: msg.value.sequence, reverse: true }) await assertBoxedSource('messagesByType', { type: 'poke', limit: 1, reverse: true }) - await assertBoxedSource('createFeedStream', { id: msg.value.author, seq: msg.value.sequence, reverse: true}) - await assertBoxedSource('createUserStream', { id: msg.value.author, seq: msg.value.sequence, reverse: true}) - await assertBoxedSource('links', { source: msg.value.author, limit: 1, values: true}) - await assertBoxedSource('createRawLogStream', { source: msg.value.author, limit: 1, reverse: true, values: true}) - - ssb.close((err) => { - t.error(err) - ssb2.close(t.end) - }) + await assertBoxedSource('createFeedStream', { id: msg.value.author, seq: msg.value.sequence, reverse: true }) + await assertBoxedSource('createUserStream', { id: msg.value.author, seq: msg.value.sequence, reverse: true }) + await assertBoxedSource('links', { source: msg.value.author, limit: 1, values: true }) + await assertBoxedSource('createRawLogStream', { source: msg.value.author, limit: 1, reverse: true, values: true }) + + t.end() }) }) }) + + // not great, but since these servers are being shared acros tests + // at least this is clear + tape.onFinish(() => { + ssb.close() + ssb2.close() + }) } run() diff --git a/test/close.js b/test/close.js index 69ac541e..a7efac98 100644 --- a/test/close.js +++ b/test/close.js @@ -9,7 +9,7 @@ var content = { type: 'whatever' } const name = `test-ssb-close-${Date.now()}` -tape('load', function (t) { +tape('close (loads and closes)', function (t) { t.plan(2) var ssb = createSSB(name, { keys, temp: false }) @@ -23,7 +23,7 @@ tape('load', function (t) { }) }) -tape('reopen', function (t) { +tape('close (reopen existing db)', function (t) { t.plan(2) // HACK: See readme section on 'known bugs'. @@ -38,9 +38,8 @@ tape('reopen', function (t) { t.deepEqual(ary[0].value.content, content, 'reopen works fine') ssb.close((err) => { t.error(err) - t.end() }) }) ) - }, 100) + }, 500) }) diff --git a/test/feed.js b/test/create-feed-stream.js similarity index 75% rename from test/feed.js rename to test/create-feed-stream.js index 717ccea5..9c0ff726 100644 --- a/test/feed.js +++ b/test/create-feed-stream.js @@ -1,11 +1,10 @@ 'use strict' var tape = require('tape') var pull = require('pull-stream') -var ssbKeys = require('ssb-keys') var createSSB = require('./util/create-ssb') function run (opts) { - tape('simple', function (t) { + tape('createFeedStream (simple)', function (t) { var ssb = createSSB('test-ssb-feed') ssb.publish({ type: 'msg', value: 'hello there!' }, function (err, msg) { @@ -20,13 +19,16 @@ function run (opts) { t.equal(ary.length, 1) t.assert(!!ary[0].key) t.assert(!!ary[0].value) - ssb.close(t.end) + ssb.close(err => { + t.error(err, 'ssb.close - createFeedStream (simple)') + t.end() + }) }) ) }) }) - tape('tail', function (t) { + tape('createFeedStream (live)', function (t) { var ssb = createSSB('test-ssb-feed2') var nDrains = 0 @@ -49,13 +51,16 @@ function run (opts) { } var int = setInterval(addAgain, 300) pull( - ssb.createFeedStream({ tail: true }), + ssb.createFeedStream({ live: true }), pull.drain(function (ary) { nDrains++ console.log('drain', nDrains) if (nDrains === 5) { clearInterval(int) - ssb.close(t.end) + ssb.close(err => { + t.error(err, 'ssb.close - createFeedStream (live)') + t.end() + }) } }) ) @@ -63,7 +68,7 @@ function run (opts) { }) }) - tape('tail, parallel add', function (t) { + tape('createFeedStream (live, parallel add)', function (t) { var ssb = createSSB('test-ssb-feed3') var nDrains = 0 @@ -88,20 +93,23 @@ function run (opts) { } pull( - ssb.createFeedStream({ tail: true }), + ssb.createFeedStream({ live: true }), pull.drain(function (ary) { nDrains++ console.log('drain', nDrains) if (nDrains === 5) { t.assert(true) - ssb.close(t.end) + ssb.close(err => { + t.error(err, 'ssb.close - createFeedStream (live parallel add)') + t.end() + }) } }) ) addAgain() }) }) - tape('keys only', function (t) { + tape('createFeedStream (keys only)', function (t) { const ssb = createSSB('test-ssb-feed4') ssb.publish({ type: 'msg', value: 'hello there!' }, function (err, msg) { @@ -113,13 +121,16 @@ function run (opts) { t.error(err) t.equal(ary.length, 1) t.ok(typeof ary[0] === 'string') - ssb.close(t.end) + ssb.close(err => { + t.error(err, 'ssb.close - createFeedStream (keys only)') + t.end() + }) }) ) }) }) - tape('values only', function (t) { + tape('createFeedStream (values only)', function (t) { var ssb = createSSB('test-ssb-feed5') ssb.publish({ type: 'msg', value: 'hello there!' }, function (err, msg) { @@ -131,7 +142,10 @@ function run (opts) { if (err) throw err t.equal(ary.length, 1) t.ok(typeof ary[0].content.type === 'string') - ssb.close(t.end) + ssb.close(err => { + t.error(err, 'ssb.close - createFeedStream (values only)') + t.end() + }) }) ) }) @@ -139,4 +153,3 @@ function run (opts) { } run() - diff --git a/test/log.js b/test/create-log-stream.js similarity index 61% rename from test/log.js rename to test/create-log-stream.js index 56f90266..9b54bf80 100644 --- a/test/log.js +++ b/test/create-log-stream.js @@ -10,7 +10,7 @@ var createSSB = require('./util/create-ssb') var generate = ssbKeys.generate function run (opts = {}) { - tape('simple', function (t) { + tape('createLogStream (simple)', function (t) { var ssb = createSSB('test-ssb-log1') var feed = createFeed(ssb, generate(), opts) @@ -24,13 +24,16 @@ function run (opts = {}) { t.equal(ary.length, 1) t.assert(!!ary[0].key) t.assert(!!ary[0].value) - ssb.close(t.end) + ssb.close(err => { + t.error(err, 'ssb.close - createLogStream (simple)') + t.end() + }) }) ) }) }) - tape('gt', function (t) { + tape('createLogStream (gt)', function (t) { var ssb = createSSB('test-ssb-log2') var feed = createFeed(ssb, generate(), opts) @@ -45,14 +48,17 @@ function run (opts = {}) { pull.collect(function (err, ary) { if (err) throw err t.equal(ary.length, 1) - ssb.close(t.end) + ssb.close(err => { + t.error(err, 'ssb.close - createLogStream (gt)') + t.end() + }) }) ) }) }) }) - tape('gt 0', function (t) { + tape('createLogStream (gt 0)', function (t) { var ssb = createSSB('test-ssb-log4') var feed = createFeed(ssb, generate(), opts) @@ -64,13 +70,16 @@ function run (opts = {}) { pull.collect(function (err, ary) { if (err) throw err t.equal(ary.length, 1) - ssb.close(t.end) + ssb.close(err => { + t.error(err, 'ssb.close - createLogStream (gt 0)') + t.end() + }) }) ) }) }) - tape('keys only', function (t) { + tape('createLogStream (keys only)', function (t) { var ssb = createSSB('test-ssb-log5') var feed = createFeed(ssb, generate(), opts) @@ -83,13 +92,16 @@ function run (opts = {}) { if (err) throw err t.equal(ary.length, 1) t.equal(typeof ary[0], 'string') - ssb.close(t.end) + ssb.close(err => { + t.error(err, 'ssb.close - createLogStream (gt)') + t.end() + }) }) ) }) }) - tape('values only', function (t) { + tape('createLogStream (values only)', function (t) { var ssb = createSSB('test-ssb-log6') var feed = createFeed(ssb, generate(), opts) @@ -102,14 +114,17 @@ function run (opts = {}) { if (err) throw err t.equal(ary.length, 1) t.equal(typeof ary[0].content.type, 'string') - ssb.close(t.end) + ssb.close(err => { + t.error(err, 'ssb.close - createLogStream (values only)') + t.end() + }) }) ) }) }) - tape('live', function (t) { - t.plan(3) + tape('createLogStream (live)', function (t) { + t.plan(4) var ssb = createSSB('test-ssb-log7') @@ -124,7 +139,10 @@ function run (opts = {}) { if (op.sync) return t.ok(true) t.ok(op.timestamp > ts) t.equal(op.value.content.type, 'msg') - ssb.close(t.end) + ssb.close(err => { + t.error(err, 'ssb.close - createLogStream (live)') + t.end() + }) }) ) @@ -132,67 +150,6 @@ function run (opts = {}) { if (err) throw err }) }) - - tape('delete message', (t) => { - var ssb = createSSB('test-ssb-log8') - - var feed = createFeed(ssb, generate(), opts) - t.plan(4) - - feed.add('msg', 'hello there!', function (err, msg) { - t.error(err) - - pull( - ssb.createFeedStream(), - pull.drain(function (msg) { - ssb.del(msg.key, err => t.error(err)) - }, () => { - pull( - ssb.createFeedStream(), - pull.drain(() => { - t.fail('no messages should be available') - }, () => { - ssb.get(msg.key, (err) => { - t.ok(err) - t.equal(err.code, 'flumelog:deleted') - ssb.close(t.end) - }) - }) - ) - }) - ) - }) - }) - - tape('delete feed', (t) => { - var ssb = createSSB('test-ssb-log9') - var feed = createFeed(ssb, generate(), opts) - - t.plan(5) - - feed.add('msg', 'hello there!', function (err) { - t.error(err) - feed.add('msg', 'hello again!', function (err, msg) { - t.error(err) - ssb.del(msg.value.author, err => { - t.error(err) - pull( - ssb.createFeedStream(), - pull.drain(() => { - t.fail('no messages should be available') - }, () => { - ssb.get(msg.key, (err) => { - t.ok(err) - t.equal(err.code, 'flumelog:deleted') - ssb.close(t.end) - }) - }) - ) - }) - }) - }) - }) } run() - diff --git a/test/sequence-stream.js b/test/create-sequence-stream.js similarity index 77% rename from test/sequence-stream.js rename to test/create-sequence-stream.js index 1b8f4cc3..10ecec67 100644 --- a/test/sequence-stream.js +++ b/test/create-sequence-stream.js @@ -4,7 +4,7 @@ const test = require('tape') const ssb = require('../').init({}, { temp: true }) -test('initial sequence numbers', (t) => { +test('createSequenceStream (initial sequence numbers)', (t) => { const since = obv() pull( @@ -16,7 +16,7 @@ test('initial sequence numbers', (t) => { t.equal(val, -1, 'since has correct init value') }) - ssb.publish({type: 'test'}, (err, publishedMessage) => { + ssb.publish({ type: 'test' }, (err, publishedMessage) => { t.error(err, 'publish() success') t.equal(since.value, 0, 'since is incremented') @@ -24,7 +24,7 @@ test('initial sequence numbers', (t) => { }) }) -test('resume sequence stream later', (t) => { +test('createSequenceStream (resume sequence stream later)', (t) => { const since = obv() pull( @@ -36,7 +36,7 @@ test('resume sequence stream later', (t) => { t.equal(val, 0, 'since has correct init value') }) - ssb.publish({type: 'test'}, (err, publishedMessage) => { + ssb.publish({ type: 'test' }, (err, publishedMessage) => { t.error(err, 'publish() success') ssb.get(since.value, (err, foundMessage) => { diff --git a/test/write-stream.js b/test/create-write-stream.js similarity index 85% rename from test/write-stream.js rename to test/create-write-stream.js index 929fc079..ab89817d 100644 --- a/test/write-stream.js +++ b/test/create-write-stream.js @@ -9,7 +9,7 @@ function run (opts = {}) { var ssb = createSSB('test-ssb-write-stream') var create = require('ssb-feed/util').create - tape('write-stream', function (t) { + tape('createWriteStream', function (t) { var keys = ssbKeys.generate() var prev @@ -21,7 +21,6 @@ function run (opts = {}) { q.push(prev = create(keys, 'msg', { count: l }, prev)) } - pull( pull.values(q), pull.asyncMap(function (data, cb) { @@ -36,7 +35,7 @@ function run (opts = {}) { ) }) - tape('write-stream, overwrite', function (t) { + tape('createWriteStream (overwrite)', function (t) { var keys = ssbKeys.generate() var prev @@ -51,7 +50,6 @@ function run (opts = {}) { q.push(q[3]) q.push(q[4]) - pull( pull.values(q), pull.asyncMap(function (data, cb) { @@ -60,8 +58,12 @@ function run (opts = {}) { }, ~~(Math.random() * 500)) }), ssb.createWriteStream(function (err) { - if (err) throw err - ssb.close(t.end) + t.error(err) + + ssb.close(err => { + t.error(err, 'ssb.close - createWriteStream') + t.end() + }) }) ) }) diff --git a/test/del.js b/test/del.js new file mode 100644 index 00000000..26f3e453 --- /dev/null +++ b/test/del.js @@ -0,0 +1,77 @@ +'use strict' +var tape = require('tape') +var pull = require('pull-stream') +var createSSB = require('./util/create-ssb') +var createFeed = require('ssb-feed') +var ssbKeys = require('ssb-keys') + +var generate = ssbKeys.generate + +function run (opts = {}) { + tape('del (delete message)', (t) => { + var ssb = createSSB('test-ssb-log8') + + var feed = createFeed(ssb, generate(), opts) + t.plan(5) + + feed.add('msg', 'hello there!', function (err, msg) { + t.error(err) + + pull( + ssb.createFeedStream(), + pull.drain(function (msg) { + ssb.del(msg.key, err => t.error(err)) + }, () => { + pull( + ssb.createFeedStream(), + pull.drain(() => { + t.fail('no messages should be available') + }, () => { + ssb.get(msg.key, (err) => { + t.ok(err) + t.equal(err.code, 'flumelog:deleted') + ssb.close(err => { + t.error(err, 'ssb.close - del (delete message)') + t.end() + }) + }) + }) + ) + }) + ) + }) + }) + + tape('del (delete feed)', (t) => { + var ssb = createSSB('test-ssb-log9') + var feed = createFeed(ssb, generate(), opts) + + t.plan(6) + + feed.add('msg', 'hello there!', function (err) { + t.error(err) + feed.add('msg', 'hello again!', function (err, msg) { + t.error(err) + ssb.del(msg.value.author, err => { + t.error(err) + pull( + ssb.createFeedStream(), + pull.drain(() => { + t.fail('no messages should be available') + }, () => { + ssb.get(msg.key, (err) => { + t.ok(err) + t.equal(err.code, 'flumelog:deleted') + ssb.close(err => { + t.error(err, 'ssb.close - del (delete feed)') + t.end() + }) + }) + }) + ) + }) + }) + }) + }) +} +run() diff --git a/test/history.js b/test/history.js index d531b8b9..3cc28342 100644 --- a/test/history.js +++ b/test/history.js @@ -49,7 +49,12 @@ function run (opts) { var id var keys2 - tape('history', function (t) { + // NOTE these tests could be out of place / poorly named? (or could be just write) + // - createUserStream + latest being tested, why? + // - these tests are assumed to run **in serial** and each test adds more context, which makes moving them dangerous + + // ODD ONE + tape('latest (history)', function (t) { keys = init(ssb, 7, function (err) { if (err) throw err pull(ssb.latest(), pull.collect(function (err, ary) { @@ -65,7 +70,7 @@ function run (opts) { id = keys.id // opts.hash(keys.public) }) - tape('since', function (t) { + tape('createHistoryStream (since seq)', function (t) { pull( ssb.createHistoryStream({ id: id, seq: 1 }), pull.collect(function (err, ary) { @@ -76,7 +81,8 @@ function run (opts) { ) }) - tape('two keys', function (t) { + // ODD ONE + tape('latest (two keys)', function (t) { keys2 = init(ssb, 4, function (err) { if (err) throw err pull(ssb.latest(), pull.collect(function (err, ary) { @@ -93,7 +99,7 @@ function run (opts) { }) }) - tape('keys & since', function (t) { + tape('createHistoryStram (keys & since)', function (t) { pull( ssb.createHistoryStream({ id: id, seq: 1, keys: true }), pull.collect(function (err, ary) { @@ -106,7 +112,8 @@ function run (opts) { ) }) - tape('user stream', function (t) { + // ODD ONE + tape('createUserStream', function (t) { pull( ssb.createUserStream({ id: id, gt: 3, lte: 7, reverse: true }), pull.collect(function (err, ary) { @@ -120,7 +127,7 @@ function run (opts) { }) ) }) - tape('keys only', function (t) { + tape('createHistoryStream (keys only)', function (t) { pull( ssb.createHistoryStream({ id: id, values: false }), pull.collect(function (err, ary) { @@ -132,7 +139,7 @@ function run (opts) { ) }) - tape('values only', function (t) { + tape('createHistoryStream (values only)', function (t) { pull( ssb.createHistoryStream({ id: id, keys: false }), pull.collect(function (err, ary) { @@ -144,7 +151,7 @@ function run (opts) { ) }) - tape('abort live stream', function (t) { + tape('createHistoryStream (abort live stream)', function (t) { var abortable = Abortable() var errMsg = 'intentional' var err = new Error(errMsg) @@ -172,7 +179,7 @@ function run (opts) { ) }) - tape('createHistoryStream with limit', function (t) { + tape('createHistoryStream (with limit)', function (t) { pull( ssb.createHistoryStream({ id: id, keys: false, limit: 5 @@ -180,11 +187,18 @@ function run (opts) { pull.collect(function (err, ary) { if (err) throw err t.equal(ary.length, 5) - ssb.close(t.end) + + // assumes this is last test run + ssb.close(() => { + if (err) console.error(err) + t.end() + }) }) ) }) + + // NOTE we might have to do this + // tape.onFinish(ssb.close) } run() - diff --git a/test/latest.js b/test/latest.js index 60d75447..8b2f5760 100644 --- a/test/latest.js +++ b/test/latest.js @@ -14,7 +14,7 @@ var carol = db.createFeed() var start = Date.now() // LEGACY: uses feed.add as a continuable -tape('empty', function (t) { +tape('latest (empty)', function (t) { cont.para([ ])(function (err) { if (err) throw err @@ -48,7 +48,10 @@ tape('latest', function (t) { return v.id }) t.deepEqual(n.sort(), [alice.id, bob.id, carol.id].sort()) - db.close(t.end) + db.close(err => { + t.error(err, 'ssb.close - latest') + t.end() + }) }) ) }) diff --git a/test/linktypes.js b/test/links-types.js similarity index 94% rename from test/linktypes.js rename to test/links-types.js index 11d19197..e8a3dcc6 100644 --- a/test/linktypes.js +++ b/test/links-types.js @@ -44,7 +44,7 @@ function run (opts = {}) { function toKV (data) { return { key: data.key, value: data.value } } - tape('reply to a message', function (t) { + tape('links/types (reply to a message)', function (t) { alice.add({ type: 'msg', value: 'hello world' }, function (err, msg) { if (err) throw err msg = toKV(msg) @@ -128,7 +128,7 @@ function run (opts = {}) { }) }) - tape('follow another user', function (t) { + tape('links/types (follow another user)', function (t) { function follow (a, b) { return function (cb) { a.add('follow', { follow: b.id }, function (err, msg) { @@ -176,7 +176,7 @@ function run (opts = {}) { }) }) - tape('check for 1:1 relationships', function (t) { + tape('links/types (check for 1:1 relationships)', function (t) { function follows (a, b) { return function (cb) { pull( @@ -213,7 +213,7 @@ function run (opts = {}) { }) }) - tape('scan links with unknown rel', function (t) { + tape('links/types (scan links with unknown rel)', function (t) { alice.add({ type: 'poke', poke: bob.id @@ -230,11 +230,13 @@ function run (opts = {}) { { type: 'follow', follow: bob.id }, { type: 'poke', poke: bob.id } ]) - ssb.close(t.end) + ssb.close(err => { + t.error(err, 'ssb.close - links/types') + t.end() + }) }) }) }) } run() - diff --git a/test/links.js b/test/links.js index f9a7961a..6e6336b7 100644 --- a/test/links.js +++ b/test/links.js @@ -29,7 +29,7 @@ function run (opts) { pull.drain(fromAlice.push.bind(fromAlice)) ) - tape('initialize', function (t) { + tape('links (initialize)', function (t) { cont.para([ alice.add({ type: 'yo!', yo: alice.id }), alice.add({ type: 'contact', follow: bob.id, okay: true }), @@ -47,7 +47,7 @@ function run (opts) { }) }) - tape('query only rel type', function (t) { + tape('links (query only rel type)', function (t) { pull( db.links({ rel: 'yo' }), pull.through(function (data) { @@ -78,7 +78,7 @@ function run (opts) { } } - tape('query by dest', function (t) { + tape('links (query by dest)', function (t) { var test = createTest(t) var mention = { source: bob.id, @@ -94,7 +94,7 @@ function run (opts) { { dest: msgs[2].key, rel: 'mentions' }, [mention]) }) - tape('realtime', function (t) { + tape('linve (realtime)', function (t) { pull( db.links({ source: alice.id, old: true }), pull.collect(function (err, ary) { @@ -107,7 +107,7 @@ function run (opts) { ) }) - tape('live link values', function (t) { + tape('links (live link values)', function (t) { var msg pull( db.links({ old: false, live: true, values: true }), @@ -119,7 +119,11 @@ function run (opts) { dest: bob.id, rel: 'foo' }) - db.close(t.end) + + db.close(err => { + t.error(err, 'ssb.close - links') + t.end() + }) }) ) diff --git a/test/mesages-by-type.js b/test/mesages-by-type.js index 9968123a..8626a03c 100644 --- a/test/mesages-by-type.js +++ b/test/mesages-by-type.js @@ -10,7 +10,7 @@ function all (stream, cb) { } function run (opts = {}) { - tape('retrive messages by type', function (t) { + tape('messagesByType', function (t) { var dbA = createSSB('msg-by-type1') var alice = createFeed(dbA, ssbKeys.generate(), opts) @@ -66,7 +66,10 @@ function run (opts = {}) { t.equal(ary.length, 1) t.equal(typeof ary[0], 'string') - dbA.close(t.end) + dbA.close(err => { + t.error(err, 'ssb.close - messagesByType') + t.end() + }) }) }) }) diff --git a/test/msg-encoding.js b/test/msg-encoding.js index bbffbe3e..5853344c 100644 --- a/test/msg-encoding.js +++ b/test/msg-encoding.js @@ -39,21 +39,21 @@ function run (opts = {}) { signed.signature = Buffer.alloc(64).toString('base64') - tape('Message', function (t) { + tape('msg encoding (Message)', function (t) { var enc = codec.encode(msg) var o = codec.decode(enc) t.deepEqual(o, msg) t.end() }) - tape('Signed', function (t) { + tape('msg encoding (Signed)', function (t) { var enc = codec.encode(signed) var o = codec.decode(enc) t.deepEqual(o, signed) t.end() }) - tape('known error case 1', function (t) { + tape('msg encoding (known error case 1)', function (t) { var ssb = createSSB('test-ssb-encoding') var feed = createFeed(ssb, generate(), opts) @@ -68,7 +68,10 @@ function run (opts = {}) { pull.collect(function (err, ary) { if (err) throw err t.equal(ary.length, 1) - ssb.close(t.end) + ssb.close(err => { + t.error(err, 'ssb.close - msg encoding') + t.end() + }) }) ) }) diff --git a/test/private2.js b/test/private2.js deleted file mode 100644 index 46084eb8..00000000 --- a/test/private2.js +++ /dev/null @@ -1,35 +0,0 @@ -const createSSB = require('./util/create-ssb') -const tape = require('tape') -const { promisify } = require('util') - -tape('partial index', async (t) => { - const name = `test-ssb-partial-index-${Date.now()}` - - t.plan(6) - - const ssb = createSSB(name, { temp: false }) - const { key } = await promisify(ssb.publish)({ type: 'test' }) - t.pass('published') - - await promisify(ssb.rebuild)() - t.pass('rebuilt') - - await promisify(ssb.close)() - t.pass('closed') - - const ssb2 = createSSB(name, { temp: false }, [require('ssb-private2')]) - - const result = await promisify(ssb2.get)(key) - t.ok(result) - - await promisify(ssb2.publish)({ type: 'test' }) - t.pass('published again') - - await promisify(ssb2.close)() - t.pass('closed again') -}) - -/* Note - this sequence of actions sets the database in a state which could get it in a locked state - * In particular ssb-private2 requires boxer and unboxer initialistion, and they can depened on one - * another, so if you're not careful. - */ diff --git a/test/rebuild.js b/test/rebuild.js index ef752584..154e0335 100644 --- a/test/rebuild.js +++ b/test/rebuild.js @@ -4,7 +4,7 @@ const { promisify } = require('util') const createSsb = require('./util/create-ssb') -tape('basic rebuild', async (t) => { +tape('rebuild (basic)', async (t) => { t.plan(3) const db = createSsb() @@ -22,7 +22,8 @@ tape('basic rebuild', async (t) => { await promisify(db.close)() t.pass('closed') }) -tape('basic rebuild (with an unboxer that requires init)', async (t) => { + +tape('rebuild (with an unboxer that requires init)', async (t) => { t.plan(3) const db = createSsb() @@ -57,12 +58,12 @@ tape('basic rebuild (with an unboxer that requires init)', async (t) => { await promisify(db.rebuild)() t.pass('rebuilt') - + await promisify(db.close)() t.pass('closed') }) -tape('new unboxer rebuild', async (t) => { +tape('rebuild (after new unboxer)', async (t) => { t.plan(7) const db = createSsb() const myId = db.id @@ -91,7 +92,7 @@ tape('new unboxer rebuild', async (t) => { const boxed = await promisify(latestByBoxStatus.get)('boxed') t.ok(boxed, "indexes can't see the unboxed message, it remains boxed") - const msgBefore = await promisify(db.get)({ id: boxed.key, meta: true, private: true }); + const msgBefore = await promisify(db.get)({ id: boxed.key, meta: true, private: true }) t.equal( typeof msgBefore.value.content, @@ -121,7 +122,7 @@ tape('new unboxer rebuild', async (t) => { await promisify(db.rebuild)() t.pass('rebuilt') - const msgAfter = await promisify(db.get)({ id: boxed.key, meta: true, private: true }); + const msgAfter = await promisify(db.get)({ id: boxed.key, meta: true, private: true }) // NOTE: Flumeview-Level doesn't actually unbox the message, since it only // runs `get(id)` under the hood. @@ -141,5 +142,36 @@ tape('new unboxer rebuild', async (t) => { await promisify(db.close)() t.pass('closed') +}) + +/* Note - this sequence of actions sets the database in a state which could get it in a locked state + * In particular ssb-private2 requires boxer and unboxer initialistion, and they can depened on one + * another, so if you're not careful. + */ + +tape('rebuild (partial index, complex boxer/unboxer)', async (t) => { + const name = `test-ssb-partial-index-${Date.now()}` + + t.plan(6) + + const ssb = createSsb(name, { temp: false }) + const { key } = await promisify(ssb.publish)({ type: 'test' }) + t.pass('published') + + await promisify(ssb.rebuild)() + t.pass('rebuilt') + + await promisify(ssb.close)() + t.pass('closed') + + const ssb2 = createSsb(name, { temp: false }, [require('ssb-private2')]) + + const result = await promisify(ssb2.get)(key) + t.ok(result) + + await promisify(ssb2.publish)({ type: 'test' }) + t.pass('published again') + await promisify(ssb2.close)() + t.pass('closed again') }) diff --git a/test/validation.js b/test/validation.js index ef6300a2..c0c7998a 100644 --- a/test/validation.js +++ b/test/validation.js @@ -12,7 +12,7 @@ function run (opts = {}) { var create = require('ssb-feed/util').create var ssb = createSSB('test-ssb-validate') - tape('simple', function (t) { + tape('validation (simple)', function (t) { var keys = generate() var prev var messages = [ @@ -27,7 +27,7 @@ function run (opts = {}) { }) }) - tape('add & validate', function (t) { + tape('validation (add & validate)', function (t) { var keys = generate() var prev ssb.add( @@ -60,7 +60,7 @@ function run (opts = {}) { ) }) - tape('race: should queue', function (t) { + tape('validation (race: should queue)', function (t) { var keys = generate() var prev var calls = 0 @@ -101,7 +101,7 @@ function run (opts = {}) { // when an add fails, you should still be able to add another // message if you wait until it has returned. - tape('too big', function (t) { + tape('validation (too big)', function (t) { var keys = generate() var feed = ssb.createFeed(keys) var str = '' @@ -116,7 +116,7 @@ function run (opts = {}) { }) // git-ssb is known to change the order of the message - tape('dict order', function (t) { + tape('validation (dict order)', function (t) { var keys = generate() var prev ssb.add( @@ -156,7 +156,10 @@ function run (opts = {}) { } }, function () { if (state.queue.length > 0) { t.pass('validate passes') } - ssb.close(t.end) + ssb.close(err => { + t.error(err, 'ssb.close - validation') + t.end() + }) }) ) } @@ -169,4 +172,3 @@ function run (opts = {}) { } run() -