BackgroundJobTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Joas Schilling <coding@schilljs.com>
  6. *
  7. * @license AGPL-3.0
  8. *
  9. * This code is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Affero General Public License, version 3,
  11. * as published by the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU Affero General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public License, version 3,
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>
  20. *
  21. */
  22. namespace OCA\UpdateNotification\Tests\Notification;
  23. use OCA\UpdateNotification\Notification\BackgroundJob;
  24. use OCP\App\IAppManager;
  25. use OCP\Http\Client\IClientService;
  26. use OCP\IConfig;
  27. use OCP\IGroupManager;
  28. use OCP\IURLGenerator;
  29. use OCP\IUser;
  30. use OCP\Notification\IManager;
  31. use Test\TestCase;
  32. class BackgroundJobTest extends TestCase {
  33. /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
  34. protected $config;
  35. /** @var IManager|\PHPUnit_Framework_MockObject_MockObject */
  36. protected $notificationManager;
  37. /** @var IGroupManager|\PHPUnit_Framework_MockObject_MockObject */
  38. protected $groupManager;
  39. /** @var IAppManager|\PHPUnit_Framework_MockObject_MockObject */
  40. protected $appManager;
  41. /** @var IClientService|\PHPUnit_Framework_MockObject_MockObject */
  42. protected $client;
  43. /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */
  44. protected $urlGenerator;
  45. public function setUp() {
  46. parent::setUp();
  47. $this->config = $this->getMockBuilder('OCP\IConfig')->getMock();
  48. $this->notificationManager = $this->getMockBuilder('OCP\Notification\IManager')->getMock();
  49. $this->groupManager = $this->getMockBuilder('OCP\IGroupManager')->getMock();
  50. $this->appManager = $this->getMockBuilder('OCP\App\IAppManager')->getMock();
  51. $this->client = $this->getMockBuilder('OCP\Http\Client\IClientService')->getMock();
  52. $this->urlGenerator = $this->getMockBuilder('OCP\IURLGenerator')->getMock();
  53. }
  54. /**
  55. * @param array $methods
  56. * @return BackgroundJob|\PHPUnit_Framework_MockObject_MockObject
  57. */
  58. protected function getJob(array $methods = []) {
  59. if (empty($methods)) {
  60. return new BackgroundJob(
  61. $this->config,
  62. $this->notificationManager,
  63. $this->groupManager,
  64. $this->appManager,
  65. $this->client,
  66. $this->urlGenerator
  67. );
  68. } {
  69. return $this->getMockBuilder('OCA\UpdateNotification\Notification\BackgroundJob')
  70. ->setConstructorArgs([
  71. $this->config,
  72. $this->notificationManager,
  73. $this->groupManager,
  74. $this->appManager,
  75. $this->client,
  76. $this->urlGenerator,
  77. ])
  78. ->setMethods($methods)
  79. ->getMock();
  80. }
  81. }
  82. public function testRun() {
  83. $job = $this->getJob([
  84. 'checkCoreUpdate',
  85. 'checkAppUpdates',
  86. ]);
  87. $job->expects($this->once())
  88. ->method('checkCoreUpdate');
  89. $job->expects($this->once())
  90. ->method('checkAppUpdates');
  91. $this->invokePrivate($job, 'run', [null]);
  92. }
  93. public function dataCheckCoreUpdate() {
  94. return [
  95. ['daily', null, null],
  96. ['git', null, null],
  97. ['beta', false, null],
  98. ['beta', [
  99. 'version' => '9.2.0',
  100. ], '9.2.0'],
  101. ['stable', false, null],
  102. ['stable', [
  103. 'version' => '9.2.0',
  104. ], '9.2.0'],
  105. ['production', false, null],
  106. ['production', [
  107. 'version' => '9.2.0',
  108. ], '9.2.0'],
  109. ];
  110. }
  111. /**
  112. * @dataProvider dataCheckCoreUpdate
  113. *
  114. * @param string $channel
  115. * @param mixed $versionCheck
  116. * @param null|string $notification
  117. */
  118. public function testCheckCoreUpdate($channel, $versionCheck, $notification) {
  119. $job = $this->getJob([
  120. 'getChannel',
  121. 'createVersionCheck',
  122. 'createNotifications',
  123. ]);
  124. $job->expects($this->once())
  125. ->method('getChannel')
  126. ->willReturn($channel);
  127. if ($versionCheck === null) {
  128. $job->expects($this->never())
  129. ->method('createVersionCheck');
  130. } else {
  131. $check = $this->getMockBuilder('OC\Updater\VersionCheck')
  132. ->disableOriginalConstructor()
  133. ->getMock();
  134. $check->expects($this->once())
  135. ->method('check')
  136. ->willReturn($versionCheck);
  137. $job->expects($this->once())
  138. ->method('createVersionCheck')
  139. ->willReturn($check);
  140. }
  141. if ($notification === null) {
  142. $this->urlGenerator->expects($this->never())
  143. ->method('linkToRouteAbsolute');
  144. $job->expects($this->never())
  145. ->method('createNotifications');
  146. } else {
  147. $this->urlGenerator->expects($this->once())
  148. ->method('linkToRouteAbsolute')
  149. ->with('settings_admin')
  150. ->willReturn('admin-url');
  151. $job->expects($this->once())
  152. ->method('createNotifications')
  153. ->willReturn('core', $notification, 'admin-url#updater');
  154. }
  155. $this->invokePrivate($job, 'checkCoreUpdate');
  156. }
  157. public function dataCheckAppUpdates() {
  158. return [
  159. [
  160. ['app1', 'app2'],
  161. [
  162. ['app1', false],
  163. ['app2', '1.9.2'],
  164. ],
  165. [
  166. ['app2', '1.9.2', 'apps-url#app-app2'],
  167. ],
  168. ],
  169. ];
  170. }
  171. /**
  172. * @dataProvider dataCheckAppUpdates
  173. *
  174. * @param string[] $apps
  175. * @param array $isUpdateAvailable
  176. * @param array $notifications
  177. */
  178. public function testCheckAppUpdates(array $apps, array $isUpdateAvailable, array $notifications) {
  179. $job = $this->getJob([
  180. 'isUpdateAvailable',
  181. 'createNotifications',
  182. ]);
  183. $this->appManager->expects($this->once())
  184. ->method('getInstalledApps')
  185. ->willReturn($apps);
  186. $job->expects($this->exactly(sizeof($apps)))
  187. ->method('isUpdateAvailable')
  188. ->willReturnMap($isUpdateAvailable);
  189. $this->urlGenerator->expects($this->exactly(sizeof($notifications)))
  190. ->method('linkToRouteAbsolute')
  191. ->with('settings.AppSettings.viewApps')
  192. ->willReturn('apps-url');
  193. $mockedMethod = $job->expects($this->exactly(sizeof($notifications)))
  194. ->method('createNotifications');
  195. call_user_func_array([$mockedMethod, 'withConsecutive'], $notifications);
  196. $this->invokePrivate($job, 'checkAppUpdates');
  197. }
  198. public function dataCreateNotifications() {
  199. return [
  200. ['app1', '1.0.0', 'link1', '1.0.0', false, false, null, null],
  201. ['app2', '1.0.1', 'link2', '1.0.0', '1.0.0', true, ['user1'], [['user1']]],
  202. ['app3', '1.0.1', 'link3', false, false, true, ['user2', 'user3'], [['user2'], ['user3']]],
  203. ];
  204. }
  205. /**
  206. * @dataProvider dataCreateNotifications
  207. *
  208. * @param string $app
  209. * @param string $version
  210. * @param string $url
  211. * @param string|false $lastNotification
  212. * @param string|false $callDelete
  213. * @param bool $createNotification
  214. * @param string[]|null $users
  215. * @param array|null $userNotifications
  216. */
  217. public function testCreateNotifications($app, $version, $url, $lastNotification, $callDelete, $createNotification, $users, $userNotifications) {
  218. $job = $this->getJob([
  219. 'deleteOutdatedNotifications',
  220. 'getUsersToNotify',
  221. ]);
  222. $this->config->expects($this->once())
  223. ->method('getAppValue')
  224. ->with('updatenotification', $app, false)
  225. ->willReturn($lastNotification);
  226. if ($lastNotification !== $version) {
  227. $this->config->expects($this->once())
  228. ->method('setAppValue')
  229. ->with('updatenotification', $app, $version);
  230. }
  231. if ($callDelete === false) {
  232. $job->expects($this->never())
  233. ->method('deleteOutdatedNotifications');
  234. } else {
  235. $job->expects($this->once())
  236. ->method('deleteOutdatedNotifications')
  237. ->with($app, $callDelete);
  238. }
  239. if ($users === null) {
  240. $job->expects($this->never())
  241. ->method('getUsersToNotify');
  242. } else {
  243. $job->expects($this->once())
  244. ->method('getUsersToNotify')
  245. ->willReturn($users);
  246. }
  247. if ($createNotification) {
  248. $notification = $this->getMockBuilder('OCP\Notification\INotification')->getMock();
  249. $notification->expects($this->once())
  250. ->method('setApp')
  251. ->with('updatenotification')
  252. ->willReturnSelf();
  253. $notification->expects($this->once())
  254. ->method('setDateTime')
  255. ->willReturnSelf();
  256. $notification->expects($this->once())
  257. ->method('setObject')
  258. ->with($app, $version)
  259. ->willReturnSelf();
  260. $notification->expects($this->once())
  261. ->method('setSubject')
  262. ->with('update_available')
  263. ->willReturnSelf();
  264. $notification->expects($this->once())
  265. ->method('setLink')
  266. ->with($url)
  267. ->willReturnSelf();
  268. if ($userNotifications !== null) {
  269. $mockedMethod = $notification->expects($this->exactly(sizeof($userNotifications)))
  270. ->method('setUser')
  271. ->willReturnSelf();
  272. call_user_func_array([$mockedMethod, 'withConsecutive'], $userNotifications);
  273. $this->notificationManager->expects($this->exactly(sizeof($userNotifications)))
  274. ->method('notify')
  275. ->willReturn($notification);
  276. }
  277. $this->notificationManager->expects($this->once())
  278. ->method('createNotification')
  279. ->willReturn($notification);
  280. } else {
  281. $this->notificationManager->expects($this->never())
  282. ->method('createNotification');
  283. }
  284. $this->invokePrivate($job, 'createNotifications', [$app, $version, $url]);
  285. }
  286. public function dataGetUsersToNotify() {
  287. return [
  288. [['g1', 'g2'], ['g1' => null, 'g2' => ['u1', 'u2']], ['u1', 'u2']],
  289. [['g3', 'g4'], ['g3' => ['u1', 'u2'], 'g4' => ['u2', 'u3']], ['u1', 'u2', 'u3']],
  290. ];
  291. }
  292. /**
  293. * @dataProvider dataGetUsersToNotify
  294. * @param string[] $groups
  295. * @param array $groupUsers
  296. * @param string[] $expected
  297. */
  298. public function testGetUsersToNotify($groups, array $groupUsers, array $expected) {
  299. $job = $this->getJob();
  300. $this->config->expects($this->once())
  301. ->method('getAppValue')
  302. ->with('updatenotification', 'notify_groups', '["admin"]')
  303. ->willReturn(json_encode($groups));
  304. $groupMap = [];
  305. foreach ($groupUsers as $gid => $uids) {
  306. if ($uids === null) {
  307. $group = null;
  308. } else {
  309. $group = $this->getGroup($gid);
  310. $group->expects($this->any())
  311. ->method('getUsers')
  312. ->willReturn($this->getUsers($uids));
  313. }
  314. $groupMap[] = [$gid, $group];
  315. }
  316. $this->groupManager->expects($this->exactly(sizeof($groups)))
  317. ->method('get')
  318. ->willReturnMap($groupMap);
  319. $result = $this->invokePrivate($job, 'getUsersToNotify');
  320. $this->assertEquals($expected, $result);
  321. // Test caching
  322. $result = $this->invokePrivate($job, 'getUsersToNotify');
  323. $this->assertEquals($expected, $result);
  324. }
  325. public function dataDeleteOutdatedNotifications() {
  326. return [
  327. ['app1', '1.1.0'],
  328. ['app2', '1.2.0'],
  329. ];
  330. }
  331. /**
  332. * @dataProvider dataDeleteOutdatedNotifications
  333. * @param string $app
  334. * @param string $version
  335. */
  336. public function testDeleteOutdatedNotifications($app, $version) {
  337. $notification = $this->getMockBuilder('OCP\Notification\INotification')->getMock();
  338. $notification->expects($this->once())
  339. ->method('setApp')
  340. ->with('updatenotification')
  341. ->willReturnSelf();
  342. $notification->expects($this->once())
  343. ->method('setObject')
  344. ->with($app, $version)
  345. ->willReturnSelf();
  346. $this->notificationManager->expects($this->once())
  347. ->method('createNotification')
  348. ->willReturn($notification);
  349. $this->notificationManager->expects($this->once())
  350. ->method('markProcessed')
  351. ->with($notification);
  352. $job = $this->getJob();
  353. $this->invokePrivate($job, 'deleteOutdatedNotifications', [$app, $version]);
  354. }
  355. /**
  356. * @param string[] $userIds
  357. * @return IUser[]|\PHPUnit_Framework_MockObject_MockObject[]
  358. */
  359. protected function getUsers(array $userIds) {
  360. $users = [];
  361. foreach ($userIds as $uid) {
  362. $user = $this->getMockBuilder('OCP\IUser')->getMock();
  363. $user->expects($this->any())
  364. ->method('getUID')
  365. ->willReturn($uid);
  366. $users[] = $user;
  367. }
  368. return $users;
  369. }
  370. /**
  371. * @param $gid
  372. * @return \OCP\IGroup|\PHPUnit_Framework_MockObject_MockObject
  373. */
  374. protected function getGroup($gid) {
  375. $group = $this->getMockBuilder('OCP\IGroup')->getMock();
  376. $group->expects($this->any())
  377. ->method('getGID')
  378. ->willReturn($gid);
  379. return $group;
  380. }
  381. }