From: Stefan Reiter Date: Mon, 8 Feb 2021 11:15:07 +0000 (+0100) Subject: extract PVE::Format from PVE::CLIFormatter for reuse X-Git-Url: https://git.proxmox.com/?p=pve-common.git;a=commitdiff_plain;h=57b33852905ccf0b11649aa00a5fa9da69e3884d extract PVE::Format from PVE::CLIFormatter for reuse and add some tests Signed-off-by: Stefan Reiter --- diff --git a/src/Makefile b/src/Makefile index 098a648..13de6c6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -16,6 +16,7 @@ LIB_SOURCES = \ CGroup.pm \ Daemon.pm \ Exception.pm \ + Format.pm \ INotify.pm \ JSONSchema.pm \ LDAP.pm \ diff --git a/src/PVE/CLIFormatter.pm b/src/PVE/CLIFormatter.pm index ccecfc3..c2f92d2 100644 --- a/src/PVE/CLIFormatter.pm +++ b/src/PVE/CLIFormatter.pm @@ -4,86 +4,27 @@ use strict; use warnings; use I18N::Langinfo; -use POSIX qw(strftime); use YAML::XS; # supports Dumping JSON::PP::Boolean $YAML::XS::Boolean = "JSON::PP"; use PVE::JSONSchema; use PVE::PTY; +use PVE::Format; use JSON; use utf8; use Encode; -sub render_timestamp { - my ($epoch) = @_; - - # ISO 8601 date format - return strftime("%F %H:%M:%S", localtime($epoch)); -} - -PVE::JSONSchema::register_renderer('timestamp', \&render_timestamp); - -sub render_timestamp_gmt { - my ($epoch) = @_; - - # ISO 8601 date format, standard Greenwich time zone - return strftime("%F %H:%M:%S", gmtime($epoch)); -} - -PVE::JSONSchema::register_renderer('timestamp_gmt', \&render_timestamp_gmt); - -sub render_duration { - my ($duration_in_seconds) = @_; - - my $text = ''; - my $rest = $duration_in_seconds; - - my $step = sub { - my ($unit, $unitlength) = @_; - - if ((my $v = int($rest/$unitlength)) > 0) { - $text .= " " if length($text); - $text .= "${v}${unit}"; - $rest -= $v * $unitlength; - } - }; - - $step->('w', 7*24*3600); - $step->('d', 24*3600); - $step->('h', 3600); - $step->('m', 60); - $step->('s', 1); - - return $text; -} - -PVE::JSONSchema::register_renderer('duration', \&render_duration); - -sub render_fraction_as_percentage { - my ($fraction) = @_; - - return sprintf("%.2f%%", $fraction*100); -} - -PVE::JSONSchema::register_renderer( - 'fraction_as_percentage', \&render_fraction_as_percentage); - -sub render_bytes { - my ($value) = @_; - - my @units = qw(B KiB MiB GiB TiB PiB); - - my $max_unit = 0; - if ($value > 1023) { - $max_unit = int(log($value)/log(1024)); - $value /= 1024**($max_unit); - } - my $unit = $units[$max_unit]; - return sprintf "%.2f $unit", $value; -} - -PVE::JSONSchema::register_renderer('bytes', \&render_bytes); +PVE::JSONSchema::register_renderer('timestamp', + \&PVE::Format::render_timestamp); +PVE::JSONSchema::register_renderer('timestamp_gmt', + \&PVE::Format::render_timestamp_gmt); +PVE::JSONSchema::register_renderer('duration', + \&PVE::Format::render_duration); +PVE::JSONSchema::register_renderer('fraction_as_percentage', + \&PVE::Format::render_fraction_as_percentage); +PVE::JSONSchema::register_renderer('bytes', + \&PVE::Format::render_bytes); sub render_yaml { my ($value) = @_; diff --git a/src/PVE/Format.pm b/src/PVE/Format.pm new file mode 100644 index 0000000..7c3c062 --- /dev/null +++ b/src/PVE/Format.pm @@ -0,0 +1,77 @@ +package PVE::Format; + +use strict; +use warnings; + +use POSIX qw(strftime); +use PVE::JSONSchema; + +use base 'Exporter'; +our @EXPORT_OK = qw( +render_timestamp +render_timestamp_gmt +render_duration +render_fraction_as_percentage +render_bytes +); + +sub render_timestamp { + my ($epoch) = @_; + + # ISO 8601 date format + return strftime("%F %H:%M:%S", localtime($epoch)); +} + +sub render_timestamp_gmt { + my ($epoch) = @_; + + # ISO 8601 date format, standard Greenwich time zone + return strftime("%F %H:%M:%S", gmtime($epoch)); +} + +sub render_duration { + my ($duration_in_seconds) = @_; + + my $text = ''; + my $rest = $duration_in_seconds; + + my $step = sub { + my ($unit, $unitlength) = @_; + + if ((my $v = int($rest/$unitlength)) > 0) { + $text .= " " if length($text); + $text .= "${v}${unit}"; + $rest -= $v * $unitlength; + } + }; + + $step->('w', 7*24*3600); + $step->('d', 24*3600); + $step->('h', 3600); + $step->('m', 60); + $step->('s', 1); + + return $text; +} + +sub render_fraction_as_percentage { + my ($fraction) = @_; + + return sprintf("%.2f%%", $fraction*100); +} + +sub render_bytes { + my ($value, $precision) = @_; + + my @units = qw(B KiB MiB GiB TiB PiB); + + my $max_unit = 0; + if ($value > 1023) { + $max_unit = int(log($value)/log(1024)); + $value /= 1024**($max_unit); + } + my $unit = $units[$max_unit]; + return sprintf "%." . ($precision || 2) . "f $unit", $value; +} + +1; diff --git a/test/format_test.pl b/test/format_test.pl index 3f225de..b6688ab 100755 --- a/test/format_test.pl +++ b/test/format_test.pl @@ -5,6 +5,7 @@ use warnings; use lib '../src'; use PVE::JSONSchema; +use PVE::CLIFormatter; use Test::More; use Test::MockModule; @@ -24,4 +25,30 @@ foreach my $id (@$invalid_configids) { is(PVE::JSONSchema::pve_verify_configid($id, $noerr), undef, 'invalid configid'); } -done_testing(); \ No newline at end of file +# test some string rendering +my $render_data = [ + ["timestamp", 0, undef, "1970-01-01 01:00:00"], + ["timestamp", 1612776831, undef, "2021-02-08 10:33:51"], + ["timestamp_gmt", 0, undef, "1970-01-01 00:00:00"], + ["timestamp_gmt", 1612776831, undef, "2021-02-08 09:33:51"], + ["duration", 0, undef, ""], + ["duration", 40, undef, "40s"], + ["duration", 60, undef, "1m"], + ["duration", 110, undef, "1m 50s"], + ["duration", 7*24*3829*2, undef, "2w 21h 22m 24s"], + ["fraction_as_percentage", 0.412, undef, "41.20%"], + ["bytes", 0, undef, "0.00 B"], + ["bytes", 1023, 4, "1023.0000 B"], + ["bytes", 1024, undef, "1.00 KiB"], + ["bytes", 1024*1024*123 + 1024*300, 1, "123.3 MiB"], + ["bytes", 1024*1024*1024*1024*4 + 1024*1024*2048*8, undef, "4.02 TiB"], +]; + +foreach my $data (@$render_data) { + my ($renderer_name, $p1, $p2, $expected) = @$data; + my $renderer = PVE::JSONSchema::get_renderer($renderer_name); + my $actual = $renderer->($p1, $p2); + is($actual, $expected, "string format '$renderer_name'"); +} + +done_testing();