podman/test/podman_client_container_checkpoint_test.dart

140 lines
4.7 KiB
Dart

import 'package:podman/podman.dart';
import 'package:test/test.dart';
import 'support/fake_podman_transport.dart';
void main() {
group('PodmanClient container checkpoint API', () {
test('supports checkpoint/export/restore flows', () async {
final checkpointArchiveBytes = <int>[1, 2, 3, 4];
final restoreArchiveBytes = <int>[9, 8, 7, 6];
final transport = FakePodmanTransport()
..enqueue(
method: HttpMethod.post,
path: '/v5.0.0/libpod/containers/web/checkpoint',
queryParameters: const <String, List<String>>{
'keep': <String>['true'],
'leaveRunning': <String>['true'],
'tcpEstablished': <String>['true'],
'ignoreRootFS': <String>['true'],
'printStats': <String>['true'],
'preCheckpoint': <String>['true'],
'withPrevious': <String>['true'],
'fileLocks': <String>['true'],
'createImage': <String>['checkpoint/web:v1'],
},
responseBody: const <String, Object?>{
'Id': 'container-123',
'runtime_checkpoint_duration': 42,
'criu_statistics': <String, Object?>{'freezing_time': 2},
},
)
..enqueue(
method: HttpMethod.post,
path: '/v5.0.0/libpod/containers/web/checkpoint',
queryParameters: const <String, List<String>>{
'keep': <String>['true'],
'export': <String>['true'],
},
responseBody: checkpointArchiveBytes,
)
..enqueue(
method: HttpMethod.post,
path: '/v5.0.0/libpod/containers/web/restore',
queryParameters: const <String, List<String>>{
'keep': <String>['true'],
'tcpEstablished': <String>['true'],
'ignoreStaticIP': <String>['true'],
'printStats': <String>['true'],
'publishPorts': <String>['8080:80'],
'pod': <String>['groupware-services'],
},
responseBody: const <String, Object?>{
'Id': 'container-123',
'runtime_restore_duration': 55,
'criu_statistics': <String, Object?>{'restore_time': 3},
},
)
..enqueue(
method: HttpMethod.post,
path: '/v5.0.0/libpod/containers/import/restore',
queryParameters: const <String, List<String>>{
'name': <String>['web-restored'],
'import': <String>['true'],
'ignoreRootFS': <String>['true'],
'ignoreVolumes': <String>['true'],
},
body: restoreArchiveBytes,
responseBody: const <String, Object?>{
'Id': 'container-456',
'runtime_restore_duration': 12,
'criu_statistics': <String, Object?>{},
},
);
final client = PodmanClient(transport: transport);
final checkpoint = await client.checkpointContainer(
'web',
options: const ContainerCheckpointOptions(
keep: true,
leaveRunning: true,
tcpEstablished: true,
ignoreRootFs: true,
printStats: true,
preCheckpoint: true,
withPrevious: true,
fileLocks: true,
createImage: 'checkpoint/web:v1',
),
);
expect(checkpoint.id, 'container-123');
expect(checkpoint.runtimeDuration, 42);
expect(checkpoint.criuStatistics['freezing_time'], 2);
final exported = await client.exportContainerCheckpoint(
'web',
options: const ContainerCheckpointOptions(keep: true),
);
expect(exported, checkpointArchiveBytes);
final restored = await client.restoreContainer(
'web',
options: const ContainerRestoreOptions(
keep: true,
tcpEstablished: true,
ignoreStaticIp: true,
printStats: true,
publishPorts: <String>['8080:80'],
pod: 'groupware-services',
),
);
expect(restored.id, 'container-123');
expect(restored.runtimeDuration, 55);
expect(restored.criuStatistics['restore_time'], 3);
final imported = await client.restoreContainerFromArchive(
restoreArchiveBytes,
options: const ContainerRestoreOptions(
name: 'web-restored',
ignoreRootFs: true,
ignoreVolumes: true,
),
);
expect(imported.id, 'container-456');
expect(imported.runtimeDuration, 12);
transport.expectNoPending();
});
test('restoreContainerFromArchive validates non-empty bytes', () async {
final client = PodmanClient(transport: FakePodmanTransport());
expect(
() => client.restoreContainerFromArchive(const <int>[]),
throwsArgumentError,
);
});
});
}