gplx/mediawiki/extensions/SemanticMediaWiki/tests/phpunit/Utils/JSONScript/JsonTestCaseFileHandler.php

500 lines
11 KiB
PHP

<?php
namespace SMW\Tests\Utils\JSONScript;
use RuntimeException;
use SMW\Tests\Utils\File\JsonFileReader;
/**
* @license GPL-2.0-or-later
* @since 2.2
*
* @author mwjames
*/
class JsonTestCaseFileHandler {
/**
* @var JsonFileReader
*/
private $fileReader;
/**
* @var string
*/
private $reasonToSkip = '';
/**
* @since 2.2
*
* @param JsonFileReader $fileReader
*/
public function __construct( JsonFileReader $fileReader ) {
$this->fileReader = $fileReader;
}
/**
* @since 2.2
*
* @return bool
*/
public function isIncomplete() {
$meta = $this->getFileContentsFor( 'meta' );
$isIncomplete = isset( $meta['is-incomplete'] ) ? (bool)$meta['is-incomplete'] : false;
if ( $isIncomplete ) {
$this->reasonToSkip = '"' . $this->getFileContentsFor( 'description' ) . '" has been marked as incomplete.';
}
return $isIncomplete;
}
/**
* @since 2.2
*
* @return bool
*/
public function getDebugMode() {
$meta = $this->getFileContentsFor( 'meta' );
return isset( $meta['debug'] ) ? (bool)$meta['debug'] : false;
}
/**
* @since 3.0
*
* @return bool
*/
public function hasAllRequirements( $dependencyDef = [] ) {
$requires = $this->getContentsFor( 'requires' );
if ( $requires === [] ) {
return true;
}
foreach ( $requires as $key => $value ) {
$res = false;
if ( isset( $dependencyDef[$key] ) && is_callable( $dependencyDef[$key] ) ) {
$res = call_user_func_array( $dependencyDef[$key], [ $value, &$this->reasonToSkip ] );
}
if ( $res === false ) {
// Default msg!
if ( $this->reasonToSkip === '' ) {
$this->reasonToSkip = "$key requirements were not met!";
}
return false;
}
}
return true;
}
/**
* @since 2.4
*
* @param array $case
* @param string $identifier
*
* @return bool
*/
public function requiredToSkipFor( array $case, $identifier ) {
$skipOn = isset( $case['skip-on'] ) ? $case['skip-on'] : [];
$identifier = strtolower( $identifier );
if ( is_bool( $skipOn ) ) {
return $skipOn;
}
if ( !is_array( $skipOn ) ) {
throw new RuntimeException( "skip-on should be an array or boolean value" );
}
// Transform for convenience `skip-except` meaning skip all
// except for ...
if ( isset( $case['skip-except'] ) ) {
foreach ( $case['skip-except'] as $id => $value ) {
$skipOn[$id] = [ "not", $value ];
}
}
$version = MW_VERSION;
foreach ( $skipOn as $id => $value ) {
$versionToSkip = '';
$compare = '=';
$noop = '';
if ( is_array( $value ) ) {
$versionToSkip = (string)$value[0];
$reason = $value[1];
} else {
$reason = $value;
}
// Support for { "skip-on": { "foo": [ "not", "Exclude all except foo ..." ] }
if ( $versionToSkip === 'not' && $identifier === $id ) {
continue;
} elseif ( $versionToSkip === 'not' && $identifier !== $id ) {
return true;
}
// Support for { "skip-on": { "postgres": [ "<9.2", "Reason..." }
if ( $identifier === 'postgres' && $identifier === $id && $versionToSkip !== '' ) {
$version = SMW_PHPUNIT_DB_VERSION;
// Support for { "skip-on": { "virtuoso": "Virtuoso 6.1 ..." }
} elseif ( $identifier === $id ) {
return true;
}
// Support for { "skip-on": { "smw->2.5.x": "Reason is ..." }
// or { "skip-on": { "mw->1.30.x": "Reason is ..." }
if ( strpos( $id, 'mw-' ) !== false ) {
[ $noop, $versionToSkip ] = explode( "mw-", $id, 2 );
}
// Support for { "skip-on": { "mediawiki": [ ">1.29.x", "Reason is ..." ] }
if ( strpos( $id, 'smw' ) !== false ) {
$version = SMW_VERSION;
} elseif ( strpos( $id, 'mediawiki' ) !== false || strpos( $id, 'mw' ) !== false ) {
$version = MW_VERSION;
} elseif ( strpos( $id, 'php' ) !== false ) {
$version = defined( 'PHP_VERSION' ) ? PHP_VERSION : 0;
}
if ( $versionToSkip !== '' && ( $versionToSkip[0] === '<' || $versionToSkip[0] === '>' ) ) {
$compare = $versionToSkip[0];
$versionToSkip = substr( $versionToSkip, 1 );
}
if ( strpos( $versionToSkip, '.x' ) ) {
$versionToSkip = str_replace( '.x', '.9999', $versionToSkip );
$compare = $compare === '=' ? '<' : $compare;
}
if ( strpos( $versionToSkip, '<' ) ) {
$versionToSkip = str_replace( '<', '', $versionToSkip );
$compare = '<';
}
// Skip any version as in { "skip-on": { "mediawiki": [ "*", "Reason is ..." ] }
if ( $versionToSkip === '*' ) {
return true;
}
if ( version_compare( $version, $versionToSkip, $compare ) ) {
$this->reasonToSkip = "Version $version is not supported ({$reason})";
return true;
}
}
return false;
}
/**
* @since 2.2
*
* @return bool
*/
public function requiredToSkipForConnector( $connectorId ) {
$connectorId = strtolower( $connectorId );
$meta = $this->getFileContentsFor( 'meta' );
$skipOn = isset( $meta['skip-on'] ) ? $meta['skip-on'] : [];
if ( array_key_exists( $connectorId, $skipOn ) ) {
$this->reasonToSkip = $skipOn[$connectorId];
}
return $this->reasonToSkip !== '';
}
/**
* @since 2.2
*
* @return bool
*/
public function requiredToSkipForJsonVersion( $version ) {
$meta = $this->getFileContentsFor( 'meta' );
if ( version_compare( $version, $meta['version'], 'ne' ) ) {
$this->reasonToSkip = 'The test case file version `' . $meta['version'] . "` is not supported due to `{$version}` being required as version.";
}
return $this->reasonToSkip !== '';
}
/**
* @since 2.2
*
* @return bool
*/
public function requiredToSkipOnSiteLanguage( $siteLanguage ) {
$meta = $this->getFileContentsFor( 'meta' );
$skipOn = isset( $meta['skip-on'] ) ? $meta['skip-on'] : [];
foreach ( $skipOn as $id => $reason ) {
if ( $id !== 'sitelanguage' ) {
continue;
}
if ( $reason[0] === $siteLanguage ) {
$this->reasonToSkip = $reason[1];
break;
}
}
return $this->reasonToSkip !== '';
}
/**
* @since 2.2
*
* @return bool
*/
public function requiredToSkipForMwVersion( $mwVersion ) {
$meta = $this->getFileContentsFor( 'meta' );
$skipOn = isset( $meta['skip-on'] ) ? $meta['skip-on'] : [];
foreach ( $skipOn as $id => $reason ) {
if ( strpos( $id, 'mediawiki' ) === false ) {
continue;
}
$versionToSkip = $skipOn['mediawiki'][0];
$compare = '=';
if ( strpos( $versionToSkip, '=' ) ) {
$list = explode( "=", $versionToSkip );
$compare = $list[0] . '=';
if ( strpos( $versionToSkip, '.x' ) ) {
$versionToSkip = str_replace( '.x', '.9999', $list[1] );
}
}
if ( !strpos( $versionToSkip, '=' ) ) {
$compare = $versionToSkip[0];
$list = explode( $compare, $versionToSkip );
if ( strpos( $versionToSkip, '.x' ) ) {
$versionToSkip = str_replace( '.x', '.9999', $list[1] );
}
}
if ( version_compare( $mwVersion, $versionToSkip, $compare ) ) {
$messageToShow = is_array( $reason ) && isset( $reason[1] ) ? $reason[1] : 'Test skipped!';
$this->reasonToSkip = "MediaWiki " . $mwVersion . " version is not supported ({$messageToShow})";
break;
}
}
return $this->reasonToSkip !== '';
}
/**
* @since 2.2
*
* @return string
*/
public function getReasonForSkip() {
return $this->reasonToSkip;
}
/**
* @since 3.0
*
* @param string $key
*
* @return booleam
*/
public function hasSetting( $key ) {
$settings = $this->getFileContentsFor( 'settings' );
return isset( $settings[$key] );
}
/**
* @since 2.2
*
* @return array|int|string|bool
* @throws RuntimeException
*/
public function getSettingsFor( $key, $callback = null ) {
$settings = $this->getFileContentsFor( 'settings' );
if ( isset( $settings[$key] ) && is_callable( $callback ) ) {
return call_user_func_array( $callback, [ $settings[$key] ] );
}
// Needs special attention due to NS constant usage
if ( $key === 'smwgNamespacesWithSemanticLinks' && isset( $settings[$key] ) ) {
$smwgNamespacesWithSemanticLinks = [];
foreach ( $settings[$key] as $ns => $value ) {
$smwgNamespacesWithSemanticLinks[constant( $ns )] = (bool)$value;
}
return $smwgNamespacesWithSemanticLinks;
}
$constantFeaturesList = [
'smwgSparqlQFeatures',
'smwgDVFeatures',
'smwgFulltextSearchIndexableDataTypes',
'smwgFieldTypeFeatures',
'smwgQueryProfiler',
'smwgParserFeatures',
'smwgCategoryFeatures',
'smwgQSortFeatures',
'smwgQEqualitySupport'
];
foreach ( $constantFeaturesList as $constantFeatures ) {
if ( $key === $constantFeatures && isset( $settings[$key] ) ) {
$features = '';
if ( !is_array( $settings[$key] ) ) {
return $settings[$key];
}
foreach ( $settings[$key] as $value ) {
$features = constant( $value ) | (int)$features;
}
return $features;
}
}
if ( $key === 'wgDefaultUserOptions' && isset( $settings[$key] ) ) {
return array_merge( $GLOBALS['wgDefaultUserOptions'], $settings[$key] );
}
// Needs special attention due to constant usage
if ( $key === 'smwgQConceptCaching' && isset( $settings[$key] ) ) {
return constant( $settings[$key] );
}
// Needs special attention due to constant usage
if ( strpos( $key, 'CacheType' ) !== false && isset( $settings[$key] ) ) {
return $settings[$key] === false ? CACHE_NONE : ( defined( $settings[$key] ) ? constant( $settings[$key] ) : $settings[$key] );
}
if ( isset( $settings[$key] ) ) {
return $settings[$key];
}
// Return values from the global settings as default
if ( isset( $GLOBALS[$key] ) || array_key_exists( $key, $GLOBALS ) ) {
return $GLOBALS[$key];
}
// Key is unknown, TestConfig will remove any remains during tearDown
return null;
}
/**
* @since 2.2
*
* @return array
*/
public function getListOfProperties() {
return $this->getFileContentsFor( 'properties' );
}
/**
* @since 2.2
*
* @return array
*/
public function getListOfSubjects() {
return $this->getFileContentsFor( 'subjects' );
}
/**
* @since 2.2
*
* @return array
*/
public function getPageCreationSetupList() {
return $this->getContentsFor( 'setup' );
}
/**
* @since 2.4
*
* @param string $key
*
* @return array
*/
public function getContentsFor( $key ) {
try {
$contents = $this->getFileContentsFor( $key );
} catch ( \Exception $e ) {
$contents = [];
}
return $contents;
}
/**
* @since 2.2
*
* @param string $key
*
* @return array
*/
public function findTestCasesFor( $key ) {
return $this->getContentsFor( $key );
}
/**
* @since 2.5
*
* @param string $type
*
* @return array
*/
public function findTasksBeforeTestExecutionByType( $type ) {
$contents = $this->getContentsFor( 'beforeTest' );
return isset( $contents[$type] ) ? $contents[$type] : [];
}
/**
* @since 2.5
*
* @param string $type
*
* @return array
*/
public function findTestCasesByType( $type ) {
return array_filter( $this->getContentsFor( 'tests' ), static function ( $contents ) use( $type ) {
return isset( $contents['type'] ) && $contents['type'] === $type;
} );
}
/**
* @since 3.0
*
* @param string $type
*
* @return int
*/
public function countTestCasesByType( $type ) {
return count( $this->findTestCasesByType( $type ) );
}
private function getFileContentsFor( $index ) {
$contents = $this->fileReader->read();
if ( isset( $contents[$index] ) ) {
return $contents[$index];
}
throw new RuntimeException( "{$index} is unknown" );
}
}