File Coverage

lib/Config/IniFiles/Check/Health.pm
Criterion Covered Total %
statement 70 94 74.4
branch 10 18 55.5
condition 3 9 33.3
subroutine 11 13 84.6
pod 3 5 60.0
total 97 139 69.7


line stmt bran cond sub pod time code
1             package Config::IniFiles::Check::Health;
2 5     5   588387 use 5.006;
  5         20  
3 5     5   3028 use Moo 2.004000;
  5         48038  
  5         39  
4 5     5   13572 use strictures 2;
  5         10975  
  5         234  
5 5     5   6088 use namespace::clean;
  5         99155  
  5         36  
6 5     5   4989 use Params::Validate 1.30 qw(validate_with OBJECT SCALAR ARRAYREF UNDEF);
  5         25237  
  5         7084  
7              
8             =head1 NAME
9              
10             Config::IniFiles::Check::Health - check ini-files for needed values
11              
12             =cut
13              
14             our $VERSION = '0.09';
15              
16             =head1 VERSION
17              
18             Version 0.09
19              
20             =cut
21              
22             =head1 SYNOPSIS
23              
24             use Config::IniFiles::Check::Health;
25              
26             # see new()
27              
28             =cut
29              
30             =head1 DESCRIPTION
31              
32             Config-IniFiles-Check-Health
33              
34             Working with Config::IniFiles needs to check the ini-files
35             for
36              
37             * checking for existing, needed values in the sections
38             * double-vars in a single section
39             * do all needed sections exist
40              
41             =cut
42              
43             =head1 SYNOPSIS
44              
45             my $ini_fn = 'utf8convertbin.ini';
46             my $ini_obj = Config::IniFiles->new( -file => $ini_fn );
47              
48             Log::Log4perl::ConfigByInifile->new(
49             { ini_obj => $ini_obj, }
50             );
51             my $logger = get_logger();
52              
53             my $ini_health_checker_obj = Config::IniFiles::Check::Health->new({
54             logger => $logger,
55             ini_obj => $ini_obj
56             });
57              
58             # Work to be done:
59             $ini_health_checker_obj->check_inifile_for_values({
60             values_must_exists => [
61             { section => 'inifiles', varname => 'findus_ini_latin1_dn' },
62             { section => 'inifiles', varname => 'findus_ini_utf8_dn' },
63             ]
64             });
65              
66             $ini_health_checker_obj->check_for_sections({
67             sections_must_exist => [ qw(log4perl inifiles) ]
68             });
69              
70             $ini_health_checker_obj->check_inifile_for_values({
71             values_must_exists => [
72             { section => 'inifiles', varname => 'findus_ini_latin1_dn' },
73             { section => 'inifiles', varname => 'findus_ini_utf8_dn' },
74             ]
75             });
76              
77             =cut
78              
79             =head1 FUNCTIONS
80              
81             =cut
82              
83             =head2 new
84              
85             my $ini_fn = 'utf8convertbin.ini';
86             my $ini_obj = Config::IniFiles->new( -file => $ini_fn );
87              
88             my $ini_health_checker_obj = Config::IniFiles::Check::Health->new({
89             # Log4perl-definition is a section in the inifile
90             # so: firstly undef
91             logger => undef,
92             ini_obj => $ini_obj
93             # optional, with default value
94             errors_are_fatal => 1
95             });
96             $ini_health_checker_obj->check_for_sections({
97             sections_must_exist => [ qw(log4perl inifiles) ]
98             });
99              
100             Log::Log4perl::ConfigByInifile->new(
101             { ini_obj => $ini_obj, }
102             );
103             my $logger = get_logger();
104              
105             # Tell about our
106             $ini_health_checker_obj->logger($logger);
107              
108             $ini_health_checker_obj->check_inifile_for_values({
109             values_must_exists => [
110             { section => 'inifiles', varname => 'findus_ini_latin1_dn' },
111             { section => 'inifiles', varname => 'findus_ini_utf8_dn' },
112             ]
113             });
114              
115             =cut
116              
117             sub BUILD {
118 4     4 0 46 my $self = shift;
119 4         23 $self->_check_new_params();
120             }
121              
122             sub _check_new_params {
123 4     4   10 my $self = shift;
124 4         16 my @all_params_must = qw( logger ini_obj);
125 4         15 my $params_wanted_href = { map { $_ => $self->$_ } @all_params_must };
  8         49  
126              
127 4         46 my $params_spec = {
128             logger => {
129             type => UNDEF | OBJECT,
130             },
131             ini_obj => {
132             type => OBJECT,
133             isa => "Config::IniFiles"
134             },
135             };
136              
137 4         241 validate_with(
138             params => $params_wanted_href,
139             spec => $params_spec,
140             );
141             }
142              
143             =head2 logger
144              
145             You can set logger to a real Perl-Log-Objekt or to undef. This is to
146             starte the object and make some tests without having a log-object in
147             the very beginning because the log-object is built with information
148             from the ini-file.
149              
150             $obj->new({ logger => undef, ...})
151              
152             # Later...
153             $obj->logger( Log::Log4perl::get_logger('Bla::Foo') )
154              
155             =cut
156              
157             has 'logger' => (
158             is => 'ro',
159             isa => sub {
160              
161             # undef is ok
162             if ( !defined( $_[0] ) ) {
163             return;
164             }
165             elsif ( ref( $_[0] ) eq 'Config::IniFiles' ) {
166             return;
167             }
168             else {
169             die "logger must be undef or of type Log::Log4perl";
170             }
171             },
172             );
173              
174             has 'ini_obj' => (
175             is => 'ro',
176             isa => sub {
177             die "ini_obj must be of type Config::IniFiles"
178             unless ref( $_[0] ) eq 'Config::IniFiles';
179             },
180             );
181              
182             =head2 errors_are_fatal
183              
184             You can switch behaviour of the following tests:
185              
186             $obj->errors_are_fatal(1); # default
187             # There should be errors, but not die
188             $obj->errors_are_fatal(0);
189             $obj->check_for_duplicate_vars_in_one_section('berlin');
190              
191             =cut
192              
193             has 'errors_are_fatal' => (
194             is => 'rw',
195             default => sub { 1 },
196             );
197              
198             =head2 check_for_duplicate_vars_in_one_section
199              
200             $obj->check_for_duplicate_vars_in_all_sections();
201              
202             =cut
203              
204             sub check_for_duplicate_vars_in_all_sections {
205 0     0 0 0 my $self = shift;
206 0         0 my $logger = $self->logger;
207 0         0 my $ini_obj = $self->ini_obj;
208 0         0 for my $cur_section ( $ini_obj->Sections ) {
209 0         0 $self->check_for_duplicate_vars_in_one_section(
210             { section => $cur_section } );
211             }
212             }
213              
214             =head2 check_for_duplicate_vars_in_one_section
215              
216             Try to avoid double vars entries like this:
217              
218             ; my.ini
219             [berlin]
220             dogs=20
221             dogs=30
222             cats=10
223              
224             Usage:
225              
226             $obj->check_for_duplicate_vars_in_one_section({ section => 'berlin' });
227              
228             =cut
229              
230             sub check_for_duplicate_vars_in_one_section {
231 1     1 1 496 my $self = shift;
232 1         21 my $args_href = validate_with(
233             params => shift,
234             spec => {
235             section => {
236             type => SCALAR,
237             },
238             }
239             );
240 1         9 my $logger = $self->logger;
241 1         4 my $ini_obj = $self->ini_obj;
242 1         3 my $section = $args_href->{section};
243 1         1 my $log_msg;
244 1         4 my $nr_of_errors = 0;
245              
246 1         5 for my $current_varname ( $ini_obj->Parameters($section) ) {
247              
248             # List context gives an element per line:
249 2         42 my @all_values = $ini_obj->val( $section, $current_varname );
250 2 100       75 if ( @all_values > 1 ) {
251 1         2 $nr_of_errors++;
252 1         3 $log_msg =
253             sprintf "Found duplicate line in section '%s' with varname='%s'",
254             $section,
255             $current_varname;
256 1         9 $self->_log_error($log_msg);
257             }
258             }
259              
260 1 50 33     11 if ( $self->errors_are_fatal && $nr_of_errors > 0 ) {
261 1         3 $log_msg =
262             sprintf 'Too many errors in check_for_duplicate_vars_in_section';
263 1         4 $self->_log_fatal($log_msg);
264             }
265             }
266              
267             =head2 check_for_sections
268              
269             $ini_health_checker_obj->check_for_sections({
270             sections_must_exist => [ qw(berlin vienna) ]
271             });
272              
273             =cut
274              
275             sub check_for_sections {
276 0     0 1 0 my $self = shift;
277 0         0 my $args_href = validate_with(
278             params => shift,
279             spec => {
280             sections_must_exist => {
281             type => ARRAYREF,
282             },
283             }
284             );
285 0         0 my $logger = $self->logger;
286 0         0 my $ini_obj = $self->ini_obj;
287 0         0 my @sections_must_exist = @{ $args_href->{sections_must_exist} };
  0         0  
288              
289 0         0 my $errors_are_fatal = $args_href->{errors_are_fatal};
290 0         0 my $log_msg;
291 0         0 my $nr_of_errors = 0;
292              
293 0         0 for my $section_name (@sections_must_exist) {
294 0 0       0 if ( !$ini_obj->SectionExists($section_name) ) {
295 0         0 $nr_of_errors++;
296 0         0 $log_msg = sprintf "Section '%s' does not exist in inifile",
297             $section_name;
298 0         0 $self->_log_error($log_msg);
299             }
300             }
301              
302 0 0 0     0 if ( $self->errors_are_fatal && $nr_of_errors > 0 ) {
303 0         0 $log_msg = sprintf 'Too many errors in check_inifile_for_sections';
304 0         0 $self->_log_fatal($log_msg);
305             }
306             }
307              
308             =head2 check_inifile_for_values
309              
310             $ini_health_checker_obj->check_inifiles_for_values({
311             values_must_exists => [
312             { section => 'bla', varname => 'nr_of_cars'},
313             { section => 'bla', varname => 'nr_of_dogs'},
314             ],
315             });
316              
317             =cut
318              
319             sub check_inifile_for_values {
320 4     4 1 1709 my $self = shift;
321 4         97 my $args_href = validate_with(
322             params => shift,
323             spec => {
324             values_must_exist => {
325             type => ARRAYREF,
326             },
327             }
328             );
329 3         19 my $logger = $self->logger;
330 3         7 my $ini_obj = $self->ini_obj;
331 3         5 my @values_must_exist = @{ $args_href->{values_must_exist} };
  3         9  
332 3         6 my $errors_are_fatal = $args_href->{errors_are_fatal};
333              
334 3         4 my $nr_of_errors = 0;
335 3         5 my $log_msg;
336              
337 3         9 for my $values_must_exist_href (@values_must_exist) {
338 6         14 my $section = $values_must_exist_href->{section};
339 6         10 my $varname = $values_must_exist_href->{varname};
340 6         16 my $value_from_inifile = $ini_obj->val( $section, $varname );
341 6 100       175 if ( !defined $value_from_inifile ) {
342 1         3 $nr_of_errors++;
343 1         3 $log_msg =
344             sprintf
345             "value MUST exist in inifile, but does not: section='%s', value='%s'",
346             $section, $varname;
347 1         15 $self->_log_error($log_msg);
348             }
349             }
350 3 100 66     29 if ( $self->errors_are_fatal && $nr_of_errors > 0 ) {
351 1         3 $log_msg = 'Too many errors in check_inifile_for_values';
352 1         4 $self->_log_fatal($log_msg);
353             }
354             }
355              
356             =head2 _log_error
357              
358             $self->_log_error("Bad thing");
359              
360             =cut
361              
362             sub _log_error {
363 2     2   4 my $self = shift;
364 2         56 my $log_msg = shift;
365 2         8 my $logger = $self->logger;
366              
367 2 50       18 if ($logger) {
368 0         0 $logger->error($log_msg);
369             }
370             else {
371 2         53 printf "ERROR - %s\n", $log_msg;
372             }
373             }
374              
375             =head2 _log_error
376              
377             if ($self->errors_are_fatal && $nr_of_errors > 0) {
378             $log_msg = sprintf 'Too many errors in check_inifile_for_sections';
379             $self->_log_fatal($log_msg);
380             }
381              
382             =cut
383              
384             sub _log_fatal {
385 2     2   4 my $self = shift;
386 2         4 my $log_msg = shift;
387 2         9 my $logger = $self->logger;
388              
389 2 50       6 if ($logger) {
390 0         0 $logger->error($log_msg);
391             }
392             else {
393 2         16 print "ERROR - $log_msg\n";
394             }
395 2 50       12 if ( $self->errors_are_fatal ) {
396 2         33 die $log_msg;
397             }
398             }
399              
400             =head1 AUTHOR
401              
402             Richard Lippmann, C<< <horshack at cpan.org> >>
403              
404             =head1 BUGS
405              
406             Please report any bugs or feature requests to C<bug-config-inifiles-check-health at rt.cpan.org>, or through
407             the web interface at L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Config-IniFiles-Check-Health>. I will be notified, and then you'll
408             automatically be notified of progress on your bug as I make changes.
409              
410              
411              
412              
413             =head1 SUPPORT
414              
415             You can find documentation for this module with the perldoc command.
416              
417             perldoc Config::IniFiles::Check::Health
418              
419              
420             You can also look for information at:
421              
422             =over 4
423              
424             =item * RT: CPAN's request tracker (report bugs here)
425              
426             L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=Config-IniFiles-Check-Health>
427              
428             =item * CPAN Ratings
429              
430             L<https://cpanratings.perl.org/d/Config-IniFiles-Check-Health>
431              
432             =item * Search CPAN
433              
434             L<https://metacpan.org/release/Config-IniFiles-Check-Health>
435              
436             =back
437              
438              
439             =head1 ACKNOWLEDGEMENTS
440              
441              
442             =head1 LICENSE AND COPYRIGHT
443              
444             This software is Copyright (c) 2024 by Richard Lippmann.
445              
446             This is free software, licensed under:
447              
448             The Artistic License 2.0 (GPL Compatible)
449              
450              
451             =cut
452              
453             1;
454