searchService.test.ts 8.8 KB
Newer Older
C
chrmarti 已提交
1 2 3 4 5 6 7
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

C
Christof Marti 已提交
8
import * as assert from 'assert';
9
import * as path from 'path';
C
chrmarti 已提交
10

J
Johannes Rieken 已提交
11
import { IProgress, IUncachedSearchStats } from 'vs/platform/search/common/search';
C
Christof Marti 已提交
12
import { ISearchEngine, IRawSearch, IRawFileMatch, ISerializedFileMatch, ISerializedSearchComplete, IFolderSearch } from 'vs/workbench/services/search/node/search';
J
Johannes Rieken 已提交
13 14
import { SearchService as RawSearchService } from 'vs/workbench/services/search/node/rawSearchService';
import { DiskSearch } from 'vs/workbench/services/search/node/searchService';
C
chrmarti 已提交
15

16
const TEST_FOLDER_QUERIES = [
17
	{ folder: path.normalize('/some/where') }
18
];
C
chrmarti 已提交
19

C
Christof Marti 已提交
20 21 22 23 24 25
const TEST_FIXTURES = path.normalize(require.toUrl('./fixtures'));
const MULTIROOT_QUERIES: IFolderSearch[] = [
	{ folder: path.join(TEST_FIXTURES, 'examples') },
	{ folder: path.join(TEST_FIXTURES, 'more') }
];

26 27 28
const stats: IUncachedSearchStats = {
	fromCache: false,
	resultCount: 4,
C
Christof Marti 已提交
29 30
	traversal: 'node',
	errors: [],
31 32 33 34 35
	fileWalkStartTime: 0,
	fileWalkResultTime: 1,
	directoriesWalked: 2,
	filesWalked: 3
};
C
chrmarti 已提交
36

37 38 39 40 41 42 43 44
class TestSearchEngine implements ISearchEngine<IRawFileMatch> {

	public static last: TestSearchEngine;

	private isCanceled = false;

	constructor(private result: () => IRawFileMatch, public config?: IRawSearch) {
		TestSearchEngine.last = this;
C
chrmarti 已提交
45 46
	}

47
	public search(onResult: (match: IRawFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void {
C
chrmarti 已提交
48 49 50
		const self = this;
		(function next() {
			process.nextTick(() => {
51 52 53 54 55 56 57
				if (self.isCanceled) {
					done(null, {
						limitHit: false,
						stats: stats
					});
					return;
				}
C
chrmarti 已提交
58 59
				const result = self.result();
				if (!result) {
C
chrmarti 已提交
60 61
					done(null, {
						limitHit: false,
62
						stats: stats
C
chrmarti 已提交
63
					});
C
chrmarti 已提交
64 65 66 67 68 69 70 71 72
				} else {
					onResult(result);
					next();
				}
			});
		})();
	}

	public cancel(): void {
73
		this.isCanceled = true;
C
chrmarti 已提交
74 75 76
	}
}

77 78
const testTimeout = 5000;

C
chrmarti 已提交
79 80
suite('SearchService', () => {

81
	const rawSearch: IRawSearch = {
82
		folderQueries: TEST_FOLDER_QUERIES,
83 84 85 86
		filePattern: 'a'
	};

	const rawMatch: IRawFileMatch = {
87
		base: path.normalize('/some'),
88
		relativePath: 'where',
89
		basename: 'where',
90 91 92 93
		size: 123
	};

	const match: ISerializedFileMatch = {
94
		path: path.normalize('/some/where')
95 96
	};

C
chrmarti 已提交
97
	test('Individual results', function () {
98
		this.timeout(testTimeout);
C
chrmarti 已提交
99
		let i = 5;
100
		const Engine = TestSearchEngine.bind(null, () => i-- && rawMatch);
C
chrmarti 已提交
101 102 103
		const service = new RawSearchService();

		let results = 0;
104
		return service.doFileSearch(Engine, rawSearch)
J
Johannes Rieken 已提交
105 106 107 108 109 110 111
			.then(() => {
				assert.strictEqual(results, 5);
			}, null, value => {
				if (!Array.isArray(value)) {
					assert.deepStrictEqual(value, match);
					results++;
				} else {
112
					assert.fail(JSON.stringify(value));
J
Johannes Rieken 已提交
113 114
				}
			});
C
chrmarti 已提交
115 116 117
	});

	test('Batch results', function () {
118
		this.timeout(testTimeout);
C
chrmarti 已提交
119
		let i = 25;
120
		const Engine = TestSearchEngine.bind(null, () => i-- && rawMatch);
C
chrmarti 已提交
121 122 123
		const service = new RawSearchService();

		const results = [];
124
		return service.doFileSearch(Engine, rawSearch, 10)
J
Johannes Rieken 已提交
125 126 127 128 129 130 131 132 133
			.then(() => {
				assert.deepStrictEqual(results, [10, 10, 5]);
			}, null, value => {
				if (Array.isArray(value)) {
					value.forEach(m => {
						assert.deepStrictEqual(m, match);
					});
					results.push(value.length);
				} else {
134
					assert.fail(JSON.stringify(value));
J
Johannes Rieken 已提交
135 136
				}
			});
C
chrmarti 已提交
137 138 139
	});

	test('Collect batched results', function () {
140
		this.timeout(testTimeout);
C
Christof Marti 已提交
141
		const uriPath = '/some/where';
C
chrmarti 已提交
142
		let i = 25;
143
		const Engine = TestSearchEngine.bind(null, () => i-- && rawMatch);
C
chrmarti 已提交
144 145 146
		const service = new RawSearchService();

		const progressResults = [];
147
		return DiskSearch.collectResults(service.doFileSearch(Engine, rawSearch, 10))
J
Johannes Rieken 已提交
148 149 150 151 152 153 154
			.then(result => {
				assert.strictEqual(result.results.length, 25, 'Result');
				assert.strictEqual(progressResults.length, 25, 'Progress');
			}, null, match => {
				assert.strictEqual(match.resource.path, uriPath);
				progressResults.push(match);
			});
C
chrmarti 已提交
155
	});
156

C
Christof Marti 已提交
157
	test('Multi-root with include pattern and maxResults', function () {
158
		this.timeout(testTimeout);
C
Christof Marti 已提交
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
		const service = new RawSearchService();

		const query: IRawSearch = {
			folderQueries: MULTIROOT_QUERIES,
			maxResults: 1,
			includePattern: {
				'*.txt': true,
				'*.js': true
			},
		};

		return DiskSearch.collectResults(service.fileSearch(query))
			.then(result => {
				assert.strictEqual(result.results.length, 1, 'Result');
			});
	});

	test('Multi-root with include pattern and exists', function () {
177
		this.timeout(testTimeout);
C
Christof Marti 已提交
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
		const service = new RawSearchService();

		const query: IRawSearch = {
			folderQueries: MULTIROOT_QUERIES,
			exists: true,
			includePattern: {
				'*.txt': true,
				'*.js': true
			},
		};

		return DiskSearch.collectResults(service.fileSearch(query))
			.then(result => {
				assert.strictEqual(result.results.length, 0, 'Result');
				assert.ok(result.limitHit);
			});
	});

196
	test('Sorted results', function () {
197
		this.timeout(testTimeout);
198
		const paths = ['bab', 'bbc', 'abb'];
199
		const matches: IRawFileMatch[] = paths.map(relativePath => ({
200
			base: path.normalize('/some/where'),
201
			relativePath,
202
			basename: relativePath,
203 204 205 206 207 208 209
			size: 3
		}));
		const Engine = TestSearchEngine.bind(null, () => matches.shift());
		const service = new RawSearchService();

		const results = [];
		return service.doFileSearch(Engine, {
210
			folderQueries: TEST_FOLDER_QUERIES,
211 212 213 214 215
			filePattern: 'bb',
			sortByScore: true,
			maxResults: 2
		}, 1).then(() => {
			assert.notStrictEqual(typeof TestSearchEngine.last.config.maxResults, 'number');
216
			assert.deepStrictEqual(results, [path.normalize('/some/where/bbc'), path.normalize('/some/where/bab')]);
217 218 219 220
		}, null, value => {
			if (Array.isArray(value)) {
				results.push(...value.map(v => v.path));
			} else {
221
				assert.fail(JSON.stringify(value));
222 223 224 225 226
			}
		});
	});

	test('Sorted result batches', function () {
227
		this.timeout(testTimeout);
228 229 230 231 232 233
		let i = 25;
		const Engine = TestSearchEngine.bind(null, () => i-- && rawMatch);
		const service = new RawSearchService();

		const results = [];
		return service.doFileSearch(Engine, {
234
			folderQueries: TEST_FOLDER_QUERIES,
235 236 237 238
			filePattern: 'a',
			sortByScore: true,
			maxResults: 23
		}, 10)
J
Johannes Rieken 已提交
239 240 241 242 243 244 245 246 247
			.then(() => {
				assert.deepStrictEqual(results, [10, 10, 3]);
			}, null, value => {
				if (Array.isArray(value)) {
					value.forEach(m => {
						assert.deepStrictEqual(m, match);
					});
					results.push(value.length);
				} else {
248
					assert.fail(JSON.stringify(value));
J
Johannes Rieken 已提交
249 250
				}
			});
251 252 253
	});

	test('Cached results', function () {
254
		this.timeout(testTimeout);
255
		const paths = ['bcb', 'bbc', 'aab'];
256
		const matches: IRawFileMatch[] = paths.map(relativePath => ({
257
			base: path.normalize('/some/where'),
258
			relativePath,
259
			basename: relativePath,
260 261 262 263 264 265 266
			size: 3
		}));
		const Engine = TestSearchEngine.bind(null, () => matches.shift());
		const service = new RawSearchService();

		const results = [];
		return service.doFileSearch(Engine, {
267
			folderQueries: TEST_FOLDER_QUERIES,
268 269 270 271 272
			filePattern: 'b',
			sortByScore: true,
			cacheKey: 'x'
		}, -1).then(complete => {
			assert.strictEqual(complete.stats.fromCache, false);
273
			assert.deepStrictEqual(results, [path.normalize('/some/where/bcb'), path.normalize('/some/where/bbc'), path.normalize('/some/where/aab')]);
274 275 276 277
		}, null, value => {
			if (Array.isArray(value)) {
				results.push(...value.map(v => v.path));
			} else {
278
				assert.fail(JSON.stringify(value));
279 280 281 282
			}
		}).then(() => {
			const results = [];
			return service.doFileSearch(Engine, {
283
				folderQueries: TEST_FOLDER_QUERIES,
284 285 286 287 288
				filePattern: 'bc',
				sortByScore: true,
				cacheKey: 'x'
			}, -1).then(complete => {
				assert.ok(complete.stats.fromCache);
289
				assert.deepStrictEqual(results, [path.normalize('/some/where/bcb'), path.normalize('/some/where/bbc')]);
290 291 292 293
			}, null, value => {
				if (Array.isArray(value)) {
					results.push(...value.map(v => v.path));
				} else {
294
					assert.fail(JSON.stringify(value));
295 296 297 298 299 300
				}
			});
		}).then(() => {
			return service.clearCache('x');
		}).then(() => {
			matches.push({
301
				base: path.normalize('/some/where'),
302
				relativePath: 'bc',
303
				basename: 'bc',
304 305 306 307
				size: 3
			});
			const results = [];
			return service.doFileSearch(Engine, {
308
				folderQueries: TEST_FOLDER_QUERIES,
309 310 311 312 313
				filePattern: 'bc',
				sortByScore: true,
				cacheKey: 'x'
			}, -1).then(complete => {
				assert.strictEqual(complete.stats.fromCache, false);
314
				assert.deepStrictEqual(results, [path.normalize('/some/where/bc')]);
315 316 317 318
			}, null, value => {
				if (Array.isArray(value)) {
					results.push(...value.map(v => v.path));
				} else {
319
					assert.fail(JSON.stringify(value));
320 321 322 323
				}
			});
		});
	});
C
chrmarti 已提交
324
});