-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
easysync tests: Split into multiple files
- Loading branch information
Showing
9 changed files
with
973 additions
and
962 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
'use strict'; | ||
|
||
const Changeset = require('../../static/js/Changeset'); | ||
const AttributePool = require('../../static/js/AttributePool'); | ||
|
||
const randInt = (maxValue) => Math.floor(Math.random() * maxValue); | ||
|
||
const poolOrArray = (attribs) => { | ||
if (attribs.getAttrib) { | ||
return attribs; // it's already an attrib pool | ||
} else { | ||
// assume it's an array of attrib strings to be split and added | ||
const p = new AttributePool(); | ||
attribs.forEach((kv) => { | ||
p.putAttrib(kv.split(',')); | ||
}); | ||
return p; | ||
} | ||
}; | ||
exports.poolOrArray = poolOrArray; | ||
|
||
const randomInlineString = (len) => { | ||
const assem = Changeset.stringAssembler(); | ||
for (let i = 0; i < len; i++) { | ||
assem.append(String.fromCharCode(randInt(26) + 97)); | ||
} | ||
return assem.toString(); | ||
}; | ||
|
||
const randomMultiline = (approxMaxLines, approxMaxCols) => { | ||
const numParts = randInt(approxMaxLines * 2) + 1; | ||
const txt = Changeset.stringAssembler(); | ||
txt.append(randInt(2) ? '\n' : ''); | ||
for (let i = 0; i < numParts; i++) { | ||
if ((i % 2) === 0) { | ||
if (randInt(10)) { | ||
txt.append(randomInlineString(randInt(approxMaxCols) + 1)); | ||
} else { | ||
txt.append('\n'); | ||
} | ||
} else { | ||
txt.append('\n'); | ||
} | ||
} | ||
return txt.toString(); | ||
}; | ||
exports.randomMultiline = randomMultiline; | ||
|
||
const randomStringOperation = (numCharsLeft) => { | ||
let result; | ||
switch (randInt(9)) { | ||
case 0: | ||
{ | ||
// insert char | ||
result = { | ||
insert: randomInlineString(1), | ||
}; | ||
break; | ||
} | ||
case 1: | ||
{ | ||
// delete char | ||
result = { | ||
remove: 1, | ||
}; | ||
break; | ||
} | ||
case 2: | ||
{ | ||
// skip char | ||
result = { | ||
skip: 1, | ||
}; | ||
break; | ||
} | ||
case 3: | ||
{ | ||
// insert small | ||
result = { | ||
insert: randomInlineString(randInt(4) + 1), | ||
}; | ||
break; | ||
} | ||
case 4: | ||
{ | ||
// delete small | ||
result = { | ||
remove: randInt(4) + 1, | ||
}; | ||
break; | ||
} | ||
case 5: | ||
{ | ||
// skip small | ||
result = { | ||
skip: randInt(4) + 1, | ||
}; | ||
break; | ||
} | ||
case 6: | ||
{ | ||
// insert multiline; | ||
result = { | ||
insert: randomMultiline(5, 20), | ||
}; | ||
break; | ||
} | ||
case 7: | ||
{ | ||
// delete multiline | ||
result = { | ||
remove: Math.round(numCharsLeft * Math.random() * Math.random()), | ||
}; | ||
break; | ||
} | ||
case 8: | ||
{ | ||
// skip multiline | ||
result = { | ||
skip: Math.round(numCharsLeft * Math.random() * Math.random()), | ||
}; | ||
break; | ||
} | ||
case 9: | ||
{ | ||
// delete to end | ||
result = { | ||
remove: numCharsLeft, | ||
}; | ||
break; | ||
} | ||
case 10: | ||
{ | ||
// skip to end | ||
result = { | ||
skip: numCharsLeft, | ||
}; | ||
break; | ||
} | ||
} | ||
const maxOrig = numCharsLeft - 1; | ||
if ('remove' in result) { | ||
result.remove = Math.min(result.remove, maxOrig); | ||
} else if ('skip' in result) { | ||
result.skip = Math.min(result.skip, maxOrig); | ||
} | ||
return result; | ||
}; | ||
|
||
const randomTwoPropAttribs = (opcode) => { | ||
// assumes attrib pool like ['apple,','apple,true','banana,','banana,true'] | ||
if (opcode === '-' || randInt(3)) { | ||
return ''; | ||
} else if (randInt(3)) { // eslint-disable-line no-dupe-else-if | ||
if (opcode === '+' || randInt(2)) { | ||
return `*${Changeset.numToString(randInt(2) * 2 + 1)}`; | ||
} else { | ||
return `*${Changeset.numToString(randInt(2) * 2)}`; | ||
} | ||
} else if (opcode === '+' || randInt(4) === 0) { | ||
return '*1*3'; | ||
} else { | ||
return ['*0*2', '*0*3', '*1*2'][randInt(3)]; | ||
} | ||
}; | ||
|
||
const randomTestChangeset = (origText, withAttribs) => { | ||
const charBank = Changeset.stringAssembler(); | ||
let textLeft = origText; // always keep final newline | ||
const outTextAssem = Changeset.stringAssembler(); | ||
const opAssem = Changeset.smartOpAssembler(); | ||
const oldLen = origText.length; | ||
|
||
const nextOp = new Changeset.Op(); | ||
|
||
const appendMultilineOp = (opcode, txt) => { | ||
nextOp.opcode = opcode; | ||
if (withAttribs) { | ||
nextOp.attribs = randomTwoPropAttribs(opcode); | ||
} | ||
txt.replace(/\n|[^\n]+/g, (t) => { | ||
if (t === '\n') { | ||
nextOp.chars = 1; | ||
nextOp.lines = 1; | ||
opAssem.append(nextOp); | ||
} else { | ||
nextOp.chars = t.length; | ||
nextOp.lines = 0; | ||
opAssem.append(nextOp); | ||
} | ||
return ''; | ||
}); | ||
}; | ||
|
||
const doOp = () => { | ||
const o = randomStringOperation(textLeft.length); | ||
if (o.insert) { | ||
const txt = o.insert; | ||
charBank.append(txt); | ||
outTextAssem.append(txt); | ||
appendMultilineOp('+', txt); | ||
} else if (o.skip) { | ||
const txt = textLeft.substring(0, o.skip); | ||
textLeft = textLeft.substring(o.skip); | ||
outTextAssem.append(txt); | ||
appendMultilineOp('=', txt); | ||
} else if (o.remove) { | ||
const txt = textLeft.substring(0, o.remove); | ||
textLeft = textLeft.substring(o.remove); | ||
appendMultilineOp('-', txt); | ||
} | ||
}; | ||
|
||
while (textLeft.length > 1) doOp(); | ||
for (let i = 0; i < 5; i++) doOp(); // do some more (only insertions will happen) | ||
const outText = `${outTextAssem.toString()}\n`; | ||
opAssem.endDocument(); | ||
const cs = Changeset.pack(oldLen, outText.length, opAssem.toString(), charBank.toString()); | ||
Changeset.checkRep(cs); | ||
return [cs, outText]; | ||
}; | ||
exports.randomTestChangeset = randomTestChangeset; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
'use strict'; | ||
|
||
const Changeset = require('../../../static/js/Changeset'); | ||
|
||
describe('easysync-assembler', function () { | ||
it('opAssembler', async function () { | ||
const x = '-c*3*4+6|3=az*asdf0*1*2*3+1=1-1+1*0+1=1-1+1|c=c-1'; | ||
const assem = Changeset.opAssembler(); | ||
for (const op of Changeset.deserializeOps(x)) assem.append(op); | ||
expect(assem.toString()).to.equal(x); | ||
}); | ||
|
||
it('smartOpAssembler', async function () { | ||
const x = '-c*3*4+6|3=az*asdf0*1*2*3+1=1-1+1*0+1=1-1+1|c=c-1'; | ||
const assem = Changeset.smartOpAssembler(); | ||
for (const op of Changeset.deserializeOps(x)) assem.append(op); | ||
assem.endDocument(); | ||
expect(assem.toString()).to.equal(x); | ||
}); | ||
|
||
describe('append atext to assembler', function () { | ||
const testAppendATextToAssembler = (testId, atext, correctOps) => { | ||
it(`testAppendATextToAssembler#${testId}`, async function () { | ||
const assem = Changeset.smartOpAssembler(); | ||
for (const op of Changeset.opsFromAText(atext)) assem.append(op); | ||
expect(assem.toString()).to.equal(correctOps); | ||
}); | ||
}; | ||
|
||
testAppendATextToAssembler(1, { | ||
text: '\n', | ||
attribs: '|1+1', | ||
}, ''); | ||
testAppendATextToAssembler(2, { | ||
text: '\n\n', | ||
attribs: '|2+2', | ||
}, '|1+1'); | ||
testAppendATextToAssembler(3, { | ||
text: '\n\n', | ||
attribs: '*x|2+2', | ||
}, '*x|1+1'); | ||
testAppendATextToAssembler(4, { | ||
text: '\n\n', | ||
attribs: '*x|1+1|1+1', | ||
}, '*x|1+1'); | ||
testAppendATextToAssembler(5, { | ||
text: 'foo\n', | ||
attribs: '|1+4', | ||
}, '+3'); | ||
testAppendATextToAssembler(6, { | ||
text: '\nfoo\n', | ||
attribs: '|2+5', | ||
}, '|1+1+3'); | ||
testAppendATextToAssembler(7, { | ||
text: '\nfoo\n', | ||
attribs: '*x|2+5', | ||
}, '*x|1+1*x+3'); | ||
testAppendATextToAssembler(8, { | ||
text: '\n\n\nfoo\n', | ||
attribs: '|2+2*x|2+5', | ||
}, '|2+2*x|1+1*x+3'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
'use strict'; | ||
|
||
const Changeset = require('../../../static/js/Changeset'); | ||
const AttributePool = require('../../../static/js/AttributePool'); | ||
const {randomMultiline, randomTestChangeset} = require('../easysync-helper.js'); | ||
|
||
describe('easysync-compose', function () { | ||
describe('compose', function () { | ||
const testCompose = (randomSeed) => { | ||
it(`testCompose#${randomSeed}`, async function () { | ||
const p = new AttributePool(); | ||
|
||
const startText = `${randomMultiline(10, 20)}\n`; | ||
|
||
const x1 = randomTestChangeset(startText); | ||
const change1 = x1[0]; | ||
const text1 = x1[1]; | ||
|
||
const x2 = randomTestChangeset(text1); | ||
const change2 = x2[0]; | ||
const text2 = x2[1]; | ||
|
||
const x3 = randomTestChangeset(text2); | ||
const change3 = x3[0]; | ||
const text3 = x3[1]; | ||
|
||
const change12 = Changeset.checkRep(Changeset.compose(change1, change2, p)); | ||
const change23 = Changeset.checkRep(Changeset.compose(change2, change3, p)); | ||
const change123 = Changeset.checkRep(Changeset.compose(change12, change3, p)); | ||
const change123a = Changeset.checkRep(Changeset.compose(change1, change23, p)); | ||
expect(change123a).to.equal(change123); | ||
|
||
expect(Changeset.applyToText(change12, startText)).to.equal(text2); | ||
expect(Changeset.applyToText(change23, text1)).to.equal(text3); | ||
expect(Changeset.applyToText(change123, startText)).to.equal(text3); | ||
}); | ||
}; | ||
|
||
for (let i = 0; i < 30; i++) testCompose(i); | ||
}); | ||
|
||
describe('compose attributes', function () { | ||
it('simpleComposeAttributesTest', async function () { | ||
const p = new AttributePool(); | ||
p.putAttrib(['bold', '']); | ||
p.putAttrib(['bold', 'true']); | ||
const cs1 = Changeset.checkRep('Z:2>1*1+1*1=1$x'); | ||
const cs2 = Changeset.checkRep('Z:3>0*0|1=3$'); | ||
const cs12 = Changeset.checkRep(Changeset.compose(cs1, cs2, p)); | ||
expect(cs12).to.equal('Z:2>1+1*0|1=2$x'); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.