mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-01-31 19:02:59 +01:00
easysync tests: Move shared helper functions to the top
This will make it easier to split `easysync.js` into multiple files.
This commit is contained in:
parent
d3427240c6
commit
6a7b54313f
1 changed files with 213 additions and 213 deletions
|
@ -28,6 +28,219 @@ 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;
|
||||
}
|
||||
};
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
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];
|
||||
};
|
||||
|
||||
describe('easysync', function () {
|
||||
it('throughIterator', 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';
|
||||
|
@ -176,19 +389,6 @@ describe('easysync', function () {
|
|||
['skip', 1, 1, true],
|
||||
], ['banana\n', 'cabbage\n', 'duffle\n']);
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
const runApplyToAttributionTest = (testId, attribs, cs, inAttr, outCorrect) => {
|
||||
it(`applyToAttribution#${testId}`, async function () {
|
||||
const p = poolOrArray(attribs);
|
||||
|
@ -354,206 +554,6 @@ describe('easysync', function () {
|
|||
'|1+1',
|
||||
]);
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
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];
|
||||
};
|
||||
|
||||
const testCompose = (randomSeed) => {
|
||||
it(`testCompose#${randomSeed}`, async function () {
|
||||
const p = new AttributePool();
|
||||
|
|
Loading…
Reference in a new issue