Skip to content

Commit c58f183

Browse files
committed
Added tests for incompatible providers.
Added IncompatibleProviderException. Moved ForeignResourceException to Porter's namespace.
1 parent b5b6777 commit c58f183

8 files changed

Lines changed: 69 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
<?php
22
declare(strict_types=1);
33

4-
namespace ScriptFUSION\Porter\Provider;
4+
namespace ScriptFUSION\Porter;
55

66
/**
77
* The exception that is thrown when a foreign resource is received.
88
*/
9-
class ForeignResourceException extends \RuntimeException
9+
final class ForeignResourceException extends \LogicException
1010
{
1111
// Intentionally empty.
1212
}

src/ImportException.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
/**
77
* The exception that is thrown when an import fails.
88
*/
9-
class ImportException extends \RuntimeException
9+
final class ImportException extends \RuntimeException
1010
{
1111
// Intentionally empty.
1212
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace ScriptFUSION\Porter;
5+
6+
/**
7+
* The exception that is thrown when a provider is incompatible with an import operation because it only supports
8+
* sync during an async import or vice-versa.
9+
*/
10+
final class IncompatibleProviderException extends \LogicException
11+
{
12+
public function __construct(string $expectedType)
13+
{
14+
parent::__construct("Provider does not implement $expectedType.");
15+
}
16+
}

src/Porter.php

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
use ScriptFUSION\Porter\Connector\ConnectorOptions;
1919
use ScriptFUSION\Porter\Connector\ImportConnectorFactory;
2020
use ScriptFUSION\Porter\Provider\AsyncProvider;
21-
use ScriptFUSION\Porter\Provider\ForeignResourceException;
2221
use ScriptFUSION\Porter\Provider\ObjectNotCreatedException;
2322
use ScriptFUSION\Porter\Provider\Provider;
2423
use ScriptFUSION\Porter\Provider\ProviderFactory;
@@ -27,6 +26,7 @@
2726
use ScriptFUSION\Porter\Specification\ImportSpecification;
2827
use ScriptFUSION\Porter\Transform\AsyncTransformer;
2928
use ScriptFUSION\Porter\Transform\Transformer;
29+
use function Amp\call;
3030

3131
/**
3232
* Imports data from a provider defined in the providers container or internal factory.
@@ -106,6 +106,10 @@ private function fetch(ImportSpecification $specification): \Iterator
106106
$resource = $specification->getResource();
107107
$provider = $this->getProvider($specification->getProviderName() ?? $resource->getProviderClassName());
108108

109+
if (!$provider instanceof Provider) {
110+
throw new IncompatibleProviderException('Provider');
111+
}
112+
109113
if ($resource->getProviderClassName() !== \get_class($provider)) {
110114
throw new ForeignResourceException(sprintf(
111115
'Cannot fetch data from foreign resource: "%s".',
@@ -143,7 +147,11 @@ public function importAsync(AsyncImportSpecification $specification): AsyncRecor
143147
$records = new AsyncProviderRecords($records, $specification->getAsyncResource());
144148
}
145149

146-
$records = $this->transformAsync($records, $specification->getTransformers(), $specification->getContext());
150+
$records = $this->transformRecordsAsync(
151+
$records,
152+
$specification->getTransformers(),
153+
$specification->getContext()
154+
);
147155

148156
return $this->createAsyncPorterRecords($records, $specification);
149157
}
@@ -157,7 +165,7 @@ public function importAsync(AsyncImportSpecification $specification): AsyncRecor
157165
*/
158166
public function importOneAsync(AsyncImportSpecification $specification): Promise
159167
{
160-
return \Amp\call(function () use ($specification) {
168+
return call(function () use ($specification) {
161169
$results = $this->importAsync($specification);
162170

163171
yield $results->advance();
@@ -178,8 +186,7 @@ private function fetchAsync(AsyncImportSpecification $specification): Iterator
178186
$provider = $this->getProvider($specification->getProviderName() ?? $resource->getProviderClassName());
179187

180188
if (!$provider instanceof AsyncProvider) {
181-
// TODO: Specific exception type.
182-
throw new \RuntimeException('Provider does not implement AsyncProvider.');
189+
throw new IncompatibleProviderException('AsyncProvider');
183190
}
184191

185192
if ($resource->getProviderClassName() !== \get_class($provider)) {
@@ -206,8 +213,6 @@ private function fetchAsync(AsyncImportSpecification $specification): Iterator
206213
* @param RecordCollection $records
207214
* @param Transformer[] $transformers
208215
* @param mixed $context
209-
*
210-
* @return RecordCollection
211216
*/
212217
private function transformRecords(RecordCollection $records, array $transformers, $context): RecordCollection
213218
{
@@ -226,10 +231,8 @@ private function transformRecords(RecordCollection $records, array $transformers
226231
* @param AsyncRecordCollection $records
227232
* @param AsyncTransformer[] $transformers
228233
* @param mixed $context
229-
*
230-
* @return AsyncRecordCollection
231234
*/
232-
private function transformAsync(
235+
private function transformRecordsAsync(
233236
AsyncRecordCollection $records,
234237
array $transformers,
235238
$context

src/ProviderNotFoundException.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
namespace ScriptFUSION\Porter;
55

6+
/**
7+
* The exception that is thrown when the specified provider name is not found.
8+
*/
69
final class ProviderNotFoundException extends \RuntimeException
710
{
811
public function __construct(string $message, \Exception $previous = null)

test/Integration/Porter/PorterAsyncTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
use Amp\Loop;
88
use Amp\Producer;
99
use ScriptFUSION\Porter\ImportException;
10+
use ScriptFUSION\Porter\IncompatibleProviderException;
1011
use ScriptFUSION\Porter\Porter;
12+
use ScriptFUSION\Porter\Provider\AsyncProvider;
13+
use ScriptFUSION\Porter\Provider\Provider;
1114
use ScriptFUSION\Porter\Specification\AsyncImportSpecification;
1215
use ScriptFUSION\Porter\Transform\FilterTransformer;
1316

@@ -53,6 +56,17 @@ public function testImportOneOfManyAsync(): \Generator
5356
yield $this->porter->importOneAsync($this->specification);
5457
}
5558

59+
/**
60+
* Tests that when importing from a provider that does not implement AsyncProvider, an exception is thrown.
61+
*/
62+
public function testImportIncompatibleProvider(): \Generator
63+
{
64+
$this->registerProvider(\Mockery::mock(Provider::class), $providerName = 'foo');
65+
66+
$this->expectException(IncompatibleProviderException::class);
67+
yield $this->porter->importAsync($this->specification->setProviderName($providerName));
68+
}
69+
5670
/**
5771
* Tests that a stack of async filter transformers are applied correctly.
5872
* The order is deterministic because filters yield immediately.

test/Integration/Porter/PorterSyncTest.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@
1414
use ScriptFUSION\Porter\Connector\Recoverable\RecoverableExceptionHandler;
1515
use ScriptFUSION\Porter\Connector\Recoverable\StatelessRecoverableExceptionHandler;
1616
use ScriptFUSION\Porter\ImportException;
17+
use ScriptFUSION\Porter\IncompatibleProviderException;
1718
use ScriptFUSION\Porter\PorterAware;
18-
use ScriptFUSION\Porter\Provider\ForeignResourceException;
19+
use ScriptFUSION\Porter\ForeignResourceException;
20+
use ScriptFUSION\Porter\Provider\AsyncProvider;
21+
use ScriptFUSION\Porter\Provider\Provider;
1922
use ScriptFUSION\Porter\ProviderNotFoundException;
2023
use ScriptFUSION\Porter\Specification\ImportSpecification;
2124
use ScriptFUSION\Porter\Specification\StaticDataImportSpecification;
@@ -146,6 +149,17 @@ public function testImportUnregisteredProvider(): void
146149
$this->porter->import($this->specification->setProviderName('foo'));
147150
}
148151

152+
/**
153+
* Tests that when importing from a provider that does not implement Provider, an exception is thrown.
154+
*/
155+
public function testImportIncompatibleProvider(): void
156+
{
157+
$this->registerProvider(\Mockery::mock(AsyncProvider::class), $providerName = 'foo');
158+
159+
$this->expectException(IncompatibleProviderException::class);
160+
$this->porter->import($this->specification->setProviderName($providerName));
161+
}
162+
149163
/**
150164
* Tests that when a resource's provider class name does not match the provider an exception is thrown.
151165
*/

test/Integration/Porter/PorterTest.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,11 @@ protected function setUp(): void
6464
$this->specification = new ImportSpecification($this->resource);
6565
}
6666

67-
protected function registerProvider(Provider $provider, string $name = null): void
67+
/**
68+
* @param Provider|AsyncProvider $provider
69+
* @param string|null $name
70+
*/
71+
protected function registerProvider($provider, string $name = null): void
6872
{
6973
$name = $name ?? \get_class($provider);
7074

0 commit comments

Comments
 (0)