CacheTest.php 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795
  1. <?php
  2. /**
  3. * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
  4. * This file is licensed under the Affero General Public License version 3 or
  5. * later.
  6. * See the COPYING-README file.
  7. */
  8. namespace Test\Files\Cache;
  9. use Doctrine\DBAL\Platforms\MySqlPlatform;
  10. use OC\Files\Cache\Cache;
  11. use OC\Files\Search\SearchComparison;
  12. use OC\Files\Search\SearchQuery;
  13. use OCP\Files\Search\ISearchComparison;
  14. use OCP\IUser;
  15. class LongId extends \OC\Files\Storage\Temporary {
  16. public function getId() {
  17. return 'long:' . str_repeat('foo', 50) . parent::getId();
  18. }
  19. }
  20. /**
  21. * Class CacheTest
  22. *
  23. * @group DB
  24. *
  25. * @package Test\Files\Cache
  26. */
  27. class CacheTest extends \Test\TestCase {
  28. /**
  29. * @var \OC\Files\Storage\Temporary $storage ;
  30. */
  31. protected $storage;
  32. /**
  33. * @var \OC\Files\Storage\Temporary $storage2 ;
  34. */
  35. protected $storage2;
  36. /**
  37. * @var \OC\Files\Cache\Cache $cache
  38. */
  39. protected $cache;
  40. /**
  41. * @var \OC\Files\Cache\Cache $cache2
  42. */
  43. protected $cache2;
  44. public function testGetNumericId() {
  45. $this->assertNotNull($this->cache->getNumericStorageId());
  46. }
  47. public function testSimple() {
  48. $file1 = 'foo';
  49. $file2 = 'foo/bar';
  50. $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder');
  51. $data2 = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file');
  52. $this->assertFalse($this->cache->inCache($file1));
  53. $this->assertEquals($this->cache->get($file1), null);
  54. $id1 = $this->cache->put($file1, $data1);
  55. $this->assertTrue($this->cache->inCache($file1));
  56. $cacheData1 = $this->cache->get($file1);
  57. foreach ($data1 as $key => $value) {
  58. $this->assertEquals($value, $cacheData1[$key]);
  59. }
  60. $this->assertEquals($cacheData1['mimepart'], 'foo');
  61. $this->assertEquals($cacheData1['fileid'], $id1);
  62. $this->assertEquals($id1, $this->cache->getId($file1));
  63. $this->assertFalse($this->cache->inCache($file2));
  64. $id2 = $this->cache->put($file2, $data2);
  65. $this->assertTrue($this->cache->inCache($file2));
  66. $cacheData2 = $this->cache->get($file2);
  67. foreach ($data2 as $key => $value) {
  68. $this->assertEquals($value, $cacheData2[$key]);
  69. }
  70. $this->assertEquals($cacheData1['fileid'], $cacheData2['parent']);
  71. $this->assertEquals($cacheData2['fileid'], $id2);
  72. $this->assertEquals($id2, $this->cache->getId($file2));
  73. $this->assertEquals($id1, $this->cache->getParentId($file2));
  74. $newSize = 1050;
  75. $newId2 = $this->cache->put($file2, array('size' => $newSize));
  76. $cacheData2 = $this->cache->get($file2);
  77. $this->assertEquals($newId2, $id2);
  78. $this->assertEquals($cacheData2['size'], $newSize);
  79. $this->assertEquals($cacheData1, $this->cache->get($file1));
  80. $this->cache->remove($file2);
  81. $this->assertFalse($this->cache->inCache($file2));
  82. $this->assertEquals($this->cache->get($file2), null);
  83. $this->assertTrue($this->cache->inCache($file1));
  84. $this->assertEquals($cacheData1, $this->cache->get($id1));
  85. }
  86. public function testPartial() {
  87. $file1 = 'foo';
  88. $this->cache->put($file1, array('size' => 10));
  89. $this->assertEquals(array('size' => 10), $this->cache->get($file1));
  90. $this->cache->put($file1, array('mtime' => 15));
  91. $this->assertEquals(array('size' => 10, 'mtime' => 15), $this->cache->get($file1));
  92. $this->cache->put($file1, array('size' => 12));
  93. $this->assertEquals(array('size' => 12, 'mtime' => 15), $this->cache->get($file1));
  94. }
  95. /**
  96. * @dataProvider folderDataProvider
  97. */
  98. public function testFolder($folder) {
  99. if (strpos($folder, 'F09F9890')) {
  100. // 4 byte UTF doesn't work on mysql
  101. $params = \OC::$server->getDatabaseConnection()->getParams();
  102. if (\OC::$server->getDatabaseConnection()->getDatabasePlatform() instanceof MySqlPlatform && $params['charset'] !== 'utf8mb4') {
  103. $this->markTestSkipped('MySQL doesn\'t support 4 byte UTF-8');
  104. }
  105. }
  106. $file2 = $folder . '/bar';
  107. $file3 = $folder . '/foo';
  108. $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory');
  109. $fileData = array();
  110. $fileData['bar'] = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file');
  111. $fileData['foo'] = array('size' => 20, 'mtime' => 25, 'mimetype' => 'foo/file');
  112. $this->cache->put($folder, $data1);
  113. $this->cache->put($file2, $fileData['bar']);
  114. $this->cache->put($file3, $fileData['foo']);
  115. $content = $this->cache->getFolderContents($folder);
  116. $this->assertEquals(count($content), 2);
  117. foreach ($content as $cachedData) {
  118. $data = $fileData[$cachedData['name']];
  119. foreach ($data as $name => $value) {
  120. $this->assertEquals($value, $cachedData[$name]);
  121. }
  122. }
  123. $file4 = $folder . '/unkownSize';
  124. $fileData['unkownSize'] = array('size' => -1, 'mtime' => 25, 'mimetype' => 'foo/file');
  125. $this->cache->put($file4, $fileData['unkownSize']);
  126. $this->assertEquals(-1, $this->cache->calculateFolderSize($folder));
  127. $fileData['unkownSize'] = array('size' => 5, 'mtime' => 25, 'mimetype' => 'foo/file');
  128. $this->cache->put($file4, $fileData['unkownSize']);
  129. $this->assertEquals(1025, $this->cache->calculateFolderSize($folder));
  130. $this->cache->remove($file2);
  131. $this->cache->remove($file3);
  132. $this->cache->remove($file4);
  133. $this->assertEquals(0, $this->cache->calculateFolderSize($folder));
  134. $this->cache->remove($folder);
  135. $this->assertFalse($this->cache->inCache($folder . '/foo'));
  136. $this->assertFalse($this->cache->inCache($folder . '/bar'));
  137. }
  138. public function testRemoveRecursive() {
  139. $folderData = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory');
  140. $fileData = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'text/plain');
  141. $folders = ['folder', 'folder/subfolder', 'folder/sub2', 'folder/sub2/sub3'];
  142. $files = ['folder/foo.txt', 'folder/bar.txt', 'folder/subfolder/asd.txt', 'folder/sub2/qwerty.txt', 'folder/sub2/sub3/foo.txt'];
  143. foreach ($folders as $folder) {
  144. $this->cache->put($folder, $folderData);
  145. }
  146. foreach ($files as $file) {
  147. $this->cache->put($file, $fileData);
  148. }
  149. $this->cache->remove('folder');
  150. foreach ($files as $file) {
  151. $this->assertFalse($this->cache->inCache($file));
  152. }
  153. }
  154. public function folderDataProvider() {
  155. return array(
  156. array('folder'),
  157. // that was too easy, try something harder
  158. array('☺, WHITE SMILING FACE, UTF-8 hex E298BA'),
  159. // what about 4 byte utf-8
  160. array('😐, NEUTRAL_FACE, UTF-8 hex F09F9890'),
  161. // now the crazy stuff
  162. array(', UNASSIGNED PRIVATE USE, UTF-8 hex EF9890'),
  163. // and my favorite
  164. 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̡͝')
  165. );
  166. }
  167. public function testEncryptedFolder() {
  168. $file1 = 'folder';
  169. $file2 = 'folder/bar';
  170. $file3 = 'folder/foo';
  171. $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory');
  172. $fileData = array();
  173. $fileData['bar'] = array('size' => 1000, 'encrypted' => 1, 'mtime' => 20, 'mimetype' => 'foo/file');
  174. $fileData['foo'] = array('size' => 20, 'encrypted' => 1, 'mtime' => 25, 'mimetype' => 'foo/file');
  175. $this->cache->put($file1, $data1);
  176. $this->cache->put($file2, $fileData['bar']);
  177. $this->cache->put($file3, $fileData['foo']);
  178. $content = $this->cache->getFolderContents($file1);
  179. $this->assertEquals(count($content), 2);
  180. foreach ($content as $cachedData) {
  181. $data = $fileData[$cachedData['name']];
  182. }
  183. $file4 = 'folder/unkownSize';
  184. $fileData['unkownSize'] = array('size' => -1, 'mtime' => 25, 'mimetype' => 'foo/file');
  185. $this->cache->put($file4, $fileData['unkownSize']);
  186. $this->assertEquals(-1, $this->cache->calculateFolderSize($file1));
  187. $fileData['unkownSize'] = array('size' => 5, 'mtime' => 25, 'mimetype' => 'foo/file');
  188. $this->cache->put($file4, $fileData['unkownSize']);
  189. $this->assertEquals(1025, $this->cache->calculateFolderSize($file1));
  190. // direct cache entry retrieval returns the original values
  191. $entry = $this->cache->get($file1);
  192. $this->assertEquals(1025, $entry['size']);
  193. $this->cache->remove($file2);
  194. $this->cache->remove($file3);
  195. $this->cache->remove($file4);
  196. $this->assertEquals(0, $this->cache->calculateFolderSize($file1));
  197. $this->cache->remove('folder');
  198. $this->assertFalse($this->cache->inCache('folder/foo'));
  199. $this->assertFalse($this->cache->inCache('folder/bar'));
  200. }
  201. public function testRootFolderSizeForNonHomeStorage() {
  202. $dir1 = 'knownsize';
  203. $dir2 = 'unknownsize';
  204. $fileData = array();
  205. $fileData[''] = array('size' => -1, 'mtime' => 20, 'mimetype' => 'httpd/unix-directory');
  206. $fileData[$dir1] = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'httpd/unix-directory');
  207. $fileData[$dir2] = array('size' => -1, 'mtime' => 25, 'mimetype' => 'httpd/unix-directory');
  208. $this->cache->put('', $fileData['']);
  209. $this->cache->put($dir1, $fileData[$dir1]);
  210. $this->cache->put($dir2, $fileData[$dir2]);
  211. $this->assertTrue($this->cache->inCache($dir1));
  212. $this->assertTrue($this->cache->inCache($dir2));
  213. // check that root size ignored the unknown sizes
  214. $this->assertEquals(-1, $this->cache->calculateFolderSize(''));
  215. // clean up
  216. $this->cache->remove('');
  217. $this->cache->remove($dir1);
  218. $this->cache->remove($dir2);
  219. $this->assertFalse($this->cache->inCache($dir1));
  220. $this->assertFalse($this->cache->inCache($dir2));
  221. }
  222. function testStatus() {
  223. $this->assertEquals(\OC\Files\Cache\Cache::NOT_FOUND, $this->cache->getStatus('foo'));
  224. $this->cache->put('foo', array('size' => -1));
  225. $this->assertEquals(\OC\Files\Cache\Cache::PARTIAL, $this->cache->getStatus('foo'));
  226. $this->cache->put('foo', array('size' => -1, 'mtime' => 20, 'mimetype' => 'foo/file'));
  227. $this->assertEquals(\OC\Files\Cache\Cache::SHALLOW, $this->cache->getStatus('foo'));
  228. $this->cache->put('foo', array('size' => 10));
  229. $this->assertEquals(\OC\Files\Cache\Cache::COMPLETE, $this->cache->getStatus('foo'));
  230. }
  231. public function putWithAllKindOfQuotesData() {
  232. return [
  233. ['`backtick`'],
  234. ['´forward´'],
  235. ['\'single\''],
  236. ];
  237. }
  238. /**
  239. * @dataProvider putWithAllKindOfQuotesData
  240. * @param $fileName
  241. */
  242. public function testPutWithAllKindOfQuotes($fileName) {
  243. $this->assertEquals(\OC\Files\Cache\Cache::NOT_FOUND, $this->cache->get($fileName));
  244. $this->cache->put($fileName, array('size' => 20, 'mtime' => 25, 'mimetype' => 'foo/file', 'etag' => $fileName));
  245. $cacheEntry = $this->cache->get($fileName);
  246. $this->assertEquals($fileName, $cacheEntry['etag']);
  247. $this->assertEquals($fileName, $cacheEntry['path']);
  248. }
  249. function testSearch() {
  250. $file1 = 'folder';
  251. $file2 = 'folder/foobar';
  252. $file3 = 'folder/foo';
  253. $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder');
  254. $fileData = array();
  255. $fileData['foobar'] = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file');
  256. $fileData['foo'] = array('size' => 20, 'mtime' => 25, 'mimetype' => 'foo/file');
  257. $this->cache->put($file1, $data1);
  258. $this->cache->put($file2, $fileData['foobar']);
  259. $this->cache->put($file3, $fileData['foo']);
  260. $this->assertEquals(2, count($this->cache->search('%foo%')));
  261. $this->assertEquals(1, count($this->cache->search('foo')));
  262. $this->assertEquals(1, count($this->cache->search('%folder%')));
  263. $this->assertEquals(1, count($this->cache->search('folder%')));
  264. $this->assertEquals(3, count($this->cache->search('%')));
  265. // case insensitive search should match the same files
  266. $this->assertEquals(2, count($this->cache->search('%Foo%')));
  267. $this->assertEquals(1, count($this->cache->search('Foo')));
  268. $this->assertEquals(1, count($this->cache->search('%Folder%')));
  269. $this->assertEquals(1, count($this->cache->search('Folder%')));
  270. $this->assertEquals(3, count($this->cache->searchByMime('foo')));
  271. $this->assertEquals(2, count($this->cache->searchByMime('foo/file')));
  272. }
  273. function testSearchByTag() {
  274. $userId = $this->getUniqueId('user');
  275. \OC::$server->getUserManager()->createUser($userId, $userId);
  276. $this->loginAsUser($userId);
  277. $user = new \OC\User\User($userId, null);
  278. $file1 = 'folder';
  279. $file2 = 'folder/foobar';
  280. $file3 = 'folder/foo';
  281. $file4 = 'folder/foo2';
  282. $file5 = 'folder/foo3';
  283. $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder');
  284. $fileData = array();
  285. $fileData['foobar'] = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file');
  286. $fileData['foo'] = array('size' => 20, 'mtime' => 25, 'mimetype' => 'foo/file');
  287. $fileData['foo2'] = array('size' => 25, 'mtime' => 28, 'mimetype' => 'foo/file');
  288. $fileData['foo3'] = array('size' => 88, 'mtime' => 34, 'mimetype' => 'foo/file');
  289. $id1 = $this->cache->put($file1, $data1);
  290. $id2 = $this->cache->put($file2, $fileData['foobar']);
  291. $id3 = $this->cache->put($file3, $fileData['foo']);
  292. $id4 = $this->cache->put($file4, $fileData['foo2']);
  293. $id5 = $this->cache->put($file5, $fileData['foo3']);
  294. $tagManager = \OC::$server->getTagManager()->load('files', [], false, $userId);
  295. $this->assertTrue($tagManager->tagAs($id1, 'tag1'));
  296. $this->assertTrue($tagManager->tagAs($id1, 'tag2'));
  297. $this->assertTrue($tagManager->tagAs($id2, 'tag2'));
  298. $this->assertTrue($tagManager->tagAs($id3, 'tag1'));
  299. $this->assertTrue($tagManager->tagAs($id4, 'tag2'));
  300. // use tag name
  301. $results = $this->cache->searchByTag('tag1', $userId);
  302. $this->assertEquals(2, count($results));
  303. usort($results, function ($value1, $value2) {
  304. return $value1['name'] >= $value2['name'];
  305. });
  306. $this->assertEquals('folder', $results[0]['name']);
  307. $this->assertEquals('foo', $results[1]['name']);
  308. // use tag id
  309. $tags = $tagManager->getTagsForUser($userId);
  310. $this->assertNotEmpty($tags);
  311. $tags = array_filter($tags, function ($tag) {
  312. return $tag->getName() === 'tag2';
  313. });
  314. $results = $this->cache->searchByTag(current($tags)->getId(), $userId);
  315. $this->assertEquals(3, count($results));
  316. usort($results, function ($value1, $value2) {
  317. return $value1['name'] >= $value2['name'];
  318. });
  319. $this->assertEquals('folder', $results[0]['name']);
  320. $this->assertEquals('foo2', $results[1]['name']);
  321. $this->assertEquals('foobar', $results[2]['name']);
  322. $tagManager->delete('tag1');
  323. $tagManager->delete('tag2');
  324. $this->logout();
  325. $user = \OC::$server->getUserManager()->get($userId);
  326. if ($user !== null) {
  327. $user->delete();
  328. }
  329. }
  330. function testSearchQueryByTag() {
  331. $userId = static::getUniqueID('user');
  332. \OC::$server->getUserManager()->createUser($userId, $userId);
  333. static::loginAsUser($userId);
  334. $user = new \OC\User\User($userId, null);
  335. $file1 = 'folder';
  336. $file2 = 'folder/foobar';
  337. $file3 = 'folder/foo';
  338. $file4 = 'folder/foo2';
  339. $file5 = 'folder/foo3';
  340. $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder');
  341. $fileData = array();
  342. $fileData['foobar'] = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file');
  343. $fileData['foo'] = array('size' => 20, 'mtime' => 25, 'mimetype' => 'foo/file');
  344. $fileData['foo2'] = array('size' => 25, 'mtime' => 28, 'mimetype' => 'foo/file');
  345. $fileData['foo3'] = array('size' => 88, 'mtime' => 34, 'mimetype' => 'foo/file');
  346. $id1 = $this->cache->put($file1, $data1);
  347. $id2 = $this->cache->put($file2, $fileData['foobar']);
  348. $id3 = $this->cache->put($file3, $fileData['foo']);
  349. $id4 = $this->cache->put($file4, $fileData['foo2']);
  350. $id5 = $this->cache->put($file5, $fileData['foo3']);
  351. $tagManager = \OC::$server->getTagManager()->load('files', [], false, $userId);
  352. $this->assertTrue($tagManager->tagAs($id1, 'tag1'));
  353. $this->assertTrue($tagManager->tagAs($id1, 'tag2'));
  354. $this->assertTrue($tagManager->tagAs($id2, 'tag2'));
  355. $this->assertTrue($tagManager->tagAs($id3, 'tag1'));
  356. $this->assertTrue($tagManager->tagAs($id4, 'tag2'));
  357. $results = $this->cache->searchQuery(new SearchQuery(
  358. new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'tagname', 'tag2'),
  359. 0, 0, [], $user
  360. ));
  361. $this->assertEquals(3, count($results));
  362. usort($results, function ($value1, $value2) {
  363. return $value1['name'] >= $value2['name'];
  364. });
  365. $this->assertEquals('folder', $results[0]['name']);
  366. $this->assertEquals('foo2', $results[1]['name']);
  367. $this->assertEquals('foobar', $results[2]['name']);
  368. $tagManager->delete('tag1');
  369. $tagManager->delete('tag2');
  370. static::logout();
  371. $user = \OC::$server->getUserManager()->get($userId);
  372. if ($user !== null) {
  373. $user->delete();
  374. }
  375. }
  376. function testSearchByQuery() {
  377. $file1 = 'folder';
  378. $file2 = 'folder/foobar';
  379. $file3 = 'folder/foo';
  380. $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder');
  381. $fileData = array();
  382. $fileData['foobar'] = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file');
  383. $fileData['foo'] = array('size' => 20, 'mtime' => 25, 'mimetype' => 'foo/file');
  384. $this->cache->put($file1, $data1);
  385. $this->cache->put($file2, $fileData['foobar']);
  386. $this->cache->put($file3, $fileData['foo']);
  387. /** @var IUser $user */
  388. $user = $this->createMock(IUser::class);
  389. $this->assertCount(1, $this->cache->searchQuery(new SearchQuery(
  390. new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'name', 'foo')
  391. , 10, 0, [], $user)));
  392. $this->assertCount(2, $this->cache->searchQuery(new SearchQuery(
  393. new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', 'foo%')
  394. , 10, 0, [], $user)));
  395. $this->assertCount(2, $this->cache->searchQuery(new SearchQuery(
  396. new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', 'foo/file')
  397. , 10, 0, [], $user)));
  398. $this->assertCount(3, $this->cache->searchQuery(new SearchQuery(
  399. new SearchComparison(ISearchComparison::COMPARE_LIKE, 'mimetype', 'foo/%')
  400. , 10, 0, [], $user)));
  401. $this->assertCount(1, $this->cache->searchQuery(new SearchQuery(
  402. new SearchComparison(ISearchComparison::COMPARE_GREATER_THAN, 'size', 100)
  403. , 10, 0, [], $user)));
  404. $this->assertCount(2, $this->cache->searchQuery(new SearchQuery(
  405. new SearchComparison(ISearchComparison::COMPARE_GREATER_THAN_EQUAL, 'size', 100)
  406. , 10, 0, [], $user)));
  407. }
  408. function movePathProvider() {
  409. return [
  410. ['folder/foo', 'folder/foobar', ['1', '2']],
  411. ['folder/foo', 'foo', ['1', '2']],
  412. ['files/Индустрия_Инженерные системы ЦОД', 'files/Индустрия_Инженерные системы ЦОД1', ['1', '2']],
  413. ];
  414. }
  415. /**
  416. * @dataProvider movePathProvider
  417. */
  418. function testMove($sourceFolder, $targetFolder, $children) {
  419. $data = array('size' => 100, 'mtime' => 50, 'mimetype' => 'foo/bar');
  420. $folderData = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory');
  421. // create folders
  422. foreach ([$sourceFolder, $targetFolder] as $current) {
  423. while (strpos($current, '/') > 0) {
  424. $current = dirname($current);
  425. $this->cache->put($current, $folderData);
  426. $this->cache2->put($current, $folderData);
  427. }
  428. }
  429. $this->cache->put($sourceFolder, $folderData);
  430. $this->cache2->put($sourceFolder, $folderData);
  431. foreach ($children as $child) {
  432. $this->cache->put($sourceFolder . '/' . $child, $data);
  433. $this->cache2->put($sourceFolder . '/' . $child, $data);
  434. }
  435. $this->cache->move($sourceFolder, $targetFolder);
  436. $this->assertFalse($this->cache->inCache($sourceFolder));
  437. $this->assertTrue($this->cache2->inCache($sourceFolder));
  438. $this->assertTrue($this->cache->inCache($targetFolder));
  439. $this->assertFalse($this->cache2->inCache($targetFolder));
  440. foreach ($children as $child) {
  441. $this->assertFalse($this->cache->inCache($sourceFolder . '/' . $child));
  442. $this->assertTrue($this->cache2->inCache($sourceFolder . '/' . $child));
  443. $this->assertTrue($this->cache->inCache($targetFolder . '/' . $child));
  444. $this->assertFalse($this->cache2->inCache($targetFolder . '/' . $child));
  445. }
  446. }
  447. function testGetIncomplete() {
  448. $file1 = 'folder1';
  449. $file2 = 'folder2';
  450. $file3 = 'folder3';
  451. $file4 = 'folder4';
  452. $data = array('size' => 10, 'mtime' => 50, 'mimetype' => 'foo/bar');
  453. $this->cache->put($file1, $data);
  454. $data['size'] = -1;
  455. $this->cache->put($file2, $data);
  456. $this->cache->put($file3, $data);
  457. $data['size'] = 12;
  458. $this->cache->put($file4, $data);
  459. $this->assertEquals($file3, $this->cache->getIncomplete());
  460. }
  461. function testNonExisting() {
  462. $this->assertFalse($this->cache->get('foo.txt'));
  463. $this->assertEquals(array(), $this->cache->getFolderContents('foo'));
  464. }
  465. function testGetById() {
  466. $storageId = $this->storage->getId();
  467. $data = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file');
  468. $id = $this->cache->put('foo', $data);
  469. if (strlen($storageId) > 64) {
  470. $storageId = md5($storageId);
  471. }
  472. $this->assertEquals(array($storageId, 'foo'), \OC\Files\Cache\Cache::getById($id));
  473. }
  474. function testStorageMTime() {
  475. $data = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file');
  476. $this->cache->put('foo', $data);
  477. $cachedData = $this->cache->get('foo');
  478. $this->assertEquals($data['mtime'], $cachedData['storage_mtime']); //if no storage_mtime is saved, mtime should be used
  479. $this->cache->put('foo', array('storage_mtime' => 30)); //when setting storage_mtime, mtime is also set
  480. $cachedData = $this->cache->get('foo');
  481. $this->assertEquals(30, $cachedData['storage_mtime']);
  482. $this->assertEquals(30, $cachedData['mtime']);
  483. $this->cache->put('foo', array('mtime' => 25)); //setting mtime does not change storage_mtime
  484. $cachedData = $this->cache->get('foo');
  485. $this->assertEquals(30, $cachedData['storage_mtime']);
  486. $this->assertEquals(25, $cachedData['mtime']);
  487. }
  488. function testLongId() {
  489. $storage = new LongId(array());
  490. $cache = $storage->getCache();
  491. $storageId = $storage->getId();
  492. $data = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file');
  493. $id = $cache->put('foo', $data);
  494. $this->assertEquals(array(md5($storageId), 'foo'), \OC\Files\Cache\Cache::getById($id));
  495. }
  496. /**
  497. * this test show the bug resulting if we have no normalizer installed
  498. */
  499. public function testWithoutNormalizer() {
  500. // folder name "Schön" with U+00F6 (normalized)
  501. $folderWith00F6 = "\x53\x63\x68\xc3\xb6\x6e";
  502. // folder name "Schön" with U+0308 (un-normalized)
  503. $folderWith0308 = "\x53\x63\x68\x6f\xcc\x88\x6e";
  504. /**
  505. * @var \OC\Files\Cache\Cache | \PHPUnit_Framework_MockObject_MockObject $cacheMock
  506. */
  507. $cacheMock = $this->getMockBuilder(Cache::class)
  508. ->setMethods(['normalize'])
  509. ->setConstructorArgs([$this->storage])
  510. ->getMock();
  511. $cacheMock->expects($this->any())
  512. ->method('normalize')
  513. ->will($this->returnArgument(0));
  514. $data = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory');
  515. // put root folder
  516. $this->assertFalse($cacheMock->get('folder'));
  517. $this->assertGreaterThan(0, $cacheMock->put('folder', $data));
  518. // put un-normalized folder
  519. $this->assertFalse($cacheMock->get('folder/' . $folderWith0308));
  520. $this->assertGreaterThan(0, $cacheMock->put('folder/' . $folderWith0308, $data));
  521. // get un-normalized folder by name
  522. $unNormalizedFolderName = $cacheMock->get('folder/' . $folderWith0308);
  523. // check if database layer normalized the folder name (this should not happen)
  524. $this->assertEquals($folderWith0308, $unNormalizedFolderName['name']);
  525. // put normalized folder
  526. $this->assertFalse($cacheMock->get('folder/' . $folderWith00F6));
  527. $this->assertGreaterThan(0, $cacheMock->put('folder/' . $folderWith00F6, $data));
  528. // this is our bug, we have two different hashes with the same name (Schön)
  529. $this->assertEquals(2, count($cacheMock->getFolderContents('folder')));
  530. }
  531. /**
  532. * this test shows that there is no bug if we use the normalizer
  533. */
  534. public function testWithNormalizer() {
  535. if (!class_exists('Patchwork\PHP\Shim\Normalizer')) {
  536. $this->markTestSkipped('The 3rdparty Normalizer extension is not available.');
  537. return;
  538. }
  539. // folder name "Schön" with U+00F6 (normalized)
  540. $folderWith00F6 = "\x53\x63\x68\xc3\xb6\x6e";
  541. // folder name "Schön" with U+0308 (un-normalized)
  542. $folderWith0308 = "\x53\x63\x68\x6f\xcc\x88\x6e";
  543. $data = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory');
  544. // put root folder
  545. $this->assertFalse($this->cache->get('folder'));
  546. $this->assertGreaterThan(0, $this->cache->put('folder', $data));
  547. // put un-normalized folder
  548. $this->assertFalse($this->cache->get('folder/' . $folderWith0308));
  549. $this->assertGreaterThan(0, $this->cache->put('folder/' . $folderWith0308, $data));
  550. // get un-normalized folder by name
  551. $unNormalizedFolderName = $this->cache->get('folder/' . $folderWith0308);
  552. // check if folder name was normalized
  553. $this->assertEquals($folderWith00F6, $unNormalizedFolderName['name']);
  554. // put normalized folder
  555. $this->assertInstanceOf('\OCP\Files\Cache\ICacheEntry', $this->cache->get('folder/' . $folderWith00F6));
  556. $this->assertGreaterThan(0, $this->cache->put('folder/' . $folderWith00F6, $data));
  557. // at this point we should have only one folder named "Schön"
  558. $this->assertEquals(1, count($this->cache->getFolderContents('folder')));
  559. }
  560. function bogusPathNamesProvider() {
  561. return array(
  562. array('/bogus.txt', 'bogus.txt'),
  563. array('//bogus.txt', 'bogus.txt'),
  564. array('bogus/', 'bogus'),
  565. array('bogus//', 'bogus'),
  566. );
  567. }
  568. /**
  569. * Test bogus paths with leading or doubled slashes
  570. *
  571. * @dataProvider bogusPathNamesProvider
  572. */
  573. public function testBogusPaths($bogusPath, $fixedBogusPath) {
  574. $data = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory');
  575. // put root folder
  576. $this->assertFalse($this->cache->get(''));
  577. $parentId = $this->cache->put('', $data);
  578. $this->assertGreaterThan(0, $parentId);
  579. $this->assertGreaterThan(0, $this->cache->put($bogusPath, $data));
  580. $newData = $this->cache->get($fixedBogusPath);
  581. $this->assertNotFalse($newData);
  582. $this->assertEquals($fixedBogusPath, $newData['path']);
  583. // parent is the correct one, resolved properly (they used to not be)
  584. $this->assertEquals($parentId, $newData['parent']);
  585. $newDataFromBogus = $this->cache->get($bogusPath);
  586. // same entry
  587. $this->assertEquals($newData, $newDataFromBogus);
  588. }
  589. public function testNoReuseOfFileId() {
  590. $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain');
  591. $this->cache->put('somefile.txt', $data1);
  592. $info = $this->cache->get('somefile.txt');
  593. $fileId = $info['fileid'];
  594. $this->cache->remove('somefile.txt');
  595. $data2 = array('size' => 200, 'mtime' => 100, 'mimetype' => 'text/plain');
  596. $this->cache->put('anotherfile.txt', $data2);
  597. $info2 = $this->cache->get('anotherfile.txt');
  598. $fileId2 = $info2['fileid'];
  599. $this->assertNotEquals($fileId, $fileId2);
  600. }
  601. public function escapingProvider() {
  602. return [
  603. ['foo'],
  604. ['o%'],
  605. ['oth_r'],
  606. ];
  607. }
  608. /**
  609. * @param string $name
  610. * @dataProvider escapingProvider
  611. */
  612. public function testEscaping($name) {
  613. $data = array('size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain');
  614. $this->cache->put($name, $data);
  615. $this->assertTrue($this->cache->inCache($name));
  616. $retrievedData = $this->cache->get($name);
  617. foreach ($data as $key => $value) {
  618. $this->assertEquals($value, $retrievedData[$key]);
  619. }
  620. $this->cache->move($name, $name . 'asd');
  621. $this->assertFalse($this->cache->inCache($name));
  622. $this->assertTrue($this->cache->inCache($name . 'asd'));
  623. $this->cache->remove($name . 'asd');
  624. $this->assertFalse($this->cache->inCache($name . 'asd'));
  625. $folderData = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory');
  626. $this->cache->put($name, $folderData);
  627. $this->cache->put('other', $folderData);
  628. $childs = ['asd', 'bar', 'foo', 'sub/folder'];
  629. $this->cache->put($name . '/sub', $folderData);
  630. $this->cache->put('other/sub', $folderData);
  631. foreach ($childs as $child) {
  632. $this->cache->put($name . '/' . $child, $data);
  633. $this->cache->put('other/' . $child, $data);
  634. $this->assertTrue($this->cache->inCache($name . '/' . $child));
  635. }
  636. $this->cache->move($name, $name . 'asd');
  637. foreach ($childs as $child) {
  638. $this->assertTrue($this->cache->inCache($name . 'asd/' . $child));
  639. $this->assertTrue($this->cache->inCache('other/' . $child));
  640. }
  641. foreach ($childs as $child) {
  642. $this->cache->remove($name . 'asd/' . $child);
  643. $this->assertFalse($this->cache->inCache($name . 'asd/' . $child));
  644. $this->assertTrue($this->cache->inCache('other/' . $child));
  645. }
  646. }
  647. protected function tearDown() {
  648. if ($this->cache) {
  649. $this->cache->clear();
  650. }
  651. parent::tearDown();
  652. }
  653. protected function setUp() {
  654. parent::setUp();
  655. $this->storage = new \OC\Files\Storage\Temporary(array());
  656. $this->storage2 = new \OC\Files\Storage\Temporary(array());
  657. $this->cache = new \OC\Files\Cache\Cache($this->storage);
  658. $this->cache2 = new \OC\Files\Cache\Cache($this->storage2);
  659. }
  660. }