Skip to content

Instantly share code, notes, and snippets.

@thekid
Created September 25, 2011 16:08
Show Gist options
  • Save thekid/1240769 to your computer and use it in GitHub Desktop.
Save thekid/1240769 to your computer and use it in GitHub Desktop.
XP Framework: Patch for issue #56
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')
- );
- }
-
}
?>
@thekid
Copy link
Author

thekid commented Oct 1, 2011

Improved version, after quite a bit of work:

$ make shootout
make[1]: Entering directory `/home/Timm Friebe/devel/1071362'
@complete: lang.FileSystemClassLoader<D:\cygwin\home\Timm Friebe\devel\1071362\complete\>
==========================================
>> #[@test]: 100000 in 0.423 seconds
>> #[@test(expect = "lang.FormatException")]: 100000 in 2.307 seconds
>> #[@named('sybase')]: 100000 in 1.669 seconds
>> #[@permission('rn=login, rt=config')]: 100000 in 1.637 seconds
>> #[@arg(name= "verbose", short="v")]: 100000 in 3.396 seconds
>> #[@arg(position= 0)]: 100000 in 2.027 seconds
>> #[@fromxml(xpath= "/root/element[position() = 3]/@id")]: 100000 in 2.334 seconds
>> #[@webmethod, @restricted(role= "admin")]: 100000 in 2.589 seconds
>> #[@restricted(roles = array("admin", "root"))]: 100000 in 2.464 seconds
>> #[@require(permissions= array("rn=a", "rn=b"))]: 100000 in 2.790 seconds
>> #[@overloaded(signatures= array(array("string"), array("string", "string")))]: 100000 in 3.050 seconds
==========================================
Total: 11 tests(s) in 24.686 seconds, avg. 2.244 seconds
make[1]: Leaving directory `/home/Timm Friebe/devel/1071362'

make[1]: Entering directory `/home/Timm Friebe/devel/1071362'
@regex: lang.FileSystemClassLoader<D:\cygwin\home\Timm Friebe\devel\1071362\regex\>
==========================================
>> #[@test]: 100000 in 1.916 seconds
>> #[@test(expect = "lang.FormatException")]: 100000 in 2.179 seconds
>> #[@named('sybase')]: 100000 in 2.817 seconds
>> #[@permission('rn=login, rt=config')]: 100000 in 3.044 seconds
>> #[@arg(name= "verbose", short="v")]: 100000 in 2.439 seconds
>> #[@arg(position= 0)]: 100000 in 2.144 seconds
>> #[@fromxml(xpath= "/root/element[position() = 3]/@id")]: 100000 in 2.662 seconds
>> #[@webmethod, @restricted(role= "admin")]: 100000 in 2.788 seconds
>> #[@restricted(roles = array("admin", "root"))]: 100000 in 2.398 seconds
>> #[@require(permissions= array("rn=a", "rn=b"))]: 100000 in 2.611 seconds
>> #[@overloaded(signatures= array(array("string"), array("string", "string")))]: 100000 in 2.611 seconds
==========================================
Total: 11 tests(s) in 27.611 seconds, avg. 2.510 seconds
make[1]: Leaving directory `/home/Timm Friebe/devel/1071362'

make[1]: Entering directory `/home/Timm Friebe/devel/1071362'
@scanner: lang.FileSystemClassLoader<D:\cygwin\home\Timm Friebe\devel\1071362\scanner\>
==========================================
>> #[@test]: 100000 in 0.323 seconds
>> #[@test(expect = "lang.FormatException")]: 100000 in 1.603 seconds
>> #[@named('sybase')]: 100000 in 0.610 seconds
>> #[@permission('rn=login, rt=config')]: 100000 in 0.618 seconds
>> #[@arg(name= "verbose", short="v")]: 100000 in 1.842 seconds
>> #[@arg(position= 0)]: 100000 in 1.573 seconds
>> #[@fromxml(xpath= "/root/element[position() = 3]/@id")]: 100000 in 2.081 seconds
>> #[@webmethod, @restricted(role= "admin")]: 100000 in 1.852 seconds
>> #[@restricted(roles = array("admin", "root"))]: 100000 in 1.848 seconds
>> #[@require(permissions= array("rn=a", "rn=b"))]: 100000 in 2.095 seconds
>> #[@overloaded(signatures= array(array("string"), array("string", "string")))]: 100000 in 2.327 seconds
==========================================
Total: 11 tests(s) in 16.772 seconds, avg. 1.525 seconds
make[1]: Leaving directory `/home/Timm Friebe/devel/1071362'

Now faster than the original regex on average!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment