| use strict; |
| use warnings FATAL => 'all'; |
| |
| use Apache::Test; |
| use Apache::TestRequest; |
| use Apache::TestUtil qw(t_write_file t_start_error_log_watch t_finish_error_log_watch t_cmp); |
| |
| use File::Spec; |
| |
| use Time::HiRes qw(usleep); |
| |
| # test ap_expr |
| |
| Apache::TestRequest::user_agent(keep_alive => 1); |
| |
| # The left-hand values are written into the config file as-is, i.e. |
| # necessary quoting for the config file parser needs to be included |
| # explicitly. |
| my @test_cases = ( |
| [ 'foo' => 'foo' ], |
| [ '%{req:SomeHeader}' => 'SomeValue' ], |
| [ '%{' => undef ], |
| [ '%' => '%' ], |
| [ '}' => '}' ], |
| [ q{\"} => q{"} ], |
| [ q{\'} => q{'} ], |
| [ q{"\%{req:SomeHeader}"} => '%{req:SomeHeader}' ], |
| [ '%{tolower:IDENT}' => 'ident' ], |
| [ '%{tolower:%{REQUEST_METHOD}}' => 'get' ], |
| ); |
| |
| if (have_min_apache_version("2.5")) { |
| my $SAN_one = "email:<redacted1>, email:<redacted2>, " . |
| "IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1, " . |
| "IP Address:192.168.169.170"; |
| my $SAN_tuple = "'email:<redacted1>', 'email:<redacted2>', " . |
| "'IP Address:127.0.0.1', 'IP Address:0:0:0:0:0:0:0:1', " . |
| "'IP Address:192.168.169.170'"; |
| my $SAN_list_one = "{ '$SAN_one' }"; |
| my $SAN_list_tuple = "{ $SAN_tuple }"; |
| |
| push(@test_cases, ( |
| [ qq["%{tolower:%{:toupper(%{REQUEST_METHOD}):}}"] => "get" ], |
| [ qq["%{: join $SAN_list_one :}"] => "$SAN_one" ], |
| [ qq["%{: join($SAN_list_tuple, ', ') :}"] => "$SAN_one" ], |
| [ qq['%{tolower:"IDENT"}'] => '"ident"' ], |
| [ qq["%{: 'IP Address:%{REMOTE_ADDR}' -in split/, /, join $SAN_list_one :}"] |
| => "true" ], |
| )); |
| } |
| |
| my $successful_expected = scalar(grep { defined $_->[1] } @test_cases); |
| |
| plan tests => scalar(@test_cases) * 2 + $successful_expected, |
| need need_lwp, |
| need_module('mod_log_debug'); |
| foreach my $t (@test_cases) { |
| my ($expr, $expect) = @{$t}; |
| |
| write_htaccess($expr); |
| |
| t_start_error_log_watch(); |
| my $response = GET('/apache/expr/index.html', |
| 'SomeHeader' => 'SomeValue', |
| 'User-Agent' => 'SomeAgent', |
| 'Referer' => 'SomeReferer'); |
| ### Sleep here, attempt to avoid intermittent failures. |
| usleep(250000); |
| my @loglines = t_finish_error_log_watch(); |
| |
| my @evalerrors = grep {/(?:internal evaluation error|flex scanner jammed)/i |
| } @loglines; |
| my $num_errors = scalar @evalerrors; |
| print "Error log should not have 'Internal evaluation error' or " . |
| "'flex scanner jammed' entries, found $num_errors:\n@evalerrors\n" |
| if $num_errors; |
| ok($num_errors == 0); |
| |
| my $rc = $response->code; |
| |
| if (!defined $expect) { |
| print qq{Should get parse error (500) for "$expr", got $rc\n}; |
| ok($rc == 500); |
| } |
| else { |
| print qq{Expected return code 200, got $rc for '$expr'\n}; |
| ok($rc == 200); |
| my @msg = grep { /log_debug:info/ } @loglines; |
| if (scalar @msg != 1) { |
| print "expected 1 message, got " . scalar @msg . ":\n@msg\n"; |
| ok(0); |
| } |
| elsif ($msg[0] =~ m{^(?:\[ # opening '[' |
| [^\]]+ # anything but a ']' |
| \] # closing ']' |
| [ ] # trailing space |
| ){4} # repeat 4 times (timestamp, level, pid, client IP) |
| (.*?) # The actual message logged by LogMessage |
| (,[ ]referer # either trailing referer (LogLevel info) |
| | # or |
| [ ]\(log_transaction) # trailing hook info (LogLevel debug and higher) |
| }x ) { |
| my $result = $1; |
| ok t_cmp($result, $expect, "log message @msg didn't match"); |
| } |
| else { |
| print "Can't extract expr result from log message:\n@msg\n"; |
| ok(0); |
| } |
| } |
| } |
| |
| exit 0; |
| |
| ### sub routines |
| sub write_htaccess |
| { |
| my $expr = shift; |
| my $file = File::Spec->catfile(Apache::Test::vars('serverroot'), 'htdocs', 'apache', 'expr', '.htaccess'); |
| t_write_file($file, << "EOF" ); |
| LogMessage $expr |
| EOF |
| } |