Skip to content

Commit cfcca86

Browse files
authored
Fix segmentMatchNONE system test for MySQL 8.0 (#135)
* Fix segmentMatchNONE test for MySQL 8.0 Comparing date/time segments against the placeholder string 'campaign' (e.g. visitEndServerDate != 'campaign') is rejected by MySQL 8.0 as an invalid DATE value; MySQL 5.7 tolerated it. Give each date/time segment a valid, type-appropriate value instead - a date for DATE() segments and an integer for the HOUR()/MINUTE()/YEAR()/... extractions - so they stay covered and the query runs on MySQL 8.0. The matched result is unchanged (the segment still matches no visits via the impossible deviceType condition). * Run plugin tests against MySQL 8.0 and MariaDB 10.6 The workflow inherited the shared action's MySQL 5.7 default, which is below Matomo's new minimum. Pin the database-backed jobs to the supported floor: PluginTests now runs a MySQL 8.0 + MariaDB 10.6 matrix, and the UI job runs on MySQL 8.0. * Only upload plugin test artifacts for the MySQL matrix leg PluginTests runs a MySQL + MariaDB matrix; the upload-artifacts condition matched both legs and uploaded twice. Restrict the upload to the MySQL leg.
1 parent 535258a commit cfcca86

2 files changed

Lines changed: 52 additions & 2 deletions

File tree

.github/workflows/matomo-tests.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ jobs:
3939
matrix:
4040
php: [ '8.1', '8.5' ]
4141
target: ['minimum_required_matomo', 'maximum_supported_matomo']
42+
database:
43+
- { engine: 'Mysql', version: '8.0' }
44+
- { engine: 'Mariadb', version: '10.6' }
4245
steps:
4346
- uses: actions/checkout@v3
4447
with:
@@ -52,9 +55,11 @@ jobs:
5255
plugin-name: 'CustomVariables'
5356
php-version: ${{ matrix.php }}
5457
test-type: 'PluginTests'
58+
mysql-engine: ${{ matrix.database.engine }}
59+
mysql-version: ${{ matrix.database.version }}
5560
matomo-test-branch: ${{ matrix.target }}
5661
artifacts-pass: ${{ secrets.ARTIFACTS_PASS }}
57-
upload-artifacts: ${{ matrix.php == '8.1' && matrix.target == 'maximum_supported_matomo' }}
62+
upload-artifacts: ${{ matrix.php == '8.1' && matrix.target == 'maximum_supported_matomo' && matrix.database.engine == 'Mysql' }}
5863
UI:
5964
runs-on: ubuntu-24.04
6065
steps:
@@ -70,5 +75,7 @@ jobs:
7075
test-type: 'UI'
7176
php-version: '8.1'
7277
node-version: '16'
78+
mysql-engine: 'Mysql'
79+
mysql-version: '8.0'
7380
artifacts-pass: ${{ secrets.ARTIFACTS_PASS }}
7481
upload-artifacts: true

tests/System/TwoVisitsWithCustomVariablesSegmentMatchNONETest.php

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
namespace Piwik\Plugins\CustomVariables\tests\System;
1111

12+
use Piwik\Columns\Dimension;
1213
use Piwik\Plugins\API\tests\System\AutoSuggestAPITest;
1314
use Piwik\Tests\Framework\TestCase\SystemTestCase;
1415
use Piwik\Plugins\CustomVariables\tests\Fixtures\TwoVisitsWithCustomVariables;
@@ -63,9 +64,15 @@ public function getSegmentToTest()
6364
$this->assertGreaterThan($minimumExpectedSegmentsCount, count($segments));
6465
$segmentExpression = array();
6566

67+
$temporalSegmentValues = self::getTemporalSegmentValues();
68+
6669
$seenVisitorId = false;
6770
foreach ($segments as $segment) {
68-
$value = 'campaign';
71+
// Date/time segments can't be compared against an arbitrary string: MySQL 8.0 rejects
72+
// e.g. "visitEndServerDate != 'campaign'" as an invalid DATE value (5.7 tolerated it).
73+
// Give them a valid, type-appropriate value (a date for DATE() segments, a number for
74+
// the HOUR()/MINUTE()/YEAR()/... integer extractions) so they stay covered.
75+
$value = $temporalSegmentValues[$segment] ?? 'campaign';
6976
if ($segment == 'visitorId') {
7077
$seenVisitorId = true;
7178
$value = '34c31e04394bdc63';
@@ -107,6 +114,42 @@ public static function getOutputPrefix()
107114
return 'twoVisitsWithCustomVariables_segmentMatchNONE';
108115
}
109116

117+
/**
118+
* Returns a valid comparison value for every non-internal segment backed by a date/time typed
119+
* dimension, keyed by segment name.
120+
*
121+
* These segments map to SQL that expects either a date (e.g. DATE(...)) or an integer (the
122+
* HOUR()/MINUTE()/YEAR()/... extractions), so an arbitrary string like "campaign" produces an
123+
* invalid DATE value error on MySQL 8.0. The returned values are valid for the respective
124+
* comparison.
125+
*/
126+
private static function getTemporalSegmentValues(): array
127+
{
128+
$temporalTypes = [
129+
Dimension::TYPE_DATE,
130+
Dimension::TYPE_DATETIME,
131+
Dimension::TYPE_TIME,
132+
Dimension::TYPE_TIMESTAMP,
133+
];
134+
135+
$values = [];
136+
foreach (Dimension::getAllDimensions() as $dimension) {
137+
if (!in_array($dimension->getType(), $temporalTypes, true)) {
138+
continue;
139+
}
140+
141+
foreach ($dimension->getSegments() as $segment) {
142+
$isIntegerExtraction = (bool) preg_match(
143+
'/^\s*(HOUR|MINUTE|SECOND|DAYOFWEEK|DAYOFMONTH|DAYOFYEAR|WEEKOFYEAR|WEEK|MONTH|QUARTER|YEAR)\s*\(/i',
144+
$segment->getSqlSegment()
145+
);
146+
$values[$segment->getSegment()] = $isIntegerExtraction ? '99' : '2099-12-31';
147+
}
148+
}
149+
150+
return $values;
151+
}
152+
110153
public static function getPathToTestDirectory()
111154
{
112155
return dirname(__FILE__);

0 commit comments

Comments
 (0)