mirror of
https://git.proxmox.com/git/pve-common
synced 2025-04-28 12:10:17 +00:00
tools: add is_deeply
to compare nested hashes/lists and scalar values recursively. Also includes some tests Signed-off-by: Dominik Csapak <d.csapak@proxmox.com> Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
parent
e42f1dd6a1
commit
15645af168
@ -2150,4 +2150,35 @@ sub get_file_hash {
|
||||
return lc($digest);
|
||||
}
|
||||
|
||||
# compare two perl variables recursively, so this works for scalars, nested
|
||||
# hashes and nested arrays
|
||||
sub is_deeply {
|
||||
my ($a, $b) = @_;
|
||||
|
||||
return 0 if defined($a) != defined($b);
|
||||
return 1 if !defined($a); # both are undef
|
||||
|
||||
my ($ref_a, $ref_b) = (ref($a), ref($b));
|
||||
|
||||
# scalar case
|
||||
return 0 if !$ref_a && !$ref_b && "$a" ne "$b";
|
||||
|
||||
# different types, ok because ref never returns undef, only empty string
|
||||
return 0 if $ref_a ne $ref_b;
|
||||
|
||||
if ($ref_a eq 'HASH') {
|
||||
return 0 if scalar(keys $a->%*) != scalar(keys $b->%*);
|
||||
for my $opt (keys $a->%*) {
|
||||
return 0 if !is_deeply($a->{$opt}, $b->{$opt});
|
||||
}
|
||||
} elsif ($ref_a eq 'ARRAY') {
|
||||
return 0 if scalar($a->@*) != scalar($b->@*);
|
||||
for (my $i = 0; $i < $a->@*; $i++) {
|
||||
return 0 if !is_deeply($a->[$i], $b->[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -6,6 +6,7 @@ TESTS = lock_file.test \
|
||||
format_test.test \
|
||||
section_config_test.test \
|
||||
api_parameter_test.test \
|
||||
is_deeply_test.test \
|
||||
|
||||
all:
|
||||
|
||||
|
142
test/is_deeply_test.pl
Executable file
142
test/is_deeply_test.pl
Executable file
@ -0,0 +1,142 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use lib '../src';
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Test::More;
|
||||
use PVE::Tools;
|
||||
|
||||
my $tests = [
|
||||
{
|
||||
name => 'both undef',
|
||||
a => undef,
|
||||
b => undef,
|
||||
expected => 1,
|
||||
},
|
||||
{
|
||||
name => 'empty string',
|
||||
a => '',
|
||||
b => '',
|
||||
expected => 1,
|
||||
},
|
||||
{
|
||||
name => 'empty string and undef',
|
||||
a => '',
|
||||
b => undef,
|
||||
expected => 0,
|
||||
},
|
||||
{
|
||||
name => '0 and undef',
|
||||
a => 0,
|
||||
b => undef,
|
||||
expected => 0,
|
||||
},
|
||||
{
|
||||
name => 'equal strings',
|
||||
a => 'test',
|
||||
b => 'test',
|
||||
expected => 1,
|
||||
},
|
||||
{
|
||||
name => 'unequal strings',
|
||||
a => 'test',
|
||||
b => 'tost',
|
||||
expected => 0,
|
||||
},
|
||||
{
|
||||
name => 'equal numerics',
|
||||
a => 42,
|
||||
b => 42,
|
||||
expected => 1,
|
||||
},
|
||||
{
|
||||
name => 'unequal numerics',
|
||||
a => 42,
|
||||
b => 420,
|
||||
expected => 0,
|
||||
},
|
||||
{
|
||||
name => 'equal arrays',
|
||||
a => ['foo', 'bar'],
|
||||
b => ['foo', 'bar'],
|
||||
expected => 1,
|
||||
},
|
||||
{
|
||||
name => 'equal empty arrays',
|
||||
a => [],
|
||||
b => [],
|
||||
expected => 1,
|
||||
},
|
||||
{
|
||||
name => 'unequal arrays',
|
||||
a => ['foo', 'bar'],
|
||||
b => ['bar', 'foo'],
|
||||
expected => 0,
|
||||
},
|
||||
{
|
||||
name => 'equal empty hashes',
|
||||
a => { },
|
||||
b => { },
|
||||
expected => 1,
|
||||
},
|
||||
{
|
||||
name => 'equal hashes',
|
||||
a => { foo => 'bar' },
|
||||
b => { foo => 'bar' },
|
||||
expected => 1,
|
||||
},
|
||||
{
|
||||
name => 'unequal hashes',
|
||||
a => { foo => 'bar' },
|
||||
b => { bar => 'foo' },
|
||||
expected => 0,
|
||||
},
|
||||
{
|
||||
name => 'equal nested hashes',
|
||||
a => {
|
||||
foo => 'bar',
|
||||
bar => 1,
|
||||
list => ['foo', 'bar'],
|
||||
properties => {
|
||||
baz => 'boo',
|
||||
},
|
||||
},
|
||||
b => {
|
||||
foo => 'bar',
|
||||
bar => 1,
|
||||
list => ['foo', 'bar'],
|
||||
properties => {
|
||||
baz => 'boo',
|
||||
},
|
||||
},
|
||||
expected => 1,
|
||||
},
|
||||
{
|
||||
name => 'unequal nested hashes',
|
||||
a => {
|
||||
foo => 'bar',
|
||||
bar => 1,
|
||||
list => ['foo', 'bar'],
|
||||
properties => {
|
||||
baz => 'boo',
|
||||
},
|
||||
},
|
||||
b => {
|
||||
foo => 'bar',
|
||||
bar => 1,
|
||||
list => ['foo', 'bar'],
|
||||
properties => {
|
||||
baz => undef,
|
||||
},
|
||||
},
|
||||
expected => 0,
|
||||
},
|
||||
];
|
||||
|
||||
for my $test ($tests->@*) {
|
||||
is (PVE::Tools::is_deeply($test->{a}, $test->{b}), $test->{expected}, $test->{name});
|
||||
}
|
||||
|
||||
done_testing();
|
Loading…
Reference in New Issue
Block a user