Files
wyczarujprezent.pl/modules/ps_metrics/vendor/overblog/dataloader-php/tests/DataLoadTest.php
2024-10-28 22:14:22 +01:00

907 lines
30 KiB
PHP

<?php
/*
* This file is part of the DataLoaderPhp package.
*
* (c) Overblog <http://github.com/overblog/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Overblog\DataLoader\Test;
use Overblog\DataLoader\DataLoader;
use Overblog\DataLoader\Option;
class DataLoadTest extends TestCase
{
/**
* @group primary-api
*/
public function testBuildsAReallyReallySimpleDataLoader()
{
/**
* @var DataLoader $identityLoader
*/
list($identityLoader) = self::idLoader();
$promise1 = $identityLoader->load(1);
$this->assertInstanceOfPromise($promise1);
$this->assertEquals(1, DataLoader::await($promise1));
}
/**
* @group primary-api
*/
public function testSupportsLoadingMultipleKeysInOneCall()
{
/**
* @var DataLoader $identityLoader
*/
list($identityLoader) = self::idLoader();
$promiseAll = $identityLoader->loadMany([1, 2]);
$this->assertInstanceOfPromise($promiseAll);
$this->assertEquals([1, 2], DataLoader::await($promiseAll));
$promiseEmpty = $identityLoader->loadMany([]);
$this->assertInstanceOfPromise($promiseEmpty);
$this->assertEquals([], DataLoader::await($promiseEmpty));
}
/**
* @group primary-api
*/
public function testBatchesMultipleRequests()
{
/**
* @var DataLoader $identityLoader
* @var \ArrayObject $loadCalls
*/
list($identityLoader, $loadCalls) = self::idLoader();
$promise1 = $identityLoader->load(1);
$promise2 = $identityLoader->load(2);
list($value1, $value2) = DataLoader::await(self::$promiseAdapter->createAll([$promise1, $promise2]));
$this->assertEquals(1, $value1);
$this->assertEquals(2, $value2);
$this->assertEquals([[1, 2]], $loadCalls->getArrayCopy());
}
/**
* @group primary-api
*/
public function testBatchesMultipleRequestsWithMaxBatchSizes()
{
/**
* @var DataLoader $identityLoader
* @var \ArrayObject $loadCalls
*/
list($identityLoader, $loadCalls) = self::idLoader(new Option(['maxBatchSize' => 2]));
$promise1 = $identityLoader->load(1);
$promise2 = $identityLoader->load(2);
$promise3 = $identityLoader->load(3);
list($value1, $value2, $value3) = DataLoader::await(self::$promiseAdapter->createAll([$promise1, $promise2, $promise3]));
$this->assertEquals(1, $value1);
$this->assertEquals(2, $value2);
$this->assertEquals(3, $value3);
$this->assertEquals([[1, 2], [3]], $loadCalls->getArrayCopy());
}
/**
* @group primary-api
*/
public function testCoalescesIdenticalRequests()
{
/**
* @var DataLoader $identityLoader
* @var \ArrayObject $loadCalls
*/
list($identityLoader, $loadCalls) = self::idLoader();
$promise1a = $identityLoader->load(1);
$promise1b = $identityLoader->load(1);
$this->assertTrue($promise1a === $promise1b);
list($value1a, $value1b) = DataLoader::await(self::$promiseAdapter->createAll([$promise1a, $promise1b]));
$this->assertEquals(1, $value1a);
$this->assertEquals(1, $value1b);
$this->assertEquals([[1]], $loadCalls->getArrayCopy());
}
/**
* @group primary-api
*/
public function testCachesRepeatedRequests()
{
/**
* @var DataLoader $identityLoader
* @var \ArrayObject $loadCalls
*/
list($identityLoader, $loadCalls) = self::idLoader();
list($a, $b) = DataLoader::await(self::$promiseAdapter->createAll([$identityLoader->load('A'), $identityLoader->load('B')]));
$this->assertEquals('A', $a);
$this->assertEquals('B', $b);
$this->assertEquals([['A', 'B']], $loadCalls->getArrayCopy());
list($a2, $c) = DataLoader::await(self::$promiseAdapter->createAll([$identityLoader->load('A'), $identityLoader->load('C')]));
$this->assertEquals('A', $a2);
$this->assertEquals('C', $c);
$this->assertEquals([['A', 'B'], ['C']], $loadCalls->getArrayCopy());
list($a3, $b2, $c2) = DataLoader::await(self::$promiseAdapter->createAll([$identityLoader->load('A'), $identityLoader->load('B'), $identityLoader->load('C')]));
$this->assertEquals('A', $a3);
$this->assertEquals('B', $b2);
$this->assertEquals('C', $c2);
$this->assertEquals([['A', 'B'], ['C']], $loadCalls->getArrayCopy());
}
/**
* @group primary-api
*/
public function testClearsSingleValueInLoader()
{
/**
* @var DataLoader $identityLoader
* @var \ArrayObject $loadCalls
*/
list($identityLoader, $loadCalls) = self::idLoader();
list($a, $b) = DataLoader::await(self::$promiseAdapter->createAll([$identityLoader->load('A'), $identityLoader->load('B')]));
$this->assertEquals('A', $a);
$this->assertEquals('B', $b);
$this->assertEquals([['A', 'B']], $loadCalls->getArrayCopy());
$identityLoader->clear('A');
list($a2, $b2) = DataLoader::await(self::$promiseAdapter->createAll([$identityLoader->load('A'), $identityLoader->load('B')]));
$this->assertEquals('A', $a2);
$this->assertEquals('B', $b2);
$this->assertEquals([['A', 'B'], ['A']], $loadCalls->getArrayCopy());
}
/**
* @group primary-api
*/
public function testClearsAllValuesInLoader()
{
/**
* @var DataLoader $identityLoader
* @var \ArrayObject $loadCalls
*/
list($identityLoader, $loadCalls) = self::idLoader();
list($a, $b) = DataLoader::await(self::$promiseAdapter->createAll([$identityLoader->load('A'), $identityLoader->load('B')]));
$this->assertEquals('A', $a);
$this->assertEquals('B', $b);
$this->assertEquals([['A', 'B']], $loadCalls->getArrayCopy());
$identityLoader->clearAll();
list($a2, $b2) = DataLoader::await(self::$promiseAdapter->createAll([$identityLoader->load('A'), $identityLoader->load('B')]));
$this->assertEquals('A', $a2);
$this->assertEquals('B', $b2);
$this->assertEquals([['A', 'B'], ['A', 'B']], $loadCalls->getArrayCopy());
}
/**
* @group primary-api
*/
public function testAllowsPrimingTheCache()
{
/**
* @var DataLoader $identityLoader
* @var \ArrayObject $loadCalls
*/
list($identityLoader, $loadCalls) = self::idLoader();
$identityLoader->prime('A', 'A');
list($a, $b) = DataLoader::await(self::$promiseAdapter->createAll([$identityLoader->load('A'), $identityLoader->load('B')]));
$this->assertEquals('A', $a);
$this->assertEquals('B', $b);
$this->assertEquals([['B']], $loadCalls->getArrayCopy());
}
/**
* @group primary-api
*/
public function testDoesNotPrimeKeysThatAlreadyExist()
{
/**
* @var DataLoader $identityLoader
* @var \ArrayObject $loadCalls
*/
list($identityLoader, $loadCalls) = self::idLoader();
$identityLoader->prime('A', 'X');
$a1 = DataLoader::await($identityLoader->load('A'));
$b1 = DataLoader::await($identityLoader->load('B'));
$this->assertEquals('X', $a1);
$this->assertEquals('B', $b1);
$identityLoader->prime('A', 'Y');
$identityLoader->prime('B', 'Y');
$a2 = DataLoader::await($identityLoader->load('A'));
$b2 = DataLoader::await($identityLoader->load('B'));
$this->assertEquals('X', $a2);
$this->assertEquals('B', $b2);
$this->assertEquals([['B']], $loadCalls->getArrayCopy());
}
/**
* @group primary-api
*/
public function testAllowsForcefullyPrimingTheCache()
{
/**
* @var DataLoader $identityLoader
* @var \ArrayObject $loadCalls
*/
list($identityLoader, $loadCalls) = self::idLoader();
$identityLoader->prime('A', 'X');
$a1 = DataLoader::await($identityLoader->load('A'));
$b1 = DataLoader::await($identityLoader->load('B'));
$this->assertEquals('X', $a1);
$this->assertEquals('B', $b1);
$identityLoader->clear('A')->prime('A', 'Y');
$identityLoader->clear('B')->prime('B', 'Y');
$a2 = DataLoader::await($identityLoader->load('A'));
$b2 = DataLoader::await($identityLoader->load('B'));
$this->assertEquals('Y', $a2);
$this->assertEquals('Y', $b2);
$this->assertEquals([['B']], $loadCalls->getArrayCopy());
}
/**
* @group represents-errors
*/
public function testResolvesToErrorToIndicateFailure()
{
/**
* @var DataLoader $evenLoader
* @var \ArrayObject $loadCalls
*/
list($evenLoader, $loadCalls) = self::eventLoader();
$caughtError = DataLoader::await($evenLoader->load(1), false);
$this->assertInstanceOf(\Exception::class, $caughtError);
$this->assertEquals($caughtError->getMessage(), 'Odd: 1');
$value2 = DataLoader::await($evenLoader->load(2));
$this->assertEquals(2, $value2);
$this->assertEquals([[1], [2]], $loadCalls->getArrayCopy());
}
/**
* @group represents-errors
*/
public function testCanRepresentFailuresAndSuccessesSimultaneously()
{
/**
* @var DataLoader $evenLoader
* @var \ArrayObject $loadCalls
*/
list($evenLoader, $loadCalls) = self::eventLoader();
$promise1 = $evenLoader->load(1);
$promise2 = $evenLoader->load(2);
$caughtError = null;
$promise1->then(null, function ($error) use (&$caughtError) {
$caughtError = $error;
});
DataLoader::await();
$this->assertInstanceOf(\Exception::class, $caughtError);
$this->assertEquals($caughtError->getMessage(), 'Odd: 1');
$this->assertEquals(2, DataLoader::await($promise2));
$this->assertEquals([[1, 2]], $loadCalls->getArrayCopy());
}
/**
* @group represents-errors
*/
public function testCachesFailedFetches()
{
/**
* @var DataLoader $errorLoader
* @var \ArrayObject $loadCalls
*/
list($errorLoader, $loadCalls) = self::errorLoader();
$caughtErrorA = null;
try {
DataLoader::await($errorLoader->load(1));
} catch (\Exception $error) {
$caughtErrorA = $error;
}
$this->assertInstanceOf(\Exception::class, $caughtErrorA);
$this->assertEquals($caughtErrorA->getMessage(), 'Error: 1');
$caughtErrorB = null;
try {
DataLoader::await($errorLoader->load(1));
} catch (\Exception $error) {
$caughtErrorB = $error;
}
$this->assertInstanceOf(\Exception::class, $caughtErrorB);
$this->assertEquals($caughtErrorB->getMessage(), 'Error: 1');
$this->assertEquals([[1]], $loadCalls->getArrayCopy());
}
/**
* @group represents-errors
*/
public function testHandlesPrimingTheCacheWithAnError()
{
/**
* @var DataLoader $identityLoader
* @var \ArrayObject $loadCalls
*/
list($identityLoader, $loadCalls) = self::idLoader();
$identityLoader->prime(1, new \Exception('Error: 1'));
$caughtErrorA = null;
try {
DataLoader::await($identityLoader->load(1));
} catch (\Exception $error) {
$caughtErrorA = $error;
}
$this->assertInstanceOf(\Exception::class, $caughtErrorA);
$this->assertEquals($caughtErrorA->getMessage(), 'Error: 1');
$this->assertEquals([], $loadCalls->getArrayCopy());
}
/**
* @group represents-errors
*/
public function testCanClearValuesFromCacheAfterErrors()
{
/**
* @var DataLoader $errorLoader
* @var \ArrayObject $loadCalls
*/
list($errorLoader, $loadCalls) = self::errorLoader();
$caughtErrorA = null;
try {
DataLoader::await(
$errorLoader->load(1)
->then(null, function ($error) use (&$errorLoader) {
$errorLoader->clear(1);
throw $error;
})
);
} catch (\Exception $error) {
$caughtErrorA = $error;
}
$this->assertInstanceOf(\Exception::class, $caughtErrorA);
$this->assertEquals($caughtErrorA->getMessage(), 'Error: 1');
$caughtErrorB = null;
try {
DataLoader::await(
$errorLoader->load(1)
->then(null, function ($error) use (&$errorLoader) {
$errorLoader->clear(1);
throw $error;
})
);
} catch (\Exception $error) {
$caughtErrorB = $error;
}
$this->assertInstanceOf(\Exception::class, $caughtErrorB);
$this->assertEquals($caughtErrorB->getMessage(), 'Error: 1');
$this->assertEquals([[1], [1]], $loadCalls->getArrayCopy());
}
/**
* @group represents-errors
*/
public function testPropagatesErrorToAllLoads()
{
/**
* @var DataLoader $failLoader
* @var \ArrayObject $loadCalls
*/
list($failLoader, $loadCalls) = self::idLoader(null, function () {
return self::$promiseAdapter->createRejected(new \Exception('I am a terrible loader'));
});
$promise1 = $failLoader->load(1);
$promise2 = $failLoader->load(2);
$caughtError1 = null;
try {
DataLoader::await($promise1);
} catch (\Exception $error) {
$caughtError1 = $error;
}
$this->assertInstanceOf(\Exception::class, $caughtError1);
$this->assertEquals($caughtError1->getMessage(), 'I am a terrible loader');
$caughtError2 = null;
try {
DataLoader::await($promise2);
} catch (\Exception $error) {
$caughtError2 = $error;
}
$this->assertInstanceOf(\Exception::class, $caughtError2);
$this->assertEquals($caughtError2->getMessage(), 'I am a terrible loader');
$this->assertEquals([[1, 2]], $loadCalls->getArrayCopy());
}
/**
* @group accepts-any-kind-of-key
*/
public function testAcceptsObjectsAsKeys()
{
/**
* @var DataLoader $identityLoader
* @var \ArrayObject $loadCalls
*/
list($identityLoader, $loadCalls) = self::idLoader();
$keyA = new \stdClass();
$keyB = new \stdClass();
list($valueA, $valueB) = DataLoader::await(self::$promiseAdapter->createAll([$identityLoader->load($keyA), $identityLoader->load($keyB)]));
$this->assertEquals($keyA, $valueA);
$this->assertEquals($keyB, $valueB);
$loadCallsArray = $loadCalls->getArrayCopy();
$this->assertCount(1, $loadCallsArray);
$this->assertCount(2, $loadCallsArray[0]);
$this->assertEquals($keyA, $loadCallsArray[0][0]);
$this->assertEquals($keyB, $loadCallsArray[0][1]);
// Caching
$identityLoader->clear($keyA);
list($valueA2, $valueB2) = DataLoader::await(self::$promiseAdapter->createAll([$identityLoader->load($keyA), $identityLoader->load($keyB)]));
$this->assertEquals($keyA, $valueA2);
$this->assertEquals($keyB, $valueB2);
$loadCallsArray = $loadCalls->getArrayCopy();
$this->assertCount(2, $loadCallsArray);
$this->assertCount(1, $loadCallsArray[1]);
$this->assertEquals($keyA, $loadCallsArray[1][0]);
}
/**
* Note: mirrors 'batches multiple requests' above.
*
* @group accepts-options
*/
public function testMayDisableBatching()
{
/**
* @var DataLoader $identityLoader
* @var \ArrayObject $loadCalls
*/
list($identityLoader, $loadCalls) = self::idLoader(new Option(['batch' => false]));
$promise1 = $identityLoader->load(1);
$promise2 = $identityLoader->load(2);
list($value1, $value2) = DataLoader::await(self::$promiseAdapter->createAll([$promise1, $promise2]));
$this->assertEquals(1, $value1);
$this->assertEquals(2, $value2);
$this->assertEquals([[1], [2]], $loadCalls->getArrayCopy());
}
/**
* Note: mirror's 'caches repeated requests' above.
*
* @group accepts-options
*/
public function testMayDisableCaching()
{
/**
* @var DataLoader $identityLoader
* @var \ArrayObject $loadCalls
*/
list($identityLoader, $loadCalls) = self::idLoader(new Option(['cache' => false]));
list($a, $b) = DataLoader::await(self::$promiseAdapter->createAll([$identityLoader->load('A'), $identityLoader->load('B')]));
$this->assertEquals('A', $a);
$this->assertEquals('B', $b);
$this->assertEquals([['A', 'B']], $loadCalls->getArrayCopy());
list($a2, $c) = DataLoader::await(self::$promiseAdapter->createAll([$identityLoader->load('A'), $identityLoader->load('C')]));
$this->assertEquals('A', $a2);
$this->assertEquals('C', $c);
$this->assertEquals([['A', 'B'], ['A', 'C']], $loadCalls->getArrayCopy());
list($a3, $b2, $c2) = DataLoader::await(self::$promiseAdapter->createAll([$identityLoader->load('A'), $identityLoader->load('B'), $identityLoader->load('C')]));
$this->assertEquals('A', $a3);
$this->assertEquals('B', $b2);
$this->assertEquals('C', $c2);
$this->assertEquals([['A', 'B'], ['A', 'C'], ['A', 'B', 'C']], $loadCalls->getArrayCopy());
}
/**
* @group accepts-options
* @group accepts-object-key-in-custom-cacheKey-function
*/
public function testAcceptsObjectsWithAComplexKey()
{
/**
* @var DataLoader $identityLoader
* @var \ArrayObject $loadCalls
*/
list($identityLoader, $loadCalls) = self::idLoader(new Option(['cacheKeyFn' => [$this, 'cacheKey']]));
$key1 = (object)['id' => 123];
$key2 = (object)['id' => 123];
$value1 = $identityLoader->await($identityLoader->load($key1));
$value2 = $identityLoader->await($identityLoader->load($key2));
$this->assertEquals([[$key1]], $loadCalls->getArrayCopy());
$this->assertEquals($value1, $key1);
$this->assertEquals($value2, $key1);
}
/**
* @group accepts-options
* @group accepts-object-key-in-custom-cacheKey-function
*/
public function testClearsObjectsWithComplexKey()
{
/**
* @var DataLoader $identityLoader
* @var \ArrayObject $loadCalls
*/
list($identityLoader, $loadCalls) = self::idLoader(new Option(['cacheKeyFn' => [$this, 'cacheKey']]));
$key1 = (object)['id' => 123];
$key2 = (object)['id' => 123];
$value1 = $identityLoader->await($identityLoader->load($key1));
$identityLoader->clear($key2); // clear equivalent object key
$value2 = $identityLoader->await($identityLoader->load($key1));
$this->assertEquals([[$key1], [$key1]], $loadCalls->getArrayCopy());
$this->assertEquals($value1, $key1);
$this->assertEquals($value2, $key1);
}
/**
* @group accepts-options
* @group accepts-object-key-in-custom-cacheKey-function
*/
public function testAcceptsObjectsWithDifferentOrderOfKeys()
{
/**
* @var DataLoader $identityLoader
* @var \ArrayObject $loadCalls
*/
list($identityLoader, $loadCalls) = self::idLoader(new Option(['cacheKeyFn' => [$this, 'cacheKey']]));
$keyA = (object)['a' => 123, 'b' => 321];
$keyB = (object)['b' => 321, 'a' => 123];
$valueA = $identityLoader->await($identityLoader->load($keyA));
$valueB = $identityLoader->await($identityLoader->load($keyB));
$this->assertEquals($valueA, $keyA);
$this->assertEquals($valueA, $valueB);
$loadCallsArray = $loadCalls->getArrayCopy();
$this->assertCount(1, $loadCallsArray);
$this->assertCount(1, $loadCallsArray[0]);
$this->assertEquals($keyA, $loadCallsArray[0][0]);
}
/**
* @group accepts-options
* @group accepts-object-key-in-custom-cacheKey-function
*/
public function testAllowsPrimingTheCacheWithAnObjectKey()
{
/**
* @var DataLoader $identityLoader
* @var \ArrayObject $loadCalls
*/
list($identityLoader, $loadCalls) = self::idLoader(new Option(['cacheKeyFn' => [$this, 'cacheKey']]));
$key1 = (object)['id' => 123];
$key2 = (object)['id' => 123];
$identityLoader->prime($key1, $key1);
$value1 = $identityLoader->await($identityLoader->load($key1));
$value2 = $identityLoader->await($identityLoader->load($key2));
$this->assertEquals([], $loadCalls->getArrayCopy());
$this->assertEquals($value1, $key1);
$this->assertEquals($value2, $key1);
}
/**
* @group accepts-options
* @group accepts-custom-cache-map-instance
*/
public function testAcceptsACustomCacheMapImplementation()
{
$aCustomMap = new SimpleMap();
/**
* @var DataLoader $identityLoader
* @var \ArrayObject $loadCalls
*/
list($identityLoader, $loadCalls) = self::idLoader(new Option(['cacheMap' => $aCustomMap]));
list($valueA, $valueB1) = DataLoader::await(self::$promiseAdapter->createAll([$identityLoader->load('a'), $identityLoader->load('b')]));
$this->assertEquals('a', $valueA);
$this->assertEquals('b', $valueB1);
$this->assertEquals([['a', 'b']], $loadCalls->getArrayCopy());
$this->assertEquals(['a', 'b'], array_keys($aCustomMap->stash->getArrayCopy()));
list($valueC, $valueB2) = DataLoader::await(self::$promiseAdapter->createAll([$identityLoader->load('c'), $identityLoader->load('b')]));
$this->assertEquals('c', $valueC);
$this->assertEquals('b', $valueB2);
$this->assertEquals([['a', 'b'], ['c']], $loadCalls->getArrayCopy());
$this->assertEquals(['a', 'b', 'c'], array_keys($aCustomMap->stash->getArrayCopy()));
// Supports clear
$identityLoader->clear('b');
$valueB3 = DataLoader::await($identityLoader->load('b'));
$this->assertEquals('b', $valueB3);
$this->assertEquals([['a', 'b'], ['c'], ['b']], $loadCalls->getArrayCopy());
$this->assertEquals(['a', 'c', 'b'], array_keys($aCustomMap->stash->getArrayCopy()));
// Supports clear all
$identityLoader->clearAll();
$this->assertEquals([], $aCustomMap->stash->getArrayCopy());
}
/**
* @group it-is-resilient-to-job-queue-ordering
*/
public function testBatchesLoadsOccurringWithinPromises()
{
/**
* @var DataLoader $identityLoader
* @var \ArrayObject $loadCalls
*/
list($identityLoader, $loadCalls) = self::idLoader();
DataLoader::await(
self::$promiseAdapter->createAll([
$identityLoader->load('A'),
self::$promiseAdapter->createFulfilled()
->then(function () {
return self::$promiseAdapter->createFulfilled();
})
->then(function () use ($identityLoader) {
$identityLoader->load('B');
self::$promiseAdapter->createFulfilled()
->then(function () use ($identityLoader) {
return self::$promiseAdapter->createFulfilled();
})
->then(function () use ($identityLoader) {
$identityLoader->load('C');
self::$promiseAdapter->createFulfilled()
->then(function () {
return self::$promiseAdapter->createFulfilled();
})
->then(function () use ($identityLoader) {
$identityLoader->load('D');
});
});
})
])
);
$this->assertEquals([['A', 'B', 'C', 'D']], $loadCalls->getArrayCopy());
}
/**
* @group it-is-resilient-to-job-queue-ordering
*/
public function testCanCallALoaderFromALoader()
{
/**
* @var DataLoader $deepLoader
* @var \ArrayObject $deepLoadCalls
*/
list($deepLoader, $deepLoadCalls) = self::idLoader();
$aLoadCalls = null;
/**
* @var DataLoader $aLoader
* @var \ArrayObject $aLoadCalls
*/
list($aLoader, $aLoadCalls) = self::idLoader(null, function ($keys) use (&$deepLoader) {
return $deepLoader->load($keys);
});
$bLoadCalls = null;
/**
* @var DataLoader $bLoader
* @var \ArrayObject $bLoadCalls
*/
list($bLoader, $bLoadCalls) = self::idLoader(null, function ($keys) use (&$deepLoader) {
return $deepLoader->load($keys);
});
list($a1, $b1, $a2, $b2) = DataLoader::await(self::$promiseAdapter->createAll([
$aLoader->load('A1'),
$bLoader->load('B1'),
$aLoader->load('A2'),
$bLoader->load('B2')
]));
$this->assertEquals('A1', $a1);
$this->assertEquals('B1', $b1);
$this->assertEquals('A2', $a2);
$this->assertEquals('B2', $b2);
$this->assertEquals([['A1', 'A2']], $aLoadCalls->getArrayCopy());
$this->assertEquals([['B1', 'B2']], $bLoadCalls->getArrayCopy());
$this->assertEquals([[['A1', 'A2'], ['B1', 'B2']]], $deepLoadCalls->getArrayCopy());
}
public function testOnDestructionAllPromiseInQueueShouldBeCancelled()
{
/**
* @var DataLoader $loader
*/
list($loader) = self::idLoader();
/** @var \Exception|null $exception */
$exception = null;
$loader->load('A1')->then(null, function ($reason) use (&$exception) {
$exception = $reason;
});
$loader->__destruct();
unset($loader);
$this->assertInstanceOf(\RuntimeException::class, $exception);
$this->assertEquals($exception->getMessage(), 'DataLoader destroyed before promise complete.');
}
public function testCallingAwaitFunctionWhenNoInstanceOfDataLoaderShouldNotThrowError()
{
DataLoader::await();
}
public function testAwaitAlsoAwaitsNewlyCreatedDataloaders()
{
$firstComplete = false;
$secondComplete = false;
$first = new DataLoader(function ($values) use (&$firstComplete, &$secondComplete) {
$second = new DataLoader(function ($values) use (&$secondComplete) {
$secondComplete = true;
return self::$promiseAdapter->createAll(['B']);
}, self::$promiseAdapter);
$second->load('B');
$firstComplete = true;
return self::$promiseAdapter->createAll(['A']);
}, self::$promiseAdapter);
// This tests that an idling dataloader do not cause the others to be skipped.
$third = new DataLoader(function () {
// noop
}, self::$promiseAdapter);
DataLoader::await($first->load('A'));
$this->assertTrue($firstComplete);
$this->assertTrue($secondComplete);
}
/**
* @runInSeparateProcess
*/
public function testAwaitShouldReturnTheValueOfFulfilledPromiseWithoutNeedingActiveDataLoaderInstance()
{
$expectedValue = 'Ok!';
$value = DataLoader::await(self::$promiseAdapter->createFulfilled($expectedValue));
$this->assertEquals($expectedValue, $value);
}
/**
* @runInSeparateProcess
*/
public function testAwaitShouldReturnTheRejectReasonOfRejectedPromiseWithoutNeedingActiveDataLoaderInstance()
{
$expectedException = new \Exception('Rejected!');
$exception = DataLoader::await(self::$promiseAdapter->createRejected($expectedException), false);
$this->assertEquals($expectedException, $exception);
}
/**
* @expectedException \Exception
* @expectedExceptionMessage Rejected!
* @runInSeparateProcess
*/
public function testAwaitShouldThrowTheRejectReasonOfRejectedPromiseWithoutNeedingActiveDataLoaderInstance()
{
DataLoader::await(self::$promiseAdapter->createRejected(new \Exception('Rejected!')));
}
public function cacheKey($key)
{
$cacheKey = [];
$key = (array)$key;
ksort($key);
foreach ($key as $k => $value) {
$cacheKey[] = $k.':'.$value;
}
return implode(',', $cacheKey);
}
private static function errorLoader()
{
return self::idLoader(null, function ($keys) {
return self::$promiseAdapter->createFulfilled(
array_map(function ($key) {
return new \Exception("Error: $key");
}, $keys)
);
});
}
private static function eventLoader()
{
return self::idLoader(null, function ($keys) {
$loadCalls[] = $keys;
return self::$promiseAdapter->createFulfilled(
array_map(function ($key) {
return $key % 2 === 0 ? $key : new \Exception("Odd: $key");
}, $keys)
);
});
}
private static function idLoader(Option $options = null, callable $batchLoadFnCallBack = null)
{
$loadCalls = new \ArrayObject();
if (null === $batchLoadFnCallBack) {
$batchLoadFnCallBack = function ($keys) {
return self::$promiseAdapter->createFulfilled($keys);
};
}
$identityLoader = new DataLoader(function ($keys) use (&$loadCalls, $batchLoadFnCallBack) {
$loadCalls[] = $keys;
return $batchLoadFnCallBack($keys);
}, self::$promiseAdapter, $options);
return [$identityLoader, $loadCalls];
}
private function assertInstanceOfPromise($object)
{
$this->assertTrue(self::$promiseAdapter->isPromise($object, true));
}
}