LookupPluginTest.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
  4. *
  5. * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
  6. *
  7. * @license GNU AGPL version 3 or any later version
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Affero General Public License as
  11. * published by the Free Software Foundation, either version 3 of the
  12. * License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Affero General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Affero General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. */
  23. namespace Test\Collaboration\Collaborators;
  24. use OC\Collaboration\Collaborators\LookupPlugin;
  25. use OC\Federation\CloudId;
  26. use OCP\Collaboration\Collaborators\ISearchResult;
  27. use OCP\Collaboration\Collaborators\SearchResultType;
  28. use OCP\Federation\ICloudId;
  29. use OCP\Federation\ICloudIdManager;
  30. use OCP\Http\Client\IClient;
  31. use OCP\Http\Client\IClientService;
  32. use OCP\Http\Client\IResponse;
  33. use OCP\IConfig;
  34. use OCP\IUser;
  35. use OCP\IUserSession;
  36. use OCP\Share\IShare;
  37. use PHPUnit\Framework\MockObject\MockObject;
  38. use Psr\Log\LoggerInterface;
  39. use Test\TestCase;
  40. class LookupPluginTest extends TestCase {
  41. /** @var IConfig|MockObject */
  42. protected $config;
  43. /** @var IClientService|MockObject */
  44. protected $clientService;
  45. /** @var IUserSession|MockObject */
  46. protected $userSession;
  47. /** @var ICloudIdManager|MockObject */
  48. protected $cloudIdManager;
  49. /** @var LookupPlugin */
  50. protected $plugin;
  51. /** @var LoggerInterface|MockObject */
  52. protected $logger;
  53. protected function setUp(): void {
  54. parent::setUp();
  55. $this->userSession = $this->createMock(IUserSession::class);
  56. $this->cloudIdManager = $this->createMock(ICloudIdManager::class);
  57. $this->config = $this->createMock(IConfig::class);
  58. $this->logger = $this->createMock(LoggerInterface::class);
  59. $this->clientService = $this->createMock(IClientService::class);
  60. $cloudId = $this->createMock(ICloudId::class);
  61. $cloudId->expects($this->any())->method('getRemote')->willReturn('myNextcloud.net');
  62. $user = $this->createMock(IUser::class);
  63. $user->expects($this->any())->method('getCloudId')->willReturn('user@myNextcloud.net');
  64. $this->userSession->expects($this->any())->method('getUser')
  65. ->willReturn($user);
  66. $this->cloudIdManager->expects($this->any())->method('resolveCloudId')
  67. ->willReturnCallback(function ($cloudId) {
  68. if ($cloudId === 'user@myNextcloud.net') {
  69. return new CloudId('user@myNextcloud.net', 'user', 'myNextcloud.net');
  70. }
  71. return new CloudId('user@someNextcloud.net', 'user', 'someNextcloud.net');
  72. });
  73. $this->plugin = new LookupPlugin(
  74. $this->config,
  75. $this->clientService,
  76. $this->userSession,
  77. $this->cloudIdManager,
  78. $this->logger
  79. );
  80. }
  81. public function testSearchNoLookupServerURI() {
  82. $this->config->expects($this->once())
  83. ->method('getAppValue')
  84. ->with('files_sharing', 'lookupServerEnabled', 'yes')
  85. ->willReturn('yes');
  86. $this->config->expects($this->exactly(2))
  87. ->method('getSystemValueBool')
  88. ->withConsecutive(
  89. ['gs.enabled', false],
  90. ['has_internet_connection', true],
  91. )->willReturnOnConsecutiveCalls(
  92. false,
  93. true,
  94. );
  95. $this->config->expects($this->once())
  96. ->method('getSystemValueString')
  97. ->with('lookup_server', 'https://lookup.nextcloud.com')
  98. ->willReturn('');
  99. $this->clientService->expects($this->never())
  100. ->method('newClient');
  101. /** @var ISearchResult|MockObject $searchResult */
  102. $searchResult = $this->createMock(ISearchResult::class);
  103. $this->plugin->search('foobar', 10, 0, $searchResult);
  104. }
  105. public function testSearchNoInternet() {
  106. $this->config->expects($this->once())
  107. ->method('getAppValue')
  108. ->with('files_sharing', 'lookupServerEnabled', 'yes')
  109. ->willReturn('yes');
  110. $this->config->expects($this->exactly(2))
  111. ->method('getSystemValueBool')
  112. ->withConsecutive(
  113. ['gs.enabled', false],
  114. ['has_internet_connection', true],
  115. )->willReturnOnConsecutiveCalls(
  116. false,
  117. false,
  118. );
  119. $this->clientService->expects($this->never())
  120. ->method('newClient');
  121. /** @var ISearchResult|MockObject $searchResult */
  122. $searchResult = $this->createMock(ISearchResult::class);
  123. $this->plugin->search('foobar', 10, 0, $searchResult);
  124. }
  125. /**
  126. * @dataProvider searchDataProvider
  127. * @param array $searchParams
  128. */
  129. public function testSearch(array $searchParams) {
  130. $type = new SearchResultType('lookup');
  131. /** @var ISearchResult|MockObject $searchResult */
  132. $searchResult = $this->createMock(ISearchResult::class);
  133. $searchResult->expects($this->once())
  134. ->method('addResultSet')
  135. ->with($type, $searchParams['expectedResult'], []);
  136. $this->config->expects($this->once())
  137. ->method('getAppValue')
  138. ->with('files_sharing', 'lookupServerEnabled', 'yes')
  139. ->willReturn('yes');
  140. $this->config->expects($this->exactly(2))
  141. ->method('getSystemValueBool')
  142. ->withConsecutive(
  143. ['gs.enabled', false],
  144. ['has_internet_connection', true],
  145. )->willReturnOnConsecutiveCalls(
  146. false,
  147. true,
  148. );
  149. $this->config->expects($this->once())
  150. ->method('getSystemValueString')
  151. ->with('lookup_server', 'https://lookup.nextcloud.com')
  152. ->willReturn($searchParams['server']);
  153. $response = $this->createMock(IResponse::class);
  154. $response->expects($this->once())
  155. ->method('getBody')
  156. ->willReturn(json_encode($searchParams['resultBody']));
  157. $client = $this->createMock(IClient::class);
  158. $client->expects($this->once())
  159. ->method('get')
  160. ->willReturnCallback(function ($url) use ($searchParams, $response) {
  161. $this->assertSame(strpos($url, $searchParams['server'] . '/users?search='), 0);
  162. $this->assertNotFalse(strpos($url, urlencode($searchParams['search'])));
  163. return $response;
  164. });
  165. $this->clientService->expects($this->once())
  166. ->method('newClient')
  167. ->willReturn($client);
  168. $moreResults = $this->plugin->search(
  169. $searchParams['search'],
  170. $searchParams['limit'],
  171. $searchParams['offset'],
  172. $searchResult
  173. );
  174. $this->assertFalse($moreResults);
  175. }
  176. /**
  177. * @dataProvider dataSearchEnableDisableLookupServer
  178. * @param array $searchParams
  179. * @param bool $GSEnabled
  180. * @param bool $LookupEnabled
  181. */
  182. public function testSearchEnableDisableLookupServer(array $searchParams, $GSEnabled, $LookupEnabled) {
  183. $type = new SearchResultType('lookup');
  184. /** @var ISearchResult|MockObject $searchResult */
  185. $searchResult = $this->createMock(ISearchResult::class);
  186. $this->config->expects($this->once())
  187. ->method('getAppValue')
  188. ->with('files_sharing', 'lookupServerEnabled', 'yes')
  189. ->willReturn($LookupEnabled ? 'yes' : 'no');
  190. if ($GSEnabled || $LookupEnabled) {
  191. $searchResult->expects($this->once())
  192. ->method('addResultSet')
  193. ->with($type, $searchParams['expectedResult'], []);
  194. $this->config->expects($this->exactly(2))
  195. ->method('getSystemValueBool')
  196. ->withConsecutive(
  197. ['gs.enabled', false],
  198. ['has_internet_connection', true],
  199. )->willReturnOnConsecutiveCalls(
  200. $GSEnabled,
  201. true,
  202. );
  203. $this->config->expects($this->once())
  204. ->method('getSystemValueString')
  205. ->with('lookup_server', 'https://lookup.nextcloud.com')
  206. ->willReturn($searchParams['server']);
  207. $response = $this->createMock(IResponse::class);
  208. $response->expects($this->once())
  209. ->method('getBody')
  210. ->willReturn(json_encode($searchParams['resultBody']));
  211. $client = $this->createMock(IClient::class);
  212. $client->expects($this->once())
  213. ->method('get')
  214. ->willReturnCallback(function ($url) use ($searchParams, $response) {
  215. $this->assertSame(strpos($url, $searchParams['server'] . '/users?search='), 0);
  216. $this->assertNotFalse(strpos($url, urlencode($searchParams['search'])));
  217. return $response;
  218. });
  219. $this->clientService->expects($this->once())
  220. ->method('newClient')
  221. ->willReturn($client);
  222. } else {
  223. $searchResult->expects($this->never())->method('addResultSet');
  224. $this->config->expects($this->exactly(2))
  225. ->method('getSystemValueBool')
  226. ->withConsecutive(
  227. ['gs.enabled', false],
  228. ['has_internet_connection', true],
  229. )->willReturnOnConsecutiveCalls(
  230. $GSEnabled,
  231. true,
  232. );
  233. }
  234. $moreResults = $this->plugin->search(
  235. $searchParams['search'],
  236. $searchParams['limit'],
  237. $searchParams['offset'],
  238. $searchResult
  239. );
  240. $this->assertFalse($moreResults);
  241. }
  242. public function testSearchLookupServerDisabled() {
  243. $this->config->expects($this->once())
  244. ->method('getAppValue')
  245. ->with('files_sharing', 'lookupServerEnabled', 'yes')
  246. ->willReturn('no');
  247. /** @var ISearchResult|MockObject $searchResult */
  248. $searchResult = $this->createMock(ISearchResult::class);
  249. $searchResult->expects($this->never())
  250. ->method('addResultSet');
  251. $searchResult->expects($this->never())
  252. ->method('markExactIdMatch');
  253. $this->assertFalse($this->plugin->search('irr', 10, 0, $searchResult));
  254. }
  255. public function dataSearchEnableDisableLookupServer() {
  256. $fedIDs = [
  257. 'foo@enceladus.moon',
  258. 'foobar@enceladus.moon',
  259. 'foongus@enceladus.moon',
  260. ];
  261. return [
  262. [[
  263. 'search' => 'foo',
  264. 'limit' => 10,
  265. 'offset' => 0,
  266. 'server' => 'https://lookup.example.io',
  267. 'resultBody' => [
  268. ['federationId' => $fedIDs[0]],
  269. ['federationId' => $fedIDs[1]],
  270. ['federationId' => $fedIDs[2]],
  271. ],
  272. 'expectedResult' => [
  273. [
  274. 'label' => $fedIDs[0],
  275. 'value' => [
  276. 'shareType' => IShare::TYPE_REMOTE,
  277. 'globalScale' => true,
  278. 'shareWith' => $fedIDs[0]
  279. ],
  280. 'extra' => ['federationId' => $fedIDs[0]],
  281. ],
  282. [
  283. 'label' => $fedIDs[1],
  284. 'value' => [
  285. 'shareType' => IShare::TYPE_REMOTE,
  286. 'globalScale' => true,
  287. 'shareWith' => $fedIDs[1]
  288. ],
  289. 'extra' => ['federationId' => $fedIDs[1]],
  290. ],
  291. [
  292. 'label' => $fedIDs[2],
  293. 'value' => [
  294. 'shareType' => IShare::TYPE_REMOTE,
  295. 'globalScale' => true,
  296. 'shareWith' => $fedIDs[2]
  297. ],
  298. 'extra' => ['federationId' => $fedIDs[2]],
  299. ],
  300. ]
  301. ],// GS , Lookup
  302. true, true
  303. ],
  304. [[
  305. 'search' => 'foo',
  306. 'limit' => 10,
  307. 'offset' => 0,
  308. 'server' => 'https://lookup.example.io',
  309. 'resultBody' => [
  310. ['federationId' => $fedIDs[0]],
  311. ['federationId' => $fedIDs[1]],
  312. ['federationId' => $fedIDs[2]],
  313. ],
  314. 'expectedResult' => [
  315. [
  316. 'label' => $fedIDs[0],
  317. 'value' => [
  318. 'shareType' => IShare::TYPE_REMOTE,
  319. 'globalScale' => true,
  320. 'shareWith' => $fedIDs[0]
  321. ],
  322. 'extra' => ['federationId' => $fedIDs[0]],
  323. ],
  324. [
  325. 'label' => $fedIDs[1],
  326. 'value' => [
  327. 'shareType' => IShare::TYPE_REMOTE,
  328. 'globalScale' => true,
  329. 'shareWith' => $fedIDs[1]
  330. ],
  331. 'extra' => ['federationId' => $fedIDs[1]],
  332. ],
  333. [
  334. 'label' => $fedIDs[2],
  335. 'value' => [
  336. 'shareType' => IShare::TYPE_REMOTE,
  337. 'globalScale' => true,
  338. 'shareWith' => $fedIDs[2]
  339. ],
  340. 'extra' => ['federationId' => $fedIDs[2]],
  341. ],
  342. ]
  343. ],// GS , Lookup
  344. true, false
  345. ],
  346. [[
  347. 'search' => 'foo',
  348. 'limit' => 10,
  349. 'offset' => 0,
  350. 'server' => 'https://lookup.example.io',
  351. 'resultBody' => [
  352. ['federationId' => $fedIDs[0]],
  353. ['federationId' => $fedIDs[1]],
  354. ['federationId' => $fedIDs[2]],
  355. ],
  356. 'expectedResult' => [
  357. [
  358. 'label' => $fedIDs[0],
  359. 'value' => [
  360. 'shareType' => IShare::TYPE_REMOTE,
  361. 'globalScale' => false,
  362. 'shareWith' => $fedIDs[0]
  363. ],
  364. 'extra' => ['federationId' => $fedIDs[0]],
  365. ],
  366. [
  367. 'label' => $fedIDs[1],
  368. 'value' => [
  369. 'shareType' => IShare::TYPE_REMOTE,
  370. 'globalScale' => false,
  371. 'shareWith' => $fedIDs[1]
  372. ],
  373. 'extra' => ['federationId' => $fedIDs[1]],
  374. ],
  375. [
  376. 'label' => $fedIDs[2],
  377. 'value' => [
  378. 'shareType' => IShare::TYPE_REMOTE,
  379. 'globalScale' => false,
  380. 'shareWith' => $fedIDs[2]
  381. ],
  382. 'extra' => ['federationId' => $fedIDs[2]],
  383. ],
  384. ]
  385. ],// GS , Lookup
  386. false, true
  387. ],
  388. [[
  389. 'search' => 'foo',
  390. 'limit' => 10,
  391. 'offset' => 0,
  392. 'server' => 'https://lookup.example.io',
  393. 'resultBody' => [
  394. ['federationId' => $fedIDs[0]],
  395. ['federationId' => $fedIDs[1]],
  396. ['federationId' => $fedIDs[2]],
  397. ],
  398. 'expectedResult' => [
  399. [
  400. 'label' => $fedIDs[0],
  401. 'value' => [
  402. 'shareType' => IShare::TYPE_REMOTE,
  403. 'shareWith' => $fedIDs[0]
  404. ],
  405. 'extra' => ['federationId' => $fedIDs[0]],
  406. ],
  407. [
  408. 'label' => $fedIDs[1],
  409. 'value' => [
  410. 'shareType' => IShare::TYPE_REMOTE,
  411. 'shareWith' => $fedIDs[1]
  412. ],
  413. 'extra' => ['federationId' => $fedIDs[1]],
  414. ],
  415. [
  416. 'label' => $fedIDs[2],
  417. 'value' => [
  418. 'shareType' => IShare::TYPE_REMOTE,
  419. 'shareWith' => $fedIDs[2]
  420. ],
  421. 'extra' => ['federationId' => $fedIDs[2]],
  422. ],
  423. ]
  424. ],// GS , Lookup
  425. false, false
  426. ],
  427. ];
  428. }
  429. public function searchDataProvider() {
  430. $fedIDs = [
  431. 'foo@enceladus.moon',
  432. 'foobar@enceladus.moon',
  433. 'foongus@enceladus.moon',
  434. ];
  435. return [
  436. // #0, standard search with results
  437. [[
  438. 'search' => 'foo',
  439. 'limit' => 10,
  440. 'offset' => 0,
  441. 'server' => 'https://lookup.example.io',
  442. 'resultBody' => [
  443. ['federationId' => $fedIDs[0]],
  444. ['federationId' => $fedIDs[1]],
  445. ['federationId' => $fedIDs[2]],
  446. ],
  447. 'expectedResult' => [
  448. [
  449. 'label' => $fedIDs[0],
  450. 'value' => [
  451. 'shareType' => IShare::TYPE_REMOTE,
  452. 'globalScale' => false,
  453. 'shareWith' => $fedIDs[0]
  454. ],
  455. 'extra' => ['federationId' => $fedIDs[0]],
  456. ],
  457. [
  458. 'label' => $fedIDs[1],
  459. 'value' => [
  460. 'shareType' => IShare::TYPE_REMOTE,
  461. 'globalScale' => false,
  462. 'shareWith' => $fedIDs[1]
  463. ],
  464. 'extra' => ['federationId' => $fedIDs[1]],
  465. ],
  466. [
  467. 'label' => $fedIDs[2],
  468. 'value' => [
  469. 'shareType' => IShare::TYPE_REMOTE,
  470. 'globalScale' => false,
  471. 'shareWith' => $fedIDs[2]
  472. ],
  473. 'extra' => ['federationId' => $fedIDs[2]],
  474. ],
  475. ]
  476. ]],
  477. // #1, search without results
  478. [[
  479. 'search' => 'foo',
  480. 'limit' => 10,
  481. 'offset' => 0,
  482. 'server' => 'https://lookup.example.io',
  483. 'resultBody' => [],
  484. 'expectedResult' => [],
  485. ]],
  486. ];
  487. }
  488. }