diff options
Diffstat (limited to 'tests/lib/Files/Cache')
-rw-r--r-- | tests/lib/Files/Cache/CacheTest.php | 678 | ||||
-rw-r--r-- | tests/lib/Files/Cache/HomeCacheTest.php | 139 | ||||
-rw-r--r-- | tests/lib/Files/Cache/MoveFromCacheTraitTest.php | 31 | ||||
-rw-r--r-- | tests/lib/Files/Cache/ScannerTest.php | 319 | ||||
-rw-r--r-- | tests/lib/Files/Cache/UpdaterLegacyTest.php | 304 | ||||
-rw-r--r-- | tests/lib/Files/Cache/UpdaterTest.php | 308 | ||||
-rw-r--r-- | tests/lib/Files/Cache/WatcherTest.php | 196 | ||||
-rw-r--r-- | tests/lib/Files/Cache/Wrapper/CacheJailTest.php | 74 | ||||
-rw-r--r-- | tests/lib/Files/Cache/Wrapper/CachePermissionsMaskTest.php | 101 |
9 files changed, 2150 insertions, 0 deletions
diff --git a/tests/lib/Files/Cache/CacheTest.php b/tests/lib/Files/Cache/CacheTest.php new file mode 100644 index 00000000000..615bb32f62c --- /dev/null +++ b/tests/lib/Files/Cache/CacheTest.php @@ -0,0 +1,678 @@ +<?php +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Files\Cache; + + +class LongId extends \OC\Files\Storage\Temporary { + public function getId() { + return 'long:' . str_repeat('foo', 50) . parent::getId(); + } +} + +/** + * Class CacheTest + * + * @group DB + * + * @package Test\Files\Cache + */ +class CacheTest extends \Test\TestCase { + /** + * @var \OC\Files\Storage\Temporary $storage ; + */ + protected $storage; + /** + * @var \OC\Files\Storage\Temporary $storage2 ; + */ + protected $storage2; + + /** + * @var \OC\Files\Cache\Cache $cache + */ + protected $cache; + /** + * @var \OC\Files\Cache\Cache $cache2 + */ + protected $cache2; + + public function testGetNumericId() { + $this->assertNotNull($this->cache->getNumericStorageId()); + } + + public function testSimple() { + $file1 = 'foo'; + $file2 = 'foo/bar'; + $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder'); + $data2 = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file'); + + $this->assertFalse($this->cache->inCache($file1)); + $this->assertEquals($this->cache->get($file1), null); + + $id1 = $this->cache->put($file1, $data1); + $this->assertTrue($this->cache->inCache($file1)); + $cacheData1 = $this->cache->get($file1); + foreach ($data1 as $key => $value) { + $this->assertEquals($value, $cacheData1[$key]); + } + $this->assertEquals($cacheData1['mimepart'], 'foo'); + $this->assertEquals($cacheData1['fileid'], $id1); + $this->assertEquals($id1, $this->cache->getId($file1)); + + $this->assertFalse($this->cache->inCache($file2)); + $id2 = $this->cache->put($file2, $data2); + $this->assertTrue($this->cache->inCache($file2)); + $cacheData2 = $this->cache->get($file2); + foreach ($data2 as $key => $value) { + $this->assertEquals($value, $cacheData2[$key]); + } + $this->assertEquals($cacheData1['fileid'], $cacheData2['parent']); + $this->assertEquals($cacheData2['fileid'], $id2); + $this->assertEquals($id2, $this->cache->getId($file2)); + $this->assertEquals($id1, $this->cache->getParentId($file2)); + + $newSize = 1050; + $newId2 = $this->cache->put($file2, array('size' => $newSize)); + $cacheData2 = $this->cache->get($file2); + $this->assertEquals($newId2, $id2); + $this->assertEquals($cacheData2['size'], $newSize); + $this->assertEquals($cacheData1, $this->cache->get($file1)); + + $this->cache->remove($file2); + $this->assertFalse($this->cache->inCache($file2)); + $this->assertEquals($this->cache->get($file2), null); + $this->assertTrue($this->cache->inCache($file1)); + + $this->assertEquals($cacheData1, $this->cache->get($id1)); + } + + public function testPartial() { + $file1 = 'foo'; + + $this->cache->put($file1, array('size' => 10)); + $this->assertEquals(array('size' => 10), $this->cache->get($file1)); + + $this->cache->put($file1, array('mtime' => 15)); + $this->assertEquals(array('size' => 10, 'mtime' => 15), $this->cache->get($file1)); + + $this->cache->put($file1, array('size' => 12)); + $this->assertEquals(array('size' => 12, 'mtime' => 15), $this->cache->get($file1)); + } + + /** + * @dataProvider folderDataProvider + */ + public function testFolder($folder) { + $file2 = $folder.'/bar'; + $file3 = $folder.'/foo'; + $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory'); + $fileData = array(); + $fileData['bar'] = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file'); + $fileData['foo'] = array('size' => 20, 'mtime' => 25, 'mimetype' => 'foo/file'); + + $this->cache->put($folder, $data1); + $this->cache->put($file2, $fileData['bar']); + $this->cache->put($file3, $fileData['foo']); + + $content = $this->cache->getFolderContents($folder); + $this->assertEquals(count($content), 2); + foreach ($content as $cachedData) { + $data = $fileData[$cachedData['name']]; + foreach ($data as $name => $value) { + $this->assertEquals($value, $cachedData[$name]); + } + } + + $file4 = $folder.'/unkownSize'; + $fileData['unkownSize'] = array('size' => -1, 'mtime' => 25, 'mimetype' => 'foo/file'); + $this->cache->put($file4, $fileData['unkownSize']); + + $this->assertEquals(-1, $this->cache->calculateFolderSize($folder)); + + $fileData['unkownSize'] = array('size' => 5, 'mtime' => 25, 'mimetype' => 'foo/file'); + $this->cache->put($file4, $fileData['unkownSize']); + + $this->assertEquals(1025, $this->cache->calculateFolderSize($folder)); + + $this->cache->remove($file2); + $this->cache->remove($file3); + $this->cache->remove($file4); + $this->assertEquals(0, $this->cache->calculateFolderSize($folder)); + + $this->cache->remove($folder); + $this->assertFalse($this->cache->inCache($folder.'/foo')); + $this->assertFalse($this->cache->inCache($folder.'/bar')); + } + + public function testRemoveRecursive() { + $folderData = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory'); + $fileData = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'text/plain'); + $folders = ['folder', 'folder/subfolder', 'folder/sub2', 'folder/sub2/sub3']; + $files = ['folder/foo.txt', 'folder/bar.txt', 'folder/subfolder/asd.txt', 'folder/sub2/qwerty.txt', 'folder/sub2/sub3/foo.txt']; + + foreach($folders as $folder){ + $this->cache->put($folder, $folderData); + } + foreach ($files as $file) { + $this->cache->put($file, $fileData); + } + + $this->cache->remove('folder'); + foreach ($files as $file) { + $this->assertFalse($this->cache->inCache($file)); + } + } + + public function folderDataProvider() { + + return array( + array('folder'), + // that was too easy, try something harder + array('☺, WHITE SMILING FACE, UTF-8 hex E298BA'), + // what about 4 byte utf-8 + array('😐, NEUTRAL_FACE, UTF-8 hex F09F9890'), + // now the crazy stuff + array(', UNASSIGNED PRIVATE USE, UTF-8 hex EF9890'), + // and my favorite + array('w͢͢͝h͡o͢͡ ̸͢k̵͟n̴͘ǫw̸̛s͘ ̀́w͘͢ḩ̵a҉̡͢t ̧̕h́o̵r͏̵rors̡ ̶͡͠lį̶e͟͟ ̶͝in͢ ͏t̕h̷̡͟e ͟͟d̛a͜r̕͡k̢̨ ͡h̴e͏a̷̢̡rt́͏ ̴̷͠ò̵̶f̸ u̧͘ní̛͜c͢͏o̷͏d̸͢e̡͝') + ); + } + + public function testEncryptedFolder() { + $file1 = 'folder'; + $file2 = 'folder/bar'; + $file3 = 'folder/foo'; + $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory'); + $fileData = array(); + $fileData['bar'] = array('size' => 1000, 'encrypted' => 1, 'mtime' => 20, 'mimetype' => 'foo/file'); + $fileData['foo'] = array('size' => 20, 'encrypted' => 1, 'mtime' => 25, 'mimetype' => 'foo/file'); + + $this->cache->put($file1, $data1); + $this->cache->put($file2, $fileData['bar']); + $this->cache->put($file3, $fileData['foo']); + + $content = $this->cache->getFolderContents($file1); + $this->assertEquals(count($content), 2); + foreach ($content as $cachedData) { + $data = $fileData[$cachedData['name']]; + } + + $file4 = 'folder/unkownSize'; + $fileData['unkownSize'] = array('size' => -1, 'mtime' => 25, 'mimetype' => 'foo/file'); + $this->cache->put($file4, $fileData['unkownSize']); + + $this->assertEquals(-1, $this->cache->calculateFolderSize($file1)); + + $fileData['unkownSize'] = array('size' => 5, 'mtime' => 25, 'mimetype' => 'foo/file'); + $this->cache->put($file4, $fileData['unkownSize']); + + $this->assertEquals(1025, $this->cache->calculateFolderSize($file1)); + // direct cache entry retrieval returns the original values + $entry = $this->cache->get($file1); + $this->assertEquals(1025, $entry['size']); + + $this->cache->remove($file2); + $this->cache->remove($file3); + $this->cache->remove($file4); + $this->assertEquals(0, $this->cache->calculateFolderSize($file1)); + + $this->cache->remove('folder'); + $this->assertFalse($this->cache->inCache('folder/foo')); + $this->assertFalse($this->cache->inCache('folder/bar')); + } + + public function testRootFolderSizeForNonHomeStorage() { + $dir1 = 'knownsize'; + $dir2 = 'unknownsize'; + $fileData = array(); + $fileData[''] = array('size' => -1, 'mtime' => 20, 'mimetype' => 'httpd/unix-directory'); + $fileData[$dir1] = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'httpd/unix-directory'); + $fileData[$dir2] = array('size' => -1, 'mtime' => 25, 'mimetype' => 'httpd/unix-directory'); + + $this->cache->put('', $fileData['']); + $this->cache->put($dir1, $fileData[$dir1]); + $this->cache->put($dir2, $fileData[$dir2]); + + $this->assertTrue($this->cache->inCache($dir1)); + $this->assertTrue($this->cache->inCache($dir2)); + + // check that root size ignored the unknown sizes + $this->assertEquals(-1, $this->cache->calculateFolderSize('')); + + // clean up + $this->cache->remove(''); + $this->cache->remove($dir1); + $this->cache->remove($dir2); + + $this->assertFalse($this->cache->inCache($dir1)); + $this->assertFalse($this->cache->inCache($dir2)); + } + + function testStatus() { + $this->assertEquals(\OC\Files\Cache\Cache::NOT_FOUND, $this->cache->getStatus('foo')); + $this->cache->put('foo', array('size' => -1)); + $this->assertEquals(\OC\Files\Cache\Cache::PARTIAL, $this->cache->getStatus('foo')); + $this->cache->put('foo', array('size' => -1, 'mtime' => 20, 'mimetype' => 'foo/file')); + $this->assertEquals(\OC\Files\Cache\Cache::SHALLOW, $this->cache->getStatus('foo')); + $this->cache->put('foo', array('size' => 10)); + $this->assertEquals(\OC\Files\Cache\Cache::COMPLETE, $this->cache->getStatus('foo')); + } + + public function putWithAllKindOfQuotesData() { + return [ + ['`backtick`'], + ['´forward´'], + ['\'single\''], + ]; + } + + /** + * @dataProvider putWithAllKindOfQuotesData + * @param $fileName + */ + public function testPutWithAllKindOfQuotes($fileName) { + + $this->assertEquals(\OC\Files\Cache\Cache::NOT_FOUND, $this->cache->get($fileName)); + $this->cache->put($fileName, array('size' => 20, 'mtime' => 25, 'mimetype' => 'foo/file', 'etag' => $fileName)); + + $cacheEntry = $this->cache->get($fileName); + $this->assertEquals($fileName, $cacheEntry['etag']); + $this->assertEquals($fileName, $cacheEntry['path']); + } + + function testSearch() { + $file1 = 'folder'; + $file2 = 'folder/foobar'; + $file3 = 'folder/foo'; + $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder'); + $fileData = array(); + $fileData['foobar'] = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file'); + $fileData['foo'] = array('size' => 20, 'mtime' => 25, 'mimetype' => 'foo/file'); + + $this->cache->put($file1, $data1); + $this->cache->put($file2, $fileData['foobar']); + $this->cache->put($file3, $fileData['foo']); + + $this->assertEquals(2, count($this->cache->search('%foo%'))); + $this->assertEquals(1, count($this->cache->search('foo'))); + $this->assertEquals(1, count($this->cache->search('%folder%'))); + $this->assertEquals(1, count($this->cache->search('folder%'))); + $this->assertEquals(3, count($this->cache->search('%'))); + + // case insensitive search should match the same files + $this->assertEquals(2, count($this->cache->search('%Foo%'))); + $this->assertEquals(1, count($this->cache->search('Foo'))); + $this->assertEquals(1, count($this->cache->search('%Folder%'))); + $this->assertEquals(1, count($this->cache->search('Folder%'))); + + $this->assertEquals(3, count($this->cache->searchByMime('foo'))); + $this->assertEquals(2, count($this->cache->searchByMime('foo/file'))); + } + + function testSearchByTag() { + $userId = $this->getUniqueId('user'); + \OC::$server->getUserManager()->createUser($userId, $userId); + $this->loginAsUser($userId); + $user = new \OC\User\User($userId, null); + + $file1 = 'folder'; + $file2 = 'folder/foobar'; + $file3 = 'folder/foo'; + $file4 = 'folder/foo2'; + $file5 = 'folder/foo3'; + $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder'); + $fileData = array(); + $fileData['foobar'] = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file'); + $fileData['foo'] = array('size' => 20, 'mtime' => 25, 'mimetype' => 'foo/file'); + $fileData['foo2'] = array('size' => 25, 'mtime' => 28, 'mimetype' => 'foo/file'); + $fileData['foo3'] = array('size' => 88, 'mtime' => 34, 'mimetype' => 'foo/file'); + + $id1 = $this->cache->put($file1, $data1); + $id2 = $this->cache->put($file2, $fileData['foobar']); + $id3 = $this->cache->put($file3, $fileData['foo']); + $id4 = $this->cache->put($file4, $fileData['foo2']); + $id5 = $this->cache->put($file5, $fileData['foo3']); + + $tagManager = \OC::$server->getTagManager()->load('files', null, null, $userId); + $this->assertTrue($tagManager->tagAs($id1, 'tag1')); + $this->assertTrue($tagManager->tagAs($id1, 'tag2')); + $this->assertTrue($tagManager->tagAs($id2, 'tag2')); + $this->assertTrue($tagManager->tagAs($id3, 'tag1')); + $this->assertTrue($tagManager->tagAs($id4, 'tag2')); + + // use tag name + $results = $this->cache->searchByTag('tag1', $userId); + + $this->assertEquals(2, count($results)); + + usort($results, function($value1, $value2) { return $value1['name'] >= $value2['name']; }); + + $this->assertEquals('folder', $results[0]['name']); + $this->assertEquals('foo', $results[1]['name']); + + // use tag id + $tags = $tagManager->getTagsForUser($userId); + $this->assertNotEmpty($tags); + $tags = array_filter($tags, function($tag) { return $tag->getName() === 'tag2'; }); + $results = $this->cache->searchByTag(current($tags)->getId(), $userId); + $this->assertEquals(3, count($results)); + + usort($results, function($value1, $value2) { return $value1['name'] >= $value2['name']; }); + + $this->assertEquals('folder', $results[0]['name']); + $this->assertEquals('foo2', $results[1]['name']); + $this->assertEquals('foobar', $results[2]['name']); + + $tagManager->delete('tag1'); + $tagManager->delete('tag2'); + + $this->logout(); + $user = \OC::$server->getUserManager()->get($userId); + if ($user !== null) { $user->delete(); } + } + + function testMove() { + $file1 = 'folder'; + $file2 = 'folder/bar'; + $file3 = 'folder/foo'; + $file4 = 'folder/foo/1'; + $file5 = 'folder/foo/2'; + $data = array('size' => 100, 'mtime' => 50, 'mimetype' => 'foo/bar'); + $folderData = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory'); + + $this->cache->put($file1, $folderData); + $this->cache->put($file2, $folderData); + $this->cache->put($file3, $folderData); + $this->cache->put($file4, $data); + $this->cache->put($file5, $data); + + /* simulate a second user with a different storage id but the same folder structure */ + $this->cache2->put($file1, $folderData); + $this->cache2->put($file2, $folderData); + $this->cache2->put($file3, $folderData); + $this->cache2->put($file4, $data); + $this->cache2->put($file5, $data); + + $this->cache->move('folder/foo', 'folder/foobar'); + + $this->assertFalse($this->cache->inCache('folder/foo')); + $this->assertFalse($this->cache->inCache('folder/foo/1')); + $this->assertFalse($this->cache->inCache('folder/foo/2')); + + $this->assertTrue($this->cache->inCache('folder/bar')); + $this->assertTrue($this->cache->inCache('folder/foobar')); + $this->assertTrue($this->cache->inCache('folder/foobar/1')); + $this->assertTrue($this->cache->inCache('folder/foobar/2')); + + /* the folder structure of the second user must not change! */ + $this->assertTrue($this->cache2->inCache('folder/bar')); + $this->assertTrue($this->cache2->inCache('folder/foo')); + $this->assertTrue($this->cache2->inCache('folder/foo/1')); + $this->assertTrue($this->cache2->inCache('folder/foo/2')); + + $this->assertFalse($this->cache2->inCache('folder/foobar')); + $this->assertFalse($this->cache2->inCache('folder/foobar/1')); + $this->assertFalse($this->cache2->inCache('folder/foobar/2')); + } + + function testGetIncomplete() { + $file1 = 'folder1'; + $file2 = 'folder2'; + $file3 = 'folder3'; + $file4 = 'folder4'; + $data = array('size' => 10, 'mtime' => 50, 'mimetype' => 'foo/bar'); + + $this->cache->put($file1, $data); + $data['size'] = -1; + $this->cache->put($file2, $data); + $this->cache->put($file3, $data); + $data['size'] = 12; + $this->cache->put($file4, $data); + + $this->assertEquals($file3, $this->cache->getIncomplete()); + } + + function testNonExisting() { + $this->assertFalse($this->cache->get('foo.txt')); + $this->assertEquals(array(), $this->cache->getFolderContents('foo')); + } + + function testGetById() { + $storageId = $this->storage->getId(); + $data = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file'); + $id = $this->cache->put('foo', $data); + + if (strlen($storageId) > 64) { + $storageId = md5($storageId); + } + $this->assertEquals(array($storageId, 'foo'), \OC\Files\Cache\Cache::getById($id)); + } + + function testStorageMTime() { + $data = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file'); + $this->cache->put('foo', $data); + $cachedData = $this->cache->get('foo'); + $this->assertEquals($data['mtime'], $cachedData['storage_mtime']); //if no storage_mtime is saved, mtime should be used + + $this->cache->put('foo', array('storage_mtime' => 30)); //when setting storage_mtime, mtime is also set + $cachedData = $this->cache->get('foo'); + $this->assertEquals(30, $cachedData['storage_mtime']); + $this->assertEquals(30, $cachedData['mtime']); + + $this->cache->put('foo', array('mtime' => 25)); //setting mtime does not change storage_mtime + $cachedData = $this->cache->get('foo'); + $this->assertEquals(30, $cachedData['storage_mtime']); + $this->assertEquals(25, $cachedData['mtime']); + } + + function testLongId() { + $storage = new LongId(array()); + $cache = $storage->getCache(); + $storageId = $storage->getId(); + $data = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file'); + $id = $cache->put('foo', $data); + $this->assertEquals(array(md5($storageId), 'foo'), \OC\Files\Cache\Cache::getById($id)); + } + + /** + * this test show the bug resulting if we have no normalizer installed + */ + public function testWithoutNormalizer() { + // folder name "Schön" with U+00F6 (normalized) + $folderWith00F6 = "\x53\x63\x68\xc3\xb6\x6e"; + + // folder name "Schön" with U+0308 (un-normalized) + $folderWith0308 = "\x53\x63\x68\x6f\xcc\x88\x6e"; + + /** + * @var \OC\Files\Cache\Cache | \PHPUnit_Framework_MockObject_MockObject $cacheMock + */ + $cacheMock = $this->getMock('\OC\Files\Cache\Cache', array('normalize'), array($this->storage), '', true); + + $cacheMock->expects($this->any()) + ->method('normalize') + ->will($this->returnArgument(0)); + + $data = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory'); + + // put root folder + $this->assertFalse($cacheMock->get('folder')); + $this->assertGreaterThan(0, $cacheMock->put('folder', $data)); + + // put un-normalized folder + $this->assertFalse($cacheMock->get('folder/' . $folderWith0308)); + $this->assertGreaterThan(0, $cacheMock->put('folder/' . $folderWith0308, $data)); + + // get un-normalized folder by name + $unNormalizedFolderName = $cacheMock->get('folder/' . $folderWith0308); + + // check if database layer normalized the folder name (this should not happen) + $this->assertEquals($folderWith0308, $unNormalizedFolderName['name']); + + // put normalized folder + $this->assertFalse($cacheMock->get('folder/' . $folderWith00F6)); + $this->assertGreaterThan(0, $cacheMock->put('folder/' . $folderWith00F6, $data)); + + // this is our bug, we have two different hashes with the same name (Schön) + $this->assertEquals(2, count($cacheMock->getFolderContents('folder'))); + } + + /** + * this test shows that there is no bug if we use the normalizer + */ + public function testWithNormalizer() { + + if (!class_exists('Patchwork\PHP\Shim\Normalizer')) { + $this->markTestSkipped('The 3rdparty Normalizer extension is not available.'); + return; + } + + // folder name "Schön" with U+00F6 (normalized) + $folderWith00F6 = "\x53\x63\x68\xc3\xb6\x6e"; + + // folder name "Schön" with U+0308 (un-normalized) + $folderWith0308 = "\x53\x63\x68\x6f\xcc\x88\x6e"; + + $data = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory'); + + // put root folder + $this->assertFalse($this->cache->get('folder')); + $this->assertGreaterThan(0, $this->cache->put('folder', $data)); + + // put un-normalized folder + $this->assertFalse($this->cache->get('folder/' . $folderWith0308)); + $this->assertGreaterThan(0, $this->cache->put('folder/' . $folderWith0308, $data)); + + // get un-normalized folder by name + $unNormalizedFolderName = $this->cache->get('folder/' . $folderWith0308); + + // check if folder name was normalized + $this->assertEquals($folderWith00F6, $unNormalizedFolderName['name']); + + // put normalized folder + $this->assertInstanceOf('\OCP\Files\Cache\ICacheEntry', $this->cache->get('folder/' . $folderWith00F6)); + $this->assertGreaterThan(0, $this->cache->put('folder/' . $folderWith00F6, $data)); + + // at this point we should have only one folder named "Schön" + $this->assertEquals(1, count($this->cache->getFolderContents('folder'))); + } + + function bogusPathNamesProvider() { + return array( + array('/bogus.txt', 'bogus.txt'), + array('//bogus.txt', 'bogus.txt'), + array('bogus/', 'bogus'), + array('bogus//', 'bogus'), + ); + } + + /** + * Test bogus paths with leading or doubled slashes + * + * @dataProvider bogusPathNamesProvider + */ + public function testBogusPaths($bogusPath, $fixedBogusPath) { + $data = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory'); + + // put root folder + $this->assertFalse($this->cache->get('')); + $parentId = $this->cache->put('', $data); + $this->assertGreaterThan(0, $parentId); + + $this->assertGreaterThan(0, $this->cache->put($bogusPath, $data)); + + $newData = $this->cache->get($fixedBogusPath); + $this->assertNotFalse($newData); + + $this->assertEquals($fixedBogusPath, $newData['path']); + // parent is the correct one, resolved properly (they used to not be) + $this->assertEquals($parentId, $newData['parent']); + + $newDataFromBogus = $this->cache->get($bogusPath); + // same entry + $this->assertEquals($newData, $newDataFromBogus); + } + + public function testNoReuseOfFileId() { + $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain'); + $this->cache->put('somefile.txt', $data1); + $info = $this->cache->get('somefile.txt'); + $fileId = $info['fileid']; + $this->cache->remove('somefile.txt'); + $data2 = array('size' => 200, 'mtime' => 100, 'mimetype' => 'text/plain'); + $this->cache->put('anotherfile.txt', $data2); + $info2 = $this->cache->get('anotherfile.txt'); + $fileId2 = $info2['fileid']; + $this->assertNotEquals($fileId, $fileId2); + } + + public function escapingProvider() { + return [ + ['foo'], + ['o%'], + ['oth_r'], + ]; + } + + /** + * @param string $name + * @dataProvider escapingProvider + */ + public function testEscaping($name) { + $data = array('size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain'); + $this->cache->put($name, $data); + $this->assertTrue($this->cache->inCache($name)); + $retrievedData = $this->cache->get($name); + foreach ($data as $key => $value) { + $this->assertEquals($value, $retrievedData[$key]); + } + $this->cache->move($name, $name . 'asd'); + $this->assertFalse($this->cache->inCache($name)); + $this->assertTrue($this->cache->inCache($name . 'asd')); + $this->cache->remove($name . 'asd'); + $this->assertFalse($this->cache->inCache($name . 'asd')); + $folderData = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory'); + $this->cache->put($name, $folderData); + $this->cache->put('other', $folderData); + $childs = ['asd', 'bar', 'foo', 'sub/folder']; + $this->cache->put($name . '/sub', $folderData); + $this->cache->put('other/sub', $folderData); + foreach ($childs as $child) { + $this->cache->put($name . '/' . $child, $data); + $this->cache->put('other/' . $child, $data); + $this->assertTrue($this->cache->inCache($name . '/' . $child)); + } + $this->cache->move($name, $name . 'asd'); + foreach ($childs as $child) { + $this->assertTrue($this->cache->inCache($name . 'asd/' . $child)); + $this->assertTrue($this->cache->inCache('other/' . $child)); + } + foreach ($childs as $child) { + $this->cache->remove($name . 'asd/' . $child); + $this->assertFalse($this->cache->inCache($name . 'asd/' . $child)); + $this->assertTrue($this->cache->inCache('other/' . $child)); + } + } + + protected function tearDown() { + if ($this->cache) { + $this->cache->clear(); + } + + parent::tearDown(); + } + + protected function setUp() { + parent::setUp(); + + $this->storage = new \OC\Files\Storage\Temporary(array()); + $this->storage2 = new \OC\Files\Storage\Temporary(array()); + $this->cache = new \OC\Files\Cache\Cache($this->storage); + $this->cache2 = new \OC\Files\Cache\Cache($this->storage2); + } +} diff --git a/tests/lib/Files/Cache/HomeCacheTest.php b/tests/lib/Files/Cache/HomeCacheTest.php new file mode 100644 index 00000000000..a144b8cabb8 --- /dev/null +++ b/tests/lib/Files/Cache/HomeCacheTest.php @@ -0,0 +1,139 @@ +<?php +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Files\Cache; + +class DummyUser extends \OC\User\User { + /** + * @var string $home + */ + private $home; + + /** + * @var string $uid + */ + private $uid; + + /** + * @param string $uid + * @param string $home + */ + public function __construct($uid, $home) { + $this->home = $home; + $this->uid = $uid; + } + + /** + * @return string + */ + public function getHome() { + return $this->home; + } + + /** + * @return string + */ + public function getUID() { + return $this->uid; + } +} + +/** + * Class HomeCacheTest + * + * @group DB + * + * @package Test\Files\Cache + */ +class HomeCacheTest extends \Test\TestCase { + /** + * @var \OC\Files\Storage\Home $storage + */ + private $storage; + + /** + * @var \OC\Files\Cache\HomeCache $cache + */ + private $cache; + + /** + * @var \OC\User\User $user + */ + private $user; + + protected function setUp() { + parent::setUp(); + + $this->user = new DummyUser('foo', \OC::$server->getTempManager()->getTemporaryFolder()); + $this->storage = new \OC\Files\Storage\Home(array('user' => $this->user)); + $this->cache = $this->storage->getCache(); + } + + /** + * Tests that the root and files folder size calculation ignores the subdirs + * that have an unknown size. This makes sure that quota calculation still + * works as it's based on the "files" folder size. + */ + public function testRootFolderSizeIgnoresUnknownUpdate() { + $dir1 = 'files/knownsize'; + $dir2 = 'files/unknownsize'; + $fileData = array(); + $fileData[''] = array('size' => -1, 'mtime' => 20, 'mimetype' => 'httpd/unix-directory'); + $fileData['files'] = array('size' => -1, 'mtime' => 20, 'mimetype' => 'httpd/unix-directory'); + $fileData[$dir1] = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'httpd/unix-directory'); + $fileData[$dir2] = array('size' => -1, 'mtime' => 25, 'mimetype' => 'httpd/unix-directory'); + + $this->cache->put('', $fileData['']); + $this->cache->put('files', $fileData['files']); + $this->cache->put($dir1, $fileData[$dir1]); + $this->cache->put($dir2, $fileData[$dir2]); + + $this->assertTrue($this->cache->inCache('files')); + $this->assertTrue($this->cache->inCache($dir1)); + $this->assertTrue($this->cache->inCache($dir2)); + + // check that files and root size ignored the unknown sizes + $this->assertEquals(1000, $this->cache->calculateFolderSize('files')); + + // clean up + $this->cache->remove(''); + $this->cache->remove('files'); + $this->cache->remove($dir1); + $this->cache->remove($dir2); + + $this->assertFalse($this->cache->inCache('files')); + $this->assertFalse($this->cache->inCache($dir1)); + $this->assertFalse($this->cache->inCache($dir2)); + } + + public function testRootFolderSizeIsFilesSize() { + $dir1 = 'files'; + $afile = 'test.txt'; + $fileData = array(); + $fileData[''] = array('size' => 1500, 'mtime' => 20, 'mimetype' => 'httpd/unix-directory'); + $fileData[$dir1] = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'httpd/unix-directory'); + $fileData[$afile] = array('size' => 500, 'mtime' => 20); + + $this->cache->put('', $fileData['']); + $this->cache->put($dir1, $fileData[$dir1]); + + $this->assertTrue($this->cache->inCache($dir1)); + + // check that root size ignored the unknown sizes + $data = $this->cache->get('files'); + $this->assertEquals(1000, $data['size']); + $data = $this->cache->get(''); + $this->assertEquals(1000, $data['size']); + + // clean up + $this->cache->remove(''); + $this->cache->remove($dir1); + + $this->assertFalse($this->cache->inCache($dir1)); + } +} diff --git a/tests/lib/Files/Cache/MoveFromCacheTraitTest.php b/tests/lib/Files/Cache/MoveFromCacheTraitTest.php new file mode 100644 index 00000000000..3d4a55c0722 --- /dev/null +++ b/tests/lib/Files/Cache/MoveFromCacheTraitTest.php @@ -0,0 +1,31 @@ +<?php +/** + * Copyright (c) 2016 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Files\Cache; + +use OC\Files\Cache\MoveFromCacheTrait; + +class FallBackCrossCacheMoveCache extends \OC\Files\Cache\Cache { + use MoveFromCacheTrait; +} + +/** + * Class MoveFromCacheTraitTest + * + * @group DB + */ +class MoveFromCacheTraitTest extends CacheTest { + protected function setUp() { + parent::setUp(); + + $this->storage = new \OC\Files\Storage\Temporary(array()); + $this->storage2 = new \OC\Files\Storage\Temporary(array()); + $this->cache = new FallBackCrossCacheMoveCache($this->storage); + $this->cache2 = new FallBackCrossCacheMoveCache($this->storage2); + } +} diff --git a/tests/lib/Files/Cache/ScannerTest.php b/tests/lib/Files/Cache/ScannerTest.php new file mode 100644 index 00000000000..4a93f3ee014 --- /dev/null +++ b/tests/lib/Files/Cache/ScannerTest.php @@ -0,0 +1,319 @@ +<?php +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Files\Cache; +use OC\Files\Cache\CacheEntry; + +/** + * Class ScannerTest + * + * @group DB + * + * @package Test\Files\Cache + */ +class ScannerTest extends \Test\TestCase { + /** + * @var \OC\Files\Storage\Storage $storage + */ + private $storage; + + /** + * @var \OC\Files\Cache\Scanner $scanner + */ + private $scanner; + + /** + * @var \OC\Files\Cache\Cache $cache + */ + private $cache; + + protected function setUp() { + parent::setUp(); + + $this->storage = new \OC\Files\Storage\Temporary(array()); + $this->scanner = new \OC\Files\Cache\Scanner($this->storage); + $this->cache = new \OC\Files\Cache\Cache($this->storage); + } + + protected function tearDown() { + if ($this->cache) { + $this->cache->clear(); + } + + parent::tearDown(); + } + + function testFile() { + $data = "dummy file data\n"; + $this->storage->file_put_contents('foo.txt', $data); + $this->scanner->scanFile('foo.txt'); + + $this->assertEquals($this->cache->inCache('foo.txt'), true); + $cachedData = $this->cache->get('foo.txt'); + $this->assertEquals($cachedData['size'], strlen($data)); + $this->assertEquals($cachedData['mimetype'], 'text/plain'); + $this->assertNotEquals($cachedData['parent'], -1); //parent folders should be scanned automatically + + $data = file_get_contents(\OC::$SERVERROOT . '/core/img/logo.png'); + $this->storage->file_put_contents('foo.png', $data); + $this->scanner->scanFile('foo.png'); + + $this->assertEquals($this->cache->inCache('foo.png'), true); + $cachedData = $this->cache->get('foo.png'); + $this->assertEquals($cachedData['size'], strlen($data)); + $this->assertEquals($cachedData['mimetype'], 'image/png'); + } + + private function fillTestFolders() { + $textData = "dummy file data\n"; + $imgData = file_get_contents(\OC::$SERVERROOT . '/core/img/logo.png'); + $this->storage->mkdir('folder'); + $this->storage->file_put_contents('foo.txt', $textData); + $this->storage->file_put_contents('foo.png', $imgData); + $this->storage->file_put_contents('folder/bar.txt', $textData); + } + + function testFolder() { + $this->fillTestFolders(); + + $this->scanner->scan(''); + $this->assertEquals($this->cache->inCache(''), true); + $this->assertEquals($this->cache->inCache('foo.txt'), true); + $this->assertEquals($this->cache->inCache('foo.png'), true); + $this->assertEquals($this->cache->inCache('folder'), true); + $this->assertEquals($this->cache->inCache('folder/bar.txt'), true); + + $cachedDataText = $this->cache->get('foo.txt'); + $cachedDataText2 = $this->cache->get('foo.txt'); + $cachedDataImage = $this->cache->get('foo.png'); + $cachedDataFolder = $this->cache->get(''); + $cachedDataFolder2 = $this->cache->get('folder'); + + $this->assertEquals($cachedDataImage['parent'], $cachedDataText['parent']); + $this->assertEquals($cachedDataFolder['fileid'], $cachedDataImage['parent']); + $this->assertEquals($cachedDataFolder['size'], $cachedDataImage['size'] + $cachedDataText['size'] + $cachedDataText2['size']); + $this->assertEquals($cachedDataFolder2['size'], $cachedDataText2['size']); + } + + function testShallow() { + $this->fillTestFolders(); + + $this->scanner->scan('', \OC\Files\Cache\Scanner::SCAN_SHALLOW); + $this->assertEquals($this->cache->inCache(''), true); + $this->assertEquals($this->cache->inCache('foo.txt'), true); + $this->assertEquals($this->cache->inCache('foo.png'), true); + $this->assertEquals($this->cache->inCache('folder'), true); + $this->assertEquals($this->cache->inCache('folder/bar.txt'), false); + + $cachedDataFolder = $this->cache->get(''); + $cachedDataFolder2 = $this->cache->get('folder'); + + $this->assertEquals(-1, $cachedDataFolder['size']); + $this->assertEquals(-1, $cachedDataFolder2['size']); + + $this->scanner->scan('folder', \OC\Files\Cache\Scanner::SCAN_SHALLOW); + + $cachedDataFolder2 = $this->cache->get('folder'); + + $this->assertNotEquals($cachedDataFolder2['size'], -1); + + $this->cache->correctFolderSize('folder'); + + $cachedDataFolder = $this->cache->get(''); + $this->assertNotEquals($cachedDataFolder['size'], -1); + } + + function testBackgroundScan() { + $this->fillTestFolders(); + $this->storage->mkdir('folder2'); + $this->storage->file_put_contents('folder2/bar.txt', 'foobar'); + + $this->scanner->scan('', \OC\Files\Cache\Scanner::SCAN_SHALLOW); + $this->assertFalse($this->cache->inCache('folder/bar.txt')); + $this->assertFalse($this->cache->inCache('folder/2bar.txt')); + $cachedData = $this->cache->get(''); + $this->assertEquals(-1, $cachedData['size']); + + $this->scanner->backgroundScan(); + + $this->assertTrue($this->cache->inCache('folder/bar.txt')); + $this->assertTrue($this->cache->inCache('folder/bar.txt')); + + $cachedData = $this->cache->get(''); + $this->assertnotEquals(-1, $cachedData['size']); + + $this->assertFalse($this->cache->getIncomplete()); + } + + public function testReuseExisting() { + $this->fillTestFolders(); + + $this->scanner->scan(''); + $oldData = $this->cache->get(''); + $this->storage->unlink('folder/bar.txt'); + $this->cache->put('folder', array('mtime' => $this->storage->filemtime('folder'), 'storage_mtime' => $this->storage->filemtime('folder'))); + $this->scanner->scan('', \OC\Files\Cache\Scanner::SCAN_SHALLOW, \OC\Files\Cache\Scanner::REUSE_SIZE); + $newData = $this->cache->get(''); + $this->assertInternalType('string', $oldData['etag']); + $this->assertInternalType('string', $newData['etag']); + $this->assertNotSame($oldData['etag'], $newData['etag']); + $this->assertEquals($oldData['size'], $newData['size']); + + $oldData = $newData; + $this->scanner->scan('', \OC\Files\Cache\Scanner::SCAN_SHALLOW, \OC\Files\Cache\Scanner::REUSE_ETAG); + $newData = $this->cache->get(''); + $this->assertSame($oldData['etag'], $newData['etag']); + $this->assertEquals(-1, $newData['size']); + + $this->scanner->scan('', \OC\Files\Cache\Scanner::SCAN_RECURSIVE); + $oldData = $this->cache->get(''); + $this->assertNotEquals(-1, $oldData['size']); + $this->scanner->scanFile('', \OC\Files\Cache\Scanner::REUSE_ETAG + \OC\Files\Cache\Scanner::REUSE_SIZE); + $newData = $this->cache->get(''); + $this->assertSame($oldData['etag'], $newData['etag']); + $this->assertEquals($oldData['size'], $newData['size']); + + $this->scanner->scan('', \OC\Files\Cache\Scanner::SCAN_RECURSIVE, \OC\Files\Cache\Scanner::REUSE_ETAG + \OC\Files\Cache\Scanner::REUSE_SIZE); + $newData = $this->cache->get(''); + $this->assertSame($oldData['etag'], $newData['etag']); + $this->assertEquals($oldData['size'], $newData['size']); + + $this->scanner->scan('', \OC\Files\Cache\Scanner::SCAN_SHALLOW, \OC\Files\Cache\Scanner::REUSE_ETAG + \OC\Files\Cache\Scanner::REUSE_SIZE); + $newData = $this->cache->get(''); + $this->assertSame($oldData['etag'], $newData['etag']); + $this->assertEquals($oldData['size'], $newData['size']); + } + + public function testRemovedFile() { + $this->fillTestFolders(); + + $this->scanner->scan(''); + $this->assertTrue($this->cache->inCache('foo.txt')); + $this->storage->unlink('foo.txt'); + $this->scanner->scan('', \OC\Files\Cache\Scanner::SCAN_SHALLOW); + $this->assertFalse($this->cache->inCache('foo.txt')); + } + + public function testRemovedFolder() { + $this->fillTestFolders(); + + $this->scanner->scan(''); + $this->assertTrue($this->cache->inCache('folder/bar.txt')); + $this->storage->rmdir('/folder'); + $this->scanner->scan('', \OC\Files\Cache\Scanner::SCAN_SHALLOW); + $this->assertFalse($this->cache->inCache('folder')); + $this->assertFalse($this->cache->inCache('folder/bar.txt')); + } + + public function testScanRemovedFile() { + $this->fillTestFolders(); + + $this->scanner->scan(''); + $this->assertTrue($this->cache->inCache('folder/bar.txt')); + $this->storage->unlink('folder/bar.txt'); + $this->scanner->scanFile('folder/bar.txt'); + $this->assertFalse($this->cache->inCache('folder/bar.txt')); + } + + public function testETagRecreation() { + $this->fillTestFolders(); + + $this->scanner->scan('folder/bar.txt'); + + // manipulate etag to simulate an empty etag + $this->scanner->scan('', \OC\Files\Cache\Scanner::SCAN_SHALLOW, \OC\Files\Cache\Scanner::REUSE_ETAG); + /** @var CacheEntry $data0 */ + $data0 = $this->cache->get('folder/bar.txt'); + $this->assertInternalType('string', $data0['etag']); + $data1 = $this->cache->get('folder'); + $this->assertInternalType('string', $data1['etag']); + $data2 = $this->cache->get(''); + $this->assertInternalType('string', $data2['etag']); + $data0['etag'] = ''; + $this->cache->put('folder/bar.txt', $data0->getData()); + + // rescan + $this->scanner->scan('folder/bar.txt', \OC\Files\Cache\Scanner::SCAN_SHALLOW, \OC\Files\Cache\Scanner::REUSE_ETAG); + + // verify cache content + $newData0 = $this->cache->get('folder/bar.txt'); + $this->assertInternalType('string', $newData0['etag']); + $this->assertNotEmpty($newData0['etag']); + } + + public function testRepairParent() { + $this->fillTestFolders(); + $this->scanner->scan(''); + $this->assertTrue($this->cache->inCache('folder/bar.txt')); + $oldFolderId = $this->cache->getId('folder'); + + // delete the folder without removing the childs + $sql = 'DELETE FROM `*PREFIX*filecache` WHERE `fileid` = ?'; + \OC_DB::executeAudited($sql, array($oldFolderId)); + + $cachedData = $this->cache->get('folder/bar.txt'); + $this->assertEquals($oldFolderId, $cachedData['parent']); + $this->assertFalse($this->cache->inCache('folder')); + + $this->scanner->scan(''); + + $this->assertTrue($this->cache->inCache('folder')); + $newFolderId = $this->cache->getId('folder'); + $this->assertNotEquals($oldFolderId, $newFolderId); + + $cachedData = $this->cache->get('folder/bar.txt'); + $this->assertEquals($newFolderId, $cachedData['parent']); + } + + public function testRepairParentShallow() { + $this->fillTestFolders(); + $this->scanner->scan(''); + $this->assertTrue($this->cache->inCache('folder/bar.txt')); + $oldFolderId = $this->cache->getId('folder'); + + // delete the folder without removing the childs + $sql = 'DELETE FROM `*PREFIX*filecache` WHERE `fileid` = ?'; + \OC_DB::executeAudited($sql, array($oldFolderId)); + + $cachedData = $this->cache->get('folder/bar.txt'); + $this->assertEquals($oldFolderId, $cachedData['parent']); + $this->assertFalse($this->cache->inCache('folder')); + + $this->scanner->scan('folder', \OC\Files\Cache\Scanner::SCAN_SHALLOW); + + $this->assertTrue($this->cache->inCache('folder')); + $newFolderId = $this->cache->getId('folder'); + $this->assertNotEquals($oldFolderId, $newFolderId); + + $cachedData = $this->cache->get('folder/bar.txt'); + $this->assertEquals($newFolderId, $cachedData['parent']); + } + + /** + * @dataProvider dataTestIsPartialFile + * + * @param string $path + * @param bool $expected + */ + public function testIsPartialFile($path, $expected) { + $this->assertSame($expected, + $this->scanner->isPartialFile($path) + ); + } + + public function dataTestIsPartialFile() { + return [ + ['foo.txt.part', true], + ['/sub/folder/foo.txt.part', true], + ['/sub/folder.part/foo.txt', true], + ['foo.txt', false], + ['/sub/folder/foo.txt', false], + ]; + } + +} diff --git a/tests/lib/Files/Cache/UpdaterLegacyTest.php b/tests/lib/Files/Cache/UpdaterLegacyTest.php new file mode 100644 index 00000000000..7d247968ca9 --- /dev/null +++ b/tests/lib/Files/Cache/UpdaterLegacyTest.php @@ -0,0 +1,304 @@ +<?php +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Files\Cache; + +use \OC\Files\Filesystem as Filesystem; +use OC\Files\Storage\Temporary; +use OC\Files\View; + +/** + * Class UpdaterLegacyTest + * + * @group DB + * + * @package Test\Files\Cache + */ +class UpdaterLegacyTest extends \Test\TestCase { + /** + * @var \OC\Files\Storage\Storage $storage + */ + private $storage; + + /** + * @var \OC\Files\Cache\Scanner $scanner + */ + private $scanner; + + /** + * @var \OC\Files\Cache\Cache $cache + */ + private $cache; + + private static $user; + + protected function setUp() { + parent::setUp(); + + $this->storage = new \OC\Files\Storage\Temporary(array()); + $textData = "dummy file data\n"; + $imgData = file_get_contents(\OC::$SERVERROOT . '/core/img/logo.png'); + $this->storage->mkdir('folder'); + $this->storage->file_put_contents('foo.txt', $textData); + $this->storage->file_put_contents('foo.png', $imgData); + $this->storage->file_put_contents('folder/bar.txt', $textData); + $this->storage->file_put_contents('folder/bar2.txt', $textData); + + $this->scanner = $this->storage->getScanner(); + $this->scanner->scan(''); + $this->cache = $this->storage->getCache(); + + if (!self::$user) { + self::$user = $this->getUniqueID(); + } + + \OC::$server->getUserManager()->createUser(self::$user, 'password'); + $this->loginAsUser(self::$user); + + Filesystem::init(self::$user, '/' . self::$user . '/files'); + + Filesystem::clearMounts(); + Filesystem::mount($this->storage, array(), '/' . self::$user . '/files'); + + \OC_Hook::clear('OC_Filesystem'); + } + + protected function tearDown() { + if ($this->cache) { + $this->cache->clear(); + } + + $result = false; + $user = \OC::$server->getUserManager()->get(self::$user); + if ($user !== null) { $result = $user->delete(); } + $this->assertTrue($result); + + $this->logout(); + parent::tearDown(); + } + + public function testWrite() { + $textSize = strlen("dummy file data\n"); + $imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo.png'); + $this->cache->put('foo.txt', array('mtime' => 100, 'storage_mtime' => 150)); + $rootCachedData = $this->cache->get(''); + $this->assertEquals(3 * $textSize + $imageSize, $rootCachedData['size']); + + $fooCachedData = $this->cache->get('foo.txt'); + Filesystem::file_put_contents('foo.txt', 'asd'); + $cachedData = $this->cache->get('foo.txt'); + $this->assertEquals(3, $cachedData['size']); + $this->assertInternalType('string', $fooCachedData['etag']); + $this->assertInternalType('string', $cachedData['etag']); + $this->assertNotSame($fooCachedData['etag'], $cachedData['etag']); + $cachedData = $this->cache->get(''); + $this->assertEquals(2 * $textSize + $imageSize + 3, $cachedData['size']); + $this->assertInternalType('string', $rootCachedData['etag']); + $this->assertInternalType('string', $cachedData['etag']); + $this->assertNotSame($rootCachedData['etag'], $cachedData['etag']); + $rootCachedData = $cachedData; + + $this->assertFalse($this->cache->inCache('bar.txt')); + Filesystem::file_put_contents('bar.txt', 'asd'); + $this->assertTrue($this->cache->inCache('bar.txt')); + $cachedData = $this->cache->get('bar.txt'); + $this->assertEquals(3, $cachedData['size']); + $mtime = $cachedData['mtime']; + $cachedData = $this->cache->get(''); + $this->assertEquals(2 * $textSize + $imageSize + 2 * 3, $cachedData['size']); + $this->assertInternalType('string', $rootCachedData['etag']); + $this->assertInternalType('string', $cachedData['etag']); + $this->assertNotSame($rootCachedData['etag'], $cachedData['etag']); + $this->assertGreaterThanOrEqual($rootCachedData['mtime'], $mtime); + } + + public function testWriteWithMountPoints() { + $storage2 = new \OC\Files\Storage\Temporary(array()); + $storage2->getScanner()->scan(''); //initialize etags + $cache2 = $storage2->getCache(); + Filesystem::mount($storage2, array(), '/' . self::$user . '/files/folder/substorage'); + $view = new View('/' . self::$user . '/files'); + $folderCachedData = $view->getFileInfo('folder'); + $substorageCachedData = $cache2->get(''); + Filesystem::file_put_contents('folder/substorage/foo.txt', 'asd'); + $this->assertTrue($cache2->inCache('foo.txt')); + $cachedData = $cache2->get('foo.txt'); + $this->assertEquals(3, $cachedData['size']); + $mtime = $cachedData['mtime']; + + $cachedData = $cache2->get(''); + $this->assertInternalType('string', $substorageCachedData['etag']); + $this->assertInternalType('string', $cachedData['etag']); + $this->assertNotSame($substorageCachedData['etag'], $cachedData['etag']); + + $cachedData = $view->getFileInfo('folder'); + $this->assertInternalType('string', $folderCachedData['etag']); + $this->assertInternalType('string', $cachedData['etag']); + $this->assertNotSame($folderCachedData['etag'], $cachedData['etag']); + } + + public function testDelete() { + $textSize = strlen("dummy file data\n"); + $imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo.png'); + $rootCachedData = $this->cache->get(''); + $this->assertEquals(3 * $textSize + $imageSize, $rootCachedData['size']); + + $this->assertTrue($this->cache->inCache('foo.txt')); + Filesystem::unlink('foo.txt'); + $this->assertFalse($this->cache->inCache('foo.txt')); + $cachedData = $this->cache->get(''); + $this->assertEquals(2 * $textSize + $imageSize, $cachedData['size']); + $this->assertInternalType('string', $rootCachedData['etag']); + $this->assertInternalType('string', $cachedData['etag']); + $this->assertNotSame($rootCachedData['etag'], $cachedData['etag']); + $this->assertGreaterThanOrEqual($rootCachedData['mtime'], $cachedData['mtime']); + $rootCachedData = $cachedData; + + Filesystem::mkdir('bar_folder'); + $this->assertTrue($this->cache->inCache('bar_folder')); + $cachedData = $this->cache->get(''); + $this->assertInternalType('string', $rootCachedData['etag']); + $this->assertInternalType('string', $cachedData['etag']); + $this->assertNotSame($rootCachedData['etag'], $cachedData['etag']); + $rootCachedData = $cachedData; + Filesystem::rmdir('bar_folder'); + $this->assertFalse($this->cache->inCache('bar_folder')); + $cachedData = $this->cache->get(''); + $this->assertInternalType('string', $rootCachedData['etag']); + $this->assertInternalType('string', $cachedData['etag']); + $this->assertNotSame($rootCachedData['etag'], $cachedData['etag']); + $this->assertGreaterThanOrEqual($rootCachedData['mtime'], $cachedData['mtime']); + } + + public function testDeleteWithMountPoints() { + $storage2 = new \OC\Files\Storage\Temporary(array()); + $cache2 = $storage2->getCache(); + Filesystem::mount($storage2, array(), '/' . self::$user . '/files/folder/substorage'); + Filesystem::file_put_contents('folder/substorage/foo.txt', 'asd'); + $view = new View('/' . self::$user . '/files'); + $this->assertTrue($cache2->inCache('foo.txt')); + $folderCachedData = $view->getFileInfo('folder'); + $substorageCachedData = $cache2->get(''); + Filesystem::unlink('folder/substorage/foo.txt'); + $this->assertFalse($cache2->inCache('foo.txt')); + + $cachedData = $cache2->get(''); + $this->assertInternalType('string', $substorageCachedData['etag']); + $this->assertInternalType('string', $cachedData['etag']); + $this->assertNotSame($substorageCachedData['etag'], $cachedData['etag']); + $this->assertGreaterThanOrEqual($substorageCachedData['mtime'], $cachedData['mtime']); + + $cachedData = $view->getFileInfo('folder'); + $this->assertInternalType('string', $folderCachedData['etag']); + $this->assertInternalType('string', $cachedData['etag']); + $this->assertNotSame($folderCachedData['etag'], $cachedData['etag']); + $this->assertGreaterThanOrEqual($folderCachedData['mtime'], $cachedData['mtime']); + } + + public function testRename() { + $textSize = strlen("dummy file data\n"); + $imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo.png'); + $rootCachedData = $this->cache->get(''); + $this->assertEquals(3 * $textSize + $imageSize, $rootCachedData['size']); + + $this->assertTrue($this->cache->inCache('foo.txt')); + $fooCachedData = $this->cache->get('foo.txt'); + $this->assertFalse($this->cache->inCache('bar.txt')); + Filesystem::rename('foo.txt', 'bar.txt'); + $this->assertFalse($this->cache->inCache('foo.txt')); + $this->assertTrue($this->cache->inCache('bar.txt')); + $cachedData = $this->cache->get('bar.txt'); + $this->assertEquals($fooCachedData['fileid'], $cachedData['fileid']); + $mtime = $cachedData['mtime']; + $cachedData = $this->cache->get(''); + $this->assertEquals(3 * $textSize + $imageSize, $cachedData['size']); + $this->assertInternalType('string', $rootCachedData['etag']); + $this->assertInternalType('string', $cachedData['etag']); + $this->assertNotSame($rootCachedData['etag'], $cachedData['etag']); + } + + public function testRenameExtension() { + $fooCachedData = $this->cache->get('foo.txt'); + $this->assertEquals('text/plain', $fooCachedData['mimetype']); + Filesystem::rename('foo.txt', 'foo.abcd'); + $fooCachedData = $this->cache->get('foo.abcd'); + $this->assertEquals('application/octet-stream', $fooCachedData['mimetype']); + } + + public function testRenameWithMountPoints() { + $storage2 = new \OC\Files\Storage\Temporary(array()); + $cache2 = $storage2->getCache(); + Filesystem::mount($storage2, array(), '/' . self::$user . '/files/folder/substorage'); + Filesystem::file_put_contents('folder/substorage/foo.txt', 'asd'); + $view = new View('/' . self::$user . '/files'); + $this->assertTrue($cache2->inCache('foo.txt')); + $folderCachedData = $view->getFileInfo('folder'); + $substorageCachedData = $cache2->get(''); + $fooCachedData = $cache2->get('foo.txt'); + Filesystem::rename('folder/substorage/foo.txt', 'folder/substorage/bar.txt'); + $this->assertFalse($cache2->inCache('foo.txt')); + $this->assertTrue($cache2->inCache('bar.txt')); + $cachedData = $cache2->get('bar.txt'); + $this->assertEquals($fooCachedData['fileid'], $cachedData['fileid']); + $mtime = $cachedData['mtime']; + + $cachedData = $cache2->get(''); + $this->assertInternalType('string', $substorageCachedData['etag']); + $this->assertInternalType('string', $cachedData['etag']); + $this->assertNotSame($substorageCachedData['etag'], $cachedData['etag']); + // rename can cause mtime change - invalid assert +// $this->assertEquals($mtime, $cachedData['mtime']); + + $cachedData = $view->getFileInfo('folder'); + $this->assertInternalType('string', $folderCachedData['etag']); + $this->assertInternalType('string', $cachedData['etag']); + $this->assertNotSame($folderCachedData['etag'], $cachedData['etag']); + // rename can cause mtime change - invalid assert +// $this->assertEquals($mtime, $cachedData['mtime']); + } + + public function testTouch() { + $rootCachedData = $this->cache->get(''); + $fooCachedData = $this->cache->get('foo.txt'); + Filesystem::touch('foo.txt'); + $cachedData = $this->cache->get('foo.txt'); + $this->assertInternalType('string', $fooCachedData['etag']); + $this->assertInternalType('string', $cachedData['etag']); + $this->assertGreaterThanOrEqual($fooCachedData['mtime'], $cachedData['mtime']); + + $cachedData = $this->cache->get(''); + $this->assertInternalType('string', $rootCachedData['etag']); + $this->assertInternalType('string', $cachedData['etag']); + $this->assertNotSame($rootCachedData['etag'], $cachedData['etag']); + $this->assertGreaterThanOrEqual($rootCachedData['mtime'], $cachedData['mtime']); + $rootCachedData = $cachedData; + + $time = 1371006070; + $barCachedData = $this->cache->get('folder/bar.txt'); + $folderCachedData = $this->cache->get('folder'); + $this->cache->put('', ['mtime' => $time - 100]); + Filesystem::touch('folder/bar.txt', $time); + $cachedData = $this->cache->get('folder/bar.txt'); + $this->assertInternalType('string', $barCachedData['etag']); + $this->assertInternalType('string', $cachedData['etag']); + $this->assertNotSame($barCachedData['etag'], $cachedData['etag']); + $this->assertEquals($time, $cachedData['mtime']); + + $cachedData = $this->cache->get('folder'); + $this->assertInternalType('string', $folderCachedData['etag']); + $this->assertInternalType('string', $cachedData['etag']); + $this->assertNotSame($folderCachedData['etag'], $cachedData['etag']); + + $cachedData = $this->cache->get(''); + $this->assertInternalType('string', $rootCachedData['etag']); + $this->assertInternalType('string', $cachedData['etag']); + $this->assertNotSame($rootCachedData['etag'], $cachedData['etag']); + $this->assertEquals($time, $cachedData['mtime']); + } + +} diff --git a/tests/lib/Files/Cache/UpdaterTest.php b/tests/lib/Files/Cache/UpdaterTest.php new file mode 100644 index 00000000000..54fb3f3fc97 --- /dev/null +++ b/tests/lib/Files/Cache/UpdaterTest.php @@ -0,0 +1,308 @@ +<?php +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Files\Cache; + +use OC\Files\Filesystem; +use OC\Files\Storage\Temporary; +use OC\Files\View; + +/** + * Class UpdaterTest + * + * @group DB + * + * @package Test\Files\Cache + */ +class UpdaterTest extends \Test\TestCase { + /** + * @var \OC\Files\Storage\Storage + */ + protected $storage; + + /** + * @var \OC\Files\Cache\Cache + */ + protected $cache; + + /** + * @var \OC\Files\View + */ + protected $view; + + /** + * @var \OC\Files\Cache\Updater + */ + protected $updater; + + protected function setUp() { + parent::setUp(); + + $this->loginAsUser(); + + $this->storage = new Temporary(array()); + $this->updater = $this->storage->getUpdater(); + $this->cache = $this->storage->getCache(); + } + + protected function tearDown() { + Filesystem::clearMounts(); + + $this->logout(); + parent::tearDown(); + } + + public function testNewFile() { + $this->storage->file_put_contents('foo.txt', 'bar'); + $this->assertFalse($this->cache->inCache('foo.txt')); + + $this->updater->update('foo.txt'); + + $this->assertTrue($this->cache->inCache('foo.txt')); + $cached = $this->cache->get('foo.txt'); + $this->assertEquals(3, $cached['size']); + $this->assertEquals('text/plain', $cached['mimetype']); + } + + public function testUpdatedFile() { + $this->storage->file_put_contents('foo.txt', 'bar'); + $this->updater->update('foo.txt'); + + $cached = $this->cache->get('foo.txt'); + $this->assertEquals(3, $cached['size']); + $this->assertEquals('text/plain', $cached['mimetype']); + + $this->storage->file_put_contents('foo.txt', 'qwerty'); + + $cached = $this->cache->get('foo.txt'); + $this->assertEquals(3, $cached['size']); + + $this->updater->update('/foo.txt'); + + $cached = $this->cache->get('foo.txt'); + $this->assertEquals(6, $cached['size']); + } + + public function testParentSize() { + $this->storage->getScanner()->scan(''); + + $parentCached = $this->cache->get(''); + $this->assertEquals(0, $parentCached['size']); + + $this->storage->file_put_contents('foo.txt', 'bar'); + + $parentCached = $this->cache->get(''); + $this->assertEquals(0, $parentCached['size']); + + $this->updater->update('foo.txt'); + + $parentCached = $this->cache->get(''); + $this->assertEquals(3, $parentCached['size']); + + $this->storage->file_put_contents('foo.txt', 'qwerty'); + + $parentCached = $this->cache->get(''); + $this->assertEquals(3, $parentCached['size']); + + $this->updater->update('foo.txt'); + + $parentCached = $this->cache->get(''); + $this->assertEquals(6, $parentCached['size']); + + $this->storage->unlink('foo.txt'); + + $parentCached = $this->cache->get(''); + $this->assertEquals(6, $parentCached['size']); + + $this->updater->remove('foo.txt'); + + $parentCached = $this->cache->get(''); + $this->assertEquals(0, $parentCached['size']); + } + + public function testMove() { + $this->storage->file_put_contents('foo.txt', 'qwerty'); + $this->updater->update('foo.txt'); + + $this->assertTrue($this->cache->inCache('foo.txt')); + $this->assertFalse($this->cache->inCache('bar.txt')); + $cached = $this->cache->get('foo.txt'); + + $this->storage->rename('foo.txt', 'bar.txt'); + + $this->assertTrue($this->cache->inCache('foo.txt')); + $this->assertFalse($this->cache->inCache('bar.txt')); + + $this->updater->renameFromStorage($this->storage, 'foo.txt', 'bar.txt'); + + $this->assertFalse($this->cache->inCache('foo.txt')); + $this->assertTrue($this->cache->inCache('bar.txt')); + + $cachedTarget = $this->cache->get('bar.txt'); + $this->assertEquals($cached['etag'], $cachedTarget['etag']); + $this->assertEquals($cached['mtime'], $cachedTarget['mtime']); + $this->assertEquals($cached['size'], $cachedTarget['size']); + $this->assertEquals($cached['fileid'], $cachedTarget['fileid']); + } + + public function testMoveNonExistingOverwrite() { + $this->storage->file_put_contents('bar.txt', 'qwerty'); + $this->updater->update('bar.txt'); + + $cached = $this->cache->get('bar.txt'); + + $this->updater->renameFromStorage($this->storage, 'foo.txt', 'bar.txt'); + + $this->assertFalse($this->cache->inCache('foo.txt')); + $this->assertTrue($this->cache->inCache('bar.txt')); + + $cachedTarget = $this->cache->get('bar.txt'); + $this->assertEquals($cached['etag'], $cachedTarget['etag']); + $this->assertEquals($cached['mtime'], $cachedTarget['mtime']); + $this->assertEquals($cached['size'], $cachedTarget['size']); + $this->assertEquals($cached['fileid'], $cachedTarget['fileid']); + } + + public function testUpdateStorageMTime() { + $this->storage->mkdir('sub'); + $this->storage->mkdir('sub2'); + $this->storage->file_put_contents('sub/foo.txt', 'qwerty'); + + $this->updater->update('sub'); + $this->updater->update('sub/foo.txt'); + $this->updater->update('sub2'); + + $cachedSourceParent = $this->cache->get('sub'); + $cachedSource = $this->cache->get('sub/foo.txt'); + + $this->storage->rename('sub/foo.txt', 'sub2/bar.txt'); + + // simulate storage having a different mtime + $testmtime = 1433323578; + + // source storage mtime change + $this->storage->touch('sub', $testmtime); + + // target storage mtime change + $this->storage->touch('sub2', $testmtime); + // some storages (like Dropbox) change storage mtime on rename + $this->storage->touch('sub2/bar.txt', $testmtime); + + $this->updater->renameFromStorage($this->storage, 'sub/foo.txt', 'sub2/bar.txt'); + + $cachedTargetParent = $this->cache->get('sub2'); + $cachedTarget = $this->cache->get('sub2/bar.txt'); + + $this->assertEquals($cachedSource['mtime'], $cachedTarget['mtime'], 'file mtime preserved'); + + $this->assertNotEquals($cachedTarget['storage_mtime'], $cachedTarget['mtime'], 'mtime is not storage_mtime for moved file'); + + $this->assertEquals($testmtime, $cachedTarget['storage_mtime'], 'target file storage_mtime propagated'); + $this->assertNotEquals($testmtime, $cachedTarget['mtime'], 'target file mtime changed, not from storage'); + + $this->assertEquals($testmtime, $cachedTargetParent['storage_mtime'], 'target parent storage_mtime propagated'); + $this->assertNotEquals($testmtime, $cachedTargetParent['mtime'], 'target folder mtime changed, not from storage'); + } + + public function testNewFileDisabled() { + $this->storage->file_put_contents('foo.txt', 'bar'); + $this->assertFalse($this->cache->inCache('foo.txt')); + + $this->updater->disable(); + $this->updater->update('/foo.txt'); + + $this->assertFalse($this->cache->inCache('foo.txt')); + } + + public function testMoveCrossStorage() { + $storage2 = new Temporary(array()); + $cache2 = $storage2->getCache(); + Filesystem::mount($storage2, array(), '/bar'); + $this->storage->file_put_contents('foo.txt', 'qwerty'); + + $this->updater->update('foo.txt'); + + $this->assertTrue($this->cache->inCache('foo.txt')); + $this->assertFalse($cache2->inCache('bar.txt')); + $cached = $this->cache->get('foo.txt'); + + // "rename" + $storage2->file_put_contents('bar.txt', 'qwerty'); + $this->storage->unlink('foo.txt'); + + $this->assertTrue($this->cache->inCache('foo.txt')); + $this->assertFalse($cache2->inCache('bar.txt')); + + $storage2->getUpdater()->renameFromStorage($this->storage, 'foo.txt', 'bar.txt'); + + $this->assertFalse($this->cache->inCache('foo.txt')); + $this->assertTrue($cache2->inCache('bar.txt')); + + $cachedTarget = $cache2->get('bar.txt'); + $this->assertEquals($cached['mtime'], $cachedTarget['mtime']); + $this->assertEquals($cached['size'], $cachedTarget['size']); + $this->assertEquals($cached['etag'], $cachedTarget['etag']); + $this->assertEquals($cached['fileid'], $cachedTarget['fileid']); + } + + public function testMoveFolderCrossStorage() { + $storage2 = new Temporary(array()); + $cache2 = $storage2->getCache(); + Filesystem::mount($storage2, array(), '/bar'); + $this->storage->mkdir('foo'); + $this->storage->mkdir('foo/bar'); + $this->storage->file_put_contents('foo/foo.txt', 'qwerty'); + $this->storage->file_put_contents('foo/bar.txt', 'foo'); + $this->storage->file_put_contents('foo/bar/bar.txt', 'qwertyuiop'); + + $this->storage->getScanner()->scan(''); + + $this->assertTrue($this->cache->inCache('foo')); + $this->assertTrue($this->cache->inCache('foo/foo.txt')); + $this->assertTrue($this->cache->inCache('foo/bar.txt')); + $this->assertTrue($this->cache->inCache('foo/bar')); + $this->assertTrue($this->cache->inCache('foo/bar/bar.txt')); + $cached = []; + $cached[] = $this->cache->get('foo'); + $cached[] = $this->cache->get('foo/foo.txt'); + $cached[] = $this->cache->get('foo/bar.txt'); + $cached[] = $this->cache->get('foo/bar'); + $cached[] = $this->cache->get('foo/bar/bar.txt'); + + // add extension to trigger the possible mimetype change + $storage2->moveFromStorage($this->storage, 'foo', 'foo.b'); + $storage2->getUpdater()->renameFromStorage($this->storage, 'foo', 'foo.b'); + + $this->assertFalse($this->cache->inCache('foo')); + $this->assertFalse($this->cache->inCache('foo/foo.txt')); + $this->assertFalse($this->cache->inCache('foo/bar.txt')); + $this->assertFalse($this->cache->inCache('foo/bar')); + $this->assertFalse($this->cache->inCache('foo/bar/bar.txt')); + $this->assertTrue($cache2->inCache('foo.b')); + $this->assertTrue($cache2->inCache('foo.b/foo.txt')); + $this->assertTrue($cache2->inCache('foo.b/bar.txt')); + $this->assertTrue($cache2->inCache('foo.b/bar')); + $this->assertTrue($cache2->inCache('foo.b/bar/bar.txt')); + + $cachedTarget = []; + $cachedTarget[] = $cache2->get('foo.b'); + $cachedTarget[] = $cache2->get('foo.b/foo.txt'); + $cachedTarget[] = $cache2->get('foo.b/bar.txt'); + $cachedTarget[] = $cache2->get('foo.b/bar'); + $cachedTarget[] = $cache2->get('foo.b/bar/bar.txt'); + + foreach ($cached as $i => $old) { + $new = $cachedTarget[$i]; + $this->assertEquals($old['mtime'], $new['mtime']); + $this->assertEquals($old['size'], $new['size']); + $this->assertEquals($old['etag'], $new['etag']); + $this->assertEquals($old['fileid'], $new['fileid']); + $this->assertEquals($old['mimetype'], $new['mimetype']); + } + } +} diff --git a/tests/lib/Files/Cache/WatcherTest.php b/tests/lib/Files/Cache/WatcherTest.php new file mode 100644 index 00000000000..3834b5591ff --- /dev/null +++ b/tests/lib/Files/Cache/WatcherTest.php @@ -0,0 +1,196 @@ +<?php +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Files\Cache; + +/** + * Class WatcherTest + * + * @group DB + * + * @package Test\Files\Cache + */ +class WatcherTest extends \Test\TestCase { + + /** + * @var \OC\Files\Storage\Storage[] $storages + */ + private $storages = array(); + + protected function setUp() { + parent::setUp(); + + $this->loginAsUser(); + } + + protected function tearDown() { + foreach ($this->storages as $storage) { + $cache = $storage->getCache(); + $ids = $cache->getAll(); + $cache->clear(); + } + + $this->logout(); + parent::tearDown(); + } + + /** + * @medium + */ + function testWatcher() { + $storage = $this->getTestStorage(); + $cache = $storage->getCache(); + $updater = $storage->getWatcher(); + $updater->setPolicy(\OC\Files\Cache\Watcher::CHECK_ONCE); + + //set the mtime to the past so it can detect an mtime change + $cache->put('', array('storage_mtime' => 10)); + + $this->assertTrue($cache->inCache('folder/bar.txt')); + $this->assertTrue($cache->inCache('folder/bar2.txt')); + + $this->assertFalse($cache->inCache('bar.test')); + $storage->file_put_contents('bar.test', 'foo'); + $updater->checkUpdate(''); + $this->assertTrue($cache->inCache('bar.test')); + $cachedData = $cache->get('bar.test'); + $this->assertEquals(3, $cachedData['size']); + + $cache->put('bar.test', array('storage_mtime' => 10)); + $storage->file_put_contents('bar.test', 'test data'); + + // make sure that PHP can read the new size correctly + clearstatcache(); + + $updater->checkUpdate('bar.test'); + $cachedData = $cache->get('bar.test'); + $this->assertEquals(9, $cachedData['size']); + + $cache->put('folder', array('storage_mtime' => 10)); + + $storage->unlink('folder/bar2.txt'); + $updater->checkUpdate('folder'); + + $this->assertTrue($cache->inCache('folder/bar.txt')); + $this->assertFalse($cache->inCache('folder/bar2.txt')); + } + + /** + * @medium + */ + public function testFileToFolder() { + $storage = $this->getTestStorage(); + $cache = $storage->getCache(); + $updater = $storage->getWatcher(); + $updater->setPolicy(\OC\Files\Cache\Watcher::CHECK_ONCE); + + //set the mtime to the past so it can detect an mtime change + $cache->put('', array('storage_mtime' => 10)); + + $storage->unlink('foo.txt'); + $storage->rename('folder', 'foo.txt'); + $updater->checkUpdate(''); + + $entry = $cache->get('foo.txt'); + $this->assertEquals('httpd/unix-directory', $entry['mimetype']); + $this->assertFalse($cache->inCache('folder')); + $this->assertFalse($cache->inCache('folder/bar.txt')); + + $storage = $this->getTestStorage(); + $cache = $storage->getCache(); + $updater = $storage->getWatcher(); + $updater->setPolicy(\OC\Files\Cache\Watcher::CHECK_ONCE); + + //set the mtime to the past so it can detect an mtime change + $cache->put('foo.txt', array('storage_mtime' => 10)); + + $storage->unlink('foo.txt'); + $storage->rename('folder', 'foo.txt'); + $updater->checkUpdate('foo.txt'); + + $entry = $cache->get('foo.txt'); + $this->assertEquals('httpd/unix-directory', $entry['mimetype']); + $this->assertTrue($cache->inCache('foo.txt/bar.txt')); + } + + public function testPolicyNever() { + $storage = $this->getTestStorage(); + $cache = $storage->getCache(); + $updater = $storage->getWatcher(); + + //set the mtime to the past so it can detect an mtime change + $cache->put('foo.txt', array('storage_mtime' => 10)); + + $updater->setPolicy(\OC\Files\Cache\Watcher::CHECK_NEVER); + + $storage->file_put_contents('foo.txt', 'q'); + $this->assertFalse($updater->checkUpdate('foo.txt')); + + $cache->put('foo.txt', array('storage_mtime' => 20)); + $storage->file_put_contents('foo.txt', 'w'); + $this->assertFalse($updater->checkUpdate('foo.txt')); + } + + public function testPolicyOnce() { + $storage = $this->getTestStorage(); + $cache = $storage->getCache(); + $updater = $storage->getWatcher(); + + //set the mtime to the past so it can detect an mtime change + $cache->put('foo.txt', array('storage_mtime' => 10)); + + $updater->setPolicy(\OC\Files\Cache\Watcher::CHECK_ONCE); + + $storage->file_put_contents('foo.txt', 'q'); + $this->assertTrue($updater->checkUpdate('foo.txt')); + + $cache->put('foo.txt', array('storage_mtime' => 20)); + $storage->file_put_contents('foo.txt', 'w'); + $this->assertFalse($updater->checkUpdate('foo.txt')); + } + + public function testPolicyAlways() { + $storage = $this->getTestStorage(); + $cache = $storage->getCache(); + $updater = $storage->getWatcher(); + + //set the mtime to the past so it can detect an mtime change + $cache->put('foo.txt', array('storage_mtime' => 10)); + + $updater->setPolicy(\OC\Files\Cache\Watcher::CHECK_ALWAYS); + + $storage->file_put_contents('foo.txt', 'q'); + $this->assertTrue($updater->checkUpdate('foo.txt')); + + $cache->put('foo.txt', array('storage_mtime' => 20)); + $storage->file_put_contents('foo.txt', 'w'); + $this->assertTrue($updater->checkUpdate('foo.txt')); + } + + /** + * @param bool $scan + * @return \OC\Files\Storage\Storage + */ + private function getTestStorage($scan = true) { + $storage = new \OC\Files\Storage\Temporary(array()); + $textData = "dummy file data\n"; + $imgData = file_get_contents(\OC::$SERVERROOT . '/core/img/logo.png'); + $storage->mkdir('folder'); + $storage->file_put_contents('foo.txt', $textData); + $storage->file_put_contents('foo.png', $imgData); + $storage->file_put_contents('folder/bar.txt', $textData); + $storage->file_put_contents('folder/bar2.txt', $textData); + + if ($scan) { + $scanner = $storage->getScanner(); + $scanner->scan(''); + } + $this->storages[] = $storage; + return $storage; + } +} diff --git a/tests/lib/Files/Cache/Wrapper/CacheJailTest.php b/tests/lib/Files/Cache/Wrapper/CacheJailTest.php new file mode 100644 index 00000000000..6ef6716f721 --- /dev/null +++ b/tests/lib/Files/Cache/Wrapper/CacheJailTest.php @@ -0,0 +1,74 @@ +<?php +/** + * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Files\Cache\Wrapper; + +use Test\Files\Cache\CacheTest; + +/** + * Class CacheJail + * + * @group DB + * + * @package Test\Files\Cache\Wrapper + */ +class CacheJailTest extends CacheTest { + /** + * @var \OC\Files\Cache\Cache $sourceCache + */ + protected $sourceCache; + + public function setUp() { + parent::setUp(); + $this->storage->mkdir('foo'); + $this->sourceCache = $this->cache; + $this->cache = new \OC\Files\Cache\Wrapper\CacheJail($this->sourceCache, 'foo'); + } + + function testSearchOutsideJail() { + $file1 = 'foo/foobar'; + $file2 = 'folder/foobar'; + $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder'); + + $this->sourceCache->put($file1, $data1); + $this->sourceCache->put($file2, $data1); + + $this->assertCount(2, $this->sourceCache->search('%foobar')); + + $result = $this->cache->search('%foobar%'); + $this->assertCount(1, $result); + $this->assertEquals('foobar', $result[0]['path']); + } + + function testClearKeepEntriesOutsideJail() { + $file1 = 'foo/foobar'; + $file2 = 'foo/foobar/asd'; + $file3 = 'folder/foobar'; + $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory'); + + $this->sourceCache->put('foo', $data1); + $this->sourceCache->put($file1, $data1); + $this->sourceCache->put($file2, $data1); + $this->sourceCache->put($file3, $data1); + + $this->cache->clear(); + + $this->assertFalse($this->cache->inCache('foobar')); + $this->assertTrue($this->sourceCache->inCache('folder/foobar')); + } + + function testGetById() { + //not supported + $this->assertTrue(true); + } + + function testGetIncomplete() { + //not supported + $this->assertTrue(true); + } +} diff --git a/tests/lib/Files/Cache/Wrapper/CachePermissionsMaskTest.php b/tests/lib/Files/Cache/Wrapper/CachePermissionsMaskTest.php new file mode 100644 index 00000000000..c12b35867ff --- /dev/null +++ b/tests/lib/Files/Cache/Wrapper/CachePermissionsMaskTest.php @@ -0,0 +1,101 @@ +<?php +/** + * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Files\Cache\Wrapper; + +use OCP\Constants; +use Test\Files\Cache\CacheTest; + +/** + * Class CachePermissionsMask + * + * @group DB + * + * @package Test\Files\Cache\Wrapper + */ +class CachePermissionsMaskTest extends CacheTest { + /** + * @var \OC\Files\Cache\Cache $sourceCache + */ + protected $sourceCache; + + public function setUp() { + parent::setUp(); + $this->storage->mkdir('foo'); + $this->sourceCache = $this->cache; + $this->cache = $this->getMaskedCached(Constants::PERMISSION_ALL); + } + + protected function getMaskedCached($mask) { + return new \OC\Files\Cache\Wrapper\CachePermissionsMask($this->sourceCache, $mask); + } + + public function maskProvider() { + return array( + array(Constants::PERMISSION_ALL), + array(Constants::PERMISSION_ALL - Constants::PERMISSION_SHARE), + array(Constants::PERMISSION_ALL - Constants::PERMISSION_UPDATE), + array(Constants::PERMISSION_READ) + ); + } + + /** + * @dataProvider maskProvider + * @param int $mask + */ + public function testGetMasked($mask) { + $cache = $this->getMaskedCached($mask); + $data = array('size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain', 'permissions' => Constants::PERMISSION_ALL); + $this->sourceCache->put('foo', $data); + $result = $cache->get('foo'); + $this->assertEquals($mask, $result['permissions']); + + $data = array('size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain', 'permissions' => Constants::PERMISSION_ALL - Constants::PERMISSION_DELETE); + $this->sourceCache->put('bar', $data); + $result = $cache->get('bar'); + $this->assertEquals($mask & ~Constants::PERMISSION_DELETE, $result['permissions']); + } + + /** + * @dataProvider maskProvider + * @param int $mask + */ + public function testGetFolderContentMasked($mask) { + $this->storage->mkdir('foo'); + $this->storage->file_put_contents('foo/bar', 'asd'); + $this->storage->file_put_contents('foo/asd', 'bar'); + $this->storage->getScanner()->scan(''); + + $cache = $this->getMaskedCached($mask); + $files = $cache->getFolderContents('foo'); + $this->assertCount(2, $files); + + foreach ($files as $file) { + $this->assertEquals($mask & ~Constants::PERMISSION_CREATE, $file['permissions']); + } + } + + /** + * @dataProvider maskProvider + * @param int $mask + */ + public function testSearchMasked($mask) { + $this->storage->mkdir('foo'); + $this->storage->file_put_contents('foo/bar', 'asd'); + $this->storage->file_put_contents('foo/foobar', 'bar'); + $this->storage->getScanner()->scan(''); + + $cache = $this->getMaskedCached($mask); + $files = $cache->search('%bar'); + $this->assertCount(2, $files); + + foreach ($files as $file) { + $this->assertEquals($mask & ~Constants::PERMISSION_CREATE, $file['permissions']); + } + } +} |