blob: 92c531df0c10032bd89cc4da93b6fd0866545675 [file]
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:io';
import 'package:native_toolchain_c/src/utils/run_process.dart';
import 'package:process/process.dart';
import 'package:test/test.dart';
import '../helpers.dart';
import 'fake_process_manager.dart';
void main() {
final whichUri = Uri.file(Platform.isWindows ? 'where' : 'which');
test('log contains working dir', () async {
final tempUri = await tempDirForTest();
final messages = <String>[];
await runProcess(
executable: whichUri,
workingDirectory: tempUri,
logger: createCapturingLogger(messages),
processManager: const LocalProcessManager(),
);
expect(messages.join('\n'), contains('cd'));
});
test('log contains env', () async {
final messages = <String>[];
await runProcess(
executable: whichUri,
environment: {'FOO': 'BAR'},
logger: createCapturingLogger(messages),
processManager: const LocalProcessManager(),
);
expect(messages.join('\n'), contains('FOO=BAR'));
});
test('stderr', () async {
final messages = <String>[];
const filePath = 'a/dart/file/which/does/not/exist.dart';
final result = await runProcess(
executable: Uri.file(Platform.resolvedExecutable),
arguments: [filePath],
logger: createCapturingLogger(messages),
processManager: const LocalProcessManager(),
);
expect(result.stderr, contains(filePath));
expect(result.toString(), contains(filePath));
});
group('with a fake process manager', () {
final executableUri = Uri.file('/bin/echo');
test('captures stdout and stderr and passes the command through', () async {
final processManager = FakeProcessManager([
const FakeCommand(
stdout: 'the standard output',
stderr: 'the standard error',
),
]);
final result = await runProcess(
executable: executableUri,
arguments: ['hello', 'world'],
logger: null,
processManager: processManager,
);
expect(result.exitCode, 0);
expect(result.stdout, 'the standard output');
expect(result.stderr, 'the standard error');
// The command list is passed through verbatim, with the executable path
// as the first element.
expect(processManager.invocations.single.command, [
executableUri.toFilePath(),
'hello',
'world',
]);
});
test(
'a non-zero exit code is returned without throwing by default',
() async {
final processManager = FakeProcessManager([
const FakeCommand(exitCode: 3, stderr: 'boom'),
]);
// By default a non-zero exit code is returned, not thrown.
final result = await runProcess(
executable: executableUri,
logger: null,
processManager: processManager,
);
expect(result.exitCode, 3);
expect(result.stderr, 'boom');
},
);
test(
'throwOnUnexpectedExitCode throws on a mismatching exit code',
() async {
final processManager = FakeProcessManager([
const FakeCommand(exitCode: 3),
]);
await expectLater(
runProcess(
executable: executableUri,
logger: null,
processManager: processManager,
throwOnUnexpectedExitCode: true,
),
throwsA(isA<ProcessException>()),
);
},
);
test('forwards the environment and working directory', () async {
final processManager = FakeProcessManager([const FakeCommand()]);
final workingDirectory = Uri.directory('/tmp/work');
await runProcess(
executable: executableUri,
workingDirectory: workingDirectory,
environment: {'FOO': 'BAR'},
logger: null,
processManager: processManager,
);
final invocation = processManager.invocations.single;
expect(invocation.environment, {'FOO': 'BAR'});
expect(invocation.workingDirectory, workingDirectory.toFilePath());
});
test('a matching command is accepted', () async {
final processManager = FakeProcessManager([
FakeCommand(command: [executableUri.toFilePath(), 'hello']),
]);
final result = await runProcess(
executable: executableUri,
arguments: ['hello'],
logger: null,
processManager: processManager,
);
expect(result.exitCode, 0);
expect(processManager.allCommandsConsumed, true);
});
test('allCommandsConsumed is false while commands remain', () async {
final processManager = FakeProcessManager([
const FakeCommand(),
const FakeCommand(),
]);
await runProcess(
executable: executableUri,
logger: null,
processManager: processManager,
);
expect(processManager.allCommandsConsumed, false);
});
test('onRun is invoked with the actual command', () async {
List<String>? seen;
final processManager = FakeProcessManager([
FakeCommand(onRun: (command) => seen = command),
]);
await runProcess(
executable: executableUri,
arguments: ['hello', 'world'],
logger: null,
processManager: processManager,
);
expect(seen, [executableUri.toFilePath(), 'hello', 'world']);
});
test('an exhausted command list throws a StateError', () async {
final processManager = FakeProcessManager([]);
await expectLater(
runProcess(
executable: executableUri,
logger: null,
processManager: processManager,
),
throwsA(isA<StateError>()),
);
});
});
}