LookupPluginTest.php 14 KB

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