*/ class AbuseFilterParserTest extends MediaWikiTestCase { /** * @return AbuseFilterParser */ static function getParser() { static $parser = null; if ( !$parser ) { $parser = new AbuseFilterParser(); } return $parser; } /** * @return [AbuseFilterParser] */ static function getParsers() { static $parsers = null; if ( !$parsers ) { $parsers = [ new AbuseFilterParser(), new AbuseFilterCachingParser() ]; } return $parsers; } /** * @dataProvider readTests */ public function testParser( $testName, $rule, $expected ) { if ( !class_exists( 'AntiSpoof' ) && preg_match( '/(cc)?norm\(/i', $rule ) ) { // The norm and ccnorm parser functions aren't working correctly without AntiSpoof $this->markTestSkipped( 'Parser test ' . $testName . ' requires the AntiSpoof extension' ); } foreach ( self::getParsers() as $parser ) { $actual = $parser->parse( $rule ); $this->assertEquals( $expected, $actual, 'Running parser test ' . $testName ); } } /** * @return array */ public function readTests() { $tests = array(); $testPath = __DIR__ . "/../parserTests"; $testFiles = glob( $testPath . "/*.t" ); foreach ( $testFiles as $testFile ) { $testName = substr( $testFile, 0, -2 ); $resultFile = $testName . '.r'; $rule = trim( file_get_contents( $testFile ) ); $result = trim( file_get_contents( $resultFile ) ) == 'MATCH'; $tests[] = array( basename( $testName ), $rule, $result ); } return $tests; } /** * Ensure that AbuseFilterTokenizer::OPERATOR_RE matches the contents * and order of AbuseFilterTokenizer::$operators. */ public function testOperatorRe() { $operatorRe = '/(' . implode( '|', array_map( function ( $op ) { return preg_quote( $op, '/' ); }, AbuseFilterTokenizer::$operators ) ) . ')/A'; $this->assertEquals( $operatorRe, AbuseFilterTokenizer::OPERATOR_RE ); } /** * Ensure that AbuseFilterTokenizer::RADIX_RE matches the contents * and order of AbuseFilterTokenizer::$bases. */ public function testRadixRe() { $baseClass = implode( '', array_keys( AbuseFilterTokenizer::$bases ) ); $radixRe = "/([0-9A-Fa-f]+(?:\.\d*)?|\.\d+)([$baseClass])?/Au"; $this->assertEquals( $radixRe, AbuseFilterTokenizer::RADIX_RE ); } /** * Ensure the number of conditions counted for given expressions is right. * * @dataProvider condCountCases */ public function testCondCount( $rule, $expected ) { $parser = self::getParser(); // Set some variables for convenience writing test cases $parser->setVars( array_combine( range( 'a', 'f' ), range( 'a', 'f' ) ) ); $countBefore = AbuseFilter::$condCount; $parser->parse( $rule ); $countAfter = AbuseFilter::$condCount; $actual = $countAfter - $countBefore; $this->assertEquals( $expected, $actual, 'Condition count for ' . $rule ); } /** * @return array */ public function condCountCases() { return array( array( '(((a == b)))', 1 ), array( 'contains_any(a, b, c)', 1 ), array( 'a == b == c', 2 ), array( 'a in b + c in d + e in f', 3 ), array( 'true', 0 ), array( 'a == a | c == d', 1 ), array( 'a == b & c == d', 1 ), ); } }