blob: 24c5e4373be175d02813549a5960d75e313da3e2 [file] [log] [blame]
// 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.
// @dart = 2.4
import 'dart:async';
import 'dart:io';
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:fuchsia_ctl/fuchsia_ctl.dart';
import 'package:fuchsia_ctl/src/image_paver.dart';
import 'package:fuchsia_ctl/src/operation_result.dart';
import 'package:fuchsia_ctl/src/ssh_key_manager.dart';
import 'package:fuchsia_ctl/src/tar.dart';
import 'package:mockito/mockito.dart';
import 'package:process/process.dart';
import 'package:test/test.dart';
import 'fakes.dart';
void main() {
const String deviceName = 'some-name-to-use';
FakeSshKeyManager sshKeyManager;
final MemoryFileSystem fs = MemoryFileSystem(style: FileSystemStyle.posix);
FakeTar tar;
MockProcessManager processManager;
SshKeyManagerProvider sshKeyManagerProvider;
setUp(() {
processManager = MockProcessManager();
sshKeyManager = const FakeSshKeyManager(true);
sshKeyManagerProvider = ({
ProcessManager processManager,
FileSystem fs,
String publicKeyPath,
}) {
return sshKeyManager;
};
});
test('Tar fails', () async {
tar = FakeTar(false, fs);
when(processManager.start(any)).thenAnswer((_) async {
return FakeProcess(0, <String>['Good job'], <String>['']);
});
final ImagePaver paver = ImagePaver(
tar: tar,
sshKeyManagerProvider: sshKeyManagerProvider,
fs: fs,
processManager: processManager,
);
final OperationResult result = await paver.pave(
'generic-x64.tgz',
deviceName,
verbose: false,
);
verifyNever(processManager.start(any));
expect(result.success, false);
expect(result.error, 'tar failed');
});
test('Ssh fails', () async {
sshKeyManager = const FakeSshKeyManager(false);
tar = FakeTar(true, fs);
when(processManager.start(any)).thenAnswer((_) async {
return FakeProcess(0, <String>['Good job'], <String>['']);
});
final ImagePaver paver = ImagePaver(
tar: tar,
sshKeyManagerProvider: sshKeyManagerProvider,
fs: fs,
processManager: processManager,
);
final OperationResult result = await paver.pave(
'generic-x64.tgz',
deviceName,
verbose: false,
);
verifyNever(processManager.start(any));
expect(result.success, false);
expect(result.error, 'ssh failed');
});
test('Pave times out', () async {
tar = FakeTar(true, fs);
when(processManager.start(any)).thenAnswer((_) async {
return Future<Process>.delayed(const Duration(milliseconds: 10), () {
return FakeProcess(0, <String>['Good job'], <String>['']);
});
});
final ImagePaver paver = ImagePaver(
tar: tar,
sshKeyManagerProvider: sshKeyManagerProvider,
fs: fs,
processManager: processManager,
);
try {
await paver.pave(
'generic-x64.tgz',
deviceName,
verbose: false,
timeoutMs: const Duration(milliseconds: 1),
);
} catch (e) {
expect(e, isA<TimeoutException>());
}
});
test('Happy path', () async {
tar = FakeTar(true, fs);
when(processManager.start(any)).thenAnswer((_) async {
return FakeProcess(0, <String>['Good job'], <String>['']);
});
final ImagePaver paver = ImagePaver(
tar: tar,
sshKeyManagerProvider: sshKeyManagerProvider,
fs: fs,
processManager: processManager,
);
final OperationResult result = await paver.pave(
'generic-x64.tgz',
deviceName,
verbose: false,
);
final List<String> capturedStartArgs = verify(
processManager.start(captureAny),
).captured.cast<List<String>>().single;
expect(capturedStartArgs.first, endsWith('/pave.sh'));
expect(capturedStartArgs.skip(1).toList(), <String>[
'--fail-fast',
'-1',
'--allow-zedboot-version-mismatch',
'-n', deviceName, //
'--authorized-keys', '.ssh/authorized_keys',
]);
expect(result.success, true);
});
}
class FakeTar implements Tar {
const FakeTar(this.passes, this.fs)
: assert(passes != null),
assert(fs != null);
final bool passes;
final MemoryFileSystem fs;
@override
Future<OperationResult> untar(String src, String destination,
{Duration timeoutMs}) async {
if (passes) {
final Directory dir = fs.directory(destination)
..createSync(recursive: true);
dir.childFile('pave.sh').createSync();
return OperationResult.success();
}
return OperationResult.error('tar failed');
}
}
class FakeSshKeyManager implements SshKeyManager {
const FakeSshKeyManager(this.passes);
final bool passes;
@override
Future<OperationResult> createKeys({
String destinationPath = '.ssh',
bool force = false,
}) async {
if (passes) {
return OperationResult.success();
}
return OperationResult.error('ssh failed');
}
}
class MockProcessManager extends Mock implements ProcessManager {}