FolderTest.php 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace Test\Files\Node;
  8. use OC\Files\Cache\Cache;
  9. use OC\Files\Cache\CacheEntry;
  10. use OC\Files\Config\CachedMountInfo;
  11. use OC\Files\FileInfo;
  12. use OC\Files\Mount\Manager;
  13. use OC\Files\Mount\MountPoint;
  14. use OC\Files\Node\File;
  15. use OC\Files\Node\Folder;
  16. use OC\Files\Node\Node;
  17. use OC\Files\Node\Root;
  18. use OC\Files\Search\SearchComparison;
  19. use OC\Files\Search\SearchOrder;
  20. use OC\Files\Search\SearchQuery;
  21. use OC\Files\Storage\Temporary;
  22. use OC\Files\Storage\Wrapper\Jail;
  23. use OCP\Files\Cache\ICacheEntry;
  24. use OCP\Files\IRootFolder;
  25. use OCP\Files\Mount\IMountPoint;
  26. use OCP\Files\NotFoundException;
  27. use OCP\Files\Search\ISearchComparison;
  28. use OCP\Files\Search\ISearchOrder;
  29. use OCP\Files\Storage;
  30. use PHPUnit\Framework\MockObject\MockObject;
  31. /**
  32. * Class FolderTest
  33. *
  34. * @group DB
  35. *
  36. * @package Test\Files\Node
  37. */
  38. class FolderTest extends NodeTest {
  39. protected function createTestNode($root, $view, $path, array $data = [], $internalPath = '', $storage = null) {
  40. $view->expects($this->any())
  41. ->method('getRoot')
  42. ->willReturn('');
  43. if ($data || $internalPath || $storage) {
  44. return new Folder($root, $view, $path, $this->getFileInfo($data, $internalPath, $storage));
  45. } else {
  46. return new Folder($root, $view, $path);
  47. }
  48. }
  49. protected function getNodeClass() {
  50. return '\OC\Files\Node\Folder';
  51. }
  52. protected function getNonExistingNodeClass() {
  53. return '\OC\Files\Node\NonExistingFolder';
  54. }
  55. protected function getViewDeleteMethod() {
  56. return 'rmdir';
  57. }
  58. public function testGetDirectoryContent() {
  59. $manager = $this->createMock(Manager::class);
  60. /**
  61. * @var \OC\Files\View | \PHPUnit\Framework\MockObject\MockObject $view
  62. */
  63. $root = $this->getMockBuilder(Root::class)
  64. ->setConstructorArgs([$manager, $this->view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  65. ->getMock();
  66. $root->expects($this->any())
  67. ->method('getUser')
  68. ->willReturn($this->user);
  69. $this->view->expects($this->any())
  70. ->method('getDirectoryContent')
  71. ->with('/bar/foo')
  72. ->willReturn([
  73. new FileInfo('/bar/foo/asd', null, 'foo/asd', ['fileid' => 2, 'path' => '/bar/foo/asd', 'name' => 'asd', 'size' => 100, 'mtime' => 50, 'mimetype' => 'text/plain'], null),
  74. new FileInfo('/bar/foo/qwerty', null, 'foo/qwerty', ['fileid' => 3, 'path' => '/bar/foo/qwerty', 'name' => 'qwerty', 'size' => 200, 'mtime' => 55, 'mimetype' => 'httpd/unix-directory'], null),
  75. ]);
  76. $this->view->method('getFileInfo')
  77. ->willReturn($this->createMock(FileInfo::class));
  78. $this->view->method('getRelativePath')
  79. ->willReturn('/bar/foo');
  80. $node = new Folder($root, $this->view, '/bar/foo');
  81. $children = $node->getDirectoryListing();
  82. $this->assertEquals(2, count($children));
  83. $this->assertInstanceOf('\OC\Files\Node\File', $children[0]);
  84. $this->assertInstanceOf('\OC\Files\Node\Folder', $children[1]);
  85. $this->assertEquals('asd', $children[0]->getName());
  86. $this->assertEquals('qwerty', $children[1]->getName());
  87. $this->assertEquals(2, $children[0]->getId());
  88. $this->assertEquals(3, $children[1]->getId());
  89. }
  90. public function testGet() {
  91. $manager = $this->createMock(Manager::class);
  92. $view = $this->getRootViewMock();
  93. $root = $this->getMockBuilder(Root::class)
  94. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  95. ->getMock();
  96. $root->expects($this->any())
  97. ->method('getUser')
  98. ->willReturn($this->user);
  99. $node = new File($root, $view, '/bar/foo/asd');
  100. $root->method('get')
  101. ->with('/bar/foo/asd')
  102. ->willReturn($node);
  103. $parentNode = new Folder($root, $view, '/bar/foo');
  104. self::assertEquals($node, $parentNode->get('asd'));
  105. }
  106. public function testNodeExists() {
  107. $manager = $this->createMock(Manager::class);
  108. $view = $this->getRootViewMock();
  109. $root = $this->getMockBuilder(Root::class)
  110. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  111. ->getMock();
  112. $root->expects($this->any())
  113. ->method('getUser')
  114. ->willReturn($this->user);
  115. $child = new Folder($root, $view, '/bar/foo/asd');
  116. $root->method('get')
  117. ->with('/bar/foo/asd')
  118. ->willReturn($child);
  119. $node = new Folder($root, $view, '/bar/foo');
  120. $this->assertTrue($node->nodeExists('asd'));
  121. }
  122. public function testNodeExistsNotExists() {
  123. $manager = $this->createMock(Manager::class);
  124. $view = $this->getRootViewMock();
  125. $root = $this->getMockBuilder(Root::class)
  126. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  127. ->getMock();
  128. $root->expects($this->any())
  129. ->method('getUser')
  130. ->willReturn($this->user);
  131. $root->method('get')
  132. ->with('/bar/foo/asd')
  133. ->will($this->throwException(new NotFoundException()));
  134. $node = new Folder($root, $view, '/bar/foo');
  135. $this->assertFalse($node->nodeExists('asd'));
  136. }
  137. public function testNewFolder() {
  138. $manager = $this->createMock(Manager::class);
  139. $view = $this->getRootViewMock();
  140. $root = $this->getMockBuilder(Root::class)
  141. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  142. ->getMock();
  143. $root->expects($this->any())
  144. ->method('getUser')
  145. ->willReturn($this->user);
  146. $view->method('getFileInfo')
  147. ->with('/bar/foo')
  148. ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL]));
  149. $view->method('mkdir')
  150. ->with('/bar/foo/asd')
  151. ->willReturn(true);
  152. $node = new Folder($root, $view, '/bar/foo');
  153. $child = new Folder($root, $view, '/bar/foo/asd', null, $node);
  154. $result = $node->newFolder('asd');
  155. $this->assertEquals($child, $result);
  156. }
  157. public function testNewFolderDeepParent() {
  158. $manager = $this->createMock(Manager::class);
  159. $view = $this->getRootViewMock();
  160. $root = $this->getMockBuilder(Root::class)
  161. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  162. ->getMock();
  163. $root->expects($this->any())
  164. ->method('getUser')
  165. ->willReturn($this->user);
  166. $view->method('getFileInfo')
  167. ->with('/foobar')
  168. ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL]));
  169. $view->method('mkdir')
  170. ->with('/foobar/asd/sdf')
  171. ->willReturn(true);
  172. $node = new Folder($root, $view, '/foobar');
  173. $child = new Folder($root, $view, '/foobar/asd/sdf', null, null);
  174. $result = $node->newFolder('asd/sdf');
  175. $this->assertEquals($child, $result);
  176. }
  177. public function testNewFolderNotPermitted() {
  178. $this->expectException(\OCP\Files\NotPermittedException::class);
  179. $manager = $this->createMock(Manager::class);
  180. $view = $this->getRootViewMock();
  181. $root = $this->getMockBuilder(Root::class)
  182. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  183. ->getMock();
  184. $root->method('getUser')
  185. ->willReturn($this->user);
  186. $view->method('getFileInfo')
  187. ->with('/bar/foo')
  188. ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_READ]));
  189. $node = new Folder($root, $view, '/bar/foo');
  190. $node->newFolder('asd');
  191. }
  192. public function testNewFile() {
  193. $manager = $this->createMock(Manager::class);
  194. $view = $this->getRootViewMock();
  195. $root = $this->getMockBuilder(Root::class)
  196. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  197. ->getMock();
  198. $root->expects($this->any())
  199. ->method('getUser')
  200. ->willReturn($this->user);
  201. $view->method('getFileInfo')
  202. ->with('/bar/foo')
  203. ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_ALL]));
  204. $view->method('touch')
  205. ->with('/bar/foo/asd')
  206. ->willReturn(true);
  207. $node = new Folder($root, $view, '/bar/foo');
  208. $child = new \OC\Files\Node\File($root, $view, '/bar/foo/asd', null, $node);
  209. $result = $node->newFile('asd');
  210. $this->assertEquals($child, $result);
  211. }
  212. public function testNewFileNotPermitted() {
  213. $this->expectException(\OCP\Files\NotPermittedException::class);
  214. $manager = $this->createMock(Manager::class);
  215. $view = $this->getRootViewMock();
  216. $root = $this->getMockBuilder(Root::class)
  217. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  218. ->getMock();
  219. $root->method('getUser')
  220. ->willReturn($this->user);
  221. $view->method('getFileInfo')
  222. ->with('/bar/foo')
  223. ->willReturn($this->getFileInfo(['permissions' => \OCP\Constants::PERMISSION_READ]));
  224. $node = new Folder($root, $view, '/bar/foo');
  225. $node->newFile('asd');
  226. }
  227. public function testGetFreeSpace() {
  228. $manager = $this->createMock(Manager::class);
  229. $view = $this->getRootViewMock();
  230. $root = $this->getMockBuilder(Root::class)
  231. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  232. ->getMock();
  233. $root->method('getUser')
  234. ->willReturn($this->user);
  235. $view->method('free_space')
  236. ->with('/bar/foo')
  237. ->willReturn(100);
  238. $node = new Folder($root, $view, '/bar/foo');
  239. $this->assertEquals(100, $node->getFreeSpace());
  240. }
  241. public function testSearch() {
  242. $manager = $this->createMock(Manager::class);
  243. $view = $this->getRootViewMock();
  244. $root = $this->getMockBuilder(Root::class)
  245. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  246. ->getMock();
  247. $root->method('getUser')
  248. ->willReturn($this->user);
  249. /** @var Storage\IStorage&MockObject $storage */
  250. $storage = $this->createMock(Storage\IStorage::class);
  251. $storage->method('getId')->willReturn('test::1');
  252. $cache = new Cache($storage);
  253. $storage->method('getCache')
  254. ->willReturn($cache);
  255. $storage->expects($this->atLeastOnce())
  256. ->method('getOwner')
  257. ->with('qwerty')
  258. ->willReturn(false);
  259. $mount = $this->createMock(IMountPoint::class);
  260. $mount->expects($this->atLeastOnce())
  261. ->method('getStorage')
  262. ->willReturn($storage);
  263. $mount->expects($this->atLeastOnce())
  264. ->method('getInternalPath')
  265. ->willReturn('foo');
  266. $cache->insert('foo', ['size' => 200, 'mtime' => 55, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]);
  267. $cache->insert('foo/qwerty', ['size' => 200, 'mtime' => 55, 'mimetype' => 'text/plain']);
  268. $root->method('getMountsIn')
  269. ->with('/bar/foo')
  270. ->willReturn([]);
  271. $root->method('getMount')
  272. ->with('/bar/foo')
  273. ->willReturn($mount);
  274. $node = new Folder($root, $view, '/bar/foo');
  275. $result = $node->search('qw');
  276. $cache->clear();
  277. $this->assertEquals(1, count($result));
  278. $this->assertEquals('/bar/foo/qwerty', $result[0]->getPath());
  279. }
  280. public function testSearchInRoot() {
  281. $manager = $this->createMock(Manager::class);
  282. $view = $this->getRootViewMock();
  283. $root = $this->getMockBuilder(Root::class)
  284. ->setMethods(['getUser', 'getMountsIn', 'getMount'])
  285. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  286. ->getMock();
  287. $root->expects($this->any())
  288. ->method('getUser')
  289. ->willReturn($this->user);
  290. /** @var \PHPUnit\Framework\MockObject\MockObject|Storage $storage */
  291. $storage = $this->createMock(Storage::class);
  292. $storage->method('getId')->willReturn('test::2');
  293. $cache = new Cache($storage);
  294. $mount = $this->createMock(IMountPoint::class);
  295. $mount->method('getStorage')
  296. ->willReturn($storage);
  297. $mount->method('getInternalPath')
  298. ->willReturn('files');
  299. $storage->method('getCache')
  300. ->willReturn($cache);
  301. $cache->insert('files', ['size' => 200, 'mtime' => 55, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]);
  302. $cache->insert('files/foo', ['size' => 200, 'mtime' => 55, 'mimetype' => 'text/plain']);
  303. $root->method('getMountsIn')
  304. ->with('')
  305. ->willReturn([]);
  306. $root->method('getMount')
  307. ->with('')
  308. ->willReturn($mount);
  309. $result = $root->search('foo');
  310. $cache->clear();
  311. $this->assertEquals(1, count($result));
  312. $this->assertEquals('/foo', $result[0]->getPath());
  313. }
  314. public function testSearchInStorageRoot() {
  315. $manager = $this->createMock(Manager::class);
  316. $view = $this->getRootViewMock();
  317. $root = $this->getMockBuilder(Root::class)
  318. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  319. ->getMock();
  320. $root->method('getUser')
  321. ->willReturn($this->user);
  322. $storage = $this->createMock(Storage::class);
  323. $storage->method('getId')->willReturn('test::1');
  324. $cache = new Cache($storage);
  325. $mount = $this->createMock(IMountPoint::class);
  326. $mount->method('getStorage')
  327. ->willReturn($storage);
  328. $mount->method('getInternalPath')
  329. ->willReturn('');
  330. $storage->method('getCache')
  331. ->willReturn($cache);
  332. $cache->insert('foo', ['size' => 200, 'mtime' => 55, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]);
  333. $cache->insert('foo/qwerty', ['size' => 200, 'mtime' => 55, 'mimetype' => 'text/plain']);
  334. $root->method('getMountsIn')
  335. ->with('/bar')
  336. ->willReturn([]);
  337. $root->method('getMount')
  338. ->with('/bar')
  339. ->willReturn($mount);
  340. $node = new Folder($root, $view, '/bar');
  341. $result = $node->search('qw');
  342. $cache->clear();
  343. $this->assertEquals(1, count($result));
  344. $this->assertEquals('/bar/foo/qwerty', $result[0]->getPath());
  345. }
  346. public function testSearchSubStorages() {
  347. $manager = $this->createMock(Manager::class);
  348. $view = $this->getRootViewMock();
  349. $root = $this->getMockBuilder(Root::class)
  350. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  351. ->getMock();
  352. $root->expects($this->any())
  353. ->method('getUser')
  354. ->willReturn($this->user);
  355. $storage = $this->createMock(Storage::class);
  356. $storage->method('getId')->willReturn('test::1');
  357. $cache = new Cache($storage);
  358. $subStorage = $this->createMock(Storage::class);
  359. $subStorage->method('getId')->willReturn('test::2');
  360. $subCache = new Cache($subStorage);
  361. $subMount = $this->getMockBuilder(MountPoint::class)->setConstructorArgs([Temporary::class, ''])->getMock();
  362. $mount = $this->createMock(IMountPoint::class);
  363. $mount->method('getStorage')
  364. ->willReturn($storage);
  365. $mount->method('getInternalPath')
  366. ->willReturn('foo');
  367. $subMount->method('getStorage')
  368. ->willReturn($subStorage);
  369. $subMount->method('getMountPoint')
  370. ->willReturn('/bar/foo/bar/');
  371. $storage->method('getCache')
  372. ->willReturn($cache);
  373. $subStorage->method('getCache')
  374. ->willReturn($subCache);
  375. $cache->insert('foo', ['size' => 200, 'mtime' => 55, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]);
  376. $cache->insert('foo/qwerty', ['size' => 200, 'mtime' => 55, 'mimetype' => 'text/plain']);
  377. $subCache->insert('asd', ['size' => 200, 'mtime' => 55, 'mimetype' => ICacheEntry::DIRECTORY_MIMETYPE]);
  378. $subCache->insert('asd/qwerty', ['size' => 200, 'mtime' => 55, 'mimetype' => 'text/plain']);
  379. $root->method('getMountsIn')
  380. ->with('/bar/foo')
  381. ->willReturn([$subMount]);
  382. $root->method('getMount')
  383. ->with('/bar/foo')
  384. ->willReturn($mount);
  385. $node = new Folder($root, $view, '/bar/foo');
  386. $result = $node->search('qw');
  387. $cache->clear();
  388. $subCache->clear();
  389. $this->assertEquals(2, count($result));
  390. }
  391. public function testIsSubNode() {
  392. $rootFolderMock = $this->createMock(IRootFolder::class);
  393. $file = new Node($rootFolderMock, $this->view, '/foo/bar');
  394. $folder = new Folder($rootFolderMock, $this->view, '/foo');
  395. $this->assertTrue($folder->isSubNode($file));
  396. $this->assertFalse($folder->isSubNode($folder));
  397. $file = new Node($rootFolderMock, $this->view, '/foobar');
  398. $this->assertFalse($folder->isSubNode($file));
  399. }
  400. public function testGetById() {
  401. $manager = $this->createMock(Manager::class);
  402. $view = $this->getRootViewMock();
  403. $root = $this->getMockBuilder(Root::class)
  404. ->setMethods(['getMountsIn', 'getMount'])
  405. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  406. ->getMock();
  407. $storage = $this->createMock(\OC\Files\Storage\Storage::class);
  408. $mount = new MountPoint($storage, '/bar');
  409. $storage->method('getId')->willReturn('');
  410. $cache = $this->getMockBuilder(Cache::class)->setConstructorArgs([$storage])->getMock();
  411. $fileInfo = new CacheEntry(['path' => 'foo/qwerty', 'mimetype' => 'text/plain'], null);
  412. $storage->method('getCache')
  413. ->willReturn($cache);
  414. $this->userMountCache->expects($this->any())
  415. ->method('getMountsForFileId')
  416. ->with(1)
  417. ->willReturn([new CachedMountInfo(
  418. $this->user,
  419. 1,
  420. 0,
  421. '/bar/',
  422. 'test',
  423. 1,
  424. ''
  425. )]);
  426. $cache->method('get')
  427. ->with(1)
  428. ->willReturn($fileInfo);
  429. $root->method('getMountsIn')
  430. ->with('/bar/foo')
  431. ->willReturn([]);
  432. $manager->method('getMountsByMountProvider')
  433. ->willReturn([$mount]);
  434. $node = new Folder($root, $view, '/bar/foo');
  435. $result = $node->getById(1);
  436. $this->assertEquals(1, count($result));
  437. $this->assertEquals('/bar/foo/qwerty', $result[0]->getPath());
  438. }
  439. public function testGetByIdMountRoot() {
  440. $manager = $this->createMock(Manager::class);
  441. $view = $this->getRootViewMock();
  442. $root = $this->getMockBuilder(Root::class)
  443. ->setMethods(['getMountsIn', 'getMount'])
  444. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  445. ->getMock();
  446. $storage = $this->createMock(\OC\Files\Storage\Storage::class);
  447. $mount = new MountPoint($storage, '/bar');
  448. $storage->method('getId')->willReturn('');
  449. $cache = $this->getMockBuilder(Cache::class)->setConstructorArgs([$storage])->getMock();
  450. $fileInfo = new CacheEntry(['path' => '', 'mimetype' => 'text/plain'], null);
  451. $storage->method('getCache')
  452. ->willReturn($cache);
  453. $this->userMountCache->expects($this->any())
  454. ->method('getMountsForFileId')
  455. ->with(1)
  456. ->willReturn([new CachedMountInfo(
  457. $this->user,
  458. 1,
  459. 0,
  460. '/bar/',
  461. 'test',
  462. 1,
  463. ''
  464. )]);
  465. $cache->method('get')
  466. ->with(1)
  467. ->willReturn($fileInfo);
  468. $manager->method('getMountsByMountProvider')
  469. ->willReturn([$mount]);
  470. $node = new Folder($root, $view, '/bar');
  471. $result = $node->getById(1);
  472. $this->assertEquals(1, count($result));
  473. $this->assertEquals('/bar', $result[0]->getPath());
  474. }
  475. public function testGetByIdOutsideFolder() {
  476. $manager = $this->createMock(Manager::class);
  477. $view = $this->getRootViewMock();
  478. $root = $this->getMockBuilder(Root::class)
  479. ->setMethods(['getMountsIn', 'getMount'])
  480. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  481. ->getMock();
  482. $storage = $this->createMock(\OC\Files\Storage\Storage::class);
  483. $mount = new MountPoint($storage, '/bar');
  484. $storage->method('getId')->willReturn('');
  485. $cache = $this->getMockBuilder(Cache::class)->setConstructorArgs([$storage])->getMock();
  486. $fileInfo = new CacheEntry(['path' => 'foobar', 'mimetype' => 'text/plain'], null);
  487. $storage->method('getCache')
  488. ->willReturn($cache);
  489. $this->userMountCache->expects($this->any())
  490. ->method('getMountsForFileId')
  491. ->with(1)
  492. ->willReturn([new CachedMountInfo(
  493. $this->user,
  494. 1,
  495. 0,
  496. '/bar/',
  497. 'test',
  498. 1,
  499. ''
  500. )]);
  501. $cache->method('get')
  502. ->with(1)
  503. ->willReturn($fileInfo);
  504. $manager->method('getMountsByMountProvider')
  505. ->willReturn([$mount]);
  506. $node = new Folder($root, $view, '/bar/foo');
  507. $result = $node->getById(1);
  508. $this->assertEquals(0, count($result));
  509. }
  510. public function testGetByIdMultipleStorages() {
  511. $manager = $this->createMock(Manager::class);
  512. $view = $this->getRootViewMock();
  513. $root = $this->getMockBuilder(Root::class)
  514. ->setMethods(['getMountsIn', 'getMount'])
  515. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  516. ->getMock();
  517. $storage = $this->createMock(\OC\Files\Storage\Storage::class);
  518. $mount1 = new MountPoint($storage, '/bar');
  519. $mount2 = new MountPoint($storage, '/bar/foo/asd');
  520. $storage->method('getId')->willReturn('');
  521. $cache = $this->getMockBuilder(Cache::class)->setConstructorArgs([$storage])->getMock();
  522. $fileInfo = new CacheEntry(['path' => 'foo/qwerty', 'mimetype' => 'text/plain'], null);
  523. $storage->method('getCache')
  524. ->willReturn($cache);
  525. $this->userMountCache->method('getMountsForFileId')
  526. ->with(1)
  527. ->willReturn([
  528. new CachedMountInfo(
  529. $this->user,
  530. 1,
  531. 0,
  532. '/bar/',
  533. 'test',
  534. 1,
  535. ''
  536. ),
  537. ]);
  538. $storage->method('getCache')
  539. ->willReturn($cache);
  540. $cache->method('get')
  541. ->with(1)
  542. ->willReturn($fileInfo);
  543. $manager->method('getMountsByMountProvider')
  544. ->willReturn([$mount1, $mount2]);
  545. $node = new Folder($root, $view, '/bar/foo');
  546. $result = $node->getById(1);
  547. $this->assertEquals(2, count($result));
  548. $this->assertEquals('/bar/foo/qwerty', $result[0]->getPath());
  549. $this->assertEquals('/bar/foo/asd/foo/qwerty', $result[1]->getPath());
  550. }
  551. public function uniqueNameProvider() {
  552. return [
  553. // input, existing, expected
  554. ['foo', [], 'foo'],
  555. ['foo', ['foo'], 'foo (2)'],
  556. ['foo', ['foo', 'foo (2)'], 'foo (3)'],
  557. ];
  558. }
  559. /**
  560. * @dataProvider uniqueNameProvider
  561. */
  562. public function testGetUniqueName($name, $existingFiles, $expected) {
  563. $manager = $this->createMock(Manager::class);
  564. $folderPath = '/bar/foo';
  565. $view = $this->getRootViewMock();
  566. $root = $this->getMockBuilder(Root::class)
  567. ->setMethods(['getUser', 'getMountsIn', 'getMount'])
  568. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  569. ->getMock();
  570. $view->expects($this->any())
  571. ->method('file_exists')
  572. ->willReturnCallback(function ($path) use ($existingFiles, $folderPath) {
  573. foreach ($existingFiles as $existing) {
  574. if ($folderPath . '/' . $existing === $path) {
  575. return true;
  576. }
  577. }
  578. return false;
  579. });
  580. $node = new Folder($root, $view, $folderPath);
  581. $this->assertEquals($expected, $node->getNonExistingName($name));
  582. }
  583. public function testRecent(): void {
  584. $manager = $this->createMock(Manager::class);
  585. $folderPath = '/bar/foo';
  586. $view = $this->getRootViewMock();
  587. /** @var \PHPUnit\Framework\MockObject\MockObject|\OC\Files\Node\Root $root */
  588. $root = $this->getMockBuilder(Root::class)
  589. ->setMethods(['getUser', 'getMountsIn', 'getMount'])
  590. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  591. ->getMock();
  592. /** @var \PHPUnit\Framework\MockObject\MockObject|\OC\Files\FileInfo $folderInfo */
  593. $folderInfo = $this->getMockBuilder(FileInfo::class)
  594. ->disableOriginalConstructor()->getMock();
  595. $baseTime = time();
  596. $storage = new Temporary();
  597. $mount = new MountPoint($storage, '');
  598. $folderInfo->expects($this->any())
  599. ->method('getMountPoint')
  600. ->willReturn($mount);
  601. $root->method('getMount')
  602. ->willReturn($mount);
  603. $root->method('getMountsIn')
  604. ->willReturn([]);
  605. $cache = $storage->getCache();
  606. $id1 = $cache->put('bar/foo/inside.txt', [
  607. 'storage_mtime' => $baseTime,
  608. 'mtime' => $baseTime,
  609. 'mimetype' => 'text/plain',
  610. 'size' => 3,
  611. 'permissions' => \OCP\Constants::PERMISSION_ALL,
  612. ]);
  613. $id2 = $cache->put('bar/foo/old.txt', [
  614. 'storage_mtime' => $baseTime - 100,
  615. 'mtime' => $baseTime - 100,
  616. 'mimetype' => 'text/plain',
  617. 'size' => 3,
  618. 'permissions' => \OCP\Constants::PERMISSION_READ,
  619. ]);
  620. $cache->put('bar/asd/outside.txt', [
  621. 'storage_mtime' => $baseTime,
  622. 'mtime' => $baseTime,
  623. 'mimetype' => 'text/plain',
  624. 'size' => 3,
  625. ]);
  626. $id3 = $cache->put('bar/foo/older.txt', [
  627. 'storage_mtime' => $baseTime - 600,
  628. 'mtime' => $baseTime - 600,
  629. 'mimetype' => 'text/plain',
  630. 'size' => 3,
  631. 'permissions' => \OCP\Constants::PERMISSION_ALL,
  632. ]);
  633. $node = new Folder($root, $view, $folderPath, $folderInfo);
  634. $nodes = $node->getRecent(5);
  635. $ids = array_map(function (Node $node) {
  636. return (int)$node->getId();
  637. }, $nodes);
  638. $this->assertEquals([$id1, $id2, $id3], $ids);
  639. }
  640. public function testRecentFolder() {
  641. $manager = $this->createMock(Manager::class);
  642. $folderPath = '/bar/foo';
  643. $view = $this->getRootViewMock();
  644. /** @var \PHPUnit\Framework\MockObject\MockObject|\OC\Files\Node\Root $root */
  645. $root = $this->getMockBuilder(Root::class)
  646. ->setMethods(['getUser', 'getMountsIn', 'getMount'])
  647. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  648. ->getMock();
  649. /** @var \PHPUnit\Framework\MockObject\MockObject|\OC\Files\FileInfo $folderInfo */
  650. $folderInfo = $this->getMockBuilder(FileInfo::class)
  651. ->disableOriginalConstructor()->getMock();
  652. $baseTime = time();
  653. $storage = new Temporary();
  654. $mount = new MountPoint($storage, '');
  655. $folderInfo->expects($this->any())
  656. ->method('getMountPoint')
  657. ->willReturn($mount);
  658. $root->method('getMount')
  659. ->willReturn($mount);
  660. $root->method('getMountsIn')
  661. ->willReturn([]);
  662. $cache = $storage->getCache();
  663. $id1 = $cache->put('bar/foo/folder', [
  664. 'storage_mtime' => $baseTime,
  665. 'mtime' => $baseTime,
  666. 'mimetype' => \OCP\Files\FileInfo::MIMETYPE_FOLDER,
  667. 'size' => 3,
  668. 'permissions' => 0,
  669. ]);
  670. $id2 = $cache->put('bar/foo/folder/bar.txt', [
  671. 'storage_mtime' => $baseTime,
  672. 'mtime' => $baseTime,
  673. 'mimetype' => 'text/plain',
  674. 'size' => 3,
  675. 'parent' => $id1,
  676. 'permissions' => \OCP\Constants::PERMISSION_ALL,
  677. ]);
  678. $id3 = $cache->put('bar/foo/folder/asd.txt', [
  679. 'storage_mtime' => $baseTime - 100,
  680. 'mtime' => $baseTime - 100,
  681. 'mimetype' => 'text/plain',
  682. 'size' => 3,
  683. 'parent' => $id1,
  684. 'permissions' => \OCP\Constants::PERMISSION_ALL,
  685. ]);
  686. $node = new Folder($root, $view, $folderPath, $folderInfo);
  687. $nodes = $node->getRecent(5);
  688. $ids = array_map(function (Node $node) {
  689. return (int)$node->getId();
  690. }, $nodes);
  691. $this->assertEquals([$id2, $id3], $ids);
  692. $this->assertEquals($baseTime, $nodes[0]->getMTime());
  693. $this->assertEquals($baseTime - 100, $nodes[1]->getMTime());
  694. }
  695. public function testRecentJail() {
  696. $manager = $this->createMock(Manager::class);
  697. $folderPath = '/bar/foo';
  698. $view = $this->getRootViewMock();
  699. /** @var \PHPUnit\Framework\MockObject\MockObject|\OC\Files\Node\Root $root */
  700. $root = $this->getMockBuilder(Root::class)
  701. ->setMethods(['getUser', 'getMountsIn', 'getMount'])
  702. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  703. ->getMock();
  704. /** @var \PHPUnit\Framework\MockObject\MockObject|\OC\Files\FileInfo $folderInfo */
  705. $folderInfo = $this->getMockBuilder(FileInfo::class)
  706. ->disableOriginalConstructor()->getMock();
  707. $baseTime = time();
  708. $storage = new Temporary();
  709. $jail = new Jail([
  710. 'storage' => $storage,
  711. 'root' => 'folder',
  712. ]);
  713. $mount = new MountPoint($jail, '/bar/foo');
  714. $folderInfo->expects($this->any())
  715. ->method('getMountPoint')
  716. ->willReturn($mount);
  717. $root->method('getMount')
  718. ->willReturn($mount);
  719. $root->method('getMountsIn')
  720. ->willReturn([]);
  721. $cache = $storage->getCache();
  722. $id1 = $cache->put('folder/inside.txt', [
  723. 'storage_mtime' => $baseTime,
  724. 'mtime' => $baseTime,
  725. 'mimetype' => 'text/plain',
  726. 'size' => 3,
  727. 'permissions' => \OCP\Constants::PERMISSION_ALL,
  728. ]);
  729. $cache->put('outside.txt', [
  730. 'storage_mtime' => $baseTime - 100,
  731. 'mtime' => $baseTime - 100,
  732. 'mimetype' => 'text/plain',
  733. 'size' => 3,
  734. ]);
  735. $node = new Folder($root, $view, $folderPath, $folderInfo);
  736. $nodes = $node->getRecent(5);
  737. $ids = array_map(function (Node $node) {
  738. return (int)$node->getId();
  739. }, $nodes);
  740. $this->assertEquals([$id1], $ids);
  741. }
  742. public function offsetLimitProvider() {
  743. return [
  744. [0, 10, ['/bar/foo/foo1', '/bar/foo/foo2', '/bar/foo/foo3', '/bar/foo/foo4', '/bar/foo/sub1/foo5', '/bar/foo/sub1/foo6', '/bar/foo/sub2/foo7', '/bar/foo/sub2/foo8'], []],
  745. [0, 5, ['/bar/foo/foo1', '/bar/foo/foo2', '/bar/foo/foo3', '/bar/foo/foo4', '/bar/foo/sub1/foo5'], []],
  746. [0, 2, ['/bar/foo/foo1', '/bar/foo/foo2'], []],
  747. [3, 2, ['/bar/foo/foo4', '/bar/foo/sub1/foo5'], []],
  748. [3, 5, ['/bar/foo/foo4', '/bar/foo/sub1/foo5', '/bar/foo/sub1/foo6', '/bar/foo/sub2/foo7', '/bar/foo/sub2/foo8'], []],
  749. [5, 2, ['/bar/foo/sub1/foo6', '/bar/foo/sub2/foo7'], []],
  750. [6, 2, ['/bar/foo/sub2/foo7', '/bar/foo/sub2/foo8'], []],
  751. [7, 2, ['/bar/foo/sub2/foo8'], []],
  752. [10, 2, [], []],
  753. [0, 5, ['/bar/foo/sub2/foo7', '/bar/foo/foo1', '/bar/foo/sub1/foo5', '/bar/foo/foo2', '/bar/foo/foo3'], [new SearchOrder(ISearchOrder::DIRECTION_ASCENDING, 'mtime')]],
  754. [3, 2, ['/bar/foo/foo2', '/bar/foo/foo3'], [new SearchOrder(ISearchOrder::DIRECTION_ASCENDING, 'mtime')]],
  755. [0, 5, ['/bar/foo/sub1/foo5', '/bar/foo/sub1/foo6', '/bar/foo/sub2/foo7', '/bar/foo/foo1', '/bar/foo/foo2'], [
  756. new SearchOrder(ISearchOrder::DIRECTION_DESCENDING, 'size'),
  757. new SearchOrder(ISearchOrder::DIRECTION_ASCENDING, 'mtime')
  758. ]],
  759. ];
  760. }
  761. /**
  762. * @dataProvider offsetLimitProvider
  763. * @param int $offset
  764. * @param int $limit
  765. * @param string[] $expectedPaths
  766. * @param ISearchOrder[] $ordering
  767. * @throws NotFoundException
  768. * @throws \OCP\Files\InvalidPathException
  769. */
  770. public function testSearchSubStoragesLimitOffset(int $offset, int $limit, array $expectedPaths, array $ordering) {
  771. if (!$ordering) {
  772. $ordering = [new SearchOrder(ISearchOrder::DIRECTION_ASCENDING, 'fileid')];
  773. }
  774. $manager = $this->createMock(Manager::class);
  775. $view = $this->getRootViewMock();
  776. $root = $this->getMockBuilder(Root::class)
  777. ->setConstructorArgs([$manager, $view, $this->user, $this->userMountCache, $this->logger, $this->userManager, $this->eventDispatcher, $this->cacheFactory])
  778. ->getMock();
  779. $root->expects($this->any())
  780. ->method('getUser')
  781. ->willReturn($this->user);
  782. $storage = $this->createMock(Storage::class);
  783. $storage->method('getId')->willReturn('test::1');
  784. $cache = new Cache($storage);
  785. $subStorage1 = $this->createMock(Storage::class);
  786. $subStorage1->method('getId')->willReturn('test::2');
  787. $subCache1 = new Cache($subStorage1);
  788. $subMount1 = $this->getMockBuilder(MountPoint::class)->setConstructorArgs([Temporary::class, ''])->getMock();
  789. $subStorage2 = $this->createMock(Storage::class);
  790. $subStorage2->method('getId')->willReturn('test::3');
  791. $subCache2 = new Cache($subStorage2);
  792. $subMount2 = $this->getMockBuilder(MountPoint::class)->setConstructorArgs([Temporary::class, ''])->getMock();
  793. $mount = $this->createMock(IMountPoint::class);
  794. $mount->method('getStorage')
  795. ->willReturn($storage);
  796. $mount->method('getInternalPath')
  797. ->willReturn('foo');
  798. $subMount1->method('getStorage')
  799. ->willReturn($subStorage1);
  800. $subMount1->method('getMountPoint')
  801. ->willReturn('/bar/foo/sub1/');
  802. $storage->method('getCache')
  803. ->willReturn($cache);
  804. $subStorage1->method('getCache')
  805. ->willReturn($subCache1);
  806. $subMount2->method('getStorage')
  807. ->willReturn($subStorage2);
  808. $subMount2->method('getMountPoint')
  809. ->willReturn('/bar/foo/sub2/');
  810. $subStorage2->method('getCache')
  811. ->willReturn($subCache2);
  812. $cache->insert('foo/foo1', ['size' => 200, 'mtime' => 10, 'mimetype' => 'text/plain']);
  813. $cache->insert('foo/foo2', ['size' => 200, 'mtime' => 20, 'mimetype' => 'text/plain']);
  814. $cache->insert('foo/foo3', ['size' => 200, 'mtime' => 30, 'mimetype' => 'text/plain']);
  815. $cache->insert('foo/foo4', ['size' => 200, 'mtime' => 40, 'mimetype' => 'text/plain']);
  816. $subCache1->insert('foo5', ['size' => 300, 'mtime' => 15, 'mimetype' => 'text/plain']);
  817. $subCache1->insert('foo6', ['size' => 300, 'mtime' => 50, 'mimetype' => 'text/plain']);
  818. $subCache2->insert('foo7', ['size' => 200, 'mtime' => 5, 'mimetype' => 'text/plain']);
  819. $subCache2->insert('foo8', ['size' => 200, 'mtime' => 60, 'mimetype' => 'text/plain']);
  820. $root->method('getMountsIn')
  821. ->with('/bar/foo')
  822. ->willReturn([$subMount1, $subMount2]);
  823. $root->method('getMount')
  824. ->with('/bar/foo')
  825. ->willReturn($mount);
  826. $node = new Folder($root, $view, '/bar/foo');
  827. $comparison = new SearchComparison(ISearchComparison::COMPARE_LIKE, 'name', '%foo%');
  828. $query = new SearchQuery($comparison, $limit, $offset, $ordering);
  829. $result = $node->search($query);
  830. $cache->clear();
  831. $subCache1->clear();
  832. $subCache2->clear();
  833. $ids = array_map(function (Node $info) {
  834. return $info->getPath();
  835. }, $result);
  836. $this->assertEquals($expectedPaths, $ids);
  837. }
  838. }