packages/deriver/tests/Integration/ExtensionFailureTest.php
1<?php
2
3declare (strict_types=1);
4
5namespace Tests\Integration;
6
7use Deriver\Deriver\Candidate\Snapshot;
8use Deriver\Deriver\Contributions;
9use Deriver\Deriver\DeriverConfig;
10use Deriver\Deriver\EvaluationOperation;
11use Deriver\Deriver\Evaluator\Call\CallDescriptor;
12use Deriver\Deriver\Evaluator\Call\CallEvaluator;
13use Deriver\Deriver\Evaluator\Call\Evaluators;
14use Deriver\Deriver\Evaluator\Call\Provider\DispatchProvider;
15use Deriver\Deriver\Evaluator\Call\Provider\Provider;
16use Deriver\Deriver\Evaluator\Call\Provider\RefinementEvaluator;
17use Deriver\Deriver\Evaluator\Call\Registrations;
18use Deriver\Deriver\Evaluator\Domain\AbstractDomain;
19use Deriver\Deriver\Evaluator\EvaluatorConfig;
20use Deriver\Deriver\Evaluator\Evidence\Frontier;
21use Deriver\Deriver\Evaluator\Execution\EvaluatorConfig as ExecutionEvaluatorConfig;
22use Deriver\Deriver\Evaluator\Index\DefinitionIndex;
23use Deriver\Deriver\Evaluator\Intrinsic\PureIntrinsic;
24use Deriver\Deriver\Evaluator\Request\ReturnQuery;
25use Deriver\Deriver\Evaluator\TargetProfile;
26use Deriver\Deriver\Evaluator\Term;
27use Deriver\Deriver\Execution\QueryExecution;
28use Deriver\Deriver\Lowerer\Declaration\Index;
29use Deriver\Deriver\MicroEvaluator;
30use Deriver\Deriver\MicroEvaluatorConversion;
31use Deriver\Deriver\Parser\Node\File;
32use Deriver\Deriver\Parser\Parser;
33use Deriver\Deriver\Parser\ParserConfig;
34use Deriver\Deriver\Providers\DeclarationProvider;
35use Deriver\Deriver\Providers\DomainProvider;
36use Deriver\Deriver\Providers\EntryPointProvider;
37use Deriver\Deriver\Providers\EnvironmentProvider;
38use Deriver\Deriver\Providers\ProviderExpansion;
39use Deriver\Deriver\Publication\CandidateQuery;
40use Deriver\Deriver\Resolver\Resolver;
41use Deriver\Deriver\SnapshotIdentity;
42use Deriver\Deriver\Sources\Path;
43use Deriver\Deriver\Sources\Source;
44use Deriver\Deriver\Sources\Sources;
45use Deriver\Exception\EvaluationContractException;
46use Deriver\Exception\EvaluationException;
47use PHPUnit\Framework\Attributes\CoversNothing;
48use PHPUnit\Framework\Attributes\Small;
49use PHPUnit\Framework\TestCase;
50use RuntimeException;
51
52#[CoversNothing]
53#[Small]
54final class ExtensionFailureTest extends TestCase
55{
56 public function testOpenPropagatesDeclarationProviderFailures(): void
57 {
58 $provider = self::createStub(DeclarationProvider::class);
59 $provider->method('id')->willReturn('broken');
60 $provider->method('version')->willReturn('1');
61 $failure = new EvaluationException('Provider export failed');
62 $provider->method('declarations')->willThrowException($failure);
63 $this->expectExceptionObject($failure);
64 $prepared1Input = new Sources([]);
65 $prepared1Configuration = new DeriverConfig();
66 $prepared1Contributions = new Contributions(providers: [$provider]);
67 $prepared1Target = new TargetProfile($prepared1Configuration->phpVersion, $prepared1Configuration->integerBits, $prepared1Configuration->floatPrecision);
68 $prepared1Providers = new ProviderExpansion($prepared1Input, array_map(Term::fromNative(...), $prepared1Configuration->environment), $prepared1Contributions);
69 $contributions = $prepared1Providers->contributions;
70 $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);
71 $prepared1Settings = new EvaluatorConfig($prepared1Target, $prepared1Providers->environment, $prepared1Configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $prepared1Configuration->evaluators));
72 $prepared1Identity = new SnapshotIdentity($prepared1Providers->input, $prepared1Settings, $prepared1Evaluators, $prepared1Providers->manifest);
73 $snapshotId = $prepared1Identity->id;
74 $input = $prepared1Providers->input;
75 $parser = new Parser(new ParserConfig($prepared1Target->version));
76 $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));
77 $prepared1Program = new Index($snapshotId, $trees);
78 $prepared1Snapshot = $prepared1Identity->snapshot(array_map(Frontier::fromDiagnostic(...), $prepared1Program->diagnostics()));
79 }
80 public function testOpenPropagatesEnvironmentProviderFailures(): void
81 {
82 $provider = self::createStub(EnvironmentProvider::class);
83 $provider->method('id')->willReturn('broken');
84 $provider->method('version')->willReturn('1');
85 $failure = new EvaluationException('Provider export failed');
86 $provider->method('environment')->willThrowException($failure);
87 $this->expectExceptionObject($failure);
88 $prepared2Input = new Sources([]);
89 $prepared2Configuration = new DeriverConfig();
90 $prepared2Contributions = new Contributions(providers: [$provider]);
91 $prepared2Target = new TargetProfile($prepared2Configuration->phpVersion, $prepared2Configuration->integerBits, $prepared2Configuration->floatPrecision);
92 $prepared2Providers = new ProviderExpansion($prepared2Input, array_map(Term::fromNative(...), $prepared2Configuration->environment), $prepared2Contributions);
93 $contributions = $prepared2Providers->contributions;
94 $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);
95 $prepared2Settings = new EvaluatorConfig($prepared2Target, $prepared2Providers->environment, $prepared2Configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $prepared2Configuration->evaluators));
96 $prepared2Identity = new SnapshotIdentity($prepared2Providers->input, $prepared2Settings, $prepared2Evaluators, $prepared2Providers->manifest);
97 $snapshotId = $prepared2Identity->id;
98 $input = $prepared2Providers->input;
99 $parser = new Parser(new ParserConfig($prepared2Target->version));
100 $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));
101 $prepared2Program = new Index($snapshotId, $trees);
102 $prepared2Snapshot = $prepared2Identity->snapshot(array_map(Frontier::fromDiagnostic(...), $prepared2Program->diagnostics()));
103 }
104 public function testOpenPropagatesEntryPointProviderFailures(): void
105 {
106 $provider = self::createStub(EntryPointProvider::class);
107 $provider->method('id')->willReturn('broken');
108 $provider->method('version')->willReturn('1');
109 $failure = new EvaluationException('Provider export failed');
110 $provider->method('entries')->willThrowException($failure);
111 $this->expectExceptionObject($failure);
112 $prepared3Input = new Sources([]);
113 $prepared3Configuration = new DeriverConfig();
114 $prepared3Contributions = new Contributions(providers: [$provider]);
115 $prepared3Target = new TargetProfile($prepared3Configuration->phpVersion, $prepared3Configuration->integerBits, $prepared3Configuration->floatPrecision);
116 $prepared3Providers = new ProviderExpansion($prepared3Input, array_map(Term::fromNative(...), $prepared3Configuration->environment), $prepared3Contributions);
117 $contributions = $prepared3Providers->contributions;
118 $prepared3Evaluators = new Evaluators(new TargetProfile($prepared3Configuration->phpVersion, $prepared3Configuration->integerBits, $prepared3Configuration->floatPrecision), new Registrations($contributions->evaluators, $contributions->providers, $contributions->domains, $contributions->intrinsics, $contributions->stateSlots), $prepared3Configuration->standardEvaluators);
119 $prepared3Settings = new EvaluatorConfig($prepared3Target, $prepared3Providers->environment, $prepared3Configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $prepared3Configuration->evaluators));
120 $prepared3Identity = new SnapshotIdentity($prepared3Providers->input, $prepared3Settings, $prepared3Evaluators, $prepared3Providers->manifest);
121 $snapshotId = $prepared3Identity->id;
122 $input = $prepared3Providers->input;
123 $parser = new Parser(new ParserConfig($prepared3Target->version));
124 $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));
125 $prepared3Program = new Index($snapshotId, $trees);
126 $prepared3Snapshot = $prepared3Identity->snapshot(array_map(Frontier::fromDiagnostic(...), $prepared3Program->diagnostics()));
127 }
128 public function testOpenPropagatesDomainProviderFailures(): void
129 {
130 $provider = self::createStub(DomainProvider::class);
131 $provider->method('id')->willReturn('broken');
132 $provider->method('version')->willReturn('1');
133 $failure = new EvaluationException('Provider export failed');
134 $provider->method('domains')->willThrowException($failure);
135 $this->expectExceptionObject($failure);
136 $prepared4Input = new Sources([]);
137 $prepared4Configuration = new DeriverConfig();
138 $prepared4Contributions = new Contributions(providers: [$provider]);
139 $prepared4Target = new TargetProfile($prepared4Configuration->phpVersion, $prepared4Configuration->integerBits, $prepared4Configuration->floatPrecision);
140 $prepared4Providers = new ProviderExpansion($prepared4Input, array_map(Term::fromNative(...), $prepared4Configuration->environment), $prepared4Contributions);
141 $contributions = $prepared4Providers->contributions;
142 $prepared4Evaluators = new Evaluators(new TargetProfile($prepared4Configuration->phpVersion, $prepared4Configuration->integerBits, $prepared4Configuration->floatPrecision), new Registrations($contributions->evaluators, $contributions->providers, $contributions->domains, $contributions->intrinsics, $contributions->stateSlots), $prepared4Configuration->standardEvaluators);
143 $prepared4Settings = new EvaluatorConfig($prepared4Target, $prepared4Providers->environment, $prepared4Configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $prepared4Configuration->evaluators));
144 $prepared4Identity = new SnapshotIdentity($prepared4Providers->input, $prepared4Settings, $prepared4Evaluators, $prepared4Providers->manifest);
145 $snapshotId = $prepared4Identity->id;
146 $input = $prepared4Providers->input;
147 $parser = new Parser(new ParserConfig($prepared4Target->version));
148 $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));
149 $prepared4Program = new Index($snapshotId, $trees);
150 $prepared4Snapshot = $prepared4Identity->snapshot(array_map(Frontier::fromDiagnostic(...), $prepared4Program->diagnostics()));
151 }
152 public function testOpenPropagatesProviderIdentityFailures(): void
153 {
154 $provider = self::createStub(Provider::class);
155 $failure = new EvaluationException('Provider implementation error');
156 $provider->method('id')->willThrowException($failure);
157 $this->expectExceptionObject($failure);
158 $prepared5Input = new Sources([]);
159 $prepared5Configuration = new DeriverConfig();
160 $prepared5Contributions = new Contributions(providers: [$provider]);
161 $prepared5Target = new TargetProfile($prepared5Configuration->phpVersion, $prepared5Configuration->integerBits, $prepared5Configuration->floatPrecision);
162 $prepared5Providers = new ProviderExpansion($prepared5Input, array_map(Term::fromNative(...), $prepared5Configuration->environment), $prepared5Contributions);
163 $contributions = $prepared5Providers->contributions;
164 $prepared5Evaluators = new Evaluators(new TargetProfile($prepared5Configuration->phpVersion, $prepared5Configuration->integerBits, $prepared5Configuration->floatPrecision), new Registrations($contributions->evaluators, $contributions->providers, $contributions->domains, $contributions->intrinsics, $contributions->stateSlots), $prepared5Configuration->standardEvaluators);
165 $prepared5Settings = new EvaluatorConfig($prepared5Target, $prepared5Providers->environment, $prepared5Configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $prepared5Configuration->evaluators));
166 $prepared5Identity = new SnapshotIdentity($prepared5Providers->input, $prepared5Settings, $prepared5Evaluators, $prepared5Providers->manifest);
167 $snapshotId = $prepared5Identity->id;
168 $input = $prepared5Providers->input;
169 $parser = new Parser(new ParserConfig($prepared5Target->version));
170 $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));
171 $prepared5Program = new Index($snapshotId, $trees);
172 $prepared5Snapshot = $prepared5Identity->snapshot(array_map(Frontier::fromDiagnostic(...), $prepared5Program->diagnostics()));
173 }
174 public function testOpenPropagatesModelDescriptorFailures(): void
175 {
176 $evaluator = self::createStub(CallEvaluator::class);
177 $failure = new EvaluationException('Evaluator descriptor implementation error');
178 $evaluator->method('descriptor')->willThrowException($failure);
179 $this->expectExceptionObject($failure);
180 $prepared6Input = new Sources([]);
181 $prepared6Configuration = new DeriverConfig();
182 $prepared6Contributions = new Contributions(evaluators: [$evaluator]);
183 $prepared6Target = new TargetProfile($prepared6Configuration->phpVersion, $prepared6Configuration->integerBits, $prepared6Configuration->floatPrecision);
184 $prepared6Providers = new ProviderExpansion($prepared6Input, array_map(Term::fromNative(...), $prepared6Configuration->environment), $prepared6Contributions);
185 $contributions = $prepared6Providers->contributions;
186 $prepared6Evaluators = new Evaluators(new TargetProfile($prepared6Configuration->phpVersion, $prepared6Configuration->integerBits, $prepared6Configuration->floatPrecision), new Registrations($contributions->evaluators, $contributions->providers, $contributions->domains, $contributions->intrinsics, $contributions->stateSlots), $prepared6Configuration->standardEvaluators);
187 $prepared6Settings = new EvaluatorConfig($prepared6Target, $prepared6Providers->environment, $prepared6Configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $prepared6Configuration->evaluators));
188 $prepared6Identity = new SnapshotIdentity($prepared6Providers->input, $prepared6Settings, $prepared6Evaluators, $prepared6Providers->manifest);
189 $snapshotId = $prepared6Identity->id;
190 $input = $prepared6Providers->input;
191 $parser = new Parser(new ParserConfig($prepared6Target->version));
192 $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));
193 $prepared6Program = new Index($snapshotId, $trees);
194 $prepared6Snapshot = $prepared6Identity->snapshot(array_map(Frontier::fromDiagnostic(...), $prepared6Program->diagnostics()));
195 }
196 public function testOpenPropagatesIntrinsicDescriptorFailures(): void
197 {
198 $intrinsic = self::createStub(PureIntrinsic::class);
199 $failure = new EvaluationException('Intrinsic descriptor implementation error');
200 $intrinsic->method('descriptor')->willThrowException($failure);
201 $this->expectExceptionObject($failure);
202 $prepared7Input = new Sources([]);
203 $prepared7Configuration = new DeriverConfig();
204 $prepared7Contributions = new Contributions(intrinsics: [$intrinsic]);
205 $prepared7Target = new TargetProfile($prepared7Configuration->phpVersion, $prepared7Configuration->integerBits, $prepared7Configuration->floatPrecision);
206 $prepared7Providers = new ProviderExpansion($prepared7Input, array_map(Term::fromNative(...), $prepared7Configuration->environment), $prepared7Contributions);
207 $contributions = $prepared7Providers->contributions;
208 $prepared7Evaluators = new Evaluators(new TargetProfile($prepared7Configuration->phpVersion, $prepared7Configuration->integerBits, $prepared7Configuration->floatPrecision), new Registrations($contributions->evaluators, $contributions->providers, $contributions->domains, $contributions->intrinsics, $contributions->stateSlots), $prepared7Configuration->standardEvaluators);
209 $prepared7Settings = new EvaluatorConfig($prepared7Target, $prepared7Providers->environment, $prepared7Configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $prepared7Configuration->evaluators));
210 $prepared7Identity = new SnapshotIdentity($prepared7Providers->input, $prepared7Settings, $prepared7Evaluators, $prepared7Providers->manifest);
211 $snapshotId = $prepared7Identity->id;
212 $input = $prepared7Providers->input;
213 $parser = new Parser(new ParserConfig($prepared7Target->version));
214 $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));
215 $prepared7Program = new Index($snapshotId, $trees);
216 $prepared7Snapshot = $prepared7Identity->snapshot(array_map(Frontier::fromDiagnostic(...), $prepared7Program->diagnostics()));
217 }
218 public function testOpenPropagatesDomainFailures(): void
219 {
220 $domain = self::createStub(AbstractDomain::class);
221 $failure = new EvaluationException('Domain implementation error');
222 $domain->method('bottom')->willThrowException($failure);
223 $this->expectExceptionObject($failure);
224 $prepared8Input = new Sources([]);
225 $prepared8Configuration = new DeriverConfig();
226 $prepared8Contributions = new Contributions(domains: [$domain]);
227 $prepared8Target = new TargetProfile($prepared8Configuration->phpVersion, $prepared8Configuration->integerBits, $prepared8Configuration->floatPrecision);
228 $prepared8Providers = new ProviderExpansion($prepared8Input, array_map(Term::fromNative(...), $prepared8Configuration->environment), $prepared8Contributions);
229 $contributions = $prepared8Providers->contributions;
230 $prepared8Evaluators = new Evaluators(new TargetProfile($prepared8Configuration->phpVersion, $prepared8Configuration->integerBits, $prepared8Configuration->floatPrecision), new Registrations($contributions->evaluators, $contributions->providers, $contributions->domains, $contributions->intrinsics, $contributions->stateSlots), $prepared8Configuration->standardEvaluators);
231 $prepared8Settings = new EvaluatorConfig($prepared8Target, $prepared8Providers->environment, $prepared8Configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $prepared8Configuration->evaluators));
232 $prepared8Identity = new SnapshotIdentity($prepared8Providers->input, $prepared8Settings, $prepared8Evaluators, $prepared8Providers->manifest);
233 $snapshotId = $prepared8Identity->id;
234 $input = $prepared8Providers->input;
235 $parser = new Parser(new ParserConfig($prepared8Target->version));
236 $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));
237 $prepared8Program = new Index($snapshotId, $trees);
238 $prepared8Snapshot = $prepared8Identity->snapshot(array_map(Frontier::fromDiagnostic(...), $prepared8Program->diagnostics()));
239 }
240 public function testDeriveCannotTurnAModelFailureIntoAnApplicationException(): void
241 {
242 $evaluator = self::createStub(CallEvaluator::class);
243 $evaluator->method('descriptor')->willReturn(new CallDescriptor('broken', '1', 'external'));
244 $failure = new EvaluationException('Evaluator implementation error');
245 $evaluator->method('evaluate')->willThrowException($failure);
246 $input = new Sources([new Source('fixture.php', '<?php function target(){try{return external();}catch(Throwable $e){return "hidden";}}')]);
247 $configuration = new DeriverConfig();
248 $contributions = new Contributions(evaluators: [$evaluator]);
249 $target = new TargetProfile($configuration->phpVersion, $configuration->integerBits, $configuration->floatPrecision);
250 $providers = new ProviderExpansion($input, array_map(Term::fromNative(...), $configuration->environment), $contributions);
251 $contributions1 = $providers->contributions;
252 $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);
253 $settings = new EvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $configuration->evaluators));
254 $identity = new SnapshotIdentity($providers->input, $settings, $evaluators, $providers->manifest);
255 $snapshotId = $identity->id;
256 $input1 = $providers->input;
257 $parser = new Parser(new ParserConfig($target->version));
258 $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));
259 $program = new Index($snapshotId, $trees);
260 $session = new QueryExecution($program, new ExecutionEvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators), $evaluators, $identity->snapshot(array_map(Frontier::fromDiagnostic(...), $program->diagnostics())));
261 $this->expectExceptionObject($failure);
262 $session->derive(new ReturnQuery('target'));
263 }
264 public function testMicroEvaluatorFailuresPropagateWithTheirIdentity(): void
265 {
266 $failure = new RuntimeException('Extension failed');
267 $micro = (new MicroEvaluatorConversion())->convert(new MicroEvaluator('broken', '1', EvaluationOperation::Function, 'provided', static fn () => throw $failure));
268 $target = new TargetProfile();
269 $snapshotId = 'test';
270 $input = new Sources([new Source('app.php', '<?php function target(){return provided();}')]);
271 $parser = new Parser(new ParserConfig($target->version));
272 $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));
273 $program = new Index($snapshotId, $trees);
274 $query = new CandidateQuery(new DefinitionIndex($program), new EvaluatorConfig($target, evaluators: [$micro]), new Evaluators($target), new Snapshot('test', [], [], $target, ''));
275 $this->expectException(EvaluationContractException::class);
276 $this->expectExceptionMessage('broken: Extension failed');
277 $query->derive(new ReturnQuery('target'));
278 }
279 public function testDerivePropagatesDispatchFailures(): void
280 {
281 $provider = self::createStub(DispatchProvider::class);
282 $provider->method('id')->willReturn('broken');
283 $provider->method('version')->willReturn('1');
284 $failure = new EvaluationException('Dispatch implementation error');
285 $provider->method('resolve')->willThrowException($failure);
286 $input = new Sources([new Source('fixture.php', '<?php interface Service {function value();} function target(Service $service){return $service->value();}')]);
287 $configuration = new DeriverConfig();
288 $contributions = new Contributions(providers: [$provider]);
289 $target = new TargetProfile($configuration->phpVersion, $configuration->integerBits, $configuration->floatPrecision);
290 $providers = new ProviderExpansion($input, array_map(Term::fromNative(...), $configuration->environment), $contributions);
291 $contributions1 = $providers->contributions;
292 $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);
293 $settings = new EvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $configuration->evaluators));
294 $identity = new SnapshotIdentity($providers->input, $settings, $evaluators, $providers->manifest);
295 $snapshotId = $identity->id;
296 $input1 = $providers->input;
297 $parser = new Parser(new ParserConfig($target->version));
298 $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));
299 $program = new Index($snapshotId, $trees);
300 $session = new QueryExecution($program, new ExecutionEvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators), $evaluators, $identity->snapshot(array_map(Frontier::fromDiagnostic(...), $program->diagnostics())));
301 $this->expectExceptionObject($failure);
302 $session->derive(new ReturnQuery('target'));
303 }
304 public function testDerivePropagatesRefinementFailures(): void
305 {
306 $provider = self::createStub(RefinementEvaluator::class);
307 $provider->method('id')->willReturn('broken');
308 $provider->method('version')->willReturn('1');
309 $failure = new EvaluationException('Refinement implementation error');
310 $provider->method('refine')->willThrowException($failure);
311 $input = new Sources([new Source('fixture.php', '<?php function target(bool $flag){return $flag ? 1 : 2;}')]);
312 $configuration = new DeriverConfig();
313 $contributions = new Contributions(providers: [$provider]);
314 $target = new TargetProfile($configuration->phpVersion, $configuration->integerBits, $configuration->floatPrecision);
315 $providers = new ProviderExpansion($input, array_map(Term::fromNative(...), $configuration->environment), $contributions);
316 $contributions1 = $providers->contributions;
317 $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);
318 $settings = new EvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators, array_map((new MicroEvaluatorConversion())->convert(...), $configuration->evaluators));
319 $identity = new SnapshotIdentity($providers->input, $settings, $evaluators, $providers->manifest);
320 $snapshotId = $identity->id;
321 $input1 = $providers->input;
322 $parser = new Parser(new ParserConfig($target->version));
323 $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));
324 $program = new Index($snapshotId, $trees);
325 $session = new QueryExecution($program, new ExecutionEvaluatorConfig($target, $providers->environment, $configuration->standardEvaluators), $evaluators, $identity->snapshot(array_map(Frontier::fromDiagnostic(...), $program->diagnostics())));
326 $this->expectExceptionObject($failure);
327 $session->derive(new ReturnQuery('target'));
328 }
329}
330