graphql-php/tests/Validator/QueryDepthTest.php
2018-10-05 10:47:57 +02:00

159 lines
4.1 KiB
PHP

<?php
declare(strict_types=1);
namespace GraphQL\Tests\Validator;
use GraphQL\Validator\Rules\QueryDepth;
use function sprintf;
use function str_replace;
class QueryDepthTest extends QuerySecurityTestCase
{
/**
* @param int $queryDepth
* @param int $maxQueryDepth
* @param string[][] $expectedErrors
*
* @dataProvider queryDataProvider
*/
public function testSimpleQueries($queryDepth, $maxQueryDepth = 7, $expectedErrors = []) : void
{
$this->assertDocumentValidator($this->buildRecursiveQuery($queryDepth), $maxQueryDepth, $expectedErrors);
}
private function buildRecursiveQuery($depth)
{
return sprintf('query MyQuery { human%s }', $this->buildRecursiveQueryPart($depth));
}
private function buildRecursiveQueryPart($depth)
{
$templates = [
'human' => ' { firstName%s } ',
'dog' => ' dogs { name%s } ',
];
$part = $templates['human'];
for ($i = 1; $i <= $depth; ++$i) {
$key = $i % 2 === 1 ? 'human' : 'dog';
$template = $templates[$key];
$part = sprintf($part, ($key === 'human' ? ' owner ' : '') . $template);
}
$part = str_replace('%s', '', $part);
return $part;
}
/**
* @param int $queryDepth
* @param int $maxQueryDepth
* @param string[][] $expectedErrors
*
* @dataProvider queryDataProvider
*/
public function testFragmentQueries($queryDepth, $maxQueryDepth = 7, $expectedErrors = []) : void
{
$this->assertDocumentValidator(
$this->buildRecursiveUsingFragmentQuery($queryDepth),
$maxQueryDepth,
$expectedErrors
);
}
private function buildRecursiveUsingFragmentQuery($depth)
{
return sprintf(
'query MyQuery { human { ...F1 } } fragment F1 on Human %s',
$this->buildRecursiveQueryPart($depth)
);
}
/**
* @param int $queryDepth
* @param int $maxQueryDepth
* @param string[][] $expectedErrors
*
* @dataProvider queryDataProvider
*/
public function testInlineFragmentQueries($queryDepth, $maxQueryDepth = 7, $expectedErrors = []) : void
{
$this->assertDocumentValidator(
$this->buildRecursiveUsingInlineFragmentQuery($queryDepth),
$maxQueryDepth,
$expectedErrors
);
}
private function buildRecursiveUsingInlineFragmentQuery($depth)
{
return sprintf(
'query MyQuery { human { ...on Human %s } }',
$this->buildRecursiveQueryPart($depth)
);
}
public function testComplexityIntrospectionQuery() : void
{
$this->assertIntrospectionQuery(11);
}
public function testIntrospectionTypeMetaFieldQuery() : void
{
$this->assertIntrospectionTypeMetaFieldQuery(1);
}
public function testTypeNameMetaFieldQuery() : void
{
$this->assertTypeNameMetaFieldQuery(1);
}
public function queryDataProvider()
{
return [
[1], // Valid because depth under default limit (7)
[2],
[3],
[4],
[5],
[6],
[7],
[8, 9], // Valid because depth under new limit (9)
[10, 0], // Valid because 0 depth disable limit
[
10,
8,
[$this->createFormattedError(8, 10)],
], // failed because depth over limit (8)
[
20,
15,
[$this->createFormattedError(15, 20)],
], // failed because depth over limit (15)
];
}
/**
* @param int $max
* @param int $count
*
* @return string
*/
protected function getErrorMessage($max, $count)
{
return QueryDepth::maxQueryDepthErrorMessage($max, $count);
}
/**
* @param int $maxDepth
*
* @return QueryDepth
*/
protected function getRule($maxDepth)
{
return new QueryDepth($maxDepth);
}
}