Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 499edda

Browse files
authored
[et] Fix concurrent modification exception (#52247)
We cannot modify the list of build targets as we're iterating over it. Instead of removing non-test/non-executable elements, instead we add executable test targets to a separate testTargets list and use that. Noticed while working on: flutter/flutter#147071 [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent ca4d5c8 commit 499edda

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

tools/engine_tool/lib/src/commands/test_command.dart

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,18 +70,18 @@ et test //flutter/fml:fml_benchmarks # Run a single test target in `//flutter/f
7070
);
7171
}
7272

73+
final List<BuildTarget> testTargets = <BuildTarget>[];
7374
for (final BuildTarget target in selectedTargets) {
74-
if (!target.testOnly || target.type != BuildTargetType.executable) {
75-
// Remove any targets that aren't testOnly and aren't executable.
76-
selectedTargets.remove(target);
75+
if (_isTestExecutable(target)) {
76+
testTargets.add(target);
7777
}
7878
if (target.executable == null) {
7979
environment.logger.fatal(
8080
'$target is an executable but is missing the executable path');
8181
}
8282
}
8383
// Chop off the '//' prefix.
84-
final List<String> buildTargets = selectedTargets
84+
final List<String> buildTargets = testTargets
8585
.map<String>(
8686
(BuildTarget target) => target.label.substring('//'.length))
8787
.toList();
@@ -95,11 +95,16 @@ et test //flutter/fml:fml_benchmarks # Run a single test target in `//flutter/f
9595
final WorkerPool workerPool =
9696
WorkerPool(environment, ProcessTaskProgressReporter(environment));
9797
final Set<ProcessTask> tasks = <ProcessTask>{};
98-
for (final BuildTarget target in selectedTargets) {
98+
for (final BuildTarget target in testTargets) {
9999
final List<String> commandLine = <String>[target.executable!.path];
100100
tasks.add(ProcessTask(
101101
target.label, environment, environment.engine.srcDir, commandLine));
102102
}
103103
return await workerPool.run(tasks) ? 0 : 1;
104104
}
105+
106+
/// Returns true if `target` is a testonly executable.
107+
static bool _isTestExecutable(BuildTarget target) {
108+
return target.testOnly && target.type == BuildTargetType.executable;
109+
}
105110
}

tools/engine_tool/test/test_command_test.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,28 @@ void main() {
6767
testEnvironment.cleanup();
6868
}
6969
});
70+
71+
test('test command skips non-testonly executables', () async {
72+
final TestEnvironment testEnvironment = TestEnvironment.withTestEngine(
73+
cannedProcesses: cannedProcesses,
74+
);
75+
try {
76+
final Environment env = testEnvironment.environment;
77+
final ToolCommandRunner runner = ToolCommandRunner(
78+
environment: env,
79+
configs: configs,
80+
);
81+
final int result = await runner.run(<String>[
82+
'test',
83+
'//third_party/protobuf:protoc',
84+
]);
85+
expect(result, equals(1));
86+
expect(testEnvironment.processHistory.length, lessThan(3));
87+
expect(testEnvironment.processHistory.where((ExecutedProcess process) {
88+
return process.command[0].contains('protoc');
89+
}), isEmpty);
90+
} finally {
91+
testEnvironment.cleanup();
92+
}
93+
});
7094
}

0 commit comments

Comments
 (0)