Created
September 25, 2011 16:08
-
-
Save thekid/1240769 to your computer and use it in GitHub Desktop.
XP Framework: Patch for issue #56
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/core/src/main/php/lang/XPClass.class.php b/core/src/main/php/lang/XPClass.class.php | |
index c4e5ee9..33b29ed 100644 | |
--- a/core/src/main/php/lang/XPClass.class.php | |
+++ b/core/src/main/php/lang/XPClass.class.php | |
@@ -583,19 +583,125 @@ | |
* @throws lang.ClassFormatException | |
*/ | |
public static function parseAnnotations($input, $context) { | |
- ob_start(); | |
- $annotations= eval('return array('.($eval= preg_replace( | |
- array('/@([a-z_]+),/i', '/@([a-z_]+)\(\'([^\']+)\'\)/ie', '/@([a-z_]+)\(/i', '/(\(|, *)([a-z_]+) *= */i'), | |
- array('\'$1\' => NULL,', '"\'$1\' => urldecode(\'".urlencode(\'$2\')."\')"', '\'$1\' => array(', '$1\'$2\' => '), | |
- trim($input, "[]# \t\n\r").',' | |
- )).');'); | |
- $msg= ltrim(ob_get_contents(), ini_get('error_prepend_string')."\r\n\t "); | |
- if (FALSE === $annotations || $msg) { | |
- ob_end_clean(); | |
- xp::gc(); | |
- raise('lang.ClassFormatException', 'Parse error: '.$msg.' of "'.addcslashes($eval, "\0..\17").'" in '.$context); | |
+ $input= trim($input, "[]# \t\n\r").']'; | |
+ $offset= 0; | |
+ $annotations= array(); | |
+ $annotation= $value= NULL; | |
+ $length= strlen($input); | |
+ while ($offset < $length) { | |
+ $state= $input{$offset}; | |
+ if ('@' === $state) { | |
+ $s= strcspn($input, ',(]', $offset); | |
+ $annotation= substr($input, $offset+ 1, $s- 1); | |
+ $offset+= $s; | |
+ } else if (']' === $state) { | |
+ $annotations[$annotation]= $value; | |
+ break; | |
+ } else if ('(' === $state) { | |
+ $peek= substr($input, $offset+ 1, strcspn($input, '="\')', $offset)); | |
+ if ('\'' === $peek{0} || '"' === $peek{0}) { | |
+ $p= $offset+ 2; | |
+ $q= $peek{0}; | |
+ while (($s= strcspn($input, $q, $p)) !== 0) { | |
+ $p+= $s; | |
+ if ('\\' !== $input{$p- 1}) break; | |
+ $p++; | |
+ } | |
+ if (!is_string($value= @eval('return '.substr($input, $offset+ 1, $p - $offset).';'))) { | |
+ raise('lang.ClassFormatException', 'Parse error: Unterminated or malformed string in '.$context); | |
+ } | |
+ $offset= $p+ 1; | |
+ } else if ('array' === substr($peek, 0, 5)) { | |
+ $b= 1; | |
+ $p= $offset+ 1+ 6; | |
+ while ($b > 0) { | |
+ $p+= strcspn($input, '()"\'', $p); | |
+ if ($p > $length) break; | |
+ if ('(' === $input{$p}) $b++; else if (')' === $input{$p}) $b--; else if ('\'' === $input{$p} || '"' === $input{$p}) { | |
+ $q= $input{$p}; | |
+ $p++; | |
+ while (($s= strcspn($input, $q, $p)) !== 0) { | |
+ $p+= $s; | |
+ if ('\\' !== $input{$p- 1}) break; | |
+ $p++; | |
+ } | |
+ } | |
+ $p++; | |
+ } | |
+ if (!is_array($value= @eval('return '.substr($input, $offset+ 1, $p- $offset- 1).';'))) { | |
+ raise('lang.ClassFormatException', 'Parse error: Unterminated or malformed array in '.$context); | |
+ } | |
+ $offset= $p; | |
+ } else if ('=' !== $peek{strlen($peek)- 1}) { | |
+ $value= eval('return '.substr($peek, 0, -1).';'); | |
+ $offset+= strlen($peek); | |
+ } else { | |
+ $value= array(); | |
+ do { | |
+ $key= trim($peek, '= '); | |
+ $offset+= strlen($peek)+ 1; | |
+ $offset+= strspn($input, ' ', $offset); | |
+ if ($offset >= $length) { | |
+ break; | |
+ } else if ('array' === substr($input, $offset, 5)) { | |
+ $b= 1; | |
+ $p= $offset+ 6; | |
+ while ($b > 0) { | |
+ $p+= strcspn($input, '()"\'', $p); | |
+ if ($p > $length) break; | |
+ if ('(' === $input{$p}) $b++; else if (')' === $input{$p}) $b--; else if ('\'' === $input{$p} || '"' === $input{$p}) { | |
+ $q= $input{$p}; | |
+ $p++; | |
+ while (($s= strcspn($input, $q, $p)) !== 0) { | |
+ $p+= $s; | |
+ if ('\\' !== $input{$p- 1}) break; | |
+ $p++; | |
+ } | |
+ } | |
+ $p++; | |
+ } | |
+ if (!is_array($value[$key]= @eval('return '.substr($input, $offset, $p- $offset).';'))) { | |
+ raise('lang.ClassFormatException', 'Parse error: Unterminated or malformed array in '.$context); | |
+ } | |
+ $offset= $p; | |
+ } else if ('\'' === $input{$offset} || '"' === $input{$offset}) { | |
+ $p= $offset+ 1; | |
+ $q= $input{$offset}; | |
+ while (($s= strcspn($input, $q, $p)) !== 0) { | |
+ $p+= $s; | |
+ if ('\\' !== $input{$p- 1}) break; | |
+ $p++; | |
+ } | |
+ if (!is_string($value[$key]= @eval('return '.substr($input, $offset, $p - $offset + 1).';'))) { | |
+ raise('lang.ClassFormatException', 'Parse error: Unterminated or malformed string in '.$context); | |
+ } | |
+ $offset= $p+ 1; | |
+ } else { | |
+ $s= strcspn($input, ',)', $offset); | |
+ $value[$key]= eval('return '.substr($input, $offset, $s).';'); | |
+ $offset+= $s; | |
+ } | |
+ | |
+ // Find next key | |
+ $s= strcspn($input, '="\')', $offset); | |
+ $peek= substr($input, $offset+ 1, $s); | |
+ } while ($s); | |
+ } | |
+ $offset++; // ")" | |
+ if ($offset > $length) { | |
+ raise('lang.ClassFormatException', 'Parse error: Expecting ] in '.$context); | |
+ } | |
+ } else if (',' === $state) { | |
+ $annotations[$annotation]= $value; | |
+ $annotation= $value= NULL; | |
+ if (FALSE === ($offset= strpos($input, '@', $offset))) { | |
+ raise('lang.ClassFormatException', 'Parse error: Expecting @ in '.$context); | |
+ } | |
+ } else { | |
+ raise('lang.ClassFormatException', 'Parse error: Unknown state '.$state.' at position '.$offset.' in '.$context); | |
+ } | |
} | |
- ob_end_clean(); | |
+ | |
return $annotations; | |
} | |
diff --git a/core/src/resources/unittest/core.ini b/core/src/resources/unittest/core.ini | |
index 8d13028..02df721 100644 | |
--- a/core/src/resources/unittest/core.ini | |
+++ b/core/src/resources/unittest/core.ini | |
@@ -9,6 +9,12 @@ description="Core tests" | |
[annotations] | |
class="net.xp_framework.unittest.core.AnnotationTest" | |
+[annotation-parsing] | |
+class="net.xp_framework.unittest.annotations.AnnotationParsingTest" | |
+ | |
+[broken-annotations] | |
+class="net.xp_framework.unittest.annotations.BrokenAnnotationTest" | |
+ | |
[errors] | |
class="net.xp_framework.unittest.core.ErrorsTest" | |
@@ -123,9 +129,6 @@ class="net.xp_framework.unittest.core.BootstrapTest" | |
[newinstance] | |
class="net.xp_framework.unittest.core.NewInstanceTest" | |
-[annotation-parsing] | |
-class="net.xp_framework.unittest.annotations.BrokenAnnotationTest" | |
- | |
[commandline] | |
class="net.xp_framework.unittest.core.CommandLineTest" | |
diff --git a/core/src/test/php/net/xp_framework/unittest/annotations/AnnotationParsingTest.class.php b/core/src/test/php/net/xp_framework/unittest/annotations/AnnotationParsingTest.class.php | |
new file mode 100644 | |
index 0000000..964524a | |
--- /dev/null | |
+++ b/core/src/test/php/net/xp_framework/unittest/annotations/AnnotationParsingTest.class.php | |
@@ -0,0 +1,389 @@ | |
+<?php | |
+/* This class is part of the XP framework | |
+ * | |
+ * $Id$ | |
+ */ | |
+ | |
+ uses('unittest.TestCase'); | |
+ | |
+ /** | |
+ * Tests the XP Framework's annotation parsing implementation | |
+ * | |
+ * @see rfc://0016 | |
+ * @see xp://lang.XPClass#parseAnnotations | |
+ * @see http://bugs.xp-framework.net/show_bug.cgi?id=38 | |
+ * @see https://github.com/xp-framework/xp-framework/issues/14 | |
+ * @see https://github.com/xp-framework/xp-framework/pull/56 | |
+ * @see https://gist.github.com/1240769 | |
+ */ | |
+ class AnnotationParsingTest extends TestCase { | |
+ | |
+ /** | |
+ * Helper | |
+ * | |
+ * @param string input | |
+ * @return [:var] | |
+ */ | |
+ protected function parse($input) { | |
+ return XPClass::parseAnnotations($input, $this->getClassName()); | |
+ } | |
+ | |
+ /** | |
+ * Tests simple annotation without a value | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function noValue() { | |
+ $this->assertEquals( | |
+ array('hello' => NULL), | |
+ $this->parse("#[@hello]") | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Tests simple annotation with string value | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function sqStringValue() { | |
+ $this->assertEquals( | |
+ array('hello' => 'World'), | |
+ $this->parse("#[@hello('World')]") | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Tests simple annotation with string value | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function sqStringValueWithEqualsSign() { | |
+ $this->assertEquals( | |
+ array('hello' => 'World=Welt'), | |
+ $this->parse("#[@hello('World=Welt')]") | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Test string with at sign inside | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function sqStringValueWithAtSign() { | |
+ $this->assertEquals( | |
+ array('hello' => '@World'), | |
+ $this->parse("#[@hello('@World')]") | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Test string with an annotation inside a string | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function sqStringValueWithAnnotation() { | |
+ $this->assertEquals( | |
+ array('hello' => '@hello("World")'), | |
+ $this->parse("#[@hello('@hello(\"World\")')]") | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Tests simple annotation with string value | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function sqStringValueWithDoubleQuotes() { | |
+ $this->assertEquals( | |
+ array('hello' => 'said "he"'), | |
+ $this->parse("#[@hello('said \"he\"')]") | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Tests simple annotation with string value | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function sqStringValueWithEscapedSingleQuotes() { | |
+ $this->assertEquals( | |
+ array('hello' => "said 'he'"), | |
+ $this->parse("#[@hello('said \'he\'')]") | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Tests simple annotation with string value | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function dqStringValue() { | |
+ $this->assertEquals( | |
+ array('hello' => 'World'), | |
+ $this->parse('#[@hello("World")]') | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Tests simple annotation with string value | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function dqStringValueWithSingleQuote() { | |
+ $this->assertEquals( | |
+ array('hello' => 'Beck\'s'), | |
+ $this->parse('#[@hello("Beck\'s")]') | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Tests simple annotation with string value | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function dqStringValueWithEscapedDoubleQuotes() { | |
+ $this->assertEquals( | |
+ array('hello' => 'said "he"'), | |
+ $this->parse('#[@hello("said \"he\"")]') | |
+ ); | |
+ } | |
+ /** | |
+ * Tests simple annotation with string value | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function dqStringValueWithEscapeSequence() { | |
+ $this->assertEquals( | |
+ array('hello' => "World\n"), | |
+ $this->parse('#[@hello("World\n")]') | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Test string with at sign inside | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function dqStringValueWithAtSign() { | |
+ $this->assertEquals( | |
+ array('hello' => '@World'), | |
+ $this->parse('#[@hello("@World")]') | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Test string with an annotation inside a string | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function dqStringValueWithAnnotation() { | |
+ $this->assertEquals( | |
+ array('hello' => '@hello(\'World\')'), | |
+ $this->parse('#[@hello("@hello(\'World\')")]') | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Tests simple annotation with an int value | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function intValue() { | |
+ $this->assertEquals( | |
+ array('answer' => 42), | |
+ $this->parse('#[@answer(42)]') | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Tests simple annotation with a double value | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function doubleValue() { | |
+ $this->assertEquals( | |
+ array('version' => 3.5), | |
+ $this->parse('#[@version(3.5)]') | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Tests simple annotation with an array value | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function arrayValue() { | |
+ $this->assertEquals( | |
+ array('versions' => array(3.4, 3.5)), | |
+ $this->parse('#[@versions(array(3.4, 3.5))]') | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Tests simple annotation with an array value | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function arrayValueWithNestedArray() { | |
+ $this->assertEquals( | |
+ array('versions' => array(array(3))), | |
+ $this->parse('#[@versions(array(array(3)))]') | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Tests simple annotation with an array value | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function arrayValueWithNestedArrays() { | |
+ $this->assertEquals( | |
+ array('versions' => array(array(3), array(4))), | |
+ $this->parse('#[@versions(array(array(3), array(4)))]') | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Tests simple annotation with an array value | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function arrayValueWithStringsContainingBraces() { | |
+ $this->assertEquals( | |
+ array('versions' => array('(3..4]')), | |
+ $this->parse('#[@versions(array("(3..4]"))]') | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Tests simple annotation with a bool value | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function boolValue() { | |
+ $this->assertEquals( | |
+ array('supported' => TRUE), | |
+ $this->parse('#[@supported(TRUE)]') | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Tests different value types | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function keyValuePairsAnnotationValue() { | |
+ $this->assertEquals( | |
+ array('config' => array('key' => 'value', 'times' => 5, 'disabled' => FALSE, 'null' => NULL, 'list' => array(1, 2))), | |
+ $this->parse("#[@config(key = 'value', times= 5, disabled= FALSE, null = NULL, list= array(1, 2))]") | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Tests multi-line annotations | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function multiLineAnnotation() { | |
+ $this->assertEquals( | |
+ array('interceptors' => array('classes' => array( | |
+ 'net.xp_framework.unittest.core.FirstInterceptor', | |
+ 'net.xp_framework.unittest.core.SecondInterceptor', | |
+ ))), | |
+ $this->parse(" | |
+ #[@interceptors(classes= array( | |
+ 'net.xp_framework.unittest.core.FirstInterceptor', | |
+ 'net.xp_framework.unittest.core.SecondInterceptor', | |
+ ))] | |
+ ") | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Tests simple xpath annotations | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function simpleXPathAnnotation() { | |
+ $this->assertEquals( | |
+ array('fromXml' => array('xpath' => '/parent/child/@attribute')), | |
+ $this->parse("#[@fromXml(xpath= '/parent/child/@attribute')]") | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Tests complex xpath annotations | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function complexXPathAnnotation() { | |
+ $this->assertEquals( | |
+ array('fromXml' => array('xpath' => '/parent[@attr="value"]/child[@attr1="val1" and @attr2="val2"]')), | |
+ $this->parse("#[@fromXml(xpath= '/parent[@attr=\"value\"]/child[@attr1=\"val1\" and @attr2=\"val2\"]')]") | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Tests string default with "=" | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function stringWithEqualSigns() { | |
+ $this->assertEquals( | |
+ array('permission' => 'rn=login, rt=config'), | |
+ $this->parse("#[@permission('rn=login, rt=config')]") | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Test string assignment without whitespace is parsed correctly. | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function stringAssignedWithoutWhitespace() { | |
+ $this->assertEquals( | |
+ array('arg' => array('name' => 'verbose', 'short' => 'v')), | |
+ $this->parse("#[@arg(name= 'verbose', short='v')]") | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Test annotation with mulitple values containing equal signs | |
+ * is parsed correctly. | |
+ * | |
+ */ | |
+ #[@test] | |
+ public function multipleValuesWithStringsAndEqualSigns() { | |
+ $this->assertEquals( | |
+ array('permission' => array('names' => array('rn=login, rt=config1', 'rn=login, rt=config2'))), | |
+ $this->parse("#[@permission(names= array('rn=login, rt=config1', 'rn=login, rt=config2'))]") | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Test unittest annotations | |
+ * | |
+ * @see xp://unittest.TestCase | |
+ */ | |
+ #[@test] | |
+ public function unittestAnnotation() { | |
+ $this->assertEquals( | |
+ array('test' => NULL, 'ignore' => NULL, 'limit' => array('time' => 0.1, 'memory' => 100)), | |
+ $this->parse("#[@test, @ignore, @limit(time = 0.1, memory = 100)]") | |
+ ); | |
+ } | |
+ | |
+ /** | |
+ * Test overloaded annotations | |
+ * | |
+ * @see xp://lang.reflect.Proxy | |
+ */ | |
+ #[@test] | |
+ public function overloadedAnnotation() { | |
+ $this->assertEquals( | |
+ array('overloaded' => array('signatures' => array(array('string'), array('string', 'string')))), | |
+ $this->parse('#[@overloaded(signatures= array(array("string"), array("string", "string")))]') | |
+ ); | |
+ } | |
+ } | |
+?> | |
diff --git a/core/src/test/php/net/xp_framework/unittest/core/AnnotatedClass.class.php b/core/src/test/php/net/xp_framework/unittest/core/AnnotatedClass.class.php | |
index 50ae87d..5998ee1 100644 | |
--- a/core/src/test/php/net/xp_framework/unittest/core/AnnotatedClass.class.php | |
+++ b/core/src/test/php/net/xp_framework/unittest/core/AnnotatedClass.class.php | |
@@ -48,58 +48,5 @@ | |
#[@test, @ignore, @limit(time = 0.1, memory = 100)] | |
public function testMethod() { } | |
- /** | |
- * Method annotated with an annotation with a hash value containing | |
- * multiple key/value pairs | |
- * | |
- */ | |
- #[@config(key = 'value', times= 5, disabled= FALSE, null = NULL, list= array(1, 2))] | |
- public function keyValuePairs() { } | |
- | |
- /** | |
- * Method annotated with a multi-line annotation | |
- * | |
- */ | |
- #[@interceptors(classes= array( | |
- # 'net.xp_framework.unittest.core.FirstInterceptor', | |
- # 'net.xp_framework.unittest.core.SecondInterceptor', | |
- #))] | |
- public function multiLine() { } | |
- | |
- /** | |
- * Method annotated with a simple xpath expression | |
- * | |
- */ | |
- #[@fromXml(xpath= '/parent/child/@attribute')] | |
- public function simpleXPath() { } | |
- | |
- /** | |
- * Method annotated with a complex xpath expression | |
- * | |
- */ | |
- #[@fromXml(xpath= '/parent[@attr="value"]/child[@attr1="val1" and @attr2="val2"]')] | |
- public function complexXPath() { } | |
- | |
- /** | |
- * Method annotated with a string default containing "=" signs | |
- * | |
- * @see http://bugs.xp-framework.net/show_bug.cgi?id=38 | |
- */ | |
- #[@permission('rn=login, rt=config')] | |
- public function stringWithEqualSigns() { } | |
- | |
- /** | |
- * Method annotated with a string, w/o whitespace in assignment | |
- * | |
- */ | |
- #[@arg(name= 'verbose', short='v')] | |
- public function stringAssignedWithoutWhitespace() {} | |
- | |
- /** | |
- * Method annotated with multiple values which contains equal signs | |
- * | |
- * #[@permission(names= array('rn=login, rt=config1', 'rn=login, rt=config2'))] | |
- */ | |
- public function multipleValuesWithStringsAndEqualSigns() { } | |
} | |
?> | |
diff --git a/core/src/test/php/net/xp_framework/unittest/core/AnnotationTest.class.php b/core/src/test/php/net/xp_framework/unittest/core/AnnotationTest.class.php | |
index a04e480..1e970c5 100644 | |
--- a/core/src/test/php/net/xp_framework/unittest/core/AnnotationTest.class.php | |
+++ b/core/src/test/php/net/xp_framework/unittest/core/AnnotationTest.class.php | |
@@ -144,10 +144,9 @@ | |
*/ | |
#[@test] | |
public function multipleAnnotationsReturnedAsList() { | |
- $method= $this->class->getMethod('multiple'); | |
$this->assertEquals( | |
array('one' => NULL, 'two' => NULL, 'three' => NULL), | |
- $method->getAnnotations() | |
+ $this->class->getMethod('multiple')->getAnnotations() | |
); | |
} | |
@@ -183,103 +182,7 @@ | |
$m= $this->class->getMethod('testMethod'); | |
$this->assertTrue($m->hasAnnotation('test')); | |
$this->assertTrue($m->hasAnnotation('ignore')); | |
- $this->assertEquals(0.1, $m->getAnnotation('limit', 'time')); | |
- $this->assertEquals(100, $m->getAnnotation('limit', 'memory')); | |
- $this->assertEquals( | |
- array('time' => 0.1, 'memory' => 100), | |
- $m->getAnnotation('limit') | |
- ); | |
- } | |
- | |
- /** | |
- * Tests getAnnotation() returns the string associated with the | |
- * annotation. | |
- * | |
- * @see xp://net.xp_framework.unittest.core.AnnotatedClass#keyValuePairs | |
- */ | |
- #[@test] | |
- public function keyValuePairsAnnotationValue() { | |
- $this->assertEquals( | |
- array('key' => 'value', 'times' => 5, 'disabled' => FALSE, 'null' => NULL, 'list' => array(1, 2)), | |
- $this->methodAnnotation('keyValuePairs', 'config') | |
- ); | |
- } | |
- | |
- /** | |
- * Tests multi-line annotations | |
- * | |
- * @see xp://net.xp_framework.unittest.core.AnnotatedClass#multiLine | |
- */ | |
- #[@test] | |
- public function multiLineAnnotation() { | |
- $this->assertEquals(array('classes' => array( | |
- 'net.xp_framework.unittest.core.FirstInterceptor', | |
- 'net.xp_framework.unittest.core.SecondInterceptor', | |
- )), $this->methodAnnotation('multiLine', 'interceptors')); | |
- } | |
- | |
- /** | |
- * Tests simple xpath annotations | |
- * | |
- * @see xp://net.xp_framework.unittest.core.AnnotatedClass#simpleXPath | |
- */ | |
- #[@test] | |
- public function simpleXPathAnnotation() { | |
- $this->assertEquals(array( | |
- 'xpath' => '/parent/child/@attribute' | |
- ), $this->methodAnnotation('simpleXPath', 'fromXml')); | |
+ $this->assertEquals(array('time' => 0.1, 'memory' => 100), $m->getAnnotation('limit')); | |
} | |
- | |
- /** | |
- * Tests complex xpath annotations | |
- * | |
- * @see xp://net.xp_framework.unittest.core.AnnotatedClass#complexXPath | |
- */ | |
- #[@test] | |
- public function complexXPathAnnotation() { | |
- $this->assertEquals(array( | |
- 'xpath' => '/parent[@attr="value"]/child[@attr1="val1" and @attr2="val2"]' | |
- ), $this->methodAnnotation('complexXPath', 'fromXml')); | |
- } | |
- | |
- /** | |
- * Tests string default with "=" | |
- * | |
- * @see xp://net.xp_framework.unittest.core.AnnotatedClass#stringWithEqualSigns | |
- * @see http://bugs.xp-framework.net/show_bug.cgi?id=38 | |
- */ | |
- #[@test] | |
- public function stringWithEqualSigns() { | |
- $this->assertEquals( | |
- 'rn=login, rt=config', | |
- $this->methodAnnotation('stringWithEqualSigns', 'permission') | |
- ); | |
- } | |
- | |
- /** | |
- * Test string assignment without whitespace is parsed correctly. | |
- * | |
- */ | |
- #[@test] | |
- public function stringAssignedWithoutWhitespace() { | |
- $this->assertEquals( | |
- array('name' => 'verbose', 'short' => 'v'), | |
- $this->methodAnnotation('stringAssignedWithoutWhitespace', 'arg') | |
- ); | |
- } | |
- | |
- /** | |
- * Test annotation with mulitple values containing equal signs | |
- * is parsed correctly. | |
- * | |
- */ | |
- #[@test, @ignore('Test needs adjustment in XPClass and AnnotatedClass')] | |
- public function multipleValuesWithStringsAndEqualSigns() { | |
- $this->assertEquals( | |
- array('rn=login, rt=config1', 'rn=login, rt=config2'), | |
- $this->methodAnnotation('multipleValuesWithStringsAndEqualSigns') | |
- ); | |
- } | |
- | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Improved version, after quite a bit of work:
Now faster than the original regex on average!