| <?php |
| /** |
| * File containing the ezcWebdavClientTestGenerator class. |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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. |
| * |
| * @package Webdav |
| * @subpackage Tests |
| * @version //autogen// |
| * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved. |
| * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 |
| */ |
| |
| /** |
| * The base directory for all following. |
| */ |
| define( 'PWD', dirname( $_SERVER['SCRIPT_FILENAME'] ) ); |
| /** |
| * Where captured data is stored. |
| */ |
| define( 'LOG_DIR', PWD . '/log' ); |
| /** |
| * Where temporary data (backend and running test number) are stored. |
| */ |
| define( 'TMP_DIR', PWD . '/tmp' ); |
| |
| require_once 'Webdav/tests/classes/test_auth.php'; |
| require_once 'Webdav/tests/classes/test_auth_ie.php'; |
| |
| /** |
| * Generator class for client test suites. |
| * |
| * An instance of this class can be used to generate a client test suite and |
| * for general testing and debugging of WebDAV clients. |
| * |
| * To run the generator copy and adjust the following code to your needs and |
| * store it as index.php in a web-enabled directory: |
| * <code> |
| * require_once 'Base/src/base.php'; |
| * |
| * function __autoload( $className ) |
| * { |
| * ezcBase::autoload( $className ); |
| * } |
| * |
| * require_once 'Webdav/tests/scripts/test_generator.php'; |
| * |
| * // Depends on mod_rewrite! Needed! |
| * $generator = new ezcWebdavClientTestGenerator( '/my/webdav/root' ); |
| * $generator->run(); |
| * $generator->store(); |
| * </code> |
| * |
| * The generator will automaticall instaniate a server for you and mock all |
| * transports contained in that server so that the request and response data is |
| * captured. If you need to add custom transport configurations, do so right |
| * before you instanciate the generator. |
| * |
| * The generator will store the collected data in a directory structure |
| * suitable for a client test suite, although it might also be used for |
| * debugging purposes. You need to have directories named log/ and tmp/ in |
| * place in your webdav root, which must be writeable by the webserver. |
| * |
| * The tmp/ dir will be used by the generator to store information between |
| * requests, like the state of the backend and the running test number. If you |
| * want to cancel the current test run, you should delete the contents of tmp/ |
| * and log/. After that, you will test with fresh data. |
| * |
| * The log/ directory stores the captured information. It contains the client |
| * test typical request/ and response/ directories for each request a client |
| * performed to the generator. Optionally, a file error.php will be generated, |
| * if any exceptions occur during the request. This file is not significant for |
| * client test cases and only meant for debugging purposes. Each request will |
| * be stored in a new test case directory, starting with a running number. |
| * |
| * To create a client test suite to be integrated into the eZ Components test |
| * suite, please consult the {@link Webdav/docs/client_tests.txt} document and |
| * follow the steps described there. |
| * |
| * @package Webdav |
| * @subpackage Tests |
| * @version //autogen// |
| */ |
| class ezcWebdavClientTestGenerator |
| { |
| |
| /** |
| * Directory to store captured data in. |
| * |
| * @var string |
| */ |
| protected $logFileBase; |
| |
| /** |
| * Backend used. |
| * |
| * @var ezcWebdavBackend |
| */ |
| protected $backend; |
| |
| /** |
| * File to restore/store the backend. |
| * |
| * @var string |
| */ |
| protected $backendFile; |
| |
| /** |
| * Server with mocked transports. |
| * |
| * @var ezcWebdavServer |
| */ |
| protected $server; |
| |
| /** |
| * Carries an array of exceptions of such occur. |
| * |
| * @var array(Exception) |
| */ |
| protected $exceptions = array(); |
| |
| /** |
| * PCREs that indicate $_SERVER keys to keep. |
| * |
| * @var array |
| */ |
| protected $serverWhiteList = array( |
| '(^CONTENT_.*$)', |
| '(^DOCUMENT_.*$)', |
| '(^GATEWAY_.*$)', |
| '(^HTTP_.*)', |
| '(^LANG$)', |
| '(^PATH_.*$)', |
| '(^PHP_SELF$)', |
| '(^PHP_AUTH.*$)', |
| '(^QUERY_.*$)', |
| '(^REDIRECT_.*$)', |
| '(^REMOTE_.*$)', |
| '(^REQUEST_.*$)', |
| '(^SCRIPT_.*$)', |
| '(^SERVER_.*$)', |
| ); |
| |
| protected $serverOverwrite = array( |
| 'REQUEST_TIME' => 1220431173, |
| 'REMOTE_HOST' => '127.0.0.1', |
| 'REMOTE_PORT' => '33458', |
| ); |
| |
| /** |
| * Number of digits for the test case number. |
| * |
| * @var mixed |
| */ |
| protected $testCaseNoDigits; |
| |
| /** |
| * Template to mock transport classes. |
| * |
| * @var string |
| */ |
| protected $mockClassSource = ' |
| class %s extends %s |
| { |
| /** |
| * Retreives the body from a global variable. |
| * |
| * @return void |
| */ |
| protected function retrieveBody() |
| { |
| $GLOBALS["EZC_WEBDAV_REQUEST_BODY"] = parent::retrieveBody(); |
| return $GLOBALS["EZC_WEBDAV_REQUEST_BODY"]; |
| } |
| |
| /** |
| * Captures the response data in global variables. |
| * |
| * @param ezcWebdavOutputResult $output |
| * @return void |
| */ |
| protected function sendResponse( ezcWebdavOutputResult $output ) |
| { |
| $GLOBALS["EZC_WEBDAV_RESPONSE_STATUS"] = $output->status; |
| $GLOBALS["EZC_WEBDAV_RESPONSE_HEADERS"] = $output->headers; |
| $GLOBALS["EZC_WEBDAV_RESPONSE_BODY"] = $output->body; |
| parent::sendResponse( $output ); |
| } |
| } |
| '; |
| |
| /** |
| * If a copy of the backend should be stored after each request. |
| * |
| * For debugging purposes. |
| * |
| * @var bool |
| */ |
| protected $storeBackends; |
| |
| /** |
| * Server base URI. |
| * |
| * @var string |
| */ |
| protected $baseUri; |
| |
| /** |
| * Current test number. |
| * |
| * @var int |
| */ |
| public $testNo; |
| |
| /** |
| * Creates a new test generator. |
| * |
| * This method checks if a backend has been stored from a previous request, |
| * restores this one or retrieves the default on. It then initializes a |
| * server using {@link initServer()} and retrieves and stores the current |
| * and next test number to set the {$logFileBase}. |
| * |
| * @param string $baseUri Base URI, if server is not in doc root. |
| * @return void |
| */ |
| public function __construct( $baseUri = '', $storeBackends = false, $ie = false, $testCaseNoDigits = 3, $lockPlugin = false ) |
| { |
| $this->storeBackends = $storeBackends; |
| $this->testCaseNoDigits = $testCaseNoDigits; |
| $this->baseUri = $baseUri; |
| |
| $this->filterServerVars(); |
| |
| // Basic path factory, use mod_rewrite! |
| try |
| { |
| $this->initBackend(); |
| $this->initServer( $ie, $lockPlugin ); |
| } |
| catch ( Exception $e ) |
| { |
| $this->exceptions[] = $e; |
| } |
| |
| $this->determineTestNo(); |
| $this->initializeLogDir(); |
| } |
| |
| /** |
| * Escape special request methods (Litmus). |
| * |
| * @param string $requestMethod |
| * @return string |
| */ |
| protected function escapeRequestMethod( $requestMethod ) |
| { |
| return strtr( |
| $requestMethod, |
| array( |
| ' ' => '_', |
| ':' => '_', |
| '(' => '', |
| ')' => '', |
| ) |
| ); |
| } |
| |
| protected function initializeLogDir() |
| { |
| // The captured data will be stored here. |
| $this->logFileBase = sprintf( "%s/%0{$this->testCaseNoDigits}s_%s", |
| LOG_DIR, |
| $this->testNo, |
| $this->escapeRequestMethod( $_SERVER['REQUEST_METHOD'] ) |
| ); |
| } |
| |
| protected function determineTestNo() |
| { |
| $testNoFile = $testNoFile = TMP_DIR . '/testno.txt'; |
| |
| // Get current test number and store it for next request |
| $this->testNo = ( file_exists( $testNoFile ) |
| ? (int) file_get_contents( $testNoFile ) |
| : 1 |
| ); |
| |
| file_put_contents( $testNoFile, ++$this->testNo ); |
| } |
| |
| /** |
| * Runs the server. |
| * |
| * @return void |
| */ |
| public function run() |
| { |
| $GLOBALS['EZC_WEBDAV_ERROR'] = array(); |
| set_error_handler( array( $this, 'handleErrors' ) ); |
| |
| try |
| { |
| $this->server->handle( $this->backend ); |
| } |
| catch ( Exception $e ) |
| { |
| $this->exceptions[] = $e; |
| } |
| |
| restore_error_handler(); |
| } |
| |
| public function handleErrors( $errNo, $errStr, $errFile, $errLine, $errContext ) |
| { |
| ob_start(); |
| debug_print_backtrace(); |
| $backtrace = ob_get_clean(); |
| |
| $GLOBALS['EZC_WEBDAV_ERROR'][] = array( |
| 'no' => $errNo, |
| 'string' => $errStr, |
| 'file' => $errFile, |
| 'line' => $errLine, |
| 'context' => $errContext, |
| 'backtrace' => $backtrace, |
| ); |
| } |
| |
| /** |
| * Stores captured data. |
| * |
| * Stores all captured data to the $logFileBase. |
| * |
| * @return void |
| */ |
| public function store() |
| { |
| $requestLogFileBase = "{$this->logFileBase}_request"; |
| $responseLogFileBase = "{$this->logFileBase}_response"; |
| |
| if ( count( $this->exceptions ) > 0 ) |
| { |
| file_put_contents( |
| "{$this->logFileBase}_exception.php", |
| "<?php\n\nreturn " . var_export( $this->exceptions, true ) . ";\n\n?>" |
| ); |
| } |
| if ( count( $GLOBALS['EZC_WEBDAV_ERROR'] ) ) |
| { |
| file_put_contents( |
| "{$this->logFileBase}_error.php", |
| "<?php\n\nreturn " . var_export( $GLOBALS['EZC_WEBDAV_ERROR'], true ) . ";\n\n?>" |
| ); |
| } |
| |
| file_put_contents( |
| "{$requestLogFileBase}_server.php", |
| "<?php\n\nreturn " . var_export( $_SERVER, true ) . ";\n\n?>" |
| ); |
| file_put_contents( |
| "{$requestLogFileBase}_body.xml", |
| $GLOBALS['EZC_WEBDAV_REQUEST_BODY'] |
| ); |
| |
| file_put_contents( |
| "{$responseLogFileBase}_headers.php", |
| "<?php\n\nreturn " . var_export( $GLOBALS['EZC_WEBDAV_RESPONSE_HEADERS'], true ) . ";\n\n?>" |
| ); |
| file_put_contents( |
| "{$responseLogFileBase}_body.xml", |
| $GLOBALS['EZC_WEBDAV_RESPONSE_BODY'] |
| ); |
| file_put_contents( |
| "{$responseLogFileBase}_status.txt", |
| $GLOBALS['EZC_WEBDAV_RESPONSE_STATUS'] |
| ); |
| |
| $serBackend = serialize( $this->backend ); |
| file_put_contents( $this->backendFile, $serBackend ); |
| if ( $this->storeBackends ) |
| { |
| file_put_contents( |
| "{$this->logFileBase}_backend.ser", |
| $serBackend |
| ); |
| } |
| |
| $serTokens = serialize( $this->server->auth->tokenAssignement ); |
| file_put_contents( $this->tokenFile, $serTokens ); |
| } |
| |
| /** |
| * Finish and cleanup. |
| * |
| * @return void |
| */ |
| public function finish() |
| { |
| // unlink( $this->lock ); |
| } |
| |
| /** |
| * Remove unwanted keys from $_SERVER. |
| * |
| * @return void |
| */ |
| protected function filterServerVars() |
| { |
| foreach ( $_SERVER as $key => $val ) |
| { |
| foreach ( $this->serverWhiteList as $regex ) |
| { |
| if ( preg_match( $regex, $key ) ) |
| { |
| continue 2; |
| } |
| } |
| // No regex matched |
| unset( $_SERVER[$key] ); |
| } |
| |
| // Adjust variables for better test case comparison |
| foreach ( $this->serverOverwrite as $key => $val ) |
| { |
| if ( isset( $_SERVER[$key] ) ) |
| { |
| $_SERVER[$key] = $val; |
| } |
| } |
| } |
| |
| /** |
| * Retrieves the initial backend. |
| * |
| * @return ezcWebdavBackend |
| */ |
| protected function getBackend() |
| { |
| try |
| { |
| return require_once dirname( __FILE__ ) . '/test_generator_backend.php'; |
| } |
| catch ( Exception $e ) |
| { |
| $this->exceptions[] = $e; |
| } |
| } |
| |
| /** |
| * Initialializes the WebDAV server used for capturing. |
| * |
| * Retrieves the global server singleton and replaces all configured |
| * transports with their corresponding mock. |
| * |
| * @param ezcWebdavPathFactory $pathFactory |
| * @return void |
| */ |
| protected function initServer( $ie, $lockPlugin ) |
| { |
| $pathFactory = new ezcWebdavBasicPathFactory( 'http://' . $_SERVER['HTTP_HOST'] . $this->baseUri ); |
| $this->server = ezcWebdavServer::getInstance(); |
| |
| foreach ( $this->server->configurations as $id => $transportCfg ) |
| { |
| // Prepare mock classes, if not done, yet |
| if ( !class_exists( ( $mockClass = ( $transportCfg->transportClass . 'Mock' ) ), false ) ) |
| { |
| eval( sprintf( $this->mockClassSource, $mockClass, $transportCfg->transportClass ) ); |
| } |
| |
| // Replace with mock config |
| $this->server->configurations[$id]->transportClass = $mockClass; |
| $this->server->configurations[$id]->pathFactory = $pathFactory; |
| } |
| |
| $this->server->auth = ( $ie ? new ezcWebdavTestAuthIe() : new ezcWebdavTestAuth() ); |
| |
| if ( $lockPlugin ) |
| { |
| $this->server->pluginRegistry->registerPlugin( |
| new ezcWebdavLockPluginConfiguration( |
| new ezcWebdavLockPluginOptions( |
| array( |
| 'backendLockTimeout' => 2000000, |
| ) |
| ) |
| ) |
| ); |
| } |
| |
| $this->server->auth->tokenAssignement = ( |
| file_exists( $this->tokenFile = TMP_DIR . '/tokens.ser' ) |
| ? unserialize( file_get_contents( $this->tokenFile ) ) |
| : array() |
| ); |
| } |
| |
| /** |
| * Initializes the back end. |
| * |
| * Reads a serialized back end or creates the default one, if no serialized |
| * version is found. |
| * |
| * @return void |
| */ |
| protected function initBackend() |
| { |
| // Restore backend from previous request or setup new |
| $this->backend = ( file_exists( ( $this->backendFile = TMP_DIR . '/backend.ser' ) ) |
| ? unserialize( file_get_contents( $this->backendFile ) ) |
| : $this->getBackend() |
| ); |
| $this->backend->options->lockFile = TMP_DIR . '/backend.lock'; |
| } |
| } |
| |
| ?> |