Commit e4a2baa8 authored by François Agneray's avatar François Agneray
Browse files

Tests package Search

parent 56208ab2
Pipeline #5138 passed with stages
in 2 minutes and 58 seconds
......@@ -13,7 +13,6 @@ declare(strict_types=1);
namespace App\Search\Query;
use Doctrine\DBAL\Query\QueryBuilder as DoctrineQueryBuilder;
use Doctrine\DBAL\Driver\ResultStatement;
use App\Search\Query\IQueryPart;
use App\Entity\Dataset;
use App\Entity\Attribute;
......
......@@ -32,64 +32,63 @@ class ConeSearch extends AbstractQueryPart
*/
public function __invoke(AnisQueryBuilder $anisQueryBuilder, Dataset $dataset, array $queryParams): void
{
if (!array_key_exists('cs', $queryParams)) {
return;
}
if (array_key_exists('cs', $queryParams)) {
$queryBuilder = $anisQueryBuilder->getDoctrineQueryBuilder();
$params = explode(':', $queryParams['cs']);
if (count($params) !== 3) {
throw SearchQueryException::badNumberOfParamsForConeSearch();
}
$queryBuilder = $anisQueryBuilder->getDoctrineQueryBuilder();
$params = explode(':', $queryParams['cs']);
if (count($params) < 3) {
throw SearchQueryException::badNumberOfParamsForConeSearch();
}
list($ra, $dec, $radius) = $params;
$ra = floatval($ra);
$dec = floatval($dec);
$radius = floatval($radius);
$coneSearchConfig = $dataset->getConfig()['cone_search'];
list($ra, $dec, $radius) = $params;
$ra = floatval($ra);
$dec = floatval($dec);
$radius = floatval($radius);
$coneSearchConfig = $dataset->getConfig()['cone_search'];
if ($coneSearchConfig['enabled'] !== true) {
throw SearchQueryException::coneSearchUnavailable();
}
if ($coneSearchConfig['enabled'] !== true) {
throw SearchQueryException::coneSearchUnavailable();
}
$attributeRa = $this->getAttribute($dataset, $coneSearchConfig['column_ra']);
$attributeDec = $this->getAttribute($dataset, $coneSearchConfig['column_dec']);
$columnRa = $dataset->getTableRef() . '.' . $attributeRa->getName();
$columnDec = $dataset->getTableRef() . '.' . $attributeDec->getName();
$attributeRa = $this->getAttribute($dataset, $coneSearchConfig['column_ra']);
$attributeDec = $this->getAttribute($dataset, $coneSearchConfig['column_dec']);
$columnRa = $dataset->getTableRef() . '.' . $attributeRa->getName();
$columnDec = $dataset->getTableRef() . '.' . $attributeDec->getName();
$cdcl2 = pow(cos($dec * (M_PI * 2) / 360), 2);
if ($radius == 0) {
$radius = 1 / 1000000;
}
$radius2 = pow($radius, 2);
$cdcl2 = pow(cos($dec * (M_PI * 2) / 360), 2);
if ($radius == 0) {
$radius = 1 / 1000000;
}
$radius2 = pow($radius, 2);
$raddeg = $radius / 3600;
$decmin = $dec - $raddeg;
$decmax = $dec + $raddeg;
if ($decmin < -90 || $decmax > 90) {
$ramin = 0;
$ramax = 360;
} else {
$ra_corrected_radius = $raddeg / cos(deg2rad(abs($dec) + $raddeg));
$ramin = $ra - $ra_corrected_radius;
$ramax = $ra + $ra_corrected_radius;
}
$raddeg = $radius / 3600;
$decmin = $dec - $raddeg;
$decmax = $dec + $raddeg;
if ($decmin < -90 || $decmax > 90) {
$ramin = 0;
$ramax = 360;
} else {
$ra_corrected_radius = $raddeg / cos(deg2rad(abs($dec) + $raddeg));
$ramin = $ra - $ra_corrected_radius;
$ramax = $ra + $ra_corrected_radius;
$coneSearchValue = '(' . $cdcl2;
$coneSearchValue .= ' * (' . $ra . ' - ' . $columnRa . ') * (' . $ra . ' - ' . $columnRa . '))';
$coneSearchValue .= ' + ((' . $dec . ' - ' . $columnDec . ') * (' . $dec . ' - ' . $columnDec . '))';
$coneSearchCriterion = $queryBuilder->expr()->lte($coneSearchValue, $radius2);
$raCriterion = (new CompositeExpression(CompositeExpression::TYPE_AND, [
$queryBuilder->expr()->gte($columnRa, $ramin),
$queryBuilder->expr()->lte($columnRa, $ramax)
]));
$decCriterion = (new CompositeExpression(CompositeExpression::TYPE_AND, [
$queryBuilder->expr()->gte($columnDec, $decmin),
$queryBuilder->expr()->lte($columnDec, $decmax)
]));
$queryBuilder->where(new CompositeExpression(CompositeExpression::TYPE_AND, [
$coneSearchCriterion,
$raCriterion,
$decCriterion
]));
}
$coneSearchValue = '(' . $cdcl2 . ' * (' . $ra . ' - ' . $columnRa . ') * (' . $ra . ' - ' . $columnRa . '))';
$coneSearchValue .= ' + ((' . $dec . ' - ' . $columnDec . ') * (' . $dec . ' - ' . $columnDec . '))';
$coneSearchCriterion = $queryBuilder->expr()->lte($coneSearchValue, $radius2);
$raCriterion = (new CompositeExpression(CompositeExpression::TYPE_AND, [
$queryBuilder->expr()->gte($columnRa, $ramin),
$queryBuilder->expr()->lte($columnRa, $ramax)
]));
$decCriterion = (new CompositeExpression(CompositeExpression::TYPE_AND, [
$queryBuilder->expr()->gte($columnDec, $decmin),
$queryBuilder->expr()->lte($columnDec, $decmax)
]));
$queryBuilder->where(new CompositeExpression(CompositeExpression::TYPE_AND, [
$coneSearchCriterion,
$raCriterion,
$decCriterion
]));
}
}
......@@ -31,18 +31,16 @@ class Limit extends AbstractQueryPart
*/
public function __invoke(AnisQueryBuilder $anisQueryBuilder, Dataset $dataset, array $queryParams): void
{
if (!array_key_exists('p', $queryParams)) {
return;
if (array_key_exists('p', $queryParams)) {
$p = explode(':', $queryParams['p']);
if (count($p) != 2) {
throw SearchQueryException::badNumberOfParamsForLimit();
}
$limit = $p[0];
$offset = ($p[1] - 1) * $limit;
$anisQueryBuilder->getDoctrineQueryBuilder()
->setFirstResult($offset)
->setMaxResults($limit);
}
$p = explode(':', $queryParams['p']);
if (count($p) != 2) {
throw SearchQueryException::badNumberOfParamsForLimit();
}
$limit = $p[0];
$offset = ($p[1] - 1) * $limit;
$anisQueryBuilder->getDoctrineQueryBuilder()
->setFirstResult($offset)
->setMaxResults($limit);
}
}
......@@ -74,11 +74,6 @@ class OperatorException extends SearchException
return new self("You passed a string value '" . $value . "' or the criterion value required a numeric value");
}
public static function operatorJsonNotSupported()
{
return new self("Operator json is not supported by the database platform used");
}
public static function operatorJsonNeedColumnTypeJson()
{
return new self("Operator js need a json attribute type");
......
......@@ -31,28 +31,26 @@ class Order extends AbstractQueryPart
*/
public function __invoke(AnisQueryBuilder $anisQueryBuilder, Dataset $dataset, array $queryParams): void
{
if (!array_key_exists('o', $queryParams)) {
return;
}
$orders = explode(';', $queryParams['o']);
foreach ($orders as $order) {
$o = explode(':', $order);
if (count($o) != 2) {
throw SearchQueryException::badNumberOfParamsForOrder();
}
$attribute = $this->getAttribute($dataset, (int) $o[0]);
if ($o[1] === 'a') {
$aord = 'ASC';
} elseif ($o[1] === 'd') {
$aord = 'DESC';
} else {
throw SearchQueryException::typeOfOrderDoesNotExist($o[1]);
if (array_key_exists('o', $queryParams)) {
$orders = explode(';', $queryParams['o']);
foreach ($orders as $order) {
$o = explode(':', $order);
if (count($o) != 2) {
throw SearchQueryException::badNumberOfParamsForOrder();
}
if ($o[1] === 'a') {
$aord = 'ASC';
} elseif ($o[1] === 'd') {
$aord = 'DESC';
} else {
throw SearchQueryException::typeOfOrderDoesNotExist($o[1]);
}
$attribute = $this->getAttribute($dataset, (int) $o[0]);
$anisQueryBuilder->getDoctrineQueryBuilder()->orderBy(
$attribute->getTableName() . '.' . $attribute->getName(),
$aord
);
}
$anisQueryBuilder->getDoctrineQueryBuilder()->orderBy(
$attribute->getTableName() . '.' . $attribute->getName(),
$aord
);
}
}
}
......@@ -50,32 +50,30 @@ class Where extends AbstractQueryPart
*/
public function __invoke(AnisQueryBuilder $anisQueryBuilder, Dataset $dataset, array $queryParams): void
{
if (!array_key_exists('c', $queryParams)) {
return;
}
$queryBuilder = $anisQueryBuilder->getDoctrineQueryBuilder();
$criteria = explode(';', $queryParams['c']);
$expressions = array();
foreach ($criteria as $criterion) {
$params = $params = explode('::', $criterion);
$attribute = $this->getAttribute($dataset, (int) $params[0]);
$column = $attribute->getTableName() . '.' . $attribute->getName();
$columnType = $attribute->getType();
if (array_key_exists(2, $params)) {
$values = explode('|', $params[2]);
} else {
$values = array();
if (array_key_exists('c', $queryParams)) {
$queryBuilder = $anisQueryBuilder->getDoctrineQueryBuilder();
$criteria = explode(';', $queryParams['c']);
$expressions = array();
foreach ($criteria as $criterion) {
$params = $params = explode('::', $criterion);
$attribute = $this->getAttribute($dataset, (int) $params[0]);
$column = $attribute->getTableName() . '.' . $attribute->getName();
$columnType = $attribute->getType();
if (array_key_exists(2, $params)) {
$values = explode('|', $params[2]);
} else {
$values = array();
}
$operator = $this->operatorFactory->create(
$params[1],
$queryBuilder->expr(),
$column,
$columnType,
$values
);
$expressions[] = $operator->getExpression();
}
$operator = $this->operatorFactory->create(
$params[1],
$queryBuilder->expr(),
$column,
$columnType,
$values
);
$expressions[] = $operator->getExpression();
$queryBuilder->andWhere(new CompositeExpression(CompositeExpression::TYPE_AND, $expressions));
}
$queryBuilder->andWhere(new CompositeExpression(CompositeExpression::TYPE_AND, $expressions));
}
}
......@@ -34,7 +34,7 @@ class ResponseFactory implements IResponseFactory
$searchResponse = new JsonResponse();
break;
case 'csv':
$searchResponse = new TextResponse(',', 'test/csv');
$searchResponse = new TextResponse(',', 'text/csv');
break;
case 'ascii':
$searchResponse = new TextResponse(' ', 'text/plain');
......
......@@ -42,7 +42,7 @@ class VotableResponse implements IResponse
}
$payload .= $this->getVoFooter();
$response->getBody()->write($payload);
return $response->withHeader('content-type', 'text/xml');
return $response->withHeader('Content-Type', 'text/xml');
}
/**
......
<?php
/*
* This file is part of Anis Server.
*
* (c) Laboratoire d'Astrophysique de Marseille / CNRS
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace App\Tests\Action;
use PHPUnit\Framework\TestCase;
use Nyholm\Psr7\ServerRequest;
use Nyholm\Psr7\Response;
final class AdminFileExplorerActionTest extends TestCase
{
private $action;
protected function setUp(): void
{
$this->action = new \App\Action\AdminFileExplorerAction('/data');
}
public function testOptionsHttpMethod(): void
{
$request = $this->getRequest('OPTIONS');
$response = ($this->action)($request, new Response(), array());
$this->assertSame($response->getHeaderLine('Access-Control-Allow-Methods'), 'GET, OPTIONS');
}
private function getRequest(string $method): ServerRequest
{
return new ServerRequest($method, '/file-explorer', array(
'Content-Type' => 'application/json'
));
}
}
<?php
/*
* This file is part of Anis Server.
*
* (c) Laboratoire d'Astrophysique de Marseille / CNRS
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace App\Tests\Action;
use PHPUnit\Framework\TestCase;
use Nyholm\Psr7\ServerRequest;
use Nyholm\Psr7\Response;
use App\tests\EntityManagerBuilder;
final class DatasetFileExplorerActionTest extends TestCase
{
private $action;
private $entityManager;
protected function setUp(): void
{
$this->entityManager = EntityManagerBuilder::getInstance();
$this->action = new \App\Action\DatasetFileExplorerAction($this->entityManager, '/data', array());
}
public function testOptionsHttpMethod(): void
{
$request = $this->getRequest('OPTIONS');
$response = ($this->action)($request, new Response(), array());
$this->assertSame($response->getHeaderLine('Access-Control-Allow-Methods'), 'GET, OPTIONS');
}
protected function tearDown(): void
{
$this->entityManager->getConnection()->close();
}
private function getRequest(string $method): ServerRequest
{
return new ServerRequest($method, '/dataset-file-explorer/observations', array(
'Content-Type' => 'application/json'
));
}
}
<?php
/*
* This file is part of Anis Server.
*
* (c) Laboratoire d'Astrophysique de Marseille / CNRS
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace App\Tests\Search\Query\Operator;
use PHPUnit\Framework\TestCase;
use App\Search\DBALConnectionFactory;
use App\Entity\Database;
final class DBALConnectionFactoryTest extends TestCase
{
/**
* @var DBALConnectionFactory
*/
private $connectionFactory;
protected function setUp(): void
{
$this->connectionFactory = new DBALConnectionFactory();
}
public function testCreate(): void
{
$database = $this->createMock(Database::class);
$database->method('getDbName')
->willReturn('test');
$database->method('getLogin')
->willReturn('user');
$database->method('getPassword')
->willReturn('password');
$database->method('getHost')
->willReturn('db');
$database->method('getPort')
->willReturn(5432);
$database->method('getType')
->willReturn('pdo_sqlite');
$connection = $this->connectionFactory->create($database);
$this->assertInstanceOf('Doctrine\DBAL\Connection', $connection);
}
}
<?php
/*
* This file is part of Anis Server.
*
* (c) Laboratoire d'Astrophysique de Marseille / CNRS
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace App\Tests\Search\Query;
use PHPUnit\Framework\TestCase;
use Doctrine\DBAL\Query\QueryBuilder as DoctrineQueryBuilder;
use App\Search\Query\AnisQueryBuilder;
use App\Entity\Dataset;
use App\Entity\Attribute;
use App\Search\Query\Select;
use App\Search\Query\From;
final class AnisQueryBuilderTest extends TestCase
{
/**
* @var AnisQueryBuilder
*/
private $anisQueryBuilder;
protected function setUp(): void
{
$this->anisQueryBuilder = new AnisQueryBuilder();
}
public function testGetDoctrineQueryBuilder()
{
$doctrineQueryBuilder = $this->createMock(DoctrineQueryBuilder::class);
$this->anisQueryBuilder->setDoctrineQueryBuilder($doctrineQueryBuilder);
$this->assertSame($doctrineQueryBuilder, $this->anisQueryBuilder->getDoctrineQueryBuilder());
}
public function testGetDatasetSelected()
{
$datasetSelected = $this->createMock(Dataset::class);
$this->anisQueryBuilder->setDatasetSelected($datasetSelected);
$this->assertSame($datasetSelected, $this->anisQueryBuilder->getDatasetSelected());
}
public function testGetAttributesSelected()
{
$ra = $this->createMock(Attribute::class);
$dec = $this->createMock(Attribute::class);
$attributesSelected = array($ra, $dec);
$this->anisQueryBuilder->setAttributesSelected($attributesSelected);
$this->assertSame($attributesSelected, $this->anisQueryBuilder->getAttributesSelected());
}
public function testBuild()
{
$select = $this->createMock(Select::class);
$select->expects($this->once())->method('__invoke');
$from = $this->createMock(From::class);
$from->expects($this->once())->method('__invoke');
$this->anisQueryBuilder->setDatasetSelected($this->createMock(Dataset::class));
$this->anisQueryBuilder->addQueryPart($select);
$this->anisQueryBuilder->addQueryPart($from);
$this->anisQueryBuilder->build(array());
}
}
<?php
/*
* This file is part of Anis Server.
*
* (c) Laboratoire d'Astrophysique de Marseille / CNRS
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace App\Tests\Search\Query;
use PHPUnit\Framework\TestCase;
use App\Search\Query\ConeSearch;
use App\Search\Query\AnisQueryBuilder;
use App\Search\Query\SearchQueryException;
use Doctrine\DBAL\Query\QueryBuilder as DoctrineQueryBuilder;
use Doctrine\DBAL\Query\Expression\ExpressionBuilder;
use App\Entity\Dataset;
use App\Entity\Attribute;
final class ConeSearchTest extends TestCase
{
public function testConeSearch(): void
{
$id = $this->createMock(Attribute::class);
$id->method('getId')->willReturn(1);
$ra = $this->createMock(Attribute::class);
$ra->method('getId')->willReturn(2);
$dec = $this->createMock(Attribute::class);
$dec->method('getId')->willReturn(3);
$datasetSelected = $this->createMock(Dataset::class);
$datasetSelected->method('getAttributes')->willReturn(array($id, $ra, $dec));
$datasetSelected->method('getConfig')->willReturn(array('cone_search' => array(
'enabled' => true,
'column_ra' => 2,
'column_dec' => 3
)));
$doctrineQueryBuilder = $this->createMock(DoctrineQueryBuilder::class);
$expr = $this->createMock(ExpressionBuilder::class);
$doctrineQueryBuilder->method('expr')->willReturn($expr);
$doctrineQueryBuilder->expects($this->once())->method('where');
$anisQueryBuilder = $this->createMock(AnisQueryBuilder::class);
$anisQueryBuilder->method('getDoctrineQueryBuilder')->willReturn($doctrineQueryBuilder);
$queryParams = array('cs' => '102.5:0.0:100');
(new ConeSearch())($anisQueryBuilder, $datasetSelected, $queryParams);
}
public function testConeSearchException(): void
{
$this->expectException(SearchQueryException::class);
$anisQueryBuilder = $this->createMock(AnisQueryBuilder::class);
$datasetSelected = $this->createMock(Dataset::class);
$queryParams = array('cs' => '102.5:0.0:100:10');
(new ConeSearch())($anisQueryBuilder, $datasetSelected, $queryParams);
}
public function testConeSearchUnavailableException(): void
{
$this->expectException(SearchQueryException::class);
$anisQueryBuilder = $this->createMock(AnisQueryBuilder::class);
$datasetSelected = $this->createMock(Dataset::class);
$datasetSelected->method('getConfig')->willReturn(array('cone_search' => array(
'enabled' => false,
'column_ra' => 2,
'column_dec' => 3
)));
$queryParams = array('cs' => '102.5:0.0:100');
(new ConeSearch())($anisQueryBuilder, $datasetSelected, $queryParams);
}
public function testConeSearchParamsValues(): void
{
$id = $this->createMock(Attribute::class);
$id->method('getId')->willReturn(1);
$ra = $this->createMock(Attribute::class);
$ra->method('getId')->willReturn(2);