podman/test/podman_client_system_test.dart

203 lines
6.7 KiB
Dart

import 'package:podman/podman.dart';
import 'package:test/test.dart';
import 'support/fake_podman_transport.dart';
void main() {
group('PodmanClient system API', () {
test('parses version output', () async {
final transport = FakePodmanTransport()
..enqueue(
method: HttpMethod.get,
path: '/v5.0.0/libpod/version',
responseBody: <String, Object?>{
'Client': <String, Object?>{'Version': '5.2.2'},
'Server': <String, Object?>{'Version': '5.2.1'},
},
);
final client = PodmanClient(transport: transport);
final version = await client.version();
expect(version.clientVersion, '5.2.2');
expect(version.serverVersion, '5.2.1');
transport.expectNoPending();
});
test('parses info output', () async {
final transport = FakePodmanTransport()
..enqueue(
method: HttpMethod.get,
path: '/v5.0.0/libpod/info',
responseBody: <String, Object?>{
'host': <String, Object?>{'os': 'linux', 'arch': 'amd64'},
},
);
final client = PodmanClient(transport: transport);
final info = await client.info();
expect(info.hostOs, 'linux');
expect(info.hostArch, 'amd64');
transport.expectNoPending();
});
test('supports system df/check/prune', () async {
final transport = FakePodmanTransport()
..enqueue(
method: HttpMethod.get,
path: '/v5.0.0/libpod/system/df',
responseBody: const <String, Object?>{
'ImagesSize': 12345,
'Images': <Object?>[
<String, Object?>{
'Repository': 'docker.io/library/hello-world',
'Tag': 'latest',
'ImageID': 'sha256:image1',
'Created': '2026-01-01T00:00:00Z',
'Size': 111,
'SharedSize': 0,
'UniqueSize': 111,
'Containers': 1,
},
],
'Containers': <Object?>[
<String, Object?>{
'ContainerID': 'container-1',
'Image': 'docker.io/library/hello-world:latest',
'Command': <String>['/hello'],
'LocalVolumes': 0,
'Size': 222,
'RWSize': 12,
'Created': '2026-01-01T00:01:00Z',
'Status': 'exited',
'Names': 'hello',
},
],
'Volumes': <Object?>[
<String, Object?>{
'VolumeName': 'gv-storage',
'Links': 1,
'Size': 333,
'ReclaimableSize': 111,
},
],
},
)
..enqueue(
method: HttpMethod.post,
path: '/v5.0.0/libpod/system/check',
queryParameters: const <String, List<String>>{
'quick': <String>['true'],
'repair': <String>['true'],
'repair_lossy': <String>['true'],
'unreferenced_layer_max_age': <String>['12h'],
},
responseBody: const <String, Object?>{
'Errors': true,
'Layers': <String, Object?>{
'layer-1': <String>['missing digest'],
},
'ROLayers': <String, Object?>{},
'RemovedLayers': <String>['layer-old'],
'Images': <String, Object?>{
'image-1': <String>['dangling data'],
},
'ROImages': <String, Object?>{},
'RemovedImages': <String, Object?>{
'image-1': <String>['localhost/image:old'],
},
'Containers': <String, Object?>{
'ctr-1': <String>['broken mount'],
},
'RemovedContainers': <String, String>{'ctr-1': 'old-container'},
},
)
..enqueue(
method: HttpMethod.post,
path: '/v5.0.0/libpod/system/prune',
queryParameters: const <String, List<String>>{
'all': <String>['true'],
'volumes': <String>['true'],
'external': <String>['true'],
'build': <String>['true'],
'filters': <String>['{"label":["managed=true"]}'],
},
responseBody: const <String, Object?>{
'PodPruneReport': <Object?>[
<String, Object?>{'Id': 'pod-1'},
],
'ContainerPruneReports': <Object?>[
<String, Object?>{'Id': 'ctr-1', 'Size': 1024},
],
'ImagePruneReports': <Object?>[
<String, Object?>{'Id': 'img-1', 'Size': 2048},
],
'NetworkPruneReports': <Object?>[
<String, Object?>{'Name': 'net-1'},
],
'VolumePruneReports': <Object?>[
<String, Object?>{'Id': 'vol-1', 'Size': 4096},
],
'ReclaimedSpace': 8192,
},
);
final client = PodmanClient(transport: transport);
final df = await client.systemDf();
expect(df.imagesSize, 12345);
expect(df.images, hasLength(1));
expect(df.containers, hasLength(1));
expect(df.volumes, hasLength(1));
expect(df.images.first.imageId, 'sha256:image1');
expect(df.containers.first.containerId, 'container-1');
expect(df.volumes.first.volumeName, 'gv-storage');
final check = await client.systemCheck(
options: const SystemCheckOptions(
quick: true,
repair: true,
repairLossy: true,
unreferencedLayerMaxAge: '12h',
),
);
expect(check.errors, isTrue);
expect(check.layers['layer-1'], contains('missing digest'));
expect(check.removedContainers['ctr-1'], 'old-container');
final prune = await client.systemPrune(
options: const SystemPruneOptions(
all: true,
volumes: true,
external: true,
build: true,
filters: <String, List<String>>{
'label': <String>['managed=true'],
},
),
);
expect(prune.podIds, contains('pod-1'));
expect(prune.containerIds, contains('ctr-1'));
expect(prune.imageIds, contains('img-1'));
expect(prune.networkNames, contains('net-1'));
expect(prune.volumeIds, contains('vol-1'));
expect(prune.reclaimedSpace, 8192);
transport.expectNoPending();
});
test('throws parse exception on invalid JSON', () async {
final transport = FakePodmanTransport()
..enqueue(
method: HttpMethod.get,
path: '/v5.0.0/libpod/version',
responseBody: '{invalid-json',
);
final client = PodmanClient(transport: transport);
await expectLater(client.version(), throwsA(isA<PodmanParseException>()));
});
});
}