3
* $RCSfile: FileSystemTest.class,v $
5
* Gallery - a web based photo album viewer and editor
6
* Copyright (C) 2000-2005 Bharat Mediratta
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or (at
11
* your option) any later version.
13
* This program is distributed in the hope that it will be useful, but
14
* WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
23
* @version $Revision: 1.16 $ $Date: 2005/08/23 03:49:33 $
24
* @package GalleryCore
26
* @author Bharat Mediratta <bharat@menalto.com>
30
* Test FileSystem functionality
32
* @package GalleryCore
36
class FileSystemTest extends GalleryTestCase {
38
function FileSystemTest($methodName) {
39
$this->GalleryTestCase($methodName);
48
$parentId = $this->_getRootId();
49
for ($i = 0; $i < $iterations; $i++) {
50
$gallery->guaranteeTimeLimit(5);
52
list ($ret, $this->_albums[$i]) = $this->_createRandomAlbum($parentId);
53
if ($ret->isError()) {
54
print $ret->getAsHtml();
55
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
58
$parentId = $this->_albums[$i]->getId();
61
/* delete the top album */
62
$this->_markForCleanup($this->_albums[0]);
65
function testFetchItemIdByPath() {
67
for ($i = 0; $i < sizeof($this->_albums); $i++) {
68
$path .= $this->_albums[$i]->getPathComponent() . '/';
70
list ($ret, $id) = GalleryCoreApi::fetchItemIdByPath($path);
71
if ($ret->isError()) {
72
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
75
$this->assertEquals($this->_albums[2]->getId(), $id);
78
function testFetchLogicalPath() {
79
list ($ret, $root) = GalleryCoreApi::loadEntitiesById($this->_getRootId());
80
if ($ret->isError()) {
81
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
84
list ($ret, $logicalPath) = $root->fetchLogicalPath();
85
if ($ret->isError()) {
86
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
89
$this->assertEquals('/', $logicalPath);
91
list ($ret, $logicalPath) = $this->_albums[1]->fetchLogicalPath();
92
if ($ret->isError()) {
93
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
96
$this->assertEquals(sprintf('/%s/%s/',
97
$this->_albums[0]->getPathComponent(),
98
$this->_albums[1]->getPathComponent()),
101
list ($ret, $item) = $this->_createRandomDataItem($this->_albums[1]->getId());
102
if ($ret->isError()) {
103
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
106
list ($ret, $logicalPath) = $item->fetchLogicalPath();
107
if ($ret->isError()) {
108
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
111
$this->assertEquals(sprintf('/%s/%s/%s',
112
$this->_albums[0]->getPathComponent(),
113
$this->_albums[1]->getPathComponent(),
114
$item->getPathComponent()),
118
function testFetchPath() {
120
$originalPlatform = $gallery->getPlatform();
121
$gallery->_platform = new FileSystemTestPlatform('/');
122
$originalAlbumsDir = $gallery->getConfig('data.gallery.albums');
123
$gallery->setConfig('data.gallery.albums', '');
125
list ($ret, $path) = $this->_albums[1]->fetchPath();
126
if ($ret->isError()) {
127
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
130
$this->assertEquals(sprintf('%s/%s/',
131
$this->_albums[0]->getPathComponent(),
132
$this->_albums[1]->getPathComponent()),
135
$gallery->_platform = new FileSystemTestPlatform('\\');
137
list ($ret, $path) = $this->_albums[1]->fetchPath();
138
if ($ret->isError()) {
139
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
142
$this->assertEquals(sprintf('%s\\%s\\',
143
$this->_albums[0]->getPathComponent(),
144
$this->_albums[1]->getPathComponent()),
147
$gallery->_platform = $originalPlatform;
148
$gallery->setConfig('data.gallery.albums', $originalAlbumsDir);
151
function testFetchChildIdByPathComponent() {
152
list ($ret, $id) = GalleryCoreApi::fetchChildIdByPathComponent(
153
$this->_albums[1]->getId(), $this->_albums[2]->getPathComponent());
155
$this->assertEquals($this->_albums[2]->getId(), $id);
159
* Verify that creating a second filesystem entity with the same path as
160
* an existing one throws a collision error.
162
function testCreateCollision() {
165
list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock($this->_albums[0]->getId());
166
if ($ret->isError()) {
167
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
170
for ($i = 0; $i < 3; $i++) {
171
$entity[$i] = new GalleryFileSystemEntity();
172
$ret = $entity[$i]->create($this->_albums[0]->getId(), 'valid_path.jpg');
173
if ($ret->isError()) {
174
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
177
$ret = $entity[$i]->save();
178
if ($ret->isError()) {
179
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
183
$this->assertEquals(sprintf('valid_path_%03d.jpg', $i),
184
$entity[$i]->getPathComponent());
188
$ret = GalleryCoreApi::releaseLocks($lockId);
189
if ($ret->isError()) {
190
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
194
function testMoveCollision() {
195
list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock(array($this->_albums[0]->getId(),
196
$this->_albums[1]->getId(),
197
$this->_albums[2]->getId()));
198
if ($ret->isError()) {
199
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
202
$ret = $this->_albums[1]->rename('foo');
203
if ($ret->isError()) {
204
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
206
$ret = $this->_albums[1]->save();
208
$ret = $this->_albums[1]->move($this->_albums[0]->getId());
209
if ($ret->isError()) {
210
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
213
$ret = $this->_albums[2]->rename('foo');
214
if ($ret->isError()) {
215
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
217
$ret = $this->_albums[2]->move($this->_albums[0]->getId());
218
if ($ret->isError()) {
219
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
222
$this->assertEquals('foo_001', $this->_albums[2]->getPathComponent());
224
$ret = GalleryCoreApi::releaseLocks($lockId);
225
if ($ret->isError()) {
226
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
231
* Test the platform->rename($old,$newpath) call of FileSystemEntity::move.
232
* The call should have legal platformspecific slashes.
234
* It tests not the functionality of FileSystemEntity::move, it only tests if
235
* FileSystemEntity::move uses valid paths (no incorrect slashes) in its call to the platform
236
* specific "rename($oldname, $newname)" function.
238
function testMoveRenameCall() {
240
/* Use a windows alike mock platfrom */
241
$originalPlatform = $gallery->getPlatform();
242
$gallery->_platform = new FileSystemTestPlatformForRename('\\');
243
/* Acquire the write locks */
244
list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock(array($this->_albums[0]->getId(),
245
$this->_albums[1]->getId(),
246
$this->_albums[2]->getId()));
247
if ($ret->isError()) {
248
$gallery->_platform = $originalPlatform;
249
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
251
/* Execute the move command, success expected*/
252
$ret = $this->_albums[2]->move($this->_albums[0]->getId());
253
if ($ret->isError()) {
254
$gallery->_platform = $originalPlatform;
255
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
257
/* Now change the mock platform to a unix alike system */
258
$gallery->_platform = new FileSystemTestPlatformForRename('/');
259
/* And move again album 1 (back, but all virtual move command), success expected */
260
$ret = $this->_albums[2]->move($this->_albums[1]->getId());
261
if ($ret->isError()) {
262
$gallery->_platform = $originalPlatform;
263
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
266
$gallery->_platform = $originalPlatform;
267
$ret = GalleryCoreApi::releaseLocks($lockId);
268
if ($ret->isError()) {
269
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
271
$gallery->_platform = $originalPlatform;
274
function testGetLegalPathComponent() {
275
/* Simple case, no collision */
277
GalleryCoreApi::getLegalPathComponent('testpath', $this->_albums[2]->getId());
278
if ($ret->isError()) {
279
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
281
$this->assertEquals('testpath', $path, 'no collision');
283
/* Collision with existing album: _001 gets added */
284
list ($ret, $path) = GalleryCoreApi::getLegalPathComponent(
285
$this->_albums[1]->getPathComponent(), $this->_albums[0]->getId());
286
if ($ret->isError()) {
287
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
289
$this->assertEquals($this->_albums[1]->getPathComponent() . '_001', $path,
292
/* Ignore self-collision */
293
list ($ret, $path) = GalleryCoreApi::getLegalPathComponent(
294
$this->_albums[1]->getPathComponent(), $this->_albums[0]->getId(),
295
$this->_albums[1]->getId());
296
if ($ret->isError()) {
297
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
299
$this->assertEquals($this->_albums[1]->getPathComponent(), $path, 'ignore self-collision');
301
/* Filename with some invalid path characters and .php extension */
302
list ($ret, $path) = GalleryCoreApi::getLegalPathComponent(
303
'my/test&file!.php', $this->_albums[1]->getId());
304
if ($ret->isError()) {
305
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
307
$this->assertEquals('my_test_file__php', $path, 'a few bad characters');
309
/* Filename of all extended characters, except extension: we rewrite with date-filename */
310
list ($ret, $path) = GalleryCoreApi::getLegalPathComponent(
311
"\xe6\xaa\x94\xe6\xa1\x88.jpg", $this->_albums[1]->getId());
312
if ($ret->isError()) {
313
return $this->failWithStatus($ret->wrap(__FILE__, __LINE__));
315
$this->assertEquals(strftime('%Y%m%d') . '.jpg', $path, 'extended characters');
322
* @package GalleryCore
323
* @subpackage PHPUnit
325
class FileSystemTestPlatform {
326
function FileSystemTestPlatform($separator) {
327
$this->_separator = $separator;
330
function getDirectorySeparator() {
331
return $this->_separator;
337
* Mock platform for the rename method
339
* Implements all methods used by FileSystemEntity::move()
341
* @package GalleryCore
342
* @subpackage PHPUnit
344
class FileSystemTestPlatformForRename extends GalleryPlatform {
345
function FileSystemTestPlatformForRename($separator) {
346
$this->_separator = $separator;
349
function getDirectorySeparator() {
350
return $this->_separator;
356
* Override rename method for the testMoveRenamePaths
357
* It won't rename the item actually, just check if the paths contain no invalid slashs
359
function rename($oldname, $newname) {
361
if ($gallery->getDebug()) {
362
$gallery->debug("rename($oldname, $newname)");
365
* Check if there are some platform specific slash problems in the paths
366
* The platform should be forced to have a '\' separator and thus, no '/'
367
* should be found in the paths.
370
* Strip off the g2data path part of the $oldname and $newname, because they are platform
371
* specific and correct anyway.
373
$oldname = substr($oldname,
374
strlen($gallery->getConfig('data.gallery.albums')));
375
$newname = substr($newname,
376
strlen($gallery->getConfig('data.gallery.albums')));
377
/* We had a case where FileSystemEntity::move produced a rename(a,b) path b, which had a
378
* separator too much and this additional seapartor wasn't even platform specific, but
379
* just '/'. The consequence: ->move() didn't work on windows xp.
380
* What we do here is: Force a windows xp separator '\' and check if no '/' separator is
381
* found in the paths. nested ifs are not necessary, but more readable.
382
* And we don't accept // or \\ in our paths. Most probably this won't be an issue, but
383
* it's good to create exactly the paths that we actually indend to create.
385
if ($this->_separator == '\\') {
386
if (strrchr($oldname, '/') || strrchr($newname, '/')
387
|| strpos($oldname, '\\\\') || strpos($newname, '\\\\')) {
390
} else if ($this->_separator == '/') {
391
if (strrchr($oldname, '\\') || strrchr($newname, '\\')
392
|| strpos($oldname, '//') || strpos($newname, '//')) {
397
/* Now pretend the rename command was successful */