import 'package:podman/podman.dart'; import 'package:test/test.dart'; import 'support/fake_podman_transport.dart'; void main() { group('PodmanClient pod API', () { test('checks whether a pod exists', () async { final transport = FakePodmanTransport() ..enqueue( method: HttpMethod.get, path: '/v5.0.0/libpod/pods/groupware/exists', statusCode: 204, ) ..enqueue( method: HttpMethod.get, path: '/v5.0.0/libpod/pods/missing/exists', statusCode: 404, ); final client = PodmanClient(transport: transport); expect(await client.podExists('groupware'), isTrue); expect(await client.podExists('missing'), isFalse); transport.expectNoPending(); }); test('lists pods', () async { final transport = FakePodmanTransport() ..enqueue( method: HttpMethod.get, path: '/v5.0.0/libpod/pods/json', responseBody: [ { 'Id': 'pod-1', 'Name': 'groupware', 'Status': 'Running', 'Cgroup': 'user.slice', 'NumberOfContainers': 3, 'Labels': {'stack': 'groupware'}, }, ], ); final client = PodmanClient(transport: transport); final pods = await client.listPods(); expect(pods, hasLength(1)); expect(pods.first.id, 'pod-1'); expect(pods.first.name, 'groupware'); expect(pods.first.containers, 3); transport.expectNoPending(); }); test('supports create, inspect, start, stop, and remove', () async { final transport = FakePodmanTransport() ..enqueue( method: HttpMethod.post, path: '/v5.0.0/libpod/pods/create', body: const { 'name': 'groupware', 'labels': {'stack': 'groupware'}, 'infra': true, }, statusCode: 201, responseBody: const {'Id': 'pod-1'}, ) ..enqueue( method: HttpMethod.get, path: '/v5.0.0/libpod/pods/pod-1/json', responseBody: const { 'Id': 'pod-1', 'Name': 'groupware', 'State': 'Created', 'Containers': [], 'Labels': {'stack': 'groupware'}, }, ) ..enqueue( method: HttpMethod.get, path: '/v5.0.0/libpod/pods/groupware/json', responseBody: const { 'Id': 'pod-1', 'Name': 'groupware', 'State': 'Created', 'Containers': [], }, ) ..enqueue( method: HttpMethod.post, path: '/v5.0.0/libpod/pods/groupware/start', statusCode: 200, ) ..enqueue( method: HttpMethod.post, path: '/v5.0.0/libpod/pods/groupware/stop', queryParameters: const >{ 't': ['3'], }, statusCode: 200, ) ..enqueue( method: HttpMethod.delete, path: '/v5.0.0/libpod/pods/groupware', queryParameters: const >{ 'force': ['true'], }, statusCode: 200, ); final client = PodmanClient(transport: transport); final created = await client.createPod( const PodCreateOptions( name: 'groupware', labels: {'stack': 'groupware'}, ), ); expect(created.id, 'pod-1'); final inspected = await client.inspectPod('groupware'); expect(inspected.name, 'groupware'); await client.startPod('groupware'); await client.stopPod('groupware', timeoutSeconds: 3); await client.removePod('groupware', force: true); transport.expectNoPending(); }); test('supports pod admin, top, stats, and prune endpoints', () async { final transport = FakePodmanTransport() ..enqueue( method: HttpMethod.post, path: '/v5.0.0/libpod/pods/groupware/kill', queryParameters: const >{ 'signal': ['SIGTERM'], }, statusCode: 200, ) ..enqueue( method: HttpMethod.post, path: '/v5.0.0/libpod/pods/groupware/pause', statusCode: 200, ) ..enqueue( method: HttpMethod.post, path: '/v5.0.0/libpod/pods/groupware/restart', statusCode: 200, ) ..enqueue( method: HttpMethod.post, path: '/v5.0.0/libpod/pods/groupware/unpause', statusCode: 200, ) ..enqueue( method: HttpMethod.get, path: '/v5.0.0/libpod/pods/groupware/top', queryParameters: const >{ 'ps_args': ['aux'], }, responseBody: const { 'Titles': ['PID', 'USER', 'COMMAND'], 'Processes': [ ['1', 'root', '/pause'], ], }, ) ..enqueue( method: HttpMethod.get, path: '/v5.0.0/libpod/pods/stats', queryParameters: const >{ 'namesOrIDs': ['groupware'], }, responseBody: const [ { 'Pod': 'pod-1', 'CID': 'ctr-1', 'Name': 'groupware', 'CPU': '2.5%', 'MemUsage': '12MiB / 1GiB', 'MemUsageBytes': '12582912 / 1073741824', 'Mem': '1.2%', 'NetIO': '5kB / 2kB', 'BlockIO': '0B / 0B', 'PIDS': '4', }, ], ) ..enqueue( method: HttpMethod.post, path: '/v5.0.0/libpod/pods/prune', responseBody: const [ {'Id': 'pod-old'}, ], ); final client = PodmanClient(transport: transport); await client.killPod('groupware', signal: 'SIGTERM'); await client.pausePod('groupware'); await client.restartPod('groupware'); await client.unpausePod('groupware'); final top = await client.topPod( 'groupware', options: const PodTopOptions(psArgs: 'aux'), ); expect(top.titles, ['PID', 'USER', 'COMMAND']); expect(top.processes, >[ ['1', 'root', '/pause'], ]); final stats = await client.podStats( options: const PodStatsOptions(namesOrIds: ['groupware']), ); expect(stats, hasLength(1)); expect(stats.single.podId, 'pod-1'); expect(stats.single.cpuPercent, '2.5%'); final pruned = await client.prunePods(); expect(pruned, hasLength(1)); expect(pruned.single.id, 'pod-old'); transport.expectNoPending(); }); test('watchPodStats and watchPodTop emit polling snapshots', () async { final transport = FakePodmanTransport() ..enqueue( method: HttpMethod.get, path: '/v5.0.0/libpod/pods/stats', queryParameters: const >{ 'namesOrIDs': ['groupware'], }, responseBody: const [ { 'Pod': 'pod-1', 'CID': 'ctr-1', 'Name': 'groupware', 'CPU': '1.0%', 'MemUsage': '10MiB / 1GiB', 'MemUsageBytes': '10485760 / 1073741824', 'Mem': '1.0%', 'NetIO': '1kB / 1kB', 'BlockIO': '0B / 0B', 'PIDS': '3', }, ], ) ..enqueue( method: HttpMethod.get, path: '/v5.0.0/libpod/pods/groupware/top', responseBody: const { 'Titles': ['PID', 'CMD'], 'Processes': [ ['1', '/pause'], ], }, ); final client = PodmanClient(transport: transport); final stats = await client .watchPodStats( options: const PodStatsOptions(namesOrIds: ['groupware']), pollInterval: const Duration(milliseconds: 1), reconnect: false, ) .first; expect(stats, hasLength(1)); expect(stats.single.podId, 'pod-1'); final top = await client .watchPodTop( 'groupware', pollInterval: const Duration(milliseconds: 1), reconnect: false, ) .first; expect(top.processes, hasLength(1)); transport.expectNoPending(); }); }); }