Skip to content

Instantly share code, notes, and snippets.

@josephg
Created August 11, 2021 06:37
Show Gist options
  • Save josephg/aa26cf2e8ed4199466be26db630a0899 to your computer and use it in GitHub Desktop.
Save josephg/aa26cf2e8ed4199466be26db630a0899 to your computer and use it in GitHub Desktop.
Test if an OT type is closed udner composition
const genOp = require('./genOp')
// const genOp = require('./genOp2')
const {type} = require('ot-text-unicode')
// const {type} = require('ot-text-tp2')
const assert = require('assert')
const genOps = (start, n = 3) => {
let ops = []
let state = start
for (let j = 0; j < n; j++) {
[op, state] = genOp(state)
ops.push(op)
}
return [ops, state]
}
const transformX = (left, right) => [
type.transform(left, right, 'left'),
type.transform(right, left, 'right')
]
function transformLists(serverOps, clientOps) {
clientOps = clientOps.slice() // Shallow copy for inline replaces.
const serverOpsOut = [];
for (let s of serverOps) {
for (let ci = 0; ci < clientOps.length; ci++) {
[s, clientOps[ci]] = transformX(s, clientOps[ci]);
}
serverOpsOut.push(s);
}
return [serverOpsOut, clientOps];
}
const test2 = () => {
for (let i = 0; i < 1000; i++) {
console.log(i)
let start = type.create('aa')
let a = genOp(start)[0]
let bs = genOps(start, 2)[0]
// let a = [1, 'X']
// let bs = [
// [{d: 'a'}],
// ['Y']
// ]
// We're testing is if
// transform(a, b0 + b1) == transform(a, b0) + transform(a', b1)
let [a1_, b1_] = transformLists([a], bs).map(x => x.reduce(type.compose))
const bCompose = bs.reduce(type.compose)
let [a2_, b2_] = transformX(a, bCompose)
assert.deepStrictEqual(a1_, a2_)
assert.deepStrictEqual(b1_, b2_)
}
}
const test = () => {
// Test:
// A and B both generate operations.
// A transforms by B's operations composed together.
// B transforms by A's operations one by one.
for (let i = 0; i < 1000000; i++) {
// for (let i = 0; i < 1; i++) {
if (i % 10000 === 0) console.log(i)
// console.log(i)
let start = type.create('aa')
let [aOps, aState] = genOps(start)
let [bOps, bState] = genOps(start)
// let [aOps, aState] = [
// [[1,"X"]],
// "aXa"
// ]
// aState = aOps.reduce(type.apply, start)
// console.log('aState', aState)
// let [bOps, bState] = [
// [
// [{"d":"a"}],
// ["Y"]
// ],
// "Ya"
// ]
// bState = bOps.reduce(type.apply, start)
// console.log('bState', bState)
let aOpsCompose = aOps.reduce(type.compose)
let bOpsCompose = bOps.reduce(type.compose)
// console.log(aOps, aOpsCompose)
// A is the client. The client always streams operations one by one from the server.
const [aOps_, bOps_] = transformLists(aOps, bOps)
const aStateFinal = bOps_.reduce(type.apply, aState)
// B is the server. The server transforms the clients' ops by the transformed local ops.
// const aOpsCompose_ = aOps_.reduce(type.compose)
// const bStateFinal = type.apply(bState, aOpsCompose_)
const [aOps__, _] = transformLists(aOps, [bOpsCompose])
const bStateFinal = aOps__.reduce(type.apply, bState)
try {
assert.deepStrictEqual(aStateFinal, bStateFinal)
} catch (e) {
console.log('initial doc', start)
console.log('aOps', aOps, '\n->', aOps_)
console.log('bOps', bOps, '\n->', bOps_)
console.log()
console.log('aOpsCompose', aOpsCompose)
// console.log('bOpsCompose', bOpsCompose)
console.log()
console.log('bOpsCompose', bOpsCompose)
console.log('aOps__', aOps__)
console.log('aOps_', aOps_)
console.log()
console.log('aStateFinal', aStateFinal)
console.log('bStateFinal', bStateFinal)
console.log()
console.log('aState', JSON.stringify([aOps, aState]))
console.log('bState', JSON.stringify([bOps, bState]))
// console.log(
throw e
}
}
}
test2()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment