view.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. <?php
  2. /**
  3. * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
  4. * This file is licensed under the Affero General Public License version 3 or
  5. * later.
  6. * See the COPYING-README file. */
  7. namespace Test\Files;
  8. class TemporaryNoTouch extends \OC\Files\Storage\Temporary {
  9. public function touch($path, $mtime = null) {
  10. return false;
  11. }
  12. }
  13. class View extends \PHPUnit_Framework_TestCase {
  14. /**
  15. * @var \OC\Files\Storage\Storage[] $storages;
  16. */
  17. private $storages = array();
  18. public function setUp() {
  19. \OC_User::clearBackends();
  20. \OC_User::useBackend(new \OC_User_Dummy());
  21. //login
  22. \OC_User::createUser('test', 'test');
  23. $this->user = \OC_User::getUser();
  24. \OC_User::setUserId('test');
  25. \OC\Files\Filesystem::clearMounts();
  26. }
  27. public function tearDown() {
  28. \OC_User::setUserId($this->user);
  29. foreach ($this->storages as $storage) {
  30. $cache = $storage->getCache();
  31. $ids = $cache->getAll();
  32. $permissionsCache = $storage->getPermissionsCache();
  33. $permissionsCache->removeMultiple($ids, \OC_User::getUser());
  34. $cache->clear();
  35. }
  36. }
  37. /**
  38. * @medium
  39. */
  40. public function testCacheAPI() {
  41. $storage1 = $this->getTestStorage();
  42. $storage2 = $this->getTestStorage();
  43. $storage3 = $this->getTestStorage();
  44. \OC\Files\Filesystem::mount($storage1, array(), '/');
  45. \OC\Files\Filesystem::mount($storage2, array(), '/substorage');
  46. \OC\Files\Filesystem::mount($storage3, array(), '/folder/anotherstorage');
  47. $textSize = strlen("dummy file data\n");
  48. $imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo.png');
  49. $storageSize = $textSize * 2 + $imageSize;
  50. $rootView = new \OC\Files\View('');
  51. $cachedData = $rootView->getFileInfo('/foo.txt');
  52. $this->assertEquals($textSize, $cachedData['size']);
  53. $this->assertEquals('text/plain', $cachedData['mimetype']);
  54. $this->assertNotEquals(-1, $cachedData['permissions']);
  55. $cachedData = $rootView->getFileInfo('/');
  56. $this->assertEquals($storageSize * 3, $cachedData['size']);
  57. $this->assertEquals('httpd/unix-directory', $cachedData['mimetype']);
  58. // get cached data excluding mount points
  59. $cachedData = $rootView->getFileInfo('/', false);
  60. $this->assertEquals($storageSize, $cachedData['size']);
  61. $this->assertEquals('httpd/unix-directory', $cachedData['mimetype']);
  62. $cachedData = $rootView->getFileInfo('/folder');
  63. $this->assertEquals($storageSize + $textSize, $cachedData['size']);
  64. $this->assertEquals('httpd/unix-directory', $cachedData['mimetype']);
  65. $folderData = $rootView->getDirectoryContent('/');
  66. /**
  67. * expected entries:
  68. * folder
  69. * foo.png
  70. * foo.txt
  71. * substorage
  72. */
  73. $this->assertEquals(4, count($folderData));
  74. $this->assertEquals('folder', $folderData[0]['name']);
  75. $this->assertEquals('foo.png', $folderData[1]['name']);
  76. $this->assertEquals('foo.txt', $folderData[2]['name']);
  77. $this->assertEquals('substorage', $folderData[3]['name']);
  78. $this->assertEquals($storageSize + $textSize, $folderData[0]['size']);
  79. $this->assertEquals($imageSize, $folderData[1]['size']);
  80. $this->assertEquals($textSize, $folderData[2]['size']);
  81. $this->assertEquals($storageSize, $folderData[3]['size']);
  82. $folderData = $rootView->getDirectoryContent('/substorage');
  83. /**
  84. * expected entries:
  85. * folder
  86. * foo.png
  87. * foo.txt
  88. */
  89. $this->assertEquals(3, count($folderData));
  90. $this->assertEquals('folder', $folderData[0]['name']);
  91. $this->assertEquals('foo.png', $folderData[1]['name']);
  92. $this->assertEquals('foo.txt', $folderData[2]['name']);
  93. $folderView = new \OC\Files\View('/folder');
  94. $this->assertEquals($rootView->getFileInfo('/folder'), $folderView->getFileInfo('/'));
  95. $cachedData = $rootView->getFileInfo('/foo.txt');
  96. $this->assertFalse($cachedData['encrypted']);
  97. $id = $rootView->putFileInfo('/foo.txt', array('encrypted' => true));
  98. $cachedData = $rootView->getFileInfo('/foo.txt');
  99. $this->assertTrue($cachedData['encrypted']);
  100. $this->assertEquals($cachedData['fileid'], $id);
  101. $this->assertFalse($rootView->getFileInfo('/non/existing'));
  102. $this->assertEquals(array(), $rootView->getDirectoryContent('/non/existing'));
  103. }
  104. /**
  105. * @medium
  106. */
  107. function testGetPath() {
  108. $storage1 = $this->getTestStorage();
  109. $storage2 = $this->getTestStorage();
  110. $storage3 = $this->getTestStorage();
  111. \OC\Files\Filesystem::mount($storage1, array(), '/');
  112. \OC\Files\Filesystem::mount($storage2, array(), '/substorage');
  113. \OC\Files\Filesystem::mount($storage3, array(), '/folder/anotherstorage');
  114. $rootView = new \OC\Files\View('');
  115. $cachedData = $rootView->getFileInfo('/foo.txt');
  116. $id1 = $cachedData['fileid'];
  117. $this->assertEquals('/foo.txt', $rootView->getPath($id1));
  118. $cachedData = $rootView->getFileInfo('/substorage/foo.txt');
  119. $id2 = $cachedData['fileid'];
  120. $this->assertEquals('/substorage/foo.txt', $rootView->getPath($id2));
  121. $folderView = new \OC\Files\View('/substorage');
  122. $this->assertEquals('/foo.txt', $folderView->getPath($id2));
  123. $this->assertNull($folderView->getPath($id1));
  124. }
  125. /**
  126. * @medium
  127. */
  128. function testMountPointOverwrite() {
  129. $storage1 = $this->getTestStorage(false);
  130. $storage2 = $this->getTestStorage();
  131. $storage1->mkdir('substorage');
  132. \OC\Files\Filesystem::mount($storage1, array(), '/');
  133. \OC\Files\Filesystem::mount($storage2, array(), '/substorage');
  134. $rootView = new \OC\Files\View('');
  135. $folderContent = $rootView->getDirectoryContent('/');
  136. $this->assertEquals(4, count($folderContent));
  137. }
  138. function testCacheIncompleteFolder() {
  139. $storage1 = $this->getTestStorage(false);
  140. \OC\Files\Filesystem::mount($storage1, array(), '/');
  141. $rootView = new \OC\Files\View('');
  142. $entries = $rootView->getDirectoryContent('/');
  143. $this->assertEquals(3, count($entries));
  144. // /folder will already be in the cache but not scanned
  145. $entries = $rootView->getDirectoryContent('/folder');
  146. $this->assertEquals(1, count($entries));
  147. }
  148. public function testAutoScan() {
  149. $storage1 = $this->getTestStorage(false);
  150. $storage2 = $this->getTestStorage(false);
  151. \OC\Files\Filesystem::mount($storage1, array(), '/');
  152. \OC\Files\Filesystem::mount($storage2, array(), '/substorage');
  153. $textSize = strlen("dummy file data\n");
  154. $rootView = new \OC\Files\View('');
  155. $cachedData = $rootView->getFileInfo('/');
  156. $this->assertEquals('httpd/unix-directory', $cachedData['mimetype']);
  157. $this->assertEquals(-1, $cachedData['size']);
  158. $folderData = $rootView->getDirectoryContent('/substorage/folder');
  159. $this->assertEquals('text/plain', $folderData[0]['mimetype']);
  160. $this->assertEquals($textSize, $folderData[0]['size']);
  161. }
  162. /**
  163. * @medium
  164. */
  165. function testSearch() {
  166. $storage1 = $this->getTestStorage();
  167. $storage2 = $this->getTestStorage();
  168. $storage3 = $this->getTestStorage();
  169. \OC\Files\Filesystem::mount($storage1, array(), '/');
  170. \OC\Files\Filesystem::mount($storage2, array(), '/substorage');
  171. \OC\Files\Filesystem::mount($storage3, array(), '/folder/anotherstorage');
  172. $rootView = new \OC\Files\View('');
  173. $results = $rootView->search('foo');
  174. $this->assertEquals(6, count($results));
  175. $paths = array();
  176. foreach ($results as $result) {
  177. $this->assertEquals($result['path'], \OC\Files\Filesystem::normalizePath($result['path']));
  178. $paths[] = $result['path'];
  179. }
  180. $this->assertContains('/foo.txt', $paths);
  181. $this->assertContains('/foo.png', $paths);
  182. $this->assertContains('/substorage/foo.txt', $paths);
  183. $this->assertContains('/substorage/foo.png', $paths);
  184. $this->assertContains('/folder/anotherstorage/foo.txt', $paths);
  185. $this->assertContains('/folder/anotherstorage/foo.png', $paths);
  186. $folderView = new \OC\Files\View('/folder');
  187. $results = $folderView->search('bar');
  188. $this->assertEquals(2, count($results));
  189. $paths = array();
  190. foreach ($results as $result) {
  191. $paths[] = $result['path'];
  192. }
  193. $this->assertContains('/anotherstorage/folder/bar.txt', $paths);
  194. $this->assertContains('/bar.txt', $paths);
  195. $results = $folderView->search('foo');
  196. $this->assertEquals(2, count($results));
  197. $paths = array();
  198. foreach ($results as $result) {
  199. $paths[] = $result['path'];
  200. }
  201. $this->assertContains('/anotherstorage/foo.txt', $paths);
  202. $this->assertContains('/anotherstorage/foo.png', $paths);
  203. $this->assertEquals(6, count($rootView->searchByMime('text')));
  204. $this->assertEquals(3, count($folderView->searchByMime('text')));
  205. }
  206. /**
  207. * @medium
  208. */
  209. function testWatcher() {
  210. $storage1 = $this->getTestStorage();
  211. \OC\Files\Filesystem::mount($storage1, array(), '/');
  212. $rootView = new \OC\Files\View('');
  213. $cachedData = $rootView->getFileInfo('foo.txt');
  214. $this->assertEquals(16, $cachedData['size']);
  215. $rootView->putFileInfo('foo.txt', array('storage_mtime' => 10));
  216. $storage1->file_put_contents('foo.txt', 'foo');
  217. clearstatcache();
  218. $cachedData = $rootView->getFileInfo('foo.txt');
  219. $this->assertEquals(3, $cachedData['size']);
  220. }
  221. /**
  222. * @medium
  223. */
  224. function testCopyBetweenStorages() {
  225. $storage1 = $this->getTestStorage();
  226. $storage2 = $this->getTestStorage();
  227. \OC\Files\Filesystem::mount($storage1, array(), '/');
  228. \OC\Files\Filesystem::mount($storage2, array(), '/substorage');
  229. $rootView = new \OC\Files\View('');
  230. $rootView->mkdir('substorage/emptyfolder');
  231. $rootView->copy('substorage', 'anotherfolder');
  232. $this->assertTrue($rootView->is_dir('/anotherfolder'));
  233. $this->assertTrue($rootView->is_dir('/substorage'));
  234. $this->assertTrue($rootView->is_dir('/anotherfolder/emptyfolder'));
  235. $this->assertTrue($rootView->is_dir('/substorage/emptyfolder'));
  236. $this->assertTrue($rootView->file_exists('/anotherfolder/foo.txt'));
  237. $this->assertTrue($rootView->file_exists('/anotherfolder/foo.png'));
  238. $this->assertTrue($rootView->file_exists('/anotherfolder/folder/bar.txt'));
  239. $this->assertTrue($rootView->file_exists('/substorage/foo.txt'));
  240. $this->assertTrue($rootView->file_exists('/substorage/foo.png'));
  241. $this->assertTrue($rootView->file_exists('/substorage/folder/bar.txt'));
  242. }
  243. /**
  244. * @medium
  245. */
  246. function testMoveBetweenStorages() {
  247. $storage1 = $this->getTestStorage();
  248. $storage2 = $this->getTestStorage();
  249. \OC\Files\Filesystem::mount($storage1, array(), '/');
  250. \OC\Files\Filesystem::mount($storage2, array(), '/substorage');
  251. $rootView = new \OC\Files\View('');
  252. $rootView->rename('foo.txt', 'substorage/folder/foo.txt');
  253. $this->assertFalse($rootView->file_exists('foo.txt'));
  254. $this->assertTrue($rootView->file_exists('substorage/folder/foo.txt'));
  255. $rootView->rename('substorage/folder', 'anotherfolder');
  256. $this->assertFalse($rootView->is_dir('substorage/folder'));
  257. $this->assertTrue($rootView->file_exists('anotherfolder/foo.txt'));
  258. $this->assertTrue($rootView->file_exists('anotherfolder/bar.txt'));
  259. }
  260. /**
  261. * @medium
  262. */
  263. function testTouch() {
  264. $storage = $this->getTestStorage(true, '\Test\Files\TemporaryNoTouch');
  265. \OC\Files\Filesystem::mount($storage, array(), '/');
  266. $rootView = new \OC\Files\View('');
  267. $oldCachedData = $rootView->getFileInfo('foo.txt');
  268. $rootView->touch('foo.txt', 500);
  269. $cachedData = $rootView->getFileInfo('foo.txt');
  270. $this->assertEquals(500, $cachedData['mtime']);
  271. $this->assertEquals($oldCachedData['storage_mtime'], $cachedData['storage_mtime']);
  272. $rootView->putFileInfo('foo.txt', array('storage_mtime' => 1000)); //make sure the watcher detects the change
  273. $rootView->file_put_contents('foo.txt', 'asd');
  274. $cachedData = $rootView->getFileInfo('foo.txt');
  275. $this->assertGreaterThanOrEqual($cachedData['mtime'], $oldCachedData['mtime']);
  276. $this->assertEquals($cachedData['storage_mtime'], $cachedData['mtime']);
  277. }
  278. /**
  279. * @medium
  280. */
  281. function testViewHooks() {
  282. $storage1 = $this->getTestStorage();
  283. $storage2 = $this->getTestStorage();
  284. $defaultRoot = \OC\Files\Filesystem::getRoot();
  285. \OC\Files\Filesystem::mount($storage1, array(), '/');
  286. \OC\Files\Filesystem::mount($storage2, array(), $defaultRoot . '/substorage');
  287. \OC_Hook::connect('OC_Filesystem', 'post_write', $this, 'dummyHook');
  288. $rootView = new \OC\Files\View('');
  289. $subView = new \OC\Files\View($defaultRoot . '/substorage');
  290. $this->hookPath = null;
  291. $rootView->file_put_contents('/foo.txt', 'asd');
  292. $this->assertNull($this->hookPath);
  293. $subView->file_put_contents('/foo.txt', 'asd');
  294. $this->assertNotNull($this->hookPath);
  295. $this->assertEquals('/substorage/foo.txt', $this->hookPath);
  296. }
  297. private $hookPath;
  298. function dummyHook($params) {
  299. $this->hookPath = $params['path'];
  300. }
  301. public function testSearchNotOutsideView() {
  302. $storage1 = $this->getTestStorage();
  303. \OC\Files\Filesystem::mount($storage1, array(), '/');
  304. $storage1->rename('folder', 'foo');
  305. $scanner = $storage1->getScanner();
  306. $scanner->scan('');
  307. $view = new \OC\Files\View('/foo');
  308. $result = $view->search('.txt');
  309. $this->assertCount(1, $result);
  310. }
  311. /**
  312. * @param bool $scan
  313. * @param string $class
  314. * @return \OC\Files\Storage\Storage
  315. */
  316. private function getTestStorage($scan = true, $class = '\OC\Files\Storage\Temporary') {
  317. /**
  318. * @var \OC\Files\Storage\Storage $storage
  319. */
  320. $storage = new $class(array());
  321. $textData = "dummy file data\n";
  322. $imgData = file_get_contents(\OC::$SERVERROOT . '/core/img/logo.png');
  323. $storage->mkdir('folder');
  324. $storage->file_put_contents('foo.txt', $textData);
  325. $storage->file_put_contents('foo.png', $imgData);
  326. $storage->file_put_contents('folder/bar.txt', $textData);
  327. if ($scan) {
  328. $scanner = $storage->getScanner();
  329. $scanner->scan('');
  330. }
  331. $this->storages[] = $storage;
  332. return $storage;
  333. }
  334. private $createHookPath;
  335. function dummyCreateHook($params) {
  336. $this->createHookPath = $params['path'];
  337. }
  338. /**
  339. * @medium
  340. */
  341. function testViewHooksIfRootStartsTheSame() {
  342. $storage1 = $this->getTestStorage();
  343. $storage2 = $this->getTestStorage();
  344. $defaultRoot = \OC\Files\Filesystem::getRoot();
  345. \OC\Files\Filesystem::mount($storage1, array(), '/');
  346. \OC\Files\Filesystem::mount($storage2, array(), $defaultRoot . '_substorage');
  347. \OC_Hook::connect('OC_Filesystem', 'post_write', $this, 'dummyHook');
  348. $subView = new \OC\Files\View($defaultRoot . '_substorage');
  349. $this->hookPath = null;
  350. $subView->file_put_contents('/foo.txt', 'asd');
  351. $this->assertNull($this->hookPath);
  352. }
  353. public function testEditNoCreateHook() {
  354. $storage1 = $this->getTestStorage();
  355. $storage2 = $this->getTestStorage();
  356. $defaultRoot = \OC\Files\Filesystem::getRoot();
  357. \OC\Files\Filesystem::mount($storage1, array(), '/');
  358. \OC\Files\Filesystem::mount($storage2, array(), $defaultRoot);
  359. \OC_Hook::connect('OC_Filesystem', 'post_create', $this, 'dummyCreateHook');
  360. $view = new \OC\Files\View($defaultRoot);
  361. $this->hookPath = null;
  362. $view->file_put_contents('/asd.txt', 'foo');
  363. $this->assertEquals('/asd.txt', $this->createHookPath);
  364. $this->createHookPath = null;
  365. $view->file_put_contents('/asd.txt', 'foo');
  366. $this->assertNull($this->createHookPath);
  367. }
  368. /**
  369. * @dataProvider resolvePathTestProvider
  370. */
  371. public function testResolvePath($expected, $pathToTest) {
  372. $storage1 = $this->getTestStorage();
  373. \OC\Files\Filesystem::mount($storage1, array(), '/');
  374. $view = new \OC\Files\View('');
  375. $result = $view->resolvePath($pathToTest);
  376. $this->assertEquals($expected, $result[1]);
  377. $exists = $view->file_exists($pathToTest);
  378. $this->assertTrue($exists);
  379. $exists = $view->file_exists($result[1]);
  380. $this->assertTrue($exists);
  381. }
  382. function resolvePathTestProvider() {
  383. return array(
  384. array('foo.txt', 'foo.txt'),
  385. array('foo.txt', '/foo.txt'),
  386. array('folder', 'folder'),
  387. array('folder', '/folder'),
  388. array('folder', 'folder/'),
  389. array('folder', '/folder/'),
  390. array('folder/bar.txt', 'folder/bar.txt'),
  391. array('folder/bar.txt', '/folder/bar.txt'),
  392. array('', ''),
  393. array('', '/'),
  394. );
  395. }
  396. }