Am 11.02.25 um 17:08 schrieb Daniel Kral: > Adds test cases for the alloc_disk wrapper subroutine to ensure that: > > - zero-sized volumes are allocated as subvols on path-based storages > - non-zero-sized volumes are allocated as raw on path-based storages > - volumes are allocated as raw on btrfs storages without quotas > - volumes are allocated as subvols on btrfs storages with quotas > - volumes are allocated as subvols on zfs storages > - volumes cannot be allocated on storages that do not support rootdir > > These test cases should allow to catch regressions in following changes > to the alloc_disk wrapper.
Always nice to have such tests up-front :) > diff --git a/src/test/run_alloc_disk_tests.pl > b/src/test/run_alloc_disk_tests.pl > new file mode 100755 > index 0000000..b13f5a2 > --- /dev/null > +++ b/src/test/run_alloc_disk_tests.pl > @@ -0,0 +1,149 @@ > +#!/usr/bin/env perl > + > +use strict; > +use warnings; > + > +use lib qw(..); > + > +use PVE::Tools; > + > +use Test::More; > +use Test::MockModule; > + > +use PVE::LXC; > + > +my $test_vmid = 100; > +my $test_root_uid = 100000; > +my $test_root_gid = 100000; > + > +my $storage_config = { > + ids => { > + local => { > + content => { > + rootdir => 1, > + }, > + path => "/var/lib/vz", > + type => "dir", > + shared => 0, > + }, > + norootdirs => { Similar to the qemu-server patch: I'd add some other content to the hash, just so it's slightly more realistic. > + path => '/var/lib/vz', > + type => 'dir',> + }, > + btrfsstore => { > + content => { > + rootdir => 1, > + }, > + path => '/butter/bread', > + type => 'btrfs', > + }, > + btrfsquotas => { > + content => { > + rootdir => 1, > + }, > + path => '/butter/bread', > + type => 'btrfs', > + quotas => 1, > + }, > + zfspool0 => { > + type => 'zfspool', > + content => { > + rootdir => 1, > + }, > + pool => 'rpool0', > + mountpoint => '/zfspool0', > + }, > + }, > +}; > + > +my $storage_module = Test::MockModule->new("PVE::Storage"); > +$storage_module->redefine( > + vdisk_alloc => sub { > + my ($storecfg, $storage, $vmid, $fmt, $name, $size_kb) = @_; > + > + $fmt //= ''; > + my $prefix = ($fmt eq 'subvol') ? 'subvol' : 'vm'; > + > + return "$storage:$prefix-$vmid-disk-0"; Nit: To have the tests be slightly more complete, you could have additional global variables for size and format, similar to how you keep track of $format_disk_called. But not too important. > + }, > +); > + > +my $format_disk_called = 0; > + > +my $lxc_module = Test::MockModule->new("PVE::LXC"); > +$lxc_module->redefine( > + format_disk => sub { > + $format_disk_called = 1; > + }, > +); > + > +my $tests = [ > + { > + description => 'allocate zero-sized volume on path-based storage', > + storage => 'local', > + size_kb => 0, > + result => ["local:subvol-$test_vmid-disk-0", 1], > + }, > + { > + description => 'allocate non-zero-sized volume on path-based storage', > + should_format_disk => 1, > + storage => 'local', > + size_kb => 1024 * 1024, > + result => ["local:vm-$test_vmid-disk-0", 0], > + }, > + { > + description => 'allocate volume on btrfs with quotas disabled', > + should_format_disk => 1, > + storage => 'btrfsstore', > + size_kb => 1024 * 1024, > + result => ["btrfsstore:vm-$test_vmid-disk-0", 0], > + }, > + { > + description => 'allocate volume on btrfs with quotas enabled', > + storage => 'btrfsquotas', > + size_kb => 1024 * 1024, > + result => ["btrfsquotas:subvol-$test_vmid-disk-0", 1], > + }, > + { > + description => 'allocate volume on zfspool', > + storage => 'zfspool0', > + size_kb => 1024 * 1024, > + result => ["zfspool0:subvol-$test_vmid-disk-0", 1], > + }, > + { > + description => 'allocate volume on storage without rootdir content type > support', > + should_fail => 1, > + storage => 'norootdirs', > + size_kb => 1024 * 1024, > + }, > +]; > + > +# multiply by 2 because of format_disk test > +plan(tests => 2 * scalar($tests->@*)); > + > +for my $case ($tests->@*) { > + my $should_format_disk = exists($case->{should_format_disk}) ? > $case->{should_format_disk} : 0; > + $format_disk_called = 0; > + > + my @result = eval { I'd prefer to be explicit: my ($volid, $needs_chown) = eval { > + PVE::LXC::alloc_disk( > + $storage_config, > + $test_vmid, > + $case->{storage}, > + $case->{size_kb}, > + $test_root_uid, > + $test_root_gid > + ) > + }; > + Style nit: I'd avoid the blank line here to make it less likely for future code to sneak in > + if ($@) { Style nit: if (my $err = $@) { and then use $err. Because what if somebody changes the $should_fail assignment to a function call in the future or adds another line in between, then you might suddenly have a different $@ in the check below. > + my $should_fail = exists($case->{should_fail}) ? $case->{should_fail} : > 0; > + is(defined($@), $should_fail, "should fail: $case->{description}") || > diag explain $@; I'd just write 1 instead of defined($@), because we are already in the failure branch. Note that defined($@) would otherwise return 'undef', so comparing against 0 wouldn't work either. And note this requires $should_fail to be exactly 1 and not some other true value. So I'd prefer using something like: if ($should_fail) { pass(...) } else { diag ... fail(...) } > + } else { > + is_deeply(\@result, $case->{result}, $case->{description}); > + } > + > + is($format_disk_called, $should_format_disk, "should format_disk: > $case->{description}"); > +} > + > +done_testing(); _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel