ScheduleTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Cron\Test\Unit\Model;
  7. use Magento\Cron\Model\Schedule;
  8. /**
  9. * Class \Magento\Cron\Test\Unit\Model\ObserverTest
  10. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  11. */
  12. class ScheduleTest extends \PHPUnit\Framework\TestCase
  13. {
  14. /**
  15. * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
  16. */
  17. protected $helper;
  18. protected $resourceJobMock;
  19. protected function setUp()
  20. {
  21. $this->helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
  22. $this->resourceJobMock = $this->getMockBuilder(\Magento\Cron\Model\ResourceModel\Schedule::class)
  23. ->disableOriginalConstructor()
  24. ->setMethods(['trySetJobUniqueStatusAtomic', '__wakeup', 'getIdFieldName'])
  25. ->getMockForAbstractClass();
  26. $this->resourceJobMock->expects($this->any())
  27. ->method('getIdFieldName')
  28. ->will($this->returnValue('id'));
  29. }
  30. /**
  31. * @param string $cronExpression
  32. * @param array $expected
  33. * @dataProvider setCronExprDataProvider
  34. */
  35. public function testSetCronExpr($cronExpression, $expected)
  36. {
  37. // 1. Create mocks
  38. /** @var \Magento\Cron\Model\Schedule $model */
  39. $model = $this->helper->getObject(\Magento\Cron\Model\Schedule::class);
  40. // 2. Run tested method
  41. $model->setCronExpr($cronExpression);
  42. // 3. Compare actual result with expected result
  43. $result = $model->getCronExprArr();
  44. $this->assertEquals($result, $expected);
  45. }
  46. /**
  47. * Data provider
  48. *
  49. * Here is a list of allowed characters and values for Cron expression
  50. * http://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.htm
  51. *
  52. * @return array
  53. */
  54. public function setCronExprDataProvider()
  55. {
  56. return [
  57. ['1 2 3 4 5', [1, 2, 3, 4, 5]],
  58. ['1 2 3 4 5 6', [1, 2, 3, 4, 5, 6]],
  59. ['a b c d e', ['a', 'b', 'c', 'd', 'e']], //should fail if validation will be added
  60. ['* * * * *', ['*', '*', '*', '*', '*']],
  61. ['0 * * * *', ['0', '*', '*', '*', '*']],
  62. ['59 * * * *', ['59', '*', '*', '*', '*']],
  63. [', * * * *', [',', '*', '*', '*', '*']],
  64. ['1-2 * * * *', ['1-2', '*', '*', '*', '*']],
  65. ['0/5 * * * *', ['0/5', '*', '*', '*', '*']],
  66. ['* 0 * * *', ['*', '0', '*', '*', '*']],
  67. ['* 59 * * *', ['*', '59', '*', '*', '*']],
  68. ['* , * * *', ['*', ',', '*', '*', '*']],
  69. ['* 1-2 * * *', ['*', '1-2', '*', '*', '*']],
  70. ['* 0/5 * * *', ['*', '0/5', '*', '*', '*']],
  71. ['* * 0 * *', ['*', '*', '0', '*', '*']],
  72. ['* * 23 * *', ['*', '*', '23', '*', '*']],
  73. ['* * , * *', ['*', '*', ',', '*', '*']],
  74. ['* * 1-2 * *', ['*', '*', '1-2', '*', '*']],
  75. ['* * 0/5 * *', ['*', '*', '0/5', '*', '*']],
  76. ['* * * 1 *', ['*', '*', '*', '1', '*']],
  77. ['* * * 31 *', ['*', '*', '*', '31', '*']],
  78. ['* * * , *', ['*', '*', '*', ',', '*']],
  79. ['* * * 1-2 *', ['*', '*', '*', '1-2', '*']],
  80. ['* * * 0/5 *', ['*', '*', '*', '0/5', '*']],
  81. ['* * * ? *', ['*', '*', '*', '?', '*']],
  82. ['* * * L *', ['*', '*', '*', 'L', '*']],
  83. ['* * * W *', ['*', '*', '*', 'W', '*']],
  84. ['* * * C *', ['*', '*', '*', 'C', '*']],
  85. ['* * * * 0', ['*', '*', '*', '*', '0']],
  86. ['* * * * 11', ['*', '*', '*', '*', '11']],
  87. ['* * * * ,', ['*', '*', '*', '*', ',']],
  88. ['* * * * 1-2', ['*', '*', '*', '*', '1-2']],
  89. ['* * * * 0/5', ['*', '*', '*', '*', '0/5']],
  90. ['* * * * JAN', ['*', '*', '*', '*', 'JAN']],
  91. ['* * * * DEC', ['*', '*', '*', '*', 'DEC']],
  92. ['* * * * JAN-DEC', ['*', '*', '*', '*', 'JAN-DEC']],
  93. ['* * * * * 1', ['*', '*', '*', '*', '*', '1']],
  94. ['* * * * * 7', ['*', '*', '*', '*', '*', '7']],
  95. ['* * * * * ,', ['*', '*', '*', '*', '*', ',']],
  96. ['* * * * * 1-2', ['*', '*', '*', '*', '*', '1-2']],
  97. ['* * * * * 0/5', ['*', '*', '*', '*', '*', '0/5']],
  98. ['* * * * * ?', ['*', '*', '*', '*', '*', '?']],
  99. ['* * * * * L', ['*', '*', '*', '*', '*', 'L']],
  100. ['* * * * * 6#3', ['*', '*', '*', '*', '*', '6#3']],
  101. ['* * * * * SUN', ['*', '*', '*', '*', '*', 'SUN']],
  102. ['* * * * * SAT', ['*', '*', '*', '*', '*', 'SAT']],
  103. ['* * * * * SUN-SAT', ['*', '*', '*', '*', '*', 'SUN-SAT']],
  104. ];
  105. }
  106. /**
  107. * @param string $cronExpression
  108. * @expectedException \Magento\Framework\Exception\CronException
  109. * @dataProvider setCronExprExceptionDataProvider
  110. */
  111. public function testSetCronExprException($cronExpression)
  112. {
  113. // 1. Create mocks
  114. /** @var \Magento\Cron\Model\Schedule $model */
  115. $model = $this->helper->getObject(\Magento\Cron\Model\Schedule::class);
  116. // 2. Run tested method
  117. $model->setCronExpr($cronExpression);
  118. }
  119. /**
  120. * Here is a list of allowed characters and values for Cron expression
  121. * http://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.htm
  122. *
  123. * @return array
  124. */
  125. public function setCronExprExceptionDataProvider()
  126. {
  127. return [
  128. [''],
  129. [null],
  130. [false],
  131. ['1 2 3 4'],
  132. ['1 2 3 4 5 6 7']
  133. ];
  134. }
  135. /**
  136. * @param int $scheduledAt
  137. * @param array $cronExprArr
  138. * @param $expected
  139. * @dataProvider tryScheduleDataProvider
  140. */
  141. public function testTrySchedule($scheduledAt, $cronExprArr, $expected)
  142. {
  143. // 1. Create mocks
  144. /** @var \Magento\Cron\Model\Schedule $model */
  145. $model = $this->helper->getObject(
  146. \Magento\Cron\Model\Schedule::class
  147. );
  148. // 2. Set fixtures
  149. $model->setScheduledAt($scheduledAt);
  150. $model->setCronExprArr($cronExprArr);
  151. // 3. Run tested method
  152. $result = $model->trySchedule();
  153. // 4. Compare actual result with expected result
  154. $this->assertEquals($expected, $result);
  155. }
  156. public function testTryScheduleWithConversionToAdminStoreTime()
  157. {
  158. $scheduledAt = '2011-12-13 14:15:16';
  159. $cronExprArr = ['*', '*', '*', '*', '*'];
  160. // 1. Create mocks
  161. $timezoneConverter = $this->createMock(\Magento\Framework\Stdlib\DateTime\TimezoneInterface::class);
  162. $timezoneConverter->expects($this->once())
  163. ->method('date')
  164. ->with($scheduledAt)
  165. ->willReturn(new \DateTime($scheduledAt));
  166. /** @var \Magento\Cron\Model\Schedule $model */
  167. $model = $this->helper->getObject(
  168. \Magento\Cron\Model\Schedule::class,
  169. ['timezoneConverter' => $timezoneConverter]
  170. );
  171. // 2. Set fixtures
  172. $model->setScheduledAt($scheduledAt);
  173. $model->setCronExprArr($cronExprArr);
  174. // 3. Run tested method
  175. $result = $model->trySchedule();
  176. // 4. Compare actual result with expected result
  177. $this->assertTrue($result);
  178. }
  179. /**
  180. * @return array
  181. */
  182. public function tryScheduleDataProvider()
  183. {
  184. $date = '2011-12-13 14:15:16';
  185. return [
  186. [$date, [], false],
  187. [$date, null, false],
  188. [$date, false, false],
  189. [$date, [], false],
  190. [$date, null, false],
  191. [$date, false, false],
  192. [strtotime($date), ['*', '*', '*', '*', '*'], true],
  193. [strtotime($date), ['15', '*', '*', '*', '*'], true],
  194. [strtotime($date), ['*', '14', '*', '*', '*'], true],
  195. [strtotime($date), ['*', '*', '13', '*', '*'], true],
  196. [strtotime($date), ['*', '*', '*', '12', '*'], true],
  197. [strtotime('Monday'), ['*', '*', '*', '*', '1'], true],
  198. ];
  199. }
  200. /**
  201. * @param string $cronExpressionPart
  202. * @param int $dateTimePart
  203. * @param bool $expectedResult
  204. * @dataProvider matchCronExpressionDataProvider
  205. */
  206. public function testMatchCronExpression($cronExpressionPart, $dateTimePart, $expectedResult)
  207. {
  208. // 1. Create mocks
  209. /** @var \Magento\Cron\Model\Schedule $model */
  210. $model = $this->helper->getObject(\Magento\Cron\Model\Schedule::class);
  211. // 2. Run tested method
  212. $result = $model->matchCronExpression($cronExpressionPart, $dateTimePart);
  213. // 3. Compare actual result with expected result
  214. $this->assertEquals($expectedResult, $result);
  215. }
  216. /**
  217. * @return array
  218. */
  219. public function matchCronExpressionDataProvider()
  220. {
  221. return [
  222. ['*', 0, true],
  223. ['*', 1, true],
  224. ['*', 59, true],
  225. ['0,1,20', 0, true],
  226. ['0,1,20', 1, true],
  227. ['0,1,20', 20, true],
  228. ['0,1,22', 2, false],
  229. ['0,1,*', 2, true],
  230. ['0-20', 0, true],
  231. ['0-20', 1, true],
  232. ['0-20', 20, true],
  233. ['0-20', 21, false],
  234. ['*/2', 0, true],
  235. ['*/2', 2, true],
  236. ['*/2', 4, true],
  237. ['*/2', 3, false],
  238. ['*/20', 40, true],
  239. ['0-20/5', 0, true],
  240. ['0-20/5', 5, true],
  241. ['0-20/5', 10, true],
  242. ['0-20/5', 21, false],
  243. ['0-20/5', 25, false],
  244. ['1/5', 5, false],
  245. ['5/5', 5, true],
  246. ['10/5', 10, true],
  247. ];
  248. }
  249. /**
  250. * @param string $cronExpressionPart
  251. * @expectedException \Magento\Framework\Exception\CronException
  252. * @dataProvider matchCronExpressionExceptionDataProvider
  253. */
  254. public function testMatchCronExpressionException($cronExpressionPart)
  255. {
  256. $dateTimePart = 10;
  257. // 1 Create mocks
  258. /** @var \Magento\Cron\Model\Schedule $model */
  259. $model = $this->helper->getObject(\Magento\Cron\Model\Schedule::class);
  260. // 2. Run tested method
  261. $model->matchCronExpression($cronExpressionPart, $dateTimePart);
  262. }
  263. /**
  264. * @return array
  265. */
  266. public function matchCronExpressionExceptionDataProvider()
  267. {
  268. return [
  269. ['1/2/3'], //Invalid cron expression, expecting 'match/modulus': 1/2/3
  270. ['1/'], //Invalid cron expression, expecting numeric modulus: 1/
  271. ['-'], //Invalid cron expression
  272. ['1-2-3'], //Invalid cron expression, expecting 'from-to' structure: 1-2-3
  273. ];
  274. }
  275. /**
  276. * @param mixed $param
  277. * @param int $expectedResult
  278. * @dataProvider getNumericDataProvider
  279. */
  280. public function testGetNumeric($param, $expectedResult)
  281. {
  282. // 1. Create mocks
  283. /** @var \Magento\Cron\Model\Schedule $model */
  284. $model = $this->helper->getObject(\Magento\Cron\Model\Schedule::class);
  285. // 2. Run tested method
  286. $result = $model->getNumeric($param);
  287. // 3. Compare actual result with expected result
  288. $this->assertEquals($expectedResult, $result);
  289. }
  290. /**
  291. * @return array
  292. */
  293. public function getNumericDataProvider()
  294. {
  295. return [
  296. [null, false],
  297. ['', false],
  298. ['0', 0],
  299. [0, 0],
  300. [1, 1],
  301. [PHP_INT_MAX, PHP_INT_MAX],
  302. [1.1, 1.1],
  303. ['feb', 2],
  304. ['Feb', 2],
  305. ['FEB', 2],
  306. ['february', 2],
  307. ['febXXX', 2],
  308. ['wed', 3],
  309. ['Wed', 3],
  310. ['WED', 3],
  311. ['Wednesday', 3],
  312. ['wedXXX', 3],
  313. ];
  314. }
  315. public function testTryLockJobSuccess()
  316. {
  317. $scheduleId = 1;
  318. $this->resourceJobMock->expects($this->once())
  319. ->method('trySetJobUniqueStatusAtomic')
  320. ->with($scheduleId, Schedule::STATUS_RUNNING, Schedule::STATUS_PENDING)
  321. ->will($this->returnValue(true));
  322. /** @var \Magento\Cron\Model\Schedule $model */
  323. $model = $this->helper->getObject(
  324. \Magento\Cron\Model\Schedule::class,
  325. [
  326. 'resource' => $this->resourceJobMock
  327. ]
  328. );
  329. $model->setId($scheduleId);
  330. $this->assertEquals(0, $model->getStatus());
  331. $model->tryLockJob();
  332. $this->assertEquals(Schedule::STATUS_RUNNING, $model->getStatus());
  333. }
  334. public function testTryLockJobFailure()
  335. {
  336. $scheduleId = 1;
  337. $this->resourceJobMock->expects($this->once())
  338. ->method('trySetJobUniqueStatusAtomic')
  339. ->with($scheduleId, Schedule::STATUS_RUNNING, Schedule::STATUS_PENDING)
  340. ->will($this->returnValue(false));
  341. /** @var \Magento\Cron\Model\Schedule $model */
  342. $model = $this->helper->getObject(
  343. \Magento\Cron\Model\Schedule::class,
  344. [
  345. 'resource' => $this->resourceJobMock
  346. ]
  347. );
  348. $model->setId($scheduleId);
  349. $this->assertEquals(0, $model->getStatus());
  350. $model->tryLockJob();
  351. $this->assertEquals(0, $model->getStatus());
  352. }
  353. }