1
0
قرینه از https://github.com/matomo-org/matomo.git synced 2025-08-25 00:17:37 +00:00
Files
matomo/tests/PHPUnit/Unit/Segment/SegmentExpressionTest.php
Stefan Giehl d6d72d1fa7 [Coding Style] Enable rule PSR1.Methods.CamelCapsMethodName.NotCamelCaps (#22144)
* [Coding Style] Enable rule PSR1.Methods.CamelCapsMethodName.NotCamelCaps

* [Coding Style] Use camel case for method names in API plugin tests (#22145)

* [Coding Style] Use camel case for method names in Core* plugin tests (#22147)

* [Coding Style] Use camel case for method names in core Unit tests (#22149)

* [Coding Style] Use camel case for method names in Actions and BulkTracking plugin tests (#22146)

* [Coding Style] Use camel case for method names in CustomDimensions and CustomJSTracker plugin tests (#22148)

* [Coding Style] Use camel case for method names in core Integration tests (#22151)

* [Coding Style] Use camel case for method names in more core plugin tests (#22153)

* [Coding Style] Use camel case for method names in more core plugin tests (#22157)

* [Coding Style] Use camel case for method names in more core plugin tests

* Update plugins/Monolog/tests/Unit/Processor/ExceptionToTextProcessorTest.php

Co-authored-by: Michal Kleiner <michal@innocraft.com>

---------

Co-authored-by: Michal Kleiner <michal@innocraft.com>

* [Coding Style] Use camel case for method names in more core plugin tests (#22159)

* [Coding Style] Use camel case for method names in remaining tests (#22160)

* [Coding Style] Use camel case for method names in remaining tests

* rename expected test files

---------

Co-authored-by: Michal Kleiner <michal@innocraft.com>
2024-04-25 20:57:55 +02:00

211 خطوط
7.5 KiB
PHP

<?php
/**
* Matomo - free/libre analytics platform
*
* @link https://matomo.org
* @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
namespace Piwik\Tests\Unit;
use Piwik\Segment\SegmentExpression;
/**
* @group SegmentExpressionTest
* @group Segment
*/
class SegmentExpressionTest extends \PHPUnit\Framework\TestCase
{
/**
* Dataprovider for testSegmentSqlSimpleNoOperation
* @return array
*/
public function getSimpleSegmentExpressions()
{
return [
// classic expressions
['A', "A"],
['A,B', "( A OR B)"],
['A;B', "A AND B"],
['A;B;C', "A AND B AND C"],
['A,B;C,D;E,F,G', "( A OR B) AND ( C OR D) AND ( E OR F OR G)"],
// unescape the backslash
['A\,B\,C,D', "( A,B,C OR D)"],
['\,A', ',A'],
// unescape only when it was escaping a known delimiter
['\\\A', '\\\A'],
// unescape at the end
['\,\;\A\B,\,C,D\;E\,', '( ,;\A\B OR ,C OR D;E,)'],
// only replace when a following expression is detected
['A,', 'A,'],
['A;', 'A;'],
['A;B;', 'A AND B;'],
['A,B,', '( A OR B,)'],
];
}
/**
* @dataProvider getSimpleSegmentExpressions
* @group Core
*/
public function testSegmentSqlSimpleNoOperation($expression, $expectedSql)
{
$segment = new SegmentExpression($expression);
$expected = ['where' => $expectedSql, 'bind' => []];
$processed = $segment->getSql();
$this->assertEquals($expected, $processed);
}
/**
* Dataprovider for testSegmentSqlWithOperations
* @return array
*/
public function getOperationSegmentExpressions()
{
// Filter expression => SQL string + Bind values
return [
['A==B%', ['where' => "A = ?", 'bind' => ['B%']]],
['ABCDEF====B===', ['where' => "ABCDEF = ?", 'bind' => ['==B===']]],
['A===B;CDEF!=C!=', ['where' => "A = ? AND ( CDEF IS NULL OR CDEF <> ? )", 'bind' => ['=B', 'C!=']]],
['A==B,C==D', ['where' => "( A = ? OR C = ?)", 'bind' => ['B', 'D']]],
['A!=B;C==D', ['where' => "( A IS NULL OR A <> ? ) AND C = ?", 'bind' => ['B', 'D']]],
['A!=B;C==D,E!=Hello World!=', ['where' => "( A IS NULL OR A <> ? ) AND ( C = ? OR ( E IS NULL OR E <> ? ))", 'bind' => ['B', 'D', 'Hello World!=']]],
['A=@B;C=$D', ['where' => "A LIKE ? AND C LIKE ?", 'bind' => ['%B%', '%D']]],
['A>B', ['where' => "A > ?", 'bind' => ['B']]],
['A<B', ['where' => "A < ?", 'bind' => ['B']]],
['A<=B', ['where' => "A <= ?", 'bind' => ['B']]],
['A>=B', ['where' => "A >= ?", 'bind' => ['B']]],
['ABCDEF>=>=>=B===', ['where' => "ABCDEF >= ?", 'bind' => ['>=>=B===']]],
['A>=<=B;CDEF>G;H>=I;J<K;L<=M', ['where' => "A >= ? AND CDEF > ? AND H >= ? AND J < ? AND L <= ?", 'bind' => ['<=B', 'G', 'I', 'K', 'M']]],
['A>=B;C>=D,E<w_ow great!', ['where' => "A >= ? AND ( C >= ? OR E < ?)", 'bind' => ['B', 'D', 'w_ow great!']]],
['A=@B_', ['where' => "A LIKE ?", 'bind' => ['%B\_%']]],
['A!@B%', ['where' => "( A IS NULL OR A NOT LIKE ? )", 'bind' => ['%B\%%']]],
['A=$B%', ['where' => "A LIKE ?", 'bind' => ['%B\%']]],
['A=^B%', ['where' => "A LIKE ?", 'bind' => ['B\%%']]],
['log_visit.A==3', ['where' => 'log_visit.A = ?', 'bind' => ['3']], [], ['log_visit']],
['log_visit.A==3;log_conversion.B>4', ['where' => 'log_visit.A = ? AND log_conversion.B > ?', 'bind' => ['3', '4']], [], ['log_visit', 'log_conversion']],
['(UNIX_TIMESTAMP(log_visit.A)-log_visit.B)==3', ['where' => '(UNIX_TIMESTAMP(log_visit.A)-log_visit.B) = ?', 'bind' => ['3']], ['log_conversion'], ['log_conversion', 'log_visit']],
['(UNIX_TIMESTAMP(`log_visit`.A)-log_visit.`B`)==3', ['where' => '(UNIX_TIMESTAMP(`log_visit`.A)-log_visit.`B`) = ?', 'bind' => ['3']], ['log_conversion'], ['log_conversion', 'log_visit']],
['(UNIX_TIMESTAMP(`log_visit.A`)-`log_visit`.`B`)==3', ['where' => '(UNIX_TIMESTAMP(`log_visit.A`)-`log_visit`.`B`) = ?', 'bind' => ['3']], ['log_conversion'], ['log_conversion', 'log_visit']],
];
}
/**
* @dataProvider getOperationSegmentExpressions
* @group Core
*/
public function testSegmentSqlWithOperations($expression, $expectedSql, $initialFrom = [], $expectedTables = [])
{
$segment = new SegmentExpression($expression);
$segment->parseSubExpressions();
$segment->parseSubExpressionsIntoSqlExpressions($initialFrom);
$processed = $segment->getSql();
$this->assertEquals($expectedSql, $processed);
$this->assertEquals($expectedTables, $initialFrom);
}
/**
* Dataprovider for testBogusFiltersExpectExceptionThrown
* @return array
*/
public function getBogusFilters()
{
return [
['A=B'],
['C!D'],
[''],
[' '],
[',;,'],
[','],
[',,'],
['!='],
];
}
/**
* @dataProvider getBogusFilters
* @group Core
*/
public function testBogusFiltersExpectExceptionThrown($bogus)
{
$this->expectException(\Exception::class);
$segment = new SegmentExpression($bogus);
$segment->parseSubExpressions();
$segment->getSql();
}
/**
* @dataProvider getTestDataForParseColumnsFromSqlExpr
*/
public function testParseColumnsFromSqlExpr($field, $expected)
{
$actual = SegmentExpression::parseColumnsFromSqlExpr($field);
$this->assertEquals($expected, $actual);
}
public function getTestDataForParseColumnsFromSqlExpr()
{
return [
[
'log_visit.column',
['log_visit.column'],
],
[
'log_visitcolumn',
[],
],
[
'`log_visit.column`',
['log_visit.column'],
],
[
'`log_visit`.column',
['log_visit.column'],
],
[
'`log_visit`.`column`',
['log_visit.column'],
],
[
'log_visit.`column`',
['log_visit.column'],
],
[
'log_visit.column == 5 OR log_link_visit_action.othercolumn <> 3',
['log_visit.column', 'log_link_visit_action.othercolumn'],
],
[
'(log_visit.column == 5)',
['log_visit.column'],
],
[
'(log_visit.column = 5) AND ((HOUR(log_visit.column) == 12)) AND FUNC(mytable.mycolumn) - OTHERFUNC(`myothertable`.`myothercolumn`) = LASTFUNC(mylasttable.mylastcolumn)',
['log_visit.column', 'mytable.mycolumn', 'myothertable.myothercolumn', 'mylasttable.mylastcolumn'],
],
[
'log_visit.column = 5 OR @@session.whatever == 5',
['log_visit.column'],
],
[
'@something.whatever = 5',
[],
],
[
'@something.whatever <> 5.0',
[],
],
[
'log_visit.thing = 3.45 AND @log_visit.what < 23.00',
['log_visit.thing'],
],
];
}
}