ILIAS  trunk Revision v13.0_alpha-52-g21c366bbdd4
AsyncTaskManagerTest.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
31use PHPUnit\Framework\Attributes\DataProvider;
32use PHPUnit\Framework\MockObject\MockObject;
33use PHPUnit\Framework\TestCase;
34
35class AsyncTaskManagerTest extends TestCase
36{
37 private Container $dic;
38 private MockObject&Persistence $persistence;
39 private MockObject&ilLogger $logger;
40 private int $scheduled_queries = 0;
41
42 protected function setUp(): void
43 {
44 $this->dic = new Container();
45 $GLOBALS['DIC'] = $this->dic;
46
47 $this->logger = $this->createMock(ilLogger::class);
48 $logger_factory = $this->createMock(ilLoggerFactory::class);
49 $logger_factory->method('getComponentLogger')->willReturn($this->logger);
50 $this->dic['ilLoggerFactory'] = $logger_factory;
51
52 $this->persistence = $this->createMock(Persistence::class);
53 $this->dic['bt.persistence'] = $this->persistence;
54
55 $ini = $this->createMock(ilIniFile::class);
56 $ini->method('readVariable')->willReturn('5');
57 $GLOBALS['ilIliasIniFile'] = $ini;
58 }
59
63 private function schedule(array ...$responses): void
64 {
65 $this->scheduled_queries = 0;
66 $index = 0;
67 $this->persistence->method('getBucketIdsByState')->willReturnCallback(
68 function (int $state) use ($responses, &$index): array {
69 if ($state === State::RUNNING) {
70 return [];
71 }
72 $this->scheduled_queries++;
73 $response = $responses[$index] ?? [];
74 $index++;
75
76 return $response;
77 }
78 );
79 }
80
81 private function runnableBucket(): MockObject&Bucket
82 {
83 $output_type = $this->createMock(Type::class);
84 $value_type = $this->createMock(Type::class);
85 $value_type->method('isExtensionOf')->willReturn(true);
86
87 $value = $this->createMock(Value::class);
88 $value->method('getType')->willReturn($value_type);
89
90 $job = $this->createMock(Job::class);
91 $job->method('getInput')->willReturn([]);
92 $job->method('getOutputType')->willReturn($output_type);
93 $job->method('run')->willReturn($value);
94
95 $bucket = $this->createMock(Bucket::class);
96 $bucket->method('getTask')->willReturn($job);
97
98 return $bucket;
99 }
100
101 private function manager(): AsyncTaskManager
102 {
103 return new AsyncTaskManager($this->persistence);
104 }
105
109 public static function corruptContainerProvider(): array
110 {
111 return [
112 'missing task container' => ['The requested task with container id 5 could not be found in the database.'],
113 'missing value container' => ['The requested value with container id 9 could not be found in the database.'],
114 ];
115 }
116
117 #[DataProvider('corruptContainerProvider')]
119 {
120 $this->schedule([1, 2], []);
121 $bucket = $this->runnableBucket();
122 $finished = false;
123 $bucket->method('setState')->willReturnCallback(function (int $state) use (&$finished): void {
124 if ($state === State::FINISHED) {
125 $finished = true;
126 }
127 });
128
129 $this->persistence->method('loadBucket')->willReturnCallback(
130 function (int $id) use ($bucket, $message): Bucket {
131 if ($id === 1) {
133 }
134
135 return $bucket;
136 }
137 );
138 $this->persistence->expects($this->once())->method('deleteBucketById')->with(1);
139 $this->persistence->expects($this->atLeastOnce())->method('updateBucket')->with($bucket);
140
141 $this->manager()->runAsync();
142
143 $this->assertTrue($finished);
144 $this->assertSame(2, $this->scheduled_queries);
145 }
146
148 {
149 $this->schedule([1, 2], []);
150 $loaded = [];
151 $this->persistence->method('loadBucket')->willReturnCallback(
152 function (int $id) use (&$loaded): Bucket {
153 $loaded[] = $id;
154 throw new ilDatabaseException('database unavailable');
155 }
156 );
157 $this->persistence->expects($this->never())->method('deleteBucketById');
158 $this->logger->expects($this->once())->method('error');
159
160 $this->manager()->runAsync();
161
162 $this->assertSame([1], $loaded);
163 }
164
166 {
167 $this->schedule([1, 2], []);
168 $bucket = $this->runnableBucket();
169 $loaded = [];
170 $this->persistence->method('loadBucket')->willReturnCallback(
171 function (int $id) use ($bucket, &$loaded): Bucket {
172 $loaded[] = $id;
173 if ($id === 1) {
174 throw new BucketNotFoundException('bucket already gone');
175 }
176
177 return $bucket;
178 }
179 );
180 $this->persistence->expects($this->never())->method('deleteBucketById');
181 $this->persistence->expects($this->atLeastOnce())->method('updateBucket')->with($bucket);
182
183 $this->manager()->runAsync();
184
185 $this->assertSame([1, 2], $loaded);
186 }
187
189 {
190 $this->schedule([1, 2, 3], []);
191 $bucket = $this->runnableBucket();
192 $loaded = [];
193 $deleted = [];
194 $this->persistence->method('loadBucket')->willReturnCallback(
195 function (int $id) use ($bucket, &$loaded): Bucket {
196 $loaded[] = $id;
197 if ($id === 1 || $id === 2) {
198 throw new SerializationException('corrupt container');
199 }
200
201 return $bucket;
202 }
203 );
204 $this->persistence->method('deleteBucketById')->willReturnCallback(
205 function (int $id) use (&$deleted): void {
206 $deleted[] = $id;
207 }
208 );
209
210 $this->manager()->runAsync();
211
212 $this->assertSame([1, 2, 3], $loaded);
213 $this->assertSame([1, 2], $deleted);
214 $this->assertSame(2, $this->scheduled_queries);
215 }
216}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
testCorruptContainerDeletesBucketAndRunsNext(string $message)
MockObject &Persistence $persistence
schedule(array ... $responses)
MockObject &ilLogger $logger
Customizing of pimple-DIC for ILIAS.
Definition: Container.php:38
Class ilDatabaseException.
Component logger with individual log levels by component id.
$GLOBALS["DIC"]
Definition: wac.php:66
$response
Definition: xapitoken.php:92