RequestSharedSecretTest.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace OCA\Federation\Tests\BackgroundJob;
  8. use GuzzleHttp\Exception\ConnectException;
  9. use OCA\Federation\BackgroundJob\RequestSharedSecret;
  10. use OCA\Federation\TrustedServers;
  11. use OCP\AppFramework\Http;
  12. use OCP\AppFramework\Utility\ITimeFactory;
  13. use OCP\BackgroundJob\IJobList;
  14. use OCP\Http\Client\IClient;
  15. use OCP\Http\Client\IClientService;
  16. use OCP\Http\Client\IResponse;
  17. use OCP\IURLGenerator;
  18. use OCP\OCS\IDiscoveryService;
  19. use PHPUnit\Framework\MockObject\MockObject;
  20. use Psr\Log\LoggerInterface;
  21. use Test\TestCase;
  22. class RequestSharedSecretTest extends TestCase {
  23. /** @var MockObject|IClientService */
  24. private $httpClientService;
  25. /** @var MockObject|IClient */
  26. private $httpClient;
  27. /** @var MockObject|IJobList */
  28. private $jobList;
  29. /** @var MockObject|IURLGenerator */
  30. private $urlGenerator;
  31. /** @var MockObject|TrustedServers */
  32. private $trustedServers;
  33. /** @var MockObject|IResponse */
  34. private $response;
  35. /** @var MockObject|IDiscoveryService */
  36. private $discoveryService;
  37. /** @var MockObject|LoggerInterface */
  38. private $logger;
  39. /** @var MockObject|ITimeFactory */
  40. private $timeFactory;
  41. /** @var RequestSharedSecret */
  42. private $requestSharedSecret;
  43. protected function setUp(): void {
  44. parent::setUp();
  45. $this->httpClientService = $this->createMock(IClientService::class);
  46. $this->httpClient = $this->getMockBuilder(IClient::class)->getMock();
  47. $this->jobList = $this->getMockBuilder(IJobList::class)->getMock();
  48. $this->urlGenerator = $this->getMockBuilder(IURLGenerator::class)->getMock();
  49. $this->trustedServers = $this->getMockBuilder(TrustedServers::class)
  50. ->disableOriginalConstructor()->getMock();
  51. $this->response = $this->getMockBuilder(IResponse::class)->getMock();
  52. $this->discoveryService = $this->getMockBuilder(IDiscoveryService::class)->getMock();
  53. $this->logger = $this->createMock(LoggerInterface::class);
  54. $this->timeFactory = $this->createMock(ITimeFactory::class);
  55. $this->discoveryService->expects($this->any())->method('discover')->willReturn([]);
  56. $this->httpClientService->expects($this->any())->method('newClient')->willReturn($this->httpClient);
  57. $this->requestSharedSecret = new RequestSharedSecret(
  58. $this->httpClientService,
  59. $this->urlGenerator,
  60. $this->jobList,
  61. $this->trustedServers,
  62. $this->discoveryService,
  63. $this->logger,
  64. $this->timeFactory
  65. );
  66. }
  67. /**
  68. * @dataProvider dataTestStart
  69. *
  70. * @param bool $isTrustedServer
  71. * @param bool $retainBackgroundJob
  72. */
  73. public function testStart($isTrustedServer, $retainBackgroundJob): void {
  74. /** @var RequestSharedSecret |MockObject $requestSharedSecret */
  75. $requestSharedSecret = $this->getMockBuilder('OCA\Federation\BackgroundJob\RequestSharedSecret')
  76. ->setConstructorArgs(
  77. [
  78. $this->httpClientService,
  79. $this->urlGenerator,
  80. $this->jobList,
  81. $this->trustedServers,
  82. $this->discoveryService,
  83. $this->logger,
  84. $this->timeFactory
  85. ]
  86. )->setMethods(['parentStart'])->getMock();
  87. $this->invokePrivate($requestSharedSecret, 'argument', [['url' => 'url', 'token' => 'token']]);
  88. $this->trustedServers->expects($this->once())->method('isTrustedServer')
  89. ->with('url')->willReturn($isTrustedServer);
  90. if ($isTrustedServer) {
  91. $requestSharedSecret->expects($this->once())->method('parentStart');
  92. } else {
  93. $requestSharedSecret->expects($this->never())->method('parentStart');
  94. }
  95. $this->invokePrivate($requestSharedSecret, 'retainJob', [$retainBackgroundJob]);
  96. $this->jobList->expects($this->once())->method('remove');
  97. $this->timeFactory->method('getTime')->willReturn(42);
  98. if ($retainBackgroundJob) {
  99. $this->jobList->expects($this->once())
  100. ->method('add')
  101. ->with(
  102. RequestSharedSecret::class,
  103. [
  104. 'url' => 'url',
  105. 'token' => 'token',
  106. 'created' => 42,
  107. 'attempt' => 1,
  108. ]
  109. );
  110. } else {
  111. $this->jobList->expects($this->never())->method('add');
  112. }
  113. $requestSharedSecret->start($this->jobList);
  114. }
  115. public function dataTestStart() {
  116. return [
  117. [true, true],
  118. [true, false],
  119. [false, false],
  120. ];
  121. }
  122. /**
  123. * @dataProvider dataTestRun
  124. *
  125. * @param int $statusCode
  126. */
  127. public function testRun(int $statusCode, int $attempt = 0): void {
  128. $target = 'targetURL';
  129. $source = 'sourceURL';
  130. $token = 'token';
  131. $argument = ['url' => $target, 'token' => $token, 'attempt' => $attempt];
  132. $this->timeFactory->method('getTime')->willReturn(42);
  133. $this->urlGenerator->expects($this->once())->method('getAbsoluteURL')->with('/')
  134. ->willReturn($source);
  135. $this->httpClient->expects($this->once())->method('post')
  136. ->with(
  137. $target . '/ocs/v2.php/apps/federation/api/v1/request-shared-secret',
  138. [
  139. 'body' =>
  140. [
  141. 'url' => $source,
  142. 'token' => $token,
  143. 'format' => 'json',
  144. ],
  145. 'timeout' => 3,
  146. 'connect_timeout' => 3,
  147. ]
  148. )->willReturn($this->response);
  149. $this->response->expects($this->once())->method('getStatusCode')
  150. ->willReturn($statusCode);
  151. $this->invokePrivate($this->requestSharedSecret, 'run', [$argument]);
  152. if (
  153. $statusCode !== Http::STATUS_OK
  154. && ($statusCode !== Http::STATUS_FORBIDDEN || $attempt < 5)
  155. ) {
  156. $this->assertTrue($this->invokePrivate($this->requestSharedSecret, 'retainJob'));
  157. } else {
  158. $this->assertFalse($this->invokePrivate($this->requestSharedSecret, 'retainJob'));
  159. }
  160. }
  161. public function dataTestRun() {
  162. return [
  163. [Http::STATUS_OK],
  164. [Http::STATUS_FORBIDDEN, 5],
  165. [Http::STATUS_FORBIDDEN],
  166. [Http::STATUS_CONFLICT],
  167. ];
  168. }
  169. public function testRunExpired(): void {
  170. $target = 'targetURL';
  171. $source = 'sourceURL';
  172. $token = 'token';
  173. $created = 42;
  174. $argument = [
  175. 'url' => $target,
  176. 'token' => $token,
  177. 'created' => $created,
  178. ];
  179. $this->urlGenerator->expects($this->once())
  180. ->method('getAbsoluteURL')
  181. ->with('/')
  182. ->willReturn($source);
  183. $this->timeFactory->method('getTime')
  184. ->willReturn($created + 2592000 + 1);
  185. $this->trustedServers->expects($this->once())
  186. ->method('setServerStatus')
  187. ->with(
  188. $target,
  189. TrustedServers::STATUS_FAILURE
  190. );
  191. $this->invokePrivate($this->requestSharedSecret, 'run', [$argument]);
  192. }
  193. public function testRunConnectionError(): void {
  194. $target = 'targetURL';
  195. $source = 'sourceURL';
  196. $token = 'token';
  197. $argument = ['url' => $target, 'token' => $token];
  198. $this->timeFactory->method('getTime')->willReturn(42);
  199. $this->urlGenerator
  200. ->expects($this->once())
  201. ->method('getAbsoluteURL')
  202. ->with('/')
  203. ->willReturn($source);
  204. $this->httpClient
  205. ->expects($this->once())
  206. ->method('post')
  207. ->with(
  208. $target . '/ocs/v2.php/apps/federation/api/v1/request-shared-secret',
  209. [
  210. 'body' =>
  211. [
  212. 'url' => $source,
  213. 'token' => $token,
  214. 'format' => 'json',
  215. ],
  216. 'timeout' => 3,
  217. 'connect_timeout' => 3,
  218. ]
  219. )->willThrowException($this->createMock(ConnectException::class));
  220. $this->invokePrivate($this->requestSharedSecret, 'run', [$argument]);
  221. $this->assertTrue($this->invokePrivate($this->requestSharedSecret, 'retainJob'));
  222. }
  223. }