RepairInvalidPathsTest.php 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl>
  4. *
  5. * @license GNU AGPL version 3 or any later version
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU Affero General Public License as
  9. * published by the Free Software Foundation, either version 3 of the
  10. * License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Affero General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. *
  20. */
  21. namespace Test\Repair;
  22. use OC\Files\Cache\Cache;
  23. use OC\Files\Storage\Temporary;
  24. use OC\Repair\NC13\RepairInvalidPaths;
  25. use OCP\IConfig;
  26. use OCP\Migration\IOutput;
  27. use Test\TestCase;
  28. /**
  29. * @group DB
  30. */
  31. class RepairInvalidPathsTest extends TestCase {
  32. /** @var Temporary */
  33. private $storage;
  34. /** @var Cache */
  35. private $cache;
  36. /** @var Temporary */
  37. private $storage2;
  38. /** @var Cache */
  39. private $cache2;
  40. /** @var RepairInvalidPaths */
  41. private $repair;
  42. protected function setUp() {
  43. parent::setUp();
  44. $this->storage = new Temporary();
  45. $this->cache = $this->storage->getCache();
  46. $this->storage2 = new Temporary();
  47. $this->cache2 = $this->storage2->getCache();
  48. $config = $this->createMock(IConfig::class);
  49. $config->expects($this->any())
  50. ->method('getSystemValue')
  51. ->with('version', '0.0.0')
  52. ->willReturn('12.0.0.0');
  53. $this->repair = new RepairInvalidPaths(\OC::$server->getDatabaseConnection(), $config);
  54. }
  55. protected function tearDown() {
  56. $this->cache->clear();
  57. return parent::tearDown();
  58. }
  59. public function testRepairNonDuplicate() {
  60. $this->storage->mkdir('foo/bar/asd');
  61. $this->storage->mkdir('foo2');
  62. $this->storage->getScanner()->scan('');
  63. $folderId = $this->cache->getId('foo/bar');
  64. $newParentFolderId = $this->cache->getId('foo2');
  65. // failed rename, moved entry is updated but not it's children
  66. $this->cache->update($folderId, ['path' => 'foo2/bar', 'parent' => $newParentFolderId]);
  67. $this->assertTrue($this->cache->inCache('foo2/bar'));
  68. $this->assertTrue($this->cache->inCache('foo/bar/asd'));
  69. $this->assertFalse($this->cache->inCache('foo2/bar/asd'));
  70. $this->assertEquals($folderId, $this->cache->get('foo/bar/asd')['parent']);
  71. $this->repair->run($this->createMock(IOutput::class));
  72. $this->assertTrue($this->cache->inCache('foo2/bar'));
  73. $this->assertTrue($this->cache->inCache('foo2/bar/asd'));
  74. $this->assertFalse($this->cache->inCache('foo/bar/asd'));
  75. $this->assertEquals($folderId, $this->cache->get('foo2/bar/asd')['parent']);
  76. $this->assertEquals($folderId, $this->cache->getId('foo2/bar'));
  77. }
  78. public function testRepairDuplicate() {
  79. $this->storage->mkdir('foo/bar/asd');
  80. $this->storage->mkdir('foo2');
  81. $this->storage->getScanner()->scan('');
  82. $folderId = $this->cache->getId('foo/bar');
  83. $newParentFolderId = $this->cache->getId('foo2');
  84. // failed rename, moved entry is updated but not it's children
  85. $this->cache->update($folderId, ['path' => 'foo2/bar', 'parent' => $newParentFolderId]);
  86. $this->storage->rename('foo/bar', 'foo2/bar');
  87. $this->storage->mkdir('foo2/bar/asd/foo');
  88. // usage causes the renamed subfolder to be scanned
  89. $this->storage->getScanner()->scan('foo2/bar/asd');
  90. $this->assertTrue($this->cache->inCache('foo2/bar'));
  91. $this->assertTrue($this->cache->inCache('foo/bar/asd'));
  92. $this->assertTrue($this->cache->inCache('foo2/bar/asd'));
  93. $this->assertEquals($folderId, $this->cache->get('foo/bar/asd')['parent']);
  94. $this->repair->run($this->createMock(IOutput::class));
  95. $this->assertTrue($this->cache->inCache('foo2/bar'));
  96. $this->assertTrue($this->cache->inCache('foo2/bar/asd'));
  97. $this->assertFalse($this->cache->inCache('foo/bar/asd'));
  98. $this->assertEquals($this->cache->getId('foo2/bar'), $this->cache->get('foo2/bar/asd')['parent']);
  99. $this->assertEquals($this->cache->getId('foo2/bar/asd'), $this->cache->get('foo2/bar/asd/foo')['parent']);
  100. }
  101. public function testRepairMultipleNonDuplicate() {
  102. $this->storage->mkdir('foo/bar/asd');
  103. $this->storage->mkdir('foo/bar2/asd');
  104. $this->storage->mkdir('foo2');
  105. $this->storage->getScanner()->scan('');
  106. $folderId1 = $this->cache->getId('foo/bar');
  107. $folderId2 = $this->cache->getId('foo/bar2');
  108. $newParentFolderId = $this->cache->getId('foo2');
  109. // failed rename, moved entry is updated but not it's children
  110. $this->cache->update($folderId1, ['path' => 'foo2/bar', 'parent' => $newParentFolderId]);
  111. $this->cache->update($folderId2, ['path' => 'foo2/bar2', 'parent' => $newParentFolderId]);
  112. $this->assertTrue($this->cache->inCache('foo2/bar'));
  113. $this->assertTrue($this->cache->inCache('foo2/bar2'));
  114. $this->assertTrue($this->cache->inCache('foo/bar/asd'));
  115. $this->assertTrue($this->cache->inCache('foo/bar2/asd'));
  116. $this->assertFalse($this->cache->inCache('foo2/bar/asd'));
  117. $this->assertFalse($this->cache->inCache('foo2/bar2/asd'));
  118. $this->assertEquals($folderId1, $this->cache->get('foo/bar/asd')['parent']);
  119. $this->assertEquals($folderId2, $this->cache->get('foo/bar2/asd')['parent']);
  120. $this->repair->run($this->createMock(IOutput::class));
  121. $this->assertTrue($this->cache->inCache('foo2/bar'));
  122. $this->assertTrue($this->cache->inCache('foo2/bar2'));
  123. $this->assertTrue($this->cache->inCache('foo2/bar/asd'));
  124. $this->assertTrue($this->cache->inCache('foo2/bar2/asd'));
  125. $this->assertFalse($this->cache->inCache('foo/bar/asd'));
  126. $this->assertFalse($this->cache->inCache('foo/bar2/asd'));
  127. $this->assertEquals($folderId1, $this->cache->get('foo2/bar/asd')['parent']);
  128. $this->assertEquals($folderId2, $this->cache->get('foo2/bar2/asd')['parent']);
  129. $this->assertEquals($folderId1, $this->cache->getId('foo2/bar'));
  130. $this->assertEquals($folderId2, $this->cache->getId('foo2/bar2'));
  131. }
  132. public function testRepairNonDuplicateBetweenStorage() {
  133. $this->storage->mkdir('foo/bar/asd');
  134. $this->storage2->mkdir('foo2');
  135. $this->storage->getScanner()->scan('');
  136. $this->storage2->getScanner()->scan('');
  137. $folderId = $this->cache->getId('foo/bar');
  138. $newParentEntry = $this->cache2->get('foo2');
  139. $newParentFolderId = $newParentEntry->getId();
  140. // failed rename, moved entry is updated but not it's children
  141. $this->cache->update($folderId, ['path' => 'foo2/bar', 'parent' => $newParentFolderId, 'storage' => $newParentEntry->getStorageId()]);
  142. $this->assertTrue($this->cache2->inCache('foo2/bar'));
  143. $this->assertTrue($this->cache->inCache('foo/bar/asd'));
  144. $this->assertFalse($this->cache2->inCache('foo2/bar/asd'));
  145. $this->assertEquals($folderId, $this->cache->get('foo/bar/asd')['parent']);
  146. $this->repair->run($this->createMock(IOutput::class));
  147. $this->assertTrue($this->cache2->inCache('foo2/bar'));
  148. $this->assertTrue($this->cache2->inCache('foo2/bar/asd'));
  149. $this->assertFalse($this->cache->inCache('foo/bar/asd'));
  150. $this->assertEquals($folderId, $this->cache2->get('foo2/bar/asd')['parent']);
  151. $this->assertEquals($folderId, $this->cache2->getId('foo2/bar'));
  152. }
  153. public function shouldRunDataProvider() {
  154. return [
  155. ['11.0.0.0', true],
  156. ['11.0.0.31', true],
  157. ['11.0.5.2', false],
  158. ['12.0.0.0', true],
  159. ['12.0.0.1', true],
  160. ['12.0.0.31', false],
  161. ['13.0.0.0', true],
  162. ['13.0.0.1', false]
  163. ];
  164. }
  165. /**
  166. * @dataProvider shouldRunDataProvider
  167. *
  168. * @param string $from
  169. * @param boolean $expected
  170. */
  171. public function testShouldRun($from, $expected) {
  172. $config = $this->createMock(IConfig::class);
  173. $config->expects($this->any())
  174. ->method('getSystemValue')
  175. ->with('version', '0.0.0')
  176. ->willReturn($from);
  177. $repair = new RepairInvalidPaths(\OC::$server->getDatabaseConnection(), $config);
  178. $this->assertEquals($expected, $this->invokePrivate($repair, 'shouldRun'));
  179. }
  180. }