1// Copyright 2014 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import 'package:file/file.dart';
6import 'package:file/memory.dart';
7import 'package:flutter_tools/src/base/common.dart';
8import 'package:flutter_tools/src/base/file_system.dart';
9import 'package:flutter_tools/src/base/io.dart' show ProcessException;
10import 'package:flutter_tools/src/base/logger.dart';
11import 'package:flutter_tools/src/base/platform.dart';
12import 'package:flutter_tools/src/cache.dart';
13import 'package:flutter_tools/src/convert.dart';
14import 'package:flutter_tools/src/dart/pub.dart';
15import 'package:flutter_tools/src/features.dart';
16import 'package:flutter_tools/src/project.dart';
17
18import '../../src/common.dart';
19import '../../src/context.dart';
20import '../../src/fake_process_manager.dart';
21import '../../src/fakes.dart';
22import '../../src/package_config.dart';
23
24void main() {
25 setUpAll(() {
26 Cache.flutterRoot = '';
27 });
28
29 testWithoutContext('Throws a tool exit if pub cannot be run', () async {
30 final FakeProcessManager processManager = FakeProcessManager.empty();
31 final BufferLogger logger = BufferLogger.test();
32 final MemoryFileSystem fileSystem = MemoryFileSystem.test();
33 processManager.excludedExecutables.add('bin/cache/dart-sdk/bin/dart');
34
35 fileSystem.file('pubspec.yaml').createSync();
36
37 final Pub pub = Pub.test(
38 fileSystem: fileSystem,
39 logger: logger,
40 processManager: processManager,
41 platform: FakePlatform(),
42 botDetector: const FakeBotDetector(false),
43 stdio: FakeStdio(),
44 );
45
46 await expectLater(
47 () => pub.get(
48 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
49 context: PubContext.pubGet,
50 checkUpToDate: true,
51 ),
52 throwsToolExit(
53 message: 'Your Flutter SDK download may be corrupt or missing permissions to run',
54 ),
55 );
56 });
57
58 group('shouldSkipThirdPartyGenerator', () {
59 testWithoutContext('does not skip pub get the parameter is false', () async {
60 final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
61 const FakeCommand(
62 command: <String>[
63 'bin/cache/dart-sdk/bin/dart',
64 'pub',
65 '--suppress-analytics',
66 '--directory',
67 '.',
68 'get',
69 '--example',
70 ],
71 ),
72 ]);
73 final BufferLogger logger = BufferLogger.test();
74 final MemoryFileSystem fileSystem = MemoryFileSystem.test();
75
76 fileSystem.file('pubspec.yaml').createSync();
77 fileSystem.file('pubspec.lock').createSync();
78 fileSystem.file('version').writeAsStringSync('b');
79 fileSystem.file('.dart_tool/package_config.json')
80 ..createSync(recursive: true)
81 ..writeAsStringSync('''
82 {
83 "configVersion": 2,
84 "packages": [],
85 "generated": "2021-07-08T10:02:49.155589Z",
86 "generator": "third-party",
87 "generatorVersion": "2.14.0-276.0.dev"
88 }
89 ''');
90
91 final Pub pub = Pub.test(
92 fileSystem: fileSystem,
93 logger: logger,
94 processManager: processManager,
95 platform: FakePlatform(),
96 botDetector: const FakeBotDetector(false),
97 stdio: FakeStdio(),
98 );
99
100 await pub.get(
101 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
102 context: PubContext.pubGet,
103 checkUpToDate: true,
104 shouldSkipThirdPartyGenerator: false,
105 );
106
107 expect(processManager, hasNoRemainingExpectations);
108 expect(fileSystem.file('.dart_tool/version').readAsStringSync(), 'b');
109 });
110
111 testWithoutContext(
112 'does not skip pub get if package_config.json has "generator": "pub"',
113 () async {
114 final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
115 const FakeCommand(
116 command: <String>[
117 'bin/cache/dart-sdk/bin/dart',
118 'pub',
119 '--suppress-analytics',
120 '--directory',
121 '.',
122 'get',
123 '--example',
124 ],
125 ),
126 ]);
127 final BufferLogger logger = BufferLogger.test();
128 final MemoryFileSystem fileSystem = MemoryFileSystem.test();
129
130 fileSystem.file('pubspec.yaml').createSync();
131 fileSystem.file('pubspec.lock').createSync();
132 fileSystem.file('.dart_tool/package_config.json')
133 ..createSync(recursive: true)
134 ..writeAsStringSync('''
135 {
136 "configVersion": 2,
137 "packages": [],
138 "generated": "2021-07-08T10:02:49.155589Z",
139 "generator": "pub",
140 "generatorVersion": "2.14.0-276.0.dev"
141 }
142 ''');
143 fileSystem.file('.dart_tool/version').writeAsStringSync('a');
144 fileSystem.file('version').writeAsStringSync('b');
145
146 final Pub pub = Pub.test(
147 fileSystem: fileSystem,
148 logger: logger,
149 processManager: processManager,
150 platform: FakePlatform(),
151 botDetector: const FakeBotDetector(false),
152 stdio: FakeStdio(),
153 );
154
155 await pub.get(
156 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
157 context: PubContext.pubGet,
158 checkUpToDate: true,
159 );
160
161 expect(processManager, hasNoRemainingExpectations);
162 expect(fileSystem.file('.dart_tool/version').readAsStringSync(), 'b');
163 },
164 );
165
166 testWithoutContext(
167 'does not skip pub get if package_config.json has "generator": "pub"',
168 () async {
169 final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
170 const FakeCommand(
171 command: <String>[
172 'bin/cache/dart-sdk/bin/dart',
173 'pub',
174 '--suppress-analytics',
175 '--directory',
176 '.',
177 'get',
178 '--example',
179 ],
180 ),
181 ]);
182 final BufferLogger logger = BufferLogger.test();
183 final MemoryFileSystem fileSystem = MemoryFileSystem.test();
184
185 fileSystem.file('pubspec.yaml').createSync();
186 fileSystem.file('pubspec.lock').createSync();
187 fileSystem.file('.dart_tool/package_config.json')
188 ..createSync(recursive: true)
189 ..writeAsStringSync('''
190 {
191 "configVersion": 2,
192 "packages": [],
193 "generated": "2021-07-08T10:02:49.155589Z",
194 "generator": "pub",
195 "generatorVersion": "2.14.0-276.0.dev"
196 }
197 ''');
198 fileSystem.file('.dart_tool/version').writeAsStringSync('a');
199 fileSystem.file('version').writeAsStringSync('b');
200
201 final Pub pub = Pub.test(
202 fileSystem: fileSystem,
203 logger: logger,
204 processManager: processManager,
205 platform: FakePlatform(),
206 botDetector: const FakeBotDetector(false),
207 stdio: FakeStdio(),
208 );
209
210 await pub.get(
211 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
212 context: PubContext.pubGet,
213 checkUpToDate: true,
214 );
215
216 expect(processManager, hasNoRemainingExpectations);
217 expect(fileSystem.file('.dart_tool/version').readAsStringSync(), 'b');
218 },
219 );
220
221 testWithoutContext('skips pub get if the package config "generator" is '
222 'different than "pub"', () async {
223 final FakeProcessManager processManager = FakeProcessManager.empty();
224 final BufferLogger logger = BufferLogger.test();
225 final MemoryFileSystem fileSystem = MemoryFileSystem.test();
226
227 fileSystem.file('pubspec.yaml').createSync();
228 fileSystem.file('pubspec.lock').createSync();
229 fileSystem.file('.dart_tool/package_config.json')
230 ..createSync(recursive: true)
231 ..writeAsStringSync('{"generator": "third-party"}');
232
233 final Pub pub = Pub.test(
234 fileSystem: fileSystem,
235 logger: logger,
236 processManager: processManager,
237 platform: FakePlatform(),
238 botDetector: const FakeBotDetector(false),
239 stdio: FakeStdio(),
240 );
241
242 await pub.get(
243 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
244 context: PubContext.pubGet,
245 checkUpToDate: true,
246 );
247
248 expect(logger.traceText, contains('Skipping pub get: generated by third-party.'));
249 });
250 });
251
252 testWithoutContext('checkUpToDate skips pub get if the package config is newer than the pubspec '
253 'and the current framework version is the same as the last version', () async {
254 final FakeProcessManager processManager = FakeProcessManager.empty();
255 final BufferLogger logger = BufferLogger.test();
256 final MemoryFileSystem fileSystem = MemoryFileSystem.test();
257
258 fileSystem.file('pubspec.yaml').createSync();
259 fileSystem.file('pubspec.lock').createSync();
260 fileSystem.file('.dart_tool/package_config.json').createSync(recursive: true);
261 fileSystem.file('.dart_tool/version').writeAsStringSync('a');
262 fileSystem.file('version').writeAsStringSync('a');
263
264 final Pub pub = Pub.test(
265 fileSystem: fileSystem,
266 logger: logger,
267 processManager: processManager,
268 platform: FakePlatform(),
269 botDetector: const FakeBotDetector(false),
270 stdio: FakeStdio(),
271 );
272
273 await pub.get(
274 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
275 context: PubContext.pubGet,
276 checkUpToDate: true,
277 );
278
279 expect(logger.traceText, contains('Skipping pub get: version match.'));
280 });
281
282 testWithoutContext(
283 'checkUpToDate does not skip pub get if the package config is newer than the pubspec '
284 'but the current framework version is not the same as the last version',
285 () async {
286 final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
287 const FakeCommand(
288 command: <String>[
289 'bin/cache/dart-sdk/bin/dart',
290 'pub',
291 '--suppress-analytics',
292 '--directory',
293 '.',
294 'get',
295 '--example',
296 ],
297 ),
298 ]);
299 final BufferLogger logger = BufferLogger.test();
300 final MemoryFileSystem fileSystem = MemoryFileSystem.test();
301
302 fileSystem.file('pubspec.yaml').createSync();
303 fileSystem.file('pubspec.lock').createSync();
304 fileSystem.file('.dart_tool/package_config.json').createSync(recursive: true);
305 fileSystem.file('.dart_tool/version').writeAsStringSync('a');
306 fileSystem.file('version').writeAsStringSync('b');
307
308 final Pub pub = Pub.test(
309 fileSystem: fileSystem,
310 logger: logger,
311 processManager: processManager,
312 platform: FakePlatform(),
313 botDetector: const FakeBotDetector(false),
314 stdio: FakeStdio(),
315 );
316
317 await pub.get(
318 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
319 context: PubContext.pubGet,
320 checkUpToDate: true,
321 );
322
323 expect(processManager, hasNoRemainingExpectations);
324 expect(fileSystem.file('.dart_tool/version').readAsStringSync(), 'b');
325 },
326 );
327
328 testWithoutContext(
329 'checkUpToDate does not skip pub get if the package config is newer than the pubspec '
330 'but the current framework version does not exist yet',
331 () async {
332 final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
333 const FakeCommand(
334 command: <String>[
335 'bin/cache/dart-sdk/bin/dart',
336 'pub',
337 '--suppress-analytics',
338 '--directory',
339 '.',
340 'get',
341 '--example',
342 ],
343 ),
344 ]);
345 final BufferLogger logger = BufferLogger.test();
346 final MemoryFileSystem fileSystem = MemoryFileSystem.test();
347
348 fileSystem.file('pubspec.yaml').createSync();
349 fileSystem.file('pubspec.lock').createSync();
350 fileSystem.file('.dart_tool/package_config.json').createSync(recursive: true);
351 fileSystem.file('version').writeAsStringSync('b');
352
353 final Pub pub = Pub.test(
354 fileSystem: fileSystem,
355 logger: logger,
356 processManager: processManager,
357 platform: FakePlatform(),
358 botDetector: const FakeBotDetector(false),
359 stdio: FakeStdio(),
360 );
361
362 await pub.get(
363 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
364 context: PubContext.pubGet,
365 checkUpToDate: true,
366 );
367
368 expect(processManager, hasNoRemainingExpectations);
369 expect(fileSystem.file('.dart_tool/version').readAsStringSync(), 'b');
370 },
371 );
372
373 testWithoutContext(
374 'checkUpToDate does not skip pub get if the package config does not exist',
375 () async {
376 final MemoryFileSystem fileSystem = MemoryFileSystem.test();
377 final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
378 FakeCommand(
379 command: const <String>[
380 'bin/cache/dart-sdk/bin/dart',
381 'pub',
382 '--suppress-analytics',
383 '--directory',
384 '.',
385 'get',
386 '--example',
387 ],
388 onRun: (_) {
389 fileSystem.file('.dart_tool/package_config.json').createSync(recursive: true);
390 },
391 ),
392 ]);
393 final BufferLogger logger = BufferLogger.test();
394
395 fileSystem.file('pubspec.yaml').createSync();
396 fileSystem.file('pubspec.lock').createSync();
397 fileSystem.file('version').writeAsStringSync('b');
398
399 final Pub pub = Pub.test(
400 fileSystem: fileSystem,
401 logger: logger,
402 processManager: processManager,
403 platform: FakePlatform(),
404 botDetector: const FakeBotDetector(false),
405 stdio: FakeStdio(),
406 );
407
408 await pub.get(
409 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
410 context: PubContext.pubGet,
411 checkUpToDate: true,
412 );
413
414 expect(processManager, hasNoRemainingExpectations);
415 expect(fileSystem.file('.dart_tool/version').readAsStringSync(), 'b');
416 },
417 );
418
419 testWithoutContext(
420 'checkUpToDate does not skip pub get if the pubspec.lock does not exist',
421 () async {
422 final MemoryFileSystem fileSystem = MemoryFileSystem.test();
423 final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
424 const FakeCommand(
425 command: <String>[
426 'bin/cache/dart-sdk/bin/dart',
427 'pub',
428 '--suppress-analytics',
429 '--directory',
430 '.',
431 'get',
432 '--example',
433 ],
434 ),
435 ]);
436 final BufferLogger logger = BufferLogger.test();
437
438 fileSystem.file('pubspec.yaml').createSync();
439 fileSystem.file('version').writeAsStringSync('b');
440 fileSystem.file('.dart_tool/package_config.json').createSync(recursive: true);
441 fileSystem.file('.dart_tool/version').writeAsStringSync('b');
442
443 final Pub pub = Pub.test(
444 fileSystem: fileSystem,
445 logger: logger,
446 processManager: processManager,
447 platform: FakePlatform(),
448 botDetector: const FakeBotDetector(false),
449 stdio: FakeStdio(),
450 );
451
452 await pub.get(
453 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
454 context: PubContext.pubGet,
455 checkUpToDate: true,
456 );
457
458 expect(processManager, hasNoRemainingExpectations);
459 expect(fileSystem.file('.dart_tool/version').readAsStringSync(), 'b');
460 },
461 );
462
463 testWithoutContext(
464 'checkUpToDate does not skip pub get if the package config is older that the pubspec',
465 () async {
466 final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
467 const FakeCommand(
468 command: <String>[
469 'bin/cache/dart-sdk/bin/dart',
470 'pub',
471 '--suppress-analytics',
472 '--directory',
473 '.',
474 'get',
475 '--example',
476 ],
477 ),
478 ]);
479 final BufferLogger logger = BufferLogger.test();
480 final MemoryFileSystem fileSystem = MemoryFileSystem.test();
481
482 fileSystem.file('pubspec.yaml').createSync();
483 fileSystem.file('pubspec.lock').createSync();
484 fileSystem.file('.dart_tool/package_config.json')
485 ..createSync(recursive: true)
486 ..setLastModifiedSync(DateTime(1991));
487 fileSystem.file('version').writeAsStringSync('b');
488
489 final Pub pub = Pub.test(
490 fileSystem: fileSystem,
491 logger: logger,
492 processManager: processManager,
493 platform: FakePlatform(),
494 botDetector: const FakeBotDetector(false),
495 stdio: FakeStdio(),
496 );
497
498 await pub.get(
499 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
500 context: PubContext.pubGet,
501 checkUpToDate: true,
502 );
503
504 expect(processManager, hasNoRemainingExpectations);
505 expect(fileSystem.file('.dart_tool/version').readAsStringSync(), 'b');
506 },
507 );
508
509 testWithoutContext(
510 'checkUpToDate does not skip pub get if the pubspec.lock is older that the pubspec',
511 () async {
512 final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
513 const FakeCommand(
514 command: <String>[
515 'bin/cache/dart-sdk/bin/dart',
516 'pub',
517 '--suppress-analytics',
518 '--directory',
519 '.',
520 'get',
521 '--example',
522 ],
523 ),
524 ]);
525 final BufferLogger logger = BufferLogger.test();
526 final MemoryFileSystem fileSystem = MemoryFileSystem.test();
527
528 fileSystem.file('pubspec.yaml').createSync();
529 fileSystem.file('pubspec.lock')
530 ..createSync()
531 ..setLastModifiedSync(DateTime(1991));
532 fileSystem.file('.dart_tool/package_config.json').createSync(recursive: true);
533 fileSystem.file('version').writeAsStringSync('b');
534 fileSystem.file('.dart_tool/version').writeAsStringSync('b');
535
536 final Pub pub = Pub.test(
537 fileSystem: fileSystem,
538 logger: logger,
539 processManager: processManager,
540 platform: FakePlatform(),
541 botDetector: const FakeBotDetector(false),
542 stdio: FakeStdio(),
543 );
544
545 await pub.get(
546 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
547 context: PubContext.pubGet,
548 checkUpToDate: true,
549 );
550
551 expect(processManager, hasNoRemainingExpectations);
552 expect(fileSystem.file('.dart_tool/version').readAsStringSync(), 'b');
553 },
554 );
555
556 testWithoutContext('pub get 66 shows message from pub', () async {
557 final BufferLogger logger = BufferLogger.test();
558 final FileSystem fileSystem = MemoryFileSystem.test();
559
560 final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
561 const FakeCommand(
562 command: <String>[
563 'bin/cache/dart-sdk/bin/dart',
564 'pub',
565 '--suppress-analytics',
566 '--directory',
567 '.',
568 'get',
569 '--example',
570 ],
571 exitCode: 66,
572 stderr: 'err1\nerr2\nerr3\n',
573 stdout: 'out1\nout2\nout3\n',
574 environment: <String, String>{
575 'FLUTTER_ROOT': '',
576 'PUB_ENVIRONMENT': 'flutter_cli:flutter_tests',
577 },
578 ),
579 ]);
580 final FakeStdio mockStdio = FakeStdio();
581 final Pub pub = Pub.test(
582 platform: FakePlatform(),
583 fileSystem: fileSystem,
584 logger: logger,
585 botDetector: const FakeBotDetector(false),
586 stdio: mockStdio,
587 processManager: processManager,
588 );
589 const String toolExitMessage = '''
590pub get failed
591command: "bin/cache/dart-sdk/bin/dart pub --suppress-analytics --directory . get --example"
592pub env: {
593 "FLUTTER_ROOT": "",
594 "PUB_ENVIRONMENT": "flutter_cli:flutter_tests",
595}
596exit code: 66
597''';
598 await expectLater(
599 () => pub.get(
600 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
601 context: PubContext.flutterTests,
602 ),
603 throwsA(
604 isA<ToolExit>().having(
605 (ToolExit error) => error.message,
606 'message',
607 contains('Failed to update packages'),
608 ),
609 ),
610 );
611 expect(logger.statusText, isEmpty);
612 expect(logger.traceText, contains(toolExitMessage));
613 expect(mockStdio.stdout.writes.map(utf8.decode), <String>['out1\nout2\nout3\n']);
614 expect(mockStdio.stderr.writes.map(utf8.decode), <String>['err1\nerr2\nerr3\n']);
615 expect(processManager, hasNoRemainingExpectations);
616 });
617
618 testWithoutContext(
619 'pub get with failing exit code even with OutputMode == failuresOnly',
620 () async {
621 final BufferLogger logger = BufferLogger.test();
622 final FileSystem fileSystem = MemoryFileSystem.test();
623
624 final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
625 const FakeCommand(
626 command: <String>[
627 'bin/cache/dart-sdk/bin/dart',
628 'pub',
629 '--suppress-analytics',
630 '--directory',
631 '.',
632 'get',
633 '--example',
634 ],
635 exitCode: 1,
636 stderr: '===pub get failed stderr here===',
637 stdout: 'out1\nout2\nout3\n',
638 environment: <String, String>{
639 'FLUTTER_ROOT': '',
640 'PUB_ENVIRONMENT': 'flutter_cli:update_packages',
641 },
642 ),
643 ]);
644
645 // Intentionally not using pub.test to simulate a real environment, but
646 // we are using non-inherited I/O to avoid printing to the console.
647 final Pub pub = Pub(
648 platform: FakePlatform(),
649 fileSystem: fileSystem,
650 logger: logger,
651 botDetector: const FakeBotDetector(false),
652 processManager: processManager,
653 );
654
655 await expectLater(
656 () => pub.get(
657 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
658 context: PubContext.updatePackages,
659 outputMode: PubOutputMode.failuresOnly,
660 ),
661 throwsToolExit(message: 'Failed to update packages'),
662 );
663 expect(logger.statusText, isEmpty);
664 expect(logger.errorText, contains('===pub get failed stderr here==='));
665 expect(
666 logger.warningText,
667 contains('git remote set-url upstream'),
668 reason: 'When update-packages fails, it is often because of missing an upstream remote.',
669 );
670 expect(processManager, hasNoRemainingExpectations);
671 },
672 );
673
674 testWithoutContext('pub get shows working directory on process exception', () async {
675 final BufferLogger logger = BufferLogger.test();
676 final FileSystem fileSystem = MemoryFileSystem.test();
677
678 final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
679 FakeCommand(
680 command: const <String>[
681 'bin/cache/dart-sdk/bin/dart',
682 'pub',
683 '--suppress-analytics',
684 '--directory',
685 '.',
686 'get',
687 '--example',
688 ],
689 onRun: (_) {
690 throw const ProcessException(
691 'bin/cache/dart-sdk/bin/dart',
692 <String>['pub', '--suppress-analytics', '--directory', '.', 'get', '--example'],
693 'message',
694 1,
695 );
696 },
697 exitCode: 66,
698 stderr: 'err1\nerr2\nerr3\n',
699 stdout: 'out1\nout2\nout3\n',
700 environment: const <String, String>{
701 'FLUTTER_ROOT': '',
702 'PUB_ENVIRONMENT': 'flutter_cli:flutter_tests',
703 },
704 ),
705 ]);
706
707 final Pub pub = Pub.test(
708 platform: FakePlatform(),
709 fileSystem: fileSystem,
710 logger: logger,
711 botDetector: const FakeBotDetector(false),
712 stdio: FakeStdio(),
713 processManager: processManager,
714 );
715 await expectLater(
716 () => pub.get(
717 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
718 context: PubContext.flutterTests,
719 ),
720 throwsA(
721 isA<ProcessException>()
722 .having(
723 (ProcessException error) => error.message,
724 'message',
725 contains('Working directory: "/" (exists)'),
726 )
727 .having(
728 (ProcessException error) => error.message,
729 'message',
730 contains('"PUB_ENVIRONMENT": "flutter_cli:flutter_tests"'),
731 ),
732 ),
733 );
734 expect(logger.statusText, isEmpty);
735 expect(logger.errorText, isEmpty);
736 expect(processManager, hasNoRemainingExpectations);
737 });
738
739 testWithoutContext('pub get does not inherit logger.verbose', () async {
740 final BufferLogger logger = BufferLogger.test(verbose: true);
741 final FileSystem fileSystem = MemoryFileSystem.test();
742 fileSystem.currentDirectory.childFile('version').createSync();
743
744 final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
745 FakeCommand(
746 command: const <String>[
747 'bin/cache/dart-sdk/bin/dart',
748 // Note: Omitted --verbose.
749 'pub',
750 '--suppress-analytics',
751 '--directory',
752 '.',
753 'get',
754 '--example',
755 ],
756 onRun:
757 (_) => writePackageConfigFile(
758 directory: fileSystem.currentDirectory,
759 mainLibName: 'my_app',
760 ),
761 ),
762 ]);
763
764 final Pub pub = Pub.test(
765 platform: FakePlatform(),
766 fileSystem: fileSystem,
767 logger: logger,
768 botDetector: const FakeBotDetector(false),
769 stdio: FakeStdio(),
770 processManager: processManager,
771 );
772
773 await expectLater(
774 pub.get(
775 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
776 context: PubContext.flutterTests,
777 outputMode: PubOutputMode.failuresOnly,
778 ),
779 completes,
780 );
781 });
782
783 // Regression test for https://github.com/flutter/flutter/issues/116627
784 testWithoutContext('pub get suppresses progress output', () async {
785 final BufferLogger logger = BufferLogger.test();
786 final FileSystem fileSystem = MemoryFileSystem.test();
787
788 final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
789 const FakeCommand(
790 command: <String>[
791 'bin/cache/dart-sdk/bin/dart',
792 'pub',
793 '--suppress-analytics',
794 '--directory',
795 '.',
796 'get',
797 '--example',
798 ],
799 stderr: 'err1\nerr2\nerr3\n',
800 stdout: 'out1\nout2\nout3\n',
801 environment: <String, String>{
802 'FLUTTER_ROOT': '',
803 'PUB_ENVIRONMENT': 'flutter_cli:flutter_tests',
804 },
805 ),
806 ]);
807
808 final FakeStdio mockStdio = FakeStdio();
809 final Pub pub = Pub.test(
810 platform: FakePlatform(),
811 fileSystem: fileSystem,
812 logger: logger,
813 processManager: processManager,
814 botDetector: const FakeBotDetector(false),
815 stdio: mockStdio,
816 );
817
818 try {
819 await pub.get(
820 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
821 context: PubContext.flutterTests,
822 outputMode: PubOutputMode.failuresOnly,
823 );
824 } on ToolExit {
825 // Ignore.
826 }
827
828 expect(mockStdio.stdout.writes.map(utf8.decode), isNot(<String>['out1\nout2\nout3\n']));
829 expect(processManager, hasNoRemainingExpectations);
830 });
831
832 testWithoutContext('pub cache in flutter root is ignored', () async {
833 final FileSystem fileSystem = MemoryFileSystem.test();
834 final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
835 const FakeCommand(
836 command: <String>[
837 'bin/cache/dart-sdk/bin/dart',
838 'pub',
839 '--suppress-analytics',
840 '--directory',
841 '.',
842 'get',
843 '--example',
844 ],
845 exitCode: 69,
846 environment: <String, String>{
847 'FLUTTER_ROOT': '',
848 'PUB_ENVIRONMENT': 'flutter_cli:flutter_tests',
849 },
850 stdout: "FakeCommand's env successfully matched",
851 ),
852 ]);
853
854 final FakeStdio mockStdio = FakeStdio();
855 final Pub pub = Pub.test(
856 platform: FakePlatform(),
857 fileSystem: fileSystem,
858 logger: BufferLogger.test(),
859 processManager: processManager,
860 botDetector: const FakeBotDetector(false),
861 stdio: mockStdio,
862 );
863
864 try {
865 await pub.get(
866 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
867 context: PubContext.flutterTests,
868 );
869 } on ToolExit {
870 // Ignore.
871 }
872
873 expect(mockStdio.stdout.writes.map(utf8.decode), <String>[
874 "FakeCommand's env successfully matched",
875 ]);
876 expect(processManager, hasNoRemainingExpectations);
877 });
878
879 testWithoutContext('Preloaded packages are added to the pub cache', () async {
880 final FileSystem fileSystem = MemoryFileSystem.test();
881 final Directory preloadCache = fileSystem.currentDirectory.childDirectory('.pub-preload-cache');
882 preloadCache.childFile('a.tar.gz').createSync(recursive: true);
883 preloadCache.childFile('b.tar.gz').createSync();
884 fileSystem.currentDirectory.childFile('version').createSync();
885
886 final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
887 const FakeCommand(
888 command: <String>[
889 'bin/cache/dart-sdk/bin/dart',
890 'pub',
891 '--suppress-analytics',
892 'cache',
893 'preload',
894 '.pub-preload-cache/a.tar.gz',
895 '.pub-preload-cache/b.tar.gz',
896 ],
897 ),
898 FakeCommand(
899 command: const <String>[
900 'bin/cache/dart-sdk/bin/dart',
901 'pub',
902 '--suppress-analytics',
903 '--directory',
904 '.',
905 'get',
906 '--example',
907 ],
908 environment: const <String, String>{
909 'FLUTTER_ROOT': '',
910 'PUB_ENVIRONMENT': 'flutter_cli:flutter_tests',
911 },
912 onRun:
913 (_) => writePackageConfigFile(
914 directory: fileSystem.currentDirectory,
915 mainLibName: 'my_app',
916 ),
917 ),
918 ]);
919
920 final Platform platform = FakePlatform(environment: <String, String>{'HOME': '/global'});
921 final BufferLogger logger = BufferLogger.test();
922 final Pub pub = Pub.test(
923 platform: platform,
924 fileSystem: fileSystem,
925 logger: logger,
926 processManager: processManager,
927 botDetector: const FakeBotDetector(false),
928 stdio: FakeStdio(),
929 );
930
931 await pub.get(
932 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
933 context: PubContext.flutterTests,
934 );
935
936 expect(processManager, hasNoRemainingExpectations);
937 expect(preloadCache.existsSync(), false);
938 });
939
940 testWithoutContext('pub cache in environment is used', () async {
941 final FileSystem fileSystem = MemoryFileSystem.test();
942 fileSystem.directory('custom/pub-cache/path').createSync(recursive: true);
943 final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
944 const FakeCommand(
945 command: <String>[
946 'bin/cache/dart-sdk/bin/dart',
947 'pub',
948 '--suppress-analytics',
949 '--directory',
950 '.',
951 'get',
952 '--example',
953 ],
954 exitCode: 69,
955 environment: <String, String>{
956 'FLUTTER_ROOT': '',
957 'PUB_ENVIRONMENT': 'flutter_cli:flutter_tests',
958 'PUB_CACHE': 'custom/pub-cache/path',
959 },
960 stdout: "FakeCommand's env successfully matched",
961 ),
962 ]);
963
964 final FakeStdio mockStdio = FakeStdio();
965 final Pub pub = Pub.test(
966 fileSystem: fileSystem,
967 logger: BufferLogger.test(),
968 processManager: processManager,
969 botDetector: const FakeBotDetector(false),
970 stdio: mockStdio,
971 platform: FakePlatform(
972 environment: const <String, String>{'PUB_CACHE': 'custom/pub-cache/path'},
973 ),
974 );
975
976 try {
977 await pub.get(
978 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
979 context: PubContext.flutterTests,
980 );
981 } on ToolExit {
982 // Ignore.
983 }
984
985 expect(mockStdio.stdout.writes.map(utf8.decode), <String>[
986 "FakeCommand's env successfully matched",
987 ]);
988 expect(processManager, hasNoRemainingExpectations);
989 });
990
991 testUsingContext(
992 'package_config_subset file is generated from packages and not timestamp',
993 () async {
994 final FileSystem fileSystem = MemoryFileSystem.test();
995 final Pub pub = Pub.test(
996 fileSystem: fileSystem,
997 logger: BufferLogger.test(),
998 processManager: FakeProcessManager.any(),
999 botDetector: const FakeBotDetector(false),
1000 stdio: FakeStdio(),
1001 platform: FakePlatform(
1002 environment: const <String, String>{'PUB_CACHE': 'custom/pub-cache/path'},
1003 ),
1004 );
1005 fileSystem.file('version').createSync();
1006 fileSystem.file('pubspec.yaml')
1007 ..createSync()
1008 ..writeAsStringSync('''
1009 flutter:
1010 generate: true
1011 ''');
1012 fileSystem.file('.dart_tool/package_config.json')
1013 ..createSync(recursive: true)
1014 ..writeAsStringSync('''
1015 {"configVersion": 2,"packages": [
1016 {
1017 "name": "flutter_tools",
1018 "rootUri": "../",
1019 "packageUri": "lib/",
1020 "languageVersion": "2.7"
1021 }
1022 ],"generated":"some-time"}
1023''');
1024
1025 await pub.get(
1026 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
1027 context: PubContext.flutterTests,
1028 );
1029
1030 expect(
1031 fileSystem.file('.dart_tool/package_config_subset').readAsStringSync(),
1032 'flutter_tools\n'
1033 '2.7\n'
1034 'file:///\n'
1035 'file:///lib/\n'
1036 '2\n',
1037 );
1038 },
1039 overrides: <Type, Generator>{
1040 // ignore: avoid_redundant_argument_values
1041 FeatureFlags: () => TestFeatureFlags(isExplicitPackageDependenciesEnabled: false),
1042 },
1043 );
1044
1045 testUsingContext(
1046 'cannot use `generate: true` with a workspace without --explicit-package-dependencies',
1047 () async {
1048 final FileSystem fileSystem = MemoryFileSystem.test();
1049 final Pub pub = Pub.test(
1050 fileSystem: fileSystem,
1051 logger: BufferLogger.test(),
1052 processManager: FakeProcessManager.any(),
1053 botDetector: const FakeBotDetector(false),
1054 stdio: FakeStdio(),
1055 platform: FakePlatform(
1056 environment: const <String, String>{'PUB_CACHE': 'custom/pub-cache/path'},
1057 ),
1058 );
1059
1060 final Directory pkg = fileSystem.directory('workspace_pkg')..createSync(recursive: true);
1061 fileSystem.file('version').createSync();
1062 pkg.childFile('pubspec.yaml')
1063 ..createSync()
1064 ..writeAsStringSync('''
1065 flutter:
1066 generate: true
1067 ''');
1068 fileSystem.file('.dart_tool/package_config.json')
1069 ..createSync(recursive: true)
1070 ..writeAsStringSync('''
1071 {"configVersion": 2,"packages": [
1072 {
1073 "name": "flutter_tools",
1074 "rootUri": "../",
1075 "packageUri": "lib/",
1076 "languageVersion": "2.7"
1077 }
1078 ],"generated":"some-time"}
1079''');
1080
1081 await expectLater(
1082 pub.get(project: FlutterProject.fromDirectoryTest(pkg), context: PubContext.flutterTests),
1083 throwsToolExit(message: '`generate: true` is not supported within workspaces unless'),
1084 );
1085 },
1086 overrides: <Type, Generator>{
1087 // ignore: avoid_redundant_argument_values
1088 FeatureFlags: () => TestFeatureFlags(isExplicitPackageDependenciesEnabled: false),
1089 },
1090 );
1091
1092 testUsingContext(
1093 'can use `generate: true` with a workspace with --explicit-package-dependencies',
1094 () async {
1095 final FileSystem fileSystem = MemoryFileSystem.test();
1096 final Pub pub = Pub.test(
1097 fileSystem: fileSystem,
1098 logger: BufferLogger.test(),
1099 processManager: FakeProcessManager.any(),
1100 botDetector: const FakeBotDetector(false),
1101 stdio: FakeStdio(),
1102 platform: FakePlatform(
1103 environment: const <String, String>{'PUB_CACHE': 'custom/pub-cache/path'},
1104 ),
1105 );
1106
1107 final Directory pkg = fileSystem.directory('workspace_pkg')..createSync(recursive: true);
1108 fileSystem.file('version').createSync();
1109 pkg.childFile('pubspec.yaml')
1110 ..createSync()
1111 ..writeAsStringSync('''
1112 flutter:
1113 generate: true
1114 ''');
1115 fileSystem.file('.dart_tool/package_config.json')
1116 ..createSync(recursive: true)
1117 ..writeAsStringSync('''
1118 {"configVersion": 2,"packages": [
1119 {
1120 "name": "flutter_tools",
1121 "rootUri": "../",
1122 "packageUri": "lib/",
1123 "languageVersion": "2.7"
1124 }
1125 ],"generated":"some-time"}
1126''');
1127
1128 await expectLater(
1129 pub.get(project: FlutterProject.fromDirectoryTest(pkg), context: PubContext.flutterTests),
1130 completes,
1131 );
1132 },
1133 overrides: <Type, Generator>{
1134 // ignore: avoid_redundant_argument_values
1135 FeatureFlags: () => TestFeatureFlags(isExplicitPackageDependenciesEnabled: true),
1136 },
1137 );
1138
1139 testWithoutContext('Pub error handling', () async {
1140 final BufferLogger logger = BufferLogger.test();
1141 final MemoryFileSystem fileSystem = MemoryFileSystem.test();
1142 final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
1143 FakeCommand(
1144 command: const <String>[
1145 'bin/cache/dart-sdk/bin/dart',
1146 'pub',
1147 '--suppress-analytics',
1148 '--directory',
1149 '.',
1150 'get',
1151 '--example',
1152 ],
1153 onRun: (_) {
1154 fileSystem.file('.dart_tool/package_config.json').setLastModifiedSync(DateTime(2002));
1155 },
1156 ),
1157 const FakeCommand(
1158 command: <String>[
1159 'bin/cache/dart-sdk/bin/dart',
1160 'pub',
1161 '--suppress-analytics',
1162 '--directory',
1163 '.',
1164 'get',
1165 '--example',
1166 ],
1167 ),
1168 FakeCommand(
1169 command: const <String>[
1170 'bin/cache/dart-sdk/bin/dart',
1171 'pub',
1172 '--suppress-analytics',
1173 '--directory',
1174 '.',
1175 'get',
1176 '--example',
1177 ],
1178 onRun: (_) {
1179 fileSystem.file('pubspec.yaml').setLastModifiedSync(DateTime(2002));
1180 },
1181 ),
1182 const FakeCommand(
1183 command: <String>[
1184 'bin/cache/dart-sdk/bin/dart',
1185 'pub',
1186 '--suppress-analytics',
1187 '--directory',
1188 '.',
1189 'get',
1190 '--example',
1191 ],
1192 ),
1193 ]);
1194 final Pub pub = Pub.test(
1195 fileSystem: fileSystem,
1196 logger: logger,
1197 processManager: processManager,
1198 platform: FakePlatform(environment: <String, String>{}),
1199 botDetector: const FakeBotDetector(false),
1200 stdio: FakeStdio(),
1201 );
1202
1203 fileSystem.file('version').createSync();
1204 // the good scenario: .packages is old, pub updates the file.
1205 fileSystem.file('.dart_tool/package_config.json')
1206 ..createSync(recursive: true)
1207 ..setLastModifiedSync(DateTime(2000));
1208 fileSystem.file('pubspec.yaml')
1209 ..createSync()
1210 ..setLastModifiedSync(DateTime(2001));
1211 await pub.get(
1212 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
1213 context: PubContext.flutterTests,
1214 ); // pub sets date of .packages to 2002
1215
1216 expect(logger.errorText, isEmpty);
1217 expect(
1218 fileSystem.file('pubspec.yaml').lastModifiedSync(),
1219 DateTime(2001),
1220 ); // because nothing should touch it
1221 logger.clear();
1222
1223 // bad scenario 1: pub doesn't update file; doesn't matter, because we do instead
1224 fileSystem.file('.dart_tool/package_config.json').setLastModifiedSync(DateTime(2000));
1225 fileSystem.file('pubspec.yaml').setLastModifiedSync(DateTime(2001));
1226 await pub.get(
1227 project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
1228 context: PubContext.flutterTests,
1229 ); // pub does nothing
1230
1231 expect(logger.statusText, isEmpty);
1232 expect(logger.errorText, isEmpty);
1233 expect(
1234 fileSystem.file('pubspec.yaml').lastModifiedSync(),
1235 DateTime(2001),
1236 ); // because nothing should touch it
1237 logger.clear();
1238 });
1239}
1240

Provided by KDAB

Privacy Policy
Learn more about Flutter for embedded and desktop on industrialflutter.com