Skip to content

Commit 624c696

Browse files
webzwo0irhansen
authored andcommitted
easysync tests: move to separate files
1 parent 1bbe0d9 commit 624c696

File tree

9 files changed

+978
-924
lines changed

9 files changed

+978
-924
lines changed
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
'use strict';
2+
3+
const Changeset = require('../../static/js/Changeset');
4+
const AttributePool = require('../../static/js/AttributePool');
5+
6+
const randInt = (maxValue) => Math.floor(Math.random() * maxValue);
7+
exports.randInt = randInt;
8+
9+
const randomMultiline = (approxMaxLines, approxMaxCols) => {
10+
const numParts = randInt(approxMaxLines * 2) + 1;
11+
const txt = Changeset.stringAssembler();
12+
txt.append(randInt(2) ? '\n' : '');
13+
for (let i = 0; i < numParts; i++) {
14+
if ((i % 2) === 0) {
15+
if (randInt(10)) {
16+
txt.append(randomInlineString(randInt(approxMaxCols) + 1));
17+
} else {
18+
txt.append('\n');
19+
}
20+
} else {
21+
txt.append('\n');
22+
}
23+
}
24+
return txt.toString();
25+
};
26+
exports.randomMultiline = randomMultiline;
27+
28+
const randomInlineString = (len) => {
29+
const assem = Changeset.stringAssembler();
30+
for (let i = 0; i < len; i++) {
31+
assem.append(String.fromCharCode(randInt(26) + 97));
32+
}
33+
return assem.toString();
34+
};
35+
exports.randomInlineString = randomInlineString;
36+
37+
const randomTestChangeset = (origText, withAttribs) => {
38+
const charBank = Changeset.stringAssembler();
39+
let textLeft = origText; // always keep final newline
40+
const outTextAssem = Changeset.stringAssembler();
41+
const opAssem = Changeset.smartOpAssembler();
42+
const oldLen = origText.length;
43+
44+
const nextOp = Changeset.newOp();
45+
46+
const appendMultilineOp = (opcode, txt) => {
47+
nextOp.opcode = opcode;
48+
if (withAttribs) {
49+
nextOp.attribs = randomTwoPropAttribs(opcode);
50+
}
51+
txt.replace(/\n|[^\n]+/g, (t) => {
52+
if (t === '\n') {
53+
nextOp.chars = 1;
54+
nextOp.lines = 1;
55+
opAssem.append(nextOp);
56+
} else {
57+
nextOp.chars = t.length;
58+
nextOp.lines = 0;
59+
opAssem.append(nextOp);
60+
}
61+
return '';
62+
});
63+
};
64+
65+
const doOp = () => {
66+
const o = randomStringOperation(textLeft.length);
67+
if (o.insert) {
68+
const txt = o.insert;
69+
charBank.append(txt);
70+
outTextAssem.append(txt);
71+
appendMultilineOp('+', txt);
72+
} else if (o.skip) {
73+
const txt = textLeft.substring(0, o.skip);
74+
textLeft = textLeft.substring(o.skip);
75+
outTextAssem.append(txt);
76+
appendMultilineOp('=', txt);
77+
} else if (o.remove) {
78+
const txt = textLeft.substring(0, o.remove);
79+
textLeft = textLeft.substring(o.remove);
80+
appendMultilineOp('-', txt);
81+
}
82+
};
83+
84+
while (textLeft.length > 1) doOp();
85+
for (let i = 0; i < 5; i++) doOp(); // do some more (only insertions will happen)
86+
const outText = `${outTextAssem.toString()}\n`;
87+
opAssem.endDocument();
88+
const cs = Changeset.pack(oldLen, outText.length, opAssem.toString(), charBank.toString());
89+
Changeset.checkRep(cs);
90+
return [cs, outText];
91+
};
92+
exports.randomTestChangeset = randomTestChangeset;
93+
94+
const randomStringOperation = (numCharsLeft) => {
95+
let result;
96+
switch (randInt(9)) {
97+
case 0:
98+
{
99+
// insert char
100+
result = {
101+
insert: randomInlineString(1),
102+
};
103+
break;
104+
}
105+
case 1:
106+
{
107+
// delete char
108+
result = {
109+
remove: 1,
110+
};
111+
break;
112+
}
113+
case 2:
114+
{
115+
// skip char
116+
result = {
117+
skip: 1,
118+
};
119+
break;
120+
}
121+
case 3:
122+
{
123+
// insert small
124+
result = {
125+
insert: randomInlineString(randInt(4) + 1),
126+
};
127+
break;
128+
}
129+
case 4:
130+
{
131+
// delete small
132+
result = {
133+
remove: randInt(4) + 1,
134+
};
135+
break;
136+
}
137+
case 5:
138+
{
139+
// skip small
140+
result = {
141+
skip: randInt(4) + 1,
142+
};
143+
break;
144+
}
145+
case 6:
146+
{
147+
// insert multiline;
148+
result = {
149+
insert: randomMultiline(5, 20),
150+
};
151+
break;
152+
}
153+
case 7:
154+
{
155+
// delete multiline
156+
result = {
157+
remove: Math.round(numCharsLeft * Math.random() * Math.random()),
158+
};
159+
break;
160+
}
161+
case 8:
162+
{
163+
// skip multiline
164+
result = {
165+
skip: Math.round(numCharsLeft * Math.random() * Math.random()),
166+
};
167+
break;
168+
}
169+
case 9:
170+
{
171+
// delete to end
172+
result = {
173+
remove: numCharsLeft,
174+
};
175+
break;
176+
}
177+
case 10:
178+
{
179+
// skip to end
180+
result = {
181+
skip: numCharsLeft,
182+
};
183+
break;
184+
}
185+
}
186+
const maxOrig = numCharsLeft - 1;
187+
if ('remove' in result) {
188+
result.remove = Math.min(result.remove, maxOrig);
189+
} else if ('skip' in result) {
190+
result.skip = Math.min(result.skip, maxOrig);
191+
}
192+
return result;
193+
};
194+
exports.randomStringOperation = randomStringOperation;
195+
196+
const randomTwoPropAttribs = (opcode) => {
197+
// assumes attrib pool like ['apple,','apple,true','banana,','banana,true']
198+
if (opcode === '-' || randInt(3)) {
199+
return '';
200+
} else if (randInt(3)) { // eslint-disable-line no-dupe-else-if
201+
if (opcode === '+' || randInt(2)) {
202+
return `*${Changeset.numToString(randInt(2) * 2 + 1)}`;
203+
} else {
204+
return `*${Changeset.numToString(randInt(2) * 2)}`;
205+
}
206+
} else if (opcode === '+' || randInt(4) === 0) {
207+
return '*1*3';
208+
} else {
209+
return ['*0*2', '*0*3', '*1*2'][randInt(3)];
210+
}
211+
};
212+
exports.randomTwoPropAttribs = randomTwoPropAttribs;
213+
214+
const poolOrArray = (attribs) => {
215+
if (attribs.getAttrib) {
216+
return attribs; // it's already an attrib pool
217+
} else {
218+
// assume it's an array of attrib strings to be split and added
219+
const p = new AttributePool();
220+
attribs.forEach((kv) => {
221+
p.putAttrib(kv.split(','));
222+
});
223+
return p;
224+
}
225+
};
226+
exports.poolOrArray = poolOrArray;
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
'use strict';
2+
3+
const Changeset = require('../../../static/js/Changeset');
4+
const {poolOrArray} = require('../easysync-helper.js');
5+
6+
describe('easysync', function () {
7+
it('opAssembler', async function () {
8+
const x = '-c*3*4+6|3=az*asdf0*1*2*3+1=1-1+1*0+1=1-1+1|c=c-1';
9+
const iter = Changeset.opIterator(x);
10+
const assem = Changeset.opAssembler();
11+
while (iter.hasNext()) assem.append(iter.next());
12+
expect(assem.toString()).to.equal(x);
13+
});
14+
15+
it('smartOpAssembler', async function () {
16+
const x = '-c*3*4+6|3=az*asdf0*1*2*3+1=1-1+1*0+1=1-1+1|c=c-1';
17+
const iter = Changeset.opIterator(x);
18+
const assem = Changeset.smartOpAssembler();
19+
while (iter.hasNext()) assem.append(iter.next());
20+
assem.endDocument();
21+
expect(assem.toString()).to.equal(x);
22+
});
23+
24+
describe('append atext to assembler', function () {
25+
const testAppendATextToAssembler = (testId, atext, correctOps) => {
26+
it(`testAppendATextToAssembler#${testId}`, async function () {
27+
const assem = Changeset.smartOpAssembler();
28+
Changeset.appendATextToAssembler(atext, assem);
29+
expect(assem.toString()).to.equal(correctOps);
30+
});
31+
};
32+
33+
testAppendATextToAssembler(1, {
34+
text: '\n',
35+
attribs: '|1+1',
36+
}, '');
37+
testAppendATextToAssembler(2, {
38+
text: '\n\n',
39+
attribs: '|2+2',
40+
}, '|1+1');
41+
testAppendATextToAssembler(3, {
42+
text: '\n\n',
43+
attribs: '*x|2+2',
44+
}, '*x|1+1');
45+
testAppendATextToAssembler(4, {
46+
text: '\n\n',
47+
attribs: '*x|1+1|1+1',
48+
}, '*x|1+1');
49+
testAppendATextToAssembler(5, {
50+
text: 'foo\n',
51+
attribs: '|1+4',
52+
}, '+3');
53+
testAppendATextToAssembler(6, {
54+
text: '\nfoo\n',
55+
attribs: '|2+5',
56+
}, '|1+1+3');
57+
testAppendATextToAssembler(7, {
58+
text: '\nfoo\n',
59+
attribs: '*x|2+5',
60+
}, '*x|1+1*x+3');
61+
testAppendATextToAssembler(8, {
62+
text: '\n\n\nfoo\n',
63+
attribs: '|2+2*x|2+5',
64+
}, '|2+2*x|1+1*x+3');
65+
});
66+
});
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
'use strict';
2+
3+
const Changeset = require('../../../static/js/Changeset');
4+
const AttributePool = require('../../../static/js/AttributePool');
5+
const {randomMultiline, randomTestChangeset} = require('../easysync-helper.js');
6+
7+
describe('easysync', function () {
8+
describe('compose', function () {
9+
const testCompose = (randomSeed) => {
10+
it(`testCompose#${randomSeed}`, async function () {
11+
const p = new AttributePool();
12+
13+
const startText = `${randomMultiline(10, 20)}\n`;
14+
15+
const x1 = randomTestChangeset(startText);
16+
const change1 = x1[0];
17+
const text1 = x1[1];
18+
19+
const x2 = randomTestChangeset(text1);
20+
const change2 = x2[0];
21+
const text2 = x2[1];
22+
23+
const x3 = randomTestChangeset(text2);
24+
const change3 = x3[0];
25+
const text3 = x3[1];
26+
27+
const change12 = Changeset.checkRep(Changeset.compose(change1, change2, p));
28+
const change23 = Changeset.checkRep(Changeset.compose(change2, change3, p));
29+
const change123 = Changeset.checkRep(Changeset.compose(change12, change3, p));
30+
const change123a = Changeset.checkRep(Changeset.compose(change1, change23, p));
31+
expect(change123a).to.equal(change123);
32+
33+
expect(Changeset.applyToText(change12, startText)).to.equal(text2);
34+
expect(Changeset.applyToText(change23, text1)).to.equal(text3);
35+
expect(Changeset.applyToText(change123, startText)).to.equal(text3);
36+
});
37+
};
38+
39+
for (let i = 0; i < 30; i++) testCompose(i);
40+
});
41+
42+
describe('compose attributes', function () {
43+
it('simpleComposeAttributesTest', async function () {
44+
const p = new AttributePool();
45+
p.putAttrib(['bold', '']);
46+
p.putAttrib(['bold', 'true']);
47+
const cs1 = Changeset.checkRep('Z:2>1*1+1*1=1$x');
48+
const cs2 = Changeset.checkRep('Z:3>0*0|1=3$');
49+
const cs12 = Changeset.checkRep(Changeset.compose(cs1, cs2, p));
50+
expect(cs12).to.equal('Z:2>1+1*0|1=2$x');
51+
});
52+
});
53+
});

0 commit comments

Comments
 (0)