Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(679)

Side by Side Diff: pkg/analysis_server/test/source/caching_put_package_map_provider_test.dart

Issue 2382033003: Revert "Remove unused option in server API" (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/analysis_server/test/mocks.dart ('k') | pkg/analysis_server/test/source/test_all.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library test.source.caching_pub_package_map_provider;
6
7 import 'dart:convert';
8 import 'dart:core';
9 import 'dart:io' as io;
10
11 import 'package:analysis_server/src/source/caching_pub_package_map_provider.dart ';
12 import 'package:analyzer/file_system/file_system.dart';
13 import 'package:analyzer/file_system/memory_file_system.dart';
14 import 'package:analyzer/source/package_map_provider.dart';
15 import 'package:analyzer/src/dart/sdk/sdk.dart';
16 import 'package:analyzer/src/generated/engine.dart';
17 import 'package:unittest/unittest.dart';
18
19 import '../utils.dart';
20
21 main() {
22 initializeTestEnvironment();
23
24 group('CachingPubPackageMapProvider', () {
25 MemoryResourceProvider resProvider;
26 _MockPubListRunner mockRunner;
27 bool writeFileException;
28
29 Map result1 = {
30 'packages': {'foo': '/tmp/proj1/packages/foo'},
31 'input_files': ['/tmp/proj1/pubspec.yaml']
32 };
33
34 Map result1error = {
35 'input_files': ['/tmp/proj1/pubspec.lock']
36 };
37
38 Map result2 = {
39 'packages': {'bar': '/tmp/proj2/packages/bar'},
40 'input_files': ['/tmp/proj2/pubspec.yaml']
41 };
42
43 Folder newProj(Map result) {
44 Map packages = result['packages'];
45 packages.forEach((String name, String path) {
46 resProvider.newFolder(path);
47 });
48 List<String> inputFiles = result['input_files'] as List<String>;
49 for (String path in inputFiles) {
50 resProvider.newFile(path, '');
51 }
52 Folder projectFolder = resProvider.getResource(inputFiles[0]).parent;
53 resProvider.newFile(projectFolder.path + '/pubspec.lock', '');
54 return projectFolder;
55 }
56
57 int mockWriteFile(File cacheFile, String content) {
58 if (writeFileException) {
59 throw 'simulated write failure: $cacheFile';
60 }
61 if (!cacheFile.exists) {
62 resProvider.newFolder(cacheFile.parent.path);
63 resProvider.newFile(cacheFile.path, content);
64 } else {
65 resProvider.modifyFile(cacheFile.path, content);
66 }
67 Resource res = resProvider.getResource(cacheFile.path);
68 if (res is File) {
69 return res.createSource().modificationStamp;
70 }
71 throw 'expected file, but found $res';
72 }
73
74 CachingPubPackageMapProvider newPkgProvider() {
75 return new CachingPubPackageMapProvider(
76 resProvider,
77 new FolderBasedDartSdk(
78 resProvider, FolderBasedDartSdk.defaultSdkDirectory(resProvider)),
79 mockRunner.runPubList,
80 mockWriteFile);
81 }
82
83 setUp(() {
84 resProvider = new MemoryResourceProvider();
85 resProvider.newFolder('/tmp/proj/packages/foo');
86 mockRunner = new _MockPubListRunner();
87 writeFileException = false;
88 });
89
90 group('computePackageMap', () {
91 // Assert pub list called once and results are cached in memory
92 test('cache memory', () {
93 expect(mockRunner.runCount, 0);
94
95 Folder folder1 = newProj(result1);
96 CachingPubPackageMapProvider pkgProvider = newPkgProvider();
97 mockRunner.nextResult = JSON.encode(result1);
98 PackageMapInfo info = pkgProvider.computePackageMap(folder1);
99 expect(mockRunner.runCount, 1);
100 _assertInfo(info, result1);
101
102 info = pkgProvider.computePackageMap(folder1);
103 expect(mockRunner.runCount, 1);
104 _assertInfo(info, result1);
105 });
106
107 // Assert pub list called once and results are cached on disk
108 test('cache disk', () {
109 expect(mockRunner.runCount, 0);
110
111 Folder folder1 = newProj(result1);
112 CachingPubPackageMapProvider pkgProvider1 = newPkgProvider();
113 mockRunner.nextResult = JSON.encode(result1);
114 PackageMapInfo info = pkgProvider1.computePackageMap(folder1);
115 expect(mockRunner.runCount, 1);
116 _assertInfo(info, result1);
117
118 CachingPubPackageMapProvider pkgProvider2 = newPkgProvider();
119 info = pkgProvider2.computePackageMap(folder1);
120 expect(mockRunner.runCount, 1);
121 _assertInfo(info, result1);
122 });
123
124 // Assert pub list called even if cache file is corrupted
125 test('corrupt cache file', () {
126 expect(mockRunner.runCount, 0);
127
128 Folder folder1 = newProj(result1);
129 CachingPubPackageMapProvider pkgProvider1 = newPkgProvider();
130 resProvider.newFile(pkgProvider1.cacheFile.path, 'corrupt content');
131 mockRunner.nextResult = JSON.encode(result1);
132 PackageMapInfo info = pkgProvider1.computePackageMap(folder1);
133 expect(mockRunner.runCount, 1);
134 _assertInfo(info, result1);
135
136 CachingPubPackageMapProvider pkgProvider2 = newPkgProvider();
137 info = pkgProvider2.computePackageMap(folder1);
138 expect(mockRunner.runCount, 1);
139 _assertInfo(info, result1);
140 });
141
142 // Assert gracefully continue even if write to file fails
143 test('failed write to cache file', () {
144 expect(mockRunner.runCount, 0);
145
146 Folder folder1 = newProj(result1);
147 CachingPubPackageMapProvider pkgProvider = newPkgProvider();
148 mockRunner.nextResult = JSON.encode(result1);
149 writeFileException = true;
150 PackageMapInfo info = pkgProvider.computePackageMap(folder1);
151 expect(mockRunner.runCount, 1);
152 _assertInfo(info, result1);
153
154 info = pkgProvider.computePackageMap(folder1);
155 expect(mockRunner.runCount, 1);
156 _assertInfo(info, result1);
157 });
158
159 // Assert modification in one shows up in the other
160 test('shared disk cache', () {
161 expect(mockRunner.runCount, 0);
162
163 Folder folder1 = newProj(result1);
164 CachingPubPackageMapProvider pkgProvider1 = newPkgProvider();
165 mockRunner.nextResult = JSON.encode(result1);
166 PackageMapInfo info = pkgProvider1.computePackageMap(folder1);
167 expect(mockRunner.runCount, 1);
168 _assertInfo(info, result1);
169
170 Folder folder2 = newProj(result2);
171 CachingPubPackageMapProvider pkgProvider2 = newPkgProvider();
172 mockRunner.nextResult = JSON.encode(result2);
173 info = pkgProvider2.computePackageMap(folder2);
174 expect(mockRunner.runCount, 2);
175 _assertInfo(info, result2);
176
177 info = pkgProvider1.computePackageMap(folder2);
178 expect(mockRunner.runCount, 2);
179 _assertInfo(info, result2);
180 });
181
182 // Assert pub list called again if input file modified
183 test('input file changed', () {
184 expect(mockRunner.runCount, 0);
185
186 Folder folder1 = newProj(result1);
187 CachingPubPackageMapProvider pkgProvider = newPkgProvider();
188 mockRunner.nextResult = JSON.encode(result1);
189 PackageMapInfo info = pkgProvider.computePackageMap(folder1);
190 expect(mockRunner.runCount, 1);
191 _assertInfo(info, result1);
192
193 resProvider.modifyFile(info.dependencies.first, 'new content');
194 mockRunner.nextResult = JSON.encode(result1);
195 info = pkgProvider.computePackageMap(folder1);
196 expect(mockRunner.runCount, 2);
197 _assertInfo(info, result1);
198 });
199
200 // Assert pub list called again if input file modified
201 // after reloading package provider cache from disk
202 test('input file changed 2', () {
203 expect(mockRunner.runCount, 0);
204
205 Folder folder1 = newProj(result1);
206 CachingPubPackageMapProvider pkgProvider1 = newPkgProvider();
207 mockRunner.nextResult = JSON.encode(result1);
208 PackageMapInfo info = pkgProvider1.computePackageMap(folder1);
209 expect(mockRunner.runCount, 1);
210 _assertInfo(info, result1);
211
212 resProvider.modifyFile(info.dependencies.first, 'new content');
213 mockRunner.nextResult = JSON.encode(result1);
214 CachingPubPackageMapProvider pkgProvider2 = newPkgProvider();
215 info = pkgProvider2.computePackageMap(folder1);
216 expect(mockRunner.runCount, 2);
217 _assertInfo(info, result1);
218 });
219
220 // Assert pub list called again if input file deleted
221 test('input file deleted', () {
222 expect(mockRunner.runCount, 0);
223
224 Folder folder1 = newProj(result1);
225 CachingPubPackageMapProvider pkgProvider = newPkgProvider();
226 mockRunner.nextResult = JSON.encode(result1);
227 PackageMapInfo info = pkgProvider.computePackageMap(folder1);
228 expect(mockRunner.runCount, 1);
229 _assertInfo(info, result1);
230
231 resProvider.deleteFile(info.dependencies.first);
232 mockRunner.nextResult = JSON.encode(result1);
233 info = pkgProvider.computePackageMap(folder1);
234 expect(mockRunner.runCount, 2);
235 _assertInfo(info, result1);
236 });
237
238 // Assert pub list not called if folder does not exist
239 // and returns same cached result if folder restored as before
240 test('project removed then restored', () {
241 expect(mockRunner.runCount, 0);
242
243 Folder folder1 = newProj(result1);
244 CachingPubPackageMapProvider pkgProvider = newPkgProvider();
245 mockRunner.nextResult = JSON.encode(result1);
246 PackageMapInfo info = pkgProvider.computePackageMap(folder1);
247 expect(mockRunner.runCount, 1);
248 _assertInfo(info, result1);
249
250 _RestorePoint restorePoint = new _RestorePoint(resProvider, folder1);
251 resProvider.deleteFolder(folder1.path);
252 info = pkgProvider.computePackageMap(folder1);
253 expect(mockRunner.runCount, 1);
254 _assertError(info, result1error);
255
256 restorePoint.restore();
257 info = pkgProvider.computePackageMap(folder1);
258 expect(mockRunner.runCount, 1);
259 _assertInfo(info, result1);
260 });
261
262 // Assert pub list *is* run again
263 // if dependency has changed during execution
264 test('dependency changed during execution', () {
265 expect(mockRunner.runCount, 0);
266
267 Folder folder1 = newProj(result1);
268 Resource pubspecFile = folder1.getChild('pubspec.yaml');
269 expect(pubspecFile.exists, isTrue);
270 CachingPubPackageMapProvider pkgProvider = newPkgProvider();
271 mockRunner.nextResultFunction = () {
272 resProvider.modifyFile(pubspecFile.path, 'new content');
273 return JSON.encode(result1);
274 };
275 mockRunner.nextResult = JSON.encode(result1);
276 PackageMapInfo info = pkgProvider.computePackageMap(folder1);
277 expect(mockRunner.runCount, 2);
278 _assertInfo(info, result1);
279 });
280 });
281 });
282 }
283
284 _assertError(PackageMapInfo info, Map expected) {
285 expect(info.packageMap, isNull);
286 List<String> expectedFiles = expected['input_files'] as List<String>;
287 expect(info.dependencies, hasLength(expectedFiles.length));
288 for (String path in expectedFiles) {
289 expect(info.dependencies, contains(path));
290 }
291 }
292
293 _assertInfo(PackageMapInfo info, Map expected) {
294 Map<String, String> expectedPackages =
295 expected['packages'] as Map<String, String>;
296 expect(info.packageMap, hasLength(expectedPackages.length));
297 for (String key in expectedPackages.keys) {
298 List<Folder> packageList = info.packageMap[key];
299 expect(packageList, hasLength(1));
300 expect(packageList[0].path, expectedPackages[key]);
301 }
302 List<String> expectedFiles = expected['input_files'] as List<String>;
303 expect(info.dependencies, hasLength(expectedFiles.length));
304 for (String path in expectedFiles) {
305 expect(info.dependencies, contains(path));
306 }
307 }
308
309 typedef String MockResultFunction();
310
311 /**
312 * Mock for simulating and tracking execution of pub list
313 */
314 class _MockPubListRunner {
315 int runCount = 0;
316 List nextResults = [];
317
318 void set nextResult(String result) {
319 nextResults.add(result);
320 }
321
322 void set nextResultFunction(MockResultFunction resultFunction) {
323 nextResults.add(resultFunction);
324 }
325
326 io.ProcessResult runPubList(Folder folder) {
327 if (nextResults.isEmpty) {
328 throw 'missing nextResult';
329 }
330 var result = nextResults.removeAt(0);
331 if (result is MockResultFunction) {
332 result = result();
333 }
334 ++runCount;
335 return new _MockResult(result);
336 }
337 }
338
339 class _MockResult implements io.ProcessResult {
340 String result;
341
342 _MockResult(this.result);
343
344 @override
345 int get exitCode => 0;
346
347 // TODO: implement stdout
348 @override
349 get stdout => result;
350
351 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
352 }
353
354 /**
355 * An object containing information to restore the state of a deleted
356 * folder and its content.
357 */
358 class _RestorePoint {
359 final MemoryResourceProvider provider;
360 final List<String> _folderPaths = <String>[];
361 final List<String> _filePaths = <String>[];
362 final List<TimestampedData> _fileContents = <TimestampedData>[];
363
364 /**
365 * Construct a new instance that captures the current state of the folder
366 * and all of its contained files and folders.
367 */
368 _RestorePoint(this.provider, Folder folder) {
369 record(folder);
370 }
371
372 /**
373 * Capture the current state of the folder
374 * and all of its contained files and folders.
375 */
376 void record(Folder folder) {
377 _folderPaths.add(folder.path);
378 for (Resource child in folder.getChildren()) {
379 if (child is Folder) {
380 record(child);
381 } else if (child is File) {
382 _filePaths.add(child.path);
383 _fileContents.add(child.createSource().contents);
384 } else {
385 throw 'unknown resource: $child';
386 }
387 }
388 }
389
390 /**
391 * Restore the original files and folders.
392 */
393 void restore() {
394 for (String path in _folderPaths) {
395 provider.newFolder(path);
396 }
397 int fileCount = _filePaths.length;
398 for (int fileIndex = 0; fileIndex < fileCount; ++fileIndex) {
399 String path = _filePaths[fileIndex];
400 TimestampedData content = _fileContents[fileIndex];
401 provider.newFile(path, content.data, content.modificationTime);
402 }
403 }
404 }
OLDNEW
« no previous file with comments | « pkg/analysis_server/test/mocks.dart ('k') | pkg/analysis_server/test/source/test_all.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698