@@ -10,6 +10,7 @@ import 'package:flutter_tools/src/artifacts.dart';
10
10
import 'package:flutter_tools/src/base/bot_detector.dart' ;
11
11
import 'package:flutter_tools/src/base/file_system.dart' ;
12
12
import 'package:flutter_tools/src/base/io.dart' as io;
13
+ import 'package:flutter_tools/src/base/logger.dart' ;
13
14
import 'package:flutter_tools/src/base/net.dart' ;
14
15
import 'package:flutter_tools/src/base/platform.dart' ;
15
16
import 'package:flutter_tools/src/base/process.dart' ;
@@ -19,6 +20,7 @@ import 'package:flutter_tools/src/globals.dart' as globals;
19
20
import 'package:flutter_tools/src/reporting/crash_reporting.dart' ;
20
21
import 'package:flutter_tools/src/reporting/reporting.dart' ;
21
22
import 'package:flutter_tools/src/runner/flutter_command.dart' ;
23
+ import 'package:test/fake.dart' ;
22
24
import 'package:unified_analytics/unified_analytics.dart' ;
23
25
24
26
import '../../src/common.dart' ;
@@ -29,12 +31,10 @@ import '../../src/fakes.dart';
29
31
const String kCustomBugInstructions = 'These are instructions to report with a custom bug tracker.' ;
30
32
31
33
void main () {
32
- int ? firstExitCode;
33
- late MemoryFileSystem fileSystem;
34
-
35
- group ('runner' , () {
34
+ group ('runner (crash reporting)' , () {
35
+ int ? firstExitCode;
36
+ late MemoryFileSystem fileSystem;
36
37
late FakeAnalytics fakeAnalytics;
37
- late TestUsage testUsage;
38
38
39
39
setUp (() {
40
40
// Instead of exiting with dart:io exit(), this causes an exception to
@@ -59,8 +59,6 @@ void main() {
59
59
fs: fileSystem,
60
60
fakeFlutterVersion: FakeFlutterVersion (),
61
61
);
62
-
63
- testUsage = TestUsage ();
64
62
});
65
63
66
64
tearDown (() {
@@ -327,10 +325,84 @@ void main() {
327
325
HttpClientFactory : () => () => FakeHttpClient .any (),
328
326
});
329
327
});
328
+ });
330
329
331
- testUsingContext ('do not print welcome on bots' , () async {
332
- io.setExitFunctionForTests ((int exitCode) {});
330
+ group ('runner' , () {
331
+ late MemoryFileSystem fs;
332
+
333
+ setUp (() {
334
+ io.setExitFunctionForTests ((int exitCode) {});
333
335
336
+ fs = MemoryFileSystem .test ();
337
+
338
+ Cache .disableLocking ();
339
+ });
340
+
341
+ tearDown (() {
342
+ io.restoreExitFunction ();
343
+ Cache .enableLocking ();
344
+ });
345
+
346
+ testUsingContext ("catches ProcessException calling git because it's not available" , () async {
347
+ final _GitNotFoundFlutterCommand command = _GitNotFoundFlutterCommand ();
348
+
349
+ await runner.run (
350
+ < String > [command.name],
351
+ () => < FlutterCommand > [
352
+ command,
353
+ ],
354
+ // This flutterVersion disables crash reporting.
355
+ flutterVersion: '[user-branch]/' ,
356
+ reportCrashes: false ,
357
+ shutdownHooks: ShutdownHooks (),
358
+ );
359
+
360
+ expect (
361
+ (globals.logger as BufferLogger ).errorText,
362
+ 'Failed to find "git" in the search path.\n '
363
+ '\n '
364
+ 'An error was encountered when trying to run git.\n '
365
+ "Please ensure git is installed and available in your system's search path. "
366
+ 'See https://docs.flutter.dev/get-started/install for instructions on installing git for your platform.\n ' );
367
+ },
368
+ overrides: < Type , Generator > {
369
+ FileSystem : () => fs,
370
+ Artifacts : () => Artifacts .test (),
371
+ ProcessManager : () =>
372
+ FakeProcessManager .any ()..excludedExecutables.add ('git' ),
373
+ },
374
+ );
375
+
376
+ testUsingContext ('handles ProcessException calling git when ProcessManager.canRun fails' , () async {
377
+ final _GitNotFoundFlutterCommand command = _GitNotFoundFlutterCommand ();
378
+
379
+ await runner.run (
380
+ < String > [command.name],
381
+ () => < FlutterCommand > [
382
+ command,
383
+ ],
384
+ // This flutterVersion disables crash reporting.
385
+ flutterVersion: '[user-branch]/' ,
386
+ reportCrashes: false ,
387
+ shutdownHooks: ShutdownHooks (),
388
+ );
389
+
390
+ expect (
391
+ (globals.logger as BufferLogger ).errorText,
392
+ 'Failed to find "git" in the search path.\n '
393
+ '\n '
394
+ 'An error was encountered when trying to run git.\n '
395
+ "Please ensure git is installed and available in your system's search path. "
396
+ 'See https://docs.flutter.dev/get-started/install for instructions on installing git for your platform.\n ' );
397
+ },
398
+ overrides: < Type , Generator > {
399
+ FileSystem : () => fs,
400
+ Artifacts : () => Artifacts .test (),
401
+ ProcessManager : () => _ErrorOnCanRunFakeProcessManager (),
402
+ },
403
+ );
404
+
405
+ testUsingContext ('do not print welcome on bots' , () async {
334
406
await runner.run (
335
407
< String > ['--version' , '--machine' ],
336
408
() => < FlutterCommand > [],
@@ -339,13 +411,13 @@ void main() {
339
411
shutdownHooks: ShutdownHooks (),
340
412
);
341
413
342
- expect (testUsage .printedWelcome, false );
414
+ expect ((globals.flutterUsage as TestUsage ) .printedWelcome, false );
343
415
},
344
416
overrides: < Type , Generator > {
345
417
FileSystem : () => MemoryFileSystem .test (),
346
418
ProcessManager : () => FakeProcessManager .any (),
347
419
BotDetector : () => const FakeBotDetector (true ),
348
- Usage : () => testUsage ,
420
+ Usage : () => TestUsage () ,
349
421
},
350
422
);
351
423
});
@@ -570,6 +642,23 @@ class CrashingFlutterCommand extends FlutterCommand {
570
642
}
571
643
}
572
644
645
+ class _GitNotFoundFlutterCommand extends FlutterCommand {
646
+ @override
647
+ String get description => '' ;
648
+
649
+ @override
650
+ String get name => 'git-not-found' ;
651
+
652
+ @override
653
+ Future <FlutterCommandResult > runCommand () {
654
+ throw const io.ProcessException (
655
+ 'git' ,
656
+ < String > ['log' ],
657
+ 'Failed to find "git" in the search path.' ,
658
+ );
659
+ }
660
+ }
661
+
573
662
class CrashingUsage implements Usage {
574
663
CrashingUsage () : _impl = Usage (
575
664
versionOverride: '[user-branch]' ,
@@ -670,3 +759,14 @@ class WaitingCrashReporter implements CrashReporter {
670
759
return _future;
671
760
}
672
761
}
762
+
763
+ class _ErrorOnCanRunFakeProcessManager extends Fake implements FakeProcessManager {
764
+ final FakeProcessManager delegate = FakeProcessManager .any ();
765
+ @override
766
+ bool canRun (dynamic executable, {String ? workingDirectory}) {
767
+ if (executable == 'git' ) {
768
+ throw Exception ("oh no, we couldn't check for git!" );
769
+ }
770
+ return delegate.canRun (executable, workingDirectory: workingDirectory);
771
+ }
772
+ }
0 commit comments