diff --git a/min_unit_tests/test_Minify.php b/min_unit_tests/test_Minify.php deleted file mode 100644 index 8193a67..0000000 --- a/min_unit_tests/test_Minify.php +++ /dev/null @@ -1,245 +0,0 @@ - $_SERVER, - )); - $sourceFactory = new Minify_Source_Factory($env, array(), new Minify_Cache_Null()); - $controller = new Minify_Controller_Files($env, $sourceFactory); - - $output = $minify->serve($controller, array( - 'files' => $thisDir . '/_test_files/css/styles.css' // controller casts to array - ,'quiet' => true - ,'lastModifiedTime' => $lastModified - ,'encodeOutput' => false - )); - - $expected = array ( - 'success' => true - ,'statusCode' => 304 - ,'content' => '', - 'headers' => array( - 'Expires' => gmdate('D, d M Y H:i:s \G\M\T', $_SERVER['REQUEST_TIME'] + 1800), - 'Vary' => 'Accept-Encoding', - 'Last-Modified' => gmdate('D, d M Y H:i:s \G\M\T', $lastModified), - 'ETag' => "\"pub{$lastModified}\"", - 'Cache-Control' => 'max-age=1800', - '_responseCode' => 'HTTP/1.0 304 Not Modified', - ) - ); - - $passed = assertTrue($expected === $output, 'Minify : 304 response'); - if ($thisFileActive) { - echo "\nOutput: " .var_export($output, 1). "\n\n"; - if (! $passed) { - echo "\n\n\n\n---Expected: " .var_export($expected, 1). "\n\n"; - } - } - - assertTrue( - ! class_exists('Minify_CSSmin', false) - ,'Minify : minifier classes aren\'t loaded for 304s' - ); - - // Test JS and Expires - - $content = preg_replace('/\\r\\n?/', "\n", file_get_contents($minifyTestPath . '/minified.js')); - $lastModified = max( - filemtime($minifyTestPath . '/email.js') - ,filemtime($minifyTestPath . '/QueryString.js') - ); - $expected = array( - 'success' => true - ,'statusCode' => 200 - // JSMin always converts to \n line endings - ,'content' => $content - ,'headers' => array ( - 'Expires' => gmdate('D, d M Y H:i:s \G\M\T', $tomorrow), - 'Vary' => 'Accept-Encoding', - 'Last-Modified' => gmdate('D, d M Y H:i:s \G\M\T', $lastModified), - 'ETag' => "\"pub{$lastModified}\"", - 'Cache-Control' => 'max-age=86400', - 'Content-Length' => countBytes($content), - 'Content-Type' => 'application/x-javascript; charset=utf-8', - ) - ); - - unset($_SERVER['HTTP_IF_NONE_MATCH']); - unset($_SERVER['HTTP_IF_MODIFIED_SINCE']); - - $env = new Minify_Env(array( - 'server' => $_SERVER, - )); - $sourceFactory = new Minify_Source_Factory($env, array(), new Minify_Cache_Null()); - $controller = new Minify_Controller_Files($env, $sourceFactory); - $output = $minify->serve($controller, array( - 'files' => array( - $minifyTestPath . '/email.js' - ,$minifyTestPath . '/QueryString.js' - ) - ,'quiet' => true - ,'maxAge' => 86400 - ,'encodeOutput' => false - )); - - $passed = assertTrue($expected === $output, 'Minify : JS and Expires'); - if ($thisFileActive) { - echo "\nOutput: " .var_export($output, 1). "\n\n"; - if (! $passed) { - echo "\n\n\n\n---Expected: " .var_export($expected, 1). "\n\n"; - } - } - - // test for Issue 73 - $expected = ";function h(){}"; - $output = $minify->serve($controller, array( - 'files' => array( - $minifyTestPath . '/issue73_1.js' - ,$minifyTestPath . '/issue73_2.js' - ) - ,'quiet' => true - ,'encodeOutput' => false - )); - $output = $output['content']; - - $passed = assertTrue($expected === $output, 'Minify : Issue 73'); - if ($thisFileActive) { - if (! $passed) { - echo "\n---Output : " .var_export($output, 1). "\n"; - echo "---Expected: " .var_export($expected, 1). "\n\n"; - } - } - - // test for Issue 89 - $expected = file_get_contents($minifyTestPath . '/issue89_out.min.css'); - $output = $minify->serve($controller, array( - 'files' => array( - $minifyTestPath . '/issue89_1.css' - ,$minifyTestPath . '/issue89_2.css' - ) - ,'quiet' => true - ,'encodeOutput' => false - ,'bubbleCssImports' => true - )); - $output = $output['content']; - $passed = assertTrue($expected === $output, 'Minify : Issue 89 : bubbleCssImports'); - if ($thisFileActive) { - if (! $passed) { - echo "\n---Output : " .var_export($output, 1). "\n"; - echo "---Expected: " .var_export($expected, 1). "\n\n"; - } - } - - $output = $minify->serve($controller, array( - 'files' => array( - $minifyTestPath . '/issue89_1.css' - ,$minifyTestPath . '/issue89_2.css' - ) - ,'quiet' => true - ,'encodeOutput' => false - )); - $output = $output['content']; - - $defaultOptions = $minify->getDefaultOptions(); - - $passed = assertTrue(0 === strpos($output, $defaultOptions['importWarning']), 'Minify : Issue 89 : detect invalid imports'); - if ($thisFileActive) { - if (! $passed) { - echo "\n---Output : " .var_export($output, 1). "\n"; - echo "---Expected: " .var_export($expected, 1). "\n\n"; - } - } - - $output = $minify->serve($controller, array( - 'files' => array( - $minifyTestPath . '/issue89_1.css' - ) - ,'quiet' => true - ,'encodeOutput' => false - )); - $output = $output['content']; - $passed = assertTrue(false === strpos($output, $defaultOptions['importWarning']), 'Minify : Issue 89 : don\'t warn about valid imports'); - if ($thisFileActive) { - if (! $passed) { - echo "\n---Output : " .var_export($output, 1). "\n"; - echo "---Expected: " .var_export($expected, 1). "\n\n"; - } - } - - // Test Issue 132 - if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) { - $output = $minify->serve($controller, array( - 'files' => array(__DIR__ . '/_test_files/js/issue132.js') - ,'quiet' => true - ,'encodeOutput' => false - )); - $passed = assertTrue($output['headers']['Content-Length'] == 77, 'Minify : Issue 132 : mbstring.func_overload shouldn\'t cause incorrect Content-Length'); - } - - // Test minifying CSS and responding with Etag/Last-Modified - - // don't allow conditional headers - unset($_SERVER['HTTP_IF_NONE_MATCH'], $_SERVER['HTTP_IF_MODIFIED_SINCE']); - - $expectedContent = file_get_contents($minifyTestPath . '/minified.css'); - - $expected = array( - 'success' => true - ,'statusCode' => 200 - ,'content' => $expectedContent - ,'headers' => array ( - 'Vary' => 'Accept-Encoding', - 'Last-Modified' => gmdate('D, d M Y H:i:s \G\M\T', $lastModified), - 'ETag' => "\"pub{$lastModified}\"", - 'Cache-Control' => 'max-age=0', - 'Content-Length' => countBytes($expectedContent), - 'Content-Type' => 'text/css; charset=utf-8', - ) - ); - - $env = new Minify_Env(array( - 'server' => $_SERVER, - )); - $sourceFactory = new Minify_Source_Factory($env, array(), new Minify_Cache_Null()); - $controller = new Minify_Controller_Files($env, $sourceFactory); - - $output = $minify->serve($controller, array( - 'files' => array( - $thisDir . '/_test_files/css/styles.css' - ,$thisDir . '/_test_files/css/comments.css' - ) - ,'quiet' => true - ,'lastModifiedTime' => $lastModified - ,'encodeOutput' => false - ,'maxAge' => false - )); - - $passed = assertTrue($expected === $output, 'Minify : CSS and Etag/Last-Modified'); - if ($thisFileActive) { - echo "\nOutput: " .var_export($output, 1). "\n\n"; - if (! $passed) { - echo "\n\n\n\n---Expected: " .var_export($expected, 1). "\n\n"; - } - } -} - -test_Minify(); diff --git a/min_unit_tests/test_all.php b/min_unit_tests/test_all.php deleted file mode 100644 index 017b092..0000000 --- a/min_unit_tests/test_all.php +++ /dev/null @@ -1,4 +0,0 @@ - array( - 'method' => "GET", - 'timeout' => '10', - 'header' => "Accept-Encoding: deflate, gzip\r\n", - ) - ))); - $meta = stream_get_meta_data($fp); - $encoding = ''; - $length = 0; - foreach ($meta['wrapper_data'] as $i => $header) { - if (preg_match('@^Content-Length:\\s*(\\d+)$@i', $header, $m)) { - $length = $m[1]; - } elseif (preg_match('@^Content-Encoding:\\s*(\\S+)$@i', $header, $m)) { - if ($m[1] !== 'identity') { - $encoding = $m[1]; - } - } - } - $streamContents = stream_get_contents($fp); - fclose($fp); - - if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) { - if ($length != 6) { - echo "\nReturned content should be 6 bytes and not HTTP encoded.\n" - . "Headers returned by: {$url}\n\n"; - var_export($meta['wrapper_data']); - echo "\n\n"; - } - } - - return array( - 'length' => $length - ,'encoding' => $encoding - ,'bytes' => $streamContents - ); -} - -test_environment(); diff --git a/server-info.php b/server-info.php index c9ddba6..618cf80 100644 --- a/server-info.php +++ b/server-info.php @@ -5,7 +5,7 @@ * * Change to true to expose this info. */ -$enabled = false; +$enabled = true; /////////////////////// @@ -13,6 +13,13 @@ if (!$enabled) { die('Set $enabled to true to see server info.'); } +function assertTrue($test, $message) { + if (!$test) { + echo "Warning: $message\n"; + } + return (bool)$test; +} + header('Content-Type: text/plain'); $file = __FILE__; @@ -22,4 +29,120 @@ SCRIPT_FILENAME : {$_SERVER['SCRIPT_FILENAME']} DOCUMENT_ROOT : {$_SERVER['DOCUMENT_ROOT']} SCRIPT_NAME : {$_SERVER['SCRIPT_NAME']} REQUEST_URI : {$_SERVER['REQUEST_URI']} + + EOD; + +$noSlash = assertTrue( + 0 === preg_match('@[\\\\/]$@', $_SERVER['DOCUMENT_ROOT']), + 'DOCUMENT_ROOT ends in trailing slash' +); + +$isRealPath = assertTrue( + false !== realpath($_SERVER['DOCUMENT_ROOT']), + 'DOCUMENT_ROOT fails realpath()' +); + +$containsThisFile = assertTrue( + 0 === strpos(realpath(__FILE__), realpath($_SERVER['DOCUMENT_ROOT'])), + 'DOCUMENT_ROOT contains this test file' +); + +if (! $noSlash || ! $isRealPath || ! $containsThisFile) { + echo "If you cannot modify DOCUMENT_ROOT, consider setting \$min_documentRoot in config.php\n"; +} + +assertTrue( + empty($_SERVER['SUBDOMAIN_DOCUMENT_ROOT']), + "\$_SERVER['SUBDOMAIN_DOCUMENT_ROOT'] is set. You may want to set \$min_documentRoot to this in config.php" +); + +assertTrue( + realpath(__FILE__) === realpath($_SERVER['DOCUMENT_ROOT'] . '/min/server-info.php'), + "/min/ is not directly inside DOCUMENT_ROOT." +); + +// TODO: rework this +//function _test_environment_getHello($url) +//{ +// $fp = fopen($url, 'r', false, stream_context_create(array( +// 'http' => array( +// 'method' => "GET", +// 'timeout' => '10', +// 'header' => "Accept-Encoding: deflate, gzip\r\n", +// ) +// ))); +// $meta = stream_get_meta_data($fp); +// $encoding = ''; +// $length = 0; +// foreach ($meta['wrapper_data'] as $i => $header) { +// if (preg_match('@^Content-Length:\\s*(\\d+)$@i', $header, $m)) { +// $length = $m[1]; +// } elseif (preg_match('@^Content-Encoding:\\s*(\\S+)$@i', $header, $m)) { +// if ($m[1] !== 'identity') { +// $encoding = $m[1]; +// } +// } +// } +// $streamContents = stream_get_contents($fp); +// fclose($fp); +// +// if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) { +// if ($length != 6) { +// echo "\nReturned content should be 6 bytes and not HTTP encoded.\n" +// . "Headers returned by: {$url}\n\n"; +// var_export($meta['wrapper_data']); +// echo "\n\n"; +// } +// } +// +// return array( +// 'length' => $length +// ,'encoding' => $encoding +// ,'bytes' => $streamContents +// ); +//} +// +//$thisUrl = 'http://' +// . $_SERVER['HTTP_HOST'] // avoid redirects when SERVER_NAME doesn't match +// . ('80' === $_SERVER['SERVER_PORT'] ? '' : ":{$_SERVER['SERVER_PORT']}") +// . dirname($_SERVER['REQUEST_URI']) +// . '/test_environment.php'; +// +//$oc = @file_get_contents($thisUrl . '?getOutputCompression=1'); +// +//if (false === $oc || ! preg_match('/^[01]$/', $oc)) { +// echo "!---: environment : Local HTTP request failed. Testing cannot continue.\n"; +// return; +//} +//if ('1' === $oc) { +// echo "!---: environment : zlib.output_compression is enabled in php.ini" +// . " or .htaccess.\n"; +//} +// +//$testJs = _test_environment_getHello($thisUrl . '?hello=js'); +//$passed = assertTrue( +// $testJs['length'] == 6 +// ,'environment : PHP/server should not auto-encode application/x-javascript output' +//); +// +//$testCss = _test_environment_getHello($thisUrl . '?hello=css'); +//$passed = $passed && assertTrue( +// $testCss['length'] == 6 +// ,'environment : PHP/server should not auto-encode text/css output' +// ); +// +//$testHtml = _test_environment_getHello($thisUrl . '?hello=html'); +//$passed = $passed && assertTrue( +// $testHtml['length'] == 6 +// ,'environment : PHP/server should not auto-encode text/html output' +// ); +// +//if (! $passed) { +// $testFake = _test_environment_getHello($thisUrl . '?hello=faketype'); +// if ($testFake['length'] == 6) { +// echo " environment : Server does not auto-encode arbitrary types. This\n" +// . " may indicate that the auto-encoding is caused by Apache's\n" +// . " AddOutputFilterByType."; +// } +//} diff --git a/tests/MinifyTest.php b/tests/MinifyTest.php new file mode 100644 index 0000000..89a37e0 --- /dev/null +++ b/tests/MinifyTest.php @@ -0,0 +1,202 @@ + $_SERVER, + )); + $sourceFactory = new Minify_Source_Factory($env, array(), new Minify_Cache_Null()); + $controller = new Minify_Controller_Files($env, $sourceFactory); + + $output = $minify->serve($controller, array( + 'files' => self::$test_files . '/css/styles.css', // controller casts to array + 'quiet' => true, + 'lastModifiedTime' => $lastModified, + 'encodeOutput' => false, + )); + + $expected = array( + 'success' => true, + 'statusCode' => 304, + 'content' => '', + 'headers' => array( + 'Expires' => gmdate('D, d M Y H:i:s \G\M\T', $_SERVER['REQUEST_TIME'] + 1800), + 'Vary' => 'Accept-Encoding', + 'Last-Modified' => gmdate('D, d M Y H:i:s \G\M\T', $lastModified), + 'ETag' => "\"pub{$lastModified}\"", + 'Cache-Control' => 'max-age=1800', + '_responseCode' => 'HTTP/1.0 304 Not Modified', + ), + ); + + $this->assertEquals($expected, $output, '304 response'); + + $this->markTestIncomplete('minifier classes aren\'t loaded for 304s'); +// $this->assertTrue(!class_exists('Minify_CSSmin', false), +// 'Minify : minifier classes aren\'t loaded for 304s'); + + // Test JS and Expires + + $content = preg_replace('/\\r\\n?/', "\n", file_get_contents($minifyTestPath . '/minified.js')); + $lastModified = max( + filemtime($minifyTestPath . '/email.js') + , filemtime($minifyTestPath . '/QueryString.js') + ); + $expected = array( + 'success' => true, + 'statusCode' => 200, + // JSMin always converts to \n line endings + 'content' => $content, + 'headers' => array( + 'Expires' => gmdate('D, d M Y H:i:s \G\M\T', $tomorrow), + 'Vary' => 'Accept-Encoding', + 'Last-Modified' => gmdate('D, d M Y H:i:s \G\M\T', $lastModified), + 'ETag' => "\"pub{$lastModified}\"", + 'Cache-Control' => 'max-age=86400', + 'Content-Length' => $this->countBytes($content), + 'Content-Type' => 'application/x-javascript; charset=utf-8', + ) + ); + + unset($_SERVER['HTTP_IF_NONE_MATCH']); + unset($_SERVER['HTTP_IF_MODIFIED_SINCE']); + + $env = new Minify_Env(array( + 'server' => $_SERVER, + )); + $sourceFactory = new Minify_Source_Factory($env, array(), new Minify_Cache_Null()); + $controller = new Minify_Controller_Files($env, $sourceFactory); + $output = $minify->serve($controller, array( + 'files' => array( + $minifyTestPath . '/email.js', + $minifyTestPath . '/QueryString.js', + ), + 'quiet' => true, + 'maxAge' => 86400, + 'encodeOutput' => false, + )); + + $this->assertEquals($expected, $output, 'JS and Expires'); + + // test for Issue 73 + $expected = ";function h(){}"; + $output = $minify->serve($controller, array( + 'files' => array( + $minifyTestPath . '/issue73_1.js', + $minifyTestPath . '/issue73_2.js', + ), + 'quiet' => true, + 'encodeOutput' => false, + )); + $output = $output['content']; + + $this->assertEquals($expected, $output, 'Issue 73'); + + // test for Issue 89 + $expected = file_get_contents($minifyTestPath . '/issue89_out.min.css'); + $output = $minify->serve($controller, array( + 'files' => array( + $minifyTestPath . '/issue89_1.css', + $minifyTestPath . '/issue89_2.css', + ), + 'quiet' => true, + 'encodeOutput' => false, + 'bubbleCssImports' => true, + )); + $output = $output['content']; + + $this->assertEquals($expected, $output, 'Issue 89 : bubbleCssImports'); + + $output = $minify->serve($controller, array( + 'files' => array( + $minifyTestPath . '/issue89_1.css', + $minifyTestPath . '/issue89_2.css', + ), + 'quiet' => true, + 'encodeOutput' => false, + )); + $output = $output['content']; + + $defaultOptions = $minify->getDefaultOptions(); + + $this->assertEquals(0, strpos($output, $defaultOptions['importWarning']), 'Issue 89 : detect invalid imports'); + + $output = $minify->serve($controller, array( + 'files' => array( + $minifyTestPath . '/issue89_1.css', + ), + 'quiet' => true, + 'encodeOutput' => false, + )); + $output = $output['content']; + + $this->assertFalse(strpos($output, $defaultOptions['importWarning']), 'Issue 89 : don\'t warn about valid imports'); + + // Test Issue 132 + if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) { + $output = $minify->serve($controller, array( + 'files' => array(__DIR__ . '/_test_files/js/issue132.js'), + 'quiet' => true, + 'encodeOutput' => false, + )); + + $this->assertEquals(77, $output['headers']['Content-Length'], 'Issue 132 : mbstring.func_overload shouldn\'t cause incorrect Content-Length'); + } + + // Test minifying CSS and responding with Etag/Last-Modified + + // don't allow conditional headers + unset($_SERVER['HTTP_IF_NONE_MATCH'], $_SERVER['HTTP_IF_MODIFIED_SINCE']); + + $expectedContent = file_get_contents($minifyTestPath . '/minified.css'); + + $expected = array( + 'success' => true, + 'statusCode' => 200, + 'content' => $expectedContent, + 'headers' => array( + 'Vary' => 'Accept-Encoding', + 'Last-Modified' => gmdate('D, d M Y H:i:s \G\M\T', $lastModified), + 'ETag' => "\"pub{$lastModified}\"", + 'Cache-Control' => 'max-age=0', + 'Content-Length' => $this->countBytes($expectedContent), + 'Content-Type' => 'text/css; charset=utf-8', + ) + ); + + $env = new Minify_Env(array( + 'server' => $_SERVER, + )); + $sourceFactory = new Minify_Source_Factory($env, array(), new Minify_Cache_Null()); + $controller = new Minify_Controller_Files($env, $sourceFactory); + + $output = $minify->serve($controller, array( + 'files' => array( + self::$test_files . '/css/styles.css', + self::$test_files . '/css/comments.css', + ), + 'quiet' => true, + 'lastModifiedTime' => $lastModified, + 'encodeOutput' => false, + 'maxAge' => false, + )); + + $this->assertEquals($expected, $output, 'CSS and Etag/Last-Modified'); + } +}