fix encoding and rb tree tests
This commit is contained in:
		
							parent
							
								
									0e426f8928
								
							
						
					
					
						commit
						4eec8ecdd3
					
				
							
								
								
									
										5
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -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", | ||||
|  | ||||
| @ -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" | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -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: [ | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| import '../../node_modules/utf8/utf8.js' | ||||
| import utf8 from 'utf-8' | ||||
| 
 | ||||
| export default class BinaryDecoder { | ||||
|   constructor (buffer) { | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| import '../../node_modules/utf8/utf8.js' | ||||
| import utf8 from 'utf-8' | ||||
| 
 | ||||
| const bits7 = 0b1111111 | ||||
| const bits8 = 0b11111111 | ||||
|  | ||||
| @ -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)
 | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| import { getStruct } from '../Util/StructReferences.js' | ||||
| import { getStruct } from '../Util/structReferences.js' | ||||
| import BinaryDecoder from '../Binary/Decoder.js' | ||||
| 
 | ||||
| class MissingEntry { | ||||
|  | ||||
| @ -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++ | ||||
|  | ||||
| @ -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) { | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
| @ -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!')
 | ||||
|  | ||||
							
								
								
									
										12
									
								
								src/Y.js
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								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 | ||||
|  | ||||
| @ -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() | ||||
|  | ||||
| @ -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,20 +71,15 @@ 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 obj = new ID(chance.integer({min: 0, max: numberOfRBTreeTests}), chance.integer({min: 0, max: 1})) | ||||
|       let nodeExists = tree.find(obj) | ||||
|         if (!nodeExists) { | ||||
|           if (elements.some(e => e[0] === obj[0])) { | ||||
|       if (nodeExists === null) { | ||||
|         if (elements.some(e => e.equals(obj))) { | ||||
|           t.assert(false, 'tree and elements contain different results') | ||||
|         } | ||||
|         elements.push(obj) | ||||
| @ -100,31 +89,28 @@ test(`random tests (${numberOfRBTreeTests})`, async function random (t) { | ||||
|       // ~20% chance to delete an element
 | ||||
|       var elem = chance.pickone(elements) | ||||
|       elements = elements.filter(function (e) { | ||||
|           return !Y.utils.compareIds(e, elem) | ||||
|         return !e.equals(elem) | ||||
|       }) | ||||
|       tree.delete(elem) | ||||
|     } | ||||
|   } | ||||
|   }) | ||||
|   await memory.whenTransactionsFinished() | ||||
|   checkRootNodeIsBlack(t, tree) | ||||
|   checkBlackHeightOfSubTreesAreEqual(t, tree) | ||||
|   checkRedNodesDoNotHaveBlackChildren(t, tree) | ||||
|   memory.requestTransaction(function () { | ||||
|   // TEST if all nodes exist
 | ||||
|   let allNodesExist = true | ||||
|   for (let id of elements) { | ||||
|     let node = tree.find(id) | ||||
|       if (!Y.utils.compareIds(node.id, id)) { | ||||
|     if (!node.id.equals(id)) { | ||||
|       allNodesExist = false | ||||
|     } | ||||
|   } | ||||
|   t.assert(allNodesExist, 'All inserted nodes exist') | ||||
|   }) | ||||
|   memory.requestTransaction(function () { | ||||
|   // TEST lower bound search
 | ||||
|   let findAllNodesWithLowerBoundSerach = true | ||||
|   for (let id of elements) { | ||||
|     let node = tree.findWithLowerBound(id) | ||||
|       if (!Y.utils.compareIds(node.id, id)) { | ||||
|     if (!node.id.equals(id)) { | ||||
|       findAllNodesWithLowerBoundSerach = false | ||||
|     } | ||||
|   } | ||||
| @ -132,16 +118,14 @@ test(`random tests (${numberOfRBTreeTests})`, async function random (t) { | ||||
|     findAllNodesWithLowerBoundSerach, | ||||
|     'Find every object with lower bound search' | ||||
|   ) | ||||
|   }) | ||||
| 
 | ||||
|   memory.requestTransaction(function () { | ||||
|   // TEST iteration (with lower bound search)
 | ||||
|   let lowerBound = chance.pickone(elements) | ||||
|   let expectedResults = elements.filter((e, pos) => | ||||
|       (Y.utils.smaller(lowerBound, e) || Y.utils.compareIds(e, lowerBound)) && | ||||
|     (lowerBound.lessThan(e) || e.equals(lowerBound)) && | ||||
|     elements.indexOf(e) === pos | ||||
|   ).length | ||||
|   let actualResults = 0 | ||||
|     tree.iterate(this, lowerBound, null, function (val) { | ||||
|   tree.iterate(lowerBound, null, function (val) { | ||||
|     if (val == null) { | ||||
|       t.assert(false, 'val is undefined!') | ||||
|     } | ||||
| @ -151,14 +135,12 @@ test(`random tests (${numberOfRBTreeTests})`, async function random (t) { | ||||
|     expectedResults === actualResults, | ||||
|     'Iterating over a tree with lower bound yields the right amount of results' | ||||
|   ) | ||||
|   }) | ||||
| 
 | ||||
|   memory.requestTransaction(function () { | ||||
|     let expectedResults = elements.filter((e, pos) => | ||||
|   expectedResults = elements.filter((e, pos) => | ||||
|     elements.indexOf(e) === pos | ||||
|   ).length | ||||
|     let actualResults = 0 | ||||
|     tree.iterate(this, null, null, function (val) { | ||||
|   actualResults = 0 | ||||
|   tree.iterate(null, null, function (val) { | ||||
|     if (val == null) { | ||||
|       t.assert(false, 'val is undefined!') | ||||
|     } | ||||
| @ -168,16 +150,14 @@ test(`random tests (${numberOfRBTreeTests})`, async function random (t) { | ||||
|     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)) && | ||||
|   expectedResults = elements.filter((e, pos) => | ||||
|     (e.lessThan(upperBound) || e.equals(upperBound)) && | ||||
|     elements.indexOf(e) === pos | ||||
|   ).length | ||||
|     let actualResults = 0 | ||||
|     tree.iterate(this, null, upperBound, function (val) { | ||||
|   actualResults = 0 | ||||
|   tree.iterate(null, upperBound, function (val) { | ||||
|     if (val == null) { | ||||
|       t.assert(false, 'val is undefined!') | ||||
|     } | ||||
| @ -187,21 +167,19 @@ test(`random tests (${numberOfRBTreeTests})`, async function random (t) { | ||||
|     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)) { | ||||
|   upperBound = chance.pickone(elements) | ||||
|   lowerBound = chance.pickone(elements) | ||||
|   if (upperBound.lessThan(lowerBound)) { | ||||
|     [lowerBound, upperBound] = [upperBound, lowerBound] | ||||
|   } | ||||
|     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)) && | ||||
|   expectedResults = elements.filter((e, pos) => | ||||
|     (lowerBound.lessThan(e) || e.equals(lowerBound)) && | ||||
|     (e.lessThan(upperBound) || e.equals(upperBound)) && | ||||
|     elements.indexOf(e) === pos | ||||
|   ).length | ||||
|     let actualResults = 0 | ||||
|     tree.iterate(this, lowerBound, upperBound, function (val) { | ||||
|   actualResults = 0 | ||||
|   tree.iterate(lowerBound, upperBound, function (val) { | ||||
|     if (val == null) { | ||||
|       t.assert(false, 'val is undefined!') | ||||
|     } | ||||
| @ -211,7 +189,4 @@ test(`random tests (${numberOfRBTreeTests})`, async function random (t) { | ||||
|     expectedResults === actualResults, | ||||
|     'iterating over a tree with upper bound yields the right amount of results' | ||||
|   ) | ||||
|   }) | ||||
| 
 | ||||
|   await memory.whenTransactionsFinished() | ||||
| }) | ||||
|  | ||||
| @ -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') | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user