test: add tests for zpool status parsing of the ZFS disk API

The detail call of the ZFS disk API parses the output of 'zpool status'
into the vdev tree of a pool. Add a test for it, which mocks the zpool
command and checks the result for a healthy pool with log, cache and
spare devices, so that fixes for the parser can extend it with their
cases.

Signed-off-by: Michal Fox <me@dualfroz.com>
This commit is contained in:
dualfroz committed 2026-10-02 16:14:52 +02:00
1 parent f0e989f1dc
commit ab748c8530
2 files changed
+166 -1

No files matched your search

+1 -1
View File
@@ -6,7 +6,7 @@ use warnings;
use TAP::Harness;
my $harness = TAP::Harness->new({ verbosity => -2 });
my $res = $harness->runtests("disklist_test.pm");
my $res = $harness->runtests("disklist_test.pm", "zfs_pool_detail_test.pm");
exit -1 if !$res || $res->{failed} || $res->{parse_errors};
+165
View File
@@ -0,0 +1,165 @@
package PVE::API2::Disks::ZFS::TestPoolDetail;
use strict;
use warnings;
use lib qw(..);
use PVE::API2::Disks::ZFS;
use Test::More;
use Test::MockModule;
my $zpool_status_output;
my $zfs_api_module = Test::MockModule->new('PVE::API2::Disks::ZFS');
$zfs_api_module->mock(
run_command => sub {
my ($cmd, %param) = @_;
my $cmdline = join(' ', @$cmd);
die "unexpected run_command call: '$cmdline'\n"
if $cmdline ne '/sbin/zpool status -P tank';
$param{outfunc}->($_) for split(/\n/, $zpool_status_output);
return 0;
},
);
# each test is comprised of the following keys:
# description => what the test is about
# status => output of 'zpool status' for the pool 'tank'
# expected => pool details as returned by the API
my $tests = [
{
description => 'healthy pool with log, cache and spare',
status => <<"EOF",
pool: tank
state: ONLINE
scan: scrub repaired 0B in 00:00:01 with 0 errors on Sun Sep 13 00:24:02 2026
config:
\tNAME STATE READ WRITE CKSUM
\ttank ONLINE 0 0 0
\t mirror-0 ONLINE 0 0 0
\t /dev/disk/by-id/ata-DISK_A-part1 ONLINE 0 0 0
\t /dev/disk/by-id/ata-DISK_B-part1 ONLINE 0 0 0
\tlogs
\t /dev/disk/by-id/nvme-LOG-part1 ONLINE 0 0 0
\tcache
\t /dev/disk/by-id/nvme-CACHE-part1 ONLINE 0 0 0
\tspares
\t /dev/disk/by-id/ata-DISK_C-part1 AVAIL
errors: No known data errors
EOF
expected => {
name => 'tank',
state => 'ONLINE',
scan => 'scrub repaired 0B in 00:00:01 with 0 errors on Sun Sep 13 00:24:02 2026',
errors => 'No known data errors',
leaf => 0,
children => [
{
name => 'tank',
state => 'ONLINE',
read => 0,
write => 0,
cksum => 0,
msg => '',
leaf => 0,
children => [
{
name => 'mirror-0',
state => 'ONLINE',
read => 0,
write => 0,
cksum => 0,
msg => '',
leaf => 0,
children => [
{
name => '/dev/disk/by-id/ata-DISK_A-part1',
state => 'ONLINE',
read => 0,
write => 0,
cksum => 0,
msg => '',
leaf => 1,
},
{
name => '/dev/disk/by-id/ata-DISK_B-part1',
state => 'ONLINE',
read => 0,
write => 0,
cksum => 0,
msg => '',
leaf => 1,
},
],
},
],
},
{
name => 'logs',
msg => '',
leaf => 0,
children => [
{
name => '/dev/disk/by-id/nvme-LOG-part1',
state => 'ONLINE',
read => 0,
write => 0,
cksum => 0,
msg => '',
leaf => 1,
},
],
},
{
name => 'cache',
msg => '',
leaf => 0,
children => [
{
name => '/dev/disk/by-id/nvme-CACHE-part1',
state => 'ONLINE',
read => 0,
write => 0,
cksum => 0,
msg => '',
leaf => 1,
},
],
},
{
name => 'spares',
msg => '',
leaf => 0,
children => [
{
name => '/dev/disk/by-id/ata-DISK_C-part1',
state => 'AVAIL',
msg => '',
leaf => 1,
},
],
},
],
},
},
];
plan tests => scalar @$tests;
for my $test (@$tests) {
$zpool_status_output = $test->{status};
my $pool = eval { PVE::API2::Disks::ZFS->detail({ node => 'localhost', name => 'tank' }) };
diag("unexpected error: $@") if $@;
is_deeply($pool, $test->{expected}, $test->{description});
}
done_testing();
1;