Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/test/common/model/editableTextModelAuto.test.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { CharCode } from '../../../../base/common/charCode.js';
7
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js';
8
import { ISingleEditOperation } from '../../../common/core/editOperation.js';
9
import { Position } from '../../../common/core/position.js';
10
import { Range } from '../../../common/core/range.js';
11
import { testApplyEditsWithSyncedModels } from './editableTextModelTestUtils.js';
12
13
const GENERATE_TESTS = false;
14
15
suite('EditorModel Auto Tests', () => {
16
17
ensureNoDisposablesAreLeakedInTestSuite();
18
19
function editOp(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, text: string[]): ISingleEditOperation {
20
return {
21
range: new Range(startLineNumber, startColumn, endLineNumber, endColumn),
22
text: text.join('\n'),
23
forceMoveMarkers: false
24
};
25
}
26
27
test('auto1', () => {
28
testApplyEditsWithSyncedModels(
29
[
30
'ioe',
31
'',
32
'yjct',
33
'',
34
'',
35
],
36
[
37
editOp(1, 2, 1, 2, ['b', 'r', 'fq']),
38
editOp(1, 4, 2, 1, ['', '']),
39
],
40
[
41
'ib',
42
'r',
43
'fqoe',
44
'',
45
'yjct',
46
'',
47
'',
48
]
49
);
50
});
51
52
test('auto2', () => {
53
testApplyEditsWithSyncedModels(
54
[
55
'f',
56
'littnhskrq',
57
'utxvsizqnk',
58
'lslqz',
59
'jxn',
60
'gmm',
61
],
62
[
63
editOp(1, 2, 1, 2, ['', 'o']),
64
editOp(2, 4, 2, 4, ['zaq', 'avb']),
65
editOp(2, 5, 6, 2, ['jlr', 'zl', 'j']),
66
],
67
[
68
'f',
69
'o',
70
'litzaq',
71
'avbtjlr',
72
'zl',
73
'jmm',
74
]
75
);
76
});
77
78
test('auto3', () => {
79
testApplyEditsWithSyncedModels(
80
[
81
'ofw',
82
'qsxmziuvzw',
83
'rp',
84
'qsnymek',
85
'elth',
86
'wmgzbwudxz',
87
'iwsdkndh',
88
'bujlbwb',
89
'asuouxfv',
90
'xuccnb',
91
],
92
[
93
editOp(4, 3, 4, 3, ['']),
94
],
95
[
96
'ofw',
97
'qsxmziuvzw',
98
'rp',
99
'qsnymek',
100
'elth',
101
'wmgzbwudxz',
102
'iwsdkndh',
103
'bujlbwb',
104
'asuouxfv',
105
'xuccnb',
106
]
107
);
108
});
109
110
test('auto4', () => {
111
testApplyEditsWithSyncedModels(
112
[
113
'fefymj',
114
'qum',
115
'vmiwxxaiqq',
116
'dz',
117
'lnqdgorosf',
118
],
119
[
120
editOp(1, 3, 1, 5, ['hp']),
121
editOp(1, 7, 2, 1, ['kcg', '', 'mpx']),
122
editOp(2, 2, 2, 2, ['', 'aw', '']),
123
editOp(2, 2, 2, 2, ['vqr', 'mo']),
124
editOp(4, 2, 5, 3, ['xyc']),
125
],
126
[
127
'fehpmjkcg',
128
'',
129
'mpxq',
130
'aw',
131
'vqr',
132
'moum',
133
'vmiwxxaiqq',
134
'dxycqdgorosf',
135
]
136
);
137
});
138
});
139
140
function getRandomInt(min: number, max: number): number {
141
return Math.floor(Math.random() * (max - min + 1)) + min;
142
}
143
144
function getRandomString(minLength: number, maxLength: number): string {
145
const length = getRandomInt(minLength, maxLength);
146
let r = '';
147
for (let i = 0; i < length; i++) {
148
r += String.fromCharCode(getRandomInt(CharCode.a, CharCode.z));
149
}
150
return r;
151
}
152
153
function generateFile(small: boolean): string {
154
const lineCount = getRandomInt(1, small ? 3 : 10);
155
const lines: string[] = [];
156
for (let i = 0; i < lineCount; i++) {
157
lines.push(getRandomString(0, small ? 3 : 10));
158
}
159
return lines.join('\n');
160
}
161
162
function generateEdits(content: string): ITestModelEdit[] {
163
164
const result: ITestModelEdit[] = [];
165
let cnt = getRandomInt(1, 5);
166
167
let maxOffset = content.length;
168
169
while (cnt > 0 && maxOffset > 0) {
170
171
const offset = getRandomInt(0, maxOffset);
172
const length = getRandomInt(0, maxOffset - offset);
173
const text = generateFile(true);
174
175
result.push({
176
offset: offset,
177
length: length,
178
text: text
179
});
180
181
maxOffset = offset;
182
cnt--;
183
}
184
185
result.reverse();
186
187
return result;
188
}
189
190
interface ITestModelEdit {
191
offset: number;
192
length: number;
193
text: string;
194
}
195
196
class TestModel {
197
198
public initialContent: string;
199
public resultingContent: string;
200
public edits: ISingleEditOperation[];
201
202
private static _generateOffsetToPosition(content: string): Position[] {
203
const result: Position[] = [];
204
let lineNumber = 1;
205
let column = 1;
206
207
for (let offset = 0, len = content.length; offset <= len; offset++) {
208
const ch = content.charAt(offset);
209
210
result[offset] = new Position(lineNumber, column);
211
212
if (ch === '\n') {
213
lineNumber++;
214
column = 1;
215
} else {
216
column++;
217
}
218
}
219
220
return result;
221
}
222
223
constructor() {
224
this.initialContent = generateFile(false);
225
226
const edits = generateEdits(this.initialContent);
227
228
const offsetToPosition = TestModel._generateOffsetToPosition(this.initialContent);
229
this.edits = [];
230
for (const edit of edits) {
231
const startPosition = offsetToPosition[edit.offset];
232
const endPosition = offsetToPosition[edit.offset + edit.length];
233
this.edits.push({
234
range: new Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column),
235
text: edit.text
236
});
237
}
238
239
this.resultingContent = this.initialContent;
240
for (let i = edits.length - 1; i >= 0; i--) {
241
this.resultingContent = (
242
this.resultingContent.substring(0, edits[i].offset) +
243
edits[i].text +
244
this.resultingContent.substring(edits[i].offset + edits[i].length)
245
);
246
}
247
}
248
249
public print(): string {
250
let r: string[] = [];
251
r.push('testApplyEditsWithSyncedModels(');
252
r.push('\t[');
253
const initialLines = this.initialContent.split('\n');
254
r = r.concat(initialLines.map((i) => `\t\t'${i}',`));
255
r.push('\t],');
256
r.push('\t[');
257
r = r.concat(this.edits.map((i) => {
258
const text = `['` + i.text!.split('\n').join(`', '`) + `']`;
259
return `\t\teditOp(${i.range.startLineNumber}, ${i.range.startColumn}, ${i.range.endLineNumber}, ${i.range.endColumn}, ${text}),`;
260
}));
261
r.push('\t],');
262
r.push('\t[');
263
const resultLines = this.resultingContent.split('\n');
264
r = r.concat(resultLines.map((i) => `\t\t'${i}',`));
265
r.push('\t]');
266
r.push(');');
267
268
return r.join('\n');
269
}
270
}
271
272
if (GENERATE_TESTS) {
273
let number = 1;
274
while (true) {
275
276
console.log('------BEGIN NEW TEST: ' + number);
277
278
const testModel = new TestModel();
279
280
// console.log(testModel.print());
281
282
console.log('------END NEW TEST: ' + (number++));
283
284
try {
285
testApplyEditsWithSyncedModels(
286
testModel.initialContent.split('\n'),
287
testModel.edits,
288
testModel.resultingContent.split('\n')
289
);
290
// throw new Error('a');
291
} catch (err) {
292
console.log(err);
293
console.log(testModel.print());
294
break;
295
}
296
297
// break;
298
}
299
300
}
301
302