forked from microsoft/vscode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdiffing.test.ts
More file actions
116 lines (100 loc) · 4.75 KB
/
diffing.test.ts
File metadata and controls
116 lines (100 loc) · 4.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { readdirSync, readFileSync, existsSync, writeFileSync, rmSync } from 'fs';
import { join, resolve } from 'path';
import { FileAccess } from 'vs/base/common/network';
import { SmartLinesDiffComputer } from 'vs/editor/common/diff/smartLinesDiffComputer';
import { StandardLinesDiffComputer } from 'vs/editor/common/diff/standardLinesDiffComputer';
suite('diff fixtures', () => {
const fixturesOutDir = FileAccess.asFileUri('vs/editor/test/node/diffing/fixtures').fsPath;
// We want the dir in src, so we can directly update the source files if they disagree and create invalid files to capture the previous state.
// This makes it very easy to update the fixtures.
const fixturesSrcDir = resolve(fixturesOutDir).replaceAll('\\', '/').replace('/out/vs/editor/', '/src/vs/editor/');
const folders = readdirSync(fixturesSrcDir);
function runTest(folder: string, diffingAlgoName: 'smart' | 'experimental') {
const folderPath = join(fixturesSrcDir, folder);
const files = readdirSync(folderPath);
const firstFileName = files.find(f => f.startsWith('1.'))!;
const secondFileName = files.find(f => f.startsWith('2.'))!;
const firstContentLines = readFileSync(join(folderPath, firstFileName), 'utf8').split(/\r\n|\r|\n/);
const secondContentLines = readFileSync(join(folderPath, secondFileName), 'utf8').split(/\r\n|\r|\n/);
const diffingAlgo = diffingAlgoName === 'smart' ? new SmartLinesDiffComputer() : new StandardLinesDiffComputer();
const diff = diffingAlgo.computeDiff(firstContentLines, secondContentLines, { ignoreTrimWhitespace: false, maxComputationTimeMs: Number.MAX_SAFE_INTEGER });
const actualDiffingResult: DiffingResult = {
originalFileName: `./${firstFileName}`,
modifiedFileName: `./${secondFileName}`,
diffs: diff.changes.map<IDetailedDiff>(c => ({
originalRange: c.originalRange.toString(),
modifiedRange: c.modifiedRange.toString(),
innerChanges: c.innerChanges?.map<IDiff>(c => ({
originalRange: c.originalRange.toString(),
modifiedRange: c.modifiedRange.toString(),
})) || null
}))
};
const expectedFilePath = join(folderPath, `${diffingAlgoName}.expected.diff.json`);
const invalidFilePath = join(folderPath, `${diffingAlgoName}.invalid.diff.json`);
const actualJsonStr = JSON.stringify(actualDiffingResult, null, '\t');
if (!existsSync(expectedFilePath)) {
// New test, create expected file
writeFileSync(expectedFilePath, actualJsonStr);
// Create invalid file so that this test fails on a re-run
writeFileSync(invalidFilePath, '');
throw new Error('No expected file! Expected and invalid files were written. Delete the invalid file to make the test pass.');
} if (existsSync(invalidFilePath)) {
const invalidJsonStr = readFileSync(invalidFilePath, 'utf8');
if (invalidJsonStr === '') {
// Update expected file
writeFileSync(expectedFilePath, actualJsonStr);
throw new Error(`Delete the invalid ${invalidFilePath} file to make the test pass.`);
} else {
const expectedFileDiffResult: DiffingResult = JSON.parse(invalidJsonStr);
try {
assert.deepStrictEqual(actualDiffingResult, expectedFileDiffResult);
} catch (e) {
writeFileSync(expectedFilePath, actualJsonStr);
throw e;
}
// Test succeeded with the invalid file, restore expected file from invalid
writeFileSync(expectedFilePath, invalidJsonStr);
rmSync(invalidFilePath);
}
} else {
const expectedJsonStr = readFileSync(expectedFilePath, 'utf8');
const expectedFileDiffResult: DiffingResult = JSON.parse(expectedJsonStr);
try {
assert.deepStrictEqual(actualDiffingResult, expectedFileDiffResult);
} catch (e) {
// Backup expected file
writeFileSync(invalidFilePath, expectedJsonStr);
// Update expected file
writeFileSync(expectedFilePath, actualJsonStr);
throw e;
}
}
}
for (const folder of folders) {
for (const diffingAlgoName of ['smart', 'experimental'] as const) {
test(`${folder}-${diffingAlgoName}`, () => {
runTest(folder, diffingAlgoName);
});
}
}
});
interface DiffingResult {
originalFileName: string;
modifiedFileName: string;
diffs: IDetailedDiff[];
}
interface IDetailedDiff {
originalRange: string; // [startLineNumber, endLineNumberExclusive)
modifiedRange: string; // [startLineNumber, endLineNumberExclusive)
innerChanges: IDiff[] | null;
}
interface IDiff {
originalRange: string; // [1,18 -> 1,19]
modifiedRange: string; // [1,18 -> 1,19]
}