FolderTest.php 33 KB

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