backupMainService.test.ts 10.5 KB
Newer Older
1 2 3 4 5 6 7 8 9
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

import * as assert from 'assert';
import * as platform from 'vs/base/common/platform';
D
Daniel Imms 已提交
10
import fs = require('fs');
11 12 13 14 15 16
import os = require('os');
import path = require('path');
import extfs = require('vs/base/node/extfs');
import pfs = require('vs/base/node/pfs');
import Uri from 'vs/base/common/uri';
import { TestEnvironmentService } from 'vs/test/utils/servicesTestUtils';
D
Daniel Imms 已提交
17
import { BackupMainService } from 'vs/platform/backup/electron-main/backupMainService';
18
import { IBackupWorkspacesFormat } from 'vs/platform/backup/common/backup';
19

D
Daniel Imms 已提交
20
class TestBackupMainService extends BackupMainService {
21
	constructor(backupHome: string, backupWorkspacesPath: string) {
22
		super(TestEnvironmentService);
23 24

		this.backupHome = backupHome;
D
Daniel Imms 已提交
25
		this.workspacesJsonPath = backupWorkspacesPath;
26 27 28

		// Force a reload with the new paths
		this.loadSync();
29
	}
30 31 32 33 34 35 36 37 38 39

	public removeWorkspaceBackupPathSync(workspace: Uri): void {
		return super.removeWorkspaceBackupPathSync(workspace);
	}

	public loadSync(): void {
		super.loadSync();
	}

	public toBackupPath(workspacePath: string): string {
D
Daniel Imms 已提交
40
		return path.join(this.backupHome, super.getWorkspaceHash(workspacePath));
41
	}
42 43
}

D
Daniel Imms 已提交
44
suite('BackupMainService', () => {
D
Daniel Imms 已提交
45
	const parentDir = path.join(os.tmpdir(), 'vsctests', 'service');
46 47 48 49 50 51
	const backupHome = path.join(parentDir, 'Backups');
	const backupWorkspacesPath = path.join(backupHome, 'workspaces.json');

	const fooFile = Uri.file(platform.isWindows ? 'C:\\foo' : '/foo');
	const barFile = Uri.file(platform.isWindows ? 'C:\\bar' : '/bar');

52
	let service: TestBackupMainService;
53 54

	setup(done => {
D
Daniel Imms 已提交
55
		service = new TestBackupMainService(backupHome, backupWorkspacesPath);
56 57 58 59

		// Delete any existing backups completely and then re-create it.
		extfs.del(backupHome, os.tmpdir(), () => {
			pfs.mkdirp(backupHome).then(() => {
D
Daniel Imms 已提交
60
				done();
61 62 63 64 65 66 67 68
			});
		});
	});

	teardown(done => {
		extfs.del(backupHome, os.tmpdir(), done);
	});

69 70 71 72
	suite('loadSync', () => {
		test('workspaceBackupPaths should return [] when workspaces.json doesn\'t exist', () => {
			assert.deepEqual(service.workspaceBackupPaths, []);
		});
D
Daniel Imms 已提交
73

74 75 76 77 78 79 80 81 82 83 84
		test('workspaceBackupPaths should return [] when workspaces.json is not properly formed JSON', () => {
			fs.writeFileSync(backupWorkspacesPath, '');
			service.loadSync();
			assert.deepEqual(service.workspaceBackupPaths, []);
			fs.writeFileSync(backupWorkspacesPath, '{]');
			service.loadSync();
			assert.deepEqual(service.workspaceBackupPaths, []);
			fs.writeFileSync(backupWorkspacesPath, 'foo');
			service.loadSync();
			assert.deepEqual(service.workspaceBackupPaths, []);
		});
D
Daniel Imms 已提交
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
		test('workspaceBackupPaths should return [] when folderWorkspaces in workspaces.json is absent', () => {
			fs.writeFileSync(backupWorkspacesPath, '{}');
			service.loadSync();
			assert.deepEqual(service.workspaceBackupPaths, []);
		});

		test('workspaceBackupPaths should return [] when folderWorkspaces in workspaces.json is not a string array', () => {
			fs.writeFileSync(backupWorkspacesPath, '{"folderWorkspaces":{}}');
			service.loadSync();
			assert.deepEqual(service.workspaceBackupPaths, []);
			fs.writeFileSync(backupWorkspacesPath, '{"folderWorkspaces":{"foo": ["bar"]}}');
			service.loadSync();
			assert.deepEqual(service.workspaceBackupPaths, []);
			fs.writeFileSync(backupWorkspacesPath, '{"folderWorkspaces":{"foo": []}}');
			service.loadSync();
			assert.deepEqual(service.workspaceBackupPaths, []);
			fs.writeFileSync(backupWorkspacesPath, '{"folderWorkspaces":{"foo": "bar"}}');
			service.loadSync();
			assert.deepEqual(service.workspaceBackupPaths, []);
			fs.writeFileSync(backupWorkspacesPath, '{"folderWorkspaces":"foo"}');
			service.loadSync();
			assert.deepEqual(service.workspaceBackupPaths, []);
			fs.writeFileSync(backupWorkspacesPath, '{"folderWorkspaces":1}');
			service.loadSync();
			assert.deepEqual(service.workspaceBackupPaths, []);
		});
D
Daniel Imms 已提交
112

113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
		test('emptyWorkspaceBackupPaths should return [] when workspaces.json doesn\'t exist', () => {
			assert.deepEqual(service.emptyWorkspaceBackupPaths, []);
		});

		test('emptyWorkspaceBackupPaths should return [] when workspaces.json is not properly formed JSON', () => {
			fs.writeFileSync(backupWorkspacesPath, '');
			service.loadSync();
			assert.deepEqual(service.emptyWorkspaceBackupPaths, []);
			fs.writeFileSync(backupWorkspacesPath, '{]');
			service.loadSync();
			assert.deepEqual(service.emptyWorkspaceBackupPaths, []);
			fs.writeFileSync(backupWorkspacesPath, 'foo');
			service.loadSync();
			assert.deepEqual(service.emptyWorkspaceBackupPaths, []);
		});

		test('emptyWorkspaceBackupPaths should return [] when folderWorkspaces in workspaces.json is absent', () => {
			fs.writeFileSync(backupWorkspacesPath, '{}');
			service.loadSync();
			assert.deepEqual(service.emptyWorkspaceBackupPaths, []);
		});

		test('emptyWorkspaceBackupPaths should return [] when folderWorkspaces in workspaces.json is not a string array', () => {
			fs.writeFileSync(backupWorkspacesPath, '{"emptyWorkspaces":{}}');
			service.loadSync();
			assert.deepEqual(service.emptyWorkspaceBackupPaths, []);
			fs.writeFileSync(backupWorkspacesPath, '{"emptyWorkspaces":{"foo": ["bar"]}}');
			service.loadSync();
			assert.deepEqual(service.emptyWorkspaceBackupPaths, []);
			fs.writeFileSync(backupWorkspacesPath, '{"emptyWorkspaces":{"foo": []}}');
			service.loadSync();
			assert.deepEqual(service.emptyWorkspaceBackupPaths, []);
			fs.writeFileSync(backupWorkspacesPath, '{"emptyWorkspaces":{"foo": "bar"}}');
			service.loadSync();
			assert.deepEqual(service.emptyWorkspaceBackupPaths, []);
			fs.writeFileSync(backupWorkspacesPath, '{"emptyWorkspaces":"foo"}');
			service.loadSync();
			assert.deepEqual(service.emptyWorkspaceBackupPaths, []);
			fs.writeFileSync(backupWorkspacesPath, '{"emptyWorkspaces":1}');
			service.loadSync();
			assert.deepEqual(service.emptyWorkspaceBackupPaths, []);
		});
D
Daniel Imms 已提交
155 156
	});

157
	test('pushWorkspaceBackupPathsSync should persist paths to workspaces.json', () => {
D
Daniel Imms 已提交
158 159
		service.registerWindowForBackups(1, false, null, fooFile.fsPath);
		service.registerWindowForBackups(2, false, null, barFile.fsPath);
160
		assert.deepEqual(service.workspaceBackupPaths, [fooFile.fsPath, barFile.fsPath]);
161 162
	});

163
	test('removeWorkspaceBackupPath should remove workspaces from workspaces.json', done => {
D
Daniel Imms 已提交
164 165
		service.registerWindowForBackups(1, false, null, fooFile.fsPath);
		service.registerWindowForBackups(2, false, null, barFile.fsPath);
D
Daniel Imms 已提交
166
		service.removeWorkspaceBackupPathSync(fooFile);
167 168 169
		pfs.readFile(backupWorkspacesPath, 'utf-8').then(buffer => {
			const json = <IBackupWorkspacesFormat>JSON.parse(buffer);
			assert.deepEqual(json.folderWorkspaces, [barFile.fsPath]);
D
Daniel Imms 已提交
170
			service.removeWorkspaceBackupPathSync(barFile);
171 172 173 174
			pfs.readFile(backupWorkspacesPath, 'utf-8').then(content => {
				const json2 = <IBackupWorkspacesFormat>JSON.parse(content);
				assert.deepEqual(json2.folderWorkspaces, []);
				done();
175 176 177 178 179
			});
		});
	});

	test('removeWorkspaceBackupPath should fail gracefully when removing a path that doesn\'t exist', done => {
180
		const workspacesJson: IBackupWorkspacesFormat = { folderWorkspaces: [fooFile.fsPath], emptyWorkspaces: [] };
181
		pfs.writeFile(backupWorkspacesPath, JSON.stringify(workspacesJson)).then(() => {
D
Daniel Imms 已提交
182
			service.removeWorkspaceBackupPathSync(barFile);
183 184 185 186 187 188 189
			pfs.readFile(backupWorkspacesPath, 'utf-8').then(content => {
				const json = <IBackupWorkspacesFormat>JSON.parse(content);
				assert.deepEqual(json.folderWorkspaces, [fooFile.fsPath]);
				done();
			});
		});
	});
190

191 192 193
	test('service validates backup workspaces on startup and cleans up', done => {

		// 1) backup workspace path does not exist
D
Daniel Imms 已提交
194 195 196 197
		console.log('fooFile :' + fooFile.fsPath);
		console.log('barFile :' + barFile.fsPath);
		service.registerWindowForBackups(1, false, null, fooFile.fsPath);
		service.registerWindowForBackups(2, false, null, barFile.fsPath);
198
		service.loadSync();
D
Daniel Imms 已提交
199
		assert.deepEqual(service.workspaceBackupPaths, []);
200 201 202 203

		// 2) backup workspace path exists with empty contents within
		fs.mkdirSync(service.toBackupPath(fooFile.fsPath));
		fs.mkdirSync(service.toBackupPath(barFile.fsPath));
D
Daniel Imms 已提交
204 205
		service.registerWindowForBackups(1, false, null, fooFile.fsPath);
		service.registerWindowForBackups(2, false, null, barFile.fsPath);
206
		service.loadSync();
D
Daniel Imms 已提交
207
		assert.deepEqual(service.workspaceBackupPaths, []);
208 209 210 211 212 213 214 215
		assert.ok(!fs.exists(service.toBackupPath(fooFile.fsPath)));
		assert.ok(!fs.exists(service.toBackupPath(barFile.fsPath)));

		// 3) backup workspace path exists with empty folders within
		fs.mkdirSync(service.toBackupPath(fooFile.fsPath));
		fs.mkdirSync(service.toBackupPath(barFile.fsPath));
		fs.mkdirSync(path.join(service.toBackupPath(fooFile.fsPath), 'file'));
		fs.mkdirSync(path.join(service.toBackupPath(barFile.fsPath), 'untitled'));
D
Daniel Imms 已提交
216 217
		service.registerWindowForBackups(1, false, null, fooFile.fsPath);
		service.registerWindowForBackups(2, false, null, barFile.fsPath);
218
		service.loadSync();
D
Daniel Imms 已提交
219
		assert.deepEqual(service.workspaceBackupPaths, []);
220 221 222 223
		assert.ok(!fs.exists(service.toBackupPath(fooFile.fsPath)));
		assert.ok(!fs.exists(service.toBackupPath(barFile.fsPath)));

		done();
224
	});
D
Daniel Imms 已提交
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239

	test('toBackupPath ignores case on Windows and Mac', () => {
		// Skip test on Linux
		if (platform.isLinux) {
			return;
		}

		if (platform.isMacintosh) {
			assert.equal(service.toBackupPath('/foo'), service.toBackupPath('/FOO'));
		}

		if (platform.isWindows) {
			assert.equal(service.toBackupPath('c:\\foo'), service.toBackupPath('C:\\FOO'));
		}
	});
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266

	suite('getBackupPath', () => {
		test('should return the window\'s correct path', done => {
			service.registerWindowForBackups(1, false, null, fooFile.fsPath);
			service.registerWindowForBackups(2, true, 'test');
			service.getBackupPath(1).then(window1Path => {
				assert.equal(window1Path, service.toBackupPath(fooFile.fsPath));
				service.getBackupPath(2).then(window2Path => {
					assert.equal(window2Path, path.join(backupHome, 'test'));
					done();
				});
			});
		});

		test('should override stale window paths with new paths', done => {
			service.registerWindowForBackups(1, false, null, fooFile.fsPath);
			service.registerWindowForBackups(1, false, null, barFile.fsPath);
			service.getBackupPath(1).then(windowPath => {
				assert.equal(windowPath, service.toBackupPath(barFile.fsPath));
				done();
			});
		});

		test('should throw when the window is not registered', () => {
			assert.throws(() => service.getBackupPath(1));
		});
	});
267
});