Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/test/smoke/src/areas/workbench/data-loss.test.ts
5267 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 { join } from 'path';
7
import { Application, ApplicationOptions, Logger, Quality } from '../../../../automation';
8
import { createApp, timeout, installDiagnosticsHandler, installAppAfterHandler, getRandomUserDataDir, suiteLogsPath, suiteCrashPath } from '../../utils';
9
10
export function setup(ensureStableCode: () => { stableCodePath: string | undefined; stableCodeVersion: { major: number; minor: number; patch: number } | undefined }, logger: Logger) {
11
describe('Data Loss (insiders -> insiders)', function () {
12
13
// Double the timeout since these tests involve 2 startups
14
this.timeout(4 * 60 * 1000);
15
16
let app: Application | undefined = undefined;
17
18
// Shared before/after handling
19
installDiagnosticsHandler(logger, () => app);
20
installAppAfterHandler(() => app);
21
22
it('verifies opened editors are restored', async function () {
23
app = createApp({
24
...this.defaultOptions,
25
logsPath: suiteLogsPath(this.defaultOptions, 'test_verifies_opened_editors_are_restored'),
26
crashesPath: suiteCrashPath(this.defaultOptions, 'test_verifies_opened_editors_are_restored')
27
});
28
await app.start();
29
30
31
// Open 3 editors
32
await app.workbench.quickaccess.openFile(join(app.workspacePathOrFolder, 'bin', 'www'));
33
await app.workbench.quickaccess.runCommand('View: Keep Editor');
34
await app.workbench.quickaccess.openFile(join(app.workspacePathOrFolder, 'app.js'));
35
await app.workbench.quickaccess.runCommand('View: Keep Editor');
36
await app.workbench.editors.newUntitledFile();
37
38
await app.restart();
39
40
// Verify 3 editors are open
41
await app.workbench.editors.selectTab('Untitled-1');
42
await app.workbench.editors.selectTab('app.js');
43
await app.workbench.editors.selectTab('www');
44
45
await app.stop();
46
app = undefined;
47
});
48
49
it('verifies editors can save and restore', async function () {
50
app = createApp({
51
...this.defaultOptions,
52
logsPath: suiteLogsPath(this.defaultOptions, 'test_verifies_editors_can_save_and_restore'),
53
crashesPath: suiteCrashPath(this.defaultOptions, 'test_verifies_editors_can_save_and_restore')
54
});
55
await app.start();
56
57
const textToType = 'Hello, Code';
58
59
// open editor and type
60
await app.workbench.quickaccess.openFile(join(app.workspacePathOrFolder, 'app.js'));
61
await app.workbench.editor.waitForTypeInEditor('app.js', textToType);
62
await app.workbench.editors.waitForTab('app.js', true);
63
64
// save
65
await app.workbench.editors.saveOpenedFile();
66
await app.workbench.editors.waitForTab('app.js', false);
67
68
// restart
69
await app.restart();
70
71
// verify contents
72
await app.workbench.editor.waitForEditorContents('app.js', contents => contents.indexOf(textToType) > -1);
73
74
await app.stop();
75
app = undefined;
76
});
77
78
it('verifies that "hot exit" works for dirty files (without delay)', function () {
79
return testHotExit.call(this, 'test_verifies_that_hot_exit_works_for_dirty_files_without_delay', undefined, undefined);
80
});
81
82
it('verifies that "hot exit" works for dirty files (with delay)', function () {
83
return testHotExit.call(this, 'test_verifies_that_hot_exit_works_for_dirty_files_with_delay', 2000, undefined);
84
});
85
86
it('verifies that auto save triggers on shutdown', function () {
87
return testHotExit.call(this, 'test_verifies_that_auto_save_triggers_on_shutdown', undefined, true);
88
});
89
90
async function testHotExit(this: import('mocha').Context, title: string, restartDelay: number | undefined, autoSave: boolean | undefined) {
91
app = createApp({
92
...this.defaultOptions,
93
logsPath: suiteLogsPath(this.defaultOptions, title),
94
crashesPath: suiteCrashPath(this.defaultOptions, title)
95
});
96
await app.start();
97
98
if (autoSave) {
99
await app.workbench.settingsEditor.addUserSetting('files.autoSave', '"afterDelay"');
100
}
101
102
const textToTypeInUntitled = 'Hello from Untitled';
103
104
await app.workbench.editors.newUntitledFile();
105
await app.workbench.editor.waitForTypeInEditor('Untitled-1', textToTypeInUntitled);
106
await app.workbench.editors.waitForTab('Untitled-1', true);
107
108
const textToType = 'Hello, Code';
109
await app.workbench.quickaccess.openFile(join(app.workspacePathOrFolder, 'readme.md'));
110
await app.workbench.editor.waitForTypeInEditor('readme.md', textToType);
111
await app.workbench.editors.waitForTab('readme.md', !autoSave);
112
113
if (typeof restartDelay === 'number') {
114
// this is an OK use of a timeout in a smoke test:
115
// we want to simulate a user having typed into
116
// the editor and pausing for a moment before
117
// terminating
118
await timeout(restartDelay);
119
}
120
121
await app.restart();
122
123
await app.workbench.editors.waitForTab('readme.md', !autoSave);
124
await app.workbench.editors.waitForTab('Untitled-1', true);
125
126
await app.workbench.editors.selectTab('readme.md');
127
await app.workbench.editor.waitForEditorContents('readme.md', contents => contents.indexOf(textToType) > -1);
128
129
await app.workbench.editors.selectTab('Untitled-1');
130
await app.workbench.editor.waitForEditorContents('Untitled-1', contents => contents.indexOf(textToTypeInUntitled) > -1);
131
132
await app.stop();
133
app = undefined;
134
}
135
});
136
137
describe('Data Loss (stable -> insiders)', function () {
138
139
// Double the timeout since these tests involve 2 startups
140
this.timeout(4 * 60 * 1000);
141
142
let insidersApp: Application | undefined = undefined;
143
let stableApp: Application | undefined = undefined;
144
145
// Shared before/after handling
146
installDiagnosticsHandler(logger, () => insidersApp ?? stableApp);
147
installAppAfterHandler(() => insidersApp ?? stableApp, async () => stableApp?.stop());
148
149
it('verifies opened editors are restored', async function () {
150
const { stableCodePath, stableCodeVersion } = ensureStableCode();
151
if (!stableCodePath) {
152
this.skip();
153
}
154
155
// macOS: the first launch of stable Code will trigger
156
// additional checks in the OS (notarization validation)
157
// so it can take a very long time. as such we install
158
// a retry handler to make sure we do not fail as a
159
// consequence.
160
if (process.platform === 'darwin') {
161
this.retries(2);
162
}
163
164
const userDataDir = getRandomUserDataDir(this.defaultOptions.userDataDir);
165
const logsPath = suiteLogsPath(this.defaultOptions, 'test_verifies_opened_editors_are_restored_from_stable');
166
const crashesPath = suiteCrashPath(this.defaultOptions, 'test_verifies_opened_editors_are_restored_from_stable');
167
168
const stableOptions: ApplicationOptions = Object.assign({}, this.defaultOptions);
169
stableOptions.codePath = stableCodePath;
170
stableOptions.userDataDir = userDataDir;
171
stableOptions.quality = Quality.Stable;
172
stableOptions.logsPath = logsPath;
173
stableOptions.crashesPath = crashesPath;
174
stableOptions.version = stableCodeVersion ?? { major: 0, minor: 0, patch: 0 };
175
176
stableApp = new Application(stableOptions);
177
await stableApp.start();
178
179
// Open 3 editors
180
await stableApp.workbench.quickaccess.openFile(join(stableApp.workspacePathOrFolder, 'bin', 'www'));
181
await stableApp.workbench.quickaccess.runCommand('View: Keep Editor');
182
await stableApp.workbench.quickaccess.openFile(join(stableApp.workspacePathOrFolder, 'app.js'));
183
await stableApp.workbench.quickaccess.runCommand('View: Keep Editor');
184
await stableApp.workbench.editors.newUntitledFile();
185
186
await stableApp.stop();
187
stableApp = undefined;
188
189
const insiderOptions: ApplicationOptions = Object.assign({}, this.defaultOptions);
190
insiderOptions.userDataDir = userDataDir;
191
insiderOptions.logsPath = logsPath;
192
insiderOptions.crashesPath = crashesPath;
193
194
insidersApp = new Application(insiderOptions);
195
await insidersApp.start();
196
197
// Verify 3 editors are open
198
await insidersApp.workbench.editors.selectTab('Untitled-1');
199
await insidersApp.workbench.editors.selectTab('app.js');
200
await insidersApp.workbench.editors.selectTab('www');
201
202
await insidersApp.stop();
203
insidersApp = undefined;
204
});
205
206
it('verifies that "hot exit" works for dirty files (without delay)', async function () {
207
return testHotExit.call(this, `test_verifies_that_hot_exit_works_for_dirty_files_without_delay_from_stable`, undefined);
208
});
209
210
it('verifies that "hot exit" works for dirty files (with delay)', async function () {
211
return testHotExit.call(this, `test_verifies_that_hot_exit_works_for_dirty_files_with_delay_from_stable`, 2000);
212
});
213
214
async function testHotExit(this: import('mocha').Context, title: string, restartDelay: number | undefined) {
215
const { stableCodePath, stableCodeVersion } = ensureStableCode();
216
if (!stableCodePath) {
217
this.skip();
218
}
219
220
const userDataDir = getRandomUserDataDir(this.defaultOptions.userDataDir);
221
const logsPath = suiteLogsPath(this.defaultOptions, title);
222
const crashesPath = suiteCrashPath(this.defaultOptions, title);
223
224
const stableOptions: ApplicationOptions = Object.assign({}, this.defaultOptions);
225
stableOptions.codePath = stableCodePath;
226
stableOptions.userDataDir = userDataDir;
227
stableOptions.quality = Quality.Stable;
228
stableOptions.logsPath = logsPath;
229
stableOptions.crashesPath = crashesPath;
230
stableOptions.version = stableCodeVersion ?? { major: 0, minor: 0, patch: 0 };
231
232
stableApp = new Application(stableOptions);
233
await stableApp.start();
234
235
const textToTypeInUntitled = 'Hello from Untitled';
236
237
await stableApp.workbench.editors.newUntitledFile();
238
await stableApp.workbench.editor.waitForTypeInEditor('Untitled-1', textToTypeInUntitled);
239
await stableApp.workbench.editors.waitForTab('Untitled-1', true);
240
241
const textToType = 'Hello, Code';
242
await stableApp.workbench.quickaccess.openFile(join(stableApp.workspacePathOrFolder, 'readme.md'));
243
await stableApp.workbench.editor.waitForTypeInEditor('readme.md', textToType);
244
await stableApp.workbench.editors.waitForTab('readme.md', true);
245
246
if (typeof restartDelay === 'number') {
247
// this is an OK use of a timeout in a smoke test
248
// we want to simulate a user having typed into
249
// the editor and pausing for a moment before
250
// terminating
251
await timeout(restartDelay);
252
}
253
254
await stableApp.stop();
255
stableApp = undefined;
256
257
const insiderOptions: ApplicationOptions = Object.assign({}, this.defaultOptions);
258
insiderOptions.userDataDir = userDataDir;
259
insiderOptions.logsPath = logsPath;
260
insiderOptions.crashesPath = crashesPath;
261
262
insidersApp = new Application(insiderOptions);
263
await insidersApp.start();
264
265
await insidersApp.workbench.editors.waitForTab('readme.md', true);
266
await insidersApp.workbench.editors.waitForTab('Untitled-1', true);
267
268
await insidersApp.workbench.editors.selectTab('readme.md');
269
await insidersApp.workbench.editor.waitForEditorContents('readme.md', contents => contents.indexOf(textToType) > -1);
270
271
await insidersApp.workbench.editors.selectTab('Untitled-1');
272
await insidersApp.workbench.editor.waitForEditorContents('Untitled-1', contents => contents.indexOf(textToTypeInUntitled) > -1);
273
274
await insidersApp.stop();
275
insidersApp = undefined;
276
}
277
});
278
}
279
280