packages/deriver/tests/Integration/SessionContractTest.php

1<?php
2
3declare (strict_types=1);
4
5namespace Tests\Integration;
6
7use Deriver\Deriver\Contributions;
8use Deriver\Deriver\DeriverConfig;
9use Deriver\Deriver\Evaluator\Call\Evaluators;
10use Deriver\Deriver\Evaluator\Call\Registrations;
11use Deriver\Deriver\Evaluator\EvaluatorConfig;
12use Deriver\Deriver\Evaluator\Evidence\Frontier;
13use Deriver\Deriver\Evaluator\Execution\Completion\Reachability;
14use Deriver\Deriver\Evaluator\Execution\EvaluatorConfig as ExecutionEvaluatorConfig;
15use Deriver\Deriver\Evaluator\Index\DefinitionIndex;
16use Deriver\Deriver\Evaluator\Request\Budget;
17use Deriver\Deriver\Evaluator\Request\EntryPoint;
18use Deriver\Deriver\Evaluator\Request\QueryScope;
19use Deriver\Deriver\Evaluator\Request\ReturnQuery;
20use Deriver\Deriver\Evaluator\Request\ValueQuery;
21use Deriver\Deriver\Evaluator\TargetProfile;
22use Deriver\Deriver\Evaluator\Term;
23use Deriver\Deriver\Execution\QueryExecution;
24use Deriver\Deriver\Lowerer\Declaration\Index;
25use Deriver\Deriver\Lowerer\Graph\ExpressionRef;
26use Deriver\Deriver\MicroEvaluatorConversion;
27use Deriver\Deriver\Parser\Node\File;
28use Deriver\Deriver\Parser\Parser;
29use Deriver\Deriver\Parser\ParserConfig;
30use Deriver\Deriver\Providers\ProviderExpansion;
31use Deriver\Deriver\Publication\CandidateQuery;
32use Deriver\Deriver\Resolver\Resolver;
33use Deriver\Deriver\Selection\CallObservations;
34use Deriver\Deriver\SnapshotIdentity;
35use Deriver\Deriver\Sources\Path;
36use Deriver\Deriver\Sources\Source;
37use Deriver\Deriver\Sources\Sources;
38use Deriver\Exception\InvalidInputException;
39use Deriver\Exception\ParserException;
40use PHPUnit\Framework\Attributes\CoversNothing;
41use PHPUnit\Framework\Attributes\Small;
42use PHPUnit\Framework\TestCase;
43
44#[CoversNothing]
45#[Small]
46final class SessionContractTest extends TestCase
47{
48    public function testQueryIdentityIncludesArgumentsScopeAndBudget(): void
49    {
50        $input = new Sources([new Source('fixture.php', '<?php function target($x){return $x;}')]);
51        $configuration = new DeriverConfig();
52        $contributions = new Contributions();
53        $target = new TargetProfile($configuration->phpVersion, $configuration->integerBits, $configuration->floatPrecision);
54        $providers = new ProviderExpansion($input, array_map(Term::fromNative(...), $configuration->environment), $contributions);
55        $contributions1 = $providers->contributions;
56        $evaluators = new Evaluators(new TargetProfile($configuration->phpVersion, $configuration->integerBits, $configuration->floatPrecision), new Registrations($contributions1->evaluators, $contributions1->providers, $contributions1->domains, $contributions1->intrinsics, $contributions1->stateSlots), $configuration->standardEvaluators);
57        $settings = new EvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $configuration->evaluators));
58        $identity = new SnapshotIdentity($providers->input, $settings, $evaluators, $providers->manifest);
59        $snapshotId = $identity->id;
60        $input1 = $providers->input;
61        $parser = new Parser(new ParserConfig($target->version));
62        $trees = array_map(static fn (Source $source): File => (new Resolver())->resolve($parser->parse(new Source(Path::normalize($source->path), $source->contents, $source->declarationsOnly))), iterator_to_array($input1, false));
63        $program = new Index($snapshotId, $trees);
64        $session = new QueryExecution($program, new ExecutionEvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators), $evaluators, $identity->snapshot(array_map(Frontier::fromDiagnostic(...), $program->diagnostics())));
65        $one = $session->derive(new ReturnQuery('target', QueryScope::fromEntrypoints([new EntryPoint('target', [Term::constant(1)])])));
66        $two = $session->derive(new ReturnQuery('target', QueryScope::fromEntrypoints([new EntryPoint('target', [Term::constant(2)])])));
67        $small = $session->derive(new ReturnQuery('target', budget: new Budget(transfers: 1)));
68        self::assertNotSame($one->reference->id, $two->reference->id);
69        self::assertNotSame($one->reference->id, $small->reference->id);
70        self::assertSame(1, $one->normalOutcomes[0]->values['return']->native());
71        self::assertSame(2, $two->normalOutcomes[0]->values['return']->native());
72    }
73    public function testRepeatedQueriesPerformTheSameLogicalWork(): void
74    {
75        $input = new Sources([new Source('fixture.php', '<?php function target(){return 42;}function unrelated(){return 100;}')]);
76        $configuration = new DeriverConfig();
77        $contributions = new Contributions();
78        $target = new TargetProfile($configuration->phpVersion, $configuration->integerBits, $configuration->floatPrecision);
79        $providers = new ProviderExpansion($input, array_map(Term::fromNative(...), $configuration->environment), $contributions);
80        $contributions1 = $providers->contributions;
81        $evaluators = new Evaluators(new TargetProfile($configuration->phpVersion, $configuration->integerBits, $configuration->floatPrecision), new Registrations($contributions1->evaluators, $contributions1->providers, $contributions1->domains, $contributions1->intrinsics, $contributions1->stateSlots), $configuration->standardEvaluators);
82        $settings = new EvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $configuration->evaluators));
83        $identity = new SnapshotIdentity($providers->input, $settings, $evaluators, $providers->manifest);
84        $snapshotId = $identity->id;
85        $input1 = $providers->input;
86        $parser = new Parser(new ParserConfig($target->version));
87        $trees = array_map(static fn (Source $source): File => (new Resolver())->resolve($parser->parse(new Source(Path::normalize($source->path), $source->contents, $source->declarationsOnly))), iterator_to_array($input1, false));
88        $program = new Index($snapshotId, $trees);
89        $session = new QueryExecution($program, new ExecutionEvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators), $evaluators, $identity->snapshot(array_map(Frontier::fromDiagnostic(...), $program->diagnostics())));
90        $first = $session->derive(new ReturnQuery('target'));
91        $session->derive(new ReturnQuery('unrelated'));
92        $repeated = $session->derive(new ReturnQuery('target'));
93        self::assertNotSame($first, $repeated);
94        self::assertEquals($first->normalOutcomes, $repeated->normalOutcomes);
95        self::assertSame(1, $repeated->statistics->graphs);
96        self::assertSame($first->statistics->transfers, $repeated->statistics->transfers);
97    }
98    public function testCallSelectionDoesNotCompileUnrelatedFunctions(): void
99    {
100        $input = new Sources([new Source('fixture.php', '<?php function selected(){observe(42);}function unrelated(){return 100;}')]);
101        $configuration = new DeriverConfig();
102        $contributions = new Contributions();
103        $target = new TargetProfile($configuration->phpVersion, $configuration->integerBits, $configuration->floatPrecision);
104        $providers = new ProviderExpansion($input, array_map(Term::fromNative(...), $configuration->environment), $contributions);
105        $contributions1 = $providers->contributions;
106        $evaluators = new Evaluators(new TargetProfile($configuration->phpVersion, $configuration->integerBits, $configuration->floatPrecision), new Registrations($contributions1->evaluators, $contributions1->providers, $contributions1->domains, $contributions1->intrinsics, $contributions1->stateSlots), $configuration->standardEvaluators);
107        $settings = new EvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $configuration->evaluators));
108        $identity = new SnapshotIdentity($providers->input, $settings, $evaluators, $providers->manifest);
109        $snapshotId = $identity->id;
110        $input1 = $providers->input;
111        $parser = new Parser(new ParserConfig($target->version));
112        $trees = array_map(static fn (Source $source): File => (new Resolver())->resolve($parser->parse(new Source(Path::normalize($source->path), $source->contents, $source->declarationsOnly))), iterator_to_array($input1, false));
113        $program = new Index($snapshotId, $trees);
114        $session = new QueryExecution($program, new ExecutionEvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators), $evaluators, $identity->snapshot(array_map(Frontier::fromDiagnostic(...), $program->diagnostics())));
115        $site = (new CallObservations($session->program, $session->evaluators))->find('observe')[0];
116        $result = $session->derive(new ValueQuery($site->argument(0)));
117        self::assertSame(42, $result->normalOutcomes[0]->values['value']->native());
118        self::assertSame(1, $result->statistics->graphs);
119    }
120    public function testFabricatedRegistersAreInvalidInsteadOfUnreachable(): void
121    {
122        $input = new Sources([new Source('fixture.php', '<?php function target(){observe(42);}')]);
123        $configuration = new DeriverConfig();
124        $contributions = new Contributions();
125        $target = new TargetProfile($configuration->phpVersion, $configuration->integerBits, $configuration->floatPrecision);
126        $providers = new ProviderExpansion($input, array_map(Term::fromNative(...), $configuration->environment), $contributions);
127        $contributions1 = $providers->contributions;
128        $evaluators = new Evaluators(new TargetProfile($configuration->phpVersion, $configuration->integerBits, $configuration->floatPrecision), new Registrations($contributions1->evaluators, $contributions1->providers, $contributions1->domains, $contributions1->intrinsics, $contributions1->stateSlots), $configuration->standardEvaluators);
129        $settings = new EvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $configuration->evaluators));
130        $identity = new SnapshotIdentity($providers->input, $settings, $evaluators, $providers->manifest);
131        $snapshotId = $identity->id;
132        $input1 = $providers->input;
133        $parser = new Parser(new ParserConfig($target->version));
134        $trees = array_map(static fn (Source $source): File => (new Resolver())->resolve($parser->parse(new Source(Path::normalize($source->path), $source->contents, $source->declarationsOnly))), iterator_to_array($input1, false));
135        $program = new Index($snapshotId, $trees);
136        $session = new QueryExecution($program, new ExecutionEvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators), $evaluators, $identity->snapshot(array_map(Frontier::fromDiagnostic(...), $program->diagnostics())));
137        $site = (new CallObservations($session->program, $session->evaluators))->find('observe')[0];
138        $this->expectException(InvalidInputException::class);
139        $session->derive(new ValueQuery(new ExpressionRef($site->argument(0)->source, $site->callable, 'missing-register')));
140    }
141    public function testProvenUnreachableObservationHasNoResidualSuccess(): void
142    {
143        $input = new Sources([new Source('fixture.php', '<?php function target(){if(false){observe(42);}}')]);
144        $configuration = new DeriverConfig();
145        $contributions = new Contributions();
146        $target = new TargetProfile($configuration->phpVersion, $configuration->integerBits, $configuration->floatPrecision);
147        $providers = new ProviderExpansion($input, array_map(Term::fromNative(...), $configuration->environment), $contributions);
148        $contributions1 = $providers->contributions;
149        $evaluators = new Evaluators(new TargetProfile($configuration->phpVersion, $configuration->integerBits, $configuration->floatPrecision), new Registrations($contributions1->evaluators, $contributions1->providers, $contributions1->domains, $contributions1->intrinsics, $contributions1->stateSlots), $configuration->standardEvaluators);
150        $settings = new EvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $configuration->evaluators));
151        $identity = new SnapshotIdentity($providers->input, $settings, $evaluators, $providers->manifest);
152        $snapshotId = $identity->id;
153        $input1 = $providers->input;
154        $parser = new Parser(new ParserConfig($target->version));
155        $trees = array_map(static fn (Source $source): File => (new Resolver())->resolve($parser->parse(new Source(Path::normalize($source->path), $source->contents, $source->declarationsOnly))), iterator_to_array($input1, false));
156        $program = new Index($snapshotId, $trees);
157        $session = new QueryExecution($program, new ExecutionEvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators), $evaluators, $identity->snapshot(array_map(Frontier::fromDiagnostic(...), $program->diagnostics())));
158        $result = $session->derive(new ValueQuery((new CallObservations($session->program, $session->evaluators))->find('observe')[0]->argument(0)));
159        self::assertSame(Reachability::Unreachable, $result->reachability);
160        self::assertSame([], $result->normalOutcomes);
161        self::assertSame([], $result->frontiers);
162    }
163    public function testMalformedSourceRaisesParserException(): void
164    {
165        $this->expectException(ParserException::class);
166        $prepared1Input = new Sources([new Source('good.php', '<?php function target(){return 42;}'), new Source('bad.php', '<?php function broken(')]);
167        $prepared1Configuration = new DeriverConfig();
168        $prepared1Contributions = new Contributions();
169        $prepared1Target = new TargetProfile($prepared1Configuration->phpVersion, $prepared1Configuration->integerBits, $prepared1Configuration->floatPrecision);
170        $prepared1Providers = new ProviderExpansion($prepared1Input, array_map(Term::fromNative(...), $prepared1Configuration->environment), $prepared1Contributions);
171        $contributions = $prepared1Providers->contributions;
172        $prepared1Evaluators = new Evaluators(new TargetProfile($prepared1Configuration->phpVersion, $prepared1Configuration->integerBits, $prepared1Configuration->floatPrecision), new Registrations($contributions->evaluators, $contributions->providers, $contributions->domains, $contributions->intrinsics, $contributions->stateSlots), $prepared1Configuration->standardEvaluators);
173        $prepared1Settings = new EvaluatorConfig($prepared1Target, $prepared1Providers->environment, $prepared1Configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $prepared1Configuration->evaluators));
174        $prepared1Identity = new SnapshotIdentity($prepared1Providers->input, $prepared1Settings, $prepared1Evaluators, $prepared1Providers->manifest);
175        $snapshotId = $prepared1Identity->id;
176        $input = $prepared1Providers->input;
177        $parser = new Parser(new ParserConfig($prepared1Target->version));
178        $trees = array_map(static fn (Source $source): File => (new Resolver())->resolve($parser->parse(new Source(Path::normalize($source->path), $source->contents, $source->declarationsOnly))), iterator_to_array($input, false));
179        $prepared1Program = new Index($snapshotId, $trees);
180        $prepared1Snapshot = $prepared1Identity->snapshot(array_map(Frontier::fromDiagnostic(...), $prepared1Program->diagnostics()));
181    }
182    public function testFileOrderDoesNotChangeSnapshotOrSemanticResult(): void
183    {
184        $a = new Source('a.php', '<?php function target(){return helper();}');
185        $b = new Source('b.php', '<?php function helper(){return 42;}');
186        $prepared2Input = new Sources([$a, $b]);
187        $prepared2Configuration = new DeriverConfig();
188        $prepared2Contributions = new Contributions();
189        $prepared2Target = new TargetProfile($prepared2Configuration->phpVersion, $prepared2Configuration->integerBits, $prepared2Configuration->floatPrecision);
190        $prepared2Providers = new ProviderExpansion($prepared2Input, array_map(Term::fromNative(...), $prepared2Configuration->environment), $prepared2Contributions);
191        $contributions = $prepared2Providers->contributions;
192        $prepared2Evaluators = new Evaluators(new TargetProfile($prepared2Configuration->phpVersion, $prepared2Configuration->integerBits, $prepared2Configuration->floatPrecision), new Registrations($contributions->evaluators, $contributions->providers, $contributions->domains, $contributions->intrinsics, $contributions->stateSlots), $prepared2Configuration->standardEvaluators);
193        $prepared2Settings = new EvaluatorConfig($prepared2Target, $prepared2Providers->environment, $prepared2Configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $prepared2Configuration->evaluators));
194        $prepared2Identity = new SnapshotIdentity($prepared2Providers->input, $prepared2Settings, $prepared2Evaluators, $prepared2Providers->manifest);
195        $snapshotId = $prepared2Identity->id;
196        $input = $prepared2Providers->input;
197        $parser = new Parser(new ParserConfig($prepared2Target->version));
198        $trees = array_map(static fn (Source $source): File => (new Resolver())->resolve($parser->parse(new Source(Path::normalize($source->path), $source->contents, $source->declarationsOnly))), iterator_to_array($input, false));
199        $prepared2Program = new Index($snapshotId, $trees);
200        $prepared2Snapshot = $prepared2Identity->snapshot(array_map(Frontier::fromDiagnostic(...), $prepared2Program->diagnostics()));
201        $first = new CandidateQuery(new DefinitionIndex($prepared2Program), $prepared2Settings, $prepared2Evaluators, $prepared2Snapshot);
202        $prepared3Input = new Sources([$b, $a]);
203        $prepared3Configuration = new DeriverConfig();
204        $prepared3Contributions = new Contributions();
205        $prepared3Target = new TargetProfile($prepared3Configuration->phpVersion, $prepared3Configuration->integerBits, $prepared3Configuration->floatPrecision);
206        $prepared3Providers = new ProviderExpansion($prepared3Input, array_map(Term::fromNative(...), $prepared3Configuration->environment), $prepared3Contributions);
207        $contributions1 = $prepared3Providers->contributions;
208        $prepared3Evaluators = new Evaluators(new TargetProfile($prepared3Configuration->phpVersion, $prepared3Configuration->integerBits, $prepared3Configuration->floatPrecision), new Registrations($contributions1->evaluators, $contributions1->providers, $contributions1->domains, $contributions1->intrinsics, $contributions1->stateSlots), $prepared3Configuration->standardEvaluators);
209        $prepared3Settings = new EvaluatorConfig($prepared3Target, $prepared3Providers->environment, $prepared3Configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $prepared3Configuration->evaluators));
210        $prepared3Identity = new SnapshotIdentity($prepared3Providers->input, $prepared3Settings, $prepared3Evaluators, $prepared3Providers->manifest);
211        $snapshotId1 = $prepared3Identity->id;
212        $input1 = $prepared3Providers->input;
213        $parser1 = new Parser(new ParserConfig($prepared3Target->version));
214        $trees1 = array_map(static fn (Source $source1): File => (new Resolver())->resolve($parser1->parse(new Source(Path::normalize($source1->path), $source1->contents, $source1->declarationsOnly))), iterator_to_array($input1, false));
215        $prepared3Program = new Index($snapshotId1, $trees1);
216        $prepared3Snapshot = $prepared3Identity->snapshot(array_map(Frontier::fromDiagnostic(...), $prepared3Program->diagnostics()));
217        $second = new CandidateQuery(new DefinitionIndex($prepared3Program), $prepared3Settings, $prepared3Evaluators, $prepared3Snapshot);
218        $one = $first->derive(new ReturnQuery('target'));
219        $two = $second->derive(new ReturnQuery('target'));
220        self::assertSame($prepared2Snapshot->id, $prepared3Snapshot->id);
221        self::assertSame($one->reference->id, $two->reference->id);
222        self::assertEquals(iterator_to_array($one, false), iterator_to_array($two, false));
223    }
224    public function testSourceCaptureDoesNotExecuteTopLevelCode(): void
225    {
226        $input = new Sources([new Source('fixture.php', '<?php throw new RuntimeException("Never execute this file");exit(99);function target(){return 42;}')]);
227        $configuration = new DeriverConfig();
228        $contributions = new Contributions();
229        $target = new TargetProfile($configuration->phpVersion, $configuration->integerBits, $configuration->floatPrecision);
230        $providers = new ProviderExpansion($input, array_map(Term::fromNative(...), $configuration->environment), $contributions);
231        $contributions1 = $providers->contributions;
232        $evaluators = new Evaluators(new TargetProfile($configuration->phpVersion, $configuration->integerBits, $configuration->floatPrecision), new Registrations($contributions1->evaluators, $contributions1->providers, $contributions1->domains, $contributions1->intrinsics, $contributions1->stateSlots), $configuration->standardEvaluators);
233        $settings = new EvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $configuration->evaluators));
234        $identity = new SnapshotIdentity($providers->input, $settings, $evaluators, $providers->manifest);
235        $snapshotId = $identity->id;
236        $input1 = $providers->input;
237        $parser = new Parser(new ParserConfig($target->version));
238        $trees = array_map(static fn (Source $source): File => (new Resolver())->resolve($parser->parse(new Source(Path::normalize($source->path), $source->contents, $source->declarationsOnly))), iterator_to_array($input1, false));
239        $program = new Index($snapshotId, $trees);
240        $session = new QueryExecution($program, new ExecutionEvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators), $evaluators, $identity->snapshot(array_map(Frontier::fromDiagnostic(...), $program->diagnostics())));
241        $result = $session->derive(new ReturnQuery('target'));
242        self::assertSame(42, $result->normalOutcomes[0]->values['return']->native());
243        self::assertSame([], $result->frontiers);
244    }
245    public function testSourceChangesInvalidateResults(): void
246    {
247        $input = new Sources([new Source('fixture.php', '<?php function target(){return 1;}')]);
248        $configuration = new DeriverConfig();
249        $contributions = new Contributions();
250        $target = new TargetProfile($configuration->phpVersion, $configuration->integerBits, $configuration->floatPrecision);
251        $providers = new ProviderExpansion($input, array_map(Term::fromNative(...), $configuration->environment), $contributions);
252        $contributions1 = $providers->contributions;
253        $evaluators = new Evaluators(new TargetProfile($configuration->phpVersion, $configuration->integerBits, $configuration->floatPrecision), new Registrations($contributions1->evaluators, $contributions1->providers, $contributions1->domains, $contributions1->intrinsics, $contributions1->stateSlots), $configuration->standardEvaluators);
254        $settings = new EvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $configuration->evaluators));
255        $identity = new SnapshotIdentity($providers->input, $settings, $evaluators, $providers->manifest);
256        $snapshotId = $identity->id;
257        $input1 = $providers->input;
258        $parser = new Parser(new ParserConfig($target->version));
259        $trees = array_map(static fn (Source $source): File => (new Resolver())->resolve($parser->parse(new Source(Path::normalize($source->path), $source->contents, $source->declarationsOnly))), iterator_to_array($input1, false));
260        $program = new Index($snapshotId, $trees);
261        $first = new QueryExecution($program, new ExecutionEvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators), $evaluators, $identity->snapshot(array_map(Frontier::fromDiagnostic(...), $program->diagnostics())));
262        $input2 = new Sources([new Source('fixture.php', '<?php function target(){return 2;}')]);
263        $configuration1 = new DeriverConfig();
264        $contributions2 = new Contributions();
265        $target1 = new TargetProfile($configuration1->phpVersion, $configuration1->integerBits, $configuration1->floatPrecision);
266        $providers1 = new ProviderExpansion($input2, array_map(Term::fromNative(...), $configuration1->environment), $contributions2);
267        $contributions3 = $providers1->contributions;
268        $evaluators1 = new Evaluators(new TargetProfile($configuration1->phpVersion, $configuration1->integerBits, $configuration1->floatPrecision), new Registrations($contributions3->evaluators, $contributions3->providers, $contributions3->domains, $contributions3->intrinsics, $contributions3->stateSlots), $configuration1->standardEvaluators);
269        $settings1 = new EvaluatorConfig($target1, $providers1->environment, $configuration1->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $configuration1->evaluators));
270        $identity1 = new SnapshotIdentity($providers1->input, $settings1, $evaluators1, $providers1->manifest);
271        $snapshotId1 = $identity1->id;
272        $input3 = $providers1->input;
273        $parser1 = new Parser(new ParserConfig($target1->version));
274        $trees1 = array_map(static fn (Source $source1): File => (new Resolver())->resolve($parser1->parse(new Source(Path::normalize($source1->path), $source1->contents, $source1->declarationsOnly))), iterator_to_array($input3, false));
275        $program1 = new Index($snapshotId1, $trees1);
276        $second = new QueryExecution($program1, new ExecutionEvaluatorConfig($target1, $providers1->environment, $configuration1->standardEvaluators), $evaluators1, $identity1->snapshot(array_map(Frontier::fromDiagnostic(...), $program1->diagnostics())));
277        self::assertNotSame($first->snapshot->id, $second->snapshot->id);
278        self::assertSame(2, $second->derive(new ReturnQuery('target'))->normalOutcomes[0]->values['return']->native());
279    }
280}
281