mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Migrate off a global test fixture for build and lint. (flutter/engine#55540)
Partial work towards https://github.com/flutter/flutter/issues/148420, unblocks https://github.com/flutter/engine/pull/55537. These tests can now be more precise, and changing the fixtures no longer has side-effects on tests across the entire repository. There are about 11 other usages (there were ~50 in these) after this PR that I'll get to, as well as the hard-coded `gn desc` output, before retiring `fixtures.dart`
This commit is contained in:
parent
bfd2fa3e8d
commit
842e2fe8f1
@ -3,43 +3,20 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:convert' as convert;
|
||||
import 'dart:ffi';
|
||||
|
||||
import 'package:engine_build_configs/engine_build_configs.dart';
|
||||
import 'package:engine_tool/src/build_utils.dart';
|
||||
import 'package:engine_tool/src/commands/command_runner.dart';
|
||||
import 'package:engine_tool/src/logger.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:platform/platform.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'fixtures.dart' as fixtures;
|
||||
import 'src/test_build_configs.dart';
|
||||
import 'utils.dart';
|
||||
|
||||
void main() {
|
||||
final linuxTestConfig = BuilderConfig.fromJson(
|
||||
path: 'ci/builders/linux_test_config.json',
|
||||
map: convert.jsonDecode(fixtures.testConfig('Linux', Platform.linux))
|
||||
as Map<String, Object?>,
|
||||
);
|
||||
|
||||
final macTestConfig = BuilderConfig.fromJson(
|
||||
path: 'ci/builders/mac_test_config.json',
|
||||
map: convert.jsonDecode(fixtures.testConfig('Mac-12', Platform.macOS))
|
||||
as Map<String, Object?>,
|
||||
);
|
||||
|
||||
final winTestConfig = BuilderConfig.fromJson(
|
||||
path: 'ci/builders/win_test_config.json',
|
||||
map: convert.jsonDecode(fixtures.testConfig('Windows-11', Platform.windows))
|
||||
as Map<String, Object?>,
|
||||
);
|
||||
|
||||
final configs = <String, BuilderConfig>{
|
||||
'linux_test_config': linuxTestConfig,
|
||||
'mac_test_config': macTestConfig,
|
||||
'win_test_config': winTestConfig,
|
||||
};
|
||||
|
||||
final cannedProcesses = [
|
||||
CannedProcess(
|
||||
(command) => command.contains('desc'),
|
||||
@ -49,21 +26,57 @@ void main() {
|
||||
|
||||
test('can find host runnable build', () async {
|
||||
final testEnv = TestEnvironment.withTestEngine(
|
||||
abi: Abi.macosArm64,
|
||||
cannedProcesses: cannedProcesses,
|
||||
);
|
||||
addTearDown(testEnv.cleanup);
|
||||
|
||||
final builder = TestBuilderConfig();
|
||||
builder.addBuild(
|
||||
name: 'macos/host_debug',
|
||||
dimension: TestDroneDimension.mac,
|
||||
);
|
||||
builder.addBuild(
|
||||
name: 'mac/host_profile',
|
||||
dimension: TestDroneDimension.mac,
|
||||
);
|
||||
builder.addBuild(
|
||||
name: 'linux/host_debug',
|
||||
dimension: TestDroneDimension.linux,
|
||||
);
|
||||
|
||||
final configs = {
|
||||
'mac_test_config': builder.buildConfig(
|
||||
path: 'ci/builders/mac_test_config.json',
|
||||
),
|
||||
};
|
||||
|
||||
final result = runnableBuilds(testEnv.environment, configs, true);
|
||||
expect(result.length, equals(4));
|
||||
expect(result[0].name, equals('ci/build_name'));
|
||||
expect(
|
||||
result.map((r) => r.name),
|
||||
unorderedEquals(['macos/host_debug', 'mac/host_profile']),
|
||||
);
|
||||
});
|
||||
|
||||
test('build command invokes gn', () async {
|
||||
final testEnv = TestEnvironment.withTestEngine(
|
||||
abi: Abi.macosArm64,
|
||||
cannedProcesses: cannedProcesses,
|
||||
);
|
||||
addTearDown(testEnv.cleanup);
|
||||
|
||||
final builder = TestBuilderConfig();
|
||||
builder.addBuild(
|
||||
name: 'macos/host_debug',
|
||||
dimension: TestDroneDimension.mac,
|
||||
);
|
||||
|
||||
final configs = {
|
||||
'mac_test_config': builder.buildConfig(
|
||||
path: 'ci/builders/mac_test_config.json',
|
||||
),
|
||||
};
|
||||
|
||||
final runner = ToolCommandRunner(
|
||||
environment: testEnv.environment,
|
||||
configs: configs,
|
||||
@ -71,8 +84,10 @@ void main() {
|
||||
final result = await runner.run([
|
||||
'build',
|
||||
'--config',
|
||||
'ci/build_name',
|
||||
'host_debug',
|
||||
]);
|
||||
|
||||
printOnFailure(testEnv.testLogs.map((r) => r.message).join('\n'));
|
||||
expect(result, equals(0));
|
||||
expect(testEnv.processHistory.length, greaterThanOrEqualTo(1));
|
||||
expect(testEnv.processHistory[0].command[0], contains('gn'));
|
||||
@ -80,10 +95,22 @@ void main() {
|
||||
|
||||
test('build command invokes ninja', () async {
|
||||
final testEnv = TestEnvironment.withTestEngine(
|
||||
abi: Abi.macosArm64,
|
||||
cannedProcesses: cannedProcesses,
|
||||
);
|
||||
addTearDown(testEnv.cleanup);
|
||||
|
||||
final builder = TestBuilderConfig();
|
||||
builder.addBuild(
|
||||
name: 'macos/host_debug',
|
||||
dimension: TestDroneDimension.mac,
|
||||
);
|
||||
|
||||
final configs = {
|
||||
'mac_test_config': builder.buildConfig(
|
||||
path: 'ci/builders/mac_test_config.json',
|
||||
),
|
||||
};
|
||||
final runner = ToolCommandRunner(
|
||||
environment: testEnv.environment,
|
||||
configs: configs,
|
||||
@ -91,8 +118,10 @@ void main() {
|
||||
final result = await runner.run([
|
||||
'build',
|
||||
'--config',
|
||||
'ci/build_name',
|
||||
'host_debug',
|
||||
]);
|
||||
|
||||
printOnFailure(testEnv.testLogs.map((r) => r.message).join('\n'));
|
||||
expect(result, equals(0));
|
||||
expect(testEnv.processHistory.length, greaterThanOrEqualTo(2));
|
||||
expect(testEnv.processHistory[1].command[0], contains('ninja'));
|
||||
@ -100,10 +129,23 @@ void main() {
|
||||
|
||||
test('build command invokes generator', () async {
|
||||
final testEnv = TestEnvironment.withTestEngine(
|
||||
abi: Abi.macosArm64,
|
||||
cannedProcesses: cannedProcesses,
|
||||
);
|
||||
addTearDown(testEnv.cleanup);
|
||||
|
||||
final builder = TestBuilderConfig();
|
||||
builder.addBuild(
|
||||
name: 'macos/host_debug',
|
||||
dimension: TestDroneDimension.mac,
|
||||
generatorTask: ('gen/script.py', ['--test-param']),
|
||||
);
|
||||
|
||||
final configs = {
|
||||
'mac_test_config': builder.buildConfig(
|
||||
path: 'ci/builders/mac_test_config.json',
|
||||
),
|
||||
};
|
||||
final runner = ToolCommandRunner(
|
||||
environment: testEnv.environment,
|
||||
configs: configs,
|
||||
@ -111,22 +153,36 @@ void main() {
|
||||
final result = await runner.run([
|
||||
'build',
|
||||
'--config',
|
||||
'ci/build_name',
|
||||
'host_debug',
|
||||
]);
|
||||
|
||||
printOnFailure(testEnv.testLogs.map((r) => r.message).join('\n'));
|
||||
expect(result, equals(0));
|
||||
expect(testEnv.processHistory.length, greaterThanOrEqualTo(3));
|
||||
expect(
|
||||
testEnv.processHistory[2].command,
|
||||
containsAllInOrder(['python3', 'gen/script.py']),
|
||||
testEnv.processHistory.map((p) => p.command),
|
||||
containsOnce(containsAllInOrder(['python3', 'gen/script.py'])),
|
||||
);
|
||||
});
|
||||
|
||||
test('build command does not invoke tests', () async {
|
||||
final testEnv = TestEnvironment.withTestEngine(
|
||||
abi: Abi.macosArm64,
|
||||
cannedProcesses: cannedProcesses,
|
||||
);
|
||||
addTearDown(testEnv.cleanup);
|
||||
|
||||
final builder = TestBuilderConfig();
|
||||
builder.addBuild(
|
||||
name: 'macos/host_debug',
|
||||
dimension: TestDroneDimension.mac,
|
||||
testTask: ('test/script.py', ['--test-param']),
|
||||
);
|
||||
|
||||
final configs = {
|
||||
'mac_test_config': builder.buildConfig(
|
||||
path: 'ci/builders/mac_test_config.json',
|
||||
),
|
||||
};
|
||||
final runner = ToolCommandRunner(
|
||||
environment: testEnv.environment,
|
||||
configs: configs,
|
||||
@ -134,19 +190,37 @@ void main() {
|
||||
final result = await runner.run([
|
||||
'build',
|
||||
'--config',
|
||||
'ci/build_name',
|
||||
'host_debug',
|
||||
]);
|
||||
|
||||
printOnFailure(testEnv.testLogs.map((r) => r.message).join('\n'));
|
||||
expect(result, equals(0));
|
||||
expect(testEnv.processHistory.length, lessThanOrEqualTo(4));
|
||||
expect(
|
||||
testEnv.processHistory.map((p) => p.command),
|
||||
isNot(contains(containsAllInOrder(['python3', 'gen/script.py']))),
|
||||
);
|
||||
});
|
||||
|
||||
test('build command runs rbe on an rbe build', () async {
|
||||
final testEnv = TestEnvironment.withTestEngine(
|
||||
abi: Abi.macosArm64,
|
||||
withRbe: true,
|
||||
cannedProcesses: cannedProcesses,
|
||||
);
|
||||
addTearDown(testEnv.cleanup);
|
||||
|
||||
final builder = TestBuilderConfig();
|
||||
builder.addBuild(
|
||||
name: 'ci/android_debug_rbe_arm64',
|
||||
dimension: TestDroneDimension.mac,
|
||||
enableRbe: true,
|
||||
);
|
||||
final configs = {
|
||||
'mac_test_config': builder.buildConfig(
|
||||
path: 'ci/builders/mac_test_config.json',
|
||||
),
|
||||
};
|
||||
|
||||
final runner = ToolCommandRunner(
|
||||
environment: testEnv.environment,
|
||||
configs: configs,
|
||||
@ -156,50 +230,93 @@ void main() {
|
||||
'--config',
|
||||
'ci/android_debug_rbe_arm64',
|
||||
]);
|
||||
|
||||
printOnFailure(testEnv.testLogs.map((r) => r.message).join('\n'));
|
||||
expect(result, equals(0));
|
||||
expect(testEnv.processHistory[0].command[0],
|
||||
contains(path.join('tools', 'gn')));
|
||||
expect(testEnv.processHistory[0].command[2], equals('--rbe'));
|
||||
expect(testEnv.processHistory[1].command[0],
|
||||
contains(path.join('reclient', 'bootstrap')));
|
||||
|
||||
final [gnCall, reclientCall, ..._] = testEnv.processHistory;
|
||||
expect(
|
||||
gnCall.command,
|
||||
containsAllInOrder([
|
||||
endsWith('tools/gn'),
|
||||
contains('--rbe'),
|
||||
]),
|
||||
);
|
||||
expect(
|
||||
reclientCall.command,
|
||||
containsAllInOrder([
|
||||
endsWith('reclient/bootstrap'),
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
test('build command plumbs -j to ninja', () async {
|
||||
final testEnv = TestEnvironment.withTestEngine(
|
||||
abi: Abi.macosArm64,
|
||||
withRbe: true,
|
||||
cannedProcesses: cannedProcesses,
|
||||
);
|
||||
addTearDown(testEnv.cleanup);
|
||||
|
||||
final builder = TestBuilderConfig();
|
||||
builder.addBuild(
|
||||
name: 'ci/android_debug_arm64',
|
||||
dimension: TestDroneDimension.mac,
|
||||
);
|
||||
|
||||
final runner = ToolCommandRunner(
|
||||
environment: testEnv.environment,
|
||||
configs: configs,
|
||||
configs: {
|
||||
'mac_test_config': builder.buildConfig(
|
||||
path: 'ci/builders/mac_test_config.json',
|
||||
),
|
||||
},
|
||||
);
|
||||
final result = await runner.run([
|
||||
'build',
|
||||
'--config',
|
||||
'ci/android_debug_rbe_arm64',
|
||||
'ci/android_debug_arm64',
|
||||
'-j',
|
||||
'500',
|
||||
]);
|
||||
|
||||
printOnFailure(testEnv.testLogs.map((r) => r.message).join('\n'));
|
||||
expect(result, equals(0));
|
||||
expect(testEnv.processHistory[0].command[0],
|
||||
contains(path.join('tools', 'gn')));
|
||||
expect(testEnv.processHistory[0].command[2], equals('--rbe'));
|
||||
expect(testEnv.processHistory[2].command.contains('500'), isTrue);
|
||||
|
||||
print(testEnv.processHistory);
|
||||
final [_, ninja, ..._] = testEnv.processHistory;
|
||||
expect(
|
||||
ninja.command,
|
||||
containsAllInOrder([
|
||||
endsWith('ninja/ninja'),
|
||||
'-j',
|
||||
'500',
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
test('build command fails when rbe is enabled but not supported', () async {
|
||||
final testEnv = TestEnvironment.withTestEngine(
|
||||
abi: Abi.macosArm64,
|
||||
cannedProcesses: cannedProcesses,
|
||||
// Intentionally omit withRbe: true.
|
||||
// That means the //flutter/build/rbe directory will not be created.
|
||||
);
|
||||
addTearDown(testEnv.cleanup);
|
||||
|
||||
final builder = TestBuilderConfig();
|
||||
builder.addBuild(
|
||||
name: 'ci/android_debug_rbe_arm64',
|
||||
dimension: TestDroneDimension.mac,
|
||||
enableRbe: true,
|
||||
);
|
||||
final runner = ToolCommandRunner(
|
||||
environment: testEnv.environment,
|
||||
configs: configs,
|
||||
configs: {
|
||||
'mac_test_config': builder.buildConfig(
|
||||
path: 'ci/builders/mac_test_config.json',
|
||||
),
|
||||
},
|
||||
);
|
||||
final result = await runner.run([
|
||||
'build',
|
||||
@ -216,14 +333,28 @@ void main() {
|
||||
|
||||
test('build command does not run rbe when disabled', () async {
|
||||
final testEnv = TestEnvironment.withTestEngine(
|
||||
abi: Abi.macosArm64,
|
||||
withRbe: true,
|
||||
cannedProcesses: cannedProcesses,
|
||||
);
|
||||
addTearDown(testEnv.cleanup);
|
||||
|
||||
final builder = TestBuilderConfig();
|
||||
builder.addBuild(
|
||||
name: 'ci/android_debug_rbe_arm64',
|
||||
dimension: TestDroneDimension.mac,
|
||||
|
||||
// Intentionally show that RBE is disabled.
|
||||
// ignore: avoid_redundant_argument_values
|
||||
enableRbe: false,
|
||||
);
|
||||
final runner = ToolCommandRunner(
|
||||
environment: testEnv.environment,
|
||||
configs: configs,
|
||||
configs: {
|
||||
'mac_test_config': builder.buildConfig(
|
||||
path: 'ci/builders/mac_test_config.json',
|
||||
),
|
||||
},
|
||||
);
|
||||
final result = await runner.run([
|
||||
'build',
|
||||
@ -231,36 +362,64 @@ void main() {
|
||||
'ci/android_debug_rbe_arm64',
|
||||
'--no-rbe',
|
||||
]);
|
||||
|
||||
printOnFailure(testEnv.testLogs.map((r) => r.message).join('\n'));
|
||||
expect(result, equals(0));
|
||||
expect(testEnv.processHistory[0].command[0],
|
||||
contains(path.join('tools', 'gn')));
|
||||
expect(testEnv.processHistory[0].command, isNot(contains(['--rbe'])));
|
||||
expect(testEnv.processHistory[1].command[0],
|
||||
contains(path.join('ninja', 'ninja')));
|
||||
|
||||
final [gn, ninja, ..._] = testEnv.processHistory;
|
||||
expect(gn.command, isNot(contains('--rbe')));
|
||||
|
||||
expect(
|
||||
ninja.command,
|
||||
containsAllInOrder(
|
||||
[
|
||||
endsWith('ninja/ninja'),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test('build command does not run rbe when rbe configs do not exist',
|
||||
() async {
|
||||
final testEnv = TestEnvironment.withTestEngine(
|
||||
abi: Abi.macosArm64,
|
||||
cannedProcesses: cannedProcesses,
|
||||
);
|
||||
addTearDown(testEnv.cleanup);
|
||||
|
||||
final builder = TestBuilderConfig();
|
||||
builder.addBuild(
|
||||
name: 'ci/android_debug_rbe_arm64',
|
||||
dimension: TestDroneDimension.mac,
|
||||
enableRbe: true,
|
||||
);
|
||||
final runner = ToolCommandRunner(
|
||||
environment: testEnv.environment,
|
||||
configs: configs,
|
||||
configs: {
|
||||
'mac_test_config': builder.buildConfig(
|
||||
path: 'ci/builders/mac_test_config.json',
|
||||
),
|
||||
},
|
||||
);
|
||||
final result = await runner.run([
|
||||
'build',
|
||||
'--config',
|
||||
'ci/android_debug_rbe_arm64',
|
||||
]);
|
||||
|
||||
printOnFailure(testEnv.testLogs.map((r) => r.message).join('\n'));
|
||||
expect(result, equals(0));
|
||||
expect(testEnv.processHistory[0].command[0],
|
||||
contains(path.join('tools', 'gn')));
|
||||
expect(testEnv.processHistory[0].command, isNot(contains(['--rbe'])));
|
||||
expect(testEnv.processHistory[1].command[0],
|
||||
contains(path.join('ninja', 'ninja')));
|
||||
|
||||
final [gn, ninja, ..._] = testEnv.processHistory;
|
||||
expect(gn.command, isNot(contains('--rbe')));
|
||||
expect(
|
||||
ninja.command,
|
||||
containsAllInOrder(
|
||||
[
|
||||
endsWith('ninja/ninja'),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test('mangleConfigName removes the OS and adds ci/ as needed', () {
|
||||
@ -359,60 +518,108 @@ void main() {
|
||||
|
||||
test('build command invokes ninja with the specified target', () async {
|
||||
final testEnv = TestEnvironment.withTestEngine(
|
||||
abi: Abi.macosArm64,
|
||||
cannedProcesses: cannedProcesses,
|
||||
);
|
||||
addTearDown(testEnv.cleanup);
|
||||
|
||||
final builder = TestBuilderConfig();
|
||||
builder.addBuild(
|
||||
name: 'ci/host_debug',
|
||||
targetDir: 'host_debug',
|
||||
dimension: TestDroneDimension.mac,
|
||||
);
|
||||
final runner = ToolCommandRunner(
|
||||
environment: testEnv.environment,
|
||||
configs: configs,
|
||||
configs: {
|
||||
'mac_test_config': builder.buildConfig(
|
||||
path: 'ci/builders/mac_test_config.json',
|
||||
),
|
||||
},
|
||||
);
|
||||
final result = await runner.run([
|
||||
'build',
|
||||
'--config',
|
||||
'host_debug',
|
||||
'ci/host_debug',
|
||||
'//flutter/fml:fml_arc_unittests',
|
||||
]);
|
||||
|
||||
printOnFailure(testEnv.testLogs.map((r) => r.message).join('\n'));
|
||||
expect(result, equals(0));
|
||||
expect(testEnv.processHistory, containsCommand((command) {
|
||||
return command.length > 3 &&
|
||||
command[0].contains('ninja') &&
|
||||
command[1].contains('-C') &&
|
||||
command[2].endsWith('/host_debug') &&
|
||||
// TODO(matanlurey): Tighten this up to be more specific.
|
||||
// The reason we need a broad check is because the test fixture
|
||||
// always returns multiple targets for gn desc, even though that is
|
||||
// not the actual behavior.
|
||||
command.sublist(3).contains('flutter/fml:fml_arc_unittests');
|
||||
}));
|
||||
|
||||
final ninjaCmd = testEnv.processHistory.firstWhere(
|
||||
(p) => p.command.first.endsWith('ninja'),
|
||||
);
|
||||
expect(
|
||||
ninjaCmd.command,
|
||||
containsAllInOrder(
|
||||
[
|
||||
endsWith('ninja'),
|
||||
'-C',
|
||||
endsWith('host_debug'),
|
||||
],
|
||||
),
|
||||
);
|
||||
expect(
|
||||
ninjaCmd.command,
|
||||
contains(
|
||||
contains('flutter/fml:fml_arc_unittests'),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test('build command invokes ninja with all matched targets', () async {
|
||||
final testEnv = TestEnvironment.withTestEngine(
|
||||
abi: Abi.macosArm64,
|
||||
cannedProcesses: cannedProcesses,
|
||||
);
|
||||
addTearDown(testEnv.cleanup);
|
||||
|
||||
final builder = TestBuilderConfig();
|
||||
builder.addBuild(
|
||||
name: 'ci/host_debug',
|
||||
targetDir: 'host_debug',
|
||||
dimension: TestDroneDimension.mac,
|
||||
);
|
||||
final runner = ToolCommandRunner(
|
||||
environment: testEnv.environment,
|
||||
configs: configs,
|
||||
configs: {
|
||||
'mac_test_config': builder.buildConfig(
|
||||
path: 'ci/builders/mac_test_config.json',
|
||||
),
|
||||
},
|
||||
);
|
||||
final result = await runner.run([
|
||||
'build',
|
||||
'--config',
|
||||
'host_debug',
|
||||
'ci/host_debug',
|
||||
'//flutter/...',
|
||||
]);
|
||||
printOnFailure(testEnv.testLogs.map((r) => r.message).join('\n'));
|
||||
expect(result, equals(0));
|
||||
expect(testEnv.processHistory, containsCommand((command) {
|
||||
return command.length > 5 &&
|
||||
command[0].contains('ninja') &&
|
||||
command[1].contains('-C') &&
|
||||
command[2].endsWith('/host_debug') &&
|
||||
command[3] == 'flutter/display_list:display_list_unittests' &&
|
||||
command[4] == 'flutter/flow:flow_unittests' &&
|
||||
command[5] == 'flutter/fml:fml_arc_unittests';
|
||||
}));
|
||||
|
||||
final ninjaCmd = testEnv.processHistory.firstWhere(
|
||||
(p) => p.command.first.endsWith('ninja'),
|
||||
);
|
||||
expect(
|
||||
ninjaCmd.command,
|
||||
containsAllInOrder(
|
||||
[
|
||||
endsWith('ninja'),
|
||||
'-C',
|
||||
endsWith('host_debug'),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
expect(
|
||||
ninjaCmd.command,
|
||||
containsAll([
|
||||
'flutter/display_list:display_list_unittests',
|
||||
'flutter/flow:flow_unittests',
|
||||
'flutter/fml:fml_arc_unittests',
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
test('build command gracefully handles no matched targets', () async {
|
||||
@ -420,27 +627,42 @@ void main() {
|
||||
CannedProcess(
|
||||
(command) => command.contains('desc'),
|
||||
stdout: fixtures.gnDescOutputEmpty(
|
||||
gnPattern: 'testing/scenario_app:sceario_app'),
|
||||
gnPattern: 'testing/scenario_app:sceario_app',
|
||||
),
|
||||
exitCode: 1,
|
||||
),
|
||||
];
|
||||
final testEnv = TestEnvironment.withTestEngine(
|
||||
abi: Abi.macosArm64,
|
||||
cannedProcesses: cannedProcesses,
|
||||
);
|
||||
addTearDown(testEnv.cleanup);
|
||||
|
||||
final builder = TestBuilderConfig();
|
||||
builder.addBuild(
|
||||
name: 'ci/host_debug',
|
||||
targetDir: 'host_debug',
|
||||
dimension: TestDroneDimension.mac,
|
||||
);
|
||||
final runner = ToolCommandRunner(
|
||||
environment: testEnv.environment,
|
||||
configs: configs,
|
||||
configs: {
|
||||
'mac_test_config': builder.buildConfig(
|
||||
path: 'ci/builders/mac_test_config.json',
|
||||
),
|
||||
},
|
||||
);
|
||||
final result = await runner.run([
|
||||
'build',
|
||||
'--config',
|
||||
'host_debug',
|
||||
'ci/host_debug',
|
||||
// Intentionally omit the prefix '//flutter/' to trigger the warning.
|
||||
'//testing/scenario_app',
|
||||
]);
|
||||
|
||||
printOnFailure(testEnv.testLogs.map((r) => r.message).join('\n'));
|
||||
expect(result, equals(0));
|
||||
|
||||
expect(
|
||||
testEnv.testLogs.map((LogRecord r) => r.message).join(),
|
||||
contains('No targets matched the pattern `testing/scenario_app'),
|
||||
@ -456,7 +678,7 @@ void main() {
|
||||
|
||||
final runner = ToolCommandRunner(
|
||||
environment: testEnv.environment,
|
||||
configs: configs,
|
||||
configs: {},
|
||||
help: true,
|
||||
);
|
||||
final result = await runner.run([
|
||||
@ -474,21 +696,74 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
test('verbose "et help build" contains CI builds', () async {
|
||||
final testEnv = TestEnvironment.withTestEngine(
|
||||
abi: Abi.macosArm64,
|
||||
cannedProcesses: cannedProcesses,
|
||||
verbose: true,
|
||||
);
|
||||
addTearDown(testEnv.cleanup);
|
||||
|
||||
final builder = TestBuilderConfig();
|
||||
builder.addBuild(
|
||||
name: 'ci/linux_android_debug',
|
||||
dimension: TestDroneDimension.mac,
|
||||
);
|
||||
final runner = ToolCommandRunner(
|
||||
environment: testEnv.environment,
|
||||
configs: {
|
||||
'linux_test_config': builder.buildConfig(
|
||||
path: 'ci/builders/linux_test_config.json',
|
||||
)
|
||||
},
|
||||
help: true,
|
||||
);
|
||||
final result = await runner.run([
|
||||
'--verbose',
|
||||
'help',
|
||||
'build',
|
||||
]);
|
||||
|
||||
printOnFailure(testEnv.testLogs.map((r) => r.message).join('\n'));
|
||||
expect(result, equals(0));
|
||||
|
||||
// Avoid a degenerate case where nothing is logged.
|
||||
expect(testEnv.testLogs, isNotEmpty, reason: 'No logs were emitted');
|
||||
print(testEnv.testLogs);
|
||||
|
||||
expect(
|
||||
testEnv.testLogs.map((LogRecord r) => r.message),
|
||||
contains(contains('[ci/')),
|
||||
);
|
||||
});
|
||||
|
||||
test('non-verbose "et help build" does not contain ci builds', () async {
|
||||
final testEnv = TestEnvironment.withTestEngine(
|
||||
abi: Abi.macosArm64,
|
||||
cannedProcesses: cannedProcesses,
|
||||
);
|
||||
addTearDown(testEnv.cleanup);
|
||||
|
||||
final builder = TestBuilderConfig();
|
||||
builder.addBuild(
|
||||
name: 'ci/linux_android_debug',
|
||||
dimension: TestDroneDimension.mac,
|
||||
);
|
||||
final runner = ToolCommandRunner(
|
||||
environment: testEnv.environment,
|
||||
configs: configs,
|
||||
configs: {
|
||||
'linux_test_config': builder.buildConfig(
|
||||
path: 'ci/builders/linux_test_config.json',
|
||||
)
|
||||
},
|
||||
help: true,
|
||||
);
|
||||
final result = await runner.run([
|
||||
'help',
|
||||
'build',
|
||||
]);
|
||||
|
||||
printOnFailure(testEnv.testLogs.map((r) => r.message).join('\n'));
|
||||
expect(result, equals(0));
|
||||
|
||||
// Avoid a degenerate case where nothing is logged.
|
||||
@ -496,7 +771,8 @@ void main() {
|
||||
|
||||
expect(
|
||||
testEnv.testLogs.map((LogRecord r) => r.message),
|
||||
isNot(contains('[ci/')),
|
||||
isNot(contains(contains('[ci/'))),
|
||||
reason: 'The log should not contain CI-prefixed builds',
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@ -2,11 +2,9 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:convert' as convert;
|
||||
import 'dart:ffi' as ffi show Abi;
|
||||
import 'dart:io' as io;
|
||||
|
||||
import 'package:engine_build_configs/engine_build_configs.dart';
|
||||
import 'package:engine_repo_tools/engine_repo_tools.dart';
|
||||
import 'package:engine_tool/src/commands/command_runner.dart';
|
||||
import 'package:engine_tool/src/environment.dart';
|
||||
@ -16,56 +14,25 @@ import 'package:process_fakes/process_fakes.dart';
|
||||
import 'package:process_runner/process_runner.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'fixtures.dart' as fixtures;
|
||||
|
||||
void main() {
|
||||
final Engine engine;
|
||||
try {
|
||||
engine = Engine.findWithin();
|
||||
} catch (e) {
|
||||
io.stderr.writeln(e);
|
||||
io.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
final BuilderConfig linuxTestConfig = BuilderConfig.fromJson(
|
||||
path: 'ci/builders/linux_test_config.json',
|
||||
map: convert.jsonDecode(fixtures.testConfig('Linux', Platform.linux))
|
||||
as Map<String, Object?>,
|
||||
);
|
||||
|
||||
final BuilderConfig macTestConfig = BuilderConfig.fromJson(
|
||||
path: 'ci/builders/mac_test_config.json',
|
||||
map: convert.jsonDecode(fixtures.testConfig('Mac-12', Platform.macOS))
|
||||
as Map<String, Object?>,
|
||||
);
|
||||
|
||||
final BuilderConfig winTestConfig = BuilderConfig.fromJson(
|
||||
path: 'ci/builders/win_test_config.json',
|
||||
map: convert.jsonDecode(fixtures.testConfig('Windows-11', Platform.windows))
|
||||
as Map<String, Object?>,
|
||||
);
|
||||
|
||||
final Map<String, BuilderConfig> configs = <String, BuilderConfig>{
|
||||
'linux_test_config': linuxTestConfig,
|
||||
'mac_test_config': macTestConfig,
|
||||
'win_test_config': winTestConfig,
|
||||
};
|
||||
final engine = Engine.findWithin();
|
||||
|
||||
(Environment, List<List<String>>) macEnv(Logger logger) {
|
||||
final List<List<String>> runHistory = <List<String>>[];
|
||||
final runHistory = <List<String>>[];
|
||||
return (
|
||||
Environment(
|
||||
abi: ffi.Abi.macosArm64,
|
||||
engine: engine,
|
||||
platform: FakePlatform(
|
||||
operatingSystem: Platform.macOS,
|
||||
resolvedExecutable: io.Platform.resolvedExecutable,
|
||||
pathSeparator: '/'),
|
||||
operatingSystem: Platform.macOS,
|
||||
resolvedExecutable: io.Platform.resolvedExecutable,
|
||||
pathSeparator: '/',
|
||||
),
|
||||
processRunner: ProcessRunner(
|
||||
processManager: FakeProcessManager(onStart: (List<String> command) {
|
||||
processManager: FakeProcessManager(onStart: (command) {
|
||||
runHistory.add(command);
|
||||
return FakeProcess();
|
||||
}, onRun: (List<String> command) {
|
||||
}, onRun: (command) {
|
||||
// Should not be executed.
|
||||
assert(false);
|
||||
return io.ProcessResult(81, 1, '', '');
|
||||
@ -81,7 +48,7 @@ void main() {
|
||||
final (Environment env, List<List<String>> runHistory) = macEnv(logger);
|
||||
final ToolCommandRunner runner = ToolCommandRunner(
|
||||
environment: env,
|
||||
configs: configs,
|
||||
configs: {},
|
||||
);
|
||||
final int result = await runner.run(<String>['lint']);
|
||||
expect(result, equals(0));
|
||||
|
||||
@ -0,0 +1,138 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:engine_build_configs/engine_build_configs.dart';
|
||||
|
||||
/// Builds a test [BuilderConfig].
|
||||
///
|
||||
/// Many tests will involve exactly one build configuration, or a small number
|
||||
/// of build configurations. Instead of constructing these configurations ahead
|
||||
/// of time, this builder is used to create them on-the-fly, with convenient
|
||||
/// methods for setting up and cloning configurations.
|
||||
///
|
||||
/// This builder exists in order to avoid global fixtures in tests that do not
|
||||
/// isolate elements of the test environment relevant to their test. Prior to
|
||||
/// the builder, 100s of lines of static configuration were used to setup and
|
||||
/// instrument tests across multiple files; instead, this builder is used to
|
||||
/// precisely configure the test environment for each test.
|
||||
///
|
||||
/// See <https://github.com/flutter/flutter/issues/148420> for more information.
|
||||
final class TestBuilderConfig {
|
||||
final _builds = <Map<String, Object?>>[];
|
||||
|
||||
/// Appends a build to the configuration.
|
||||
void addBuild({
|
||||
required String name,
|
||||
required TestDroneDimension dimension,
|
||||
bool enableRbe = false,
|
||||
String description = 'A default description.',
|
||||
String? targetDir,
|
||||
(String, List<String>)? generatorTask,
|
||||
(String, List<String>)? testTask,
|
||||
}) {
|
||||
_builds.add({
|
||||
'archives': [],
|
||||
'drone_dimensions': [
|
||||
dimension._dimension,
|
||||
],
|
||||
'gclient_variables': <String, Object?>{},
|
||||
'gn': [
|
||||
if (enableRbe) '--rbe',
|
||||
],
|
||||
'name': name,
|
||||
'description': description,
|
||||
'ninja': <String, Object?>{
|
||||
if (targetDir case final targetDir?) ...{
|
||||
'config': targetDir,
|
||||
'targets': ['ninja_target'],
|
||||
}
|
||||
},
|
||||
'tests': _testTask(testTask),
|
||||
'generators': _generatorTask(generatorTask),
|
||||
});
|
||||
}
|
||||
|
||||
static List<Object?> _testTask((String, List<String>)? task) {
|
||||
if (task == null) {
|
||||
return [];
|
||||
}
|
||||
final (script, args) = task;
|
||||
return [
|
||||
{
|
||||
'name': 'test_task',
|
||||
'language': 'python',
|
||||
'scripts': [script],
|
||||
'parameters': args,
|
||||
'contexts': ['context'],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
static Map<String, Object?> _generatorTask((String, List<String>)? task) {
|
||||
if (task == null) {
|
||||
return {};
|
||||
}
|
||||
final (script, args) = task;
|
||||
return {
|
||||
'tasks': [
|
||||
{
|
||||
'name': 'generator_task',
|
||||
'language': 'python',
|
||||
'scripts': [script],
|
||||
'parameters': args,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
/// Copies the state of `this` as a new [TestBuilderConfig].
|
||||
TestBuilderConfig clone() {
|
||||
final clone = TestBuilderConfig();
|
||||
clone._builds.addAll(_builds);
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// Creates and returns a [BuilderConfig] capturing the current builder state.
|
||||
///
|
||||
/// [path] is the path to the configuration file that would be read from disk.
|
||||
///
|
||||
/// After creation, the builder state remains, and changes can be made to the
|
||||
/// builder to create a new configuration without affecting the previous one
|
||||
/// created.
|
||||
BuilderConfig buildConfig({
|
||||
required String path,
|
||||
}) {
|
||||
final config = BuilderConfig.fromJson(map: buildJson(), path: path);
|
||||
if (config.check(path) case final errors when errors.isNotEmpty) {
|
||||
throw StateError('Invalid configuration:\n${errors.join('\n')}');
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
/// Creates and returns the JSON serialized format of a [BuilderConfig].
|
||||
///
|
||||
/// Most of the time, use [build] instead of this method.
|
||||
///
|
||||
/// It is undefined behavior to mutate the returned map.
|
||||
Map<String, Object?> buildJson() {
|
||||
return {
|
||||
'builds': _builds,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Fixed set of dimensions for [TestBuilderConfig.addBuild].
|
||||
enum TestDroneDimension {
|
||||
/// Runs on Linux.
|
||||
linux('os=Linux'),
|
||||
|
||||
/// Runs on macOS.
|
||||
mac('os=Mac-12'),
|
||||
|
||||
/// Runs on Windows.
|
||||
win('os=Windows-11');
|
||||
|
||||
const TestDroneDimension(this._dimension);
|
||||
final String _dimension;
|
||||
}
|
||||
@ -69,10 +69,10 @@ class TestEnvironment {
|
||||
abi: abi,
|
||||
engine: engine,
|
||||
platform: FakePlatform(
|
||||
operatingSystem: _operatingSystemForAbi(abi),
|
||||
resolvedExecutable: io.Platform.resolvedExecutable,
|
||||
pathSeparator: _pathSeparatorForAbi(abi),
|
||||
numberOfProcessors: 32,
|
||||
operatingSystem: _operatingSystemForAbi(abi),
|
||||
resolvedExecutable: io.Platform.resolvedExecutable,
|
||||
pathSeparator: _pathSeparatorForAbi(abi),
|
||||
numberOfProcessors: 32,
|
||||
),
|
||||
processRunner: ProcessRunner(
|
||||
processManager: FakeProcessManager(onStart: (List<String> command) {
|
||||
@ -84,7 +84,8 @@ class TestEnvironment {
|
||||
return processResult;
|
||||
}, onRun: (List<String> command) {
|
||||
final io.ProcessResult result = _getCannedProcessResult(
|
||||
command, cannedProcesses,
|
||||
command,
|
||||
cannedProcesses,
|
||||
);
|
||||
processHistory.add(ExecutedProcess(
|
||||
command,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user