Skip to content

Commit 309a8f7

Browse files
webzwo0irhansen
authored andcommitted
easysync tests: Split into multiple files
1 parent 2599191 commit 309a8f7

File tree

9 files changed

+973
-962
lines changed

9 files changed

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