Skip to content

Commit 78d924a

Browse files
authored
[flutter_tools] [dap] Add support for passing env variables to spawned processes (#107415)
* [flutter_tools] [dap] Add support for passing env variables to spawned processes * Use named args * Use in-memory fs and FakePlatform * Pass filesystem style to MemoryFileSystem
1 parent 66cd09d commit 78d924a

File tree

6 files changed

+166
-35
lines changed

6 files changed

+166
-35
lines changed

packages/flutter_tools/lib/src/debug_adapters/flutter_adapter.dart

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,11 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
305305
...?userArgs,
306306
];
307307

308-
await launchAsProcess(executable, processArgs);
308+
await launchAsProcess(
309+
executable: executable,
310+
processArgs: processArgs,
311+
env: args.env,
312+
);
309313

310314
// Delay responding until the app is launched and (optionally) the debugger
311315
// is connected.
@@ -316,12 +320,17 @@ class FlutterDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArguments
316320
}
317321

318322
@visibleForOverriding
319-
Future<void> launchAsProcess(String executable, List<String> processArgs) async {
323+
Future<void> launchAsProcess({
324+
required String executable,
325+
required List<String> processArgs,
326+
required Map<String, String>? env,
327+
}) async {
320328
logger?.call('Spawning $executable with $processArgs in ${args.cwd}');
321329
final Process process = await Process.start(
322330
executable,
323331
processArgs,
324332
workingDirectory: args.cwd,
333+
environment: env,
325334
);
326335
_process = process;
327336
pidsToTerminate.add(process.pid);

packages/flutter_tools/lib/src/debug_adapters/flutter_adapter_args.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class FlutterAttachRequestArguments
2020
super.restart,
2121
super.name,
2222
super.cwd,
23+
super.env,
2324
super.additionalProjectPaths,
2425
super.debugSdkLibraries,
2526
super.debugExternalPackageLibraries,
@@ -91,6 +92,7 @@ class FlutterLaunchRequestArguments
9192
super.restart,
9293
super.name,
9394
super.cwd,
95+
super.env,
9496
super.additionalProjectPaths,
9597
super.debugSdkLibraries,
9698
super.debugExternalPackageLibraries,

packages/flutter_tools/lib/src/debug_adapters/flutter_test_adapter.dart

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,11 @@ class FlutterTestDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArgum
135135
...?args.args,
136136
];
137137

138-
await launchAsProcess(executable, processArgs);
138+
await launchAsProcess(
139+
executable: executable,
140+
processArgs: processArgs,
141+
env: args.env,
142+
);
139143

140144
// Delay responding until the debugger is connected.
141145
if (debug) {
@@ -144,12 +148,17 @@ class FlutterTestDebugAdapter extends DartDebugAdapter<FlutterLaunchRequestArgum
144148
}
145149

146150
@visibleForOverriding
147-
Future<void> launchAsProcess(String executable, List<String> processArgs) async {
151+
Future<void> launchAsProcess({
152+
required String executable,
153+
required List<String> processArgs,
154+
required Map<String, String>? env,
155+
}) async {
148156
logger?.call('Spawning $executable with $processArgs in ${args.cwd}');
149157
final Process process = await Process.start(
150158
executable,
151159
processArgs,
152160
workingDirectory: args.cwd,
161+
environment: env,
153162
);
154163
_process = process;
155164
pidsToTerminate.add(process.pid);

packages/flutter_tools/test/general.shard/dap/flutter_adapter_test.dart

Lines changed: 79 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,39 @@
44

55
import 'dart:async';
66

7+
import 'package:file/memory.dart';
8+
import 'package:flutter_tools/src/base/platform.dart';
79
import 'package:flutter_tools/src/cache.dart';
810
import 'package:flutter_tools/src/debug_adapters/flutter_adapter_args.dart';
9-
import 'package:flutter_tools/src/globals.dart' as globals;
11+
import 'package:flutter_tools/src/globals.dart' as globals show platform;
1012
import 'package:test/fake.dart';
1113
import 'package:test/test.dart';
1214
import 'package:vm_service/vm_service.dart';
1315

1416
import 'mocks.dart';
1517

1618
void main() {
19+
// Use the real platform as a base so that Windows bots test paths.
20+
final FakePlatform platform = FakePlatform.fromPlatform(globals.platform);
21+
final FileSystemStyle fsStyle = platform.isWindows ? FileSystemStyle.windows : FileSystemStyle.posix;
22+
1723
group('flutter adapter', () {
18-
final String expectedFlutterExecutable = globals.platform.isWindows
24+
final String expectedFlutterExecutable = platform.isWindows
1925
? r'C:\fake\flutter\bin\flutter.bat'
2026
: '/fake/flutter/bin/flutter';
2127

2228
setUpAll(() {
23-
Cache.flutterRoot = globals.platform.isWindows
29+
Cache.flutterRoot = platform.isWindows
2430
? r'C:\fake\flutter'
2531
: '/fake/flutter';
2632
});
2733

28-
29-
group('launchRequest', () {
30-
test('runs "flutter run" with --machine', () async {
31-
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform);
34+
group('launchRequest', () {
35+
test('runs "flutter run" with --machine', () async {
36+
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
37+
fileSystem: MemoryFileSystem.test(style: fsStyle),
38+
platform: platform,
39+
);
3240
final Completer<void> responseCompleter = Completer<void>();
3341

3442
final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
@@ -43,8 +51,33 @@ void main() {
4351
expect(adapter.processArgs, containsAllInOrder(<String>['run', '--machine']));
4452
});
4553

54+
test('includes env variables', () async {
55+
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
56+
fileSystem: MemoryFileSystem.test(style: fsStyle),
57+
platform: platform,
58+
);
59+
final Completer<void> responseCompleter = Completer<void>();
60+
61+
final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
62+
cwd: '/project',
63+
program: 'foo.dart',
64+
env: <String, String>{
65+
'MY_TEST_ENV': 'MY_TEST_VALUE',
66+
},
67+
);
68+
69+
await adapter.configurationDoneRequest(MockRequest(), null, () {});
70+
await adapter.launchRequest(MockRequest(), args, responseCompleter.complete);
71+
await responseCompleter.future;
72+
73+
expect(adapter.env!['MY_TEST_ENV'], 'MY_TEST_VALUE');
74+
});
75+
4676
test('does not record the VMs PID for terminating', () async {
47-
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform);
77+
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
78+
fileSystem: MemoryFileSystem.test(style: fsStyle),
79+
platform: platform,
80+
);
4881
final Completer<void> responseCompleter = Completer<void>();
4982

5083
final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
@@ -65,10 +98,12 @@ void main() {
6598
});
6699
});
67100

68-
69-
group('attachRequest', () {
70-
test('runs "flutter attach" with --machine', () async {
71-
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform);
101+
group('attachRequest', () {
102+
test('runs "flutter attach" with --machine', () async {
103+
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
104+
fileSystem: MemoryFileSystem.test(style: fsStyle),
105+
platform: platform,
106+
);
72107
final Completer<void> responseCompleter = Completer<void>();
73108

74109
final FlutterAttachRequestArguments args = FlutterAttachRequestArguments(
@@ -83,7 +118,10 @@ void main() {
83118
});
84119

85120
test('does not record the VMs PID for terminating', () async {
86-
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform);
121+
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
122+
fileSystem: MemoryFileSystem.test(style: fsStyle),
123+
platform: platform,
124+
);
87125
final Completer<void> responseCompleter = Completer<void>();
88126

89127
final FlutterAttachRequestArguments args = FlutterAttachRequestArguments(
@@ -105,7 +143,10 @@ void main() {
105143

106144
group('--start-paused', () {
107145
test('is passed for debug mode', () async {
108-
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform);
146+
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
147+
fileSystem: MemoryFileSystem.test(style: fsStyle),
148+
platform: platform,
149+
);
109150
final Completer<void> responseCompleter = Completer<void>();
110151

111152
final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
@@ -121,7 +162,10 @@ void main() {
121162
});
122163

123164
test('is not passed for noDebug mode', () async {
124-
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform);
165+
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
166+
fileSystem: MemoryFileSystem.test(style: fsStyle),
167+
platform: platform,
168+
);
125169
final Completer<void> responseCompleter = Completer<void>();
126170

127171
final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
@@ -138,7 +182,10 @@ void main() {
138182
});
139183

140184
test('is not passed if toolArgs contains --profile', () async {
141-
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform);
185+
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
186+
fileSystem: MemoryFileSystem.test(style: fsStyle),
187+
platform: platform,
188+
);
142189
final Completer<void> responseCompleter = Completer<void>();
143190

144191
final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
@@ -155,7 +202,10 @@ void main() {
155202
});
156203

157204
test('is not passed if toolArgs contains --release', () async {
158-
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform);
205+
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
206+
fileSystem: MemoryFileSystem.test(style: fsStyle),
207+
platform: platform,
208+
);
159209
final Completer<void> responseCompleter = Completer<void>();
160210

161211
final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
@@ -173,7 +223,10 @@ void main() {
173223
});
174224

175225
test('includes toolArgs', () async {
176-
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform);
226+
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
227+
fileSystem: MemoryFileSystem.test(style: fsStyle),
228+
platform: platform,
229+
);
177230
final Completer<void> responseCompleter = Completer<void>();
178231

179232
final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
@@ -193,7 +246,10 @@ void main() {
193246

194247
group('includes customTool', () {
195248
test('with no args replaced', () async {
196-
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform);
249+
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
250+
fileSystem: MemoryFileSystem.test(style: fsStyle),
251+
platform: platform,
252+
);
197253
final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
198254
cwd: '/project',
199255
program: 'foo.dart',
@@ -212,7 +268,10 @@ void main() {
212268
});
213269

214270
test('with all args replaced', () async {
215-
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(fileSystem: globals.fs, platform: globals.platform);
271+
final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
272+
fileSystem: MemoryFileSystem.test(style: fsStyle),
273+
platform: platform,
274+
);
216275
final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
217276
cwd: '/project',
218277
program: 'foo.dart',

packages/flutter_tools/test/general.shard/dap/flutter_test_adapter_test.dart

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,35 @@
44

55
import 'dart:async';
66

7+
import 'package:file/memory.dart';
8+
import 'package:flutter_tools/src/base/platform.dart';
79
import 'package:flutter_tools/src/cache.dart';
810
import 'package:flutter_tools/src/debug_adapters/flutter_adapter_args.dart';
9-
import 'package:flutter_tools/src/globals.dart' as globals;
11+
import 'package:flutter_tools/src/globals.dart' as globals show platform;
1012
import 'package:test/test.dart';
1113

1214
import 'mocks.dart';
1315

1416
void main() {
17+
// Use the real platform as a base so that Windows bots test paths.
18+
final FakePlatform platform = FakePlatform.fromPlatform(globals.platform);
19+
final FileSystemStyle fsStyle = platform.isWindows ? FileSystemStyle.windows : FileSystemStyle.posix;
20+
1521
group('flutter test adapter', () {
16-
final String expectedFlutterExecutable = globals.platform.isWindows
22+
final String expectedFlutterExecutable = platform.isWindows
1723
? r'C:\fake\flutter\bin\flutter.bat'
1824
: '/fake/flutter/bin/flutter';
1925

2026
setUpAll(() {
21-
Cache.flutterRoot = globals.platform.isWindows
27+
Cache.flutterRoot = platform.isWindows
2228
? r'C:\fake\flutter'
2329
: '/fake/flutter';
2430
});
2531

2632
test('includes toolArgs', () async {
2733
final MockFlutterTestDebugAdapter adapter = MockFlutterTestDebugAdapter(
28-
fileSystem: globals.fs,
29-
platform: globals.platform,
34+
fileSystem: MemoryFileSystem.test(style: fsStyle),
35+
platform: platform,
3036
);
3137
final Completer<void> responseCompleter = Completer<void>();
3238
final MockRequest request = MockRequest();
@@ -45,10 +51,34 @@ void main() {
4551
expect(adapter.processArgs, contains('tool_arg'));
4652
});
4753

54+
test('includes env variables', () async {
55+
final MockFlutterTestDebugAdapter adapter = MockFlutterTestDebugAdapter(
56+
fileSystem: MemoryFileSystem.test(style: fsStyle),
57+
platform: platform,
58+
);
59+
final Completer<void> responseCompleter = Completer<void>();
60+
final MockRequest request = MockRequest();
61+
final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
62+
cwd: '/project',
63+
program: 'foo.dart',
64+
env: <String, String>{
65+
'MY_TEST_ENV': 'MY_TEST_VALUE',
66+
},
67+
);
68+
69+
await adapter.configurationDoneRequest(request, null, () {});
70+
await adapter.launchRequest(request, args, responseCompleter.complete);
71+
await responseCompleter.future;
72+
73+
expect(adapter.env!['MY_TEST_ENV'], 'MY_TEST_VALUE');
74+
});
75+
4876
group('includes customTool', () {
4977
test('with no args replaced', () async {
50-
final MockFlutterTestDebugAdapter adapter = MockFlutterTestDebugAdapter(fileSystem: globals.fs,
51-
platform: globals.platform,);
78+
final MockFlutterTestDebugAdapter adapter = MockFlutterTestDebugAdapter(
79+
fileSystem: MemoryFileSystem.test(style: fsStyle),
80+
platform: platform,
81+
);
5282
final Completer<void> responseCompleter = Completer<void>();
5383
final MockRequest request = MockRequest();
5484
final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
@@ -68,8 +98,10 @@ void main() {
6898
});
6999

70100
test('with all args replaced', () async {
71-
final MockFlutterTestDebugAdapter adapter = MockFlutterTestDebugAdapter(fileSystem: globals.fs,
72-
platform: globals.platform,);
101+
final MockFlutterTestDebugAdapter adapter = MockFlutterTestDebugAdapter(
102+
fileSystem: MemoryFileSystem.test(style: fsStyle),
103+
platform: platform,
104+
);
73105
final Completer<void> responseCompleter = Completer<void>();
74106
final MockRequest request = MockRequest();
75107
final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(

0 commit comments

Comments
 (0)