Lucas Werkmeister (WMDE) has uploaded a new change for review. (
https://gerrit.wikimedia.org/r/363605 )
Change subject: Implement Format constraint with SPARQL
......................................................................
Implement Format constraint with SPARQL
SparqlHelper gains a method to test if a string matches a regular
expression using SPARQL’s REGEX() function, and FormatChecker is
injected an optional SparqlHelper which it uses to check the constraint
if the SparqlHelper available.
The violation message gains parameters for the property, value and
regular expression.
The query service returns a different result for an invalid query, so we
can detect this case and report it as an invalid constraint parameter.
The SparqlHelper throws a ConstraintParameterException in that case, and
a new message is added for it.
ConstraintParameterRenderer’s formatByRole method is made public and
static, so that SparqlHelper can use it without needing a
ConstraintParameterRenderer injected.
The tests for the format checker are updated to no longer assert a TODO
status; the mock matchesRegularExpression implementation is the old
FormatChecker implementation which was removed in commit b325c00e99
(change I28d2850f89). A test for the behavior without SPARQL (TODO, as
before) is added.
Two tests for SparqlHelper are added, which test that it constructs the
query correctly (including correct input escaping) and that it correctly
detects the case of an invalid regex and throws an exception.
Bug: T102752
Change-Id: I920c6eedbfad9a75b39e01da595294c13c0b8cfc
---
M i18n/en.json
M i18n/qqq.json
M includes/ConstraintCheck/Checker/FormatChecker.php
M includes/ConstraintCheck/Helper/SparqlHelper.php
M includes/ConstraintParameterRenderer.php
M includes/ConstraintReportFactory.php
M tests/phpunit/Checker/FormatChecker/FormatCheckerTest.php
M tests/phpunit/Helper/SparqlHelperTest.php
8 files changed, 217 insertions(+), 47 deletions(-)
git pull
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/WikibaseQualityConstraints
refs/changes/05/363605/1
diff --git a/i18n/en.json b/i18n/en.json
index 3ae6ce2..15168f7 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -64,6 +64,7 @@
"wbqc-violation-message-parameter-string": "The value for the parameter
\"$1\" must be a string, not \"$2\".",
"wbqc-violation-message-parameter-single": "The parameter \"$1\" must
only have a single value.",
"wbqc-violation-message-parameter-oneof": "The parameter \"$1\" must be
{{PLURAL:$2|1=$4.|2=either $4 or $5.|one of the following:$3}}",
+ "wbqc-violation-message-parameter-regex": "$1 is not a valid regular
expression.",
"wbqc-violation-message-sparql-error": "The SPARQL query resulted in an
error.",
"wbqc-violation-message-commons-link-no-existent": "Commons link should
exist.",
@@ -77,7 +78,7 @@
"wbqc-violation-message-diff-within-range-property-must-exist": "The
property defined in the parameters must exist.",
"wbqc-violation-message-diff-within-range-property-needs value": "The
property defined in the parameters needs to have a value.",
"wbqc-violation-message-diff-within-range-must-have-equal-types": "The
property defined in the parameters must have a value of the same type as this
property.",
- "wbqc-violation-message-format": "The property's value must match the
pattern defined in the parameters.",
+ "wbqc-violation-message-format": "The value for $1 ($2) should match
the pattern $3.",
"wbqc-violation-message-inverse": "$1 should also have the inverse
statement $2 $3.",
"wbqc-violation-message-item": "An entity with $1 should also have
{{PLURAL:$3|0=a statement $2.|1=a statement $2 $5.|a statement for $2 with one
of the following values:$4}}",
"wbqc-violation-message-mandatory-qualifier": "This $1 statement is
missing a qualifier $2.",
diff --git a/i18n/qqq.json b/i18n/qqq.json
index 51f6970..8c72113 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -60,6 +60,7 @@
"wbqc-violation-message-parameter-string": "Message for when the value
of a constraint parameter must be a string, but is some other value type. $1
contains the parameter, $2 the value.",
"wbqc-violation-message-parameter-single": "Message for when a
constraint parameter has multiple values but only supports one. $1 contains the
parameter.",
"wbqc-violation-message-parameter-oneof": "Message for when a
constraint parameter must be one of several values, but is something different.
$1 contains the parameter, $2 the number of allowed values (possibly 1), $3 an
HTML list of all allowed values, and $4, $5 etc. are the individual allowed
values.{{Related|wbqc-violation-message-one-of}}",
+ "wbqc-violation-message-parameter-regex": "Message for when a
constraint parameter must be a valid regular expression, but has an error. $1
contains the parameter value.",
"wbqc-violation-message-sparql-error": "Message for when a constraint
checker runs a SPARQL query but the SPARQL endpoint returns an error instead of
query results.",
"wbqc-violation-message-commons-link-no-existent": "Message for
violation of Commons link constraint. When linked commons page does not exist.",
"wbqc-violation-message-commons-link-not-well-formed": "Message for
violation of Commons link constraint. When link contains invalid characters.",
@@ -72,7 +73,7 @@
"wbqc-violation-message-diff-within-range-property-must-exist":
"Message for violation of Diff within range constraint. When given property
does not exist (any more).",
"wbqc-violation-message-diff-within-range-property-needs value":
"Message for violation of Diff within range constraint. When given property
does not have a value.",
"wbqc-violation-message-diff-within-range-must-have-equal-types":
"Message for violation of Diff within range constraint. When this and the given
property differ in value type.",
- "wbqc-violation-message-format": "Message for violation of format
constraint. When string does not match given pattern.",
+ "wbqc-violation-message-format": "Message for a violation of the
“Format” constraint, when the value of a statement does not match a certain
pattern. Parameters:\n* $1 is the property of the statement that has the
constraint.\n* $2 is the text value of the statement.\n* $3 is the pattern.",
"wbqc-violation-message-inverse": "Message for a violation of the
“Inverse” constraint, when the inverse statement of a statement does not exist.
$1, $2 and $3 contain the expected subject entity, property, and target entity
of the missing inverse statement.",
"wbqc-violation-message-item": "Message for a violation of the “Item”
constraint, when the subject entity of a statement is missing another
statement. Parameters:\n* $1 is the property of the statement that has the
constraint.\n* $2 is the property of the missing statement.\n* $3 is the number
of values permitted for the missing statement (or 0, in which case the
constraint only specifies that there should be a statement but not the values
it should have).\n* $4 is an HTML list of all values permitted for the missing
statement.\n* $5, $6 etc. are the individual values permitted for the missing
statement.\n{{Related|wbqc-violation-message-target-required-claim}}",
"wbqc-violation-message-mandatory-qualifier": "Message for a violation
of the “Mandatory qualifier” constraint, when a mandatory qualifier is missing
on a statement. Parameters:\n* $1 is the property of the statement.\n* $2 is
the missing qualifier.",
diff --git a/includes/ConstraintCheck/Checker/FormatChecker.php
b/includes/ConstraintCheck/Checker/FormatChecker.php
index 7a6d6c2..96de987 100644
--- a/includes/ConstraintCheck/Checker/FormatChecker.php
+++ b/includes/ConstraintCheck/Checker/FormatChecker.php
@@ -2,12 +2,14 @@
namespace WikibaseQuality\ConstraintReport\ConstraintCheck\Checker;
+use DataValues\StringValue;
use Wikibase\DataModel\Entity\EntityDocument;
use Wikibase\DataModel\Snak\PropertyValueSnak;
use Wikibase\DataModel\Statement\StatementListProvider;
use WikibaseQuality\ConstraintReport\Constraint;
use WikibaseQuality\ConstraintReport\ConstraintCheck\ConstraintChecker;
use
WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\ConstraintParameterParser;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\SparqlHelper;
use WikibaseQuality\ConstraintReport\ConstraintCheck\Result\CheckResult;
use WikibaseQuality\ConstraintReport\ConstraintParameterRenderer;
use Wikibase\DataModel\Statement\Statement;
@@ -30,15 +32,23 @@
private $constraintParameterRenderer;
/**
+ * @var SparqlHelper
+ */
+ private $sparqlHelper;
+
+ /**
* @param ConstraintParameterParser $constraintParameterParser
* @param ConstraintParameterRenderer $constraintParameterRenderer
+ * @param SparqlHelper|null $sparqlHelper
*/
public function __construct(
ConstraintParameterParser $constraintParameterParser,
- ConstraintParameterRenderer $constraintParameterRenderer
+ ConstraintParameterRenderer $constraintParameterRenderer,
+ SparqlHelper $sparqlHelper = null
) {
$this->constraintParameterParser = $constraintParameterParser;
$this->constraintParameterRenderer =
$constraintParameterRenderer;
+ $this->sparqlHelper = $sparqlHelper;
}
/**
@@ -76,22 +86,46 @@
* error handling:
* type of $dataValue for properties with 'Format' constraint
has to be 'string' or 'monolingualtext'
*/
- $type = $dataValue->getType();
- if ( $type !== 'string' && $type !== 'monolingualtext' ) {
- $message = wfMessage(
"wbqc-violation-message-value-needed-of-type" )
- ->rawParams(
-
$this->constraintParameterRenderer->formatItemId(
$constraint->getConstraintTypeItemId(),
ConstraintParameterRenderer::ROLE_CONSTRAINT_TYPE_ITEM ),
- wfMessage(
'datatypes-type-string' )->escaped(),
- wfMessage(
'datatypes-type-monolingualtext' )->escaped()
- )
- ->escaped();
- return new CheckResult( $entity->getId(), $statement,
$constraint, $parameters, CheckResult::STATUS_VIOLATION, $message );
+ switch ( $dataValue->getType() ) {
+ case 'string':
+ $text = $dataValue->getValue();
+ break;
+ case 'monolingualtext':
+ $text = $dataValue->getText();
+ break;
+ default:
+ $message = wfMessage(
"wbqc-violation-message-value-needed-of-type" )
+ ->rawParams(
+
$this->constraintParameterRenderer->formatItemId(
$constraint->getConstraintTypeItemId(),
ConstraintParameterRenderer::ROLE_CONSTRAINT_TYPE_ITEM ),
+ wfMessage(
'datatypes-type-string' )->escaped(),
+ wfMessage(
'datatypes-type-monolingualtext' )->escaped()
+ )
+ ->escaped();
+ return new CheckResult( $entity->getId(),
$statement, $constraint, $parameters, CheckResult::STATUS_VIOLATION, $message );
}
- $message = wfMessage( "wbqc-violation-message-security-reason" )
- ->rawParams(
$this->constraintParameterRenderer->formatItemId(
$constraint->getConstraintTypeItemId(),
ConstraintParameterRenderer::ROLE_CONSTRAINT_TYPE_ITEM ) )
- ->escaped();
- return new CheckResult( $entity->getId(), $statement,
$constraint, $parameters, CheckResult::STATUS_TODO, $message );
+ if ( $this->sparqlHelper !== null ) {
+ if ( $this->sparqlHelper->matchesRegularExpression(
$text, $format ) ) {
+ $message = '';
+ $status = CheckResult::STATUS_COMPLIANCE;
+ } else {
+ $message = wfMessage(
'wbqc-violation-message-format' )
+ ->rawParams(
+
$this->constraintParameterRenderer->formatEntityId(
$statement->getPropertyId(),
ConstraintParameterRenderer::ROLE_CONSTRAINT_PROPERTY ),
+
$this->constraintParameterRenderer->formatDataValue( new StringValue( $text ),
ConstraintParameterRenderer::ROLE_OBJECT ),
+
$this->constraintParameterRenderer->formatByRole(
ConstraintParameterRenderer::ROLE_CONSTRAINT_PARAMETER_VALUE,
+
'<code><nowiki>' . htmlspecialchars( $format ) . '</nowiki></code>' )
+ )
+ ->escaped();
+ $status = CheckResult::STATUS_VIOLATION;
+ }
+ } else {
+ $message = wfMessage(
"wbqc-violation-message-security-reason" )
+ ->rawParams(
$this->constraintParameterRenderer->formatItemId(
$constraint->getConstraintTypeItemId(),
ConstraintParameterRenderer::ROLE_CONSTRAINT_TYPE_ITEM ) )
+ ->escaped();
+ $status = CheckResult::STATUS_TODO;
+ }
+ return new CheckResult( $entity->getId(), $statement,
$constraint, $parameters, $status, $message );
}
}
diff --git a/includes/ConstraintCheck/Helper/SparqlHelper.php
b/includes/ConstraintCheck/Helper/SparqlHelper.php
index 54e63b6..610da37 100644
--- a/includes/ConstraintCheck/Helper/SparqlHelper.php
+++ b/includes/ConstraintCheck/Helper/SparqlHelper.php
@@ -9,6 +9,7 @@
use Wikibase\DataModel\Entity\EntityIdParser;
use Wikibase\DataModel\Statement\Statement;
use Wikibase\Rdf\RdfVocabulary;
+use WikibaseQuality\ConstraintReport\ConstraintParameterRenderer;
/**
* Class for running a SPARQL query on some endpoint and getting the results.
@@ -146,6 +147,50 @@
}
/**
+ * Return SPARQL code for a string literal with $text as content.
+ * @param string $text
+ * @return string
+ */
+ private function stringLiteral( $text ) {
+ return '"' . strtr( $text, [ '"' => '\\"', '\\' => '\\\\' ] ) .
'"';
+ }
+
+ /**
+ * @param string $text
+ * @param string $regex
+ * @return boolean
+ * @throws SparqlHelperException if the query times out or some other
error occurs
+ * @throws ConstraintParameterException if the $regex is invalid
+ */
+ public function matchesRegularExpression( $text, $regex ) {
+ $textStringLiteral = $this->stringLiteral( $text );
+ $regexStringLiteral = $this->stringLiteral( '^' . $regex . '$'
);
+
+ $query = <<<EOF
+SELECT (REGEX($textStringLiteral, $regexStringLiteral) AS ?matches) WHERE {}
+EOF;
+
+ $result = $this->runQuery( $query );
+
+ $vars = $result['results']['bindings'][0];
+ if ( $vars === null ) {
+ var_dump( $result );
+ }
+ if ( array_key_exists( 'matches', $vars ) ) {
+ // true or false ⇒ regex okay, text matches or not
+ return $vars['matches']['value'] === 'true';
+ } else {
+ // empty result: regex broken
+ throw new ConstraintParameterException(
+ wfMessage(
'wbqc-violation-message-parameter-regex' )
+ ->rawParams(
ConstraintParameterRenderer::formatByRole(
ConstraintParameterRenderer::ROLE_CONSTRAINT_PARAMETER_VALUE,
+ '<code><nowiki>' .
htmlspecialchars( $regex ) . '</nowiki></code>' ) )
+ ->escaped()
+ );
+ }
+ }
+
+ /**
* Runs a query against the configured endpoint and returns the results.
*
* @param string $query The query, unencoded (plain string).
diff --git a/includes/ConstraintParameterRenderer.php
b/includes/ConstraintParameterRenderer.php
index 6d3b74a..9a0a795 100644
--- a/includes/ConstraintParameterRenderer.php
+++ b/includes/ConstraintParameterRenderer.php
@@ -181,7 +181,7 @@
* @param string $value HTML
* @return string HTML
*/
- private function formatByRole( $role, $value ) {
+ public static function formatByRole( $role, $value ) {
if ( $role === null ) {
return $value;
}
@@ -197,7 +197,7 @@
* @return string HTML
*/
public function formatDataValue( DataValue $value, $role = null ) {
- return $this->formatByRole( $role,
+ return self::formatByRole( $role,
$this->dataValueFormatter->format( $value ) );
}
@@ -207,7 +207,7 @@
* @return string HTML
*/
public function formatEntityId( EntityId $entityId, $role = null ) {
- return $this->formatByRole( $role,
+ return self::formatByRole( $role,
$this->entityIdLabelFormatter->formatEntityId(
$entityId ) );
}
@@ -227,7 +227,7 @@
try {
return $this->formatEntityId( new PropertyId(
$propertyId ), $role );
} catch ( InvalidArgumentException $e ) {
- return $this->formatByRole( $role,
+ return self::formatByRole( $role,
htmlspecialchars( $propertyId ) );
}
} else {
@@ -251,7 +251,7 @@
try {
return $this->formatEntityId( new ItemId(
$itemId ), $role );
} catch ( InvalidArgumentException $e ) {
- return $this->formatByRole( $role,
+ return self::formatByRole( $role,
htmlspecialchars( $itemId ) );
}
} else {
@@ -271,12 +271,12 @@
case $value->isValue():
return $this->formatEntityId(
$value->getItemId(), $role );
case $value->isSomeValue():
- return $this->formatByRole( $role,
+ return self::formatByRole( $role,
'<span
class="wikibase-snakview-variation-somevaluesnak">'
. wfMessage(
'wikibase-snakview-snaktypeselector-somevalue' )->escaped()
. '</span>' );
case $value->isNoValue():
- return $this->formatByRole( $role,
+ return self::formatByRole( $role,
'<span
class="wikibase-snakview-variation-novaluesnak">'
. wfMessage(
'wikibase-snakview-snaktypeselector-novalue' )->escaped()
. '</span>' );
diff --git a/includes/ConstraintReportFactory.php
b/includes/ConstraintReportFactory.php
index 96cd99a..e6f101a 100644
--- a/includes/ConstraintReportFactory.php
+++ b/includes/ConstraintReportFactory.php
@@ -222,7 +222,7 @@
'Single value' => new SingleValueChecker(),
'Multi value' => new MultiValueChecker(),
'Unique value' => new UniqueValueChecker(
$this->constraintParameterRenderer, $sparqlHelper ),
- 'Format' => new FormatChecker(
$this->constraintParameterParser, $this->constraintParameterRenderer ),
+ 'Format' => new FormatChecker(
$this->constraintParameterParser, $this->constraintParameterRenderer,
$sparqlHelper ),
'Commons link' => new CommonsLinkChecker(
$this->constraintParameterParser, $this->constraintParameterRenderer,
$this->titleParser ),
'One of' => new OneOfChecker(
$this->constraintParameterParser, $this->constraintParameterRenderer ),
];
diff --git a/tests/phpunit/Checker/FormatChecker/FormatCheckerTest.php
b/tests/phpunit/Checker/FormatChecker/FormatCheckerTest.php
index 4770feb..cf817d6 100644
--- a/tests/phpunit/Checker/FormatChecker/FormatCheckerTest.php
+++ b/tests/phpunit/Checker/FormatChecker/FormatCheckerTest.php
@@ -13,6 +13,7 @@
use Wikibase\DataModel\Entity\PropertyId;
use WikibaseQuality\ConstraintReport\Constraint;
use WikibaseQuality\ConstraintReport\ConstraintCheck\Checker\FormatChecker;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\SparqlHelper;
use WikibaseQuality\ConstraintReport\Tests\ConstraintParameters;
use WikibaseQuality\ConstraintReport\Tests\ResultAssertions;
@@ -38,7 +39,21 @@
protected function setUp() {
parent::setUp();
- $this->formatChecker = new FormatChecker(
$this->getConstraintParameterParser(), $this->getConstraintParameterRenderer()
);
+ $sparqlHelper = $this->getMockBuilder( SparqlHelper::class )
+ ->disableOriginalConstructor()
+ ->setMethods( [
'matchesRegularExpression' ] )
+ ->getMock();
+ $sparqlHelper->method( 'matchesRegularExpression' )
+ ->will( $this->returnCallback(
+ function( $text, $pattern ) {
+ return preg_match( '/^' . str_replace(
'/', '\/', $pattern ) . '$/', $text );
+ }
+ ) );
+ $this->formatChecker = new FormatChecker(
+ $this->getConstraintParameterParser(),
+ $this->getConstraintParameterRenderer(),
+ $sparqlHelper
+ );
}
public function testFormatConstraintImdb() {
@@ -71,70 +86,70 @@
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoCompliance( $result );
+ $this->assertCompliance( $result );
$result = $this->formatChecker->checkConstraint(
$statement2,
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoCompliance( $result );
+ $this->assertCompliance( $result );
$result = $this->formatChecker->checkConstraint(
$statement3,
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoCompliance( $result );
+ $this->assertCompliance( $result );
$result = $this->formatChecker->checkConstraint(
$statement4,
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoCompliance( $result );
+ $this->assertCompliance( $result );
$result = $this->formatChecker->checkConstraint(
$statement5,
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoViolation( $result );
+ $this->assertViolation( $result );
$result = $this->formatChecker->checkConstraint(
$statement6,
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoViolation( $result );
+ $this->assertViolation( $result );
$result = $this->formatChecker->checkConstraint(
$statement7,
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoViolation( $result );
+ $this->assertViolation( $result );
$result = $this->formatChecker->checkConstraint(
$statement8,
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoViolation( $result );
+ $this->assertViolation( $result );
$result = $this->formatChecker->checkConstraint(
$statement9,
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoViolation( $result );
+ $this->assertViolation( $result );
$result = $this->formatChecker->checkConstraint(
$statement10,
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoViolation( $result );
+ $this->assertViolation( $result );
}
public function testFormatConstraintTaxonName() {
@@ -174,70 +189,70 @@
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoCompliance( $result );
+ $this->assertCompliance( $result );
$result = $this->formatChecker->checkConstraint(
$statement2,
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoCompliance( $result );
+ $this->assertCompliance( $result );
$result = $this->formatChecker->checkConstraint(
$statement3,
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoCompliance( $result );
+ $this->assertCompliance( $result );
$result = $this->formatChecker->checkConstraint(
$statement4,
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoCompliance( $result );
+ $this->assertCompliance( $result );
$result = $this->formatChecker->checkConstraint(
$statement5,
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoViolation( $result );
+ $this->assertViolation( $result );
$result = $this->formatChecker->checkConstraint(
$statement6,
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoViolation( $result );
+ $this->assertViolation( $result );
$result = $this->formatChecker->checkConstraint(
$statement7,
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoViolation( $result );
+ $this->assertViolation( $result );
$result = $this->formatChecker->checkConstraint(
$statement8,
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoViolation( $result );
+ $this->assertViolation( $result );
$result = $this->formatChecker->checkConstraint(
$statement9,
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoViolation( $result );
+ $this->assertViolation( $result );
$result = $this->formatChecker->checkConstraint(
$statement10,
$this->getConstraintMock( $this->formatParameter(
$pattern ) ),
$this->getEntity()
);
- $this->assertTodoViolation( $result );
+ $this->assertViolation( $result );
}
public function testFormatConstraintNoStringValue() {
@@ -273,6 +288,24 @@
$this->assertEquals( 'violation', $result->getStatus(), 'check
should not comply' );
}
+ public function testFormatConstraintWithoutSparql() {
+ $statement = new Statement( new PropertyValueSnak( new
PropertyId( 'P1' ), new StringValue( '' ) ) );
+ $constraint = $this->getConstraintMock( $this->formatParameter(
'.' ) );
+ $checker = new FormatChecker(
+ $this->getConstraintParameterParser(),
+ $this->getConstraintParameterRenderer(),
+ null
+ );
+
+ $result = $checker->checkConstraint(
+ $statement,
+ $constraint,
+ $this->getEntity()
+ );
+
+ $this->assertTodoViolation( $result );
+ }
+
/**
* @param string[] $parameters
*
diff --git a/tests/phpunit/Helper/SparqlHelperTest.php
b/tests/phpunit/Helper/SparqlHelperTest.php
index d604b47..2378e67 100644
--- a/tests/phpunit/Helper/SparqlHelperTest.php
+++ b/tests/phpunit/Helper/SparqlHelperTest.php
@@ -6,11 +6,16 @@
use Wikibase\DataModel\Entity\ItemId;
use Wikibase\DataModel\Entity\ItemIdParser;
use Wikibase\DataModel\Entity\PropertyId;
+use Wikibase\DataModel\Snak\PropertyNoValueSnak;
use Wikibase\DataModel\Snak\PropertyValueSnak;
use Wikibase\DataModel\Statement\Statement;
use Wikibase\Rdf\RdfVocabulary;
+use WikibaseQuality\ConstraintReport\Constraint;
+use
WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\ConstraintParameterException;
use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\SparqlHelper;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\Result\CheckResult;
use WikibaseQuality\ConstraintReport\Tests\DefaultConfig;
+use WikibaseQuality\ConstraintReport\Tests\ResultAssertions;
/**
* @covers
\WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\SparqlHelper
@@ -22,7 +27,7 @@
*/
class SparqlHelperTest extends \PHPUnit_Framework_TestCase {
- use DefaultConfig;
+ use DefaultConfig, ResultAssertions;
public function testHasType() {
$sparqlHelper = $this->getMockBuilder( SparqlHelper::class )
@@ -102,4 +107,55 @@
);
}
+ public function testMatchesRegularExpression() {
+ $text = '""\'\\\\"<<'; // ""'\\"<<
+ $regex = '\\"\\\\"\\\\\\"'; // \"\\"\\\"
+ $query = 'SELECT (REGEX("\\""\'\\\\\\\\\\"<<",
"^\\\\\\"\\\\\\\\\\"\\\\\\\\\\\\\\"$") AS ?matches) WHERE {}';
+ $sparqlHelper = $this->getMockBuilder( SparqlHelper::class )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'runQuery' ] )
+ ->getMock();
+
+ $sparqlHelper->expects( $this->once() )
+ ->method( 'runQuery' )
+ ->with( $this->equalTo( $query ) )
+ ->willReturn( [ 'results' => [ 'bindings' => [ [
'matches' => [ 'value' => 'false' ] ] ] ] ] );
+
+ $result = $sparqlHelper->matchesRegularExpression( $text,
$regex );
+
+ $this->assertFalse( $result );
+ }
+
+ public function testMatchesRegularExpressionBadRegex() {
+ $text = '';
+ $regex = '(.{2,5)?';
+ $query = 'SELECT (REGEX("", "^(.{2,5)?$") AS ?matches) WHERE
{}';
+ $sparqlHelper = $this->getMockBuilder( SparqlHelper::class )
+ ->disableOriginalConstructor()
+ ->setMethods( [ 'runQuery' ] )
+ ->getMock();
+ $messageKey = 'wbqc-violation-message-parameter-regex';
+
+ $sparqlHelper->expects( $this->once() )
+ ->method( 'runQuery' )
+ ->with( $this->equalTo( $query ) )
+ ->willReturn( [ 'results' => [ 'bindings' => [ [] ] ] ]
);
+
+ try {
+ call_user_func_array( [ $sparqlHelper,
'matchesRegularExpression' ], [ $text, $regex ] );
+ $this->assertTrue( false,
+ "matchesRegularExpression should have thrown a
ConstraintParameterException with message ⧼$messageKey⧽." );
+ } catch ( ConstraintParameterException $exception ) {
+ $checkResult = new CheckResult(
+ new ItemId( 'Q1' ),
+ new Statement( new PropertyNoValueSnak( new
PropertyId( 'P1' ) ) ),
+ $this->getMockBuilder( Constraint::class
)->disableOriginalConstructor()->getMock(),
+ [],
+ CheckResult::STATUS_VIOLATION,
+ $exception->getMessage()
+ );
+ $this->assertViolation( $checkResult, $messageKey );
+ }
+ }
+
}
--
To view, visit https://gerrit.wikimedia.org/r/363605
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I920c6eedbfad9a75b39e01da595294c13c0b8cfc
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/WikibaseQualityConstraints
Gerrit-Branch: master
Gerrit-Owner: Lucas Werkmeister (WMDE) <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits