From 4eec8ecdd333c9c92de9e3c0232df2f2b2c1668a Mon Sep 17 00:00:00 2001 From: Kevin Jahns Date: Sun, 15 Oct 2017 12:17:25 +0200 Subject: [PATCH] fix encoding and rb tree tests --- package-lock.json | 5 + package.json | 4 +- rollup.test.js | 2 +- src/Binary/Decoder.js | 2 +- src/Binary/Encoder.js | 2 +- src/MessageHandler/deleteSet.js | 2 +- src/MessageHandler/integrateRemoteStructs.js | 2 +- src/MessageHandler/stateSet.js | 2 +- src/MessageHandler/update.js | 2 +- src/Util/ID.js | 2 +- src/Util/Tree.js | 7 +- src/Y.js | 12 +- test/encode-decode.js | 4 +- test/red-black-tree.js | 261 +++++++++---------- tests-lib/helper.js | 17 +- 15 files changed, 151 insertions(+), 175 deletions(-) diff --git a/package-lock.json b/package-lock.json index 16d0d127..e6c4a05e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4206,6 +4206,11 @@ "string.prototype.codepointat": "0.2.0" } }, + "utf8": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz", + "integrity": "sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY=" + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index 40cd2b1f..befd2203 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,8 @@ "tag-dist-files": "^0.1.6" }, "dependencies": { - "debug": "^2.6.8" + "debug": "^2.6.8", + "utf-8": "^1.0.0", + "utf8": "^2.1.2" } } diff --git a/rollup.test.js b/rollup.test.js index e0dbe22d..8b2b604d 100644 --- a/rollup.test.js +++ b/rollup.test.js @@ -3,7 +3,7 @@ import commonjs from 'rollup-plugin-commonjs' import multiEntry from 'rollup-plugin-multi-entry' export default { - entry: 'test/*.js', + entry: 'test/{encode-decode,red-black-tree}.js', moduleName: 'y-tests', format: 'umd', plugins: [ diff --git a/src/Binary/Decoder.js b/src/Binary/Decoder.js index 6cb11d1d..72c4453b 100644 --- a/src/Binary/Decoder.js +++ b/src/Binary/Decoder.js @@ -1,4 +1,4 @@ -import '../../node_modules/utf8/utf8.js' +import utf8 from 'utf-8' export default class BinaryDecoder { constructor (buffer) { diff --git a/src/Binary/Encoder.js b/src/Binary/Encoder.js index 00fe7cca..dfa62a5f 100644 --- a/src/Binary/Encoder.js +++ b/src/Binary/Encoder.js @@ -1,4 +1,4 @@ -import '../../node_modules/utf8/utf8.js' +import utf8 from 'utf-8' const bits7 = 0b1111111 const bits8 = 0b11111111 diff --git a/src/MessageHandler/deleteSet.js b/src/MessageHandler/deleteSet.js index 4a22f2be..555183ae 100644 --- a/src/MessageHandler/deleteSet.js +++ b/src/MessageHandler/deleteSet.js @@ -65,7 +65,7 @@ export function readDeleteSet (y, decoder) { } var pos = 0 var d = dv[pos] - y.ds.iterate(this, [user, 0], [user, Number.MAX_VALUE], function (n) { + y.ds.iterate([user, 0], [user, Number.MAX_VALUE], function (n) { // cases: // 1. d deletes something to the right of n // => go to next n (break) diff --git a/src/MessageHandler/integrateRemoteStructs.js b/src/MessageHandler/integrateRemoteStructs.js index c5b33e22..b969c737 100644 --- a/src/MessageHandler/integrateRemoteStructs.js +++ b/src/MessageHandler/integrateRemoteStructs.js @@ -1,4 +1,4 @@ -import { getStruct } from '../Util/StructReferences.js' +import { getStruct } from '../Util/structReferences.js' import BinaryDecoder from '../Binary/Decoder.js' class MissingEntry { diff --git a/src/MessageHandler/stateSet.js b/src/MessageHandler/stateSet.js index 057d5518..88b5a577 100644 --- a/src/MessageHandler/stateSet.js +++ b/src/MessageHandler/stateSet.js @@ -14,7 +14,7 @@ export function writeStateSet (encoder) { let lenPosition = encoder.pos let len = 0 encoder.writeUint32(0) - this.ss.iterate(this, null, null, function (n) { + this.ss.iterate(null, null, function (n) { encoder.writeVarUint(n.id[0]) encoder.writeVarUint(n.clock) len++ diff --git a/src/MessageHandler/update.js b/src/MessageHandler/update.js index 0f66a7df..85a64503 100644 --- a/src/MessageHandler/update.js +++ b/src/MessageHandler/update.js @@ -1,5 +1,5 @@ -import { getStruct } from '../Util/StructReferences.js' +import { getStruct } from '../Util/structReferences.js' export function stringifyUpdate (decoder, strBuilder) { while (decoder.length !== decoder.pos) { diff --git a/src/Util/ID.js b/src/Util/ID.js index 2de00f6d..bfc1b666 100644 --- a/src/Util/ID.js +++ b/src/Util/ID.js @@ -10,7 +10,7 @@ export default class ID { return new ID(this.user, this.clock) } equals (id) { - return id !== null && id.user === this.user && id.clock === this.user + return id !== null && id.user === this.user && id.clock === this.clock } lessThan (id) { return this.user < id.user || (this.user === id.user && this.clock < id.clock) diff --git a/src/Util/Tree.js b/src/Util/Tree.js index 71b58842..0680bf77 100644 --- a/src/Util/Tree.js +++ b/src/Util/Tree.js @@ -232,11 +232,11 @@ export default class Tree { findNode (id) { var o = this.root if (o === null) { - return false + return null } else { while (true) { if (o === null) { - return false + return null } if (id.lessThan(o.val.id)) { o = o.left @@ -249,9 +249,6 @@ export default class Tree { } } delete (id) { - if (id == null || id.constructor !== Array) { - throw new Error('id is expected to be an Array!') - } var d = this.findNode(id) if (d == null) { // throw new Error('Element does not exist!') diff --git a/src/Y.js b/src/Y.js index 1a859d88..9c33de87 100644 --- a/src/Y.js +++ b/src/Y.js @@ -1,11 +1,3 @@ - -// import debug from 'debug' -export function debug (namespace) { - return function log (message) { - console.log(namespace, message) - } -} - import DeleteStore from './Store/DeleteStore.js' import OperationStore from './Store/OperationStore.js' import StateStore from './Store/StateStore.js' @@ -21,6 +13,8 @@ import YMap from './Type/YMap.js' import YText from './Type/YText.js' import YXml from './Type/YXml.js' +import debug from 'debug' + export default class Y { constructor (opts) { this.userID = generateUserID() @@ -101,6 +95,8 @@ Y.Map = YMap Y.Text = YText Y.Xml = YXml +export { default as debug } from 'debug' + Y.debug = debug debug.formatters.Y = messageToString debug.formatters.y = messageToRoomname diff --git a/test/encode-decode.js b/test/encode-decode.js index 8e9b2ac2..576b3ebe 100644 --- a/test/encode-decode.js +++ b/test/encode-decode.js @@ -1,9 +1,9 @@ -import { test } from '../node_modules/cutest/cutest.js' +import { test } from '../node_modules/cutest/cutest.mjs' import '../node_modules/chance/chance.js' -import Y from '../src/y.js' import BinaryEncoder from '../src/Binary/Encoder.js' import BinaryDecoder from '../src/Binary/Decoder.js' import { generateUserID } from '../src/Util/generateUserID.js' +import Chance from 'chance' function testEncoding (t, write, read, val) { let encoder = new BinaryEncoder() diff --git a/test/red-black-tree.js b/test/red-black-tree.js index 14a19164..299e85f0 100644 --- a/test/red-black-tree.js +++ b/test/red-black-tree.js @@ -1,4 +1,5 @@ -import Y from '../src/y.js' +import RedBlackTree from '../src/Util/Tree.js' +import ID from '../src/Util/ID.js' import Chance from 'chance' import { test, proxyConsole } from 'cutest' @@ -53,23 +54,16 @@ function checkRootNodeIsBlack (t, tree) { } test('RedBlack Tree', async function redBlackTree (t) { - let memory = new Y.memory(null, { // eslint-disable-line - name: 'Memory', - gcTimeout: -1 - }) - let tree = memory.os - memory.requestTransaction(function () { - tree.put({id: [8433]}) - tree.put({id: [12844]}) - tree.put({id: [1795]}) - tree.put({id: [30302]}) - tree.put({id: [64287]}) - tree.delete([8433]) - tree.put({id: [28996]}) - tree.delete([64287]) - tree.put({id: [22721]}) - }) - await memory.whenTransactionsFinished() + let tree = new RedBlackTree() + tree.put({id: new ID(8433, 0)}) + tree.put({id: new ID(12844, 0)}) + tree.put({id: new ID(1795, 0)}) + tree.put({id: new ID(30302, 0)}) + tree.put({id: new ID(64287)}) + tree.delete(new ID(8433, 0)) + tree.put({id: new ID(28996)}) + tree.delete(new ID(64287)) + tree.put({id: new ID(22721)}) checkRootNodeIsBlack(t, tree) checkBlackHeightOfSubTreesAreEqual(t, tree) checkRedNodesDoNotHaveBlackChildren(t, tree) @@ -77,141 +71,122 @@ test('RedBlack Tree', async function redBlackTree (t) { test(`random tests (${numberOfRBTreeTests})`, async function random (t) { let chance = new Chance(t.getSeed() * 1000000000) - let memory = new Y.memory(null, { // eslint-disable-line - name: 'Memory', - gcTimeout: -1 - }) - let tree = memory.os + let tree = new RedBlackTree() let elements = [] - memory.requestTransaction(function () { - for (var i = 0; i < numberOfRBTreeTests; i++) { - if (chance.bool({likelihood: 80})) { - // 80% chance to insert an element - let obj = [chance.integer({min: 0, max: numberOfRBTreeTests})] - let nodeExists = tree.find(obj) - if (!nodeExists) { - if (elements.some(e => e[0] === obj[0])) { - t.assert(false, 'tree and elements contain different results') - } - elements.push(obj) - tree.put({id: obj}) + for (var i = 0; i < numberOfRBTreeTests; i++) { + if (chance.bool({likelihood: 80})) { + // 80% chance to insert an element + let obj = new ID(chance.integer({min: 0, max: numberOfRBTreeTests}), chance.integer({min: 0, max: 1})) + let nodeExists = tree.find(obj) + if (nodeExists === null) { + if (elements.some(e => e.equals(obj))) { + t.assert(false, 'tree and elements contain different results') } - } else if (elements.length > 0) { - // ~20% chance to delete an element - var elem = chance.pickone(elements) - elements = elements.filter(function (e) { - return !Y.utils.compareIds(e, elem) - }) - tree.delete(elem) + elements.push(obj) + tree.put({id: obj}) } + } else if (elements.length > 0) { + // ~20% chance to delete an element + var elem = chance.pickone(elements) + elements = elements.filter(function (e) { + return !e.equals(elem) + }) + tree.delete(elem) } - }) - await memory.whenTransactionsFinished() + } checkRootNodeIsBlack(t, tree) checkBlackHeightOfSubTreesAreEqual(t, tree) checkRedNodesDoNotHaveBlackChildren(t, tree) - memory.requestTransaction(function () { - let allNodesExist = true - for (let id of elements) { - let node = tree.find(id) - if (!Y.utils.compareIds(node.id, id)) { - allNodesExist = false - } + // TEST if all nodes exist + let allNodesExist = true + for (let id of elements) { + let node = tree.find(id) + if (!node.id.equals(id)) { + allNodesExist = false } - t.assert(allNodesExist, 'All inserted nodes exist') - }) - memory.requestTransaction(function () { - let findAllNodesWithLowerBoundSerach = true - for (let id of elements) { - let node = tree.findWithLowerBound(id) - if (!Y.utils.compareIds(node.id, id)) { - findAllNodesWithLowerBoundSerach = false - } + } + t.assert(allNodesExist, 'All inserted nodes exist') + // TEST lower bound search + let findAllNodesWithLowerBoundSerach = true + for (let id of elements) { + let node = tree.findWithLowerBound(id) + if (!node.id.equals(id)) { + findAllNodesWithLowerBoundSerach = false } - t.assert( - findAllNodesWithLowerBoundSerach, - 'Find every object with lower bound search' - ) - }) - - memory.requestTransaction(function () { - let lowerBound = chance.pickone(elements) - let expectedResults = elements.filter((e, pos) => - (Y.utils.smaller(lowerBound, e) || Y.utils.compareIds(e, lowerBound)) && - elements.indexOf(e) === pos - ).length - let actualResults = 0 - tree.iterate(this, lowerBound, null, function (val) { - if (val == null) { - t.assert(false, 'val is undefined!') - } - actualResults++ - }) - t.assert( - expectedResults === actualResults, - 'Iterating over a tree with lower bound yields the right amount of results' - ) - }) - - memory.requestTransaction(function () { - let expectedResults = elements.filter((e, pos) => - elements.indexOf(e) === pos - ).length - let actualResults = 0 - tree.iterate(this, null, null, function (val) { - if (val == null) { - t.assert(false, 'val is undefined!') - } - actualResults++ - }) - t.assert( - expectedResults === actualResults, - 'iterating over a tree without bounds yields the right amount of results' - ) - }) - - memory.requestTransaction(function () { - let upperBound = chance.pickone(elements) - let expectedResults = elements.filter((e, pos) => - (Y.utils.smaller(e, upperBound) || Y.utils.compareIds(e, upperBound)) && - elements.indexOf(e) === pos - ).length - let actualResults = 0 - tree.iterate(this, null, upperBound, function (val) { - if (val == null) { - t.assert(false, 'val is undefined!') - } - actualResults++ - }) - t.assert( - expectedResults === actualResults, - 'iterating over a tree with upper bound yields the right amount of results' - ) - }) - - memory.requestTransaction(function () { - let upperBound = chance.pickone(elements) - let lowerBound = chance.pickone(elements) - if (Y.utils.smaller(upperBound, lowerBound)) { - [lowerBound, upperBound] = [upperBound, lowerBound] + } + t.assert( + findAllNodesWithLowerBoundSerach, + 'Find every object with lower bound search' + ) + // TEST iteration (with lower bound search) + let lowerBound = chance.pickone(elements) + let expectedResults = elements.filter((e, pos) => + (lowerBound.lessThan(e) || e.equals(lowerBound)) && + elements.indexOf(e) === pos + ).length + let actualResults = 0 + tree.iterate(lowerBound, null, function (val) { + if (val == null) { + t.assert(false, 'val is undefined!') } - let expectedResults = elements.filter((e, pos) => - (Y.utils.smaller(lowerBound, e) || Y.utils.compareIds(e, lowerBound)) && - (Y.utils.smaller(e, upperBound) || Y.utils.compareIds(e, upperBound)) && - elements.indexOf(e) === pos - ).length - let actualResults = 0 - tree.iterate(this, lowerBound, upperBound, function (val) { - if (val == null) { - t.assert(false, 'val is undefined!') - } - actualResults++ - }) - t.assert( - expectedResults === actualResults, - 'iterating over a tree with upper bound yields the right amount of results' - ) + actualResults++ }) + t.assert( + expectedResults === actualResults, + 'Iterating over a tree with lower bound yields the right amount of results' + ) - await memory.whenTransactionsFinished() + expectedResults = elements.filter((e, pos) => + elements.indexOf(e) === pos + ).length + actualResults = 0 + tree.iterate(null, null, function (val) { + if (val == null) { + t.assert(false, 'val is undefined!') + } + actualResults++ + }) + t.assert( + expectedResults === actualResults, + 'iterating over a tree without bounds yields the right amount of results' + ) + + let upperBound = chance.pickone(elements) + expectedResults = elements.filter((e, pos) => + (e.lessThan(upperBound) || e.equals(upperBound)) && + elements.indexOf(e) === pos + ).length + actualResults = 0 + tree.iterate(null, upperBound, function (val) { + if (val == null) { + t.assert(false, 'val is undefined!') + } + actualResults++ + }) + t.assert( + expectedResults === actualResults, + 'iterating over a tree with upper bound yields the right amount of results' + ) + + upperBound = chance.pickone(elements) + lowerBound = chance.pickone(elements) + if (upperBound.lessThan(lowerBound)) { + [lowerBound, upperBound] = [upperBound, lowerBound] + } + expectedResults = elements.filter((e, pos) => + (lowerBound.lessThan(e) || e.equals(lowerBound)) && + (e.lessThan(upperBound) || e.equals(upperBound)) && + elements.indexOf(e) === pos + ).length + actualResults = 0 + tree.iterate(lowerBound, upperBound, function (val) { + if (val == null) { + t.assert(false, 'val is undefined!') + } + actualResults++ + }) + t.assert( + expectedResults === actualResults, + 'iterating over a tree with upper bound yields the right amount of results' + ) }) diff --git a/tests-lib/helper.js b/tests-lib/helper.js index de60e07f..ca4ceb73 100644 --- a/tests-lib/helper.js +++ b/tests-lib/helper.js @@ -1,13 +1,15 @@ -import _Y from '../../yjs/src/y.js' +import _Y from '../src/Y.js' import yTest from './test-connector.js' import Chance from 'chance' -export let Y = _Y +export const Y = _Y -export var database = { name: 'memory' } -export var connector = { name: 'test', url: 'http://localhost:1234' } +Y.extend(yTest) + +export const database = { name: 'memory' } +export const connector = { name: 'test', url: 'http://localhost:1234' } function getStateSet (y) { let ss = {} @@ -19,7 +21,7 @@ function getStateSet (y) { function getDeleteSet (y) { var ds = {} - y.ds.iterate(this, null, null, function (n) { + y.ds.iterate(null, null, function (n) { var user = n.id[0] var counter = n.id[1] var len = n.len @@ -108,7 +110,7 @@ export async function compareUsers (t, users) { var data = users.forEach(u => { var data = {} let ops = [] - y.os.iterate(null, null, function (op) { + u.os.iterate(null, null, function (op) { if (!op._deleted) { ops.push({ left: op._left, @@ -132,8 +134,7 @@ export async function compareUsers (t, users) { for (var i = 0; i < data.length - 1; i++) { await t.asyncGroup(async () => { t.compare(userArrayValues[i], userArrayValues[i + 1], 'array types') - t.compare(userMapOneValues[i], userMapOneValues[i + 1], 'map types (propery "one")') - t.compare(userMapTwoValues[i], userMapTwoValues[i + 1], 'map types (propery "two")') + t.compare(userMapValues[i], userMapValues[i + 1], 'map types') t.compare(userXmlValues[i], userXmlValues[i + 1], 'xml types') t.compare(data[i].os, data[i + 1].os, 'os') t.compare(data[i].ds, data[i + 1].ds, 'ds')