public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Michal Fox <me@dualfroz.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH storage 1/3] test: add tests for zpool status parsing of the ZFS disk API
Date: Sat,  3 Oct 2026 12:49:15 +0000	[thread overview]
Message-ID: <20261003124917.7-2-me@dualfroz.com> (raw)
In-Reply-To: <20261003124917.7-1-me@dualfroz.com>

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>
---
The test goes through the API handler, which checks that /sbin/zpool
exists, so it relies on zfsutils-linux from the Build-Depends.

 src/test/run_disk_tests.pl       |   2 +-
 src/test/zfs_pool_detail_test.pm | 165 +++++++++++++++++++++++++++++++
 2 files changed, 166 insertions(+), 1 deletion(-)
 create mode 100644 src/test/zfs_pool_detail_test.pm

diff --git a/src/test/run_disk_tests.pl b/src/test/run_disk_tests.pl
index 5a6af07..b4fd09b 100755
--- a/src/test/run_disk_tests.pl
+++ b/src/test/run_disk_tests.pl
@@ -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};
 
diff --git a/src/test/zfs_pool_detail_test.pm b/src/test/zfs_pool_detail_test.pm
new file mode 100644
index 0000000..a062656
--- /dev/null
+++ b/src/test/zfs_pool_detail_test.pm
@@ -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;
-- 
2.43.0




  reply	other threads:[~2026-10-03 12:49 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-03 12:49 [PATCH storage 0/3] api: disks: zfs: fix error counters and in-use spares in pool details Michal Fox
2026-10-03 12:49 ` Michal Fox [this message]
2026-10-03 12:49 ` [PATCH storage 2/3] fix #6640, #6938: api: disks: zfs: return exact error counters Michal Fox
2026-10-03 12:49 ` [PATCH storage 3/3] fix #6389: api: disks: zfs: parse the message of hot spares in use Michal Fox

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261003124917.7-2-me@dualfroz.com \
    --to=me@dualfroz.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal