blob: 58c11d374b693b8e9994105e48b244e7613407ee [file] [log] [blame]
import 'dart:io';
import 'package:async/async.dart';
import 'package:path/path.dart' as p;
import 'package:fxtest/fxtest.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
// Mock this because it checks environment variables
class MockEnvReader extends Mock implements EnvReader {}
// Mock this because it creates processes
class FakeTestRunner extends Fake implements TestRunner {
final int exitCode;
FakeTestRunner(this.exitCode);
FakeTestRunner.passing() : exitCode = 0;
FakeTestRunner.failing() : exitCode = 2;
@override
Future<ProcessResult> run(
String command,
List<String> args, {
String workingDirectory,
}) async {
return Future.value(
ProcessResult(1, 0, args.join(' '), workingDirectory.toString()),
);
}
}
void main() {
// out of test, out of fxtest, out of scripts
// Alternatively, we could read the FUCHSIA_BUILD_DIR env variable,
// but we're trying to have this code remain env-variable independent
String buildDir = p.join('..', '..', '..', 'out/default');
group('tests.json entries are correctly parsed', () {
test('for host tests', () {
TestsManifestReader tr = TestsManifestReader();
List<dynamic> testJson = [
{
'environments': [],
'test': {
'cpu': 'x64',
'deps_file':
'host_x64/gen/topaz/tools/doc_checker/doc_checker_tests.deps.json',
'path': 'host_x64/doc_checker_tests',
'name': '//topaz/tools/doc_checker:doc_checker_tests',
'os': 'linux'
}
},
];
List<TestDefinition> tds = tr.parseManifest(testJson, buildDir);
expect(tds, hasLength(1));
expect(tds[0].packageUrl, '');
expect(tds[0].depsFile, testJson[0]['test']['deps_file']);
expect(tds[0].path, testJson[0]['test']['path']);
expect(tds[0].name, testJson[0]['test']['name']);
expect(tds[0].cpu, testJson[0]['test']['cpu']);
expect(tds[0].os, testJson[0]['test']['os']);
expect(tds[0].executionHandle.testType, TestType.host);
});
test('for device tests', () {
TestsManifestReader tr = TestsManifestReader();
List<dynamic> testJson = [
{
'environments': [],
'test': {
'cpu': 'arm64',
'path':
'/pkgfs/packages/run_test_component_test/0/test/run_test_component_test',
'name':
'//garnet/bin/run_test_component/test:run_test_component_test',
'os': 'fuchsia',
'package_url':
'fuchsia-pkg://fuchsia.com/run_test_component_test#meta/run_test_component_test.cmx',
}
},
];
List<TestDefinition> tds = tr.parseManifest(testJson, buildDir);
expect(tds, hasLength(1));
expect(tds[0].packageUrl, testJson[0]['test']['package_url']);
expect(tds[0].depsFile, '');
expect(tds[0].path, testJson[0]['test']['path']);
expect(tds[0].name, testJson[0]['test']['name']);
expect(tds[0].cpu, testJson[0]['test']['cpu']);
expect(tds[0].os, testJson[0]['test']['os']);
expect(tds[0].executionHandle.testType, TestType.component);
});
test('for unsupported tests', () {
TestsManifestReader tr = TestsManifestReader();
List<dynamic> testJson = [
{
'environments': [],
'test': {
'cpu': 'arm64',
'name':
'//garnet/bin/run_test_component/test:run_test_component_test',
'os': 'fuchsia',
}
},
];
List<TestDefinition> tds = tr.parseManifest(testJson, buildDir);
expect(tds, hasLength(1));
expect(tds[0].path, '');
expect(tds[0].executionHandle.testType, TestType.unsupported);
});
});
group('tests are aggregated correctly', () {
void _ignoreEvents(TestEvent _) {}
TestsManifestReader tr = TestsManifestReader();
List<TestDefinition> testDefinitions = [
TestDefinition(
buildDir: buildDir,
os: 'fuchsia',
packageUrl: 'fuchsia-pkg://fuchsia.com/fancy#test.cmx',
name: 'device test',
),
TestDefinition(
buildDir: buildDir,
os: 'linux',
path: '/asdf',
name: '//host/test',
),
];
test('when the -h flag is passed', () {
TestFlags testFlags = TestFlags.host(['//host/test']);
ParsedManifest parsedManifest = tr.aggregateTests(
testDefinitions: testDefinitions,
buildDir: buildDir,
eventEmitter: _ignoreEvents,
testFlags: testFlags,
);
expect(parsedManifest.testBundles, hasLength(1));
expect(parsedManifest.testBundles[0].testDefinition.name, '//host/test');
});
test('when the -d flag is passed', () {
TestFlags testFlags =
TestFlags.device(['fuchsia-pkg://fuchsia.com/fancy#test.cmx']);
ParsedManifest parsedManifest = tr.aggregateTests(
testDefinitions: testDefinitions,
buildDir: buildDir,
eventEmitter: _ignoreEvents,
testFlags: testFlags,
);
expect(parsedManifest.testBundles, hasLength(1));
expect(parsedManifest.testBundles[0].testDefinition.name, 'device test');
});
test('when no flags are passed', () {
TestFlags testFlags = TestFlags.all();
ParsedManifest parsedManifest = tr.aggregateTests(
testDefinitions: testDefinitions,
buildDir: buildDir,
eventEmitter: _ignoreEvents,
testFlags: testFlags,
);
expect(parsedManifest.testBundles, hasLength(2));
});
test('when packageUrl `name` is matched', () {
TestFlags testFlags = TestFlags.all(['fancy']);
ParsedManifest parsedManifest = tr.aggregateTests(
testDefinitions: testDefinitions,
buildDir: buildDir,
eventEmitter: _ignoreEvents,
testFlags: testFlags,
);
expect(parsedManifest.testBundles, hasLength(1));
expect(parsedManifest.testBundles[0].testDefinition.name, 'device test');
});
test('when packageUrl `name` is matched but discriminating flag prevents',
() {
TestFlags testFlags = TestFlags.host(['fancy']);
ParsedManifest parsedManifest = tr.aggregateTests(
testDefinitions: testDefinitions,
buildDir: buildDir,
eventEmitter: _ignoreEvents,
testFlags: testFlags,
);
expect(parsedManifest.testBundles, hasLength(0));
});
test('when . is passed from the build dir', () {
TestFlags testFlags = TestFlags.host(['.']);
// Copy the list
var tds = testDefinitions.sublist(0)
..addAll([
TestDefinition(
os: 'linux',
name: 'awesome host test',
path: 'host_x64/test',
buildDir: buildDir,
),
]);
ParsedManifest parsedManifest = tr.aggregateTests(
testDefinitions: tds,
buildDir: buildDir,
eventEmitter: _ignoreEvents,
testFlags: testFlags,
);
expect(parsedManifest.testBundles, hasLength(1));
expect(
parsedManifest.testBundles[0].testDefinition.name,
'awesome host test',
);
});
test('when . is passed from the build dir and there\'s device tests', () {
TestFlags testFlags = TestFlags.all(['.']);
// Copy the list
var tds = testDefinitions.sublist(0)
..addAll([
TestDefinition(
os: 'fuchsia',
name: 'awesome device test',
path: '/pkgfs/stuff',
buildDir: buildDir,
),
]);
ParsedManifest parsedManifest = tr.aggregateTests(
testDefinitions: tds,
buildDir: buildDir,
eventEmitter: _ignoreEvents,
testFlags: testFlags,
);
expect(parsedManifest.testBundles, hasLength(0));
});
});
group('fuchsia-package URLs are correctly parsed', () {
test('when all components are present', () {
PackageUrl packageUrl = PackageUrl.fromString(
'fuchsia-pkg://myroot.com/pkg-name/VARIANT?hash=asdf#OMG.cmx');
expect(packageUrl.host, 'myroot.com');
expect(packageUrl.packageName, 'pkg-name');
expect(packageUrl.packageVariant, 'VARIANT');
expect(packageUrl.hash, 'asdf');
expect(packageUrl.resourcePath, 'OMG.cmx');
});
test('when the variant is missing', () {
PackageUrl packageUrl = PackageUrl.fromString(
'fuchsia-pkg://myroot.com/pkg-name?hash=asdf#OMG.cmx');
expect(packageUrl.host, 'myroot.com');
expect(packageUrl.packageName, 'pkg-name');
expect(packageUrl.packageVariant, null);
expect(packageUrl.hash, 'asdf');
expect(packageUrl.resourcePath, 'OMG.cmx');
});
test('when the hash is missing', () {
PackageUrl packageUrl = PackageUrl.fromString(
'fuchsia-pkg://myroot.com/pkg-name/VARIANT#OMG.cmx');
expect(packageUrl.host, 'myroot.com');
expect(packageUrl.packageName, 'pkg-name');
expect(packageUrl.packageVariant, 'VARIANT');
expect(packageUrl.hash, null);
expect(packageUrl.resourcePath, 'OMG.cmx');
});
test('when the resource path is missing', () {
PackageUrl packageUrl = PackageUrl.fromString(
'fuchsia-pkg://myroot.com/pkg-name/VARIANT?hash=asdf');
expect(packageUrl.host, 'myroot.com');
expect(packageUrl.packageName, 'pkg-name');
expect(packageUrl.packageVariant, 'VARIANT');
expect(packageUrl.hash, 'asdf');
expect(packageUrl.resourcePath, '');
});
test('when the variant and hash are missing', () {
PackageUrl packageUrl =
PackageUrl.fromString('fuchsia-pkg://myroot.com/pkg-name#OMG.cmx');
expect(packageUrl.host, 'myroot.com');
expect(packageUrl.packageName, 'pkg-name');
expect(packageUrl.packageVariant, null);
expect(packageUrl.hash, null);
expect(packageUrl.resourcePath, 'OMG.cmx');
});
test('when the variant and resource path are missing', () {
PackageUrl packageUrl =
PackageUrl.fromString('fuchsia-pkg://myroot.com/pkg-name?hash=asdf');
expect(packageUrl.host, 'myroot.com');
expect(packageUrl.packageName, 'pkg-name');
expect(packageUrl.packageVariant, null);
expect(packageUrl.hash, 'asdf');
expect(packageUrl.resourcePath, '');
});
test('when the hash and resource path are missing', () {
PackageUrl packageUrl =
PackageUrl.fromString('fuchsia-pkg://myroot.com/pkg-name/VARIANT');
expect(packageUrl.host, 'myroot.com');
expect(packageUrl.packageName, 'pkg-name');
expect(packageUrl.packageVariant, 'VARIANT');
expect(packageUrl.hash, null);
expect(packageUrl.resourcePath, '');
});
test('when the variant, hash, and resource path are missing', () {
PackageUrl packageUrl =
PackageUrl.fromString('fuchsia-pkg://myroot.com/pkg-name');
expect(packageUrl.host, 'myroot.com');
expect(packageUrl.packageName, 'pkg-name');
expect(packageUrl.packageVariant, null);
expect(packageUrl.hash, null);
expect(packageUrl.resourcePath, '');
});
});
group('fuchsia directories are located correctly', () {
test('when the build directory is inside the checkout', () {
var envReader = MockEnvReader();
when(envReader.getEnv('FUCHSIA_DIR')).thenReturn('/root/path/fuchsia');
when(envReader.getEnv('FUCHSIA_BUILD_DIR'))
.thenReturn('/root/path/fuchsia/out/default');
var fuchsiaLocator = FuchsiaLocator(envReader: envReader);
expect(fuchsiaLocator.fuchsiaDir, '/root/path/fuchsia');
expect(fuchsiaLocator.buildDir, '/root/path/fuchsia/out/default');
expect(fuchsiaLocator.relativeBuildDir, '/out/default');
expect(fuchsiaLocator.userFriendlyBuildDir, '//out/default');
});
test('when the cwd is requested from the build dir itself', () {
var envReader = MockEnvReader();
when(envReader.getEnv('FUCHSIA_DIR')).thenReturn('/root/path/fuchsia');
when(envReader.getEnv('FUCHSIA_BUILD_DIR'))
.thenReturn('/root/path/fuchsia/out/default');
when(envReader.getCwd()).thenReturn('/root/path/fuchsia/out/default');
var fuchsiaLocator = FuchsiaLocator(envReader: envReader);
expect(fuchsiaLocator.relativeCwd, '.');
});
test('when the cwd is requested from within the build dir', () {
var envReader = MockEnvReader();
when(envReader.getEnv('FUCHSIA_DIR')).thenReturn('/root/path/fuchsia');
when(envReader.getEnv('FUCHSIA_BUILD_DIR'))
.thenReturn('/root/path/fuchsia/out/default');
when(envReader.getCwd())
.thenReturn('/root/path/fuchsia/out/default/host_x64');
var fuchsiaLocator = FuchsiaLocator(envReader: envReader);
expect(fuchsiaLocator.relativeCwd, 'host_x64');
});
test(
'when the cwd is requested from within the tree but not within '
'the build dir', () {
var envReader = MockEnvReader();
when(envReader.getEnv('FUCHSIA_DIR')).thenReturn('/root/path/fuchsia');
when(envReader.getEnv('FUCHSIA_BUILD_DIR'))
.thenReturn('/root/path/fuchsia/out/default');
when(envReader.getCwd()).thenReturn('/root/path/fuchsia/tools');
var fuchsiaLocator = FuchsiaLocator(envReader: envReader);
expect(fuchsiaLocator.relativeCwd, '/root/path/fuchsia/tools');
});
test('when fuchsia tree directory path does not contain "fuchsia"', () {
var envReader = MockEnvReader();
when(envReader.getEnv('FUCHSIA_DIR')).thenReturn('/root/path/dev');
when(envReader.getEnv('FUCHSIA_BUILD_DIR'))
.thenReturn('/root/path/dev/out/default');
when(envReader.getCwd()).thenReturn('/root/path/dev/out/default');
var fuchsiaLocator = FuchsiaLocator(envReader: envReader);
expect(fuchsiaLocator.relativeCwd, '.');
});
});
group('test name arguments are parsed correctly', () {
test('when a dot is passed to stand in as the current directory', () {
var envReader = MockEnvReader();
when(envReader.getEnv('FUCHSIA_BUILD_DIR'))
.thenReturn('/root/path/fuchsia/out/default');
when(envReader.getCwd())
.thenReturn('/root/path/fuchsia/out/default/host_x64/gen');
var fuchsiaLocator = FuchsiaLocator(envReader: envReader);
var collector = TestNamesCollector(
[
['.'],
],
fuchsiaLocator: fuchsiaLocator,
);
expect(collector.collect(), ['host_x64/gen']);
});
test('when a duplicate is passed in', () {
var collector = TestNamesCollector([
['asdf'],
['asdf', 'xyz']
]);
expect(collector.collect(), ['asdf', 'xyz']);
});
test('when a dot and duplicate are passed in', () {
var envReader = MockEnvReader();
when(envReader.getEnv('FUCHSIA_BUILD_DIR'))
.thenReturn('/root/path/fuchsia/out/default');
when(envReader.getCwd())
.thenReturn('/root/path/fuchsia/out/default/host_x64');
var fuchsiaLocator = FuchsiaLocator(envReader: envReader);
var collector = TestNamesCollector(
[
['asdf'],
['asdf', '.']
],
fuchsiaLocator: fuchsiaLocator,
);
expect(collector.collect(), ['asdf', 'host_x64']);
});
test('when a dot is passed from the build directory', () {
var envReader = MockEnvReader();
when(envReader.getEnv('FUCHSIA_BUILD_DIR'))
.thenReturn('/root/path/fuchsia/out/default');
when(envReader.getCwd()).thenReturn('/root/path/fuchsia/out/default');
var fuchsiaLocator = FuchsiaLocator(envReader: envReader);
var collector = TestNamesCollector(
[
['.']
],
fuchsiaLocator: fuchsiaLocator,
);
expect(collector.collect(), ['.']);
});
});
group('arguments are passed through correctly', () {
void _ignoreEvents(TestEvent _) {}
TestsManifestReader tr = TestsManifestReader();
List<TestDefinition> testDefinitions = [
TestDefinition(
buildDir: buildDir,
os: 'fuchsia',
packageUrl: 'fuchsia-pkg://fuchsia.com/fancy#test.cmx',
name: 'device test',
),
TestDefinition(
buildDir: buildDir,
os: 'linux',
path: '/asdf',
name: 'example test',
),
];
test('when there are pass-thru commands', () async {
var testFlags = TestFlags(
testNames: ['example test'],
passThroughTokens: ['--xyz'],
);
ParsedManifest manifest = tr.aggregateTests(
buildDir: '/custom',
eventEmitter: _ignoreEvents,
testDefinitions: testDefinitions,
testFlags: testFlags,
testRunner: FakeTestRunner.passing(),
);
expect(manifest.testBundles, hasLength(1));
var stream = StreamQueue(manifest.testBundles[0].run());
TestEvent event = await stream.next;
expect(event, isA<TestStarted>());
event = await stream.next;
expect(event, isA<TestResult>());
TestResult resultEvent = event;
// [FakeTestRunner] passes args through to its stdout, so we can check
// that the args were in fact passed through by evaluating that
expect(resultEvent.message, '--xyz');
});
});
}