From: Dominik Csapak <d.csapak@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH common v4 2/5] tools: add is_deeply
Date: Thu, 16 Nov 2023 16:21:48 +0100 [thread overview]
Message-ID: <20231116152152.1371406-3-d.csapak@proxmox.com> (raw)
In-Reply-To: <20231116152152.1371406-1-d.csapak@proxmox.com>
to compare nested hashes/lists and scalar values recursively.
Also includes some tests
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
changes from v3:
* rename the testfile is_deeply_test to match Makefile
src/PVE/Tools.pm | 31 +++++++++
test/Makefile | 1 +
test/is_deeply_test.pl | 142 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 174 insertions(+)
create mode 100755 test/is_deeply_test.pl
diff --git a/src/PVE/Tools.pm b/src/PVE/Tools.pm
index b3af2c6..766c809 100644
--- a/src/PVE/Tools.pm
+++ b/src/PVE/Tools.pm
@@ -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;
diff --git a/test/Makefile b/test/Makefile
index 82f40ab..b0de1a5 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -6,6 +6,7 @@ TESTS = lock_file.test \
format_test.test \
section_config_test.test \
api_parameter_test.test \
+ is_deeply_test.test \
all:
diff --git a/test/is_deeply_test.pl b/test/is_deeply_test.pl
new file mode 100755
index 0000000..f546b36
--- /dev/null
+++ b/test/is_deeply_test.pl
@@ -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();
--
2.30.2
next prev parent reply other threads:[~2023-11-16 15:22 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-16 15:21 [pve-devel] [PATCH common/widget-toolkit v4] implement oneOf schema Dominik Csapak
2023-11-16 15:21 ` [pve-devel] [PATCH common v4 1/5] section config: add test for the schemas Dominik Csapak
2023-11-16 15:21 ` Dominik Csapak [this message]
2023-11-16 15:21 ` [pve-devel] [PATCH common v4 3/5] json schema: implement 'oneOf' schema Dominik Csapak
2023-11-16 15:21 ` [pve-devel] [PATCH common v4 4/5] section config: allow separated property lists for plugins Dominik Csapak
2023-11-16 15:21 ` [pve-devel] [PATCH common v4 5/5] section config: add tests for separated property lists Dominik Csapak
2023-11-16 15:21 ` [pve-devel] [PATCH widget-toolkit v4 1/1] api-viewer: implement basic oneOf support Dominik Csapak
2023-11-17 9:06 ` [pve-devel] applied: [PATCH common/widget-toolkit v4] implement oneOf schema Thomas Lamprecht
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=20231116152152.1371406-3-d.csapak@proxmox.com \
--to=d.csapak@proxmox.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal