Implement #015359: access.php - new MatchOrder=host_uri
[tinyz:tinyz.git] / tests / tests / kernel / private / webdav / backend_content_regression_test.php
1 <?php
2 /**
3  * File containing the eZWebDAVBackendContentRegressionTest class.
4  *
5  * @copyright Copyright (C) 1999-2010 eZ Systems AS. All rights reserved.
6  * @license http://ez.no/licenses/gnu_gpl GNU GPLv2
7  * @package tests
8  */
9
10 require_once( 'wrappers.php' );
11
12 /**
13  * Main test class for WebDAV tests.
14  *
15  * Read doc/features/specifications/trunk/webdav/testing.txt for information
16  * about the WebDAV tests and what is needed to make them work on another
17  * machine.
18  *
19  * This class requires the extension eZSiteAccessHelper
20  * {@link http://svn.ez.no/svn/commercial/projects/qa/trunk/ezsiteaccesshelper/}.
21  *
22  * In the constructor:
23  * - ./siteaccess/site.ini.append.php.replace is copied over site.ini.append.php,
24  *   with certain values replaced dynamically (@ezc_siteaccess@ and
25  *   @ezc_webdav_database@)
26  * - the extension ezsiteaccesshelper is called to create the siteaccess with
27  *   the same name as this class (in lowercase), and it will copy the site.ini.append.php
28  *   file to the ezp/siteaccess/@ezc_siteaccess@ folder
29  * - the extension ezsiteaccesshelper is called to enable the created siteaccess
30  *   in ezp/siteaccess/override/site.ini.append.php
31  */
32 class eZWebDAVBackendContentRegressionTest extends ezpTestRegressionTest
33 {
34     /**
35      * Setting needed to keep the global variables working between the tests.
36      *
37      * @var bool
38      */
39     protected $backupGlobals = FALSE;
40
41     /**
42      * Fills $this->files with all the .request files found in the regression
43      * directory, recursively.
44      */
45     public function __construct()
46     {
47         $siteaccess = strtolower( __CLASS__ );
48
49         if ( ezcBaseFeatures::classExists( 'eZSiteAccessHelper', true ) )
50         {
51             require_once( 'siteaccesscreator.php' );
52
53             // - ./siteaccess/site.ini.append.php.replace is copied over site.ini.append.php,
54             //   with certain values replaced dynamically (@ezc_siteaccess@ and
55             //   @ezc_webdav_database@)
56             // - the extension ezsiteaccesshelper is called to create the siteaccess with
57             //   the same name as this class (in lowercase), and it will copy the site.ini.append.php
58             //   file to the ezp/siteaccess/@ezc_siteaccess@ folder
59             // - the extension ezsiteaccesshelper is called to enable the created siteaccess
60             //   in ezp/siteaccess/override/site.ini.append.php
61             $replace = array();
62             $replace['@ezc_siteaccess@'] = $siteaccess;
63             $replace['@ezc_webdav_database@'] = ezpTestRunner::dsn()->database;
64
65             $templateDir = dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'siteaccess';
66
67             try
68             {
69                 // replace @ezc_siteaccess@ and @ezc_webdav_database@ in site.ini.append.php
70                 // with respective values
71                 $contents = file_get_contents( $templateDir . DIRECTORY_SEPARATOR . 'site.ini.append.php.replace' );
72                 if ( count( $replace ) > 0 )
73                 {
74                     foreach ( $replace as $key => $replacement )
75                     {
76                         $contents = str_replace( $key, $replacement, $contents );
77                     }
78                 }
79
80                 file_put_contents( $templateDir . DIRECTORY_SEPARATOR . 'site.ini.append.php', $contents );
81
82                 ezpSiteAccessCreator::$docRoot = eZSys::rootDir() . DIRECTORY_SEPARATOR;
83                 ezpSiteAccessCreator::createSiteAccess( $siteaccess, $templateDir );
84             }
85             catch ( Exception $e )
86             {
87                 // eZSiteAccessHelper::createSiteAccess throws an exception
88                 // if the siteaccess exists already
89                 // var_dump( $e->getMessage() );
90             }
91         }
92         else
93         {
94             die ( "The WebDAV test suite requires the extension eZSiteAccessHelper in order to create a siteaccess.\n" );
95         }
96
97         $basePath = dirname( __FILE__ ) . '/regression';
98
99         $this->readDirRecursively( $basePath, $this->files, 'request' );
100
101         parent::__construct();
102     }
103
104     /**
105      * Called by PHPUnit before each test.
106      */
107     public function setUp()
108     {
109         // Call the setUp() in ezpDatabaseTestCase
110         parent::setUp();
111
112         // Set these to your own values
113         // @todo get these values automatically from somewhere (how to get the password?)
114         $GLOBALS['ezc_webdav_username'] = 'admin';
115         $GLOBALS['ezc_webdav_password'] = 'publish';
116         $GLOBALS['ezc_webdav_host'] = 'webdav.ezp';
117
118         // A compound value from the above
119         $GLOBALS['ezc_webdav_url'] = 'http://' . $GLOBALS['ezc_webdav_host'] . '/';
120
121         // Set some server variables (not all of them are needed)
122         $_SERVER['HTTP_USER_AGENT'] = 'cadaver/0.22.5 neon/0.26.3';
123         $_SERVER['SERVER_NAME'] = 'webdav';
124         $_SERVER['SERVER_PORT'] = '80';
125
126         // Set to null various variables used in the tests
127         $GLOBALS['ezc_response_body'] = null;
128         $GLOBALS['ezc_post_body'] = null;
129         $GLOBALS['ezc_webdav_testfolder'] = null;
130         $GLOBALS['ezc_webdav_testfolderobject'] = null;
131         $GLOBALS['ezc_webdav_testfolderid'] = null;
132
133         // Not sure if these 2 values are needed
134         $_SERVER['SCRIPT_FILENAME'] = eZSys::rootDir() . DIRECTORY_SEPARATOR . 'index.php';
135         $_SERVER['DOCUMENT_ROOT'] = eZSys::rootDir();
136
137         $GLOBALS['ezc_siteaccess'] = strtolower( __CLASS__ );
138
139         // Remove the siteaccess from settings/override/site.ini.append.php
140         // in case it already exists
141         try
142         {
143             ezpSiteAccessCreator::disableSiteAccess( $GLOBALS['ezc_siteaccess'] );
144         }
145         catch ( ezsahINIVariableNotSetException $e )
146         {
147             // eZSiteAccessHelper::disableSiteAccess throws an exception
148             // if the siteaccess does not exist already in
149             // settings/override/site.ini.append.php
150         }
151
152         // Add the siteaccess to settings/override/site.ini.append.php
153         ezpSiteAccessCreator::enableSiteAccess( $GLOBALS['ezc_siteaccess'] );
154     }
155
156     /**
157      * Called by PHPUnit after each test.
158      */
159     public function tearDown()
160     {
161         // Remove the siteaccess from settings/override/site.ini.append.php
162         // in case a test fails
163         try
164         {
165             ezpSiteAccessCreator::disableSiteAccess( $GLOBALS['ezc_siteaccess'] );
166         }
167         catch ( ezsahINIVariableNotSetException $e )
168         {
169             // eZSiteAccessHelper::disableSiteAccess throws an exception
170             // if the siteaccess does not exist already in
171             // settings/override/site.ini.append.php
172         }
173
174         // Remove the created folder if it exists
175         if ( $GLOBALS['ezc_webdav_testfolderobject'] !== null )
176         {
177             $GLOBALS['ezc_webdav_testfolderobject']->remove();
178             $GLOBALS['ezc_webdav_testfolderobject'] = null;
179         }
180         parent::tearDown();
181     }
182
183     /**
184      * Called by PHPUnit to create this test suite.
185      */
186     public static function suite()
187     {
188         // @todo Is this needed?
189         // PHPUnit_Util_Filter::addFileToWhitelist( '/home/as/dev/work/http/ezp/trunk/kernel/private/classes/webdav/ezwebdavcontentbackend.php' );
190
191         $ini = eZINI::instance( 'i18n.ini' );
192
193         list( $i18nSettings['internal-charset'], $i18nSettings['http-charset'], $i18nSettings['mbstring-extension'] ) =
194             $ini->variableMulti( 'CharacterSettings', array( 'Charset', 'HTTPCharset', 'MBStringExtension' ), array( false, false, 'enabled' ) );
195
196         //include_once( 'lib/ezi18n/classes/eztextcodec.php' );
197         eZTextCodec::updateSettings( $i18nSettings );
198
199         require_once 'kernel/common/i18n.php';
200
201         return new ezpTestRegressionSuite( __CLASS__ );
202     }
203
204     /**
205      * Clean the $text of dynamic stuff (creation date, etags, etc).
206      *
207      * Optionally append $body to $text, with "\n\n" between them.
208      *
209      * @param string $text
210      * @param string $body
211      * @return string
212      */
213     protected function cleanForCompare( $text, $body = null )
214     {
215         $result = $text;
216         $result = preg_replace( array( '/ETag: (\w+)/' ), array( 'ETag: XXX' ), $result );
217         $result = preg_replace( '@<D:creationdate>.*?</D:creationdate>@', '<D:creationdate>XXX</D:creationdate>', $result );
218         $result = preg_replace( '@<D:getlastmodified>.*?</D:getlastmodified>@', '<D:getlastmodified>XXX</D:getlastmodified>', $result );
219         $result = preg_replace( '@<D:getetag>.*?</D:getetag>@', '<D:getetag>XXX</D:getetag>', $result );
220         $result = preg_replace( '/@ezc_webdav_host@/', $GLOBALS['ezc_webdav_host'], $result );
221         $result = preg_replace( '/@ezc_siteaccess@/', $GLOBALS['ezc_siteaccess'], $result );
222         $result = preg_replace( '/@ezc_webdav_testfolder@/', $GLOBALS['ezc_webdav_testfolder'], $result );
223         if ( $body !== null )
224         {
225             $result = "{$result}\n\n{$body}";
226         }
227         return $result;
228     }
229
230     /**
231      * Skips the test $file if the directory name is uncommented in $skipTests
232      * inside the function.
233      *
234      * @param string $file
235      */
236     protected function skip( $file )
237     {
238         // uncomment the tests that you want to skip
239         $skipTests = array(
240                 // 'COPY',
241                 // 'DELETE',
242                 // 'GET',
243                 // 'HEAD',
244                 // 'MKCOL',
245                 // 'MOVE',
246                 // 'OPTIONS',
247                 // 'PROPFIND',
248                 // 'PROPPATCH',
249                 // 'PUT',
250             );
251
252         foreach ( $skipTests as $test )
253         {
254             if ( strpos( $file, $test ) !== false )
255             {
256                 $this->markTestSkipped( "Test environment is configured to skip {$test} tests." );
257                 break;
258             }
259         }
260     }
261
262     /**
263      * Runs the $file (.request file from $this->files) as a PHPUnit test.
264      *
265      * Steps performed:
266      *  - setUp() is called automatically before this function
267      *  - skip the test $file if declared. See {@link skip()}
268      *  - identify test files attached to the .request file $file (.expected, .body)
269      *  - initialize various global variables (together with $GLOBALS from setUp())
270      *  - create an eZ Publish folder with the name $file
271      *  - include $file (the .request file) as PHP code. $GLOBALS and $_SERVER values set in there
272      *    will be used further on
273      *  - initialize the WebDAV system like in webdav.php (it does NOT go through webdav.php)
274      *  - create an eZWebDAVContentBackend object and use ezcWebdavServer to handle the
275      *    WebDAV request specified in the .request file $file (through $_SERVER variables
276      *    'REQUEST_METHOD' and 'REQUEST_URI' and others.
277      *  - the output from the WebDAV system is collected in $GLOBALS['ezc_response_body']
278      *    (through hacks in wrappers.php).
279      *  - append the .body file contents to the $GLOBALS['ezc_response_body'] if it exists
280      *  - clean the response and the .expected file with cleanForCompare() (eg. creation date, etags etc)
281      *  - compare the response and the .expected file with assertEquals(). Same contents means the test passed.
282      *  - tearDown() is called automatically after this function
283      *
284      * See doc/specifications/trunk/webdav/testing.txt for detailed information
285      * about each $GLOBALS and $_SERVER variables.
286      *
287      * @param string $file
288      */
289     public function testRunRegression( $file )
290     {
291         // 'ezc' = use eZWebDAVContentBackend (new eZ Publish WebDAV based on ezcWebdav)
292         // 'ezp' = use eZWebDAVContentServer  (old eZ Publish WebDAV)
293         // Only 'ezc' is supported for now
294         $system = 'ezc';
295
296         // uncomment the tests that you want to skip in the skip() function
297         $this->skip( $file );
298
299         $error = '';
300         $response = null;
301
302         $outFile = $this->outFileName( $file, '.request', '.expected' );
303         $bodyFile = $this->outFileName( $file, '.request', '.body' );
304
305         $parts = pathinfo( $file );
306         $GLOBALS['ezc_webdav_testfolder'] = $parts['filename'];
307
308         // Create an eZ Publish folder for each test with the name of the test
309         // $GLOBALS['ezc_webdav_testfolderid'] can be used in the .request file
310         // to create file, image, folder etc under the test folder.
311         $folder = new ezpObject( "folder", 2 );
312         $folder->name = $GLOBALS['ezc_webdav_testfolder'];
313         $folder->publish();
314         $GLOBALS['ezc_webdav_testfolderobject'] = $folder;
315         $GLOBALS['ezc_webdav_testfolderid'] = $folder->mainNode->node_id;
316
317         // var_dump( $GLOBALS['ezc_webdav_testfolder'] . ' (' . $GLOBALS['ezc_webdav_testfolderid'] . ')' );
318
319         eZExtension::activateExtensions( 'default' );
320
321         eZModule::setGlobalPathList( array( "kernel" ) );
322
323         eZUser::logoutCurrent();
324
325         eZSys::init( 'webdav.php' );
326
327         // include the .request file. $GLOBALS and $_SERVER defined in the file
328         // will be used in the test
329         include $file;
330
331         // var_dump( '--- After include' );
332         // These values can be overwritten in the included $file which contains the WebDAV request
333         $username = $GLOBALS['ezc_webdav_username'];
334         $password = $GLOBALS['ezc_webdav_password'];
335
336         // Set the HTTP_AUTHORIZATION header
337         $_SERVER['HTTP_AUTHORIZATION'] = 'Basic ' . base64_encode( "{$username}:{$password}" );
338         // var_dump( 'Default REQUEST_URI: ' . $_SERVER['REQUEST_URI'] );
339
340         // var_dump( 'Cleaned REQUEST_URI: ' . $_SERVER['REQUEST_URI'] );
341         if ( $system === 'ezc' )
342         {
343             // Use eZ Components
344             // clean the REQUEST_URI and HTTP_DESTINATION
345             $_SERVER['REQUEST_URI'] = urldecode( $_SERVER['REQUEST_URI'] );
346             if ( isset( $_SERVER['HTTP_DESTINATION'] ) )
347             {
348                 $_SERVER['HTTP_DESTINATION'] = urldecode( $_SERVER['HTTP_DESTINATION'] );
349             }
350
351             $server = ezcWebdavServer::getInstance();
352
353             $backend = new eZWebDAVContentBackend();
354             $server->configurations = new ezcWebdavServerConfigurationManagerWrapper();
355
356             $server->init( new ezcWebdavBasicPathFactory( $GLOBALS['ezc_webdav_url'] ),
357                            new ezcWebdavXmlTool(),
358                            new ezcWebdavPropertyHandler(),
359                            new ezcWebdavHeaderHandler(),
360                            new ezcWebdavTransportWrapper() );
361
362             $server->auth = new eZWebDAVContentBackendAuth();
363         }
364         else
365         {
366             // Use the previous WebDAV system in eZ Publish
367             $backend = new eZWebDAVContentServerWrapper();
368         }
369
370         $currentSite = $backend->currentSiteFromPath( $_SERVER['REQUEST_URI'] );
371         if ( $currentSite )
372         {
373             $backend->setCurrentSite( $currentSite );
374         }
375
376         if ( $system === 'ezc' )
377         {
378             $server->handle( $backend );
379         }
380         else
381         {
382             $backend->processClientRequest();
383         }
384
385         // This value comes from the included $file which contains the WebDAV request
386         $response = trim( $GLOBALS['ezc_response_body'] );
387
388         $expected = trim( file_get_contents( $outFile ) );
389
390         $body = null;
391         if ( file_exists( $bodyFile ) )
392         {
393             $body = trim( file_get_contents( $bodyFile ) );
394         }
395
396         // replace dynamic text (eg. ETag) with static text
397         // $body = optional body content (eg. for binary files) to be appended to $expected
398         $expected = $this->cleanForCompare( $expected, $body );
399         $response = $this->cleanForCompare( $response );
400
401         $this->assertEquals( $expected, $response, "The expected response " . basename( $outFile ) . " (" . strlen( $expected ) . ") is not the same as the response got from request " . basename( $file ) . " (" . strlen( $response ) . "). {$error}" );
402     }
403 }
404 ?>