geoff 2004/11/01 11:45:16
Modified: perl-framework/Apache-Test/lib/Apache TestConfigPHP.pm TestRunPHP.pm Log: autogenerate php.ini and make sure that php picks it up move functions to test-more.php Revision Changes Path 1.8 +508 -112 httpd-test/perl-framework/Apache-Test/lib/Apache/TestConfigPHP.pm Index: TestConfigPHP.pm =================================================================== RCS file: /home/cvs/httpd-test/perl-framework/Apache-Test/lib/Apache/TestConfigPHP.pm,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- TestConfigPHP.pm 26 Oct 2004 16:55:49 -0000 1.7 +++ TestConfigPHP.pm 1 Nov 2004 19:45:16 -0000 1.8 @@ -28,28 +28,47 @@ @Apache::TestConfigPHP::ISA = qw(Apache::TestConfig); -sub new { - return shift->SUPER::new(@_); -} +my ($php_ini, $test_more); -my %outside_container = map { $_, 1 } qw{ -Alias AliasMatch -}; +{ + # __DATA__ contains both php.ini and test-more.php -my %strip_tags = map { $_ => 1} qw(base noautoconfig); + local $/ = "END_OF_FILE\n"; + + $php_ini = <DATA>; + chomp $php_ini; + + $test_more = <DATA>; + chomp $test_more; +} -#test .php's can have configuration after the __DATA__ token -sub add_module_config { - # this is just a stub at the moment until somebody gives me - # an end-of-file PHP token that is similar to __DATA__ or __END__ +sub new { + return shift->SUPER::new(@_); } -my @extra_subdirs = qw(Response); +my %warn_style = ( + html => sub { "<!-- @_ -->" }, + c => sub { "/* @_ */" }, + ini => sub { join '', grep {s/^/; /gm} @_ }, + default => sub { join '', grep {s/^/\# /gm} @_ }, +); + +my %file_ext = ( + map({$_ => 'html'} qw(htm html)), + map({$_ => 'c' } qw(c h)), + map({$_ => 'ini' } qw(ini)), +); + +sub warn_style_sub_ref { + my ($self, $filename) = @_; + my $ext = $self->filename_ext($filename); + return $warn_style{ $file_ext{$ext} || 'default' }; +} sub configure_php_tests_pick { my($self, $entries) = @_; - for my $subdir (@extra_subdirs) { + for my $subdir (qw(Response)) { my $dir = catfile $self->{vars}->{t_dir}, lc $subdir; next unless -d $dir; @@ -115,25 +134,43 @@ my $path = catfile $serverroot, 'conf'; - my $cfg = "php_value include_path $path\n"; - - my $php = $self->{vars}->{php_module}; + # make sure that require() or include() calls can find + # the generated test-more.php without using absolute paths + my $cfg = { php_value => "include_path $path", }; + $self->postamble(IfModule => $self->{vars}->{php_module}, $cfg); - $self->postamble(IfModule => $php, $cfg); + # give test-more.php access to the ServerRoot directive + $self->postamble("SetEnv SERVER_ROOT $serverroot\n"); } sub configure_php_functions { my $self = shift; my $dir = catfile $self->{vars}->{serverroot}, 'conf'; - my $file = catfile $dir, 'test_more.inc'; + my $file = catfile $dir, 'test-more.php'; $self->gendir($dir); my $fh = $self->genfile($file, undef, 1); - while (my $line = <DATA>) { - print $fh $line; - } + print $fh $test_more; + + close $fh or die "close $file: $!"; + + $self->clean_add_file($file); +} + +sub configure_php_ini { + my $self = shift; + + my $dir = catfile $self->{vars}->{serverroot}, 'conf'; + my $file = catfile $dir, 'php.ini'; + my $log = catfile $self->{vars}->{t_logs}, 'error_log'; + + $self->gendir($dir); + my $fh = $self->genfile($file, undef); + + $php_ini =~ s/[EMAIL PROTECTED]@/error_log $log/; + print $fh $php_ini; close $fh or die "close $file: $!"; @@ -182,187 +219,546 @@ 1; __DATA__ +; This is php.ini-recommended from php 5.0.2, +; used in place of your locally installed php.ini file +; as part of the pristine environment Apache-Test creates +; for you +; +; exceptions to php.ini-recommended are as follows: +display_startup_errors = On +html_errors = Off [EMAIL PROTECTED]@ + +; the rest of php.ini-recommended, unaltered, save for +; some tidying like the removal of comments and blank lines + +[PHP] +engine = On +zend.ze1_compatibility_mode = Off +short_open_tag = On +asp_tags = Off +precision = 14 +y2k_compliance = On +output_buffering = 4096 +zlib.output_compression = Off +implicit_flush = Off +unserialize_callback_func= +serialize_precision = 100 +allow_call_time_pass_reference = Off +safe_mode = Off +safe_mode_gid = Off +safe_mode_include_dir = +safe_mode_exec_dir = +safe_mode_allowed_env_vars = PHP_ +safe_mode_protected_env_vars = LD_LIBRARY_PATH +disable_functions = +disable_classes = +expose_php = On +max_execution_time = 30 +max_input_time = 60 +memory_limit = 8M +error_reporting = E_ALL +display_errors = Off +;display_startup_errors = Off +log_errors = On +log_errors_max_len = 1024 +ignore_repeated_errors = Off +ignore_repeated_source = Off +report_memleaks = On +track_errors = Off +variables_order = "GPCS" +register_globals = Off +register_long_arrays = Off +register_argc_argv = Off +post_max_size = 8M +magic_quotes_gpc = Off +magic_quotes_runtime = Off +magic_quotes_sybase = Off +auto_prepend_file = +auto_append_file = +default_mimetype = "text/html" +doc_root = +user_dir = +extension_dir = "./" +enable_dl = On +file_uploads = On +upload_max_filesize = 2M +allow_url_fopen = On +default_socket_timeout = 60 +[Syslog] +define_syslog_variables = Off +[mail function] +SMTP = localhost +smtp_port = 25 +[SQL] +sql.safe_mode = Off +[ODBC] +odbc.allow_persistent = On +odbc.check_persistent = On +odbc.max_persistent = -1 +odbc.max_links = -1 +odbc.defaultlrl = 4096 +odbc.defaultbinmode = 1 +[MySQL] +mysql.allow_persistent = On +mysql.max_persistent = -1 +mysql.max_links = -1 +mysql.default_port = +mysql.default_socket = +mysql.default_host = +mysql.default_user = +mysql.default_password = +mysql.connect_timeout = 60 +mysql.trace_mode = Off +[MySQLI] +mysqli.max_links = -1 +mysqli.default_port = 3306 +mysqli.default_socket = +mysqli.default_host = +mysqli.default_user = +mysqli.default_password = +mysqli.reconnect = Off +[mSQL] +msql.allow_persistent = On +msql.max_persistent = -1 +msql.max_links = -1 +[PostgresSQL] +pgsql.allow_persistent = On +pgsql.auto_reset_persistent = Off +pgsql.max_persistent = -1 +pgsql.max_links = -1 +pgsql.ignore_notice = 0 +pgsql.log_notice = 0 +[Sybase] +sybase.allow_persistent = On +sybase.max_persistent = -1 +sybase.max_links = -1 +sybase.min_error_severity = 10 +sybase.min_message_severity = 10 +sybase.compatability_mode = Off +[Sybase-CT] +sybct.allow_persistent = On +sybct.max_persistent = -1 +sybct.max_links = -1 +sybct.min_server_severity = 10 +sybct.min_client_severity = 10 +[dbx] +dbx.colnames_case = "lowercase" +[bcmath] +bcmath.scale = 0 +[browscap] +[Informix] +ifx.default_host = +ifx.default_user = +ifx.default_password = +ifx.allow_persistent = On +ifx.max_persistent = -1 +ifx.max_links = -1 +ifx.textasvarchar = 0 +ifx.byteasvarchar = 0 +ifx.charasvarchar = 0 +ifx.blobinfile = 0 +ifx.nullformat = 0 +[Session] +session.save_handler = files +session.use_cookies = 1 +session.name = PHPSESSID +session.auto_start = 0 +session.cookie_lifetime = 0 +session.cookie_path = / +session.cookie_domain = +session.serialize_handler = php +session.gc_probability = 1 +session.gc_divisor = 1000 +session.gc_maxlifetime = 1440 +session.bug_compat_42 = 0 +session.bug_compat_warn = 1 +session.referer_check = +session.entropy_length = 0 +session.entropy_file = +session.cache_limiter = nocache +session.cache_expire = 180 +session.use_trans_sid = 0 +session.hash_function = 0 +session.hash_bits_per_character = 5 +url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry" +[MSSQL] +mssql.allow_persistent = On +mssql.max_persistent = -1 +mssql.max_links = -1 +mssql.min_error_severity = 10 +mssql.min_message_severity = 10 +mssql.compatability_mode = Off +mssql.secure_connection = Off +[Assertion] +[Ingres II] +ingres.allow_persistent = On +ingres.max_persistent = -1 +ingres.max_links = -1 +ingres.default_database = +ingres.default_user = +ingres.default_password = +[Verisign Payflow Pro] +pfpro.defaulthost = "test-payflow.verisign.com" +pfpro.defaultport = 443 +pfpro.defaulttimeout = 30 +[Sockets] +sockets.use_system_read = On +[com] +[mbstring] +[FrontBase] +[exif] +[Tidy] +tidy.clean_output = Off +[soap] +soap.wsdl_cache_enabled=1 +soap.wsdl_cache_dir="/tmp" +soap.wsdl_cache_ttl=86400 +END_OF_FILE <?php -# emulation of Perl's Test::More for PHP -# -# see -# http://search.cpan.org/dist/Test-Simple/lib/Test/More.pm -# for Perl's documentation - these functions should behave -# in the same way -# -# based on initial work from Andy Lester -# extensive rework by Chris Shiflett +/*******************************************************************\ +* PROJECT INFORMATION * +* * +* Project: Apache-Test * +* URL: http://httpd.apache.org/test/ * +* Notice: Copyright (c) 2004 The Apache Software Foundation * +* * +********************************************************************* +* LICENSE INFORMATION * +* * +* Licensed under the Apache License, Version 2.0 (the "License"); * +* you may not use this file except in compliance with the * +* License. You may obtain a copy of the License at: * +* * +* http://www.apache.org/licenses/LICENSE-2.0 * +* * +* Unless required by applicable law or agreed to in writing, * +* software distributed under the License is distributed on an "AS * +* IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * +* express or implied. See the License for the specific language * +* governing permissions and limitations under the License. * +* * +********************************************************************* +* MODULE INFORMATION * +* * +* This is a PHP implementation of Test::More: * +* * +* http://search.cpan.org/dist/Test-Simple/lib/Test/More.pm * +* * +********************************************************************* +* CREDITS * +* * +* Originally inspired by work from Andy Lester. Written and * +* maintained by Chris Shiflett. For contact information, see: * +* * +* http://shiflett.org/contact * +* * +\*******************************************************************/ + +header('Content-Type: text/plain'); +register_shutdown_function('_test_end'); $_no_plan = false; $_num_failures = 0; $_num_skips = 0; -$_test = 0; +$_skip_all = false; +$_skip_reason = ''; +$_test_num = 0; + +function plan($plan) +{ + # plan('no_plan'); + # plan('skip_all'); + # plan('skip_all' => 'My reason is...'); + # plan(23); -register_shutdown_function('_test_end'); + global $_no_plan; + global $_skip_all; + global $_skip_reason; -function diag($lines) + switch ($plan) + { + case 'no_plan': + $_no_plan = true; + break; + case 'skip_all': + $_skip_all = true; + break; + case 'Array': + $_skip_all = true; + $_skip_reason = $plan['skip_all']; + break; + default: + echo "1..$plan\n"; + break; + } +} + +function ok($pass, $test_name = '') { - if (is_string($lines)) + global $_test_num; + global $_num_failures; + global $_num_skips; + + $_test_num++; + + if ($_num_skips) { - $lines = explode("\n", $lines); + $_num_skips--; + return true; } - foreach ($lines as $str) + if (!empty($test_name)) { - echo "# $str\n"; + $test_name = "- $test_name"; } -} -function fail($name = '') -{ - return ok(false, $name); + if ($pass) + { + echo "ok $_test_num $test_name\n"; + } + else + { + echo "not ok $_test_num $test_name\n"; + + $_num_failures++; + $caller = debug_backtrace(); + + if (strstr($caller['0']['file'], $_SERVER['PHP_SELF'])) + { + $file = $caller['0']['file']; + $line = $caller['0']['line']; + } + else + { + $file = $caller['1']['file']; + $line = $caller['1']['line']; + } + + $file = str_replace($_SERVER['SERVER_ROOT'], 't', $file); + + diag(" Failed test ($file at line $line)"); + } + + return $pass; } -function is($actual, $expected, $name = '') +function is($this, $that, $test_name = '') { - $ok = ($expected == $actual); - ok($ok, $name); + $pass = ($this == $that); + ok($pass, $test_name); - if (!$ok) + if (!$pass) { - diag(" got: '$actual'"); - diag(" expected: '$expected'"); + diag(" got: '$this'"); + diag(" expected: '$that'"); } - return $ok; + return $pass; } - -function isnt($actual, $dontwant, $name = '') + +function isnt($this, $that, $test_name = '') { - $ok = ($actual != $dontwant); - ok($ok, $name); + $pass = ($this != $that); + ok($pass, $test_name); - if (!$ok) + if (!$pass) { - diag("Didn't want '$actual'"); + diag(" '$this'"); + diag(" !="); + diag(" '$that'"); } - return $ok; + return $pass; } -function isa_ok($object, $class, $name = null) +function like($string, $regex, $test_name = '') { - if (isset($object)) - { - $actual = get_class($object); - - if (!isset($name)) - { - $name = "Object is of type $class"; - } + $pass = preg_match($regex, $string); + ok($pass, $test_name); - return is(get_class($object), strtolower($class), $name); - } - else + if (!$pass) { - return fail('object is undefined'); + diag(" '$string'"); + diag(" doesn't match '$regex'"); } + + return $pass; } -function like($string, $regex, $name='') +function unlike($string, $regex, $test_name = '') { - $ok = ok(preg_match($regex, $string), $name); + $pass = !preg_match($regex, $string); + ok($pass, $test_name); - if (!$ok) + if (!$pass) { - diag(" '$string'"); - diag(" doesn't match '$regex'"); - + diag(" '$string'"); + diag(" matches '$regex'"); } - return $ok; + return $pass; } -function no_plan() +function cmp_ok($this, $operator, $that, $test_name = '') { - global $_no_plan; - $_no_plan = true; + eval('$pass = ($this ' . $operator . ' $that);'); + ok($pass, $test_name); + + if (!$pass) + { + diag(" got: '$this'"); + diag(" expected: '$that'"); + } + + return $pass; } -function ok($condition, $name = '') +function can_ok($object, $methods) { - global $_test; - global $_num_failures; - global $_num_skips; - $_test++; - $caller = debug_backtrace(); + $pass = true; + $errors = array(); - if ($_num_skips) + foreach ($methods as $method) { - $_num_skips--; - return true; + if (!method_exists($object, $method)) + { + $pass = false; + $errors[] = " method_exists(\$object, $method) failed"; + } } - if (basename($caller['0']['file']) == 'test_more.inc') + if ($pass) { - $file = $caller['1']['file']; - $line = $caller['1']['line']; + ok(true, "method_exists(\$object, ...)"); } else { - $file = $caller['0']['file']; - $line = $caller['0']['line']; + ok(false, "method_exists(\$object, ...)"); + diag($errors); } - $file = str_replace($_SERVER['SERVER_ROOT'], 't', $file); + return $pass; +} + +function isa_ok($object, $expected_class, $object_name = 'The object') +{ + $got_class = get_class($object); - if (!$condition) + if (version_compare(php_version(), '5', '>=')) { - echo "not ok $_test"; - $_num_failures++; + $pass = ($got_class == $expected_class); } else { - echo "ok $_test"; + $pass = ($got_class == strtolower($expected_class)); } - if (!empty($name)) + if ($pass) { - echo " - $name"; + ok(true, "$object_name isa $expected_class"); } - - echo "\n"; - - if (!$condition) + else { - echo "# Failed test ($file at line $line)\n"; + ok(false, "$object_name isn't a '$expected_class' it's a '$got_class'"); } - return $condition; + return $pass; } -function pass($name = '') +function pass($test_name = '') { - return ok(true, $name); + return ok(true, $test_name); } -function plan($num_tests) +function fail($test_name = '') +{ + return ok(false, $test_name); +} + +function diag($message) +{ + if (is_array($message)) + { + foreach($message as $current) + { + echo "# $current\n"; + } + } + else + { + echo "# $message\n"; + } +} + +function include_ok($module) { - echo "1..$num_tests\n"; + $pass = ((include $module) == 'OK'); + return ok($pass); } -function skip($msg, $num) +function require_ok($module) +{ + $pass = ((require $module) == 'OK'); + return ok($pass); +} + +function skip($message, $num) { global $_num_skips; + if ($num < 0) + { + $num = 0; + } + for ($i = 0; $i < $num; $i++) { - pass("# SKIP $msg"); + # FIXME: The pound sign should replace the hyphen + pass("# SKIP $message"); } $_num_skips = $num; } +# function todo() +# { +# } + +# function todo_skip() +# { +# } + +# function is_deeply() +# { +# } + +# function eq_array() +# { +# } + +# function eq_hash() +# { +# } + +# function eq_set() +# { +# } + function _test_end() { + global $_no_plan; + global $_num_failures; + global $_test_num; + if ($_no_plan) { - echo "1..$_test\n"; + echo "1..$_test_num\n"; + } + + if ($_num_failures) + { + diag("Looks like you failed $_num_failures tests of $_test_num."); } } ?> 1.4 +19 -5 httpd-test/perl-framework/Apache-Test/lib/Apache/TestRunPHP.pm Index: TestRunPHP.pm =================================================================== RCS file: /home/cvs/httpd-test/perl-framework/Apache-Test/lib/Apache/TestRunPHP.pm,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- TestRunPHP.pm 26 Oct 2004 16:55:49 -0000 1.3 +++ TestRunPHP.pm 1 Nov 2004 19:45:16 -0000 1.4 @@ -17,6 +17,8 @@ use strict; use warnings FATAL => 'all'; +use File::Spec::Functions qw(catfile); + use Apache::TestRun (); use Apache::TestConfigParse (); use Apache::TestTrace; @@ -27,10 +29,20 @@ use File::Spec::Functions qw(catfile); -#subclass of Apache::TestRun that configures mod_perlish things +# subclass of Apache::TestRun that configures php things use vars qw(@ISA); @ISA = qw(Apache::TestRun); +sub start { + my $self = shift; + + # point php to our own php.ini file + $ENV{PHPRC} = catfile $self->{test_config}->{vars}->{serverroot}, + 'conf'; + + $self->SUPER::start(@_); +} + sub new_test_config { my $self = shift; @@ -43,6 +55,7 @@ my $test_config = $self->{test_config}; $test_config->postamble_register(qw(configure_php_inc + configure_php_ini configure_php_functions configure_php_tests)); } @@ -115,7 +128,8 @@ prior to configuring the test framework as shown above, either by virtue of PHP being compiled into the C<httpd> binary statically or through an active C<LoadModule> statement within the configuration -located in C</my/local/apache/conf/httpd.conf>. +located in C</my/local/apache/conf/httpd.conf>. Other required modules +are the (very common) mod_alias and mod_env. now, like with C<Apache::TestRun> and C<Apache::TestRunPerl>, you can place client-side Perl test scripts under C<t/>, such as C<t/01basic.t>, @@ -157,7 +171,7 @@ # http://search.cpan.org/dist/Test-Simple/lib/Test/More.pm # for Perl's documentation - these functions should behave # in the same way - require 'test_more.inc'; + require 'test-more.php'; # plan() the number of tests plan(6); @@ -178,10 +192,10 @@ is ('biff', 'biff', 'baz is a baz'); ?> -the include library C<test_more.inc> is automatically generated by +the include library C<test-more.php> is automatically generated by C<Apache::TestConfigPHP> and configurations tweaked in such a a way that your PHP scripts can find it without issue. the -functions provided by C<test_more.inc> are equivalent in name and +functions provided by C<test-more.php> are equivalent in name and function to those in C<Test::More>, a standard Perl testing library, so you can see that manpage for details on the syntax and functionality of each.