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