Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TextRender: support builtin module general as alias for CCM/general #73

Merged
merged 1 commit into from
Dec 3, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
59 changes: 57 additions & 2 deletions src/main/perl/TextRender.pm
Expand Up @@ -139,7 +139,58 @@ Initialize the process object. Arguments:

=item module

The rendering module to use (see C<CAF::TextRender> for details).
The rendering module to use (see L<CAF::TextRender> for details).

CCM provides following additional builtin modules:

=over

=item general

using TT to render a C<Config::General> compatible file.
(This is an alias for the C<CCM/general> TT module).

Contents is a hashref (does not require a C<Element> instance),
with key/value pairs generated according to
the basetype of the value as follows:

=over

=item scalar

converted in a single line
<key> <value>

=item arrayref of scalars

converted in multiple lines as follows
<key> <scalar element0>
<key> <scalar element1>
...

=item hashref

generates a block with format
<"key">
<recursive rendering of the value>
</"key">

=item arrayref of hashref

generates series of blocks
<"key">
<recursive rendering of the element0>
</"key">
<"key">
<recursive rendering of the element1>
</"key">
...

=back

(Whitespace in the block name is enforced with double quotes.)

=back

=item contents

Expand Down Expand Up @@ -262,6 +313,11 @@ sub _initialize
$self->{elementopts} = {};
}

# The general alias
if ($module eq 'general' && ! defined($opts{relpath})) {
$opts{relpath} = 'CCM';
}

return $self->SUPER::_initialize($module, $contents, %opts);
}

Expand Down Expand Up @@ -323,7 +379,6 @@ sub _make_predefined_options
}
}


if ($elopts->{doublequote}) {
push(@{$opts{convert_string}}, $ELEMENT_CONVERT{doublequote_string});
} elsif ($elopts->{singlequote}) {
Expand Down
17 changes: 17 additions & 0 deletions src/main/resources/general.tt
@@ -0,0 +1,17 @@
[%- # no data in schema
data = data.defined ? data : CCM.contents -%]
[%- FOREACH p IN data.pairs -%]
[%- IF CCM.is_scalar(p.value) -%]
[% p.key %] [% p.value %]
[% ELSIF CCM.is_list(p.value) -%]
[%- FOREACH el IN p.value -%]
[% IF CCM.is_scalar(el) -%]
[% p.key %] [% el %]
[% ELSE -%]
[% INCLUDE 'CCM/general_block.tt' data=el name=p.key %]
[% END -%]
[% END -%]
[%- ELSIF CCM.is_hash(p.value) -%]
[% INCLUDE 'CCM/general_block.tt' data=p.value name=p.key %]
[% END -%]
[% END -%]
3 changes: 3 additions & 0 deletions src/main/resources/general_block.tt
@@ -0,0 +1,3 @@
<"[% name %]">
[% INCLUDE 'CCM/general.tt' data=data FILTER indent -%]
</"[% name %]">[%- -%]
40 changes: 40 additions & 0 deletions src/main/resources/tests/profiles/general.pan
@@ -0,0 +1,40 @@
object template general;

"/name_level0" = "value_level0";
"/nameb_level0" = "valueb_level0";
"/list_level0" = list(
"l0_value_el0",
"l0_value_el1",
);
"/list_level0b/l0_dict_el2" = list(
dict(
"ll0_name1", "ll0_value1",
"ll0_list", list("ll0_el0", "ll0_el1"),
),
);

prefix "/dict_level0";
"name_level1" = "value_level1";
"list_level1" = list(
"l1_value_el0",
"l1_value_el1",
);
"list_level1b/l1_dict_el2" = list(
dict(
"ll1_name1", "ll1_value1",
"ll1_list", list("ll1_el0", "ll1_el1"),
),
);

prefix "/dict_level0/list_level1b/level2";
"name_level2" = "value_level2";
"list_level2" = list(
"l2_value_el0",
"l2_value_el1",
);
"list_level2b/l2_dict_el2" = list(
dict(
"ll2_name1", "ll2_value1",
"ll2_list", list("ll2_el0", "ll2_el1"),
),
);
41 changes: 41 additions & 0 deletions src/main/resources/tests/regexps/general/value
@@ -0,0 +1,41 @@
Value test for CCM/general module
---
renderpath=/
rendermodule=general
contentspath=/
---
^<"dict_level0">$
^\s{4}list_level1 l1_value_el0$
^\s{4}list_level1 l1_value_el1$
^\s{4}<"list_level1b">$
^\s{8}<"l1_dict_el2">$
^\s{12}ll1_list ll1_el0$
^\s{12}ll1_list ll1_el1$
^\s{12}ll1_name1 ll1_value1$
^\s{8}</"l1_dict_el2">$
^\s{8}<"level2">$
^\s{12}list_level2 l2_value_el0$
^\s{12}list_level2 l2_value_el1$
^\s{12}<"list_level2b">$
^\s{16}<"l2_dict_el2">$
^\s{20}ll2_list ll2_el0$
^\s{20}ll2_list ll2_el1$
^\s{20}ll2_name1 ll2_value1$
^\s{16}</"l2_dict_el2">$
^\s{12}</"list_level2b">$
^\s{12}name_level2 value_level2$
^\s{8}</"level2">$
^\s{4}</"list_level1b">$
^\s{4}name_level1 value_level1$
^</"dict_level0">$
^list_level0 l0_value_el0$
^list_level0 l0_value_el1$
^<"list_level0b">$
^\s{4}<"l0_dict_el2">$
^\s{8}ll0_list ll0_el0$
^\s{8}ll0_list ll0_el1$
^\s{8}ll0_name1 ll0_value1$
^\s{4}</"l0_dict_el2">$
^</"list_level0b">$
^name_level0 value_level0$
^nameb_level0 valueb_level0$
50 changes: 50 additions & 0 deletions src/test/perl/textrender.t
Expand Up @@ -16,8 +16,11 @@ use Readonly;
use Test::Quattor qw(textrender);
use EDG::WP4::CCM::TextRender;
use Test::Quattor::RegexpTest;
use Test::Quattor::TextRender::Base;
use Cwd;

use Config::General;

ok(EDG::WP4::CCM::CCfg::getCfgValue('json_typed'), 'json_typed (still) enabled');


Expand Down Expand Up @@ -280,5 +283,52 @@ $rt->test();
diag("$trd_s");
diag explain $trd_s->{contents};

=pod

=head2 general alias

Test general as alias for CCM/general, validate C<Config::General> format

=cut

my $caf_trd = mock_textrender();


my $contents = {
'name_level0' => 'scalar_level0',
'level1' => {
'name_level1' => 'scalar_level1',
'name_level2' => [
'scalar_element0',
'scalar_element1',
]
},
"level2 space", {
'more' => 'values',
'name2_level2' => [
{ 'l2_more' => 'l2 values'},
{ 'l2_moreb' => 'l2_moreb'},
]
},
};

$trd = EDG::WP4::CCM::TextRender->new('general', $contents);
is($trd->{module}, 'general', 'module general is alias for CCM/general (relative module name ok)');
is($trd->{relpath}, 'CCM', 'module general is alias for CCM/general (relpath ok)');
ok($trd->{method_is_tt}, "method_is_tt is true for module general");

my $txt = "$trd";
$txt =~ s/\s+//g; # squash whitespace
# the correctnes is verified in detail in the TT unittests
is($txt,
'<"level1">name_level1scalar_level1name_level2scalar_element0name_level2scalar_element1</"level1"><"level2space">morevalues<"name2_level2">l2_morel2values</"name2_level2"><"name2_level2">l2_morebl2_moreb</"name2_level2"></"level2space">name_level0scalar_level0',
"general / CCM/general module rendered correctly");

# No error logging in the module
ok(! exists($trd->{fail}), "No errors logged anywhere");

my %cg_cfg = Config::General->new(-String => "$trd")->getall();
is_deeply(\%cg_cfg, $contents, "Correctly rendered valid Config::General");
diag explain \%cg_cfg;

done_testing;