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