6
6
7
7
namespace Magento \Framework \ParallelProcess ;
8
8
9
+ use Magento \Framework \App \Cache ;
9
10
use Magento \Framework \ParallelProcess \Fork \PcntlForkManager ;
10
11
use Magento \Framework \ParallelProcess \Process \Data ;
11
12
use Magento \Framework \ParallelProcess \Process \ExitedWithErrorException ;
12
13
use Magento \Framework \ParallelProcess \Process \RunnerInterface ;
13
14
use PHPUnit \Framework \TestCase ;
15
+ use Magento \TestFramework \Helper \Bootstrap ;
14
16
15
17
class ProcessManagerTest extends TestCase
16
18
{
17
- public function testRun ()
19
+ /**
20
+ * @var Cache
21
+ */
22
+ private $ cache ;
23
+
24
+ /**
25
+ * @var \ArrayObject
26
+ */
27
+ private $ createdCacheIds ;
28
+
29
+ /**
30
+ * @inheritDoc
31
+ */
32
+ protected function setUp ()
33
+ {
34
+ parent ::setUp ();
35
+ $ this ->cache = Bootstrap::getObjectManager ()->get (Cache::class);
36
+ $ this ->createdCacheIds = new \ArrayObject ();
37
+ }
38
+
39
+ /**
40
+ * @inheritDoc
41
+ */
42
+ protected function tearDown ()
18
43
{
19
- $ runner = new class implements RunnerInterface {
44
+ parent ::tearDown ();
45
+ foreach ($ this ->createdCacheIds as $ cacheId ) {
46
+ $ this ->cache ->remove ($ cacheId );
47
+ }
48
+ }
49
+
50
+ /**
51
+ * @param int|null $limit Max number of processes.
52
+ * @param array $processes
53
+ *
54
+ * @dataProvider getSuccessfulProcesses
55
+ */
56
+ public function testRun (array $ processes , int $ limit = null )
57
+ {
58
+ $ cache = $ this ->cache ;
59
+ $ createCacheId = function (string $ id ): string
60
+ {
61
+ return 'magento2_parallel_process_test_id_ ' . $ id ;
62
+ };
63
+ foreach ($ processes as $ process ) {
64
+ $ this ->createdCacheIds [] = $ createCacheId ($ process ['id ' ]);
65
+ }
66
+ $ runner = new class ($ cache , $ createCacheId ) implements RunnerInterface {
67
+ /**
68
+ * @var Cache
69
+ */
70
+ private $ cache ;
71
+
72
+ /**
73
+ * @var callable
74
+ */
75
+ private $ createCacheId ;
76
+
77
+ public function __construct ($ cache , $ createId )
78
+ {
79
+ $ this ->cache = $ cache ;
80
+ $ this ->createCacheId = $ createId ;
81
+ }
82
+
20
83
/**
21
84
* @inheritDoc
22
85
*/
23
86
public function run (array $ data )
24
87
{
25
- usleep (rand (50 , 200 ));
26
- echo PHP_EOL .$ data ['id ' ].PHP_EOL ;
88
+ usleep (rand (32 , 256 ));
89
+
90
+ foreach ($ data ['depends ' ] as $ dependsOnId ) {
91
+ $ dependencyResult = $ this ->cache
92
+ ->load (($ this ->createCacheId )($ dependsOnId ));
93
+ if ($ dependencyResult !== 'success ' ) {
94
+ throw new \RuntimeException (
95
+ 'Provider process didn \'t successfully finish '
96
+ );
97
+ }
98
+ }
99
+ $ id = ($ this ->createCacheId )($ data ['id ' ]);
100
+ $ this ->cache ->save ('success ' , $ id );
27
101
}
28
102
};
29
103
$ fork = new PcntlForkManager ();
30
- $ successful = [];
31
- $ failed = [];
32
- for ($ i = 1 ; $ i <= 10 ; $ i ++) {
33
- if (rand (0 ,1 )) {
34
- $ dependsOn = ['id ' .rand (1 ,10 )];
35
- if ($ dependsOn [0 ] === 'id ' .$ i ) {
36
- $ dependsOn = [];
104
+ /** @var Data[] $data */
105
+ $ data = [];
106
+ foreach ($ processes as $ process ) {
107
+ $ data [] = new Data ($ process ['id ' ], $ process , $ process ['depends ' ]);
108
+ }
109
+ $ manager = new ProcessManager ($ runner , $ fork , $ data , $ limit );
110
+
111
+ $ manager ->run ();
112
+ }
113
+
114
+ /**
115
+ * @return array
116
+ */
117
+ public function getSuccessfulProcesses ()
118
+ {
119
+ $ processes = [
120
+ ['id ' => 'id1 ' , 'depends ' => []],
121
+ ['id ' => 'id2 ' , 'depends ' => []],
122
+ ['id ' => 'id3 ' , 'depends ' => []],
123
+ ['id ' => 'id4 ' , 'depends ' => ['id1 ' ]],
124
+ ['id ' => 'id5 ' , 'depends ' => ['id1 ' , 'id2 ' ]],
125
+ ['id ' => 'id6 ' , 'depends ' => ['id3 ' ]],
126
+ ['id ' => 'id7 ' , 'depends ' => ['id5 ' ]],
127
+ ['id ' => 'id8 ' , 'depends ' => ['id1 ' ]],
128
+ ['id ' => 'id9 ' , 'depends ' => ['id1 ' ]],
129
+ ['id ' => 'id10 ' , 'depends ' => ['id1 ' ]],
130
+ ];
131
+
132
+ return [
133
+ [
134
+ 'processes ' => $ processes ,
135
+ 'limit ' => 5
136
+ ],
137
+ [
138
+ 'processes ' => $ processes ,
139
+ 'limit ' => 15
140
+ ],
141
+ [
142
+ 'processes ' => $ processes ,
143
+ 'limit ' => 1
144
+ ],
145
+ [
146
+ 'processes ' => $ processes ,
147
+ 'limit ' => null
148
+ ],
149
+ ];
150
+ }
151
+
152
+ /**
153
+ * @param int|null $limit Max number of processes.
154
+ * @param array $processes
155
+ * @param string[] $wasNotLaunched
156
+ * @param string[] $finished
157
+ *
158
+ * @dataProvider getFailingProcesses
159
+ */
160
+ public function testFailures (
161
+ array $ processes ,
162
+ array $ wasNotLaunched ,
163
+ array $ finished ,
164
+ int $ limit =null
165
+ ) {
166
+ $ cache = $ this ->cache ;
167
+ $ createCacheId = function (string $ id ): string
168
+ {
169
+ return 'magento2_parallel_process_test_id_ ' . $ id ;
170
+ };
171
+ foreach ($ processes as $ process ) {
172
+ $ this ->createdCacheIds [] = $ createCacheId ($ process ['id ' ]);
173
+ }
174
+ $ runner = new class ($ cache , $ createCacheId ) implements RunnerInterface {
175
+ /**
176
+ * @var Cache
177
+ */
178
+ private $ cache ;
179
+
180
+ /**
181
+ * @var callable
182
+ */
183
+ private $ createCacheId ;
184
+
185
+ public function __construct ($ cache , $ createId )
186
+ {
187
+ $ this ->cache = $ cache ;
188
+ $ this ->createCacheId = $ createId ;
189
+ }
190
+
191
+ /**
192
+ * @inheritDoc
193
+ */
194
+ public function run (array $ data )
195
+ {
196
+ usleep (rand (32 , 256 ));
197
+
198
+ if ($ data ['depends ' ]) {
199
+ foreach ($ data ['depends ' ] as $ dependsOnId ) {
200
+ if ($ this ->cache ->load (($ this ->createCacheId )($ dependsOnId )) !== 'success ' ) {
201
+ $ id = ($ this ->createCacheId )($ data ['id ' ]);
202
+ $ this ->cache ->save ('failure ' , $ id );
203
+ throw new \RuntimeException ();
204
+ }
205
+ }
206
+ } else {
207
+ if (!isset ($ data ['success ' ])) {
208
+ throw new \RuntimeException ('Failed ' );
209
+ } else {
210
+ $ id = ($ this ->createCacheId )($ data ['id ' ]);
211
+ $ this ->cache ->save ('success ' , $ id );
212
+ }
37
213
}
38
- } else {
39
- $ dependsOn = [];
40
214
}
41
- $ successful [] = new Data ('id ' . $ i , ['id ' =>'id ' .$ i ], $ dependsOn );
215
+ };
216
+ $ fork = new PcntlForkManager ();
217
+ /** @var Data[] $data */
218
+ $ data = [];
219
+ foreach ($ processes as $ process ) {
220
+ $ data [] = new Data ($ process ['id ' ], $ process , $ process ['depends ' ]);
42
221
}
43
- $ failed [] = new Data ( ' idFailed ' , [] );
222
+ $ manager = new ProcessManager ( $ runner , $ fork , $ data , $ limit );
44
223
45
- $ manager = new ProcessManager ($ runner , $ fork , array_merge ($ successful , $ failed ), 8 );
224
+ /** @var string[] $actuallyFailed */
225
+ $ actuallyFailed = [];
46
226
try {
47
227
$ manager ->run ();
48
228
} catch (ExitedWithErrorException $ exception ) {
49
- $ this ->assertEquals ($ failed , $ exception ->getFailedProcesses ());
229
+ $ actuallyFailed = array_map (
230
+ function (Data $ data ) {
231
+ return $ data ->getId ();
232
+ },
233
+ $ exception ->getFailedProcesses ()
234
+ );
235
+ }
236
+ foreach ($ processes as $ process ) {
237
+ if (!isset ($ process ['success ' ])) {
238
+ $ this ->assertContains ($ process ['id ' ], $ actuallyFailed );
239
+ }
240
+ }
241
+ foreach ($ wasNotLaunched as $ id ) {
242
+ $ this ->assertFalse ($ this ->cache ->load ($ createCacheId ($ id )));
50
243
}
244
+ foreach ($ finished as $ id ) {
245
+ $ this ->assertNotContains ($ id , $ actuallyFailed );
246
+ $ this ->assertNotEmpty ($ this ->cache ->load ($ createCacheId ($ id )));
247
+ }
248
+ }
249
+
250
+ /**
251
+ * @return array
252
+ */
253
+ public function getFailingProcesses ()
254
+ {
255
+ $ processes = [];
256
+ $ processes [] = ['id ' => 'id1 ' , 'depends ' => []];
257
+ $ processes [] = ['id ' => 'id2 ' , 'depends ' => []];
258
+ $ processes [] = ['id ' => 'id3 ' , 'depends ' => []];
259
+ $ processes [] = ['id ' => 'id4 ' , 'depends ' => ['id1 ' ]];
260
+ $ processes [] = ['id ' => 'id5 ' , 'depends ' => ['id1 ' , 'id2 ' ]];
261
+ $ processes [] = ['id ' => 'id6 ' , 'depends ' => ['id3 ' ]];
262
+ $ processes [] = ['id ' => 'id7 ' , 'depends ' => [], 'success ' => true ];
263
+ $ wasNotLaunched = ['id4 ' , 'id5 ' , 'id6 ' ];
264
+ $ finished = ['id7 ' ];
265
+
266
+ return [
267
+ [
268
+ 'processes ' => $ processes ,
269
+ 'wasNotLaunched ' => $ wasNotLaunched ,
270
+ 'finished ' => $ finished ,
271
+ 'limit ' => 5 ,
272
+ ],
273
+ [
274
+ 'processes ' => $ processes ,
275
+ 'wasNotLaunched ' => $ wasNotLaunched ,
276
+ 'finished ' => $ finished ,
277
+ 'limit ' => 15 ,
278
+ ],
279
+ [
280
+ 'processes ' => $ processes ,
281
+ 'wasNotLaunched ' => $ wasNotLaunched ,
282
+ 'finished ' => $ finished ,
283
+ 'limit ' => 1 ,
284
+ ],
285
+ [
286
+ 'processes ' => $ processes ,
287
+ 'wasNotLaunched ' => $ wasNotLaunched ,
288
+ 'finished ' => $ finished ,
289
+ 'limit ' => null ,
290
+ ],
291
+ ];
51
292
}
52
293
}
0 commit comments