22// Use of this source code is governed by a BSD-style license that can be 
33// found in the LICENSE file. 
44
5+ import  'package:args/command_runner.dart' ;
6+ import  'package:flutter_tools/src/application_package.dart' ;
57import  'package:flutter_tools/src/base/common.dart' ;
68import  'package:flutter_tools/src/build_info.dart' ;
9+ import  'package:flutter_tools/src/cache.dart' ;
710import  'package:flutter_tools/src/commands/run.dart' ;
811import  'package:flutter_tools/src/device.dart' ;
912import  'package:flutter_tools/src/runner/flutter_command.dart' ;
13+ import  'package:flutter_tools/src/version.dart' ;
1014import  'package:mockito/mockito.dart' ;
1115
1216import  '../src/common.dart' ;
1317import  '../src/context.dart' ;
1418import  '../src/mocks.dart' ;
1519
1620void  main () {
17-   final  MockDeviceManager  mockDeviceManager =  MockDeviceManager ();
18- 
1921  group ('run' , () {
22+     MockApplicationPackageFactory  mockApplicationPackageFactory;
23+     MockDeviceManager  mockDeviceManager;
24+     MockFlutterVersion  mockStableFlutterVersion;
25+     MockFlutterVersion  mockUnstableFlutterVersion;
26+ 
27+     setUpAll (() {
28+       Cache .disableLocking ();
29+       mockApplicationPackageFactory =  MockApplicationPackageFactory ();
30+       mockDeviceManager =  MockDeviceManager ();
31+       mockStableFlutterVersion =  MockFlutterVersion (isStable:  true );
32+       mockUnstableFlutterVersion =  MockFlutterVersion (isStable:  false );
33+     });
34+ 
2035    testUsingContext ('fails when target not found' , () async  {
2136      final  RunCommand  command =  RunCommand ();
2237      applyMocksToCommand (command);
@@ -28,6 +43,92 @@ void main() {
2843      }
2944    });
3045
46+ 
47+     group ('dart-flags option' , () {
48+       setUpAll (() {
49+         when (mockDeviceManager.getDevices ()).thenAnswer ((Invocation  invocation) {
50+           return  Stream <Device >.fromIterable (< Device > [
51+             FakeDevice (),
52+           ]);
53+         });
54+       });
55+ 
56+       RunCommand  command;
57+       List <String > args;
58+       setUp (() {
59+         command =  TestRunCommand ();
60+         args =  < String >  [
61+           'run' ,
62+           '--dart-flags' , '"--observe"' ,
63+           '--no-hot' ,
64+         ];
65+       });
66+ 
67+       testUsingContext ('is not available on stable channel' , () async  {
68+         // Stable branch. 
69+         try  {
70+           await  createTestCommandRunner (command).run (args);
71+           fail ('Expect exception' );
72+         // ignore: unused_catch_clause 
73+         } on  UsageException  catch (e) {
74+           // Not available while on stable branch. 
75+         }
76+       }, overrides:  < Type , Generator > {
77+         DeviceManager :  () =>  mockDeviceManager,
78+         FlutterVersion :  () =>  mockStableFlutterVersion,
79+       });
80+ 
81+       testUsingContext ('is populated in debug mode' , () async  {
82+         // FakeDevice.startApp checks that --dart-flags doesn't get dropped and 
83+         // throws ToolExit with FakeDevice.kSuccess if the flag is populated. 
84+         try  {
85+           await  createTestCommandRunner (command).run (args);
86+           fail ('Expect exception' );
87+         } on  ToolExit  catch  (e) {
88+           expect (e.exitCode, FakeDevice .kSuccess);
89+         }
90+       }, overrides:  < Type , Generator > {
91+         ApplicationPackageFactory :  () =>  mockApplicationPackageFactory,
92+         DeviceManager :  () =>  mockDeviceManager,
93+         FlutterVersion :  () =>  mockUnstableFlutterVersion,
94+       });
95+ 
96+       testUsingContext ('is populated in profile mode' , () async  {
97+         args.add ('--profile' );
98+ 
99+         // FakeDevice.startApp checks that --dart-flags doesn't get dropped and 
100+         // throws ToolExit with FakeDevice.kSuccess if the flag is populated. 
101+         try  {
102+           await  createTestCommandRunner (command).run (args);
103+           fail ('Expect exception' );
104+         } on  ToolExit  catch  (e) {
105+           expect (e.exitCode, FakeDevice .kSuccess);
106+         }
107+       }, overrides:  < Type , Generator > {
108+         ApplicationPackageFactory :  () =>  mockApplicationPackageFactory,
109+         DeviceManager :  () =>  mockDeviceManager,
110+         FlutterVersion :  () =>  mockUnstableFlutterVersion,
111+       });
112+ 
113+       testUsingContext ('is not populated in release mode' , () async  {
114+         args.add ('--release' );
115+ 
116+         // FakeDevice.startApp checks that --dart-flags *does* get dropped and 
117+         // throws ToolExit with FakeDevice.kSuccess if the flag is set to the 
118+         // empty string. 
119+         try  {
120+           await  createTestCommandRunner (command).run (args);
121+           fail ('Expect exception' );
122+         } on  ToolExit  catch  (e) {
123+           expect (e.exitCode, FakeDevice .kSuccess);
124+         }
125+       }, overrides:  < Type , Generator > {
126+         ApplicationPackageFactory :  () =>  mockApplicationPackageFactory,
127+         DeviceManager :  () =>  mockDeviceManager,
128+         FlutterVersion :  () =>  mockUnstableFlutterVersion,
129+       });
130+     });
131+ 
31132    testUsingContext ('should only request artifacts corresponding to connected devices' , () async  {
32133      when (mockDeviceManager.getDevices ()).thenAnswer ((Invocation  invocation) {
33134        return  Stream <Device >.fromIterable (< Device > [
@@ -89,3 +190,73 @@ class MockDevice extends Mock implements Device {
89190  @override 
90191  Future <TargetPlatform > get  targetPlatform async  =>  _targetPlatform;
91192}
193+ 
194+ class  TestRunCommand  extends  RunCommand  {
195+   @override 
196+   // ignore: must_call_super 
197+   Future <void > validateCommand () async  {
198+     devices =  await  deviceManager.getDevices ().toList ();
199+   }
200+ }
201+ 
202+ class  MockStableFlutterVersion  extends  MockFlutterVersion  {
203+   @override 
204+   bool  get  isStable =>  true ;
205+ }
206+ 
207+ class  FakeDevice  extends  Fake  implements  Device  {
208+   static  const  int  kSuccess =  1 ;
209+   static  const  int  kFailure =  - 1 ;
210+   final  TargetPlatform  _targetPlatform =  TargetPlatform .ios;
211+ 
212+   void  _throwToolExit (int  code) =>  throwToolExit (null , exitCode:  code);
213+ 
214+   @override 
215+   Future <bool > get  isLocalEmulator =>  Future <bool >.value (false );
216+ 
217+   @override 
218+   bool  get  supportsHotReload =>  false ;
219+ 
220+   @override 
221+   Future <String > get  sdkNameAndVersion =>  Future <String >.value ('' );
222+ 
223+   @override 
224+   DeviceLogReader  getLogReader ({ ApplicationPackage  app }) {
225+     return  MockDeviceLogReader ();
226+   }
227+ 
228+   @override 
229+   String  get  name =>  'FakeDevice' ;
230+ 
231+   @override 
232+   Future <TargetPlatform > get  targetPlatform async  =>  _targetPlatform;
233+ 
234+   @override 
235+   Future <LaunchResult > startApp (
236+     ApplicationPackage  package, {
237+     String  mainPath,
238+     String  route,
239+     DebuggingOptions  debuggingOptions,
240+     Map <String , dynamic > platformArgs,
241+     bool  prebuiltApplication =  false ,
242+     bool  usesTerminalUi =  true ,
243+     bool  ipv6 =  false ,
244+   }) async  {
245+     final  String  dartFlags =  debuggingOptions.dartFlags;
246+     // In release mode, --dart-flags should be set to the empty string and 
247+     // provided flags should be dropped. In debug and profile modes, 
248+     // --dart-flags should not be empty. 
249+     if  (debuggingOptions.buildInfo.isRelease) {
250+       if  (dartFlags.isNotEmpty) {
251+         _throwToolExit (kFailure);
252+       }
253+       _throwToolExit (kSuccess);
254+     } else  {
255+       if  (dartFlags.isEmpty) {
256+         _throwToolExit (kFailure);
257+       }
258+       _throwToolExit (kSuccess);
259+     }
260+     return  null ;
261+   }
262+ }
0 commit comments