packages/deriver/tests/Unit/Deriver/Evaluator/Predicate/BranchTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Deriver\Evaluator\Predicate;
6
7use Deriver\Deriver\Evaluator\Call\Evaluators;
8use Deriver\Deriver\Evaluator\Enumeration\Choices;
9use Deriver\Deriver\Evaluator\Evaluator;
10use Deriver\Deriver\Evaluator\EvaluatorConfig;
11use Deriver\Deriver\Evaluator\Index\DefinitionIndex;
12use Deriver\Deriver\Evaluator\Micro\Request;
13use Deriver\Deriver\Evaluator\Predicate\Branch;
14use Deriver\Deriver\Evaluator\Request\Budget;
15use Deriver\Deriver\Evaluator\Scope\Context;
16use Deriver\Deriver\Evaluator\Scope\Frame;
17use Deriver\Deriver\Evaluator\Term;
18use Deriver\Deriver\Lowerer\Declaration\Index;
19use Deriver\Deriver\Parser\Parser;
20use Deriver\Deriver\Parser\ParserConfig;
21use Deriver\Deriver\Resolver\Resolver;
22use Deriver\Deriver\Sources\Source;
23use PHPUnit\Framework\Attributes\CoversNothing;
24use PHPUnit\Framework\TestCase;
25
26#[CoversNothing]
27final class BranchTest extends TestCase
28{
29    public function testConditionDefaultsToBothBranchesWithoutOpeningItsInput(): void
30    {
31        $source = 'function subject(){return missing();}';
32        $tree = (new Resolver())->resolve((new Parser(new ParserConfig('8.3')))->parse(new Source('a.php', '<?php ' . $source)));
33        $index = new DefinitionIndex(new Index('s', [$tree]));
34        $config = new EvaluatorConfig();
35        $engine = new Evaluator(new Context($index, $config, new Evaluators($config->target), new Budget()));
36        $graph = $index->graph('subject');
37        self::assertNotNull($graph);
38        $frame = new Frame($graph, 'source:subject');
39        $result = (new Branch($engine))->condition($frame, $graph->returns()[0][1], 32);
40        self::assertCount(2, iterator_to_array((new Choices())->alternatives($result)));
41        self::assertSame(0, $engine->context->referenceExpansions);
42    }
43
44    public function testEvaluateRequiresNoInstructionOrInputForDefaultSelection(): void
45    {
46        $source = 'function subject(){return 42;}';
47        $tree = (new Resolver())->resolve((new Parser(new ParserConfig('8.3')))->parse(new Source('a.php', '<?php ' . $source)));
48        $index = new DefinitionIndex(new Index('s', [$tree]));
49        $config = new EvaluatorConfig();
50        $engine = new Evaluator(new Context($index, $config, new Evaluators($config->target), new Budget()));
51        $graph = $index->graph('subject');
52        self::assertNotNull($graph);
53        $frame = new Frame($graph, 'source:subject');
54        $site = new \Deriver\Deriver\Evaluator\Micro\Site('branch', '', $graph->body->source, static fn (): Term => Term::constant(99), static fn (): Term => Term::constant(false));
55        $result = (new Branch($engine))->evaluate(new Request($engine, $frame, null, 32, site: $site));
56        self::assertSame([true,false], array_map(static fn (array $row) => $row[0]->native(), iterator_to_array((new Choices())->alternatives($result))));
57    }
58    public function testInputRejectsAnAbsentConditionOperand(): void
59    {
60        $source = 'function subject(){return 42;}';
61        $tree = (new Resolver())->resolve((new Parser(new ParserConfig('8.3')))->parse(new Source('a.php', '<?php ' . $source)));
62        $index = new DefinitionIndex(new Index('s', [$tree]));
63        $config = new EvaluatorConfig();
64        $engine = new Evaluator(new Context($index, $config, new Evaluators($config->target), new Budget()));
65        $graph = $index->graph('subject');
66        self::assertNotNull($graph);
67        $frame = new Frame($graph, 'source:subject');
68        $this->expectException(\Deriver\Exception\EvaluationContractException::class);
69        (new Branch($engine))->input($frame, $graph->returns()[0][1], 1, 32, true);
70    }
71
72}
73