blob: 47b04a6f515ce07610d2af04f9e3a6800e41ca26 [file] [log] [blame]
// Copyright 2019 The Fuchsia 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:meta/meta.dart';
/// Simple class to hold shared parameters.
class _FlagsMixin {
final bool dryRun;
final bool isVerbose;
/// The maximum number of tests to run. If 0, all tests will be executed.
final int limit;
final bool allOutput;
/// Extra tokens to be passed through to individual tests.
final List<String> passThroughTokens;
final bool simpleOutput;
final bool shouldOnlyRunDeviceTests;
final bool shouldOnlyRunHostTests;
final bool shouldFailFast;
final bool shouldPrintSkipped;
final bool shouldRandomizeTestOrder;
final bool shouldSilenceUnsupported;
final int warnSlowerThan;
_FlagsMixin({
this.dryRun = false,
this.isVerbose = false,
this.limit = 0,
this.allOutput = false,
this.passThroughTokens = const [],
this.simpleOutput = false,
this.shouldOnlyRunDeviceTests = false,
this.shouldOnlyRunHostTests = false,
this.shouldFailFast = false,
this.shouldPrintSkipped = false,
this.shouldRandomizeTestOrder = false,
this.shouldSilenceUnsupported = false,
this.warnSlowerThan = 0,
});
@override
String toString() => '''<TestFlags
dryRun: $dryRun
allOutput: $allOutput,
limit: $limit
isVerbose: $isVerbose
passThroughTokens: $passThroughTokens,
simpleOutput: $simpleOutput,
shouldOnlyRunDeviceTests: $shouldOnlyRunDeviceTests
shouldOnlyRunHostTests: $shouldOnlyRunHostTests
shouldFailFast: $shouldFailFast
shouldPrintSkipped: $shouldPrintSkipped
shouldRandomizeTestOrder: $shouldRandomizeTestOrder
shouldSilenceUnsupported: $shouldSilenceUnsupported
warnSlowerThan: $warnSlowerThan
>''';
}
/// The parsed parameters passed by our test-running user for evaluation
/// against specific tests available to the current build.
///
/// This handles the fact that users can invoke flags we need to honor in a
/// combinatorial sort of way. For example, consider this invocation:
///
/// ```sh
/// fx test //network //bootloader -d
/// ```
///
/// Here, our developer wants to run all device network tests and all device
/// bootloader tests. To streamline the code that delivers this, we will expand
/// parameters and pretend the developer executed the following two commands:
///
/// ```sh
/// fx test //network -d
/// fx test //bootloader -d
/// ```
/// Each "imagined" command will produce a set of tests which will be combined
/// into a master list of tests we run in one go, with aggregated output.
/// However, the intermediate layer streamlines much of our matching logic.
///
/// [TestFlags] executes this combinatorial explosion by expanding its
/// parameters into a list of [PermutatedTestFlag] instances.
class TestFlags extends _FlagsMixin {
final List<String> testNames;
TestFlags({
@required this.testNames,
dryRun,
isVerbose,
limit,
allOutput,
passThroughTokens,
simpleOutput,
shouldFailFast,
shouldOnlyRunDeviceTests,
shouldOnlyRunHostTests,
shouldPrintSkipped,
shouldRandomizeTestOrder,
shouldSilenceUnsupported,
warnSlowerThan,
}) : super(
dryRun: dryRun ?? false,
isVerbose: isVerbose ?? false,
limit: limit,
allOutput: allOutput ?? false,
passThroughTokens: passThroughTokens ?? <String>[],
simpleOutput: simpleOutput ?? false,
shouldFailFast: shouldFailFast ?? false,
shouldOnlyRunDeviceTests: shouldOnlyRunDeviceTests ?? false,
shouldOnlyRunHostTests: shouldOnlyRunHostTests ?? false,
shouldPrintSkipped: shouldPrintSkipped ?? false,
shouldRandomizeTestOrder: shouldRandomizeTestOrder ?? false,
shouldSilenceUnsupported: shouldSilenceUnsupported ?? false,
warnSlowerThan: warnSlowerThan,
);
factory TestFlags.all([List<String> tNames]) {
return TestFlags(
testNames: tNames ?? [],
dryRun: false,
limit: 0,
isVerbose: false,
allOutput: false,
shouldOnlyRunDeviceTests: false,
shouldOnlyRunHostTests: false,
shouldFailFast: false,
shouldPrintSkipped: false,
shouldRandomizeTestOrder: false,
shouldSilenceUnsupported: false,
warnSlowerThan: 0,
);
}
factory TestFlags.host(List<String> tNames) {
return TestFlags(
testNames: tNames,
dryRun: false,
limit: 0,
isVerbose: false,
allOutput: false,
simpleOutput: true,
shouldOnlyRunDeviceTests: false,
shouldOnlyRunHostTests: true,
shouldFailFast: false,
shouldPrintSkipped: false,
shouldRandomizeTestOrder: false,
shouldSilenceUnsupported: false,
warnSlowerThan: 0,
);
}
factory TestFlags.device(List<String> tNames) {
return TestFlags(
testNames: tNames,
dryRun: false,
limit: 0,
isVerbose: false,
allOutput: false,
simpleOutput: true,
shouldOnlyRunDeviceTests: true,
shouldOnlyRunHostTests: false,
shouldFailFast: false,
shouldPrintSkipped: false,
shouldRandomizeTestOrder: false,
shouldSilenceUnsupported: false,
warnSlowerThan: 0,
);
}
Iterable<PermutatedTestFlags> get permutations sync* {
// Check for having zero `testName` instances, which indicates that the
// developer wants a wide-open run that includes as many tests as possible
if (testNames.isEmpty) {
yield PermutatedTestFlags(
dryRun: dryRun,
limit: 0,
isVerbose: isVerbose,
allOutput: allOutput,
passThroughTokens: passThroughTokens,
simpleOutput: simpleOutput,
shouldFailFast: shouldFailFast,
shouldOnlyRunDeviceTests: shouldOnlyRunDeviceTests,
shouldOnlyRunHostTests: shouldOnlyRunHostTests,
shouldPrintSkipped: shouldPrintSkipped,
shouldRandomizeTestOrder: shouldRandomizeTestOrder,
shouldSilenceUnsupported: shouldSilenceUnsupported,
testName: null,
warnSlowerThan: warnSlowerThan,
);
return;
}
for (String testName in testNames) {
yield PermutatedTestFlags(
dryRun: dryRun,
isVerbose: isVerbose,
limit: 0,
allOutput: allOutput,
passThroughTokens: passThroughTokens,
simpleOutput: simpleOutput,
shouldFailFast: shouldFailFast,
shouldOnlyRunDeviceTests: shouldOnlyRunDeviceTests,
shouldOnlyRunHostTests: shouldOnlyRunHostTests,
shouldPrintSkipped: shouldPrintSkipped,
shouldRandomizeTestOrder: shouldRandomizeTestOrder,
shouldSilenceUnsupported: shouldSilenceUnsupported,
testName: testName,
warnSlowerThan: warnSlowerThan,
);
}
}
}
/// An expanded set of flags passed to `fx test` against which all available
/// tests will be examined.
class PermutatedTestFlags extends _FlagsMixin {
String testName;
PermutatedTestFlags({
@required this.testName,
dryRun,
isVerbose,
limit,
allOutput,
passThroughTokens,
simpleOutput,
shouldFailFast,
shouldOnlyRunDeviceTests,
shouldOnlyRunHostTests,
shouldPrintSkipped,
shouldRandomizeTestOrder,
shouldSilenceUnsupported,
warnSlowerThan,
}) : super(
dryRun: dryRun,
isVerbose: isVerbose,
limit: limit,
allOutput: allOutput,
passThroughTokens: passThroughTokens,
simpleOutput: simpleOutput,
shouldFailFast: shouldFailFast,
shouldOnlyRunDeviceTests: shouldOnlyRunDeviceTests,
shouldOnlyRunHostTests: shouldOnlyRunHostTests,
shouldPrintSkipped: shouldPrintSkipped,
shouldRandomizeTestOrder: shouldRandomizeTestOrder,
shouldSilenceUnsupported: shouldSilenceUnsupported,
warnSlowerThan: warnSlowerThan,
);
@override
String toString() {
var chunks = <String>[
if (testName != null) testName,
if (shouldOnlyRunDeviceTests) '-d',
if (shouldOnlyRunHostTests) '-h',
];
var chunksStr = chunks.isNotEmpty ? ' ${chunks.join(" ")}' : '';
return '<PermuatedTestFlags$chunksStr>';
}
}