You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

520 lines
17 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Björn Schießle <bjoern@schiessle.org>
  6. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  7. * @author Joas Schilling <coding@schilljs.com>
  8. * @author Jörn Friedrich Dreyer <jfd@butonic.de>
  9. * @author Morris Jobke <hey@morrisjobke.de>
  10. * @author Robin Appelman <robin@icewind.nl>
  11. * @author Roeland Jago Douma <roeland@famdouma.nl>
  12. * @author Thomas Müller <thomas.mueller@tmit.eu>
  13. * @author Vincent Petry <pvince81@owncloud.com>
  14. *
  15. * @license AGPL-3.0
  16. *
  17. * This code is free software: you can redistribute it and/or modify
  18. * it under the terms of the GNU Affero General Public License, version 3,
  19. * as published by the Free Software Foundation.
  20. *
  21. * This program is distributed in the hope that it will be useful,
  22. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. * GNU Affero General Public License for more details.
  25. *
  26. * You should have received a copy of the GNU Affero General Public License, version 3,
  27. * along with this program. If not, see <http://www.gnu.org/licenses/>
  28. *
  29. */
  30. namespace OCA\Files_Sharing\Tests;
  31. use OC\Files\Storage\Temporary;
  32. use OC\Files\Storage\Wrapper\Jail;
  33. use OCA\Files_Sharing\SharedStorage;
  34. use OCP\Share\IShare;
  35. /**
  36. * Class CacheTest
  37. *
  38. * @group DB
  39. */
  40. class CacheTest extends TestCase {
  41. /**
  42. * @var \OC\Files\View
  43. */
  44. public $user2View;
  45. /** @var \OC\Files\Cache\Cache */
  46. protected $ownerCache;
  47. /** @var \OC\Files\Cache\Cache */
  48. protected $sharedCache;
  49. /** @var \OC\Files\Storage\Storage */
  50. protected $ownerStorage;
  51. /** @var \OC\Files\Storage\Storage */
  52. protected $sharedStorage;
  53. /** @var \OCP\Share\IManager */
  54. protected $shareManager;
  55. protected function setUp(): void {
  56. parent::setUp();
  57. $this->shareManager = \OC::$server->getShareManager();
  58. $userManager = \OC::$server->getUserManager();
  59. $userManager->get(self::TEST_FILES_SHARING_API_USER1)->setDisplayName('User One');
  60. $userManager->get(self::TEST_FILES_SHARING_API_USER2)->setDisplayName('User Two');
  61. self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
  62. $this->user2View = new \OC\Files\View('/'. self::TEST_FILES_SHARING_API_USER2 . '/files');
  63. // prepare user1's dir structure
  64. $this->view->mkdir('container');
  65. $this->view->mkdir('container/shareddir');
  66. $this->view->mkdir('container/shareddir/subdir');
  67. $this->view->mkdir('container/shareddir/emptydir');
  68. $textData = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  69. $this->view->file_put_contents('container/not shared.txt', $textData);
  70. $this->view->file_put_contents('container/shared single file.txt', $textData);
  71. $this->view->file_put_contents('container/shareddir/bar.txt', $textData);
  72. $this->view->file_put_contents('container/shareddir/subdir/another.txt', $textData);
  73. $this->view->file_put_contents('container/shareddir/subdir/another too.txt', $textData);
  74. $this->view->file_put_contents('container/shareddir/subdir/not a text file.xml', '<xml></xml>');
  75. list($this->ownerStorage,) = $this->view->resolvePath('');
  76. $this->ownerCache = $this->ownerStorage->getCache();
  77. $this->ownerStorage->getScanner()->scan('');
  78. // share "shareddir" with user2
  79. $rootFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1);
  80. $node = $rootFolder->get('container/shareddir');
  81. $share = $this->shareManager->newShare();
  82. $share->setNode($node)
  83. ->setShareType(IShare::TYPE_USER)
  84. ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
  85. ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
  86. ->setPermissions(\OCP\Constants::PERMISSION_ALL);
  87. $share = $this->shareManager->createShare($share);
  88. $share->setStatus(IShare::STATUS_ACCEPTED);
  89. $this->shareManager->updateShare($share);
  90. $node = $rootFolder->get('container/shared single file.txt');
  91. $share = $this->shareManager->newShare();
  92. $share->setNode($node)
  93. ->setShareType(IShare::TYPE_USER)
  94. ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
  95. ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
  96. ->setPermissions(\OCP\Constants::PERMISSION_ALL & ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE));
  97. $share = $this->shareManager->createShare($share);
  98. $share->setStatus(IShare::STATUS_ACCEPTED);
  99. $this->shareManager->updateShare($share);
  100. // login as user2
  101. self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
  102. // retrieve the shared storage
  103. $secondView = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2);
  104. list($this->sharedStorage,) = $secondView->resolvePath('files/shareddir');
  105. $this->sharedCache = $this->sharedStorage->getCache();
  106. }
  107. protected function tearDown(): void {
  108. if ($this->sharedCache) {
  109. $this->sharedCache->clear();
  110. }
  111. self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
  112. $shares = $this->shareManager->getSharesBy(self::TEST_FILES_SHARING_API_USER1, IShare::TYPE_USER);
  113. foreach ($shares as $share) {
  114. $this->shareManager->deleteShare($share);
  115. }
  116. $this->view->deleteAll('container');
  117. $this->ownerCache->clear();
  118. parent::tearDown();
  119. }
  120. public function searchDataProvider() {
  121. return [
  122. ['%another%',
  123. [
  124. ['name' => 'another too.txt', 'path' => 'subdir/another too.txt'],
  125. ['name' => 'another.txt', 'path' => 'subdir/another.txt'],
  126. ]
  127. ],
  128. ['%Another%',
  129. [
  130. ['name' => 'another too.txt', 'path' => 'subdir/another too.txt'],
  131. ['name' => 'another.txt', 'path' => 'subdir/another.txt'],
  132. ]
  133. ],
  134. ['%dir%',
  135. [
  136. ['name' => 'emptydir', 'path' => 'emptydir'],
  137. ['name' => 'subdir', 'path' => 'subdir'],
  138. ['name' => 'shareddir', 'path' => ''],
  139. ]
  140. ],
  141. ['%Dir%',
  142. [
  143. ['name' => 'emptydir', 'path' => 'emptydir'],
  144. ['name' => 'subdir', 'path' => 'subdir'],
  145. ['name' => 'shareddir', 'path' => ''],
  146. ]
  147. ],
  148. ['%txt%',
  149. [
  150. ['name' => 'bar.txt', 'path' => 'bar.txt'],
  151. ['name' => 'another too.txt', 'path' => 'subdir/another too.txt'],
  152. ['name' => 'another.txt', 'path' => 'subdir/another.txt'],
  153. ]
  154. ],
  155. ['%Txt%',
  156. [
  157. ['name' => 'bar.txt', 'path' => 'bar.txt'],
  158. ['name' => 'another too.txt', 'path' => 'subdir/another too.txt'],
  159. ['name' => 'another.txt', 'path' => 'subdir/another.txt'],
  160. ]
  161. ],
  162. ['%',
  163. [
  164. ['name' => 'bar.txt', 'path' => 'bar.txt'],
  165. ['name' => 'emptydir', 'path' => 'emptydir'],
  166. ['name' => 'subdir', 'path' => 'subdir'],
  167. ['name' => 'another too.txt', 'path' => 'subdir/another too.txt'],
  168. ['name' => 'another.txt', 'path' => 'subdir/another.txt'],
  169. ['name' => 'not a text file.xml', 'path' => 'subdir/not a text file.xml'],
  170. ['name' => 'shareddir', 'path' => ''],
  171. ]
  172. ],
  173. ['%nonexistent%',
  174. [
  175. ]
  176. ],
  177. ];
  178. }
  179. /**
  180. * we cannot use a dataProvider because that would cause the stray hook detection to remove the hooks
  181. * that were added in setUpBeforeClass.
  182. */
  183. public function testSearch() {
  184. foreach ($this->searchDataProvider() as $data) {
  185. list($pattern, $expectedFiles) = $data;
  186. $results = $this->sharedStorage->getCache()->search($pattern);
  187. $this->verifyFiles($expectedFiles, $results);
  188. }
  189. }
  190. /**
  191. * Test searching by mime type
  192. */
  193. public function testSearchByMime() {
  194. $results = $this->sharedStorage->getCache()->searchByMime('text');
  195. $check = [
  196. [
  197. 'name' => 'bar.txt',
  198. 'path' => 'bar.txt'
  199. ],
  200. [
  201. 'name' => 'another too.txt',
  202. 'path' => 'subdir/another too.txt'
  203. ],
  204. [
  205. 'name' => 'another.txt',
  206. 'path' => 'subdir/another.txt'
  207. ],
  208. ];
  209. $this->verifyFiles($check, $results);
  210. }
  211. public function testGetFolderContentsInRoot() {
  212. $results = $this->user2View->getDirectoryContent('/');
  213. // we should get the shared items "shareddir" and "shared single file.txt"
  214. // additional root will always contain the example file "welcome.txt",
  215. // so this will be part of the result
  216. $this->verifyFiles(
  217. [
  218. [
  219. 'name' => 'welcome.txt',
  220. 'path' => 'files/welcome.txt',
  221. 'mimetype' => 'text/plain',
  222. ],
  223. [
  224. 'name' => 'shareddir',
  225. 'path' => 'files/shareddir',
  226. 'mimetype' => 'httpd/unix-directory',
  227. 'uid_owner' => self::TEST_FILES_SHARING_API_USER1,
  228. 'displayname_owner' => 'User One',
  229. ],
  230. [
  231. 'name' => 'shared single file.txt',
  232. 'path' => 'files/shared single file.txt',
  233. 'mimetype' => 'text/plain',
  234. 'uid_owner' => self::TEST_FILES_SHARING_API_USER1,
  235. 'displayname_owner' => 'User One',
  236. ],
  237. ],
  238. $results
  239. );
  240. }
  241. public function testGetFolderContentsInSubdir() {
  242. $results = $this->user2View->getDirectoryContent('/shareddir');
  243. $this->verifyFiles(
  244. [
  245. [
  246. 'name' => 'bar.txt',
  247. 'path' => 'bar.txt',
  248. 'mimetype' => 'text/plain',
  249. 'uid_owner' => self::TEST_FILES_SHARING_API_USER1,
  250. 'displayname_owner' => 'User One',
  251. ],
  252. [
  253. 'name' => 'emptydir',
  254. 'path' => 'emptydir',
  255. 'mimetype' => 'httpd/unix-directory',
  256. 'uid_owner' => self::TEST_FILES_SHARING_API_USER1,
  257. 'displayname_owner' => 'User One',
  258. ],
  259. [
  260. 'name' => 'subdir',
  261. 'path' => 'subdir',
  262. 'mimetype' => 'httpd/unix-directory',
  263. 'uid_owner' => self::TEST_FILES_SHARING_API_USER1,
  264. 'displayname_owner' => 'User One',
  265. ],
  266. ],
  267. $results
  268. );
  269. }
  270. public function testGetFolderContentsWhenSubSubdirShared() {
  271. self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
  272. $rootFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1);
  273. $node = $rootFolder->get('container/shareddir/subdir');
  274. $share = $this->shareManager->newShare();
  275. $share->setNode($node)
  276. ->setShareType(IShare::TYPE_USER)
  277. ->setSharedWith(self::TEST_FILES_SHARING_API_USER3)
  278. ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
  279. ->setPermissions(\OCP\Constants::PERMISSION_ALL);
  280. $share = $this->shareManager->createShare($share);
  281. $share->setStatus(IShare::STATUS_ACCEPTED);
  282. $this->shareManager->updateShare($share);
  283. self::loginHelper(self::TEST_FILES_SHARING_API_USER3);
  284. $thirdView = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER3 . '/files');
  285. $results = $thirdView->getDirectoryContent('/subdir');
  286. $this->verifyFiles(
  287. [
  288. [
  289. 'name' => 'another too.txt',
  290. 'path' => 'another too.txt',
  291. 'mimetype' => 'text/plain',
  292. 'uid_owner' => self::TEST_FILES_SHARING_API_USER1,
  293. 'displayname_owner' => 'User One',
  294. ],
  295. [
  296. 'name' => 'another.txt',
  297. 'path' => 'another.txt',
  298. 'mimetype' => 'text/plain',
  299. 'uid_owner' => self::TEST_FILES_SHARING_API_USER1,
  300. 'displayname_owner' => 'User One',
  301. ],
  302. [
  303. 'name' => 'not a text file.xml',
  304. 'path' => 'not a text file.xml',
  305. 'mimetype' => 'application/xml',
  306. 'uid_owner' => self::TEST_FILES_SHARING_API_USER1,
  307. 'displayname_owner' => 'User One',
  308. ],
  309. ],
  310. $results
  311. );
  312. self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
  313. $this->shareManager->deleteShare($share);
  314. }
  315. /**
  316. * Check if 'results' contains the expected 'examples' only.
  317. *
  318. * @param array $examples array of example files
  319. * @param array $results array of files
  320. */
  321. private function verifyFiles($examples, $results) {
  322. $this->assertEquals(count($examples), count($results));
  323. foreach ($examples as $example) {
  324. foreach ($results as $key => $result) {
  325. if ($result['name'] === $example['name']) {
  326. $this->verifyKeys($example, $result);
  327. unset($results[$key]);
  328. break;
  329. }
  330. }
  331. }
  332. $this->assertEquals([], $results);
  333. }
  334. /**
  335. * verify if each value from the result matches the expected result
  336. * @param array $example array with the expected results
  337. * @param array $result array with the results
  338. */
  339. private function verifyKeys($example, $result) {
  340. foreach ($example as $key => $value) {
  341. $this->assertEquals($value, $result[$key]);
  342. }
  343. }
  344. public function testGetPathByIdDirectShare() {
  345. self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
  346. \OC\Files\Filesystem::file_put_contents('test.txt', 'foo');
  347. $info = \OC\Files\Filesystem::getFileInfo('test.txt');
  348. $rootFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1);
  349. $node = $rootFolder->get('test.txt');
  350. $share = $this->shareManager->newShare();
  351. $share->setNode($node)
  352. ->setShareType(IShare::TYPE_USER)
  353. ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
  354. ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
  355. ->setPermissions(\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_SHARE);
  356. $share = $this->shareManager->createShare($share);
  357. $share->setStatus(IShare::STATUS_ACCEPTED);
  358. $this->shareManager->updateShare($share);
  359. \OC_Util::tearDownFS();
  360. self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
  361. $this->assertTrue(\OC\Files\Filesystem::file_exists('/test.txt'));
  362. list($sharedStorage) = \OC\Files\Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/test.txt');
  363. /**
  364. * @var \OCA\Files_Sharing\SharedStorage $sharedStorage
  365. */
  366. $sharedCache = $sharedStorage->getCache();
  367. $this->assertEquals('', $sharedCache->getPathById($info->getId()));
  368. }
  369. public function testGetPathByIdShareSubFolder() {
  370. self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
  371. \OC\Files\Filesystem::mkdir('foo');
  372. \OC\Files\Filesystem::mkdir('foo/bar');
  373. \OC\Files\Filesystem::touch('foo/bar/test.txt');
  374. $folderInfo = \OC\Files\Filesystem::getFileInfo('foo');
  375. $fileInfo = \OC\Files\Filesystem::getFileInfo('foo/bar/test.txt');
  376. $rootFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1);
  377. $node = $rootFolder->get('foo');
  378. $share = $this->shareManager->newShare();
  379. $share->setNode($node)
  380. ->setShareType(IShare::TYPE_USER)
  381. ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
  382. ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
  383. ->setPermissions(\OCP\Constants::PERMISSION_ALL);
  384. $share = $this->shareManager->createShare($share);
  385. $share->setStatus(IShare::STATUS_ACCEPTED);
  386. $this->shareManager->updateShare($share);
  387. \OC_Util::tearDownFS();
  388. self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
  389. $this->assertTrue(\OC\Files\Filesystem::file_exists('/foo'));
  390. list($sharedStorage) = \OC\Files\Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/foo');
  391. /**
  392. * @var \OCA\Files_Sharing\SharedStorage $sharedStorage
  393. */
  394. $sharedCache = $sharedStorage->getCache();
  395. $this->assertEquals('', $sharedCache->getPathById($folderInfo->getId()));
  396. $this->assertEquals('bar/test.txt', $sharedCache->getPathById($fileInfo->getId()));
  397. }
  398. public function testNumericStorageId() {
  399. self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
  400. \OC\Files\Filesystem::mkdir('foo');
  401. $rootFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1);
  402. $node = $rootFolder->get('foo');
  403. $share = $this->shareManager->newShare();
  404. $share->setNode($node)
  405. ->setShareType(IShare::TYPE_USER)
  406. ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
  407. ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
  408. ->setPermissions(\OCP\Constants::PERMISSION_ALL);
  409. $share = $this->shareManager->createShare($share);
  410. $share->setStatus(IShare::STATUS_ACCEPTED);
  411. $this->shareManager->updateShare($share);
  412. \OC_Util::tearDownFS();
  413. list($sourceStorage) = \OC\Files\Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER1 . '/files/foo');
  414. self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
  415. $this->assertTrue(\OC\Files\Filesystem::file_exists('/foo'));
  416. /** @var SharedStorage $sharedStorage */
  417. list($sharedStorage) = \OC\Files\Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/foo');
  418. $this->assertEquals($sourceStorage->getCache()->getNumericStorageId(), $sharedStorage->getCache()->getNumericStorageId());
  419. }
  420. public function testShareJailedStorage() {
  421. $sourceStorage = new Temporary();
  422. $sourceStorage->mkdir('jail');
  423. $sourceStorage->mkdir('jail/sub');
  424. $sourceStorage->file_put_contents('jail/sub/foo.txt', 'foo');
  425. $jailedSource = new Jail([
  426. 'storage' => $sourceStorage,
  427. 'root' => 'jail'
  428. ]);
  429. $sourceStorage->getScanner()->scan('');
  430. $this->registerMount(self::TEST_FILES_SHARING_API_USER1, $jailedSource, '/' . self::TEST_FILES_SHARING_API_USER1 . '/files/foo');
  431. self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
  432. $rootFolder = \OC::$server->getUserFolder(self::TEST_FILES_SHARING_API_USER1);
  433. $node = $rootFolder->get('foo/sub');
  434. $share = $this->shareManager->newShare();
  435. $share->setNode($node)
  436. ->setShareType(IShare::TYPE_USER)
  437. ->setSharedWith(self::TEST_FILES_SHARING_API_USER2)
  438. ->setSharedBy(self::TEST_FILES_SHARING_API_USER1)
  439. ->setPermissions(\OCP\Constants::PERMISSION_ALL);
  440. $share = $this->shareManager->createShare($share);
  441. $share->setStatus(IShare::STATUS_ACCEPTED);
  442. $this->shareManager->updateShare($share);
  443. \OC_Util::tearDownFS();
  444. self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
  445. $this->assertEquals('foo', \OC\Files\Filesystem::file_get_contents('/sub/foo.txt'));
  446. \OC\Files\Filesystem::file_put_contents('/sub/bar.txt', 'bar');
  447. /** @var SharedStorage $sharedStorage */
  448. list($sharedStorage) = \OC\Files\Filesystem::resolvePath('/' . self::TEST_FILES_SHARING_API_USER2 . '/files/sub');
  449. $this->assertTrue($sharedStorage->getCache()->inCache('bar.txt'));
  450. $this->assertTrue($sourceStorage->getCache()->inCache('jail/sub/bar.txt'));
  451. }
  452. }