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

Side by Side Diff: packages/analyzer/test/src/context/cache_test.dart

Issue 1400473008: Roll Observatory packages and add a roll script (Closed) Base URL: git@github.com:dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 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
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.src.task.driver_test;
6
7 import 'package:analyzer/src/context/cache.dart';
8 import 'package:analyzer/src/generated/engine.dart'
9 show
10 AnalysisContext,
11 CacheState,
12 InternalAnalysisContext,
13 RetentionPriority;
14 import 'package:analyzer/src/generated/java_engine.dart';
15 import 'package:analyzer/src/generated/sdk_io.dart';
16 import 'package:analyzer/src/generated/source.dart';
17 import 'package:analyzer/src/generated/utilities_collection.dart';
18 import 'package:analyzer/src/task/model.dart';
19 import 'package:analyzer/task/model.dart';
20 import 'package:typed_mock/typed_mock.dart';
21 import 'package:unittest/unittest.dart';
22
23 import '../../generated/test_support.dart';
24 import '../../reflective_tests.dart';
25 import '../../utils.dart';
26
27 main() {
28 initializeTestEnvironment();
29 runReflectiveTests(AnalysisCacheTest);
30 runReflectiveTests(CacheEntryTest);
31 runReflectiveTests(CacheFlushManagerTest);
32 runReflectiveTests(SdkCachePartitionTest);
33 runReflectiveTests(UniversalCachePartitionTest);
34 runReflectiveTests(ResultDataTest);
35 }
36
37 AnalysisCache createCache(
38 {AnalysisContext context,
39 RetentionPriority policy: RetentionPriority.LOW}) {
40 CachePartition partition = new UniversalCachePartition(context);
41 return new AnalysisCache(<CachePartition>[partition]);
42 }
43
44 class AbstractCacheTest {
45 InternalAnalysisContext context;
46 AnalysisCache cache;
47
48 void setUp() {
49 context = new _InternalAnalysisContextMock();
50 when(context.priorityTargets).thenReturn([]);
51 cache = createCache(context: context);
52 when(context.analysisCache).thenReturn(cache);
53 }
54 }
55
56 @reflectiveTest
57 class AnalysisCacheTest extends AbstractCacheTest {
58 void test_creation() {
59 expect(cache, isNotNull);
60 }
61
62 void test_get() {
63 AnalysisTarget target = new TestSource();
64 expect(cache.get(target), isNull);
65 }
66
67 void test_getContextFor() {
68 AnalysisTarget target = new TestSource();
69 expect(cache.getContextFor(target), context);
70 }
71
72 void test_getSourcesWithFullName() {
73 String filePath = '/foo/lib/file.dart';
74 // no sources
75 expect(cache.getSourcesWithFullName(filePath), isEmpty);
76 // add source1
77 TestSourceWithUri source1 =
78 new TestSourceWithUri(filePath, Uri.parse('file://$filePath'));
79 cache.put(new CacheEntry(source1));
80 expect(cache.getSourcesWithFullName(filePath), unorderedEquals([source1]));
81 // add source2
82 TestSourceWithUri source2 =
83 new TestSourceWithUri(filePath, Uri.parse('package:foo/file.dart'));
84 cache.put(new CacheEntry(source2));
85 expect(cache.getSourcesWithFullName(filePath),
86 unorderedEquals([source1, source2]));
87 // remove source1
88 cache.remove(source1);
89 expect(cache.getSourcesWithFullName(filePath), unorderedEquals([source2]));
90 // remove source2
91 cache.remove(source2);
92 expect(cache.getSourcesWithFullName(filePath), isEmpty);
93 // ignored
94 cache.remove(source1);
95 cache.remove(source2);
96 expect(cache.getSourcesWithFullName(filePath), isEmpty);
97 }
98
99 void test_getState_hasEntry_flushed() {
100 ResultDescriptor result = new ResultDescriptor('result', -1);
101 AnalysisTarget target = new TestSource();
102 CacheEntry entry = new CacheEntry(target);
103 cache.put(entry);
104 entry.setState(result, CacheState.FLUSHED);
105 expect(cache.getState(target, result), CacheState.FLUSHED);
106 }
107
108 void test_getState_hasEntry_valid() {
109 ResultDescriptor result = new ResultDescriptor('result', -1);
110 AnalysisTarget target = new TestSource();
111 CacheEntry entry = new CacheEntry(target);
112 cache.put(entry);
113 entry.setValue(result, '', []);
114 expect(cache.getState(target, result), CacheState.VALID);
115 }
116
117 void test_getState_noEntry() {
118 ResultDescriptor result = new ResultDescriptor('result', -1);
119 AnalysisTarget target = new TestSource();
120 expect(cache.getState(target, result), CacheState.INVALID);
121 }
122
123 void test_getValue_hasEntry_valid() {
124 ResultDescriptor result = new ResultDescriptor('result', -1);
125 AnalysisTarget target = new TestSource();
126 CacheEntry entry = new CacheEntry(target);
127 cache.put(entry);
128 entry.setValue(result, 111, []);
129 expect(cache.getValue(target, result), 111);
130 }
131
132 void test_getValue_noEntry() {
133 ResultDescriptor result = new ResultDescriptor('result', -1);
134 AnalysisTarget target = new TestSource();
135 expect(cache.getValue(target, result), -1);
136 }
137
138 void test_iterator() {
139 AnalysisTarget target = new TestSource();
140 CacheEntry entry = new CacheEntry(target);
141 cache.put(entry);
142 MapIterator<AnalysisTarget, CacheEntry> iterator = cache.iterator();
143 expect(iterator.moveNext(), isTrue);
144 expect(iterator.key, same(target));
145 expect(iterator.value, same(entry));
146 expect(iterator.moveNext(), isFalse);
147 }
148
149 void test_put() {
150 AnalysisTarget target = new TestSource();
151 CacheEntry entry = new CacheEntry(target);
152 expect(cache.get(target), isNull);
153 cache.put(entry);
154 expect(cache.get(target), entry);
155 }
156
157 void test_remove() {
158 AnalysisTarget target1 = new TestSource('/a.dart');
159 AnalysisTarget target2 = new TestSource('/b.dart');
160 AnalysisTarget target3 = new TestSource('/c.dart');
161 CacheEntry entry1 = new CacheEntry(target1);
162 CacheEntry entry2 = new CacheEntry(target2);
163 CacheEntry entry3 = new CacheEntry(target3);
164 cache.put(entry1);
165 cache.put(entry2);
166 cache.put(entry3);
167 ResultDescriptor result1 = new ResultDescriptor('result1', -1);
168 ResultDescriptor result2 = new ResultDescriptor('result2', -2);
169 ResultDescriptor result3 = new ResultDescriptor('result3', -3);
170 // set results, all of them are VALID
171 entry1.setValue(result1, 111, TargetedResult.EMPTY_LIST);
172 entry2.setValue(result2, 222, [new TargetedResult(target1, result1)]);
173 entry3.setValue(result3, 333, []);
174 expect(entry1.getState(result1), CacheState.VALID);
175 expect(entry2.getState(result2), CacheState.VALID);
176 expect(entry3.getState(result3), CacheState.VALID);
177 expect(entry1.getValue(result1), 111);
178 expect(entry2.getValue(result2), 222);
179 expect(entry3.getValue(result3), 333);
180 // remove entry1, invalidate result2 and remove empty entry2
181 expect(cache.remove(target1), entry1);
182 expect(cache.get(target1), isNull);
183 expect(cache.get(target2), isNull);
184 expect(cache.get(target3), entry3);
185 expect(entry3.getState(result3), CacheState.VALID);
186 }
187
188 void test_remove_invalidateResults_sameTarget() {
189 AnalysisTarget target = new TestSource('/a.dart');
190 CacheEntry entry = new CacheEntry(target);
191 cache.put(entry);
192 ResultDescriptor result1 = new ResultDescriptor('result1', -1);
193 ResultDescriptor result2 = new ResultDescriptor('result2', -2);
194 // set results, all of them are VALID
195 entry.setValue(result1, 111, TargetedResult.EMPTY_LIST);
196 entry.setValue(result2, 222, [new TargetedResult(target, result1)]);
197 expect(entry.getState(result1), CacheState.VALID);
198 expect(entry.getState(result2), CacheState.VALID);
199 expect(entry.getValue(result1), 111);
200 expect(entry.getValue(result2), 222);
201 // remove target, invalidate result2
202 expect(cache.remove(target), entry);
203 expect(cache.get(target), isNull);
204 expect(entry.getState(result2), CacheState.INVALID);
205 }
206
207 void test_size() {
208 int size = 4;
209 for (int i = 0; i < size; i++) {
210 AnalysisTarget target = new TestSource("/test$i.dart");
211 cache.put(new CacheEntry(target));
212 }
213 expect(cache.size(), size);
214 }
215
216 void test_sources() {
217 AnalysisTarget source1 = new TestSource('1.dart');
218 AnalysisTarget source2 = new TestSource('2.dart');
219 AnalysisTarget target1 = new _TestAnalysisTarget();
220 // no entries
221 expect(cache.sources, isEmpty);
222 // add source1
223 cache.put(new CacheEntry(source1));
224 expect(cache.sources, unorderedEquals([source1]));
225 // add target1
226 cache.put(new CacheEntry(target1));
227 expect(cache.sources, unorderedEquals([source1]));
228 // add source2
229 cache.put(new CacheEntry(source2));
230 expect(cache.sources, unorderedEquals([source1, source2]));
231 // remove source1
232 cache.remove(source1);
233 expect(cache.sources, unorderedEquals([source2]));
234 // remove source2
235 cache.remove(source2);
236 expect(cache.sources, isEmpty);
237 }
238 }
239
240 @reflectiveTest
241 class CacheEntryTest extends AbstractCacheTest {
242 test_dispose() {
243 ResultDescriptor descriptor1 = new ResultDescriptor('result1', -1);
244 ResultDescriptor descriptor2 = new ResultDescriptor('result2', -2);
245 AnalysisTarget target1 = new TestSource('1.dart');
246 AnalysisTarget target2 = new TestSource('2.dart');
247 TargetedResult result1 = new TargetedResult(target1, descriptor1);
248 TargetedResult result2 = new TargetedResult(target2, descriptor2);
249 CacheEntry entry1 = new CacheEntry(target1);
250 CacheEntry entry2 = new CacheEntry(target2);
251 cache.put(entry1);
252 cache.put(entry2);
253 entry1.setValue(descriptor1, 1, TargetedResult.EMPTY_LIST);
254 entry2.setValue(descriptor2, 2, <TargetedResult>[result1]);
255 // target2 is listed as dependent in target1
256 expect(
257 entry1.getResultData(descriptor1).dependentResults, contains(result2));
258 // dispose entry2, result2 is removed from result1
259 entry2.dispose();
260 expect(entry1.getResultData(descriptor1).dependentResults, isEmpty);
261 }
262
263 test_explicitlyAdded() {
264 AnalysisTarget target = new TestSource();
265 CacheEntry entry = new CacheEntry(target);
266 expect(entry.explicitlyAdded, false);
267 entry.explicitlyAdded = true;
268 expect(entry.explicitlyAdded, true);
269 }
270
271 test_fixExceptionState_error_exception() {
272 AnalysisTarget target = new TestSource();
273 ResultDescriptor result = new ResultDescriptor('test', null);
274 CaughtException exception = new CaughtException(null, null);
275 CacheEntry entry = new CacheEntry(target);
276 entry.setErrorState(exception, <ResultDescriptor>[result]);
277 entry.fixExceptionState();
278 expect(entry.getState(result), CacheState.ERROR);
279 expect(entry.exception, exception);
280 }
281
282 test_fixExceptionState_noError_exception() {
283 AnalysisTarget target = new TestSource();
284 ResultDescriptor result = new ResultDescriptor('test', null);
285 CacheEntry entry = new CacheEntry(target);
286 cache.put(entry);
287 // set one result to ERROR
288 CaughtException exception = new CaughtException(null, null);
289 entry.setErrorState(exception, <ResultDescriptor>[result]);
290 // set the same result to VALID
291 entry.setValue(result, 1, TargetedResult.EMPTY_LIST);
292 // fix the exception state
293 entry.fixExceptionState();
294 expect(entry.exception, isNull);
295 }
296
297 test_fixExceptionState_noError_noException() {
298 AnalysisTarget target = new TestSource();
299 ResultDescriptor result = new ResultDescriptor('test', null);
300 CacheEntry entry = new CacheEntry(target);
301 entry.fixExceptionState();
302 expect(entry.getState(result), CacheState.INVALID);
303 expect(entry.exception, isNull);
304 }
305
306 test_getState() {
307 AnalysisTarget target = new TestSource();
308 ResultDescriptor result = new ResultDescriptor('test', null);
309 CacheEntry entry = new CacheEntry(target);
310 expect(entry.getState(result), CacheState.INVALID);
311 }
312
313 test_getValue_default() {
314 AnalysisTarget target = new TestSource();
315 String defaultValue = 'value';
316 ResultDescriptor result = new ResultDescriptor('test', defaultValue);
317 CacheEntry entry = new CacheEntry(target);
318 expect(entry.getValue(result), defaultValue);
319 }
320
321 test_getValue_flushResults() {
322 ResultCachingPolicy cachingPolicy = new SimpleResultCachingPolicy(2, 2);
323 ResultDescriptor descriptor1 =
324 new ResultDescriptor('result1', null, cachingPolicy: cachingPolicy);
325 ResultDescriptor descriptor2 =
326 new ResultDescriptor('result2', null, cachingPolicy: cachingPolicy);
327 ResultDescriptor descriptor3 =
328 new ResultDescriptor('result3', null, cachingPolicy: cachingPolicy);
329 AnalysisTarget target = new TestSource();
330 CacheEntry entry = new CacheEntry(target);
331 cache.put(entry);
332 {
333 entry.setValue(descriptor1, 1, TargetedResult.EMPTY_LIST);
334 expect(entry.getState(descriptor1), CacheState.VALID);
335 }
336 {
337 entry.setValue(descriptor2, 2, TargetedResult.EMPTY_LIST);
338 expect(entry.getState(descriptor1), CacheState.VALID);
339 expect(entry.getState(descriptor2), CacheState.VALID);
340 }
341 // get descriptor1, so that descriptor2 will be flushed
342 entry.getValue(descriptor1);
343 {
344 entry.setValue(descriptor3, 3, TargetedResult.EMPTY_LIST);
345 expect(entry.getState(descriptor1), CacheState.VALID);
346 expect(entry.getState(descriptor2), CacheState.FLUSHED);
347 expect(entry.getState(descriptor3), CacheState.VALID);
348 }
349 }
350
351 test_hasErrorState_false() {
352 AnalysisTarget target = new TestSource();
353 CacheEntry entry = new CacheEntry(target);
354 expect(entry.hasErrorState(), false);
355 }
356
357 test_hasErrorState_true() {
358 AnalysisTarget target = new TestSource();
359 ResultDescriptor result = new ResultDescriptor('test', null);
360 CaughtException exception = new CaughtException(null, null);
361 CacheEntry entry = new CacheEntry(target);
362 entry.setErrorState(exception, <ResultDescriptor>[result]);
363 expect(entry.hasErrorState(), true);
364 }
365
366 test_invalidateAllInformation() {
367 AnalysisTarget target = new TestSource();
368 ResultDescriptor result = new ResultDescriptor('test', null);
369 CacheEntry entry = new CacheEntry(target);
370 entry.setValue(result, 'value', TargetedResult.EMPTY_LIST);
371 entry.invalidateAllInformation();
372 expect(entry.getState(result), CacheState.INVALID);
373 expect(entry.getValue(result), isNull);
374 }
375
376 test_setErrorState() {
377 AnalysisTarget target = new TestSource();
378 ResultDescriptor result1 = new ResultDescriptor('res1', 1);
379 ResultDescriptor result2 = new ResultDescriptor('res2', 2);
380 ResultDescriptor result3 = new ResultDescriptor('res3', 3);
381 // prepare some good state
382 CacheEntry entry = new CacheEntry(target);
383 entry.setValue(result1, 10, TargetedResult.EMPTY_LIST);
384 entry.setValue(result2, 20, TargetedResult.EMPTY_LIST);
385 entry.setValue(result3, 30, TargetedResult.EMPTY_LIST);
386 // set error state
387 CaughtException exception = new CaughtException(null, null);
388 entry.setErrorState(exception, <ResultDescriptor>[result1, result2]);
389 // verify
390 expect(entry.exception, exception);
391 expect(entry.getState(result1), CacheState.ERROR);
392 expect(entry.getState(result2), CacheState.ERROR);
393 expect(entry.getState(result3), CacheState.VALID);
394 expect(entry.getValue(result1), 1);
395 expect(entry.getValue(result2), 2);
396 expect(entry.getValue(result3), 30);
397 }
398
399 test_setErrorState_invalidateDependent() {
400 AnalysisTarget target1 = new TestSource('/a.dart');
401 AnalysisTarget target2 = new TestSource('/b.dart');
402 CacheEntry entry1 = new CacheEntry(target1);
403 CacheEntry entry2 = new CacheEntry(target2);
404 cache.put(entry1);
405 cache.put(entry2);
406 ResultDescriptor result1 = new ResultDescriptor('result1', -1);
407 ResultDescriptor result2 = new ResultDescriptor('result2', -2);
408 ResultDescriptor result3 = new ResultDescriptor('result3', -3);
409 ResultDescriptor result4 = new ResultDescriptor('result4', -4);
410 // set results, all of them are VALID
411 entry1.setValue(result1, 111, TargetedResult.EMPTY_LIST);
412 entry2.setValue(result2, 222, [new TargetedResult(target1, result1)]);
413 entry2.setValue(result3, 333, [new TargetedResult(target2, result2)]);
414 entry2.setValue(result4, 444, []);
415 expect(entry1.getState(result1), CacheState.VALID);
416 expect(entry2.getState(result2), CacheState.VALID);
417 expect(entry2.getState(result3), CacheState.VALID);
418 expect(entry2.getState(result4), CacheState.VALID);
419 expect(entry1.getValue(result1), 111);
420 expect(entry2.getValue(result2), 222);
421 expect(entry2.getValue(result3), 333);
422 expect(entry2.getValue(result4), 444);
423 // set error state
424 CaughtException exception = new CaughtException(null, null);
425 entry1.setErrorState(exception, <ResultDescriptor>[result1]);
426 // result2 and result3 are invalidated, result4 is intact
427 expect(entry1.getState(result1), CacheState.ERROR);
428 expect(entry2.getState(result2), CacheState.ERROR);
429 expect(entry2.getState(result3), CacheState.ERROR);
430 expect(entry2.getState(result4), CacheState.VALID);
431 expect(entry1.getValue(result1), -1);
432 expect(entry2.getValue(result2), -2);
433 expect(entry2.getValue(result3), -3);
434 expect(entry2.getValue(result4), 444);
435 expect(entry1.exception, exception);
436 expect(entry2.exception, exception);
437 }
438
439 test_setErrorState_noDescriptors() {
440 AnalysisTarget target = new TestSource();
441 CaughtException exception = new CaughtException(null, null);
442 CacheEntry entry = new CacheEntry(target);
443 expect(() {
444 entry.setErrorState(exception, <ResultDescriptor>[]);
445 }, throwsArgumentError);
446 }
447
448 test_setErrorState_noException() {
449 AnalysisTarget target = new TestSource();
450 ResultDescriptor result = new ResultDescriptor('test', null);
451 CacheEntry entry = new CacheEntry(target);
452 expect(() {
453 entry.setErrorState(null, <ResultDescriptor>[result]);
454 }, throwsArgumentError);
455 }
456
457 test_setErrorState_nullDescriptors() {
458 AnalysisTarget target = new TestSource();
459 CaughtException exception = new CaughtException(null, null);
460 CacheEntry entry = new CacheEntry(target);
461 expect(() {
462 entry.setErrorState(exception, null);
463 }, throwsArgumentError);
464 }
465
466 test_setState_error() {
467 AnalysisTarget target = new TestSource();
468 ResultDescriptor result = new ResultDescriptor('test', null);
469 CacheEntry entry = new CacheEntry(target);
470 entry.setValue(result, 42, TargetedResult.EMPTY_LIST);
471 // an invalid state change
472 expect(() {
473 entry.setState(result, CacheState.ERROR);
474 }, throwsArgumentError);
475 // no changes
476 expect(entry.getState(result), CacheState.VALID);
477 expect(entry.getValue(result), 42);
478 }
479
480 test_setState_flushed() {
481 AnalysisTarget target = new TestSource();
482 ResultDescriptor result = new ResultDescriptor('test', 1);
483 CacheEntry entry = new CacheEntry(target);
484 // set VALID
485 entry.setValue(result, 10, TargetedResult.EMPTY_LIST);
486 expect(entry.getState(result), CacheState.VALID);
487 expect(entry.getValue(result), 10);
488 // set FLUSHED
489 entry.setState(result, CacheState.FLUSHED);
490 expect(entry.getState(result), CacheState.FLUSHED);
491 expect(entry.getValue(result), 1);
492 }
493
494 test_setState_inProcess() {
495 AnalysisTarget target = new TestSource();
496 ResultDescriptor result = new ResultDescriptor('test', 1);
497 CacheEntry entry = new CacheEntry(target);
498 // set VALID
499 entry.setValue(result, 10, TargetedResult.EMPTY_LIST);
500 expect(entry.getState(result), CacheState.VALID);
501 expect(entry.getValue(result), 10);
502 // set IN_PROCESS
503 entry.setState(result, CacheState.IN_PROCESS);
504 expect(entry.getState(result), CacheState.IN_PROCESS);
505 expect(entry.getValue(result), 10);
506 }
507
508 test_setState_invalid() {
509 AnalysisTarget target = new TestSource();
510 ResultDescriptor result = new ResultDescriptor('test', 1);
511 CacheEntry entry = new CacheEntry(target);
512 cache.put(entry);
513 // set VALID
514 entry.setValue(result, 10, TargetedResult.EMPTY_LIST);
515 expect(entry.getState(result), CacheState.VALID);
516 expect(entry.getValue(result), 10);
517 // listen, expect "result" invalidation event
518 int numberOfEvents = 0;
519 cache.onResultInvalidated.listen((event) {
520 numberOfEvents++;
521 expect(event.entry, same(entry));
522 expect(event.descriptor, same(result));
523 });
524 // set INVALID
525 entry.setState(result, CacheState.INVALID);
526 expect(entry.getState(result), CacheState.INVALID);
527 expect(entry.getValue(result), 1);
528 expect(numberOfEvents, 1);
529 }
530
531 test_setState_invalid_dependencyCycle() {
532 AnalysisTarget target1 = new TestSource('/a.dart');
533 AnalysisTarget target2 = new TestSource('/b.dart');
534 CacheEntry entry1 = new CacheEntry(target1);
535 CacheEntry entry2 = new CacheEntry(target2);
536 cache.put(entry1);
537 cache.put(entry2);
538 ResultDescriptor result = new ResultDescriptor('result', -1);
539 // Set each result as VALID with a dependency on on the other.
540 entry1.setValue(result, 100, [new TargetedResult(target2, result)]);
541 entry2.setValue(result, 200, [new TargetedResult(target1, result)]);
542 expect(entry1.getState(result), CacheState.VALID);
543 expect(entry2.getState(result), CacheState.VALID);
544 // Listen, expect entry1.result and entry2.result invalidation events.
545 int numberOfEvents = 0;
546 bool wasEntry1 = false;
547 bool wasEntry2 = false;
548 cache.onResultInvalidated.listen((event) {
549 numberOfEvents++;
550 if (event.entry == entry1) wasEntry1 = true;
551 if (event.entry == entry2) wasEntry2 = true;
552 expect(event.descriptor, same(result));
553 });
554 // Invalidate entry1.result; this should cause entry2 to be also
555 // cleared without going into an infinite regress.
556 entry1.setState(result, CacheState.INVALID);
557 expect(cache.get(target1), isNull);
558 expect(cache.get(target2), isNull);
559 expect(numberOfEvents, 2);
560 expect(wasEntry1, isTrue);
561 expect(wasEntry2, isTrue);
562 }
563
564 test_setState_invalid_invalidateDependent() {
565 AnalysisTarget target = new TestSource();
566 CacheEntry entry = new CacheEntry(target);
567 cache.put(entry);
568 ResultDescriptor result1 = new ResultDescriptor('result1', -1);
569 ResultDescriptor result2 = new ResultDescriptor('result2', -2);
570 ResultDescriptor result3 = new ResultDescriptor('result3', -3);
571 ResultDescriptor result4 = new ResultDescriptor('result4', -4);
572 // set results, all of them are VALID
573 entry.setValue(result1, 111, TargetedResult.EMPTY_LIST);
574 entry.setValue(result2, 222, [new TargetedResult(target, result1)]);
575 entry.setValue(result3, 333, [new TargetedResult(target, result2)]);
576 entry.setValue(result4, 444, []);
577 expect(entry.getState(result1), CacheState.VALID);
578 expect(entry.getState(result2), CacheState.VALID);
579 expect(entry.getState(result3), CacheState.VALID);
580 expect(entry.getState(result4), CacheState.VALID);
581 expect(entry.getValue(result1), 111);
582 expect(entry.getValue(result2), 222);
583 expect(entry.getValue(result3), 333);
584 expect(entry.getValue(result4), 444);
585 // invalidate result1, invalidates result2 and result3, result4 is intact
586 entry.setState(result1, CacheState.INVALID);
587 expect(entry.getState(result1), CacheState.INVALID);
588 expect(entry.getState(result2), CacheState.INVALID);
589 expect(entry.getState(result3), CacheState.INVALID);
590 expect(entry.getState(result4), CacheState.VALID);
591 expect(entry.getValue(result1), -1);
592 expect(entry.getValue(result2), -2);
593 expect(entry.getValue(result3), -3);
594 expect(entry.getValue(result4), 444);
595 // result4 is still valid, so the entry is still in the cache
596 expect(cache.get(target), entry);
597 }
598
599 test_setState_invalid_removeEmptyEntry() {
600 AnalysisTarget target1 = new TestSource('/a.dart');
601 AnalysisTarget target2 = new TestSource('/b.dart');
602 CacheEntry entry1 = new CacheEntry(target1);
603 CacheEntry entry2 = new CacheEntry(target2);
604 cache.put(entry1);
605 cache.put(entry2);
606 ResultDescriptor result1 = new ResultDescriptor('result1', -1);
607 ResultDescriptor result2 = new ResultDescriptor('result2', -2);
608 ResultDescriptor result3 = new ResultDescriptor('result3', -3);
609 // set results, all of them are VALID
610 entry1.setValue(result1, 111, TargetedResult.EMPTY_LIST);
611 entry2.setValue(result2, 222, [new TargetedResult(target1, result1)]);
612 entry2.setValue(result3, 333, [new TargetedResult(target2, result2)]);
613 expect(entry1.getState(result1), CacheState.VALID);
614 expect(entry2.getState(result2), CacheState.VALID);
615 expect(entry2.getState(result3), CacheState.VALID);
616 expect(entry1.getValue(result1), 111);
617 expect(entry2.getValue(result2), 222);
618 expect(entry2.getValue(result3), 333);
619 // invalidate result1, remove entry1 & entry2
620 entry1.setState(result1, CacheState.INVALID);
621 expect(cache.get(target1), isNull);
622 expect(cache.get(target2), isNull);
623 }
624
625 test_setState_invalid_withDelta_keepDependency() {
626 Source target = new TestSource('/test.dart');
627 CacheEntry entry = new CacheEntry(target);
628 cache.put(entry);
629 ResultDescriptor result1 = new ResultDescriptor('result1', -1);
630 ResultDescriptor result2 = new ResultDescriptor('result2', -2);
631 ResultDescriptor result3 = new ResultDescriptor('result3', -3);
632 // set results, all of them are VALID
633 entry.setValue(result1, 111, TargetedResult.EMPTY_LIST);
634 entry.setValue(result2, 222, [new TargetedResult(target, result1)]);
635 entry.setValue(result3, 333, [new TargetedResult(target, result2)]);
636 expect(entry.getState(result1), CacheState.VALID);
637 expect(entry.getState(result2), CacheState.VALID);
638 expect(entry.getState(result3), CacheState.VALID);
639 // result2 depends on result1
640 expect(entry.getResultData(result1).dependentResults,
641 unorderedEquals([new TargetedResult(target, result2)]));
642 expect(entry.getResultData(result2).dependedOnResults,
643 unorderedEquals([new TargetedResult(target, result1)]));
644 // invalidate result2 with Delta: keep result2, invalidate result3
645 entry.setState(result2, CacheState.INVALID,
646 delta: new _KeepContinueDelta(target, result2));
647 expect(entry.getState(result1), CacheState.VALID);
648 expect(entry.getState(result2), CacheState.VALID);
649 expect(entry.getState(result3), CacheState.INVALID);
650 // result2 still depends on result1
651 expect(entry.getResultData(result1).dependentResults,
652 unorderedEquals([new TargetedResult(target, result2)]));
653 expect(entry.getResultData(result2).dependedOnResults,
654 unorderedEquals([new TargetedResult(target, result1)]));
655 }
656
657 test_setState_valid() {
658 AnalysisTarget target = new TestSource();
659 ResultDescriptor result = new ResultDescriptor('test', null);
660 CacheEntry entry = new CacheEntry(target);
661 expect(() => entry.setState(result, CacheState.VALID), throwsArgumentError);
662 }
663
664 test_setValue() {
665 AnalysisTarget target = new TestSource();
666 ResultDescriptor result = new ResultDescriptor('test', null);
667 String value = 'value';
668 CacheEntry entry = new CacheEntry(target);
669 entry.setValue(result, value, TargetedResult.EMPTY_LIST);
670 expect(entry.getState(result), CacheState.VALID);
671 expect(entry.getValue(result), value);
672 }
673
674 test_setValue_flushResults() {
675 ResultCachingPolicy cachingPolicy = new SimpleResultCachingPolicy(2, 2);
676 ResultDescriptor descriptor1 =
677 new ResultDescriptor('result1', null, cachingPolicy: cachingPolicy);
678 ResultDescriptor descriptor2 =
679 new ResultDescriptor('result2', null, cachingPolicy: cachingPolicy);
680 ResultDescriptor descriptor3 =
681 new ResultDescriptor('result3', null, cachingPolicy: cachingPolicy);
682 AnalysisTarget target = new TestSource();
683 CacheEntry entry = new CacheEntry(target);
684 cache.put(entry);
685 {
686 entry.setValue(descriptor1, 1, TargetedResult.EMPTY_LIST);
687 expect(entry.getState(descriptor1), CacheState.VALID);
688 }
689 {
690 entry.setValue(descriptor2, 2, TargetedResult.EMPTY_LIST);
691 expect(entry.getState(descriptor1), CacheState.VALID);
692 expect(entry.getState(descriptor2), CacheState.VALID);
693 }
694 {
695 entry.setValue(descriptor3, 3, TargetedResult.EMPTY_LIST);
696 expect(entry.getState(descriptor1), CacheState.FLUSHED);
697 expect(entry.getState(descriptor2), CacheState.VALID);
698 expect(entry.getState(descriptor3), CacheState.VALID);
699 }
700 }
701
702 test_setValue_keepDependent() {
703 AnalysisTarget target = new TestSource();
704 CacheEntry entry = new CacheEntry(target);
705 cache.put(entry);
706 ResultDescriptor result1 = new ResultDescriptor('result1', -1);
707 ResultDescriptor result2 = new ResultDescriptor('result2', -2);
708 // set results, all of them are VALID
709 entry.setValue(result1, 111, TargetedResult.EMPTY_LIST);
710 entry.setValue(result2, 222, [new TargetedResult(target, result1)]);
711 expect(entry.getState(result1), CacheState.VALID);
712 expect(entry.getState(result2), CacheState.VALID);
713 expect(entry.getValue(result1), 111);
714 expect(entry.getValue(result2), 222);
715 // set result1; result2 is intact
716 entry.setValue(result1, 1111, TargetedResult.EMPTY_LIST);
717 expect(entry.getState(result1), CacheState.VALID);
718 expect(entry.getState(result2), CacheState.VALID);
719 expect(entry.getValue(result1), 1111);
720 expect(entry.getValue(result2), 222);
721 }
722
723 test_setValueIncremental() {
724 AnalysisTarget target = new TestSource();
725 CacheEntry entry = new CacheEntry(target);
726 cache.put(entry);
727 ResultDescriptor result1 = new ResultDescriptor('result1', -1);
728 ResultDescriptor result2 = new ResultDescriptor('result2', -2);
729 ResultDescriptor result3 = new ResultDescriptor('result3', -3);
730 // set results, all of them are VALID
731 entry.setValue(result1, 111, TargetedResult.EMPTY_LIST);
732 entry.setValue(result2, 222, [new TargetedResult(target, result1)]);
733 entry.setValue(result3, 333, [new TargetedResult(target, result2)]);
734 expect(entry.getState(result1), CacheState.VALID);
735 expect(entry.getState(result2), CacheState.VALID);
736 expect(entry.getState(result3), CacheState.VALID);
737 expect(entry.getValue(result1), 111);
738 expect(entry.getValue(result2), 222);
739 expect(entry.getValue(result3), 333);
740 // replace result1, keep "dependedOn", invalidate result3
741 entry.setValueIncremental(result2, 2222, true);
742 expect(entry.getState(result1), CacheState.VALID);
743 expect(entry.getState(result2), CacheState.VALID);
744 expect(entry.getState(result3), CacheState.INVALID);
745 expect(entry.getValue(result1), 111);
746 expect(entry.getValue(result2), 2222);
747 expect(entry.getValue(result3), -3);
748 expect(entry.getResultData(result1).dependentResults,
749 unorderedEquals([new TargetedResult(target, result2)]));
750 expect(entry.getResultData(result2).dependedOnResults,
751 unorderedEquals([new TargetedResult(target, result1)]));
752 }
753
754 test_toString_empty() {
755 AnalysisTarget target = new TestSource();
756 CacheEntry entry = new CacheEntry(target);
757 expect(entry.toString(), isNotNull);
758 }
759
760 test_toString_nonEmpty() {
761 AnalysisTarget target = new TestSource();
762 ResultDescriptor result = new ResultDescriptor('test', null);
763 CacheEntry entry = new CacheEntry(target);
764 entry.setValue(result, 42, TargetedResult.EMPTY_LIST);
765 expect(entry.toString(), isNotNull);
766 }
767 }
768
769 @reflectiveTest
770 class CacheFlushManagerTest {
771 CacheFlushManager manager = new CacheFlushManager(
772 new SimpleResultCachingPolicy(15, 3), (AnalysisTarget target) => false);
773
774 test_madeActive() {
775 manager.madeActive();
776 expect(manager.maxSize, 15);
777 }
778
779 test_madeIdle() {
780 manager.madeActive();
781 AnalysisTarget target = new TestSource();
782 // prepare TargetedResult(s)
783 List<TargetedResult> results = <TargetedResult>[];
784 for (int i = 0; i < 15; i++) {
785 ResultDescriptor descriptor = new ResultDescriptor('result$i', null);
786 results.add(new TargetedResult(target, descriptor));
787 }
788 // notify about storing TargetedResult(s)
789 for (TargetedResult result in results) {
790 manager.resultStored(result, null);
791 }
792 expect(manager.recentlyUsed, results);
793 expect(manager.currentSize, 15);
794 // make idle
795 List<TargetedResult> resultsToFlush = manager.madeIdle();
796 expect(manager.maxSize, 3);
797 expect(manager.recentlyUsed, results.skip(15 - 3));
798 expect(resultsToFlush, results.take(15 - 3));
799 }
800
801 test_new() {
802 expect(manager.maxActiveSize, 15);
803 expect(manager.maxIdleSize, 3);
804 expect(manager.maxSize, 3);
805 expect(manager.currentSize, 0);
806 expect(manager.recentlyUsed, isEmpty);
807 }
808
809 test_resultAccessed() {
810 ResultDescriptor descriptor1 = new ResultDescriptor('result1', null);
811 ResultDescriptor descriptor2 = new ResultDescriptor('result2', null);
812 ResultDescriptor descriptor3 = new ResultDescriptor('result3', null);
813 AnalysisTarget target = new TestSource();
814 TargetedResult result1 = new TargetedResult(target, descriptor1);
815 TargetedResult result2 = new TargetedResult(target, descriptor2);
816 TargetedResult result3 = new TargetedResult(target, descriptor3);
817 manager.resultStored(result1, null);
818 manager.resultStored(result2, null);
819 manager.resultStored(result3, null);
820 expect(manager.currentSize, 3);
821 expect(manager.recentlyUsed, orderedEquals([result1, result2, result3]));
822 // access result2
823 manager.resultAccessed(result2);
824 expect(manager.currentSize, 3);
825 expect(manager.recentlyUsed, orderedEquals([result1, result3, result2]));
826 }
827
828 test_resultAccessed_negativeMaxSize() {
829 manager = new CacheFlushManager(new SimpleResultCachingPolicy(-1, -1),
830 (AnalysisTarget target) => false);
831 ResultDescriptor descriptor1 = new ResultDescriptor('result1', null);
832 ResultDescriptor descriptor2 = new ResultDescriptor('result2', null);
833 AnalysisTarget target = new TestSource();
834 TargetedResult result1 = new TargetedResult(target, descriptor1);
835 TargetedResult result2 = new TargetedResult(target, descriptor2);
836 manager.resultStored(result1, null);
837 manager.resultStored(result2, null);
838 expect(manager.currentSize, 0);
839 expect(manager.recentlyUsed, isEmpty);
840 // access result2
841 manager.resultAccessed(result2);
842 expect(manager.currentSize, 0);
843 expect(manager.recentlyUsed, isEmpty);
844 }
845
846 test_resultAccessed_noSuchResult() {
847 ResultDescriptor descriptor1 = new ResultDescriptor('result1', null);
848 ResultDescriptor descriptor2 = new ResultDescriptor('result2', null);
849 ResultDescriptor descriptor3 = new ResultDescriptor('result3', null);
850 AnalysisTarget target = new TestSource();
851 TargetedResult result1 = new TargetedResult(target, descriptor1);
852 TargetedResult result2 = new TargetedResult(target, descriptor2);
853 TargetedResult result3 = new TargetedResult(target, descriptor3);
854 manager.resultStored(result1, null);
855 manager.resultStored(result2, null);
856 expect(manager.currentSize, 2);
857 expect(manager.recentlyUsed, orderedEquals([result1, result2]));
858 // access result3, no-op
859 manager.resultAccessed(result3);
860 expect(manager.currentSize, 2);
861 expect(manager.recentlyUsed, orderedEquals([result1, result2]));
862 }
863
864 test_resultStored() {
865 ResultDescriptor descriptor1 = new ResultDescriptor('result1', null);
866 ResultDescriptor descriptor2 = new ResultDescriptor('result2', null);
867 ResultDescriptor descriptor3 = new ResultDescriptor('result3', null);
868 ResultDescriptor descriptor4 = new ResultDescriptor('result4', null);
869 AnalysisTarget target = new TestSource();
870 TargetedResult result1 = new TargetedResult(target, descriptor1);
871 TargetedResult result2 = new TargetedResult(target, descriptor2);
872 TargetedResult result3 = new TargetedResult(target, descriptor3);
873 TargetedResult result4 = new TargetedResult(target, descriptor4);
874 manager.resultStored(result1, null);
875 manager.resultStored(result2, null);
876 manager.resultStored(result3, null);
877 expect(manager.currentSize, 3);
878 expect(manager.recentlyUsed, orderedEquals([result1, result2, result3]));
879 // store result2 again
880 {
881 List<TargetedResult> resultsToFlush = manager.resultStored(result2, null);
882 expect(resultsToFlush, isEmpty);
883 expect(manager.currentSize, 3);
884 expect(manager.recentlyUsed, orderedEquals([result1, result3, result2]));
885 }
886 // store result4
887 {
888 List<TargetedResult> resultsToFlush = manager.resultStored(result4, null);
889 expect(resultsToFlush, [result1]);
890 expect(manager.currentSize, 3);
891 expect(manager.recentlyUsed, orderedEquals([result3, result2, result4]));
892 expect(manager.resultSizeMap, {result3: 1, result2: 1, result4: 1});
893 }
894 }
895
896 test_resultStored_negativeMaxSize() {
897 manager = new CacheFlushManager(new SimpleResultCachingPolicy(-1, -1),
898 (AnalysisTarget target) => false);
899 ResultDescriptor descriptor1 = new ResultDescriptor('result1', null);
900 ResultDescriptor descriptor2 = new ResultDescriptor('result2', null);
901 AnalysisTarget target = new TestSource();
902 TargetedResult result1 = new TargetedResult(target, descriptor1);
903 TargetedResult result2 = new TargetedResult(target, descriptor2);
904 manager.resultStored(result1, null);
905 manager.resultStored(result2, null);
906 expect(manager.currentSize, 0);
907 expect(manager.recentlyUsed, isEmpty);
908 }
909
910 test_targetRemoved() {
911 ResultDescriptor descriptor1 = new ResultDescriptor('result1', null);
912 ResultDescriptor descriptor2 = new ResultDescriptor('result2', null);
913 ResultDescriptor descriptor3 = new ResultDescriptor('result3', null);
914 AnalysisTarget target1 = new TestSource('a.dart');
915 AnalysisTarget target2 = new TestSource('b.dart');
916 TargetedResult result1 = new TargetedResult(target1, descriptor1);
917 TargetedResult result2 = new TargetedResult(target2, descriptor2);
918 TargetedResult result3 = new TargetedResult(target1, descriptor3);
919 manager.resultStored(result1, null);
920 manager.resultStored(result2, null);
921 manager.resultStored(result3, null);
922 expect(manager.currentSize, 3);
923 expect(manager.recentlyUsed, orderedEquals([result1, result2, result3]));
924 expect(manager.resultSizeMap, {result1: 1, result2: 1, result3: 1});
925 // remove target1
926 {
927 manager.targetRemoved(target1);
928 expect(manager.currentSize, 1);
929 expect(manager.recentlyUsed, orderedEquals([result2]));
930 expect(manager.resultSizeMap, {result2: 1});
931 }
932 // remove target2
933 {
934 manager.targetRemoved(target2);
935 expect(manager.currentSize, 0);
936 expect(manager.recentlyUsed, isEmpty);
937 expect(manager.resultSizeMap, isEmpty);
938 }
939 }
940 }
941
942 abstract class CachePartitionTest extends EngineTestCase {
943 CachePartition createPartition();
944
945 void test_creation() {
946 expect(createPartition(), isNotNull);
947 }
948
949 void test_entrySet() {
950 CachePartition partition = createPartition();
951 AnalysisTarget target = new TestSource();
952 CacheEntry entry = new CacheEntry(target);
953 partition.put(entry);
954 Map<AnalysisTarget, CacheEntry> entryMap = partition.map;
955 expect(entryMap, hasLength(1));
956 AnalysisTarget entryKey = entryMap.keys.first;
957 expect(entryKey, target);
958 expect(entryMap[entryKey], entry);
959 }
960
961 void test_get() {
962 CachePartition partition = createPartition();
963 AnalysisTarget target = new TestSource();
964 expect(partition.get(target), isNull);
965 }
966
967 void test_put_alreadyInPartition() {
968 CachePartition partition1 = createPartition();
969 CachePartition partition2 = createPartition();
970 AnalysisTarget target = new TestSource();
971 CacheEntry entry = new CacheEntry(target);
972 partition1.put(entry);
973 expect(() => partition2.put(entry), throwsStateError);
974 }
975
976 void test_put_noFlush() {
977 CachePartition partition = createPartition();
978 AnalysisTarget target = new TestSource();
979 CacheEntry entry = new CacheEntry(target);
980 partition.put(entry);
981 expect(partition.get(target), entry);
982 }
983
984 void test_remove_absent() {
985 CachePartition partition = createPartition();
986 AnalysisTarget target = new TestSource();
987 expect(partition.get(target), isNull);
988 expect(partition.remove(target), isNull);
989 expect(partition.get(target), isNull);
990 }
991
992 void test_remove_present() {
993 CachePartition partition = createPartition();
994 AnalysisTarget target = new TestSource();
995 CacheEntry entry = new CacheEntry(target);
996 partition.put(entry);
997 expect(partition.get(target), entry);
998 expect(partition.remove(target), entry);
999 expect(partition.get(target), isNull);
1000 }
1001 }
1002
1003 @reflectiveTest
1004 class ResultDataTest extends EngineTestCase {
1005 test_creation() {
1006 String value = 'value';
1007 ResultData data = new ResultData(new ResultDescriptor('test', value));
1008 expect(data, isNotNull);
1009 expect(data.state, CacheState.INVALID);
1010 expect(data.value, value);
1011 }
1012
1013 test_flush() {
1014 ResultDescriptor result = new ResultDescriptor('test', -1);
1015 ResultData data = new ResultData(result);
1016 data.state = CacheState.VALID;
1017 data.value = 123;
1018 data.flush();
1019 expect(data.state, CacheState.FLUSHED);
1020 expect(data.value, -1);
1021 }
1022 }
1023
1024 @reflectiveTest
1025 class SdkCachePartitionTest extends CachePartitionTest {
1026 CachePartition createPartition() {
1027 return new SdkCachePartition(null);
1028 }
1029
1030 void test_contains_false() {
1031 CachePartition partition = createPartition();
1032 AnalysisTarget target = new TestSource();
1033 expect(partition.isResponsibleFor(target), isFalse);
1034 }
1035
1036 void test_contains_true() {
1037 SdkCachePartition partition = new SdkCachePartition(null);
1038 SourceFactory factory = new SourceFactory(
1039 [new DartUriResolver(DirectoryBasedDartSdk.defaultSdk)]);
1040 AnalysisTarget target = factory.forUri("dart:core");
1041 expect(partition.isResponsibleFor(target), isTrue);
1042 }
1043 }
1044
1045 @reflectiveTest
1046 class UniversalCachePartitionTest extends CachePartitionTest {
1047 CachePartition createPartition() {
1048 return new UniversalCachePartition(null);
1049 }
1050
1051 void test_contains() {
1052 UniversalCachePartition partition = new UniversalCachePartition(null);
1053 TestSource source = new TestSource();
1054 expect(partition.isResponsibleFor(source), isTrue);
1055 }
1056
1057 test_dispose() {
1058 InternalAnalysisContext context = new _InternalAnalysisContextMock();
1059 CachePartition partition1 = new UniversalCachePartition(context);
1060 CachePartition partition2 = new UniversalCachePartition(context);
1061 AnalysisCache cache = new AnalysisCache([partition1, partition2]);
1062 when(context.analysisCache).thenReturn(cache);
1063 // configure
1064 // prepare entries
1065 ResultDescriptor descriptor1 = new ResultDescriptor('result1', -1);
1066 ResultDescriptor descriptor2 = new ResultDescriptor('result2', -2);
1067 AnalysisTarget target1 = new TestSource('1.dart');
1068 AnalysisTarget target2 = new TestSource('2.dart');
1069 TargetedResult result1 = new TargetedResult(target1, descriptor1);
1070 TargetedResult result2 = new TargetedResult(target2, descriptor2);
1071 CacheEntry entry1 = new CacheEntry(target1);
1072 CacheEntry entry2 = new CacheEntry(target2);
1073 partition1.put(entry1);
1074 partition2.put(entry2);
1075 entry1.setValue(descriptor1, 1, TargetedResult.EMPTY_LIST);
1076 entry2.setValue(descriptor2, 2, <TargetedResult>[result1]);
1077 // target2 is listed as dependent in target1
1078 expect(
1079 entry1.getResultData(descriptor1).dependentResults, contains(result2));
1080 // dispose
1081 partition2.dispose();
1082 expect(partition1.get(target1), same(entry1));
1083 expect(partition2.get(target2), isNull);
1084 // result2 is removed from result1
1085 expect(entry1.getResultData(descriptor1).dependentResults, isEmpty);
1086 }
1087 }
1088
1089 class _InternalAnalysisContextMock extends TypedMock
1090 implements InternalAnalysisContext {
1091 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
1092 }
1093
1094 /**
1095 * Keep the given [keepDescriptor], invalidate all the other results.
1096 */
1097 class _KeepContinueDelta implements Delta {
1098 final Source source;
1099 final ResultDescriptor keepDescriptor;
1100
1101 _KeepContinueDelta(this.source, this.keepDescriptor);
1102
1103 @override
1104 DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
1105 ResultDescriptor descriptor) {
1106 if (descriptor == keepDescriptor) {
1107 return DeltaResult.KEEP_CONTINUE;
1108 }
1109 return DeltaResult.INVALIDATE;
1110 }
1111 }
1112
1113 class _TestAnalysisTarget implements AnalysisTarget {
1114 @override
1115 Source get source => null;
1116 }
OLDNEW
« no previous file with comments | « packages/analyzer/test/src/context/abstract_context.dart ('k') | packages/analyzer/test/src/context/context_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698