Test to reduce the potential for accidental breakage on regex changes. Signed-off-by: Alwin Antreich <a.antre...@proxmox.com> --- test/run_parser_tests.pl | 6 +- test/test_list_volumes.pm | 309 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 test/test_list_volumes.pm
diff --git a/test/run_parser_tests.pl b/test/run_parser_tests.pl index 79093aa..4b1c003 100755 --- a/test/run_parser_tests.pl +++ b/test/run_parser_tests.pl @@ -6,7 +6,11 @@ use warnings; use TAP::Harness; my $harness = TAP::Harness->new( { verbosity => -1 }); -my $res = $harness->runtests("test_archive_info.pm", "test_parse_volname.pm"); +my $res = $harness->runtests( + "test_archive_info.pm", + "test_parse_volname.pm", + "test_list_volumes.pm", +); exit -1 if !$res || $res->{failed} || $res->{parse_errors}; diff --git a/test/test_list_volumes.pm b/test/test_list_volumes.pm new file mode 100644 index 0000000..4b3fdb7 --- /dev/null +++ b/test/test_list_volumes.pm @@ -0,0 +1,309 @@ +package PVE::Storage::TestListVolumes; + +BEGIN { + use constant DEFAULT_SIZE => 131072; # 128 kiB + use constant DEFAULT_USED => 262144; # 256 kiB + use constant DEFAULT_CTIME => 1234567890; + + # override the build-in stat routine to fix output values + # used in $get_subdir_files + *CORE::GLOBAL::stat = sub { + my ($fn) = shift; + my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, + $mtime, $ctime, $blksize, $blocks) = CORE::stat($fn); + + # fixed: file creation time + $ctime = DEFAULT_CTIME; + $size = DEFAULT_SIZE; + + return ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, + $mtime, $ctime, $blksize, $blocks); + }; +} + +use strict; +use warnings; + +use lib qw(..); + +use PVE::Storage; +use PVE::Cluster; +use PVE::Tools qw(run_command); + +use Test::More; +use Test::MockModule; + +use Cwd; +use File::Basename; +use File::Path qw(make_path remove_tree); + +# get_vmlist() return values +my $vmlist = { + 'version' => 1, + 'ids' => { + '16110' => { + 'version' => 4, + 'node' => 'x42', + 'type' => 'qemu' + }, + '16112' => { + 'type' => 'lxc', + 'version' => 7, + 'node' => 'x42' + }, + '16114' => { + 'type' => 'qemu', + 'node' => 'x42', + 'version' => 2 + }, + '16113' => { + 'version' => 5, + 'node' => 'x42', + 'type' => 'qemu' + }, + '16115' => { + 'node' => 'x42', + 'version' => 1, + 'type' => 'qemu' + }, + '9004' => { + 'type' => 'qemu', + 'version' => 6, + 'node' => 'x42' + } + } +}; + +my $storage_dir = getcwd() . '/test_list_volumes'; +my $scfg = { + 'type' => 'dir', + 'maxfiles' => 0, + 'path' => $storage_dir, + 'shared' => 0, + 'content' => { + 'iso' => 1, + 'rootdir' => 1, + 'vztmpl' => 1, + 'images' => 1, + 'snippets' => 1, + 'backup' => 1, + }, +}; +my @tests = ( + { + vmid => '16110', + files => [ + "$storage_dir/images/16110/vm-16110-disk-0.qcow2", + "$storage_dir/images/16110/vm-16110-disk-1.qcow2", + "$storage_dir/images/16110/vm-16110-disk-2.qcow2", + "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_11_40.vma.gz", + "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_12_45.vma.lzo", + "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_13_55.vma", + "$storage_dir/snippets/userconfig.yaml", + "$storage_dir/snippets/hookscript.pl", + ], + expected => [ + { 'content' => 'images', 'ctime' => DEFAULT_CTIME, 'format' => 'qcow2', 'parent' => undef, 'size' => DEFAULT_SIZE, 'used' => DEFAULT_USED, 'vmid' => '16110', 'volid' => 'local:16110/vm-16110-disk-0.qcow2' }, + { 'content' => 'images', 'ctime' => DEFAULT_CTIME, 'format' => 'qcow2', 'parent' => undef, 'size' => DEFAULT_SIZE, 'used' => DEFAULT_USED, 'vmid' => '16110', 'volid' => 'local:16110/vm-16110-disk-1.qcow2' }, + { 'content' => 'images', 'ctime' => DEFAULT_CTIME, 'format' => 'qcow2', 'parent' => undef, 'size' => DEFAULT_SIZE, 'used' => DEFAULT_USED, 'vmid' => '16110', 'volid' => 'local:16110/vm-16110-disk-2.qcow2' }, + { 'content' => 'backup', 'ctime' => DEFAULT_CTIME, 'format' => 'vma.gz', 'size' => DEFAULT_SIZE, 'vmid' => '16110', 'volid' => 'local:backup/vzdump-qemu-16110-2020_03_30-21_11_40.vma.gz' }, + { 'content' => 'backup', 'ctime' => DEFAULT_CTIME, 'format' => 'vma.lzo', 'size' => DEFAULT_SIZE, 'vmid' => '16110', 'volid' => 'local:backup/vzdump-qemu-16110-2020_03_30-21_12_45.vma.lzo' }, + { 'content' => 'backup', 'ctime' => DEFAULT_CTIME, 'format' => 'vma', 'size' => DEFAULT_SIZE, 'vmid' => '16110', 'volid' => 'local:backup/vzdump-qemu-16110-2020_03_30-21_13_55.vma' }, + { 'content' => 'snippets', 'ctime' => DEFAULT_CTIME, 'format' => 'snippet', 'size' => DEFAULT_SIZE, 'volid' => 'local:snippets/hookscript.pl' }, + { 'content' => 'snippets', 'ctime' => DEFAULT_CTIME, 'format' => 'snippet', 'size' => DEFAULT_SIZE, 'volid' => 'local:snippets/userconfig.yaml' }, + ], + description => 'VMID: 16110, VM, qcow2, backup, snippets', + }, + { + vmid => '16112', + files => [ + "$storage_dir/images/16112/vm-16112-disk-0.raw", + "$storage_dir/dump/vzdump-lxc-16112-2020_03_30-21_39_30.tar.lzo", + "$storage_dir/dump/vzdump-lxc-16112-2020_03_30-21_49_30.tar.gz", + "$storage_dir/dump/vzdump-lxc-16112-2020_03_30-21_59_30.tgz", + ], + expected => [ + { 'content' => 'rootdir', 'ctime' => DEFAULT_CTIME, 'format' => 'raw', 'parent' => undef, 'size' => DEFAULT_SIZE, 'used' => DEFAULT_USED, 'vmid' => '16112', 'volid' => 'local:16112/vm-16112-disk-0.raw' }, + { 'content' => 'backup', 'ctime' => DEFAULT_CTIME, 'format' => 'tar.lzo', 'size' => DEFAULT_SIZE, 'vmid' => '16112', 'volid' => 'local:backup/vzdump-lxc-16112-2020_03_30-21_39_30.tar.lzo' }, + { 'content' => 'backup', 'ctime' => DEFAULT_CTIME, 'format' => 'tar.gz', 'size' => DEFAULT_SIZE, 'vmid' => '16112', 'volid' => 'local:backup/vzdump-lxc-16112-2020_03_30-21_49_30.tar.gz' }, + { 'content' => 'backup', 'ctime' => DEFAULT_CTIME, 'format' => 'tgz', 'size' => DEFAULT_SIZE, 'vmid' => '16112', 'volid' => 'local:backup/vzdump-lxc-16112-2020_03_30-21_59_30.tgz' }, + ], + description => 'VMID: 16112, lxc, raw, backup', + }, + { + vmid => '16113', + files => [ + "$storage_dir/images/16113/vm-16113-disk-0.raw", + "$storage_dir/images/16113/vm-16113-disk-1.raw", + "$storage_dir/images/16113/vm-16113-disk-2.raw", + "$storage_dir/images/16113/vm-16113-disk-3.raw", + ], + expected => [ + { 'content' => 'images', 'ctime' => DEFAULT_CTIME, 'format' => 'raw', 'parent' => undef, 'size' => DEFAULT_SIZE, 'used' => DEFAULT_USED, 'vmid' => '16113', 'volid' => 'local:16113/vm-16113-disk-0.raw' }, + { 'content' => 'images', 'ctime' => DEFAULT_CTIME, 'format' => 'raw', 'parent' => undef, 'size' => DEFAULT_SIZE, 'used' => DEFAULT_USED, 'vmid' => '16113', 'volid' => 'local:16113/vm-16113-disk-1.raw' }, + { 'content' => 'images', 'ctime' => DEFAULT_CTIME, 'format' => 'raw', 'parent' => undef, 'size' => DEFAULT_SIZE, 'used' => DEFAULT_USED, 'vmid' => '16113', 'volid' => 'local:16113/vm-16113-disk-2.raw' }, + { 'content' => 'images', 'ctime' => DEFAULT_CTIME, 'format' => 'raw', 'parent' => undef, 'size' => DEFAULT_SIZE, 'used' => DEFAULT_USED, 'vmid' => '16113', 'volid' => 'local:16113/vm-16113-disk-3.raw' }, + ], + description => 'VMID: 16113, VM, raw images only', + }, + { + vmid => '16114', + files => [ + "$storage_dir/images/16114/vm-16114-disk-0.qcow2", + "$storage_dir/images/16114/vm-16114-disk-1.qcow2", + ], + parent => [ + "../9004/base-9004-disk-0.qcow2", + "../9004/base-9004-disk-1.qcow2", + ], + expected => [ + { 'content' => 'images', 'ctime' => DEFAULT_CTIME, 'format' => 'qcow2', 'parent' => '../9004/base-9004-disk-0.qcow2', 'size' => DEFAULT_SIZE, 'used' => DEFAULT_USED, 'vmid' => '16114', 'volid' => 'local:9004/base-9004-disk-0.qcow2/16114/vm-16114-disk-0.qcow2' }, + { 'content' => 'images', 'ctime' => DEFAULT_CTIME, 'format' => 'qcow2', 'parent' => '../9004/base-9004-disk-1.qcow2', 'size' => DEFAULT_SIZE, 'used' => DEFAULT_USED, 'vmid' => '16114', 'volid' => 'local:9004/base-9004-disk-1.qcow2/16114/vm-16114-disk-1.qcow2' }, + ], + description => 'VMID: 16114, VM, qcow2, linked clone', + }, + { + vmid => '16115', + files => [ "$storage_dir/images/16115/vm-16115-disk-0.vmdk", ], + expected => [ { 'content' => 'images', 'ctime' => DEFAULT_CTIME, 'format' => 'vmdk', 'parent' => undef, 'size' => DEFAULT_SIZE, 'used' => DEFAULT_USED, 'vmid' => '16115', 'volid' => 'local:16115/vm-16115-disk-0.vmdk' }, ], + description => 'VMID: 16115, VM, vmdk', + }, + { vmid => '9004', + files => [ + "$storage_dir/images/9004/base-9004-disk-0.qcow2", + "$storage_dir/images/9004/base-9004-disk-1.qcow2", + ], + expected => [ + { 'content' => 'images', 'ctime' => DEFAULT_CTIME, 'format' => 'qcow2', 'parent' => undef, 'size' => DEFAULT_SIZE, 'used' => DEFAULT_USED, 'vmid' => '9004', 'volid' => 'local:9004/base-9004-disk-0.qcow2' }, + { 'content' => 'images', 'ctime' => DEFAULT_CTIME, 'format' => 'qcow2', 'parent' => undef, 'size' => DEFAULT_SIZE, 'used' => DEFAULT_USED, 'vmid' => '9004', 'volid' => 'local:9004/base-9004-disk-1.qcow2' }, + ], + description => 'VMID: 9004, VM, template, qcow2', + }, + { + vmid => undef, + files => [ + "$storage_dir/dump/vzdump-lxc-19253-2020_02_03-19_57_43.tar.gz", + "$storage_dir/dump/vzdump-lxc-19254-2019_01_21-19_29_19.tar", + "$storage_dir/template/iso/archlinux-2020.02.01-x86_64.iso", + "$storage_dir/template/iso/debian-8.11.1-amd64-DVD-1.iso", + "$storage_dir/template/iso/debian-9.12.0-amd64-netinst.iso", + "$storage_dir/template/iso/proxmox-ve_6.1-1.iso", + "$storage_dir/template/cache/archlinux-base_20190924-1_amd64.tar.gz", + "$storage_dir/template/cache/debian-10.0-standard_10.0-1_amd64.tar.gz", + "$storage_dir/template/cache/alpine-3.10-default_20190626_amd64.tar.xz", + "$storage_dir/snippets/userconfig.yaml", + "$storage_dir/snippets/hookscript.pl", + "$storage_dir/private/1234/", # fileparse needs / at the end + "$storage_dir/private/1234/subvol-1234-disk-0.subvol/", # fileparse needs / at the end + ], + expected => [ + { 'content' => 'vztmpl', 'ctime' => DEFAULT_CTIME, 'format' => 'txz', 'size' => DEFAULT_SIZE, 'volid' => 'local:vztmpl/alpine-3.10-default_20190626_amd64.tar.xz' }, + { 'content' => 'vztmpl', 'ctime' => DEFAULT_CTIME, 'format' => 'tgz', 'size' => DEFAULT_SIZE, 'volid' => 'local:vztmpl/archlinux-base_20190924-1_amd64.tar.gz' }, + { 'content' => 'vztmpl', 'ctime' => DEFAULT_CTIME, 'format' => 'tgz', 'size' => DEFAULT_SIZE, 'volid' => 'local:vztmpl/debian-10.0-standard_10.0-1_amd64.tar.gz' }, + + { 'content' => 'iso', 'ctime' => DEFAULT_CTIME , 'format' => 'iso', 'size' => DEFAULT_SIZE, 'volid' => 'local:iso/archlinux-2020.02.01-x86_64.iso' }, + { 'content' => 'iso', 'ctime' => DEFAULT_CTIME , 'format' => 'iso', 'size' => DEFAULT_SIZE, 'volid' => 'local:iso/debian-8.11.1-amd64-DVD-1.iso' }, + { 'content' => 'iso', 'ctime' => DEFAULT_CTIME , 'format' => 'iso', 'size' => DEFAULT_SIZE, 'volid' => 'local:iso/debian-9.12.0-amd64-netinst.iso' }, + { 'content' => 'iso', 'ctime' => DEFAULT_CTIME , 'format' => 'iso', 'size' => DEFAULT_SIZE, 'volid' => 'local:iso/proxmox-ve_6.1-1.iso' }, + + { 'content' => 'backup', 'ctime' => DEFAULT_CTIME, 'format' => 'tar.gz', 'size' => DEFAULT_SIZE, 'vmid' => '19253', 'volid' => 'local:backup/vzdump-lxc-19253-2020_02_03-19_57_43.tar.gz' }, + { 'content' => 'backup', 'ctime' => DEFAULT_CTIME, 'format' => 'tar', 'size' => DEFAULT_SIZE, 'vmid' => '19254', 'volid' => 'local:backup/vzdump-lxc-19254-2019_01_21-19_29_19.tar' }, + + { 'content' => 'snippets', 'ctime' => DEFAULT_CTIME, 'format' => 'snippet', 'size' => DEFAULT_SIZE, 'volid' => 'local:snippets/hookscript.pl' }, + { 'content' => 'snippets', 'ctime' => DEFAULT_CTIME, 'format' => 'snippet', 'size' => DEFAULT_SIZE, 'volid' => 'local:snippets/userconfig.yaml' }, + ], + description => 'VMID: none, templates, snippets, backup', + }, + { + # string instead of vmid in folder + #"$storage_dir/images/ssss/base-4321-disk-0.qcow2/1234/vm-1234-disk-0.qcow2", + vmid => undef, + files => [ + "$storage_dir/images/1234/vm-1234-disk-0.qcow2", + ], + parent => [ + "../ssss/base-4321-disk-0.qcow2", + ], + expected => [ { 'content' => 'images', 'ctime' => DEFAULT_CTIME, 'format' => 'qcow2', 'parent' => '../ssss/base-4321-disk-0.qcow2', 'size' => DEFAULT_SIZE, 'used' => DEFAULT_USED, 'vmid' => '1234', 'volid' => 'local:1234/vm-1234-disk-0.qcow2' } ], + description => 'VMID: none, parent, non-matching', + }, + { + # failed matches + vmid => undef, + files => [ + "$storage_dir/images/ssss/base-4321-disk-0.raw", + "$storage_dir/images/ssss/vm-1234-disk-0.qcow2", + "$storage_dir/template/iso/yet-again-a-installation-disk.dvd", + "$storage_dir/template/cache/debian-10.0-standard_10.0-1_amd64.zip.gz", + "$storage_dir/template/cache/debian-10.0-standard_10.0-1_amd64.tar.bz2", + "$storage_dir/private/subvol-19254-disk-0/19254", + "$storage_dir/dump/vzdump-openvz-16112-2020_03_30-21_39_30.tar.bz2", + "$storage_dir/dump/vzdump-openvz-16112-2020_03_30-21_39_30.zip.gz", + "$storage_dir/dump/vzdump-openvz-16112-2020_03_30-21_39_30.tgz.lzo", + "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_12_40.vma.xz", + "$storage_dir/dump/vzdump-qemu-16110-2020_03_30-21_12_40.vms.gz", + ], + expected => [], # returns empty list + description => 'VMID: none, non-matching', + }, +); + + +my $mock_cluster = Test::MockModule->new('PVE::Cluster', no_auto => 1); +$mock_cluster->redefine(get_vmlist => sub { return $vmlist; }); + +my $mock_fsi = Test::MockModule->new('PVE::Storage::Plugin', no_auto => 1); +$mock_fsi->redefine(file_size_info => sub { + my ($filename, $timeout) = @_; + my ($size, $format, $used, $parent, $ctime) = $mock_fsi->original('file_size_info')->($filename, $timeout); + + $size = DEFAULT_SIZE; + $used = DEFAULT_USED; + + return wantarray ? ($size, $format, $used, $parent, $ctime) : $size; +}); + +plan tests => scalar @tests; + +my $sid = 'local'; +my $types = [ 'rootdir', 'images', 'vztmpl', 'iso', 'backup', 'snippets' ]; +my @suffixes = ( 'qcow2', 'raw', 'vmdk', 'vhdx' ); + +foreach my $tt (@tests) { + my $vmid = $tt->{vmid}; + my $files = $tt->{files}; + my $expected = $tt->{expected}; + my $description = $tt->{description}; + my $parent = $tt->{parent}; + + # prepare environment + my $num = 0; #parent disks + for my $file (@$files) { + my ($name, $dir, $suffix) = fileparse($file, @suffixes); + + make_path($dir, { verbose => 1, mode => 0755 }); + + if ($name) { + my @cmd = ( '/usr/bin/qemu-img', 'create', "$file", DEFAULT_SIZE ); + push @cmd, ( '-f', $suffix ) if $suffix; + push @cmd, ( '-u', '-b', @$parent[$num] ) if $parent; + $num++; + + run_command([@cmd]); + } + } + + # run tests + my $got; + eval { $got = PVE::Storage::Plugin->list_volumes($sid, $scfg, $vmid, $types) }; + $got = $@ if $@; + + is_deeply($got, $expected, $description) || diag(explain($got)); + + # clean up + remove_tree($storage_dir, { verbose => 1 }); +} + +done_testing(); + +1; -- 2.20.1 _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel