#!/usr/bin/perl use strict; use warnings; use lib '..'; use Test::More; use Test::MockModule; use PVE::VZDump; my $vzdump_config; my $storage_config; sub prepare_storage_config { my ($param) = @_; $storage_config = "dir: local\n"; $storage_config .= "\tcontent backup\n"; $storage_config .= "\tpath /var/lib/vz\n"; foreach my $key (keys %{$param}) { my $value = $param->{$key}; $storage_config .= "\t${key} ${value}\n"; } } sub prepare_vzdump_config { my ($param) = @_; $vzdump_config = ""; foreach my $key (keys %{$param}) { my $value = $param->{$key}; $vzdump_config .= "${key}: ${value}\n"; } } my $pve_vzdump_module = Test::MockModule->new('PVE::VZDump'); $pve_vzdump_module->mock( mkpath => sub { return; }, check_bin => sub { return; }, ); my $pve_storage_module = Test::MockModule->new('PVE::Storage'); $pve_storage_module->mock( activate_storage => sub { return; }, ); my $pve_cluster_module = Test::MockModule->new('PVE::Cluster'); $pve_cluster_module->mock( get_config => sub { my ($filename) = @_; die "unexpected filename '$filename'\n" if $filename ne 'storage.cfg'; return $storage_config; }, # never update during the tests cfs_update => sub { return; }, ); my $pve_tools_module = Test::MockModule->new('PVE::Tools'); $pve_tools_module->mock( file_get_contents => sub { my ($filename) = @_; die "unexpected filename '$filename'\n" if $filename ne '/etc/vzdump.conf'; return $vzdump_config; }, ); my $tested_options; # each test consists of the following: # name - unique name for the test # cli_param - CLI parameters to be passed to new(); vmid and storage are hardcoded # storage_param - parameters for the mocked storage configuration # vzdump_param - parameters for the mocked /etc/vzdump.conf # expected - expected options # # To begin testing for different options, use a fake test like the first one my @tests = ( { description => 'BEGIN RETENTION TESTS', tested_options => ['prune-backups', 'remove'], }, { description => 'no params', expected => { 'prune-backups' => { 'keep-all' => 1, }, remove => 0, }, }, # TODO make parse error critical? { description => 'maxfiles vzdump 1', vzdump_param => { maxfiles => 0, }, expected => { 'prune-backups' => { 'keep-all' => 1, }, remove => 0, }, }, { description => 'maxfiles vzdump 2', vzdump_param => { maxfiles => 7, }, expected => { 'prune-backups' => { 'keep-last' => 7, }, remove => 1, }, }, { description => 'maxfiles storage 1', storage_param => { maxfiles => 0, }, expected => { 'prune-backups' => { 'keep-all' => 1, }, remove => 0, }, }, { description => 'maxfiles storage 2', storage_param => { maxfiles => 7, }, expected => { 'prune-backups' => { 'keep-last' => 7, }, remove => 1, }, }, { description => 'maxfiles CLI 1', cli_param => { maxfiles => 0, }, expected => { 'prune-backups' => { 'keep-all' => 1, }, remove => 0, }, }, { description => 'maxfiles CLI 2', cli_param => { maxfiles => 7, }, expected => { 'prune-backups' => { 'keep-last' => 7, }, remove => 1, }, }, { description => 'prune-backups vzdump 1', vzdump_param => { 'prune-backups' => 'keep-last=1,keep-hourly=2,keep-daily=3,' . 'keep-weekly=4,keep-monthly=5,keep-yearly=6', }, expected => { 'prune-backups' => { 'keep-last' => 1, 'keep-hourly' => 2, 'keep-daily' => 3, 'keep-weekly' => 4, 'keep-monthly' => 5, 'keep-yearly' => 6, }, remove => 1, }, }, { description => 'prune-backups vzdump 2', vzdump_param => { 'prune-backups' => 'keep-all=1', }, expected => { 'prune-backups' => { 'keep-all' => 1, }, remove => 0, }, }, { description => 'prune-backups vzdump 3', vzdump_param => { 'prune-backups' => 'keep-hourly=0,keep-monthly=0,keep-yearly=0', }, expected => { 'prune-backups' => { 'keep-all' => 1, }, remove => 0, }, }, { description => 'both vzdump 1', vzdump_param => { 'prune-backups' => 'keep-all=1', maxfiles => 7, }, expected => { 'prune-backups' => { 'keep-all' => 1, }, remove => 0, }, }, { description => 'prune-backups storage 1', storage_param => { 'prune-backups' => 'keep-last=1,keep-hourly=2,keep-daily=3,' . 'keep-weekly=4,keep-monthly=5,keep-yearly=6', }, expected => { 'prune-backups' => { 'keep-last' => 1, 'keep-hourly' => 2, 'keep-daily' => 3, 'keep-weekly' => 4, 'keep-monthly' => 5, 'keep-yearly' => 6, }, remove => 1, }, }, { description => 'prune-backups storage 2', storage_param => { 'prune-backups' => 'keep-last=0,keep-hourly=0,keep-daily=0,' . 'keep-weekly=0,keep-monthly=0,keep-yearly=0', }, expected => { 'prune-backups' => { 'keep-all' => 1, }, remove => 0, }, }, { description => 'prune-backups storage 3', storage_param => { 'prune-backups' => 'keep-hourly=0,keep-monthly=0,keep-yearly=0', }, expected => { 'prune-backups' => { 'keep-all' => 1, }, remove => 0, }, }, { description => 'both storage 1', storage_param => { 'prune-backups' => 'keep-hourly=1,keep-monthly=2,keep-yearly=3', maxfiles => 0, }, expected => { 'prune-backups' => { 'keep-hourly' => 1, 'keep-monthly' => 2, 'keep-yearly' => 3, }, remove => 1, }, }, { description => 'prune-backups CLI 1', cli_param => { 'prune-backups' => 'keep-last=1,keep-hourly=2,keep-daily=3,' . 'keep-weekly=4,keep-monthly=5,keep-yearly=6', }, expected => { 'prune-backups' => { 'keep-last' => 1, 'keep-hourly' => 2, 'keep-daily' => 3, 'keep-weekly' => 4, 'keep-monthly' => 5, 'keep-yearly' => 6, }, remove => 1, }, }, { description => 'prune-backups CLI 2', cli_param => { 'prune-backups' => 'keep-last=0,keep-hourly=0,keep-daily=0,' . 'keep-weekly=0,keep-monthly=0,keep-yearly=0', }, expected => { 'prune-backups' => { 'keep-all' => 1, }, remove => 0, }, }, { description => 'prune-backups CLI 3', cli_param => { 'prune-backups' => 'foo=bar', }, expected => "format error\n" . "foo: property is not defined in schema and the schema does not allow additional properties\n", }, { description => 'both CLI 1', cli_param => { 'prune-backups' => 'keep-hourly=1,keep-monthly=2,keep-yearly=3', maxfiles => 4, }, expected => "400 Parameter verification failed.\n" . "prune-backups: option conflicts with option 'maxfiles'\n", }, { description => 'mixed 1', vzdump_param => { maxfiles => 7, }, storage_param => { 'prune-backups' => 'keep-hourly=24', }, expected => { 'prune-backups' => { 'keep-hourly' => 24, }, remove => 1, }, }, # TODO make parse error critical? { description => 'mixed 2', vzdump_param => { maxfiles => 7, }, storage_param => { 'prune-backups' => 'keephourly=24', }, expected => { 'prune-backups' => { 'keep-last' => 7, }, remove => 1, }, }, { description => 'mixed 3', vzdump_param => { maxfiles => 7, }, cli_param => { 'prune-backups' => 'keep-all=1', }, expected => { 'prune-backups' => { 'keep-all' => 1, }, remove => 0, }, }, { description => 'mixed 4', vzdump_param => { maxfiles => 7, }, storage_param => { 'prune-backups' => 'keep-all=0,keep-last=10', }, cli_param => { 'prune-backups' => 'keep-all=1', }, expected => { 'prune-backups' => { 'keep-all' => 1, }, remove => 0, }, }, { description => 'mixed 5', vzdump_param => { maxfiles => 7, }, storage_param => { 'prune-backups' => 'keep-all=0,keep-last=10', }, expected => { 'prune-backups' => { 'keep-last' => 10, }, remove => 1, }, }, { description => 'mixed 6', storage_param => { 'prune-backups' => 'keep-last=10', }, cli_param => { 'prune-backups' => 'keep-all=1', }, expected => { 'prune-backups' => { 'keep-all' => 1, }, remove => 0, }, }, { description => 'mixed 7', storage_param => { 'prune-backups' => 'keep-all=1', }, cli_param => { 'prune-backups' => 'keep-last=10', }, expected => { 'prune-backups' => { 'keep-last' => 10, }, remove => 1, }, }, { description => 'mixed 8', storage_param => { 'prune-backups' => 'keep-last=10', }, vzdump_param => { 'prune-backups' => 'keep-all=1', }, expected => { 'prune-backups' => { 'keep-last' => 10, }, remove => 1, }, }, { description => 'mixed 9', vzdump_param => { 'prune-backups' => 'keep-last=10', }, cli_param => { 'prune-backups' => 'keep-all=1', }, expected => { 'prune-backups' => { 'keep-all' => 1, }, remove => 0, }, }, { description => 'BEGIN MAILTO TESTS', tested_options => ['mailto'], }, { description => 'mailto vzdump 1', vzdump_param => { 'mailto' => 'developer@proxmox.com', }, expected => { 'mailto' => [ 'developer@proxmox.com', ], }, }, { description => 'mailto vzdump 2', vzdump_param => { 'mailto' => 'developer@proxmox.com admin@proxmox.com', }, expected => { 'mailto' => [ 'developer@proxmox.com', 'admin@proxmox.com', ], }, }, { description => 'mailto vzdump 3', vzdump_param => { 'mailto' => 'developer@proxmox.com,admin@proxmox.com', }, expected => { 'mailto' => [ 'developer@proxmox.com', 'admin@proxmox.com', ], }, }, { description => 'mailto vzdump 4', vzdump_param => { 'mailto' => 'developer@proxmox.com, admin@proxmox.com', }, expected => { 'mailto' => [ 'developer@proxmox.com', 'admin@proxmox.com', ], }, }, { description => 'mailto vzdump 5', vzdump_param => { 'mailto' => ' ,,; developer@proxmox.com, ; admin@proxmox.com ', }, expected => { 'mailto' => [ 'developer@proxmox.com', 'admin@proxmox.com', ], }, }, { description => 'mailto vzdump 6', vzdump_param => { 'mailto' => '', }, expected => { 'mailto' => [], }, }, { description => 'mailto CLI 1', cli_param => { 'mailto' => 'developer@proxmox.com', }, expected => { 'mailto' => [ 'developer@proxmox.com', ], }, }, { description => 'mailto CLI 2', cli_param => { 'mailto' => 'developer@proxmox.com admin@proxmox.com', }, expected => { 'mailto' => [ 'developer@proxmox.com', 'admin@proxmox.com', ], }, }, { description => 'mailto CLI 3', cli_param => { 'mailto' => 'developer@proxmox.com,admin@proxmox.com', }, expected => { 'mailto' => [ 'developer@proxmox.com', 'admin@proxmox.com', ], }, }, { description => 'mailto CLI 4', cli_param => { 'mailto' => 'developer@proxmox.com, admin@proxmox.com', }, expected => { 'mailto' => [ 'developer@proxmox.com', 'admin@proxmox.com', ], }, }, { description => 'mailto CLI 5', cli_param => { 'mailto' => ' ,,; developer@proxmox.com, ; admin@proxmox.com ', }, expected => { 'mailto' => [ 'developer@proxmox.com', 'admin@proxmox.com', ], }, }, { description => 'mailto both 1', vzdump_param => { 'mailto' => 'developer@proxmox.com', }, cli_param => { 'mailto' => 'admin@proxmox.com', }, expected => { 'mailto' => [ 'admin@proxmox.com', ], }, }, { description => 'mailto both 2', vzdump_param => { 'mailto' => 'developer@proxmox.com', }, cli_param => { 'mailto' => '', }, expected => { 'mailto' => [], }, }, ); plan tests => scalar @tests; foreach my $test (@tests) { if (defined($test->{tested_options})) { $tested_options = $test->{tested_options}; ok(1, $test->{description}); next; } prepare_storage_config($test->{storage_param}); prepare_vzdump_config($test->{vzdump_param}); $test->{cli_param}->{vmid} = 100; $test->{cli_param}->{storage} = 'local'; my $got = eval { PVE::VZDump::verify_vzdump_parameters($test->{cli_param}, 1); PVE::VZDump::parse_mailto_exclude_path($test->{cli_param}); my $vzdump = PVE::VZDump->new('fake cmdline', $test->{cli_param}, undef); my $opts = $vzdump->{opts} or die "did not get options\n"; die "maxfiles is defined" if defined($opts->{maxfiles}); my $res = {}; foreach my $opt (@{$tested_options}) { next if !defined($opts->{$opt}); $res->{$opt} = $opts->{$opt}; } return $res; }; $got = $@ if $@; is_deeply($got, $test->{expected}, $test->{description}) || diag(explain($got)); } done_testing();