| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | ## no critic [ControlStructures::ProhibitPostfixControls] | 
| 2 |  |  |  |  |  |  | ## no critic [ValuesAndExpressions::ProhibitConstantPragma] | 
| 3 |  |  |  |  |  |  | ## no critic (ControlStructures::ProhibitCascadingIfElse) | 
| 4 |  |  |  |  |  |  | package Env::Assert; | 
| 5 | 3 |  |  | 3 |  | 683662 | use strict; | 
|  | 3 |  |  |  |  | 19 |  | 
|  | 3 |  |  |  |  | 82 |  | 
| 6 | 3 |  |  | 3 |  | 16 | use warnings; | 
|  | 3 |  |  |  |  | 5 |  | 
|  | 3 |  |  |  |  | 77 |  | 
| 7 |  |  |  |  |  |  |  | 
| 8 | 3 |  |  | 3 |  | 15 | use Exporter 'import'; | 
|  | 3 |  |  |  |  | 6 |  | 
|  | 3 |  |  |  |  | 202 |  | 
| 9 |  |  |  |  |  |  | our @EXPORT_OK = qw( | 
| 10 |  |  |  |  |  |  | assert | 
| 11 |  |  |  |  |  |  | report_errors | 
| 12 |  |  |  |  |  |  | file_to_desc | 
| 13 |  |  |  |  |  |  | ); | 
| 14 |  |  |  |  |  |  | our %EXPORT_TAGS = ( 'all' => [qw( assert report_errors file_to_desc )], ); | 
| 15 |  |  |  |  |  |  |  | 
| 16 | 3 |  |  | 3 |  | 1627 | use English qw( -no_match_vars );    # Avoids regex performance penalty in perl 5.18 and earlier | 
|  | 3 |  |  |  |  | 11486 |  | 
|  | 3 |  |  |  |  | 18 |  | 
| 17 | 3 |  |  | 3 |  | 1126 | use Carp; | 
|  | 3 |  |  |  |  | 6 |  | 
|  | 3 |  |  |  |  | 217 |  | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | # ABSTRACT: Ensure that the environment variables match what you need, or abort. | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  | our $VERSION = '0.006'; # VERSION: generated by DZP::OurPkgVersion | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | use constant { | 
| 24 | 3 |  |  |  |  | 3431 | ENV_ASSERT_MISSING_FROM_ENVIRONMENT    => 1, | 
| 25 |  |  |  |  |  |  | ENV_ASSERT_INVALID_CONTENT_IN_VARIABLE => 2, | 
| 26 |  |  |  |  |  |  | ENV_ASSERT_MISSING_FROM_DEFINITION     => 3, | 
| 27 |  |  |  |  |  |  | DEFAULT_PARAMETER_BREAK_AT_FIRST_ERROR => 0, | 
| 28 |  |  |  |  |  |  | INDENT                                 => q{    }, | 
| 29 | 3 |  |  | 3 |  | 32 | }; | 
|  | 3 |  |  |  |  | 6 |  | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | sub assert { | 
| 32 | 5 |  |  | 5 | 1 | 11614 | my ( $env, $want, $params ) = @_; | 
| 33 | 5 | 50 |  |  |  | 14 | $params = {} if !$params; | 
| 34 | 5 | 50 | 33 |  |  | 29 | croak 'Invalid options. Not a hash' if ( ref $env ne 'HASH' || ref $want ne 'HASH' ); | 
| 35 |  |  |  |  |  |  |  | 
| 36 |  |  |  |  |  |  | # Set default options | 
| 37 | 5 |  | 100 |  |  | 23 | $params->{'break_at_first_error'} //= DEFAULT_PARAMETER_BREAK_AT_FIRST_ERROR; | 
| 38 |  |  |  |  |  |  |  | 
| 39 | 5 |  |  |  |  | 8 | my $success = 1; | 
| 40 | 5 |  |  |  |  | 7 | my %errors; | 
| 41 | 5 |  |  |  |  | 9 | my $vars = $want->{'variables'}; | 
| 42 | 5 |  |  |  |  | 8 | my $opts = $want->{'options'}; | 
| 43 | 5 |  |  |  |  | 8 | foreach my $var_name ( keys %{$vars} ) { | 
|  | 5 |  |  |  |  | 14 |  | 
| 44 | 7 |  |  |  |  | 17 | my $var      = $vars->{$var_name}; | 
| 45 | 7 |  | 50 |  |  | 43 | my $required = $var->{'required'} // 1; | 
| 46 | 7 |  | 50 |  |  | 17 | my $regexp   = $var->{'regexp'}   // q{.*}; | 
| 47 | 7 | 100 | 66 |  |  | 291 | if ( ( $opts->{'exact'} || $required ) && !defined $env->{$var_name} ) { | 
|  |  | 100 | 66 |  |  |  |  | 
| 48 | 3 |  |  |  |  | 6 | $success = 0; | 
| 49 | 3 |  |  |  |  | 12 | $errors{'variables'}->{$var_name} = { | 
| 50 |  |  |  |  |  |  | type    => ENV_ASSERT_MISSING_FROM_ENVIRONMENT, | 
| 51 |  |  |  |  |  |  | message => "Variable $var_name is missing from environment", | 
| 52 |  |  |  |  |  |  | }; | 
| 53 | 3 | 50 |  |  |  | 9 | goto EXIT if ( $params->{'break_at_first_error'} ); | 
| 54 |  |  |  |  |  |  | } | 
| 55 |  |  |  |  |  |  | elsif ( $env->{$var_name} !~ m/$regexp/msx ) { | 
| 56 | 1 |  |  |  |  | 5 | $success = 0; | 
| 57 | 1 |  |  |  |  | 6 | $errors{'variables'}->{$var_name} = { | 
| 58 |  |  |  |  |  |  | type    => ENV_ASSERT_INVALID_CONTENT_IN_VARIABLE, | 
| 59 |  |  |  |  |  |  | message => "Variable $var_name has invalid content", | 
| 60 |  |  |  |  |  |  | }; | 
| 61 | 1 | 50 |  |  |  | 5 | goto EXIT if ( $params->{'break_at_first_error'} ); | 
| 62 |  |  |  |  |  |  | } | 
| 63 |  |  |  |  |  |  | } | 
| 64 | 5 | 100 |  |  |  | 12 | if ( $opts->{'exact'} ) { | 
| 65 | 4 |  |  |  |  | 9 | foreach my $var_name ( keys %{$env} ) { | 
|  | 4 |  |  |  |  | 10 |  | 
| 66 | 6 | 100 |  |  |  | 23 | if ( !exists $vars->{$var_name} ) { | 
| 67 | 2 |  |  |  |  | 3 | $success = 0; | 
| 68 | 2 |  |  |  |  | 13 | $errors{'variables'}->{$var_name} = { | 
| 69 |  |  |  |  |  |  | type    => ENV_ASSERT_MISSING_FROM_DEFINITION, | 
| 70 |  |  |  |  |  |  | message => "Variable $var_name is missing from description", | 
| 71 |  |  |  |  |  |  | }; | 
| 72 | 2 | 50 |  |  |  | 8 | goto EXIT if ( $params->{'break_at_first_error'} ); | 
| 73 |  |  |  |  |  |  | } | 
| 74 |  |  |  |  |  |  | } | 
| 75 |  |  |  |  |  |  | } | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  | EXIT: | 
| 78 | 5 |  |  |  |  | 22 | return { success => $success, errors => \%errors, }; | 
| 79 |  |  |  |  |  |  | } | 
| 80 |  |  |  |  |  |  |  | 
| 81 |  |  |  |  |  |  | sub report_errors { | 
| 82 | 3 |  |  | 3 | 1 | 7577 | my ($errors) = @_; | 
| 83 | 3 |  |  |  |  | 6 | my $out = q{}; | 
| 84 | 3 |  |  |  |  | 7 | $out .= sprintf "Environment Assert: ERRORS:\n"; | 
| 85 | 3 |  |  |  |  | 5 | foreach my $error_area_name ( sort keys %{$errors} ) { | 
|  | 3 |  |  |  |  | 10 |  | 
| 86 | 2 |  |  |  |  | 10 | $out .= sprintf "%s%s:\n", INDENT, $error_area_name; | 
| 87 | 2 |  |  |  |  | 5 | foreach my $error_key ( sort keys %{ $errors->{$error_area_name} } ) { | 
|  | 2 |  |  |  |  | 9 |  | 
| 88 | 3 |  |  |  |  | 13 | $out .= sprintf "%s%s: %s\n", INDENT . INDENT, $error_key, $errors->{$error_area_name}->{$error_key}->{'message'}; | 
| 89 |  |  |  |  |  |  | } | 
| 90 |  |  |  |  |  |  | } | 
| 91 | 3 |  |  |  |  | 9 | return $out; | 
| 92 |  |  |  |  |  |  | } | 
| 93 |  |  |  |  |  |  |  | 
| 94 |  |  |  |  |  |  | sub file_to_desc { | 
| 95 | 0 |  |  | 0 | 1 | 0 | my @rows = @_; | 
| 96 | 0 |  |  |  |  | 0 | my %desc = ( 'options' => {}, 'variables' => {}, ); | 
| 97 | 0 |  |  |  |  | 0 | foreach (@rows) { | 
| 98 |  |  |  |  |  |  |  | 
| 99 |  |  |  |  |  |  | # This is envassert meta command | 
| 100 |  |  |  |  |  |  | ## no critic (RegularExpressions::ProhibitComplexRegexes) | 
| 101 | 0 | 0 |  |  |  | 0 | if ( | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 102 |  |  |  |  |  |  | m{ | 
| 103 |  |  |  |  |  |  | ^ [[:space:]]{0,} [#]{2} | 
| 104 |  |  |  |  |  |  | [[:space:]]{1,} envassert [[:space:]]{1,} | 
| 105 |  |  |  |  |  |  | [(] opts: [[:space:]]{0,} (? .*) [)] | 
| 106 |  |  |  |  |  |  | [[:space:]]{0,} $ | 
| 107 |  |  |  |  |  |  | }msx | 
| 108 |  |  |  |  |  |  | ) | 
| 109 |  |  |  |  |  |  | { | 
| 110 | 0 |  |  |  |  | 0 | my $opts = _interpret_opts( $LAST_PAREN_MATCH{opts} ); | 
| 111 | 0 |  |  |  |  | 0 | foreach ( keys %{$opts} ) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 112 | 0 |  |  |  |  | 0 | $desc{'options'}->{$_} = $opts->{$_}; | 
| 113 |  |  |  |  |  |  | } | 
| 114 |  |  |  |  |  |  | } | 
| 115 |  |  |  |  |  |  | elsif ( | 
| 116 |  |  |  |  |  |  | # This is comment row | 
| 117 |  |  |  |  |  |  | m{ | 
| 118 |  |  |  |  |  |  | ^ [[:space:]]{0,} [#]{1} .* $ | 
| 119 |  |  |  |  |  |  | }msx | 
| 120 |  |  |  |  |  |  | ) | 
| 121 |  |  |  |  |  |  | { | 
| 122 | 0 |  |  |  |  | 0 | 1; | 
| 123 |  |  |  |  |  |  | } | 
| 124 |  |  |  |  |  |  | elsif ( | 
| 125 |  |  |  |  |  |  | # This is empty row | 
| 126 |  |  |  |  |  |  | m{ | 
| 127 |  |  |  |  |  |  | ^ [[:space:]]{0,} $ | 
| 128 |  |  |  |  |  |  | }msx | 
| 129 |  |  |  |  |  |  | ) | 
| 130 |  |  |  |  |  |  | { | 
| 131 | 0 |  |  |  |  | 0 | 1; | 
| 132 |  |  |  |  |  |  | } | 
| 133 |  |  |  |  |  |  | elsif ( | 
| 134 |  |  |  |  |  |  | # This is env var description | 
| 135 |  |  |  |  |  |  | m{ | 
| 136 |  |  |  |  |  |  | ^ (? [^=]{1,}) = (? .*) $ | 
| 137 |  |  |  |  |  |  | }msx | 
| 138 |  |  |  |  |  |  | ) | 
| 139 |  |  |  |  |  |  | { | 
| 140 | 0 |  |  |  |  | 0 | $desc{'variables'}->{ $LAST_PAREN_MATCH{name} } = { regexp => $LAST_PAREN_MATCH{value} }; | 
| 141 |  |  |  |  |  |  | } | 
| 142 |  |  |  |  |  |  | } | 
| 143 | 0 |  |  |  |  | 0 | return \%desc; | 
| 144 |  |  |  |  |  |  | } | 
| 145 |  |  |  |  |  |  |  | 
| 146 |  |  |  |  |  |  | # Private subroutines | 
| 147 |  |  |  |  |  |  |  | 
| 148 |  |  |  |  |  |  | sub _interpret_opts { | 
| 149 | 6 |  |  | 6 |  | 9411 | my ($opts_str) = @_; | 
| 150 | 6 |  |  |  |  | 49 | my @opts = split qr{ | 
| 151 |  |  |  |  |  |  | [[:space:]]{0,} [,] [[:space:]]{0,} | 
| 152 |  |  |  |  |  |  | }msx, $opts_str; | 
| 153 | 6 |  |  |  |  | 17 | my %opts; | 
| 154 | 6 |  |  |  |  | 11 | foreach (@opts) { | 
| 155 | 11 |  |  |  |  | 42 | my ( $key, $val ) = split qr/=/msx; | 
| 156 | 11 |  |  |  |  | 35 | $opts{$key} = $val; | 
| 157 |  |  |  |  |  |  | } | 
| 158 | 6 |  |  |  |  | 18 | return \%opts; | 
| 159 |  |  |  |  |  |  | } | 
| 160 |  |  |  |  |  |  |  | 
| 161 |  |  |  |  |  |  | 1; | 
| 162 |  |  |  |  |  |  |  | 
| 163 |  |  |  |  |  |  | __END__ |