CrontabManagerTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\Crontab\Test\Unit;
  7. use Magento\Framework\Crontab\CrontabManager;
  8. use Magento\Framework\Crontab\CrontabManagerInterface;
  9. use Magento\Framework\ShellInterface;
  10. use Magento\Framework\Phrase;
  11. use Magento\Framework\Exception\LocalizedException;
  12. use Magento\Framework\Filesystem;
  13. use Magento\Framework\App\Filesystem\DirectoryList;
  14. use Magento\Framework\Filesystem\Directory\ReadInterface;
  15. use Magento\Framework\Filesystem\DriverPool;
  16. class CrontabManagerTest extends \PHPUnit\Framework\TestCase
  17. {
  18. /**
  19. * @var ShellInterface|\PHPUnit_Framework_MockObject_MockObject
  20. */
  21. private $shellMock;
  22. /**
  23. * @var Filesystem|\PHPUnit_Framework_MockObject_MockObject
  24. */
  25. private $filesystemMock;
  26. /**
  27. * @var CrontabManager
  28. */
  29. private $crontabManager;
  30. /**
  31. * @return void
  32. */
  33. protected function setUp()
  34. {
  35. $this->shellMock = $this->getMockBuilder(ShellInterface::class)
  36. ->getMockForAbstractClass();
  37. $this->filesystemMock = $this->getMockBuilder(Filesystem::class)
  38. ->disableOriginalClone()
  39. ->disableOriginalConstructor()
  40. ->getMock();
  41. $this->crontabManager = new CrontabManager($this->shellMock, $this->filesystemMock);
  42. }
  43. /**
  44. * @return void
  45. */
  46. public function testGetTasksNoCrontab()
  47. {
  48. $exception = new \Exception('crontab: no crontab for user');
  49. $localizedException = new LocalizedException(new Phrase('Some error'), $exception);
  50. $this->shellMock->expects($this->once())
  51. ->method('execute')
  52. ->with('crontab -l', [])
  53. ->willThrowException($localizedException);
  54. $this->assertEquals([], $this->crontabManager->getTasks());
  55. }
  56. /**
  57. * @param string $content
  58. * @param array $tasks
  59. * @return void
  60. * @dataProvider getTasksDataProvider
  61. */
  62. public function testGetTasks($content, $tasks)
  63. {
  64. $this->shellMock->expects($this->once())
  65. ->method('execute')
  66. ->with('crontab -l', [])
  67. ->willReturn($content);
  68. $this->assertEquals($tasks, $this->crontabManager->getTasks());
  69. }
  70. /**
  71. * @return array
  72. */
  73. public function getTasksDataProvider()
  74. {
  75. return [
  76. [
  77. 'content' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
  78. . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL
  79. . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL
  80. . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL,
  81. 'tasks' => ['* * * * * /bin/php /var/www/magento/bin/magento cron:run'],
  82. ],
  83. [
  84. 'content' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
  85. . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL
  86. . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL
  87. . '* * * * * /bin/php /var/www/magento/bin/magento setup:cron:run' . PHP_EOL
  88. . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL,
  89. 'tasks' => [
  90. '* * * * * /bin/php /var/www/magento/bin/magento cron:run',
  91. '* * * * * /bin/php /var/www/magento/bin/magento setup:cron:run',
  92. ],
  93. ],
  94. [
  95. 'content' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL,
  96. 'tasks' => [],
  97. ],
  98. [
  99. 'content' => '',
  100. 'tasks' => [],
  101. ],
  102. ];
  103. }
  104. /**
  105. * @return void
  106. * @expectedException \Magento\Framework\Exception\LocalizedException
  107. * @expectedExceptionMessage Shell error
  108. */
  109. public function testRemoveTasksWithException()
  110. {
  111. $exception = new \Exception('Shell error');
  112. $localizedException = new LocalizedException(new Phrase('Some error'), $exception);
  113. $this->shellMock->expects($this->at(0))
  114. ->method('execute')
  115. ->with('crontab -l', [])
  116. ->willReturn('');
  117. $this->shellMock->expects($this->at(1))
  118. ->method('execute')
  119. ->with('echo "" | crontab -', [])
  120. ->willThrowException($localizedException);
  121. $this->crontabManager->removeTasks();
  122. }
  123. /**
  124. * @param string $contentBefore
  125. * @param string $contentAfter
  126. * @return void
  127. * @dataProvider removeTasksDataProvider
  128. */
  129. public function testRemoveTasks($contentBefore, $contentAfter)
  130. {
  131. $this->shellMock->expects($this->at(0))
  132. ->method('execute')
  133. ->with('crontab -l', [])
  134. ->willReturn($contentBefore);
  135. $this->shellMock->expects($this->at(1))
  136. ->method('execute')
  137. ->with('echo "' . $contentAfter . '" | crontab -', []);
  138. $this->crontabManager->removeTasks();
  139. }
  140. /**
  141. * @return array
  142. */
  143. public function removeTasksDataProvider()
  144. {
  145. return [
  146. [
  147. 'contentBefore' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
  148. . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL
  149. . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL
  150. . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL,
  151. 'contentAfter' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
  152. ],
  153. [
  154. 'contentBefore' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
  155. . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL
  156. . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL
  157. . '* * * * * /bin/php /var/www/magento/bin/magento setup:cron:run' . PHP_EOL
  158. . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL,
  159. 'contentAfter' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
  160. ],
  161. [
  162. 'contentBefore' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL,
  163. 'contentAfter' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
  164. ],
  165. [
  166. 'contentBefore' => '',
  167. 'contentAfter' => ''
  168. ],
  169. ];
  170. }
  171. /**
  172. * @return void
  173. * @expectedException \Magento\Framework\Exception\LocalizedException
  174. * @expectedExceptionMessage The list of tasks is empty. Add tasks and try again.
  175. */
  176. public function testSaveTasksWithEmptyTasksList()
  177. {
  178. $baseDirMock = $this->getMockBuilder(ReadInterface::class)
  179. ->getMockForAbstractClass();
  180. $baseDirMock->expects($this->never())
  181. ->method('getAbsolutePath')
  182. ->willReturn('/var/www/magento2/');
  183. $logDirMock = $this->getMockBuilder(ReadInterface::class)
  184. ->getMockForAbstractClass();
  185. $logDirMock->expects($this->never())
  186. ->method('getAbsolutePath');
  187. $this->filesystemMock->expects($this->any())
  188. ->method('getDirectoryRead')
  189. ->willReturnMap([
  190. [DirectoryList::ROOT, DriverPool::FILE, $baseDirMock],
  191. [DirectoryList::LOG, DriverPool::FILE, $logDirMock],
  192. ]);
  193. $this->crontabManager->saveTasks([]);
  194. }
  195. /**
  196. * @return void
  197. * @expectedException \Magento\Framework\Exception\LocalizedException
  198. * @expectedExceptionMessage The command shouldn't be empty. Enter and try again.
  199. */
  200. public function testSaveTasksWithoutCommand()
  201. {
  202. $baseDirMock = $this->getMockBuilder(ReadInterface::class)
  203. ->getMockForAbstractClass();
  204. $baseDirMock->expects($this->once())
  205. ->method('getAbsolutePath')
  206. ->willReturn('/var/www/magento2/');
  207. $logDirMock = $this->getMockBuilder(ReadInterface::class)
  208. ->getMockForAbstractClass();
  209. $logDirMock->expects($this->once())
  210. ->method('getAbsolutePath')
  211. ->willReturn('/var/www/magento2/var/log/');
  212. $this->filesystemMock->expects($this->any())
  213. ->method('getDirectoryRead')
  214. ->willReturnMap([
  215. [DirectoryList::ROOT, DriverPool::FILE, $baseDirMock],
  216. [DirectoryList::LOG, DriverPool::FILE, $logDirMock],
  217. ]);
  218. $this->crontabManager->saveTasks([
  219. 'myCron' => ['expression' => '* * * * *']
  220. ]);
  221. }
  222. /**
  223. * @param array $tasks
  224. * @param string $content
  225. * @param string $contentToSave
  226. * @return void
  227. * @dataProvider saveTasksDataProvider
  228. */
  229. public function testSaveTasks($tasks, $content, $contentToSave)
  230. {
  231. $baseDirMock = $this->getMockBuilder(ReadInterface::class)
  232. ->getMockForAbstractClass();
  233. $baseDirMock->expects($this->once())
  234. ->method('getAbsolutePath')
  235. ->willReturn('/var/www/magento2/');
  236. $logDirMock = $this->getMockBuilder(ReadInterface::class)
  237. ->getMockForAbstractClass();
  238. $logDirMock->expects($this->once())
  239. ->method('getAbsolutePath')
  240. ->willReturn('/var/www/magento2/var/log/');
  241. $this->filesystemMock->expects($this->any())
  242. ->method('getDirectoryRead')
  243. ->willReturnMap([
  244. [DirectoryList::ROOT, DriverPool::FILE, $baseDirMock],
  245. [DirectoryList::LOG, DriverPool::FILE, $logDirMock],
  246. ]);
  247. $this->shellMock->expects($this->at(0))
  248. ->method('execute')
  249. ->with('crontab -l', [])
  250. ->willReturn($content);
  251. $this->shellMock->expects($this->at(1))
  252. ->method('execute')
  253. ->with('echo "' . $contentToSave . '" | crontab -', []);
  254. $this->crontabManager->saveTasks($tasks);
  255. }
  256. /**
  257. * @return array
  258. */
  259. public function saveTasksDataProvider()
  260. {
  261. $content = '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
  262. . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL
  263. . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL
  264. . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL;
  265. return [
  266. [
  267. 'tasks' => [
  268. ['expression' => '* * * * *', 'command' => 'run.php']
  269. ],
  270. 'content' => $content,
  271. 'contentToSave' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
  272. . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL
  273. . '* * * * * ' . PHP_BINARY . ' run.php' . PHP_EOL
  274. . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL,
  275. ],
  276. [
  277. 'tasks' => [
  278. ['expression' => '1 2 3 4 5', 'command' => 'run.php']
  279. ],
  280. 'content' => $content,
  281. 'contentToSave' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
  282. . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL
  283. . '1 2 3 4 5 ' . PHP_BINARY . ' run.php' . PHP_EOL
  284. . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL,
  285. ],
  286. [
  287. 'tasks' => [
  288. ['command' => '{magentoRoot}run.php >> {magentoLog}cron.log']
  289. ],
  290. 'content' => $content,
  291. 'contentToSave' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
  292. . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL
  293. . '* * * * * ' . PHP_BINARY . ' /var/www/magento2/run.php >>'
  294. . ' /var/www/magento2/var/log/cron.log' . PHP_EOL
  295. . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL,
  296. ],
  297. [
  298. 'tasks' => [
  299. ['command' => '{magentoRoot}run.php % cron:run | grep -v "Ran \'jobs\' by schedule"']
  300. ],
  301. 'content' => $content,
  302. 'contentToSave' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
  303. . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL
  304. . '* * * * * ' . PHP_BINARY . ' /var/www/magento2/run.php'
  305. . ' %% cron:run | grep -v \"Ran \'jobs\' by schedule\"' . PHP_EOL
  306. . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL,
  307. ],
  308. [
  309. 'tasks' => [
  310. ['command' => '{magentoRoot}run.php % cron:run | grep -v "Ran \'jobs\' by schedule"']
  311. ],
  312. 'content' => '* * * * * /bin/php /var/www/cron.php',
  313. 'contentToSave' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
  314. . CrontabManagerInterface::TASKS_BLOCK_START . ' ' . md5(BP) . PHP_EOL
  315. . '* * * * * ' . PHP_BINARY . ' /var/www/magento2/run.php'
  316. . ' %% cron:run | grep -v \"Ran \'jobs\' by schedule\"' . PHP_EOL
  317. . CrontabManagerInterface::TASKS_BLOCK_END . ' ' . md5(BP) . PHP_EOL,
  318. ],
  319. ];
  320. }
  321. }