ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
ReaderTest.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
23use PHPUnit\Framework\TestCase;
26
28{
29}
30
32{
33}
34
36{
37}
38
40{
41}
42
43
44class ReaderTest extends TestCase
45{
46 protected D\Reader $reader;
47
48 public function setUp(): void
49 {
50 $this->reader = new D\Reader();
51 }
52
53 public function testNullComponent(): void
54 {
55 $component = new class () implements Component {
56 public function init(
57 array | \ArrayAccess &$define,
58 array | \ArrayAccess &$implement,
59 array | \ArrayAccess &$use,
60 array | \ArrayAccess &$contribute,
61 array | \ArrayAccess &$seek,
62 array | \ArrayAccess &$provide,
63 array | \ArrayAccess &$pull,
64 array | \ArrayAccess &$internal,
65 ): void {
66 }
67 };
68
69 $result = $this->reader->read($component);
70
71 $this->assertEquals(new D\OfComponent($component), $result);
72 }
73
74 public function testSimpleDefine(): void
75 {
76 $component = new class () implements Component {
77 public function init(
78 array | \ArrayAccess &$define,
79 array | \ArrayAccess &$implement,
80 array | \ArrayAccess &$use,
81 array | \ArrayAccess &$contribute,
82 array | \ArrayAccess &$seek,
83 array | \ArrayAccess &$provide,
84 array | \ArrayAccess &$pull,
85 array | \ArrayAccess &$internal,
86 ): void {
87 $define[] = TestInterface::class;
88 }
89 };
90 $result = $this->reader->read($component);
91
92 $name = new D\Name(TestInterface::class);
93 $define = new D\Define($name, false);
94
95 $this->assertEquals(new D\OfComponent($component, $define), $result);
96 }
97
99 {
100 $this->expectException(\LogicException::class);
101
102 $result = $this->reader->read(new class () implements Component {
103 public function init(
104 array | \ArrayAccess &$define,
105 array | \ArrayAccess &$implement,
106 array | \ArrayAccess &$use,
107 array | \ArrayAccess &$contribute,
108 array | \ArrayAccess &$seek,
109 array | \ArrayAccess &$provide,
110 array | \ArrayAccess &$pull,
111 array | \ArrayAccess &$internal,
112 ): void {
113 $define[TestInterface::class] = fn() => new class ($use[ILIAS\Component\Service::class]) implements TestInterface {};
114 }
115 });
116 }
117
119 {
120 $this->expectException(\LogicException::class);
121
122 $result = $this->reader->read(new class () implements Component {
123 public function init(
124 array | \ArrayAccess &$define,
125 array | \ArrayAccess &$implement,
126 array | \ArrayAccess &$use,
127 array | \ArrayAccess &$contribute,
128 array | \ArrayAccess &$seek,
129 array | \ArrayAccess &$provide,
130 array | \ArrayAccess &$pull,
131 array | \ArrayAccess &$internal,
132 ): void {
133 $implement[TestInterface::class] = null;
134 }
135 });
136 }
137
139 {
140 $component = new class () implements Component {
141 public function init(
142 array | \ArrayAccess &$define,
143 array | \ArrayAccess &$implement,
144 array | \ArrayAccess &$use,
145 array | \ArrayAccess &$contribute,
146 array | \ArrayAccess &$seek,
147 array | \ArrayAccess &$provide,
148 array | \ArrayAccess &$pull,
149 array | \ArrayAccess &$internal,
150 ): void {
151 $implement[TestInterface::class] = fn() => new ImplementsTestInterface();
152 }
153 };
154 $result = $this->reader->read($component);
155
156 $name = TestInterface::class;
157 $implement = new D\Out(D\OutType::IMPLEMENT, $name, ["class" => ImplementsTestInterface::class, "position" => 0], []);
158
159 $this->assertEquals(new D\OfComponent($component, $implement), $result);
160 }
161
163 {
164 $this->expectException(\LogicException::class);
165
166 $result = $this->reader->read(new class () implements Component {
167 public function init(
168 array | \ArrayAccess &$define,
169 array | \ArrayAccess &$implement,
170 array | \ArrayAccess &$use,
171 array | \ArrayAccess &$contribute,
172 array | \ArrayAccess &$seek,
173 array | \ArrayAccess &$provide,
174 array | \ArrayAccess &$pull,
175 array | \ArrayAccess &$internal,
176 ): void {
177 $implement[TestInterface::class] = fn() => new class () {};
178 }
179 });
180 }
181
183 {
184 $component = new class () implements Component {
185 public function init(
186 array | \ArrayAccess &$define,
187 array | \ArrayAccess &$implement,
188 array | \ArrayAccess &$use,
189 array | \ArrayAccess &$contribute,
190 array | \ArrayAccess &$seek,
191 array | \ArrayAccess &$provide,
192 array | \ArrayAccess &$pull,
193 array | \ArrayAccess &$internal,
194 ): void {
195 $implement[TestInterface::class] = fn() => new ImplementsTestInterface($use[TestInterface::class], $seek[TestInterface::class], $pull[TestInterface::class], $internal["something"]);
196
197 $internal["something"] = fn() => new Implements2TestInterface();
198 }
199 };
200
201 $result = $this->reader->read($component);
202
203 $name = TestInterface::class;
204 $use = new D\In(D\InType::USE, $name);
205 $seek = new D\In(D\InType::SEEK, $name);
206 $pull = new D\In(D\InType::PULL, $name);
207 $internal_in = new D\In(D\InType::INTERNAL, "something");
208 $internal_out = new D\Out(D\OutType::INTERNAL, "something", null, []);
209 $implement = new D\Out(D\OutType::IMPLEMENT, $name, ["class" => ImplementsTestInterface::class, "position" => 0], [$use, $seek, $pull, $internal_in]);
210
211 $expected = new D\OfComponent($component, $use, $seek, $pull, $internal_in, $internal_out, $implement);
212
213 $this->assertEquals($expected, $result);
214
215 $this->assertEquals([$implement], $result[(string) $implement]);
216 $this->assertEquals([$use], $result[(string) $use]);
217 $this->assertEquals([$seek], $result[(string) $seek]);
218 $this->assertEquals([$pull], $result[(string) $pull]);
219 $this->assertEquals([$internal_in], $result[(string) $internal_in]);
220 $this->assertEquals([$internal_out], $result[(string) $internal_out]);
221 }
222
224 {
225 $component = new class () implements Component {
226 public function init(
227 array | \ArrayAccess &$define,
228 array | \ArrayAccess &$implement,
229 array | \ArrayAccess &$use,
230 array | \ArrayAccess &$contribute,
231 array | \ArrayAccess &$seek,
232 array | \ArrayAccess &$provide,
233 array | \ArrayAccess &$pull,
234 array | \ArrayAccess &$internal,
235 ): void {
236 $implement[TestInterface::class] = fn() => new ImplementsTestInterface();
237 $implement[TestInterface::class] = fn() => new Implements2TestInterface();
238 }
239 };
240 $result = $this->reader->read($component);
241
242 $name = TestInterface::class;
243 $implement = new D\Out(D\OutType::IMPLEMENT, $name, ["class" => ImplementsTestInterface::class, "position" => 0], []);
244 $implement2 = new D\Out(D\OutType::IMPLEMENT, $name, ["class" => Implements2TestInterface::class, "position" => 1], []);
245
246 $this->assertEquals(new D\OfComponent($component, $implement, $implement2), $result);
247 $this->assertCount(2, $result[(string) $implement]);
248 }
249
250 public function testUseWithoutContext(): void
251 {
252 $this->expectException(\LogicException::class);
253
254 $result = $this->reader->read(new class () implements Component {
255 public function init(
256 array | \ArrayAccess &$define,
257 array | \ArrayAccess &$implement,
258 array | \ArrayAccess &$use,
259 array | \ArrayAccess &$contribute,
260 array | \ArrayAccess &$seek,
261 array | \ArrayAccess &$provide,
262 array | \ArrayAccess &$pull,
263 array | \ArrayAccess &$internal,
264 ): void {
265 $foo = $use[TestInterface::class];
266 }
267 });
268 }
269
271 {
272 $this->expectException(\LogicException::class);
273
274 $result = $this->reader->read(new class () implements Component {
275 public function init(
276 array | \ArrayAccess &$define,
277 array | \ArrayAccess &$implement,
278 array | \ArrayAccess &$use,
279 array | \ArrayAccess &$contribute,
280 array | \ArrayAccess &$seek,
281 array | \ArrayAccess &$provide,
282 array | \ArrayAccess &$pull,
283 array | \ArrayAccess &$internal,
284 ): void {
285 $contribute[TestInterface::class] = null;
286 }
287 });
288 }
289
291 {
292 $component = new class () implements Component {
293 public function init(
294 array | \ArrayAccess &$define,
295 array | \ArrayAccess &$implement,
296 array | \ArrayAccess &$use,
297 array | \ArrayAccess &$contribute,
298 array | \ArrayAccess &$seek,
299 array | \ArrayAccess &$provide,
300 array | \ArrayAccess &$pull,
301 array | \ArrayAccess &$internal,
302 ): void {
303 $contribute[TestInterface::class] = fn() => new ImplementsTestInterface();
304 }
305 };
306 $result = $this->reader->read($component);
307
308 $name = TestInterface::class;
309 $contribute = new D\Out(D\OutType::CONTRIBUTE, $name, ["position" => 0], []);
310
311 $this->assertEquals(new D\OfComponent($component, $contribute), $result);
312 }
313
315 {
316 $this->expectException(\LogicException::class);
317
318 $result = $this->reader->read(new class () implements Component {
319 public function init(
320 array | \ArrayAccess &$define,
321 array | \ArrayAccess &$implement,
322 array | \ArrayAccess &$use,
323 array | \ArrayAccess &$contribute,
324 array | \ArrayAccess &$seek,
325 array | \ArrayAccess &$provide,
326 array | \ArrayAccess &$pull,
327 array | \ArrayAccess &$internal,
328 ): void {
329 $contribute[TestInterface::class] = fn() => new class () {};
330 }
331 });
332 }
333
335 {
336 $component = new class () implements Component {
337 public function init(
338 array | \ArrayAccess &$define,
339 array | \ArrayAccess &$implement,
340 array | \ArrayAccess &$use,
341 array | \ArrayAccess &$contribute,
342 array | \ArrayAccess &$seek,
343 array | \ArrayAccess &$provide,
344 array | \ArrayAccess &$pull,
345 array | \ArrayAccess &$internal,
346 ): void {
347 $contribute[TestInterface::class] = fn() => new ImplementsTestInterface($use[TestInterface::class], $seek[TestInterface::class], $pull[TestInterface::class], $internal["something"]);
348 $internal["something"] = fn() => new Implements2TestInterface();
349 }
350 };
351 $result = $this->reader->read($component);
352
353 $name = TestInterface::class;
354 $use = new D\In(D\InType::USE, $name);
355 $seek = new D\In(D\InType::SEEK, $name);
356 $pull = new D\In(D\InType::PULL, $name);
357 $internal_in = new D\In(D\InType::INTERNAL, "something");
358 $internal_out = new D\Out(D\OutType::INTERNAL, "something", null, []);
359 $contribute = new D\Out(D\OutType::CONTRIBUTE, $name, ["position" => 0], [$use, $seek, $pull, $internal_in]);
360
361 $expected = new D\OfComponent($component, $use, $seek, $pull, $internal_in, $internal_out, $contribute);
362
363 $this->assertEquals([$contribute], $result[(string) $contribute]);
364 $this->assertEquals([$use], $result[(string) $use]);
365 $this->assertEquals([$seek], $result[(string) $seek]);
366 $this->assertEquals([$pull], $result[(string) $pull]);
367 $this->assertEquals([$internal_in], $result[(string) $internal_in]);
368 $this->assertEquals([$internal_out], $result[(string) $internal_out]);
369 }
370
371 public function testSeekWithoutContext(): void
372 {
373 $this->expectException(\LogicException::class);
374
375 $result = $this->reader->read(new class () implements Component {
376 public function init(
377 array | \ArrayAccess &$define,
378 array | \ArrayAccess &$implement,
379 array | \ArrayAccess &$use,
380 array | \ArrayAccess &$contribute,
381 array | \ArrayAccess &$seek,
382 array | \ArrayAccess &$provide,
383 array | \ArrayAccess &$pull,
384 array | \ArrayAccess &$internal,
385 ): void {
386 $foo = $seek[TestInterface::class];
387 }
388 });
389 }
390
391 public function testProvideWithoutImplementation(): void
392 {
393 $this->expectException(\LogicException::class);
394
395 $result = $this->reader->read(new class () implements Component {
396 public function init(
397 array | \ArrayAccess &$define,
398 array | \ArrayAccess &$implement,
399 array | \ArrayAccess &$use,
400 array | \ArrayAccess &$contribute,
401 array | \ArrayAccess &$seek,
402 array | \ArrayAccess &$provide,
403 array | \ArrayAccess &$pull,
404 array | \ArrayAccess &$internal,
405 ): void {
406 $provide[TestInterface::class] = null;
407 }
408 });
409 }
410
412 {
413 $component = new class () implements Component {
414 public function init(
415 array | \ArrayAccess &$define,
416 array | \ArrayAccess &$implement,
417 array | \ArrayAccess &$use,
418 array | \ArrayAccess &$contribute,
419 array | \ArrayAccess &$seek,
420 array | \ArrayAccess &$provide,
421 array | \ArrayAccess &$pull,
422 array | \ArrayAccess &$internal,
423 ): void {
424 $provide[TestInterface::class] = fn() => new ImplementsTestInterface();
425 }
426 };
427 $result = $this->reader->read($component);
428
429 $name = TestInterface::class;
430 $provide = new D\Out(D\OutType::PROVIDE, $name, null, []);
431
432 $this->assertEquals(new D\OfComponent($component, $provide), $result);
433 }
434
436 {
437 $this->expectException(\LogicException::class);
438
439 $result = $this->reader->read(new class () implements Component {
440 public function init(
441 array | \ArrayAccess &$define,
442 array | \ArrayAccess &$implement,
443 array | \ArrayAccess &$use,
444 array | \ArrayAccess &$contribute,
445 array | \ArrayAccess &$seek,
446 array | \ArrayAccess &$provide,
447 array | \ArrayAccess &$pull,
448 array | \ArrayAccess &$internal,
449 ): void {
450 $provide[TestInterface::class] = fn() => new class () {};
451 }
452 });
453 }
454
456 {
457 $component = new class () implements Component {
458 public function init(
459 array | \ArrayAccess &$define,
460 array | \ArrayAccess &$implement,
461 array | \ArrayAccess &$use,
462 array | \ArrayAccess &$contribute,
463 array | \ArrayAccess &$seek,
464 array | \ArrayAccess &$provide,
465 array | \ArrayAccess &$pull,
466 array | \ArrayAccess &$internal,
467 ): void {
468 $provide[TestInterface::class] = fn() => new ImplementsTestInterface($use[TestInterface::class], $seek[TestInterface::class], $pull[TestInterface::class], $internal["something"]);
469
470 $internal["something"] = fn() => new Implements2TestInterface();
471 }
472 };
473 $result = $this->reader->read($component);
474
475 $name = TestInterface::class;
476 $use = new D\In(D\InType::USE, $name);
477 $seek = new D\In(D\InType::SEEK, $name);
478 $pull = new D\In(D\InType::PULL, $name);
479 $internal_in = new D\In(D\InType::INTERNAL, "something");
480 $internal_out = new D\Out(D\OutType::INTERNAL, "something", null, []);
481 $provide = new D\Out(D\OutType::PROVIDE, $name, null, [$use, $seek, $pull, $internal_in]);
482
483 $expected = new D\OfComponent($component, $use, $seek, $pull, $internal_in, $internal_out, $provide);
484
485 $this->assertEquals($expected, $result);
486
487 $this->assertEquals([$provide], $result[(string) $provide]);
488 $this->assertEquals([$use], $result[(string) $use]);
489 $this->assertEquals([$seek], $result[(string) $seek]);
490 $this->assertEquals([$pull], $result[(string) $pull]);
491 $this->assertEquals([$internal_in], $result[(string) $internal_in]);
492 $this->assertEquals([$internal_out], $result[(string) $internal_out]);
493 }
494
495 public function testPullWithoutContext(): void
496 {
497 $this->expectException(\LogicException::class);
498
499 $result = $this->reader->read(new class () implements Component {
500 public function init(
501 array | \ArrayAccess &$define,
502 array | \ArrayAccess &$implement,
503 array | \ArrayAccess &$use,
504 array | \ArrayAccess &$contribute,
505 array | \ArrayAccess &$seek,
506 array | \ArrayAccess &$provide,
507 array | \ArrayAccess &$pull,
508 array | \ArrayAccess &$internal,
509 ): void {
510 $foo = $pull[TestInterface::class];
511 }
512 });
513 }
514
515 public function testSimpleInternal(): void
516 {
517 $this->expectException(\LogicException::class);
518
519 $raw_name = "some_name";
520
521 $result = $this->reader->read(new class ($raw_name) implements Component {
522 public function __construct(
523 protected string $raw_name
524 ) {
525 }
526
527 public function init(
528 array | \ArrayAccess &$define,
529 array | \ArrayAccess &$implement,
530 array | \ArrayAccess &$use,
531 array | \ArrayAccess &$contribute,
532 array | \ArrayAccess &$seek,
533 array | \ArrayAccess &$provide,
534 array | \ArrayAccess &$pull,
535 array | \ArrayAccess &$internal,
536 ): void {
537 $internal[$this->raw_name] = fn() => $internal[$this->raw_name];
538 }
539 });
540 }
541
542 public function testReaderProvidesMocks(): void
543 {
544 $raw_name = "some_name";
545 $results = [];
546
547 $result = $this->reader->read(new class ($raw_name, $results) implements Component {
548 public function __construct(
549 protected string $raw_name,
550 protected array &$results
551 ) {
552 }
553
554 public function init(
555 array | \ArrayAccess &$define,
556 array | \ArrayAccess &$implement,
557 array | \ArrayAccess &$use,
558 array | \ArrayAccess &$contribute,
559 array | \ArrayAccess &$seek,
560 array | \ArrayAccess &$provide,
561 array | \ArrayAccess &$pull,
562 array | \ArrayAccess &$internal,
563 ): void {
564 $provide[TestInterface::class] = fn() => new class (
566 $use[TestInterface::class],
567 $seek[TestInterface::class],
568 $pull[TestInterface::class]
569 ) implements TestInterface {
570 public function __construct(
571 array &$results,
572 $a,
573 $b,
574 $c
575 ) {
576 $results[] = $a;
577 $results[] = $b;
578 $results[] = $c;
579 }
580 };
581 }
582 });
583
584 $this->assertInstanceOf(TestInterface::class, $results[0]);
585 $this->assertEquals([], $results[1]);
586 $this->assertInstanceOf(TestInterface::class, $results[2]);
587 }
588
589 public function testReaderResolvesInternal(): void
590 {
591 $raw_name = "some_name";
592 $results = [];
593
594 $result = $this->reader->read(new class ($raw_name, $results) implements Component {
595 public function __construct(
596 protected string $raw_name,
597 protected array &$results
598 ) {
599 }
600
601 public function init(
602 array | \ArrayAccess &$define,
603 array | \ArrayAccess &$implement,
604 array | \ArrayAccess &$use,
605 array | \ArrayAccess &$contribute,
606 array | \ArrayAccess &$seek,
607 array | \ArrayAccess &$provide,
608 array | \ArrayAccess &$pull,
609 array | \ArrayAccess &$internal,
610 ): void {
611 $provide[TestInterface::class] = fn() => new class (
613 $internal["foo"],
614 $internal["bar"],
615 $internal["baz"]
616 ) implements TestInterface {
617 public function __construct(
618 array &$results,
619 $a,
620 $b,
621 $c
622 ) {
623 $results[] = $a;
624 $results[] = $b;
625 $results[] = $c;
626 }
627 };
628
629 $internal["foo"] = fn() => $use[TestInterface::class];
630 $internal["bar"] = fn() => $seek[TestInterface::class];
631 $internal["baz"] = fn() => $pull[TestInterface2::class];
632 }
633 });
634
635 $this->assertInstanceOf(TestInterface::class, $results[0]);
636 $this->assertEquals([], $results[1]);
637 $this->assertInstanceOf(TestInterface2::class, $results[2]);
638 }
639}
A dependency where the component needs something from the world.
Definition: In.php:27
A dependency where the component gives something to the world.
Definition: Out.php:27
init(array|\ArrayAccess &$define, array|\ArrayAccess &$implement, array|\ArrayAccess &$use, array|\ArrayAccess &$contribute, array|\ArrayAccess &$seek, array|\ArrayAccess &$provide, array|\ArrayAccess &$pull, array|\ArrayAccess &$internal,)
Definition: Component.php:25
__construct()
Constructor setup ILIAS global object @access public.
Definition: class.ilias.php:76
$c
Definition: deliver.php:25
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
$results