Skip to content

Commit 9ce215c

Browse files
committed
Added tests for custom doctrine functions
1 parent 753ecee commit 9ce215c

File tree

6 files changed

+382
-0
lines changed

6 files changed

+382
-0
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
/*
3+
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
4+
*
5+
* Copyright (C) 2019 - 2026 Jan Böhmer (https://github.com/jbtronics)
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU Affero General Public License as published
9+
* by the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU Affero General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Affero General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
declare(strict_types=1);
22+
23+
namespace App\Tests\Doctrine\Functions;
24+
25+
use Doctrine\DBAL\Connection;
26+
use Doctrine\DBAL\Platforms\AbstractPlatform;
27+
use Doctrine\ORM\Query\AST\Node;
28+
use Doctrine\ORM\Query\SqlWalker;
29+
use PHPUnit\Framework\TestCase;
30+
31+
abstract class AbstractDoctrineFunctionTestCase extends TestCase
32+
{
33+
protected function createSqlWalker(AbstractPlatform $platform, string $serverVersion = '11.0.0-MariaDB'): SqlWalker
34+
{
35+
$connection = $this->createMock(Connection::class);
36+
$connection->method('getDatabasePlatform')->willReturn($platform);
37+
$connection->method('getServerVersion')->willReturn($serverVersion);
38+
39+
$sqlWalker = $this->getMockBuilder(SqlWalker::class)
40+
->disableOriginalConstructor()
41+
->onlyMethods(['getConnection'])
42+
->getMock();
43+
44+
$sqlWalker->method('getConnection')->willReturn($connection);
45+
46+
return $sqlWalker;
47+
}
48+
49+
protected function createNode(string $sql): Node
50+
{
51+
$node = $this->createMock(Node::class);
52+
$node->method('dispatch')->willReturn($sql);
53+
54+
return $node;
55+
}
56+
57+
protected function setObjectProperty(object $object, string $property, mixed $value): void
58+
{
59+
$reflection = new \ReflectionProperty($object, $property);
60+
$reflection->setValue($object, $value);
61+
}
62+
63+
protected function setStaticProperty(string $class, string $property, mixed $value): void
64+
{
65+
$reflection = new \ReflectionProperty($class, $property);
66+
$reflection->setValue(null, $value);
67+
}
68+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
/*
3+
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
4+
*
5+
* Copyright (C) 2019 - 2026 Jan Böhmer (https://github.com/jbtronics)
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU Affero General Public License as published
9+
* by the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU Affero General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Affero General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
declare(strict_types=1);
22+
23+
24+
namespace App\Tests\Doctrine\Functions;
25+
26+
use App\Doctrine\Functions\ArrayPosition;
27+
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
28+
29+
final class ArrayPositionTest extends AbstractDoctrineFunctionTestCase
30+
{
31+
public function testArrayPositionBuildsSql(): void
32+
{
33+
$function = new ArrayPosition('ARRAY_POSITION');
34+
$this->setObjectProperty($function, 'array', $this->createNode(':ids'));
35+
$this->setObjectProperty($function, 'field', $this->createNode('p.id'));
36+
37+
$sql = $function->getSql($this->createSqlWalker(new PostgreSQLPlatform()));
38+
39+
$this->assertSame('ARRAY_POSITION(:ids, p.id)', $sql);
40+
}
41+
}
42+
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
/*
3+
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
4+
*
5+
* Copyright (C) 2019 - 2026 Jan Böhmer (https://github.com/jbtronics)
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU Affero General Public License as published
9+
* by the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU Affero General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Affero General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
declare(strict_types=1);
22+
23+
namespace App\Tests\Doctrine\Functions;
24+
25+
use App\Doctrine\Functions\Field2;
26+
use Doctrine\DBAL\Platforms\MySQLPlatform;
27+
28+
final class Field2Test extends AbstractDoctrineFunctionTestCase
29+
{
30+
public function testField2BuildsSql(): void
31+
{
32+
$function = new Field2('FIELD2');
33+
$this->setObjectProperty($function, 'field', $this->createNode('p.id'));
34+
$this->setObjectProperty($function, 'values', [
35+
$this->createNode('1'),
36+
$this->createNode('2'),
37+
$this->createNode('3'),
38+
]);
39+
40+
$sql = $function->getSql($this->createSqlWalker(new MySQLPlatform()));
41+
42+
$this->assertSame('FIELD2(p.id, 1, 2, 3)', $sql);
43+
}
44+
}
45+
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
/*
3+
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
4+
*
5+
* Copyright (C) 2019 - 2026 Jan Böhmer (https://github.com/jbtronics)
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU Affero General Public License as published
9+
* by the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU Affero General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Affero General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
declare(strict_types=1);
22+
23+
namespace App\Tests\Doctrine\Functions;
24+
25+
use App\Doctrine\Functions\ILike;
26+
use Doctrine\DBAL\Platforms\AbstractPlatform;
27+
use Doctrine\DBAL\Platforms\MySQLPlatform;
28+
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
29+
use Doctrine\DBAL\Platforms\SQLitePlatform;
30+
use Doctrine\DBAL\Platforms\SQLServerPlatform;
31+
use PHPUnit\Framework\Attributes\DataProvider;
32+
33+
final class ILikeTest extends AbstractDoctrineFunctionTestCase
34+
{
35+
public static function iLikePlatformProvider(): \Generator
36+
{
37+
yield 'mysql' => [new MySQLPlatform(), '(part_name LIKE :pattern)'];
38+
yield 'postgres' => [new PostgreSQLPlatform(), '(part_name ILIKE :pattern)'];
39+
yield 'sqlite' => [new SQLitePlatform(), "(part_name LIKE :pattern ESCAPE '\\')"];
40+
}
41+
42+
#[DataProvider('iLikePlatformProvider')]
43+
public function testILikeUsesExpectedOperator(AbstractPlatform $platform, string $expectedSql): void
44+
{
45+
$function = new ILike('ILIKE');
46+
$function->value = $this->createNode('part_name');
47+
$function->expr = $this->createNode(':pattern');
48+
49+
$sql = $function->getSql($this->createSqlWalker($platform));
50+
51+
$this->assertSame($expectedSql, $sql);
52+
}
53+
54+
public function testILikeThrowsOnUnsupportedPlatform(): void
55+
{
56+
$function = new ILike('ILIKE');
57+
$function->value = $this->createNode('part_name');
58+
$function->expr = $this->createNode(':pattern');
59+
60+
$this->expectException(\RuntimeException::class);
61+
$this->expectExceptionMessage('does not support case insensitive like expressions');
62+
63+
$function->getSql($this->createSqlWalker(new SQLServerPlatform()));
64+
}
65+
}
66+
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
/*
3+
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
4+
*
5+
* Copyright (C) 2019 - 2026 Jan Böhmer (https://github.com/jbtronics)
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU Affero General Public License as published
9+
* by the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU Affero General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Affero General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
declare(strict_types=1);
22+
23+
namespace App\Tests\Doctrine\Functions;
24+
25+
use App\Doctrine\Functions\Natsort;
26+
use Doctrine\DBAL\Platforms\MariaDBPlatform;
27+
use Doctrine\DBAL\Platforms\MySQLPlatform;
28+
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
29+
use Doctrine\DBAL\Platforms\SQLitePlatform;
30+
31+
final class NatsortTest extends AbstractDoctrineFunctionTestCase
32+
{
33+
protected function setUp(): void
34+
{
35+
parent::setUp();
36+
37+
Natsort::allowSlowNaturalSort(false);
38+
$this->setStaticProperty(Natsort::class, 'supportsNaturalSort', null);
39+
}
40+
41+
public function testNatsortUsesPostgresCollation(): void
42+
{
43+
$function = new Natsort('NATSORT');
44+
$this->setObjectProperty($function, 'field', $this->createNode('part_name'));
45+
46+
$sql = $function->getSql($this->createSqlWalker(new PostgreSQLPlatform()));
47+
48+
$this->assertSame('part_name COLLATE numeric', $sql);
49+
}
50+
51+
public function testNatsortUsesMariaDbNativeFunctionOnSupportedVersion(): void
52+
{
53+
$function = new Natsort('NATSORT');
54+
$this->setObjectProperty($function, 'field', $this->createNode('part_name'));
55+
56+
$sql = $function->getSql($this->createSqlWalker(new MariaDBPlatform(), '10.11.2-MariaDB'));
57+
58+
$this->assertSame('NATURAL_SORT_KEY(part_name)', $sql);
59+
}
60+
61+
public function testNatsortFallsBackWithoutSlowSort(): void
62+
{
63+
$function = new Natsort('NATSORT');
64+
$this->setObjectProperty($function, 'field', $this->createNode('part_name'));
65+
66+
$sql = $function->getSql($this->createSqlWalker(new MariaDBPlatform(), '10.6.10-MariaDB'));
67+
68+
$this->assertSame('part_name', $sql);
69+
}
70+
71+
public function testNatsortUsesSlowSortFunctionOnMySqlWhenEnabled(): void
72+
{
73+
Natsort::allowSlowNaturalSort();
74+
75+
$function = new Natsort('NATSORT');
76+
$this->setObjectProperty($function, 'field', $this->createNode('part_name'));
77+
78+
$sql = $function->getSql($this->createSqlWalker(new MySQLPlatform()));
79+
80+
$this->assertSame('NatSortKey(part_name, 0)', $sql);
81+
}
82+
83+
public function testNatsortUsesSlowSortCollationOnSqliteWhenEnabled(): void
84+
{
85+
Natsort::allowSlowNaturalSort();
86+
87+
$function = new Natsort('NATSORT');
88+
$this->setObjectProperty($function, 'field', $this->createNode('part_name'));
89+
90+
$sql = $function->getSql($this->createSqlWalker(new SQLitePlatform()));
91+
92+
$this->assertSame('part_name COLLATE NATURAL_CMP', $sql);
93+
}
94+
}
95+
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
/*
3+
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
4+
*
5+
* Copyright (C) 2019 - 2026 Jan Böhmer (https://github.com/jbtronics)
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU Affero General Public License as published
9+
* by the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU Affero General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Affero General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
declare(strict_types=1);
22+
23+
namespace App\Tests\Doctrine\Functions;
24+
25+
use App\Doctrine\Functions\Regexp;
26+
use Doctrine\DBAL\Platforms\AbstractPlatform;
27+
use Doctrine\DBAL\Platforms\MySQLPlatform;
28+
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
29+
use Doctrine\DBAL\Platforms\SQLitePlatform;
30+
use Doctrine\DBAL\Platforms\SQLServerPlatform;
31+
use PHPUnit\Framework\Attributes\DataProvider;
32+
33+
final class RegexpTest extends AbstractDoctrineFunctionTestCase
34+
{
35+
public static function regexpPlatformProvider(): \Generator
36+
{
37+
yield 'mysql' => [new MySQLPlatform(), '(part_name REGEXP :regex)'];
38+
yield 'sqlite' => [new SQLitePlatform(), '(part_name REGEXP :regex)'];
39+
yield 'postgres' => [new PostgreSQLPlatform(), '(part_name ~* :regex)'];
40+
}
41+
42+
#[DataProvider('regexpPlatformProvider')]
43+
public function testRegexpUsesExpectedOperator(AbstractPlatform $platform, string $expectedSql): void
44+
{
45+
$function = new Regexp('REGEXP');
46+
$this->setObjectProperty($function, 'value', $this->createNode('part_name'));
47+
$this->setObjectProperty($function, 'regexp', $this->createNode(':regex'));
48+
49+
$sql = $function->getSql($this->createSqlWalker($platform));
50+
51+
$this->assertSame($expectedSql, $sql);
52+
}
53+
54+
public function testRegexpThrowsOnUnsupportedPlatform(): void
55+
{
56+
$function = new Regexp('REGEXP');
57+
$this->setObjectProperty($function, 'value', $this->createNode('part_name'));
58+
$this->setObjectProperty($function, 'regexp', $this->createNode(':regex'));
59+
60+
$this->expectException(\RuntimeException::class);
61+
$this->expectExceptionMessage('does not support regular expressions');
62+
63+
$function->getSql($this->createSqlWalker(new SQLServerPlatform()));
64+
}
65+
}
66+

0 commit comments

Comments
 (0)