forked from laravel/framework
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CallbackSchedulingTest.php
140 lines (113 loc) · 4.14 KB
/
CallbackSchedulingTest.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<?php
namespace Illuminate\Tests\Integration\Console;
use Illuminate\Cache\ArrayStore;
use Illuminate\Cache\Repository;
use Illuminate\Console\Events\ScheduledTaskFailed;
use Illuminate\Console\Scheduling\CacheEventMutex;
use Illuminate\Console\Scheduling\CacheSchedulingMutex;
use Illuminate\Console\Scheduling\EventMutex;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Console\Scheduling\SchedulingMutex;
use Illuminate\Container\Container;
use Illuminate\Contracts\Cache\Factory;
use Illuminate\Contracts\Events\Dispatcher;
use Orchestra\Testbench\TestCase;
use RuntimeException;
class CallbackSchedulingTest extends TestCase
{
protected $log = [];
protected function setUp(): void
{
parent::setUp();
$cache = new class implements Factory
{
public $store;
public function __construct()
{
$this->store = new Repository(new ArrayStore(true));
}
public function store($name = null)
{
return $this->store;
}
};
$container = Container::getInstance();
$container->instance(EventMutex::class, new CacheEventMutex($cache));
$container->instance(SchedulingMutex::class, new CacheSchedulingMutex($cache));
}
protected function tearDown(): void
{
Container::setInstance(null);
parent::tearDown();
}
/**
* @dataProvider executionProvider
*/
public function testExecutionOrder($background)
{
$event = $this->app->make(Schedule::class)
->call($this->logger('call'))
->after($this->logger('after 1'))
->before($this->logger('before 1'))
->after($this->logger('after 2'))
->before($this->logger('before 2'));
if ($background) {
$event->runInBackground();
}
$this->artisan('schedule:run');
$this->assertLogged('before 1', 'before 2', 'call', 'after 1', 'after 2');
}
public function testExceptionHandlingInCallback()
{
$event = $this->app->make(Schedule::class)
->call($this->logger('call'))
->name('test-event')
->withoutOverlapping();
// Set up "before" and "after" hooks to ensure they're called
$event->before($this->logger('before'))->after($this->logger('after'));
// Register a hook to validate that the mutex was initially created
$mutexWasCreated = false;
$event->before(function () use (&$mutexWasCreated, $event) {
$mutexWasCreated = $event->mutex->exists($event);
});
// We'll trigger an exception in an "after" hook to test exception handling
$event->after(function () {
throw new RuntimeException;
});
// Because exceptions are caught by the ScheduleRunCommand, we need to listen for
// the "failed" event to check whether our exception was actually thrown
$failed = false;
$this->app->make(Dispatcher::class)
->listen(ScheduledTaskFailed::class, function (ScheduledTaskFailed $failure) use (&$failed, $event) {
if ($failure->task === $event) {
$failed = true;
}
});
$this->artisan('schedule:run');
// Hooks and execution should happn in correct order
$this->assertLogged('before', 'call', 'after');
// Our exception should have resulted in a failure event
$this->assertTrue($failed);
// Validate that the mutex was originally created, but that it's since
// been removed (even though an exception was thrown)
$this->assertTrue($mutexWasCreated);
$this->assertFalse($event->mutex->exists($event));
}
public function executionProvider()
{
return [
'Foreground' => [false],
'Background' => [true],
];
}
protected function logger($message)
{
return function () use ($message) {
$this->log[] = $message;
};
}
protected function assertLogged(...$message)
{
$this->assertEquals($message, $this->log);
}
}